1

In several views I have an extension that implements the protocol UICollectionViewDelegateFlowLayout like this:

extension MyView: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: CGFloat((collectionView.frame.size.width / 2) - 5), height: CGFloat(165))
     }
      
     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
         return 10
     }
      
     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
         return 10
     }
}

It works fine, but the thing is I have several views with this same exact code, except that the extension is on each respective view. I thought maybe there is a way to reduce the amount of code using a protocol extension that gives all access to these functions. I tried something like this:

protocol A where Self: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
      
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
      
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
}

extension A {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: CGFloat((collectionView.frame.size.width / 2) - 5), height: CGFloat(165))
     }
      
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 10
    }
      
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 10
    }
}

But this doesn't take, and I suspect it has something to do with the functions being delegate functions that I don't call on my own.

Anyway, is there a nice way to deal with this?

Joakim Sjöstedt
  • 824
  • 2
  • 9
  • 18
  • What does "this doesn't take" mean? By the way, you don't need to define the 3 functions *within* the `protocol` -- they can just be implemented in the extension, since they are optional delegate methods. – jnpdx Oct 07 '22 at 23:00
  • 1
    Try subclassing UICollectionView and overriding them there. – Leo Dabus Oct 07 '22 at 23:10
  • 1
    @jnpdx I mean that the delegate functions aren't triggered. When I implement the protocol I get an error saying `Non-'@objc' method 'collectionView(_:layout:minimumInteritemSpacingForSectionAt:)' does not satisfy optional requirement of '@objc' protocol 'UICollectionViewDelegateFlowLayout'` If I try adding the annotation I get an error... – Joakim Sjöstedt Oct 09 '22 at 08:17
  • @LeoDabus Hmm, gave it a try but didn't get it right. Could you elaborate? – Joakim Sjöstedt Oct 09 '22 at 08:25
  • Does this answer your question? [Non-'@objc' method does not satisfy optional requirement of '@objc' protocol](https://stackoverflow.com/questions/39487168/non-objc-method-does-not-satisfy-optional-requirement-of-objc-protocol) – AnderCover Apr 02 '23 at 02:33

0 Answers0