我正在尝试使用协议和委托,并且在初始化委托时卡住了。
在我班的第一名,我试着加上

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?

您只需要这样做,如果myDelegateMyClass对象本身将保持对MyClass的强引用。如果不是,你可能不需要让你的代表软弱。这取决于你的对象模型,你还没有和我们分享。

09-11 18:56