AL3MS
AL3MS

Reputation: 91

Can AnyObject be treated as normal objects ? How?

I have AnyObject

    var currentObject : AnyObject

its value depends on if statement :

 if sender.tag == 1 { 
         currentObject = object1()
 }
else if sender.tag == 2 {
        currentObject = object2()
}
.....
etc

numberOfRowsInSection function:

   public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
       return(currentObject.count)
    }

cellForRowAt function:

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath) as UITableViewCell 
    let p = currentObject.item[indexPath.row] 
    cell.textLabel?.text = p.something
    return(cell)
}

and I want to use this line at cellForRowAt function to retrieve cell content from different objects

let p = currentObject.item[indexPath.row] 

I got an error says: 'AnyObject' is not a subtype of 'NSIndexPath'

I want my AnyObject to be treated as the object that I already assigned to it.

any suggestions ?

Upvotes: 0

Views: 89

Answers (3)

Dejan Skledar
Dejan Skledar

Reputation: 11435

AnyObject can be treated as a "base class" for all objects.

So if you have:

let index: AnyObject = IndexPath(item: 0, section: 0)

You can use it by casting it to the desired type:

if let indexPath = index as? IndexPath {
   // indexPath is type of IndexPath
}

Not all AnyObject can be IndexPath, thats why the cast can fail.

This is really basic learning here. I Suggest you check out A Swift Tour by Apple.

Upvotes: 2

vadian
vadian

Reputation: 285260

You are strongly discouraged from using that kind of approach.

Use a protocol based solution.

In your example both types are supposed to respond to item so declare a protocol

protocol HasItem {
    var items : [MyType] { get }
}

I'm using the plural form items as the type is an array.


Then adopt the protocol in your object classes

struct Object1 : HasItem {
    var items = [MyType]()
}

struct Object2 : HasItem {
    var items = [MyType]()
}

Now you can declare currentObject as HasItem

var currentObject : HasItem

Since the compiler knows that an object which conforms to HasItem has an items array this will compile flawlessly

let p = currentObject.items[indexPath.row]

The return value in numberOfRowsInSection is not logical. Most likely this is intended

return currentObject.items.count

And please be aware that return is not a function, there are no parentheses.


If you want to use other common properties and functions in the protocol type you have to add those to the protocol.

And if MyType could be also of different types use another protocol with a property something.

Upvotes: 0

donnywals
donnywals

Reputation: 7591

What you are referring to as an Object is actually a Dictionary. Object is not something that exists in Swift in the way that you're thinking about.

That said, what you might want to do is cast your AnyObject as follows:

if let myDict = currentObject.item as? [AnyObject],
   let p = myDict[indexPath.row] {

   // p is now an AnyObject, cast to whatever you need again

}

Swift is a very strict language so you'll need to make sure that Swift always knows what type something is. Imagine this object:

{
  "id": 10,
  "label": "hello world"
}

You would extract the id and label in Swift like this:

let myObject: [String: AnyObject] = // import the above object as you please
let label = myObject["label"] as? String // cast to string so Swift knows what the type of the label is
let id = myObject["id"] as? Int // must cast again so Swift knows the type of the id.

Hope this is of some help to you :)

Upvotes: 0

Related Questions