我对 Swift 和一般的异步代码都很陌生,所以请告诉我这是否还很遥远。基本上我想要:
- 打开应用
- 这会触发 CloudKit 记录的读取
- 读取完成后,UILabel 将显示检索到的记录数
这本身显然没有用,但作为一个原则,它将帮助我理解异步代码操作,以及如何在完成时触发操作。
// In ViewController Swift file:
class ViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
readDatabase()
}
@IBOutlet weak var myLabel: UILabel!
}
let VC=ViewController()
//In Another Swift file:
func readDatabase() {
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "myRecord", predicate: predicate)
let container = CKContainer.default()
let privateDB = container.privateCloudDatabase
privateDB.perform(query, inZoneWith:nil) { (allRecs, err) in
VC.myLabel.text = ("\(allRecs?.count) records retreived")
/*
ERROR OCCURS IN LINE ABOVE:
CONSOLE: fatal error: unexpectedly found nil while unwrapping an Optional value
BY CODE LINE: Thread 8:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
*/
}
}
我可以从 viewDidLoad 函数中设置文本字段,那么为什么不能从该函数中调用的函数中设置文本字段呢?
我尝试过的其他一些事情:
- 使用异步调度将其放在线程 1 上
- 在 ViewController 类中实现 var with,并使用 didSet 设置文本,在 privateDB.perform 代码中将 var 设置为所需的值以触发更改
这两者都会产生与上面相同的问题。
是的,我知道 .perform 中没有任何错误处理,并且有记录。如果我在 View 加载后几秒钟手动触发将 UILabel 文本设置为记录计数,则效果很好。
所以问题是...... 如何以数据库读取完成为触发器,将记录的属性加载到 View 中?
谢谢
<小时/>编辑
这里实际发生的是,VC
是全局创建的,但从未呈现 - 因为 loadView
从未被调用过,myLabel
也没有' t 存在,并且作为强制展开的属性,在引用它时导致崩溃
最佳答案
问题出在这一行:let VC=ViewController()
。在这里,您实例化 ViewController 类的一个新实例,并尝试在该新创建的实例上设置标签。但是,您可能希望在当前显示的 viewController 实例上设置标签。
只需将此行 VC.myLabel.text = ("\(allRecs?.count) 条记录检索")
更改为 self.myLabel.text = ("\(allRecs?. count) 检索到的记录")
它应该可以正常工作。
关于ios - 在 Swift 中 CloudKit 异步操作完成时设置 UILabel 文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44418155/