gpt4 book ai didi

ios - 在 iOS 的 ViewController 中声明 View 时,为什么在 Swift 中使用 "weak"关键字

转载 作者:行者123 更新时间:2023-11-29 05:15:48 25 4
gpt4 key购买 nike

在 ViewController 中设置 View 的以下方法有什么区别

强制解开:

class VC: UIViewController() {
var customView: UIView!

override func viewDidLoad() {
super.viewDidLoad()
customView = UIView(frame: .zero)
addSubview(customView)
}
}

弱力解包:

class VC: UIViewController() {
weak var customView: UIView!

override func viewDidLoad() {
super.viewDidLoad()
customView = UIView(frame: .zero)
addSubview(customView)
}
}

:

class VC: UIViewController() {
weak var customView: UIView

override func viewDidLoad() {
super.viewDidLoad()
customView = UIView(frame: .zero)
addSubview(customView)
}
}

在声明中构造:

class VC: UIViewController() {
var customView = UIView(frame: .zero)

override func viewDidLoad() {
super.viewDidLoad()
addSubview(customView)
}
}

weak 在声明中构造

class VC: UIViewController() {
weak var customView = UIView(frame: .zero))

override func viewDidLoad() {
super.viewDidLoad()
addSubview(customView)
}
}

最佳答案

您的问题可能与 Xcode 创建 socket 有关:

@IBoutlet weak var label: UILabel!

苹果(和其他专家)已经讨论过是否应该在这里使用weak(因为这些 View 几乎总是由view本身保留 - 我相信如果你深入挖掘你会发现关于它的讨论无休无止。您通常会删除上面的 weak 而不会产生任何副作用(尝试一下,看看 - 在 View Controller dealloc 中添加一条日志消息。

但是,让我们来回答您的具体问题。我在一个测试项目中开设了一个小类(每个人想要探索此类主题时都应该这样做!):

final class MemoryTest: NSObject {

lazy var vc1 = VC1()
lazy var vc2 = VC2()
lazy var vc4 = VC4()
lazy var vc5 = VC5()

func test() {
let _ = vc1
let _ = vc2
// let _ = vc3
let _ = vc4
let _ = vc5
}
}

// What is the difference between the following methods of setting up views in a ViewController

// `force-unwrapped`:

/*
Interoperability with Objective C required this.
Any code accessing vc1 before its set will crash, forced unwrapped means that Swift will always try to unwrap what is
otherwise an optional, and if nil boom down youg go.

Since Objective C can deal with nil objects, you can access it and read properties, all of which will be nil
*/
@objcMembers
class VC1: UIViewController {
var customView: UIView!

init() {
super.init(nibName: nil, bundle: nil)

//print("BG Color 1", customView.backgroundColor) // Compiler warning then a crash
print("BG Color 2", customView?.backgroundColor ?? "none") // crash
customView = UIView(frame: .zero)
view.addSubview(customView)
customView = nil // the view is still there - its retained by your view, but your reference to it is gone
//print("BG Color 3", customView.backgroundColor ?? "none") // crash
}
required init?(coder: NSCoder) { // compiler forces this
fatalError("init(coder:) has not been implemented")
}
}

//`weak force-unwrapped`:

@objcMembers
class VC2: UIViewController {
weak var customView: UIView!

init() {
super.init(nibName: nil, bundle: nil)

// customView = UIView(frame: .zero) // Compiler error - cannot even build - compiler knows this will be released immediately
view.addSubview(UIView(frame: .zero)) // view retains this newly added view
customView = view.subviews.first // since its retained already, we can reference it "weakly" (meaning its not further retained)

customView.backgroundColor = .yellow
print("Frame", customView.frame)
customView.removeFromSuperview() // since customView is weak, it got nilled with the view was released

// immediate refernces still work - there is some delay until that customView actually gets dealloed
print("CustomerView", String(format: "Pointer %p", customView)) // Still there ...

DispatchQueue.main.async {
if self.customView == .none {
print("Its gone now!")
}
//print("CustomerView", String(format: "Pointer %p", self.customView)) // Crash!
}
}
required init?(coder: NSCoder) { // compiler forces this
fatalError("init(coder:) has not been implemented")
}
}

//`weak`: this is an illegal syntax and you cannot compile it

// class VC3: UIViewController {
// weak var customView: UIView // Compiler hard error, requires either a "!" or "?" suffix
//
// init() {
// super.init(nibName: nil, bundle: nil)
//
// customView = UIView(frame: .zero)
// view.addSubview(customView)
// }
// required init?(coder: NSCoder) { // compiler forces this
// fatalError("init(coder:) has not been implemented")
// }
// }

//constructed in declaration:

@objcMembers
class VC4: UIViewController {
var customView = UIView(frame: .zero)

init() {
super.init(nibName: nil, bundle: nil)

print("Frame", customView.frame) // fine - the view is constructed immediately, and since its "strong" the view persists until
// dealloc.
super.viewDidLoad()
view.addSubview(customView)
}
required init?(coder: NSCoder) { // compiler forces this
fatalError("init(coder:) has not been implemented")
}
}

//`weak` constructed in declaration

@objcMembers
class VC5: UIViewController {
weak var customView = UIView(frame: .zero) // Compiler warning, the view is instantiated, then immediately released.
{ didSet { if customView == nil { print("NIL !!!") } } } // does not work - the change isn't ob

init() {
print("CUSTOMVIEW", customView?.frame ?? "already gone") // its gone

super.init(nibName: nil, bundle: nil)

print("CUSTOMVIEW", customView?.frame ?? "already gone") // its gone

// At this point, customView was allocated, then immediately released as its not retained elsewhere
super.viewDidLoad()
//view.addSubview(customView!) // Crash
}
required init?(coder: NSCoder) { // compiler forces this
fatalError("init(coder:) has not been implemented")
}
}

但是,Objective C 并不关心这些。这是引用所有这些类的另一个类:

@implementation ObjcTest

- (void)test {
VC1 *vc1 = [VC1 new];
NSLog(@"vc1 %@", vc1.customView);

VC2 *vc2 = [VC2 new];
NSLog(@"vc2 %@", vc2.customView);

VC4 *vc4 = [VC4 new];
NSLog(@"vc4 %@", vc4.customView);

VC5 *vc5 = [VC5 new];
NSLog(@"vc5 %@", vc5.customView);
}

@end

/* Console:

2019-12-05 16:37:52.534537-0500 TableSelections[51189:30629412] vc1 (null)
2019-12-05 16:37:52.537241-0500 TableSelections[51189:30629412] vc2 <UIView: 0x7fcc73c34230; frame = (0 0; 0 0);
layer = <CALayer: 0x600000001140>>
2019-12-05 16:37:52.537535-0500 TableSelections[51189:30629412] vc4 <UIView: 0x7fcc760019e0; frame = (0 0; 0 0);
layer = <CALayer: 0x6000000244a0>>
2019-12-05 16:37:52.537734-0500 TableSelections[51189:30629412] vc5 (null)
*/

关于ios - 在 iOS 的 ViewController 中声明 View 时,为什么在 Swift 中使用 "weak"关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59201536/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com