swift optional chaining with cast
ios, swift
Solution
There are 2 problems: the first is that in this line:
let name: String = self.detailItem?.valueForKey("name") as String
the right part is an optional (`detailItem` is optional), so whatever the expression returns, it cannot be assigned to a non-optional variable having type `String`
The second problem is that `valueForKey` returns `AnyObject!`, which can be an instance of any class - but `String` is not a class, you'd need `Any` in order to be able to cast that into a `String`. I presume that `NSManagedObject` returns an `NSString`, so you can achieve what you need with this line:
let name: String? = (self.detailItem?.valueForKey("name") as? NSString) as? String
Problem
The code below highlights a problem I'm having combining optional chaining and casts with Apple's swift language ``` import Foundation import CoreData class MyExample { var detailItem: NSManagedObject? func example() { //In the actual implementation it is assigned to a UITableViewCell textLabel.text with the same result. let name: String = self.detailItem?.valueForKey("name") as String } } ``` The above results in: 'AnyObject' is not convertible to 'String' I am able to do this by making the class variable an implicitly unwrapped optional as follows: ``` class MyExample2 { var detailItem: NSManagedObject! func example() { let name: String = self.detailItem.valueForKey("name") as String } } ``` This works, but now this variable doesn't reflect my real world need for it to be optional This next example also works with detailItem as optional: ``` class MyExample3 { var detailItem: NSManagedObject? func example() { let name: String = self.detailItem?.valueForKey("name").description as String } } ``` The problem with the above is I had to use description. It's generally not a good idea to use output from this function to show to the user (according to Apple, and just common sense) The above also only works because I am looking for a string. If I needed an object, it wouldn't work. As a point of interest this example throws a different error: ``` class MyExample4 { var detailItem: NSManagedObject? func example() { let name: String = self.detailItem?.valueForKey("name") } } ``` The above throws: Could not find member 'valueForKey' NSmanagedObject clearly has a valueForKey. Trying one more thing, I discovered a potential solution: ``` class MyExamplePotentialSolution { var detailItem: NSManagedObject? func example() { let name: NSString = self.detailItem?.valueForKey("name") as NSString } } ``` The problem with the above, is it doesn't work when actually assigned to a UITableViewCell detailTextLabel.text attribute. Any ideas? Updated Answer The simplest real world usage turned out to be this: ``` cell.detailTextLabel.text = self.detailItem?.valueForKey("name") as? NSString ``` The key is AnyObject can't be cast to a native swift type directly. As the accepted answer showed, it can be cast as a native Swift string from NSString. It just isn't necessary in this case.