我剛剛更新到 Xcode 13.3,我看到了幾個新警告的實體,這是我在以前版本的 Xcode 中沒有看到的。例如,我有一個名為 LabelAndSwitchTableViewCell 的簡單表格視圖單元格,如下所示:
import UIKit
class LabelAndSwitchTableViewCell: UITableViewCell {
private let label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let _switch: UISwitch = {
let _switch = UISwitch()
_switch.translatesAutoresizingMaskIntoConstraints = false
_switch.addTarget(self, action: #selector(didToggleSwitch), for: .valueChanged)
return _switch
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(label)
contentView.addSubview(_switch)
// layout constraints removed for brevity
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func didToggleSwitch() {
print("Switch was toggled...")
}
}
如您所見,我正在向開關中添加一個目標,當開關的值發生變化時要呼叫它:
_switch.addTarget(self, action: #selector(didToggleSwitch), for: .valueChanged)
更新到 Xcode 13.3 后,我現在在這一行看到一個新警告:
'self' refers to the method 'LabelAndSwitchTableViewCell.self', which may be unexpected
Xcode 建議消除此警告是為了替換:
_switch.addTarget(self, action: #selector(didToggleSwitch), for: .valueChanged)
...和...
_switch.addTarget(LabelAndSwitchTableViewCell.self, action: #selector(didToggleSwitch), for: .valueChanged)
進行此更改確實會使警告靜音,但也會在我切換開關時導致應用程式崩潰(無法識別的選擇器)。這是那次崩潰的轉儲:
[app_mockup.LabelAndSwitchTableViewCell didToggleSwitch]: unrecognized selector sent to class 0x1043d86e8
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ' [app_mockup.LabelAndSwitchTableViewCell didToggleSwitch]: unrecognized selector sent to class 0x1043d86e8'
制作該didToggleSwitch()方法static將防止崩潰,但我不確定為什么要這樣做。我顯然可以恢復更改(從LabelAndSwitchTableViewCell.selfback 到 just self),但我想知道我是否應該采取其他措施來解決這個問題?
uj5u.com熱心網友回復:
您可以通過將 let 更改為惰性 var 來修復
private lazy var _switch2: UISwitch = {
let _switch = UISwitch()
_switch.translatesAutoresizingMaskIntoConstraints = false
_switch.addTarget(self, action: #selector(didToggleSwitch), for: .valueChanged)
return _switch
}()
Xcode 修復它的建議是錯誤的。
uj5u.com熱心網友回復:
原因是self在物件初始化的第一階段還沒有準備好。階段 1 是設定所有存盤的屬性,只有在階段 2 才能訪問self.
要修復您的代碼,您可以使用lazy屬性,初始化階段 1 已完成。
這是參考:

對于此警告:
- 如果沒有超類,或者沒有超類,
NSObject直接self在存盤屬性中使用是錯誤的。 - 如果超類是
NSObject,則self編譯為自動閉包(ClassXXX) -> () -> ClassXXX。所以在運行時,self 將被用作當前實體。但是,由于 Swift 5.6 警告我們,我認為在未來的 Swift 版本中可能不允許在 NSObject 子類的存盤屬性中參考 self 。
示例1:沒有超類時出錯

示例 2:AST 中編譯后的 self
對于此代碼:
import Foundation
class MyTest: NSObject {
var myself = self
}
這是編譯的 AST 的一部分:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/446759.html
