Swift 可选链与强制类型转换

5
下面的代码突显了我在使用苹果Swift语言时结合可选链和强制类型转换时遇到的问题。
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
    }
}

上述代码会导致以下错误:
'AnyObject' 无法转换为 'String'
可以通过将类变量设置为隐式解包可选类型来解决该问题,示例如下:
class MyExample2 {

    var detailItem: NSManagedObject!

    func example() {
        let name: String = self.detailItem.valueForKey("name") as String
    }
}

这段代码可以运行,但是现在这个变量不符合我在实际应用中需要它是可选的需求。
下一个例子也可以使用optional作为detailItem:
class MyExample3 {

    var detailItem: NSManagedObject?

    func example() {
        let name: String = self.detailItem?.valueForKey("name").description as String
    }
}

以上的问题是我不得不使用描述。根据苹果公司的说法和常识,通常不建议使用此函数的输出来展示给用户。
以上的例子之所以有效,是因为我正在寻找一个字符串。如果我需要一个对象,它将不起作用。
作为一个有趣的点,这个例子会抛出一个不同的错误:
class MyExample4 {

    var detailItem: NSManagedObject?

    func example() {
        let name: String = self.detailItem?.valueForKey("name")
    }
}

上述错误信息如下:
“无法找到'member'valueForKey'。”
NSManagedObject 明确具有 valueForKey 方法。
尝试另一种方法后,我发现了一个可能的解决方案:
class MyExamplePotentialSolution {

    var detailItem: NSManagedObject?

    func example() {
        let name: NSString = self.detailItem?.valueForKey("name") as NSString
    }
}

上述方法的问题在于,当实际分配给UITableViewCell的detailTextLabel.text属性时,它无法正常工作。
有什么想法吗?
更新的答案:
最简单的实际使用方法是这样的:
cell.detailTextLabel.text = self.detailItem?.valueForKey("name") as? NSString

关键是AnyObject不能直接转换为本地的Swift类型。正如所接受的答案所示,它可以从NSString转换为本地的Swift字符串。但在这种情况下并不需要。

1个回答

5

有两个问题:第一个问题在于这一行:

let name: String = self.detailItem?.valueForKey("name") as String

右侧部分是可选的(`detailItem` 是可选的),因此无论表达式返回什么,它都不能分配给类型为 `String` 的非可选变量。
第二个问题是 `valueForKey` 返回 `AnyObject!`,它可以是任何类的实例 - 但 `String` 不是一个类,你需要使用 `Any` 才能将其转换为 `String`。 我假设 `NSManagedObject` 返回一个 `NSString`,因此您可以使用以下行来实现所需的内容:
let name: String? = (self.detailItem?.valueForKey("name") as? NSString) as? String

这是我在潜在的修复版本中尝试的事情之一。这是我尝试过的内容:cell.detailTextLabel.text = self.detailItem?.valueForKey("name") as NSString; // 这不仅无法编译,而且会导致Xcode中的sourcekit崩溃。 - Derrek
这段代码是可以运行的: let name: String? = (self.detailItem?.valueForKey("name") as? NSString) as? String cell.detailTextLabel.text = name - Derrek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接