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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With