意外发现nil

Unexpectly found nil

我正在更新 CoreData,我需要加载数据以编辑到文本字段。在 viewDidLoad 的 AddViewController 中,我有

if let myData = data {

            knihaTextField.text = data.valueForKey("kniha") as? String
            autorTextField.text = data.valueForKey("autor") as? String
            rokTextField.text = data.valueForKey("rok") as? String
            vydavatelstvoTextField.text = data.valueForKey("vydavatelstvo") as? String
            stranyTextField.text = data.valueForKey("strany") as? String

        }

在knihaTextField.text = data.valueForKey("kniha")中作为?字符串我收到错误

fatal error: unexpectedly found nil while unwrapping an Optional value

完整代码:

http://pastebin.com/yF53nbSE

我正在做从 DetailView 到 PridatView 的 segue - 完整代码:

http://pastebin.com/BeG4eZHX

这里对 if let 的工作原理存在误解。

if let 语句之后使用 myData,而不是 data

if let myData = data {
    knihaTextField.text = myData.valueForKey("kniha") as? String
}

你不知道你的某些参数是否不为零。你应该为你的所有参数做一个可选的绑定(以防你总是需要它们全部设置)。这就是从 Swift 1.2 (Xcode 6.3 Beta):

开始进行多重展开的方式

编辑:您可以使用shorthand语法访问值:

if let myData = data as? NSDictionary {
    if let kniha = myData["kniha"] as? String, autor = myData["autor"] as? String, 
       rok = myData["rok"] as? String, vydavatelstvo = myData["vydavatelstvo"] as? String, 
       strany = myData["strany"] as? String {
           knihaTextField.text = kniha 
           autorTextField.text = autor
           rokTextField.text = rok
           vydavatelstvoTextField.text = vydavatelstvo
           stranyTextField.text = strany
    }
}

knihaTextField大概是nil。如果您使用的是 Interface Builder,那么您还没有连接它。

看到您的代码后 - 问题在于文本字段位于单元格内。创建单元格时,您将它们的文本字段保存到变量中。但是,viewDidLoad 通常是控制器中的第一个调用,肯定在 table 视图委托之前调用,因此您的所有文本字段都将是 nil.

我的建议是忘记 viewDidLoad 并删除所有 UITextField 变量。相反,您应该:

if (indexPath.row == 0) {
    cell!.configure("Názov knihy", delegate:self)
    cell!.textField.text = data?.valueForKey("kniha") as? String
}
else if (indexPath.row == 1) {
    cell!.configure("Meno autora", delegate:self)
    cell!.textField.text = data?.valueForKey("autor") as? String
}

你也可以像这样简化代码

let titles = ["Názov knihy", "Meno autora"] //add the other titles here
let propertyKeys = ["kniha", "autor"]   //add the other keys here

cell!.configure(titles[indexPath.row], delegate:self)
cell!.textField.text = data?.valueForKey(propertyKeys[indexPath.row]) as? String

如果您想在多个文本字段之间进行区分,这是使用 UIView.tag 的一种简单(不是最佳)解决方案。

cell!.textField.tag = indexPath.row

您的代码中还有其他问题。通常,table 单元格是动态释放和重新分配的,因此您不能以这种方式保留对文本字段的引用。

最好的架构可能是:

  1. 每个 String 值都有实例变量。
  2. viewDidLoad 中设置来自 data 的变量值。
  3. cellForRow中只使用实例变量,不要使用data
  4. 有一个 UITextFieldDelegate 可以将文本值保存回您的实例变量(使用 tag 区分文本字段)。
  5. saveTapped中使用实例变量写回data,不要使用textFields。

老实说,如果您删除 UITableView 并将其替换为 UIScrollView,整个用例会变得更容易。在 Interface Builder 中设计屏幕会使它变得非常快并且会变得更容易,因为您不会遇到单元重用的问题。此外,如果连接正确,viewDidLoad.

中的所有文本字段都已经非零

伙计们,谢谢你们的帮助。但是我和朋友一起解决了。并决定它需要在 viewDidAppear

 override public func viewDidAppear(animated: Bool) {
        if let myData = data {
            knihaTextField.text = myData.valueForKey("kniha") as? String
            autorTextField.text = myData.valueForKey("autor") as? String
            rokTextField.text = myData.valueForKey("rok") as? String
            vydavatelstvoTextField.text = myData.valueForKey("vydavatelstvo") as? String
            stranyTextField.text = myData.valueForKey("strany") as? String
        } 
    }