我不确定在Swift中调用API时是否应该使用[weak self]。我正在使用Firebase创建一个用户,如果用户创建成功,我想使用self执行segue。
这是我的代码:
import UIKit
import FirebaseAuth
class RegisterViewController: UIViewController {
@IBOutlet weak var emailTextfield: UITextField!
@IBOutlet weak var passwordTextfield: UITextField!
@IBAction func registerPressed(_ sender: UIButton) {
if let email = emailTextfield.text, let password = passwordTextfield.text {
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
if let e = error {
print(e)
} else {
self.performSegue(withIdentifier: "registerToChat", sender: self)
}
}
}
}}
代码正在工作,但我不确定如果Firebase API请求不工作或延迟很长时间,并且RegisterViewController的self指针没有被释放,会发生什么。因此,我还想讨论一下使用可能会遇到延迟的API的一般做法,以及在这种情况下是否应该始终使用[weak self]。
2条答案
按热度按时间8yparm6h1#
在您的示例中,您几乎肯定会使用对
self
的弱引用。如果视图控制器已经被解除,那么执行segue就没有意义了。虽然这里没有持久的强引用周期风险,但是没有理由将这个视图控制器保留在内存中超过需要的时间。使用weak
引用允许视图控制器在不再需要时立即释放,并且不必等待异步调用完成。使用weak
引用是一种很好的防御性编程模式.希望这回答了关于您的具体问题的问题,但更一般地说,有一些考虑因素:
1.这不是一个问题,但我们经常使用
weak
引用来消除持久的强引用循环的可能性(在这些情况下,闭包可能保存在某些属性中,并且API服务忽略了在完成时释放这个闭包)。这在成熟的API(如Firebase)中通常不是一个问题,但在自制的API或服务中更是一个问题,这些API或服务可能不会注意这些细节。当我们不能完全确定库在内存语义方面的规范性时,我们通常会以防御性的方式使用weak
引用。1.当处理一个不是视图控制器的调用者时(通常,视图控制器应该在相关的视图被解除时被释放;对于某些服务类可能不是这样),它会引发是否要在请求完成之前保留强引用。
例如,通过设计,如果您使用
URLSession
的委托,它会保持对其委托的强引用,直到会话无效。其他服务可能不会这样做。无论如何,肯定有这样的用例,在启动了一些异步请求之后,调用者可能希望将结果保存在一些模型对象或缓存中,而不管视图是否被解除。在这样的极端情况下,您可能有意识地需要一个临时的self
强引用,直到请求完成。1.当您关注内存语义时,通常更广泛的问题是“当调用者被释放时应该发生什么”。具体来说,在处理可取消的API时,我们不担心调用者的生命周期,而是关注被调用API的生命周期。具体来说,我们可能会在不再需要请求的结果时立即显式取消请求。在这种情况下,您不仅可以释放
self
的资源,还可以释放API服务的资源。现在,在您的示例中,
Auth
可能不支持取消。如果没有,这个问题就没有意义了。但是在API确实支持取消的情况下,而不是纠缠于“我应该保持强引用直到请求完成”,你应该关注“如果调用者在异步请求完成之前被解散,我应该立即停止/取消异步API吗?””所以,对于“我应该总是使用
weak
引用吗?”的简短回答是,“经常,但这取决于。”通常我们倾向于weak
引用,但也有很多用例,我们可能会有意识地使用强引用或追求主动取消模式。最后还有一个与内存语义无关的松散相关的问题。也就是说,如果用户在异步请求进行时完全离开应用程序,您希望发生什么?有时(尤其是上传、发布请求等),应用可能希望向操作系统请求一点额外时间,以防用户在请求进行时离开应用。例如,在iOS中,我们可以在后台继续前台工作。
42fyovps2#
你应该在一个闭包中使用
[weak self]
,以避免给出强引用和避免引用循环。您可以查看此文档以了解是否应该始终在闭包内部使用[weak self]
。参见You don’t (always) need [weak self]或Understanding Weak and Unowned References in Swift Closures。
对于API调用,使用
[weak self]
或执行异步操作是一个很好的实践,以防止强引用周期和潜在的内存泄漏。