41

I have the following code and I'm confused about this error message:

Instance member 'mydate' cannot be used on type 'TableViewController'

Code:

class TableViewController: UITableViewController {    
    let mydate = NSDate()
    let items = [
        (1, 9, 7, "A", mydate),
        (2, 9, 7, "B", mydate),
        (3, 9, 7, "C", mydate),
        (4, 9, 7, "D", mydate)
    ]

When I write the following, I can build it but I don't know why the oder snippet is not working:

class TableViewController: UITableViewController {    
    let mydate = NSDate()
    let items = [
        (1, 9, 7, "A", nil),
        (2, 9, 7, "B", mydate),
        (3, 9, 7, "C", mydate),
        (4, 9, 7, "D", mydate)
    ]
Cœur
  • 37,241
  • 25
  • 195
  • 267
gurehbgui
  • 14,236
  • 32
  • 106
  • 178
  • I ran into the same thing. Your cleanest option is to define them in the class, but populate them in your viewDidLoad() func. This will allow you to nest all you want without these annoying compiling errors. – Mark Löwe Feb 29 '16 at 00:12
  • 2
    @MarkLöwe, that' not "the cleanest solution". And these compiler errors are valid and consistent with the design of the language. The cleanest solution is the solution written here. Initialising in `viewDidLoad` may not be even possible in non-viewcontroller-based classes. Let's not mislead people with ridiculous comments. – avismara Apr 21 '16 at 12:02
  • internal static var mydate : NSDate; internal static var items; This is the easy way to fix this – SOUA Hamza Oct 25 '16 at 10:48

3 Answers3

47

The problem here is that you are using self before the class is fully initialised. You can either have a getter which will be called every time you access the variable or compute it lazily.

Here is some code:

class TableViewController: UITableViewController {
    let mydate = NSDate()
    var items : [(Int,Int,Int,String,NSDate)] {
        get {
            return [
                (1, 9, 7, "A", mydate),
                (2, 9, 7, "B", mydate),
                (3, 9, 7, "C", mydate),
                (4, 9, 7, "D", mydate)
            ]

        }
    }
}

Lazy computation:

class TableViewController: UITableViewController {
    let mydate = NSDate()
    lazy var items : [(Int,Int,Int,String,NSDate)] =  {

            return [
                (1, 9, 7, "A", self.mydate),
                (2, 9, 7, "B", self.mydate),
                (3, 9, 7, "C", self.mydate),
                (4, 9, 7, "D", self.mydate)
            ]


    }()
}
avismara
  • 5,141
  • 2
  • 32
  • 56
3

You can use this code

var items:Array<(Int, Int, Int, String, NSDate)> {
        get {
            return [
                (1, 9, 7, "A", mydate),
                (2, 9, 7, "B", mydate),
                (3, 9, 7, "C", mydate),
                (4, 9, 7, "D", mydate)
            ]
        }
    }
r4id4
  • 5,877
  • 8
  • 46
  • 76
-1

The compiler gets confused because it doesn't know the type of the optional NSDate. You can let it know explicitly about the type.

let items : Array<(Int, Int, Int, String, NSDate?)> = [
    (1, 9, 7, "A", nil),
    (2, 9, 7, "B", mydate),
    (3, 9, 7, "C", mydate),
    (4, 9, 7, "D", mydate)
]

Edit: For the problem with using instance variable, you could initialise your items with a closure.

let items : Array<(Int, Int, Int, String, NSDate?)> = {
    let mydate = NSDate()
    return [
        (1, 9, 7, "A", nil),
        (2, 9, 7, "B", mydate),
        (3, 9, 7, "C", mydate),
        (4, 9, 7, "D", mydate)
    ]
    }()
Adam
  • 26,549
  • 8
  • 62
  • 79