ios - 无主变量和异步函数
问题描述
我有一个具有无主变量的类。像这样:
class Student {
unowned var school: School
init(_ school: School) {
self.school = school
}
}
现在想象我在类中有一个转义的异步函数:
class Student {
unowned var school: School
init(_ school: School) {
self.school = school
}
// When this function is first called
// I can guarantee school has not been de-initialized
func reportAttendance(completionHandler: @escaping (() -> Void)) {
database.studentDidReportAttendance(student: self) {
// I cannot guarantee school has not been deinitialized
// when this callback function returns!
school.updateAttendance()
completionHandler()
}
}
}
我这里的问题是我可以保证reportAttendance()
调用的时候,那个学校没有被反初始化,但是在数据库响应的时间里,我不能保证那个学校不会被反初始化。因此,如果是这样,那么当异步块返回并尝试访问学校时,我会收到运行时错误。
我的问题是如何在第一次调用该函数时创建对学校的临时强引用,然后在我能够安全地updateAttendance
在学校运行后释放它?
谢谢
解决方案
您可以在函数内创建一个局部变量以保持强引用;看到这个测试:
class School {
deinit {
print ("School.deinit")
}
}
class Student {
unowned var school:School
init(_ school: School) {
self.school = school
}
func printSchool() -> (() -> Void) {
let strongSchool = self.school
return { print ("I'm going to \(strongSchool)") }
}
}
if (1==1) {
var s:School? = School()
let student = Student(s!)
let p = student.printSchool()
s = nil
p() // Won't crash
}
没有strongSchool
,代码段就会崩溃。
问题是我们在闭包之外创建了一个强引用——此时你保证它仍然存在——然后在闭包内引用它。这样,我们
- 不要捕获
student
/self
,而只捕获school
- 避免循环引用,以防
database
学生可以强烈访问并将闭包保持为属性(因为self
->database
->closure
->self
)并且只要school
不引用数据库(嗯,写起来比想起来更复杂)
但正如@matt 所说,unowned
这是非常危险的,weak
应该首选,除了一些不常见的情况,你有无数的无主对象,这会导致大量的内务管理开销。
推荐阅读
- c# - Unity 2d刚体;在 Y 轴上以相同的速度移动比在 X 轴上快
- c++ - 如何在 Visual Studio for C++ 中启用 Intellisense 补全?
- html - Iframe css 样式在 Iphone 上不起作用,如何解决这个问题?
- python - 为什么在平局时会转到 else 语句?
- sql - 如何将行数据显示为列
- python - opencv undistortPoints 不会不失真
- batch-file - 有没有办法在一次检查中减少咨询时间?
- java - 排除 Java 文件中的元素
- c++ - 将 Box2D 添加到 Xcode (12.4) 项目时遇到问题
- java - 如何计算用户输入的字符串?(爪哇)