我正在试验Protocols和Delegates,我在初始化委托时遇到困难。
在我班上的最顶层,我尝试添加
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
答案 0 :(得分:1)
正如其他人所指出的那样,因为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
,但为了使上述工作正常,您需要在正确处理手势之前设置这两者。< / p>
顺便说一句,我不知道MyClass
与其myDelegate
之间的关系是什么,但通常会让代表weak
避免强引用周期。为此,请将协议定义为类协议:
protocol myDelegateProtocol : class {
func clickedCellIndexPath(indexPath: Int)
}
然后将您的myDelegate
定义为weak
:
weak var myDelegate: KDRearrangableClickedCellDelegate?
如果myDelegate
的{{1}}对象本身会保留对MyClass
的强引用,则只需执行此操作即可。如果没有,您可能不需要让您的代表弱。它只取决于你没有与我们分享的对象模型。
答案 1 :(得分:0)
您已将myDelegate
声明为非可选,这意味着必须在调用init()
之前在super.init()
方法中对其进行初始化。如果您使用setup()
方法为myDelegate
分配值(我猜是这样的,尽管您还没有包含setup()
在此处实施),然后您需要在 setup()
之前调用super.init()
,和/或将myDelegate
声明为可选(使用&# 39;&#39;。)
答案 2 :(得分:0)
这是造成问题的原因:
var myDelegate : myDelegateProtocol
myDelegate被声明为非可选,但您没有初始化 它在你的init函数中。如果您在设置中初始化它() 函数,你需要将myDelegate的声明更改为这样。
var myDelegate : myDelegateProtocol!