Swift 由于无可选值,无法在详细视图中设置领域数据库对象的属性

Swift 由于无可选值,无法在详细视图中设置领域数据库对象的属性,swift,uitableview,realm,uisplitviewcontroller,Swift,Uitableview,Realm,Uisplitviewcontroller,我有一个包含客户机对象的领域数据库,每个对象都有自己的文档列表。在SplitViewController中,我有一个表视图,显示所有添加的客户端。单击客户端时,我可以在另一个tableview中显示该特定客户端的所有文档。出现的问题是,当单击文档时,应用程序崩溃,详细信息视图控制器给出以下错误:线程1:致命错误:在展开可选值时意外发现nil 我已尝试解决此问题,但在应用程序的另一部分中没有主详细信息屏幕出现此问题,因此我觉得出现此问题的原因可能是两个TableView,也可能是Realm数据库出

我有一个包含客户机对象的领域数据库,每个对象都有自己的文档列表。在SplitViewController中,我有一个表视图,显示所有添加的客户端。单击客户端时,我可以在另一个tableview中显示该特定客户端的所有文档。出现的问题是,当单击文档时,应用程序崩溃,详细信息视图控制器给出以下错误:线程1:致命错误:在展开可选值时意外发现nil

我已尝试解决此问题,但在应用程序的另一部分中没有主详细信息屏幕出现此问题,因此我觉得出现此问题的原因可能是两个TableView,也可能是Realm数据库出现问题

一件奇怪的事是,即使我自己分配标签的值而不使用数据库中的值,我也会遇到同样的致命错误

客户:斯威夫特

import Foundation
import RealmSwift

class Client: Object {

@objc dynamic var name: String = ""
@objc dynamic var age: Int = 0
@objc dynamic var bond: Double = 0.0
@objc dynamic var continuances: Int = 0

//Realm syntax to define a to-many relationship meaning each Client can have a number of Document objects
let documents = List<Document>()

}
DocumentTableViewController.swift

import UIKit
import RealmSwift

class DocumentTableViewController: UITableViewController {

let realm = try! Realm()
var documents : Results<Document>?

//Data type optional document because it will be nil until it is set
var selectedClient : Client? {
    //Everything in the did set function will happen as soon as this variable is set with a value
    didSet {
        loadDocuments()
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

//Mark - Model Manipulation Methods

func loadDocuments(){

    //Pulls all document objects out of our realm (persistent data)
    documents = selectedClient?.documents.sorted(byKeyPath: "title", ascending: true)

    tableView.reloadData()
}

// MARK: - Table view data source

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return documents?.count ?? 0
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    performSegue(withIdentifier: "goToDocumentDetails", sender: self)
}

//Load the documents for the selected client
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let navigationController = segue.destination as? UINavigationController
    let viewController = navigationController?.topViewController as? DocumentDetailsViewController

    if let indexPath = tableView.indexPathForSelectedRow {
        viewController?.selectedDocument = documents?[indexPath.row]
    }
}

//MARK: - HELPER FUNCTIONS FOR TESTING

@IBAction func addTestDocument(_ sender: UIBarButtonItem) {

    if let currentClient = self.selectedClient {
        do {
            try self.realm.write {
                let newDocument = Document()
                newDocument.title = "TEST"
                currentClient.documents.append(newDocument)
                print(documents?.count ?? 0)
            }
        } catch {
            print("Error saving new document")
        }
    }

    loadDocuments()

}

}
import UIKit
import RealmSwift

class DocumentDetailsViewController: UIViewController {

let realm = try! Realm()
//var documents : Results<Document>?

@IBOutlet weak var titleLabel: UILabel!

//Data type optional document because it will be nil until it is set
var selectedDocument : Document? {
    //Everything in the did set function will happen as soon as this variable is set with a value
    didSet {
        titleLabel.textColor = UIColor.blue
        titleLabel.text = selectedDocument?.title
    }
}
导入UIKit
导入RealmSwift
类DocumentTableViewController:UITableViewController{
让realm=try!realm()
var文档:结果?
//数据类型可选文档,因为在设置之前它将为零
var selectedClient:客户端{
//使用值设置此变量后,did set函数中的所有内容都将立即发生
迪塞特{
加载文档()
}
}
重写func viewDidLoad(){
super.viewDidLoad()
//加载视图后执行任何其他设置。
}
//标记模型操作方法
func loadDocuments(){
//将所有文档对象移出我们的领域(持久数据)
documents=selectedClient?.documents.sorted(按键路径:“标题”,升序:true)
tableView.reloadData()
}
//标记:-表视图数据源
重写func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int{
返回文件?计数?0
}
重写func tableView(tableView:UITableView,didSelectRowAt indexPath:indexPath){
性能检查(带有标识符:“goToDocumentDetails”,发件人:self)
}
//加载所选客户端的文档
覆盖功能准备(对于segue:UIStoryboardSegue,发送方:有吗?){
让navigationController=segue.destination为?UINavigationController
让viewController=navigationController?.topViewController作为文档详细信息viewController
如果让indexPath=tableView.indexPathForSelectedRow{
viewController?.selectedDocument=文档?[indexPath.row]
}
}
//MARK:-用于测试的辅助函数
@iAction func addTestDocument(uu发件人:UIBarButtonim){
如果让currentClient=self.selectedClient{
做{
尝试self.realm.write{
让newDocument=Document()
newDocument.title=“测试”
currentClient.documents.append(新文档)
打印(文件?.count±0)
}
}抓住{
打印(“保存新文档时出错”)
}
}
加载文档()
}
}
DocumentDetailsViewController.swift

import UIKit
import RealmSwift

class DocumentTableViewController: UITableViewController {

let realm = try! Realm()
var documents : Results<Document>?

//Data type optional document because it will be nil until it is set
var selectedClient : Client? {
    //Everything in the did set function will happen as soon as this variable is set with a value
    didSet {
        loadDocuments()
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

//Mark - Model Manipulation Methods

func loadDocuments(){

    //Pulls all document objects out of our realm (persistent data)
    documents = selectedClient?.documents.sorted(byKeyPath: "title", ascending: true)

    tableView.reloadData()
}

// MARK: - Table view data source

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return documents?.count ?? 0
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    performSegue(withIdentifier: "goToDocumentDetails", sender: self)
}

//Load the documents for the selected client
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let navigationController = segue.destination as? UINavigationController
    let viewController = navigationController?.topViewController as? DocumentDetailsViewController

    if let indexPath = tableView.indexPathForSelectedRow {
        viewController?.selectedDocument = documents?[indexPath.row]
    }
}

//MARK: - HELPER FUNCTIONS FOR TESTING

@IBAction func addTestDocument(_ sender: UIBarButtonItem) {

    if let currentClient = self.selectedClient {
        do {
            try self.realm.write {
                let newDocument = Document()
                newDocument.title = "TEST"
                currentClient.documents.append(newDocument)
                print(documents?.count ?? 0)
            }
        } catch {
            print("Error saving new document")
        }
    }

    loadDocuments()

}

}
import UIKit
import RealmSwift

class DocumentDetailsViewController: UIViewController {

let realm = try! Realm()
//var documents : Results<Document>?

@IBOutlet weak var titleLabel: UILabel!

//Data type optional document because it will be nil until it is set
var selectedDocument : Document? {
    //Everything in the did set function will happen as soon as this variable is set with a value
    didSet {
        titleLabel.textColor = UIColor.blue
        titleLabel.text = selectedDocument?.title
    }
}
导入UIKit
导入RealmSwift
类DocumentDetailsViewController:UIViewController{
让realm=try!realm()
//var文档:结果?
@IBVAR弱var标题标签:UILabel!
//数据类型可选文档,因为在设置之前它将为零
var selectedDocument:文档{
//使用值设置此变量后,did set函数中的所有内容都将立即发生
迪塞特{
titleLabel.textColor=UIColor.blue
titleLabel.text=所选文档?.title
}
}

我希望在传入所选文档对象后,我能够以编程方式更改DocumentsDetailViewController中的值,但尝试以任何方式更改该值都会产生一个nil可选值异常。

这是一个常见的错误/误解。它与领域完全无关

在你打电话的那一刻

viewController?.selectedDocument = documents?[indexPath.row]
目标视图控制器中的插座尚未连接,因此
标题标签
didSet
中为
nil


一种可能的解决方案是将
didSet
中的代码移动到
viewDidLoad

var selectedDocument : Document?

override func viewDidLoad() {
    super.viewDidLoad()
    titleLabel.textColor = UIColor.blue
    titleLabel.text = selectedDocument?.title
}

非常感谢它的工作!我不知道这为什么会引起我的问题。在我的应用程序的不同部分,我有IBOutlets,它们立即加载到DidSet函数中,它们没有引起我相同的问题。我想我知道为什么我现在有这个问题,感谢你的回答。在查看我的代码后,我看到以前我使用didSet()加载值时,它不是加载到IBOutlets中,而是加载到作为TableViewController一部分的outlets中。