我有一个带有Client对象的领域数据库,每个对象都有自己的Document列表。在我的SplitViewController中,我有一个显示所有已添加客户端的表格视图。单击一个客户端后,我可以在另一个表格视图中显示该特定客户端的所有文档。发生的问题是在单击文档时应用程序崩溃,并且详细信息视图控制器给出以下错误:线程1:致命错误:在展开一个可选值时意外发现nil。
我已经尝试解决此问题,并且在应用程序另一部分的主从屏幕中没有出现此问题,所以我认为此问题是由于两个表视图或Realm数据库中的某个问题而发生的。
一个奇怪的事情是,即使我自己分配标签的值而不使用数据库中的值,我也遇到同样的致命错误。
Client.swift
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>()
}
Document.swift
import Foundation
import RealmSwift
class Document: Object {
@objc dynamic var title: String = ""
@objc dynamic var image: String = ""
//An inverse relationship with each Document having an associatedClient that is of the
//type Client and it comes from the property called "documents" from the Client forward relationship
var associatedClient = LinkingObjects(fromType: Client.self, property: "documents")
}
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()
}
}
DocumentDetailsViewController.swift
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
}
}
我希望在传入所选Document对象之后,能够以编程方式更改DocumentsDetailViewController中的值,但是尝试以任何方式更改该值都会产生nil个可选值异常。
答案 0 :(得分:1)
这是一个常见的错误/误解。它与Realm完全无关。
此刻您致电
viewController?.selectedDocument = documents?[indexPath.row]
目标视图控制器中的插座尚未连接,因此titleLabel
中的nil
是didSet
。
可能的解决方案是将didSet
中的代码移至viewDidLoad
var selectedDocument : Document?
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.textColor = UIColor.blue
titleLabel.text = selectedDocument?.title
}