-2

我得到了 iOS14 用户的崩溃日志。我可以对此做些什么,还是应该等到 iOS14 正式发布?

这是带有 textField 的 myCustomTableViewCell:

class TextTVCell: UITableViewCell, UITextFieldDelegate {
weak var delegate: TextTVCellDelegate?

weak var textField: UITextField? = {         // I have to make it optional because of weak reference
    let textField = UITextField()
    textField.translatesAutoresizingMaskIntoConstraints = false
    return textField
}()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setupSubviews()
}
required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

private func setupSubviews() {
    contentView.addSubview(textField!)
    ......... // constraints, ...
} 

强制解包会导致任何带有 iOS14 的设备崩溃。下面它工作得很好。

这是我的崩溃日志:

Incident Identifier: AB559313-AD92-4B3A-AA90-97AE47315DEF
Hardware Model:      iPhone9,4
Process:             FormaleBriefe [6654]
Path:                /private/var/containers/Bundle/Application/798B5135-DEB8-451D-858F-AE9FA47F6C7B/FormaleBriefe.app/FormaleBriefe
Identifier:          frugalResolution.Briefe
Version:             5 (2.2.2)
AppStoreTools:       11E707
AppVariant:          1:iPhone9,4:13
Code Type:           ARM-64 (Native)
Role:                Foreground
Parent Process:      launchd [1]
Coalition:           frugalResolution.Briefe [1134]


Date/Time:           2020-08-02 22:52:50.5708 +0200
Launch Time:         2020-08-02 22:52:48.3752 +0200
OS Version:          iPhone OS 14.0 (18A5332f)
Release Type:        Beta
Baseband Version:    4.50.04
Report Version:      104

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000104fac2ac
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [6654]
Triggered by Thread:  0

Thread 0 name:
Thread 0 Crashed:
0   FormaleBriefe                   0x0000000104fac2ac TextTVCell.setupSubviews() + 3800 (TextTVCell.swift:41)
1   FormaleBriefe                   0x0000000104fab458 TextTVCell.setupSubviews() + 132 (TextTVCell.swift:0)
2   FormaleBriefe                   0x0000000104facb98 specialized TextTVCell.init(style:reuseIdentifier:) + 296 (TextTVCell.swift:32)
3   FormaleBriefe                   0x0000000104fab374 @objc TextTVCell.init(style:reuseIdentifier:) + 72 (<compiler-generated>:0)
4   UIKitCore                       0x000000019b63f448 -[UITableView _dequeueReusableViewOfType:withIdentifier:] + 532 (UITableView.m:8843)
5   FormaleBriefe                   0x0000000104f8ca34 LetterWriterVC.tableView(_:cellForRowAt:) + 1504 (LetterWriterVC.swift:555)
6   FormaleBriefe                   0x0000000104f8d6bc @objc
4

1 回答 1

2

您的代码始终是反模式(又名错误)。一个简单的测试将显示模式的问题。我将使用视图控制器:

weak var textField: UITextField? = { 
    let textField = UITextField()
    return textField
}()

override func viewDidLoad() {
    super.viewDidLoad()
    let tf = self.textField
    print(tf as Any) // nil
}

我们运行应用程序,控制台打印nil. 你可以很容易地看到原因。在某些时候,textField实例属性被初始化,因此闭包运行并返回一个文本字段并分配给textField. 但是那个参考是weak!这意味着:不要抓住我。所以实例属性保留文本字段;它删除它,文本字段不存在,并且引用被替换为nil.

简单的解决方案:不要那样做!正如我所说,这是一种反模式。删除单词weak,或者,如果您打算保持对文本字段的弱引用,请使用不同的模式,例如:

weak var textField: UITextField?
private func createTextField() -> UITextField  {
    let textField = UITextField()
    self.textField = textField
    return textField
}
override func viewDidLoad() {
    super.viewDidLoad()
    print(tf as Any) // text field
    print(self.textField as Any) // text field
    // and now put it into the interface immediately
    // or it will go out of existence _again!_
}

就我个人而言,我所做的并非如此。我这样做:

weak var textField: UITextField?
private func createTextField() -> UITextField  {
    let textField = UITextField()
    return textField
}
override func viewDidLoad() {
    super.viewDidLoad()
    let tf = self.createTextField()
    self.textField = tf
    // and now put it into the interface immediately or it will go out of existence
}

在现实生活中,该代码将在setup例程中。换句话说,我将setup创建视图并将它们分配给弱引用,同时将它们放入界面中,这是例程的工作。

当然,还有另一种可能性就是放弃weak,不做任何其他事情。做textField一个强有力的参考!对子视图进行强引用绝对没有错——当然,除非该子视图也对您有强引用,但这种情况不太可能发生,如果出现这种情况是可以避免的。

于 2020-08-04T12:04:20.333 回答