未引用的对象是否可能保留在内存中并调用目标操作?
Is it possible for an unreferenced object to stay in memory and invoke target action?
我有一个 class 这样的:
class Example: UIView {
init(frame: CGRect) {
super.init(frame: frame);
let tap = UITapGestureRecognizer(target: self, action: #selector(dismiss(_:)));
self.addGestureRecognizer(tap)
self.isUserInteractionEnabled = true;
self.backgroundColor = UIColor.red;
}
func show(parentView: UIView) {
parentView.addSubview(self);
}
@objc func dismiss(_ sender: UITapGestureRecognizer? = nil) {
self.removeFromSuperview();
}
}
然后我想这样称呼它:
override func viewWillAppear() {
super.viewWillAppear();
Example.init(frame: self.view.bounds).show(parentView: self.view);
}
视图按预期显示为红色背景。但是当我点击视图时,什么也没有发生。甚至没有调用 dismiss 函数。
但是如果这样做的话:
var example : UIView!;
override func viewWillAppear() {
super.viewWillAppear();
example = Example.init(frame: self.view.bounds);
example.show(parentView: self.view);
}
水龙头工作正常。我怀疑这是因为该物体在途中被破坏了?但它仍然存在于 UIView
子视图堆栈中?我认为它没有被完全破坏,因为它被父视图子视图引用了,对吗?我可以在不创建局部变量来保存对象(仅由子视图引用)的情况下使目标操作起作用吗?
您不需要为 Example
的实例创建 ivar。通过调用 show(parent:)
你最终将它添加到视图层次结构中,视图层次结构保留了它。所以它留在记忆中。
如果我 运行 在一个全新的 Xcode 单视图应用程序项目中使用您的示例代码,它在没有 ivar 的情况下也能正常工作。我的代码是:
import UIKit
class Example: UIView {
override init(frame: CGRect) {
super.init(frame: frame);
let tap = UITapGestureRecognizer(target: self, action: #selector(dismiss(_:)));
self.addGestureRecognizer(tap)
self.isUserInteractionEnabled = true;
self.backgroundColor = UIColor.red;
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func show(parentView: UIView) {
parentView.addSubview(self);
}
@objc func dismiss(_ sender: UITapGestureRecognizer? = nil) {
self.removeFromSuperview();
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
Example.init(frame: self.view.bounds).show(parentView: self.view);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
当我 运行 这段代码时会发生什么:
因此,点击红色 Example
视图似乎使其消失,就像您希望的那样。
是的,这是可行的,因为父视图始终是其子视图的所有者。如果不是这样,您 iPhone 上的大多数屏幕都会非常空旷,因为它们没有所有者。为此,outlets使用弱引用也是可以的。
我有一个 class 这样的:
class Example: UIView {
init(frame: CGRect) {
super.init(frame: frame);
let tap = UITapGestureRecognizer(target: self, action: #selector(dismiss(_:)));
self.addGestureRecognizer(tap)
self.isUserInteractionEnabled = true;
self.backgroundColor = UIColor.red;
}
func show(parentView: UIView) {
parentView.addSubview(self);
}
@objc func dismiss(_ sender: UITapGestureRecognizer? = nil) {
self.removeFromSuperview();
}
}
然后我想这样称呼它:
override func viewWillAppear() {
super.viewWillAppear();
Example.init(frame: self.view.bounds).show(parentView: self.view);
}
视图按预期显示为红色背景。但是当我点击视图时,什么也没有发生。甚至没有调用 dismiss 函数。
但是如果这样做的话:
var example : UIView!;
override func viewWillAppear() {
super.viewWillAppear();
example = Example.init(frame: self.view.bounds);
example.show(parentView: self.view);
}
水龙头工作正常。我怀疑这是因为该物体在途中被破坏了?但它仍然存在于 UIView
子视图堆栈中?我认为它没有被完全破坏,因为它被父视图子视图引用了,对吗?我可以在不创建局部变量来保存对象(仅由子视图引用)的情况下使目标操作起作用吗?
您不需要为 Example
的实例创建 ivar。通过调用 show(parent:)
你最终将它添加到视图层次结构中,视图层次结构保留了它。所以它留在记忆中。
如果我 运行 在一个全新的 Xcode 单视图应用程序项目中使用您的示例代码,它在没有 ivar 的情况下也能正常工作。我的代码是:
import UIKit
class Example: UIView {
override init(frame: CGRect) {
super.init(frame: frame);
let tap = UITapGestureRecognizer(target: self, action: #selector(dismiss(_:)));
self.addGestureRecognizer(tap)
self.isUserInteractionEnabled = true;
self.backgroundColor = UIColor.red;
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func show(parentView: UIView) {
parentView.addSubview(self);
}
@objc func dismiss(_ sender: UITapGestureRecognizer? = nil) {
self.removeFromSuperview();
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
Example.init(frame: self.view.bounds).show(parentView: self.view);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
当我 运行 这段代码时会发生什么:
因此,点击红色 Example
视图似乎使其消失,就像您希望的那样。
是的,这是可行的,因为父视图始终是其子视图的所有者。如果不是这样,您 iPhone 上的大多数屏幕都会非常空旷,因为它们没有所有者。为此,outlets使用弱引用也是可以的。