8

I'm loading a list of objects from a core data database into a table view.

class ScheduleViewController: UITableViewController {

    private var items: [AnyObject]?

    // MARK: - Table view data source
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let itemCount = items?.count {
            return itemCount
        }
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("DayScheduleCell", forIndexPath: indexPath) as DayScheduleCell

        if let act = items[indexPath.row] as Activity {
            if act.client != nil {
                // ...
            }
        }

        return cell
    }
}

The data is retrieved inside a closure so I have declared an items array as an optional because it might be nil in the first run.

I'm getting the error '[AnyObject]?' does not have a member named 'subscript' at this line if let act = items[indexPath.row] as? Activity.

I can't figure out how to resolve this.

Isuru
  • 30,617
  • 60
  • 187
  • 303

3 Answers3

21

The array is declared as:

 private var items: [AnyObject]?

so, as you also said, it's an optional

In swift an optional is an enum, so a type on its own - and as an optional, it can contain either a nil value or an object of the contained type.

You want to apply the subscript to the array, not to the optional, so before using it you have to unwrap the array from the optional

items?[indexPath.row]

but that's not all - you also have to use the conditional downcast:

as? Activity

because the previous expression can evaluate to nil

So the correct way to write the if statement is

if let act = items?[indexPath.row] as? Activity {
Antonio
  • 71,651
  • 11
  • 148
  • 165
  • Thanks for the reply. I'm getting a new error **Cannot invoke '!=' with an argument list of type '(@lvalue Client, NilLiteralConvertible)'** at the line `if act.client != nil`. The client property is a property that holds a `Client` object. Please see the `NSManagedObject` [subclass](http://pastie.org/9584414#) of `Activity`. In the Data Model inspect under properties for client, its checked as optional though. – Isuru Sep 22 '14 at 14:32
  • `client` is not an optional, and as such it cannot be `nil` - hence you cannot check if it's not nil. That `if` is conceptually redundant and of course considered an error for the compiler – Antonio Sep 22 '14 at 14:46
  • So according to [this](http://stackoverflow.com/q/25485273/1077789) question, even though properties are marked optional in Core Data, its not mentioned in the generated `NSManagedObject` classes. You have to manually add it. I added a `?` in front of the client property and now it works fine. – Isuru Sep 22 '14 at 14:47
2

First of all you need to unwrap or optional chain the items as it can be nil. AnyObject has different behaviour when getting as element from array, due to the fact that AnyObject can be a function. You would have to cast from items like this:

if let act = items?[indexPath.row] as AnyObject? as Activity? {
    if act.client != nil {
        // ...
    }
}

If items will never contain a function you can use

private var items: [Any]?

instead and cast with:

if let act = items?[indexPath.row] as? Activity {
    if act.client != nil {
        // ...
    }
}
Kirsteins
  • 27,065
  • 8
  • 76
  • 78
  • Thanks for the reply. But unfortunately I still get the same error at the same line. – Isuru Sep 22 '14 at 14:20
  • Sorry, I had a typo. Try now. – Kirsteins Sep 22 '14 at 14:21
  • That error is gone. But I get a new error **Cannot invoke '!=' with an argument list of type '(@lvalue Client, NilLiteralConvertible)'** at the line `if act.client != nil` – Isuru Sep 22 '14 at 14:22
  • Is `client` property declared as optional value? – Kirsteins Sep 22 '14 at 14:26
  • It's another object in my core data database. [Here](http://pastie.org/9584414) is the `NSManagedObject` subclass of it. In the Data Model Inspector under Properties, its checked as Optional though. – Isuru Sep 22 '14 at 14:29
  • `client` is marked as as optional (perhaps in NSManagedObject underlying subclass it is) and cannot be compared to `nil`. I think you have to manually mark `client` property as optional. At least this question has similar problem: http://stackoverflow.com/questions/25485273/swift-coredata-cannot-automatically-set-optional-attribute-on-generated-nsman – Kirsteins Sep 22 '14 at 14:43
  • Yes, I just saw this question as well and manually marked the optional and now the error is gone. Thank you. – Isuru Sep 22 '14 at 14:46
  • I got 2 answers to this question and both of them are correct. I'll have to accept @Antonio's answer because he replied first. Sorry. But thank you again for helping me out. :) – Isuru Sep 22 '14 at 14:50
1

I have fixed my problem by convert index var type from UInt to Int

let obj = items[Int(index)]

Hope this can help someone who still get this problem.

z33
  • 1,193
  • 13
  • 24