属性'self.myDelegate'未在super.init初始化 - 委托

时间:2016-04-14 23:41:11

标签: swift delegates protocols initializer

我正在试验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

3 个答案:

答案 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!