可选的致命错误没有意义

fatal errors with optionals not making sense

我一直收到一个致命错误,说一个值是如何解包的,它是零,我不明白是如何解包的。当我用特定变量实例化一个视图控制器时,它们都会显示出来,但是当我精确地执行一个 segue VC 时,这些值不会显示出来。

以这些函数为例...

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    
  
    
    if let displayVC = storyboard?.instantiateViewController(withIdentifier: Constants.Storyboards.TeachStoryboardID) as? SchoolEventDetailsViewController {
        
        displayVC.selectedEventName = events[indexPath.row].eventName
        displayVC.selectedEventDate = documentsDate[indexPath.row].eventDate
        displayVC.selectedEventCost = documentsCost[indexPath.row].eventCost
        displayVC.selectedEventGrade = documentsGrade[indexPath.row].eventGrade
        displayVC.selectedEventDocID = documentsID[indexPath.row]?.docID
        
        navigationController?.pushViewController(displayVC, animated: true)
    }
}

这与此功能相结合:

func verifyInstantiation() {
    if let dateToLoad = selectedEventDate {
        dateEditableTextF.text = dateToLoad
    }
    
    if let costToLoad = selectedEventCost {
        costEditableTextF.text = costToLoad
    }
    
    if let gradesToLoad = selectedEventGrade {
        gradesEditableTextF.text = gradesToLoad
    }
    
    if let docIDtoLoad = selectedEventDocID {
        docIDUneditableTextF.text = docIDtoLoad
    }
    
    if let eventNameToLoad = selectedEventName {
        eventNameEditableTextF.text = eventNameToLoad
    }
}

有助于完美加载数据,但是当我尝试从搜索控制器执行 segue 时,数据不存在。

override func viewDidLoad() {
    super.viewDidLoad()
    
    navigationItem.title = selectedEventName

我将 vc 的标题设置为具有事件名称,并且我最近还添加了一个文本字段来存储它以及用于实验目的(这个问题)。

现在的问题是我想从 Algolia 搜索控制器到那个 VC 进行数据传输,我得到了所有其他字段,除了一个是文档 ID。所以我创建了一个完成处理程序函数来获取文档 ID 作为字符串,并在执行 segue 时将其插入 vc,就像实例化 vc 时它的存在方式一样。

函数如下:

func getTheEventDocID(completion: @escaping ((String?) -> ())) {
    documentListener = db.collection(Constants.Firebase.schoolCollectionName).whereField("event_name", isEqualTo: selectedEventName ?? navigationItem.title).addSnapshotListener(includeMetadataChanges: true) { (querySnapshot, error) in
        if let error = error {
            print("There was an error fetching the documents: \(error)")
        } else {
            self.documentsID = querySnapshot!.documents.map { document in
                return EventDocID(docID: (document.documentID) as! String)
            }
            let fixedID = "\(self.documentsID)"
            let substrings = fixedID.dropFirst(22).dropLast(3)
            let realString = String(substrings)
            completion(realString)
        }
    }
}

我认为 selectedEventNamenavigationItem.title 可以完成工作并在我现在将展示的数据传输函数中使用该函数时提供值 :

 //MARK: - Data Transfer From Algolia Search to School Event Details
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    
    otherVC.getTheEventDocID { (eventdocid) in
        if let id = eventdocid {
            if segue.identifier == Constants.Segues.fromSearchToSchoolEventDetails {
                let vc = segue.destination as! SchoolEventDetailsViewController
                vc.selectedEventName = self.nameTheEvent
                vc.selectedEventDate = self.dateTheEvent
                vc.selectedEventCost = self.costTheEvent
                vc.selectedEventGrade = self.gradeTheEvent
                vc.selectedEventDocID = id
            }
        }
    }
 
    
}

但是当点击搜索结果时它最终什么也没有显示,这非常令人沮丧,我不明白为什么当我在 SchoolEventDetailsVC 中声明它们时它们都是空值。我试图强制解包 selectedEventName 并且它崩溃说有一个 nil 值,我无法弄清楚为什么。这个问题实际上还有很多,但我只是尽量保持简短,这样人们就会真正尝试阅读它并提供帮助,因为没有人读过我 post 的问题,所以提前谢谢。

我有点搞不懂 otherVC 是什么,它在 getTheEventDocID 中设置了自己的 属性,而在闭包中你设置了 [=14] 的属性=],这是一个不同的控制器。不过没关系,我希望你知道你在做什么。

由于 getTheEventDocID 异步运行,视图将在数据可用之前加载并显示。因此,viewDidLoad看到的不是实际数据,而是即将过时的东西。

因此,您需要通知详细信息视图控制器有新数据可用,并刷新其用户界面。像

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    otherVC.getTheEventDocID { (eventdocid) in
        if let id = eventdocid {
            if segue.identifier == Constants.Segues.fromSearchToSchoolEventDetails {
                let vc = segue.destination as! SchoolEventDetailsViewController
                vc.selectedEventName = self.nameTheEvent
                vc.selectedEventDate = self.dateTheEvent
                vc.selectedEventCost = self.costTheEvent
                vc.selectedEventGrade = self.gradeTheEvent
                vc.selectedEventDocID = id
                vc.updateUI()
            }
        }
    }
}

并在目标视图控制器中:

class SchoolEventDetailsViewController ... {
    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
    }

    func updateUI () {
        navigationItem.title = selectedEventName
        // and so on
    }
}

好的,所以我决定尝试一种变通方法并完全放弃 getTheEventDocID() 方法,因为它只会给我带来压力。所以我决定放弃 Firebase 生成的文档 IDS,只使用我创建的函数生成的 10 位数字 ID。我还想出了如何通过将随机的 10 位数字 ID 存储在变量中并在两个地方使用它来在 Algolia 记录中添加完全相同的 10 位数字 ID。所以现在我不再使用查询调用来获取 Firebase 生成的文档 ID 并让我的应用程序在每次单击搜索结果时崩溃,我基本上编辑了 Algolia 记录的 Struct 并添加了一个 eventDocID 属性 可以与 hits.hitSource(at: indexPath.row).eventDocID.

一起使用

现在,就像我通过 segue 数据传输将其他字段添加到 vc 一样,我现在可以用我的文档 ID 做同样的事情,因为一切都匹配:)。