3

I have multiple view controllers which shows same kind of cells. I want to set delegate in a protocol extension like this:

class ProductsViewController: UIViewController, ProductShowcase {
    //other properties
    @IBOutlet weak var productCollectionView: UICollectionView!
    var dataSource: DataSource!

    override func viewDidLoad() {
        super.viewDidLoad()

        setupDataSource()

        setupCollectionView()
    }

    func didSelectProduct(product: Product) {
        print(product)
    }

    //other functions
}

protocol ProductShowcase: UICollectionViewDelegate {
    var dataSource: DataSource! { get set }
    var productCollectionView: UICollectionView! { get }

    func didSelectProduct(product: Product)
}

extension ProductShowcase {
    func setupCollectionView() {
        productCollectionView.registerClass(ProductCollectionViewCell.self, forCellWithReuseIdentifier: "productCell")
        productCollectionView.dataSource = dataSource
        print(self) //prints ProductsViewController
        productCollectionView.delegate = self // 
        print(productCollectionView.delegate) //prints optional ProductsViewController
    }
}

extension ProductShowcase {
    //this delegate method is not called
    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
        didSelectProduct(dataSource.dataObjects[indexPath.row])
    }
}

When didSelectItemAtIndexPath is implemented in ProductsViewController it gets called. Is there something I missed or is this a wrong approach?

osrl
  • 8,168
  • 8
  • 36
  • 57
  • I believe you are running into the current Objective-C interoperability limitation described here: http://stackoverflow.com/questions/39487168/non-objc-method-does-not-satisfy-optional-requirement-of-objc-protocol/39604189#39604189 – Matthew Seaman Nov 03 '16 at 16:23

1 Answers1

3

It is a Objective-C interoperability limitation. You are not allowed to implement protocols with optionals function in protocol extension like you wanted (protocols which are from Objective-C type UIKit control's delegates and datasources, etc.). You can have default implementation of only protocol that are written like:

// No, @objc in the front of protocol. (i.e. objc-type protocol)
protocol X {
}
Bibek
  • 3,689
  • 3
  • 19
  • 28
  • Putting the implementation in `protocol ProductShowcase: UICollectionViewDelegate` will solve the problem? Where can I read about this Objective-C interoperability limitation? Also, note that in swift 3 I get Segmentation Fault 11 on that line – osrl Nov 05 '16 at 08:23
  • It won't solve your problem. Only the way to solve your problem is subclassing. Some limitations in here: https://www.lynda.com/Swift-tutorials/Limitations-language-interoperability/185037/367698-4.html?certificate=CE455E2C8E994AB398FA5E8CA22AC26B – Bibek Nov 05 '16 at 14:55