Swift 在作用域结束之前,编译器是否隐式取消包装可选变量?
通过swift编译器优化,隐式展开的可选变量不会在整个范围内存在,而是在使用后立即释放 这是我的环境:Swift 在作用域结束之前,编译器是否隐式取消包装可选变量?,swift,variables,scope,rx-swift,Swift,Variables,Scope,Rx Swift,通过swift编译器优化,隐式展开的可选变量不会在整个范围内存在,而是在使用后立即释放 这是我的环境: swift --version 输出 Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28) Target: x86_64-apple-darwin20.2.0 Xcode版本是版本12.3(12C33) 考虑这个最基本的例子来说明问题: final类SomeClass{ func doSth(){} 脱硝{ 印
swift --version
输出
Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
Target: x86_64-apple-darwin20.2.0
Xcode版本是版本12.3(12C33)
考虑这个最基本的例子来说明问题:
final类SomeClass{
func doSth(){}
脱硝{
印刷品(“脱硝”)
}
}
func do(){
var someObject:SomeClass!=SomeClass()
someObject.doSth()
打印(“完成”)
}
这应该是个好消息
done
deinit
但是,在发布版本中(启用了Swift代码优化“-O”),它以另一种方式打印:
deinit
done
这仅适用于var someObject:SomeClass代码>
该代码的以下更改正确地完成了所有输出(意味着当函数的作用域离开时对象被释放):
将var定义为常量:
func-dosthsspecial(){
让someObject:SomeClass!=SomeClass()
someObject.doSth()
打印(“完成”)
}
明确将var定义为可选:
func-dosthsspecial(){
var someObject:SomeClass?=SomeClass()
someObject.doSth()
打印(“完成”)
}
访问权限(如可选):
func-dosthsspecial(){
var someObject:SomeClass!=SomeClass()
someObject?.doSth()
打印(“完成”)
}
最后三个实现都是输出
done
deinit
按这个顺序
不知怎的,这让我哑口无言
但是作为一个程序员,我们习惯于在函数中使用局部变量,直到离开作用域为止
自从ARC首次为ObjC发布以来,情况就不是这样了。ARC始终可以选择在上次使用对象后释放对象(并且经常使用此选项)。这是经过设计的,在Swift(或者在ObjC中也是如此)中不是一个bug
在Swift中,如果要将对象的生存期延长到其最后一次使用之后,则显式地用于此目的
var someObject: SomeClass! = SomeClass()
withExtendedLifetime(someObject) {
someObject.doSth()
print("done")
}
请记住,对象对其进行平衡的retain/AUTORELASE调用是合法的,这可能会导致它们超出其范围。这在Swift中不太常见,但仍然是合法的,如果您将Swift对象传递给ObjC,就会发生这种情况(这可能发生在许多您可能无法预料的地方)
您应该非常小心地依赖于何时调用deinit
。它可以让你吃惊,甚至在所有情况下都没有承诺(例如,在C++上的程序退出时不调用代码> DENITIT <代码>,这会使C++开发者感到惊讶)。
IMOperformAsyncSyncTask
是一种危险的模式,应该以更清晰的所有权重新设计。我没有做足够的RxSwift工作来立即重新设计它,但是在DispatchSemaphore上阻塞整个线程似乎是与任何反应式系统集成的错误方式。线程是一种有限的资源,这迫使系统创建更多的线程,而这个线程被阻塞,不做任何事情