【问题标题】:Unable to pass Data to my second view controller无法将数据传递给我的第二个视图控制器
【发布时间】:2017-05-18 22:16:46
【问题描述】:

尝试传递已从 CoreData 调用的数据时,返回的错误显示 Thread 1: EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP, subcode=0x0)。调试器读取

致命错误:在展开可选值时意外发现 nil

但是,当我在将变量分配给文本字段之前添加打印语句时,变量会正确打印出来。我已经迷失了。任何帮助,将不胜感激。

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
          let myVC = storyboard?.instantiateViewController(withIdentifier: "editInventoryItem") as! AddInventoryItemVC
          var inventoryItemName: String = ""
          var inventoryItemStock: Double = 0.0
          var inventoryItemPG: Double = 0.0
          var inventoryItemVG: Double = 0.0
          let itemName = flavors[indexPath.row]

          let appDelegate = UIApplication.shared.delegate as! AppDelegate
          let context = appDelegate.persistentContainer.viewContext
          let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Inventory")

          request.predicate = NSPredicate(format: "inventoryItemName ==%@", itemName)
          if let result = try? context.fetch(request) {
              for object in result as! [NSManagedObject] {
                  inventoryItemName = object.value(forKey: "inventoryItemName") as! String
                  inventoryItemStock = object.value(forKey: "inventoryItemStock") as! Double
                  inventoryItemPG = object.value(forKey: "inventoryItemPGPercent") as! Double
                  inventoryItemVG = object.value(forKey: "inventoryItemVGPercent") as! Double
              }
          } else {

          }

          myVC.itemName.text = inventoryItemName
          myVC.itemStock.text = "\(inventoryItemStock)"
          myVC.itemPG.text = "\(inventoryItemPG)"
          myVC.itemVG.text = "\(inventoryItemVG)"

          performSegue(withIdentifier: "editInventoryItem", sender: "")
      }

编辑: 在应用了 Rinki 的建议后,Xcode 给了我以下更正,并且在运行时仍然返回相同的错误。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let itemName = flavors[indexPath.row]

    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Inventory")

    request.predicate = NSPredicate(format: "inventoryItemName ==%@", itemName)
    if let result = try? context.fetch(request) {
        for object in result as! [NSManagedObject] {
            inventoryItemName = object.value(forKey: "inventoryItemName") as! String
            inventoryItemStock = object.value(forKey: "inventoryItemStock") as! Double
            inventoryItemPG = object.value(forKey: "inventoryItemPGPercent") as! Double
            inventoryItemVG = object.value(forKey: "inventoryItemVGPercent") as! Double
        }
    } else {

    }
    performSegue(withIdentifier: "editInventoryItem", sender: "")
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "editInventoryItem" {
        let myVC = segue.destination as! AddInventoryItemVC
        myVC.itemName.text = inventoryItemName
        myVC.itemStock.text = "\(inventoryItemStock)"
        myVC.itemPG.text = "\(inventoryItemPG)"
        myVC.itemVG.text = "\(inventoryItemVG)"
    }
}

更新:经过一些打印后,现在返回错误的原因是有道理的。 prepareForSegue()didSelectRow 之前被调用,因此该值当前为零,但我不知道如何在调用prepareForSegue() 之前调用didSelectRow

编辑:在做了一些研究并实施了单例之后,我已经解决了这个问题。我在 Singleton 中添加了一个 identifier 变量,在调用 didSelectRow 时将变量更改为 editInventoryItem。在第二个 VC 上,我设置了一个简单的 if 语句,将 identifiereditInventoryItem 进行比较并填充相关文本字段。

感谢大家的帮助。一个错误下来,可能是 5,000,000 ! :D

【问题讨论】:

  • 您是如何初始化分配数据的变量的?您可能没有对接收属性的强引用,从而丢失了该数据。我知道在深入研究子/父上下文时,需要将子上下文连同数据一起传递和分配给接收类——对子上下文进行弱引用。
  • 现在它们在两个单独的函数中使用,我将它们移到类的开头,使它们对两个函数都可用。
  • 放置断点并检查您在哪一行收到此错误?
  • Rinki 检查我的更新。该值为 nil,因为在 didSelectRow 之前调用了 prepare()。不过,我不知道为什么或如何解决它。
  • 请原谅我缺乏知识,但我不知道在调用prepare() 函数时用什么替换UIStoryboardSegue

标签: ios swift core-data segue


【解决方案1】:

您的问题与核心数据无关,而是您对 segue 的使用。 performSegue 方法是从情节提要中创建一个新的 viewController。从instantiateViewController 创建的myVC 在函数结束时被丢弃。而是使用 prepareForSegue:sender: 将值添加到 viewController。

【讨论】:

    【解决方案2】:

    调用performSegue后会调用prepareForSegue()方法:

    performSegue(withIdentifier: "editInventoryItem", sender: nil)
    

    在这里您可以将数据从 SourceViewController 发送到 Destination View Controller。

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
    
        if(segue.identifier == "editInventoryItem") {
            let myVC = segue.destinationViewController as! NextViewController
            myVC.itemName.text = inventoryItemName
          myVC.itemStock.text = "\(inventoryItemStock)"
          myVC.itemPG.text = "\(inventoryItemPG)"
          myVC.itemVG.text = "\(inventoryItemVG)"
        }
    }
    

    【讨论】:

      【解决方案3】:

      在第一个ViewController上,我的代码如下:

      func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
          let itemName = flavors[indexPath.row]
      
          let appDelegate = UIApplication.shared.delegate as! AppDelegate
          let context = appDelegate.persistentContainer.viewContext
          let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Inventory")
      
          request.predicate = NSPredicate(format: "inventoryItemName ==%@", itemName)
          if let result = try? context.fetch(request) {
              for object in result as! [NSManagedObject] {
                  Singleton.sharedInstance.itemName = object.value(forKey: "inventoryItemName") as! String
                  Singleton.sharedInstance.itemStock = object.value(forKey: "inventoryItemStock") as! Double
                  Singleton.sharedInstance.itemPG = object.value(forKey: "inventoryItemPGPercent") as! Double
                  Singleton.sharedInstance.itemVG = object.value(forKey: "inventoryItemVGPercent") as! Double
              }
          } else {
      
          }
          Singleton.sharedInstance.identifier = "editInventoryItem"
      }
      

      我的单身人士:

      struct Singleton {
          static var sharedInstance = Singleton()
      
          var identifier = ""
          var itemName = ""
          var itemStock = 0.0
          var itemVG = 0.0
          var itemPG = 0.0
      }
      

      在第一个ViewController上,我的实现代码如下:

      override func viewDidAppear(_ animated: Bool) {
          print(Singleton.sharedInstance.identifier)
          print(Singleton.sharedInstance.itemName)
      
          if Singleton.sharedInstance.identifier == "editInventoryItem" {
              nicotineSwitch.isEnabled = false
              VGSwitch.isEnabled = false
              PGSwitch.isEnabled = false
      
              itemName.text = Singleton.sharedInstance.itemName
              itemStock.text = "\(Singleton.sharedInstance.itemStock)"
              itemPG.text = "\(Singleton.sharedInstance.itemPG)"
              itemVG.text = "\(Singleton.sharedInstance.itemVG)"
              Singleton.sharedInstance.identifier = ""
          }
      }
      

      【讨论】:

        【解决方案4】:

        也许你可以试试Singleton shared instance

        新建一个 NSObject 类型的 Swift 文件

        YourAppState.swift

            class YourAppState : NSObject {
                class var sharedInstance: YourAppState {
                  struct Static {
                    static var onceToken: dispatch_once_t = 0
                    static var instance: YourAppState? = nil
                  }
        
                  dispatch_once(&Static.onceToken) {
                    Static.instance = YourAppState()
                  }
        
                 return Static.instance!
        
                }
            }
        

        有了它,您可以执行以下操作:

        在共享实例文件中创建一个新变量,

        var inventoryItemName = ""

        在去下一个 VC 或执行 segue 之前, 将值赋予inventoryItemName = object.value(forKey: "inventoryItemName") as! String。在目标 VC 类中传递这样的值。

        self.itemName.text = YourAppState.sharedInstance().inventoryItemName

        只需确保在执行转场之前添加该值即可。

        希望对你有帮助,干杯!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多