我正在尝试使用协议和委托,并且在初始化委托时卡住了。
在我班的第一名,我试着加上
protocol myDelegateProtocol {
func clickedCellIndexPath(indexPath: Int)
}
class MyClass {
var myDelegate : myDelegateProtocol
override init() {
super.init()
self.setup() // error 1
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) // error 2
}
}
它开始为两个init闭包提供错误
两个错误:
Property 'self.myDelegate' not initialized at super.init
我错过了什么或做错了什么?
如果我试图声明它为
var myDelegate: myDelegateProtocol?
,它不会给出那个错误,但它会迫使我强制展开myDelegate!
,此时它返回nil。编辑:如果我强迫它在顶部展开,那么我将在以下部分收到错误。。
...
var myDelegate : myDelegateProtocol!
func handleTap(sender: UITapGestureRecognizer? = nil) {
if let point = sender?.locationInView(collectionView) {
print("Y")
let clickedCell = collectionView!.indexPathForItemAtPoint(point)!.row
print(clickedCell) // prints
self.myDelegate.clickedCellIndexPath(clickedCell) // error here
}
}
编辑2:
所以我的完整代码
protocol myDelegateProtocol {
func clickedCellIndexPath(indexPath: Int)
}
class MyClass {
var myDelegate: KDRearrangableClickedCellDelegate!
override init() {
super.init()
self.setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func setup() {
if let collectionView = self.collectionView {
let tap = UITapGestureRecognizer(target: self, action: #selector(KDRearrangeableCollectionViewFlowLayout.handleTap(_:)))
tap.delegate = self
collectionView.addGestureRecognizer(tap)
}
}
func handleTap(sender: UITapGestureRecognizer? = nil) {
if let point = sender?.locationInView(collectionView) {
let clickedCell = collectionView!.indexPathForItemAtPoint(point)!.row
print(clickedCell)
self.myDelegate.clickedCellIndexPath(clickedCell)
}
}
此时我收到这个错误:
致命错误:在展开可选值时意外找到nil
最佳答案
正如其他人指出的,因为myDelegate
没有在init
中初始化,所以必须使其成为可选的。例如:
var myDelegate: KDRearrangableClickedCellDelegate?
然后,当您需要使用它时,打开这个可选的,例如:
func handleTap(sender: UITapGestureRecognizer) {
if let point = sender.locationInView(collectionView) {
if let clickedCell = collectionView?.indexPathForItemAtPoint(point)?.item {
print(clickedCell)
myDelegate?.clickedCellIndexPath(clickedCell)
}
}
}
我个人建议使用可选(
KDRearrangableClickedCellDelegate?
)而不是隐式展开(KDRearrangableClickedCellDelegate!
),这样,如果您还没有设置myDelegate
,您的应用程序就不会崩溃。显然,如果要调用clickedCellIndexPath
,必须实际设置myDelegate
。我还对clickedCell
进行了可选绑定,这样如果点击不在单元格上,它就不会崩溃。另外,我使用的是item
而不是row
,因为集合视图通常不使用item
/section
而不是row
/section
。您不向我们展示如何设置
collectionView
或如何设置myDelegate
,但要使上述操作正常工作,您需要同时设置这两个选项,才能正确处理手势。作为旁白,我不知道
MyClass
和它的myDelegate
之间的关系是什么,但是您经常使用委托weak
来避免强引用循环。为此,请将协议定义为类协议:protocol myDelegateProtocol : class {
func clickedCellIndexPath(indexPath: Int)
}
然后将您的
myDelegate
定义为weak
:weak var myDelegate: KDRearrangableClickedCellDelegate?
您只需要这样做,如果
myDelegate
的MyClass
对象本身将保持对MyClass
的强引用。如果不是,你可能不需要让你的代表软弱。这取决于你的对象模型,你还没有和我们分享。