reimplementation of a function added in a protocol extension isn’t called












3















I added a protocol extension for a protocol with an associated type called PickerType. I wrote a reimplementation of a function, refresh(:,completion:) that’s defined in the protocol and implemented in a different protocol extension.



But the function inside my new extension isn’t called when I call refresh(:,completion:) unless the compiler knows what type PickerType is. I wrote the following:



extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
func refresh(_ sender: Any, completion: (() -> Void)?) {
print("we're trying to have this implementation called")
PickerType.startSync()
}
}


It gets called as I would expect if I call refresh(:,completion:) on a PickerSectionProvider<ObservationType> (see the code from my Playground below) but not when I call refresh(:,completion:) on an ItemProvider, which is a generic type that must conform to PickerItemProvider (again see my code below).



// We are trying to get our pickers to sync their provided type when you pull to refresh. But the implementation of refresh(:, completion:) that we added doesn’t get called.

import Foundation

protocol PickerItemProvider: class {
associatedtype PickerType
func findItem(by identifier: NSNumber) -> PickerType?
func itemAt(_ indexPath: IndexPath) -> PickerType?
func refresh(_ sender: Any, completion: (() -> Void)?)
}

extension PickerItemProvider {
func findItem(by identifier: NSNumber) -> PickerType? {
return nil
}

public func refresh(_ sender: Any, completion: (() -> Void)?) {
print("the default refresh implementation")
}
}

public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
return nil
}
}

extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
func refresh(_ sender: Any, completion: (() -> Void)?) {
print("we’re trying to have this implementation called instead of the above implementation of refresh")
PickerType.startSync()
}
}

protocol SyncableEntity {
static func startSync()
}

extension SyncableEntity {
static func startSync() {

}
}

class ObservationType: Equatable, SyncableEntity {

}

func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
return false
}

class GenericPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
var itemProvider: ItemProvider?

init() {

}

func foo() {
// Why doesn’t the implementation of refresh(:,completion:) we added get called here?
itemProvider?.refresh("dummy sender") {

}
}
}

class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
var pickerController = GenericPickerViewController<T, ItemProvider>()
}

let pickerSectionProvider = PickerSectionProvider<ObservationType>()

let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

row.pickerController.itemProvider = pickerSectionProvider

row.pickerController.foo()









share|improve this question



























    3















    I added a protocol extension for a protocol with an associated type called PickerType. I wrote a reimplementation of a function, refresh(:,completion:) that’s defined in the protocol and implemented in a different protocol extension.



    But the function inside my new extension isn’t called when I call refresh(:,completion:) unless the compiler knows what type PickerType is. I wrote the following:



    extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
    func refresh(_ sender: Any, completion: (() -> Void)?) {
    print("we're trying to have this implementation called")
    PickerType.startSync()
    }
    }


    It gets called as I would expect if I call refresh(:,completion:) on a PickerSectionProvider<ObservationType> (see the code from my Playground below) but not when I call refresh(:,completion:) on an ItemProvider, which is a generic type that must conform to PickerItemProvider (again see my code below).



    // We are trying to get our pickers to sync their provided type when you pull to refresh. But the implementation of refresh(:, completion:) that we added doesn’t get called.

    import Foundation

    protocol PickerItemProvider: class {
    associatedtype PickerType
    func findItem(by identifier: NSNumber) -> PickerType?
    func itemAt(_ indexPath: IndexPath) -> PickerType?
    func refresh(_ sender: Any, completion: (() -> Void)?)
    }

    extension PickerItemProvider {
    func findItem(by identifier: NSNumber) -> PickerType? {
    return nil
    }

    public func refresh(_ sender: Any, completion: (() -> Void)?) {
    print("the default refresh implementation")
    }
    }

    public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
    func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
    return nil
    }
    }

    extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
    func refresh(_ sender: Any, completion: (() -> Void)?) {
    print("we’re trying to have this implementation called instead of the above implementation of refresh")
    PickerType.startSync()
    }
    }

    protocol SyncableEntity {
    static func startSync()
    }

    extension SyncableEntity {
    static func startSync() {

    }
    }

    class ObservationType: Equatable, SyncableEntity {

    }

    func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
    return false
    }

    class GenericPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
    var itemProvider: ItemProvider?

    init() {

    }

    func foo() {
    // Why doesn’t the implementation of refresh(:,completion:) we added get called here?
    itemProvider?.refresh("dummy sender") {

    }
    }
    }

    class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
    var pickerController = GenericPickerViewController<T, ItemProvider>()
    }

    let pickerSectionProvider = PickerSectionProvider<ObservationType>()

    let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

    row.pickerController.itemProvider = pickerSectionProvider

    row.pickerController.foo()









    share|improve this question

























      3












      3








      3








      I added a protocol extension for a protocol with an associated type called PickerType. I wrote a reimplementation of a function, refresh(:,completion:) that’s defined in the protocol and implemented in a different protocol extension.



      But the function inside my new extension isn’t called when I call refresh(:,completion:) unless the compiler knows what type PickerType is. I wrote the following:



      extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
      func refresh(_ sender: Any, completion: (() -> Void)?) {
      print("we're trying to have this implementation called")
      PickerType.startSync()
      }
      }


      It gets called as I would expect if I call refresh(:,completion:) on a PickerSectionProvider<ObservationType> (see the code from my Playground below) but not when I call refresh(:,completion:) on an ItemProvider, which is a generic type that must conform to PickerItemProvider (again see my code below).



      // We are trying to get our pickers to sync their provided type when you pull to refresh. But the implementation of refresh(:, completion:) that we added doesn’t get called.

      import Foundation

      protocol PickerItemProvider: class {
      associatedtype PickerType
      func findItem(by identifier: NSNumber) -> PickerType?
      func itemAt(_ indexPath: IndexPath) -> PickerType?
      func refresh(_ sender: Any, completion: (() -> Void)?)
      }

      extension PickerItemProvider {
      func findItem(by identifier: NSNumber) -> PickerType? {
      return nil
      }

      public func refresh(_ sender: Any, completion: (() -> Void)?) {
      print("the default refresh implementation")
      }
      }

      public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
      func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
      return nil
      }
      }

      extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
      func refresh(_ sender: Any, completion: (() -> Void)?) {
      print("we’re trying to have this implementation called instead of the above implementation of refresh")
      PickerType.startSync()
      }
      }

      protocol SyncableEntity {
      static func startSync()
      }

      extension SyncableEntity {
      static func startSync() {

      }
      }

      class ObservationType: Equatable, SyncableEntity {

      }

      func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
      return false
      }

      class GenericPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
      var itemProvider: ItemProvider?

      init() {

      }

      func foo() {
      // Why doesn’t the implementation of refresh(:,completion:) we added get called here?
      itemProvider?.refresh("dummy sender") {

      }
      }
      }

      class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
      var pickerController = GenericPickerViewController<T, ItemProvider>()
      }

      let pickerSectionProvider = PickerSectionProvider<ObservationType>()

      let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

      row.pickerController.itemProvider = pickerSectionProvider

      row.pickerController.foo()









      share|improve this question














      I added a protocol extension for a protocol with an associated type called PickerType. I wrote a reimplementation of a function, refresh(:,completion:) that’s defined in the protocol and implemented in a different protocol extension.



      But the function inside my new extension isn’t called when I call refresh(:,completion:) unless the compiler knows what type PickerType is. I wrote the following:



      extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
      func refresh(_ sender: Any, completion: (() -> Void)?) {
      print("we're trying to have this implementation called")
      PickerType.startSync()
      }
      }


      It gets called as I would expect if I call refresh(:,completion:) on a PickerSectionProvider<ObservationType> (see the code from my Playground below) but not when I call refresh(:,completion:) on an ItemProvider, which is a generic type that must conform to PickerItemProvider (again see my code below).



      // We are trying to get our pickers to sync their provided type when you pull to refresh. But the implementation of refresh(:, completion:) that we added doesn’t get called.

      import Foundation

      protocol PickerItemProvider: class {
      associatedtype PickerType
      func findItem(by identifier: NSNumber) -> PickerType?
      func itemAt(_ indexPath: IndexPath) -> PickerType?
      func refresh(_ sender: Any, completion: (() -> Void)?)
      }

      extension PickerItemProvider {
      func findItem(by identifier: NSNumber) -> PickerType? {
      return nil
      }

      public func refresh(_ sender: Any, completion: (() -> Void)?) {
      print("the default refresh implementation")
      }
      }

      public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
      func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
      return nil
      }
      }

      extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
      func refresh(_ sender: Any, completion: (() -> Void)?) {
      print("we’re trying to have this implementation called instead of the above implementation of refresh")
      PickerType.startSync()
      }
      }

      protocol SyncableEntity {
      static func startSync()
      }

      extension SyncableEntity {
      static func startSync() {

      }
      }

      class ObservationType: Equatable, SyncableEntity {

      }

      func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
      return false
      }

      class GenericPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
      var itemProvider: ItemProvider?

      init() {

      }

      func foo() {
      // Why doesn’t the implementation of refresh(:,completion:) we added get called here?
      itemProvider?.refresh("dummy sender") {

      }
      }
      }

      class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
      var pickerController = GenericPickerViewController<T, ItemProvider>()
      }

      let pickerSectionProvider = PickerSectionProvider<ObservationType>()

      let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

      row.pickerController.itemProvider = pickerSectionProvider

      row.pickerController.foo()






      swift






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 15 '18 at 22:28









      Justin GarciaJustin Garcia

      1137




      1137
























          2 Answers
          2






          active

          oldest

          votes


















          2














          See the corrected implementation below,



          import Foundation

          protocol PickerItemProvider: class {
          associatedtype PickerType
          func findItem(by identifier: NSNumber) -> PickerType?
          func itemAt(_ indexPath: IndexPath) -> PickerType?
          }

          extension PickerItemProvider {
          func findItem(by identifier: NSNumber) -> PickerType? {
          return nil
          }

          func refresh(_ sender: Any, completion: (() -> Void)?) {
          print("the default refresh implementation")
          }
          }

          public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
          func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
          return nil
          }
          }

          extension PickerItemProvider where PickerType: Equatable & SyncableEntity {

          func refresh(_ sender: Any, completion: (() -> Void)?) {
          print("we’re trying to have this implementation called instead of the above implementation of refresh")
          PickerType.startSync()
          }
          }

          protocol SyncableEntity {
          static func startSync()
          }

          extension SyncableEntity {
          static func startSync() {

          }
          }

          class ObservationType: Equatable, SyncableEntity {

          }

          func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
          return false
          }

          class GenericPickerViewController<PickerType: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
          var itemProvider: ItemProvider?

          init() {

          }

          func foo() {
          // Why doesn’t the implementation of refresh(:,completion:) we added get called here?
          itemProvider?.refresh("dummy sender") {

          }
          }
          }

          class PopupPickerRow<T: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
          var pickerController = GenericPickerViewController<T, ItemProvider>()
          }

          let pickerSectionProvider = PickerSectionProvider<ObservationType>()

          let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

          row.pickerController.itemProvider = pickerSectionProvider

          row.pickerController.foo()


          First of all, when you want to override a method implementation declared as a requirement in the protocol and provided some default implementation in the protocol extension it will always call the method implemented in the extension discarding the where clause requirements. You can see similar issues in this question and this.



          So to make the protocol look for the method fulfilling the constraints in where clause you need to remove the method signature from the protocol and keep it only inside the extension as i did above.



          Secondly you were missed the PickerType requirement to be Equatable & SyncableEntity while defining GenericPickerViewController and PopupPickerRow so i updated that also.






          share|improve this answer


























          • Thank you for your response, but we are trying to let PopupPickerRow and GenericPickerViewController work with anything as long as it’s Equatable, not restrict ourselves to Equatable & SyncableEntity. If I remove that change you made the problem persists.

            – Justin Garcia
            Nov 15 '18 at 23:29








          • 1





            Yes, but then your protocol requirement to call that method implementation will break and it will call the default method without considering any constraints. I hope you got the idea what was wrong with your implementation so its up to you how you want to handle it.

            – Kamran
            Nov 15 '18 at 23:35











          • I think I’m starting to understand. so at compile time the default implementation of refresh(:,completion:) is chosen because all that is known about itemProvider is that it’s of a type that conforms to PickerItemProvider where PickerType is Equatable?

            – Justin Garcia
            Nov 15 '18 at 23:44











          • so I added an extension on GenericPickerViewController where PickerType conforms to Equatable and SyncableEntity that adds a different implementation of foo(). calls to refresh(:,completion:) on itemProvider in that extension result in calls to the refresh(:,completion:) implementation I added.

            – Justin Garcia
            Nov 15 '18 at 23:51













          • Well that works in the Playground but not in my project. I guess that’s because when the real foo() is compiled the compiler doesn’t know what type PickerType is going to be, so it chooses the default one not the one in the extension I added.

            – Justin Garcia
            Nov 16 '18 at 0:20





















          2














          I added two functions on GenericPickerViewController, one for setting it up with a PickerItemProvider whose PickerType simply conforms to Equatable, and another to set it up with a PickerItemProvider whose PickerType conforms to SyncableEntity. This way the compiler knows which refresh(:,completion:) to call. Here is the Playground code:



          import Foundation
          import CoreData

          protocol PickerItemProvider: class {
          associatedtype PickerType
          func itemAt(_ indexPath: IndexPath) -> PickerType?
          }

          extension PickerItemProvider {
          public func refresh(_ sender: Any, completion: (() -> Void)?) {
          print("the default refresh implementation")
          }
          }

          public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
          func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
          return nil
          }
          }

          extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
          func refresh(_ sender: Any, completion: (() -> Void)?) {
          print("we’re trying to have this implementation called instead of the above implementation of refresh")
          PickerType.startSync()
          completion?()
          }
          }

          protocol SyncableEntity {
          associatedtype EntityType
          static func startSync()
          }

          extension SyncableEntity {
          static func startSync() {
          print("starting sync")
          }
          }

          class ObservationType: Equatable, SyncableEntity {
          typealias EntityType = NSManagedObject
          }

          func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
          return false
          }

          class GeneralPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
          private var itemProvider: ItemProvider?

          private var refresher: ((Any, (() -> ())?) -> ())?

          func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType {
          refresher = { sender, completion in
          itemProvider.refresh(self, completion: {
          completion?()
          })
          }
          self.itemProvider = (itemProvider as! ItemProvider)
          }

          func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType, PickerType: SyncableEntity {
          refresher = { sender, completion in
          itemProvider.refresh(self, completion: {
          completion?()
          })
          }
          self.itemProvider = (itemProvider as! ItemProvider)
          }

          func foo() {
          refresher?(self, {
          print("finished")
          })
          }
          }

          class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
          var pickerController = GeneralPickerViewController<T, ItemProvider>()
          }

          let pickerSectionProvider = PickerSectionProvider<ObservationType>()

          let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

          row.pickerController.setup(with: pickerSectionProvider)

          row.pickerController.foo()





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53328770%2freimplementation-of-a-function-added-in-a-protocol-extension-isn-t-called%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2














            See the corrected implementation below,



            import Foundation

            protocol PickerItemProvider: class {
            associatedtype PickerType
            func findItem(by identifier: NSNumber) -> PickerType?
            func itemAt(_ indexPath: IndexPath) -> PickerType?
            }

            extension PickerItemProvider {
            func findItem(by identifier: NSNumber) -> PickerType? {
            return nil
            }

            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("the default refresh implementation")
            }
            }

            public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
            func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
            return nil
            }
            }

            extension PickerItemProvider where PickerType: Equatable & SyncableEntity {

            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("we’re trying to have this implementation called instead of the above implementation of refresh")
            PickerType.startSync()
            }
            }

            protocol SyncableEntity {
            static func startSync()
            }

            extension SyncableEntity {
            static func startSync() {

            }
            }

            class ObservationType: Equatable, SyncableEntity {

            }

            func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
            return false
            }

            class GenericPickerViewController<PickerType: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
            var itemProvider: ItemProvider?

            init() {

            }

            func foo() {
            // Why doesn’t the implementation of refresh(:,completion:) we added get called here?
            itemProvider?.refresh("dummy sender") {

            }
            }
            }

            class PopupPickerRow<T: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
            var pickerController = GenericPickerViewController<T, ItemProvider>()
            }

            let pickerSectionProvider = PickerSectionProvider<ObservationType>()

            let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

            row.pickerController.itemProvider = pickerSectionProvider

            row.pickerController.foo()


            First of all, when you want to override a method implementation declared as a requirement in the protocol and provided some default implementation in the protocol extension it will always call the method implemented in the extension discarding the where clause requirements. You can see similar issues in this question and this.



            So to make the protocol look for the method fulfilling the constraints in where clause you need to remove the method signature from the protocol and keep it only inside the extension as i did above.



            Secondly you were missed the PickerType requirement to be Equatable & SyncableEntity while defining GenericPickerViewController and PopupPickerRow so i updated that also.






            share|improve this answer


























            • Thank you for your response, but we are trying to let PopupPickerRow and GenericPickerViewController work with anything as long as it’s Equatable, not restrict ourselves to Equatable & SyncableEntity. If I remove that change you made the problem persists.

              – Justin Garcia
              Nov 15 '18 at 23:29








            • 1





              Yes, but then your protocol requirement to call that method implementation will break and it will call the default method without considering any constraints. I hope you got the idea what was wrong with your implementation so its up to you how you want to handle it.

              – Kamran
              Nov 15 '18 at 23:35











            • I think I’m starting to understand. so at compile time the default implementation of refresh(:,completion:) is chosen because all that is known about itemProvider is that it’s of a type that conforms to PickerItemProvider where PickerType is Equatable?

              – Justin Garcia
              Nov 15 '18 at 23:44











            • so I added an extension on GenericPickerViewController where PickerType conforms to Equatable and SyncableEntity that adds a different implementation of foo(). calls to refresh(:,completion:) on itemProvider in that extension result in calls to the refresh(:,completion:) implementation I added.

              – Justin Garcia
              Nov 15 '18 at 23:51













            • Well that works in the Playground but not in my project. I guess that’s because when the real foo() is compiled the compiler doesn’t know what type PickerType is going to be, so it chooses the default one not the one in the extension I added.

              – Justin Garcia
              Nov 16 '18 at 0:20


















            2














            See the corrected implementation below,



            import Foundation

            protocol PickerItemProvider: class {
            associatedtype PickerType
            func findItem(by identifier: NSNumber) -> PickerType?
            func itemAt(_ indexPath: IndexPath) -> PickerType?
            }

            extension PickerItemProvider {
            func findItem(by identifier: NSNumber) -> PickerType? {
            return nil
            }

            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("the default refresh implementation")
            }
            }

            public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
            func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
            return nil
            }
            }

            extension PickerItemProvider where PickerType: Equatable & SyncableEntity {

            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("we’re trying to have this implementation called instead of the above implementation of refresh")
            PickerType.startSync()
            }
            }

            protocol SyncableEntity {
            static func startSync()
            }

            extension SyncableEntity {
            static func startSync() {

            }
            }

            class ObservationType: Equatable, SyncableEntity {

            }

            func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
            return false
            }

            class GenericPickerViewController<PickerType: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
            var itemProvider: ItemProvider?

            init() {

            }

            func foo() {
            // Why doesn’t the implementation of refresh(:,completion:) we added get called here?
            itemProvider?.refresh("dummy sender") {

            }
            }
            }

            class PopupPickerRow<T: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
            var pickerController = GenericPickerViewController<T, ItemProvider>()
            }

            let pickerSectionProvider = PickerSectionProvider<ObservationType>()

            let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

            row.pickerController.itemProvider = pickerSectionProvider

            row.pickerController.foo()


            First of all, when you want to override a method implementation declared as a requirement in the protocol and provided some default implementation in the protocol extension it will always call the method implemented in the extension discarding the where clause requirements. You can see similar issues in this question and this.



            So to make the protocol look for the method fulfilling the constraints in where clause you need to remove the method signature from the protocol and keep it only inside the extension as i did above.



            Secondly you were missed the PickerType requirement to be Equatable & SyncableEntity while defining GenericPickerViewController and PopupPickerRow so i updated that also.






            share|improve this answer


























            • Thank you for your response, but we are trying to let PopupPickerRow and GenericPickerViewController work with anything as long as it’s Equatable, not restrict ourselves to Equatable & SyncableEntity. If I remove that change you made the problem persists.

              – Justin Garcia
              Nov 15 '18 at 23:29








            • 1





              Yes, but then your protocol requirement to call that method implementation will break and it will call the default method without considering any constraints. I hope you got the idea what was wrong with your implementation so its up to you how you want to handle it.

              – Kamran
              Nov 15 '18 at 23:35











            • I think I’m starting to understand. so at compile time the default implementation of refresh(:,completion:) is chosen because all that is known about itemProvider is that it’s of a type that conforms to PickerItemProvider where PickerType is Equatable?

              – Justin Garcia
              Nov 15 '18 at 23:44











            • so I added an extension on GenericPickerViewController where PickerType conforms to Equatable and SyncableEntity that adds a different implementation of foo(). calls to refresh(:,completion:) on itemProvider in that extension result in calls to the refresh(:,completion:) implementation I added.

              – Justin Garcia
              Nov 15 '18 at 23:51













            • Well that works in the Playground but not in my project. I guess that’s because when the real foo() is compiled the compiler doesn’t know what type PickerType is going to be, so it chooses the default one not the one in the extension I added.

              – Justin Garcia
              Nov 16 '18 at 0:20
















            2












            2








            2







            See the corrected implementation below,



            import Foundation

            protocol PickerItemProvider: class {
            associatedtype PickerType
            func findItem(by identifier: NSNumber) -> PickerType?
            func itemAt(_ indexPath: IndexPath) -> PickerType?
            }

            extension PickerItemProvider {
            func findItem(by identifier: NSNumber) -> PickerType? {
            return nil
            }

            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("the default refresh implementation")
            }
            }

            public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
            func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
            return nil
            }
            }

            extension PickerItemProvider where PickerType: Equatable & SyncableEntity {

            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("we’re trying to have this implementation called instead of the above implementation of refresh")
            PickerType.startSync()
            }
            }

            protocol SyncableEntity {
            static func startSync()
            }

            extension SyncableEntity {
            static func startSync() {

            }
            }

            class ObservationType: Equatable, SyncableEntity {

            }

            func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
            return false
            }

            class GenericPickerViewController<PickerType: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
            var itemProvider: ItemProvider?

            init() {

            }

            func foo() {
            // Why doesn’t the implementation of refresh(:,completion:) we added get called here?
            itemProvider?.refresh("dummy sender") {

            }
            }
            }

            class PopupPickerRow<T: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
            var pickerController = GenericPickerViewController<T, ItemProvider>()
            }

            let pickerSectionProvider = PickerSectionProvider<ObservationType>()

            let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

            row.pickerController.itemProvider = pickerSectionProvider

            row.pickerController.foo()


            First of all, when you want to override a method implementation declared as a requirement in the protocol and provided some default implementation in the protocol extension it will always call the method implemented in the extension discarding the where clause requirements. You can see similar issues in this question and this.



            So to make the protocol look for the method fulfilling the constraints in where clause you need to remove the method signature from the protocol and keep it only inside the extension as i did above.



            Secondly you were missed the PickerType requirement to be Equatable & SyncableEntity while defining GenericPickerViewController and PopupPickerRow so i updated that also.






            share|improve this answer















            See the corrected implementation below,



            import Foundation

            protocol PickerItemProvider: class {
            associatedtype PickerType
            func findItem(by identifier: NSNumber) -> PickerType?
            func itemAt(_ indexPath: IndexPath) -> PickerType?
            }

            extension PickerItemProvider {
            func findItem(by identifier: NSNumber) -> PickerType? {
            return nil
            }

            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("the default refresh implementation")
            }
            }

            public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
            func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
            return nil
            }
            }

            extension PickerItemProvider where PickerType: Equatable & SyncableEntity {

            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("we’re trying to have this implementation called instead of the above implementation of refresh")
            PickerType.startSync()
            }
            }

            protocol SyncableEntity {
            static func startSync()
            }

            extension SyncableEntity {
            static func startSync() {

            }
            }

            class ObservationType: Equatable, SyncableEntity {

            }

            func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
            return false
            }

            class GenericPickerViewController<PickerType: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
            var itemProvider: ItemProvider?

            init() {

            }

            func foo() {
            // Why doesn’t the implementation of refresh(:,completion:) we added get called here?
            itemProvider?.refresh("dummy sender") {

            }
            }
            }

            class PopupPickerRow<T: Equatable & SyncableEntity, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
            var pickerController = GenericPickerViewController<T, ItemProvider>()
            }

            let pickerSectionProvider = PickerSectionProvider<ObservationType>()

            let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

            row.pickerController.itemProvider = pickerSectionProvider

            row.pickerController.foo()


            First of all, when you want to override a method implementation declared as a requirement in the protocol and provided some default implementation in the protocol extension it will always call the method implemented in the extension discarding the where clause requirements. You can see similar issues in this question and this.



            So to make the protocol look for the method fulfilling the constraints in where clause you need to remove the method signature from the protocol and keep it only inside the extension as i did above.



            Secondly you were missed the PickerType requirement to be Equatable & SyncableEntity while defining GenericPickerViewController and PopupPickerRow so i updated that also.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 15 '18 at 23:13

























            answered Nov 15 '18 at 23:03









            KamranKamran

            6,55821028




            6,55821028













            • Thank you for your response, but we are trying to let PopupPickerRow and GenericPickerViewController work with anything as long as it’s Equatable, not restrict ourselves to Equatable & SyncableEntity. If I remove that change you made the problem persists.

              – Justin Garcia
              Nov 15 '18 at 23:29








            • 1





              Yes, but then your protocol requirement to call that method implementation will break and it will call the default method without considering any constraints. I hope you got the idea what was wrong with your implementation so its up to you how you want to handle it.

              – Kamran
              Nov 15 '18 at 23:35











            • I think I’m starting to understand. so at compile time the default implementation of refresh(:,completion:) is chosen because all that is known about itemProvider is that it’s of a type that conforms to PickerItemProvider where PickerType is Equatable?

              – Justin Garcia
              Nov 15 '18 at 23:44











            • so I added an extension on GenericPickerViewController where PickerType conforms to Equatable and SyncableEntity that adds a different implementation of foo(). calls to refresh(:,completion:) on itemProvider in that extension result in calls to the refresh(:,completion:) implementation I added.

              – Justin Garcia
              Nov 15 '18 at 23:51













            • Well that works in the Playground but not in my project. I guess that’s because when the real foo() is compiled the compiler doesn’t know what type PickerType is going to be, so it chooses the default one not the one in the extension I added.

              – Justin Garcia
              Nov 16 '18 at 0:20





















            • Thank you for your response, but we are trying to let PopupPickerRow and GenericPickerViewController work with anything as long as it’s Equatable, not restrict ourselves to Equatable & SyncableEntity. If I remove that change you made the problem persists.

              – Justin Garcia
              Nov 15 '18 at 23:29








            • 1





              Yes, but then your protocol requirement to call that method implementation will break and it will call the default method without considering any constraints. I hope you got the idea what was wrong with your implementation so its up to you how you want to handle it.

              – Kamran
              Nov 15 '18 at 23:35











            • I think I’m starting to understand. so at compile time the default implementation of refresh(:,completion:) is chosen because all that is known about itemProvider is that it’s of a type that conforms to PickerItemProvider where PickerType is Equatable?

              – Justin Garcia
              Nov 15 '18 at 23:44











            • so I added an extension on GenericPickerViewController where PickerType conforms to Equatable and SyncableEntity that adds a different implementation of foo(). calls to refresh(:,completion:) on itemProvider in that extension result in calls to the refresh(:,completion:) implementation I added.

              – Justin Garcia
              Nov 15 '18 at 23:51













            • Well that works in the Playground but not in my project. I guess that’s because when the real foo() is compiled the compiler doesn’t know what type PickerType is going to be, so it chooses the default one not the one in the extension I added.

              – Justin Garcia
              Nov 16 '18 at 0:20



















            Thank you for your response, but we are trying to let PopupPickerRow and GenericPickerViewController work with anything as long as it’s Equatable, not restrict ourselves to Equatable & SyncableEntity. If I remove that change you made the problem persists.

            – Justin Garcia
            Nov 15 '18 at 23:29







            Thank you for your response, but we are trying to let PopupPickerRow and GenericPickerViewController work with anything as long as it’s Equatable, not restrict ourselves to Equatable & SyncableEntity. If I remove that change you made the problem persists.

            – Justin Garcia
            Nov 15 '18 at 23:29






            1




            1





            Yes, but then your protocol requirement to call that method implementation will break and it will call the default method without considering any constraints. I hope you got the idea what was wrong with your implementation so its up to you how you want to handle it.

            – Kamran
            Nov 15 '18 at 23:35





            Yes, but then your protocol requirement to call that method implementation will break and it will call the default method without considering any constraints. I hope you got the idea what was wrong with your implementation so its up to you how you want to handle it.

            – Kamran
            Nov 15 '18 at 23:35













            I think I’m starting to understand. so at compile time the default implementation of refresh(:,completion:) is chosen because all that is known about itemProvider is that it’s of a type that conforms to PickerItemProvider where PickerType is Equatable?

            – Justin Garcia
            Nov 15 '18 at 23:44





            I think I’m starting to understand. so at compile time the default implementation of refresh(:,completion:) is chosen because all that is known about itemProvider is that it’s of a type that conforms to PickerItemProvider where PickerType is Equatable?

            – Justin Garcia
            Nov 15 '18 at 23:44













            so I added an extension on GenericPickerViewController where PickerType conforms to Equatable and SyncableEntity that adds a different implementation of foo(). calls to refresh(:,completion:) on itemProvider in that extension result in calls to the refresh(:,completion:) implementation I added.

            – Justin Garcia
            Nov 15 '18 at 23:51







            so I added an extension on GenericPickerViewController where PickerType conforms to Equatable and SyncableEntity that adds a different implementation of foo(). calls to refresh(:,completion:) on itemProvider in that extension result in calls to the refresh(:,completion:) implementation I added.

            – Justin Garcia
            Nov 15 '18 at 23:51















            Well that works in the Playground but not in my project. I guess that’s because when the real foo() is compiled the compiler doesn’t know what type PickerType is going to be, so it chooses the default one not the one in the extension I added.

            – Justin Garcia
            Nov 16 '18 at 0:20







            Well that works in the Playground but not in my project. I guess that’s because when the real foo() is compiled the compiler doesn’t know what type PickerType is going to be, so it chooses the default one not the one in the extension I added.

            – Justin Garcia
            Nov 16 '18 at 0:20















            2














            I added two functions on GenericPickerViewController, one for setting it up with a PickerItemProvider whose PickerType simply conforms to Equatable, and another to set it up with a PickerItemProvider whose PickerType conforms to SyncableEntity. This way the compiler knows which refresh(:,completion:) to call. Here is the Playground code:



            import Foundation
            import CoreData

            protocol PickerItemProvider: class {
            associatedtype PickerType
            func itemAt(_ indexPath: IndexPath) -> PickerType?
            }

            extension PickerItemProvider {
            public func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("the default refresh implementation")
            }
            }

            public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
            func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
            return nil
            }
            }

            extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
            func refresh(_ sender: Any, completion: (() -> Void)?) {
            print("we’re trying to have this implementation called instead of the above implementation of refresh")
            PickerType.startSync()
            completion?()
            }
            }

            protocol SyncableEntity {
            associatedtype EntityType
            static func startSync()
            }

            extension SyncableEntity {
            static func startSync() {
            print("starting sync")
            }
            }

            class ObservationType: Equatable, SyncableEntity {
            typealias EntityType = NSManagedObject
            }

            func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
            return false
            }

            class GeneralPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
            private var itemProvider: ItemProvider?

            private var refresher: ((Any, (() -> ())?) -> ())?

            func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType {
            refresher = { sender, completion in
            itemProvider.refresh(self, completion: {
            completion?()
            })
            }
            self.itemProvider = (itemProvider as! ItemProvider)
            }

            func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType, PickerType: SyncableEntity {
            refresher = { sender, completion in
            itemProvider.refresh(self, completion: {
            completion?()
            })
            }
            self.itemProvider = (itemProvider as! ItemProvider)
            }

            func foo() {
            refresher?(self, {
            print("finished")
            })
            }
            }

            class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
            var pickerController = GeneralPickerViewController<T, ItemProvider>()
            }

            let pickerSectionProvider = PickerSectionProvider<ObservationType>()

            let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

            row.pickerController.setup(with: pickerSectionProvider)

            row.pickerController.foo()





            share|improve this answer




























              2














              I added two functions on GenericPickerViewController, one for setting it up with a PickerItemProvider whose PickerType simply conforms to Equatable, and another to set it up with a PickerItemProvider whose PickerType conforms to SyncableEntity. This way the compiler knows which refresh(:,completion:) to call. Here is the Playground code:



              import Foundation
              import CoreData

              protocol PickerItemProvider: class {
              associatedtype PickerType
              func itemAt(_ indexPath: IndexPath) -> PickerType?
              }

              extension PickerItemProvider {
              public func refresh(_ sender: Any, completion: (() -> Void)?) {
              print("the default refresh implementation")
              }
              }

              public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
              func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
              return nil
              }
              }

              extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
              func refresh(_ sender: Any, completion: (() -> Void)?) {
              print("we’re trying to have this implementation called instead of the above implementation of refresh")
              PickerType.startSync()
              completion?()
              }
              }

              protocol SyncableEntity {
              associatedtype EntityType
              static func startSync()
              }

              extension SyncableEntity {
              static func startSync() {
              print("starting sync")
              }
              }

              class ObservationType: Equatable, SyncableEntity {
              typealias EntityType = NSManagedObject
              }

              func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
              return false
              }

              class GeneralPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
              private var itemProvider: ItemProvider?

              private var refresher: ((Any, (() -> ())?) -> ())?

              func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType {
              refresher = { sender, completion in
              itemProvider.refresh(self, completion: {
              completion?()
              })
              }
              self.itemProvider = (itemProvider as! ItemProvider)
              }

              func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType, PickerType: SyncableEntity {
              refresher = { sender, completion in
              itemProvider.refresh(self, completion: {
              completion?()
              })
              }
              self.itemProvider = (itemProvider as! ItemProvider)
              }

              func foo() {
              refresher?(self, {
              print("finished")
              })
              }
              }

              class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
              var pickerController = GeneralPickerViewController<T, ItemProvider>()
              }

              let pickerSectionProvider = PickerSectionProvider<ObservationType>()

              let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

              row.pickerController.setup(with: pickerSectionProvider)

              row.pickerController.foo()





              share|improve this answer


























                2












                2








                2







                I added two functions on GenericPickerViewController, one for setting it up with a PickerItemProvider whose PickerType simply conforms to Equatable, and another to set it up with a PickerItemProvider whose PickerType conforms to SyncableEntity. This way the compiler knows which refresh(:,completion:) to call. Here is the Playground code:



                import Foundation
                import CoreData

                protocol PickerItemProvider: class {
                associatedtype PickerType
                func itemAt(_ indexPath: IndexPath) -> PickerType?
                }

                extension PickerItemProvider {
                public func refresh(_ sender: Any, completion: (() -> Void)?) {
                print("the default refresh implementation")
                }
                }

                public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
                func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
                return nil
                }
                }

                extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
                func refresh(_ sender: Any, completion: (() -> Void)?) {
                print("we’re trying to have this implementation called instead of the above implementation of refresh")
                PickerType.startSync()
                completion?()
                }
                }

                protocol SyncableEntity {
                associatedtype EntityType
                static func startSync()
                }

                extension SyncableEntity {
                static func startSync() {
                print("starting sync")
                }
                }

                class ObservationType: Equatable, SyncableEntity {
                typealias EntityType = NSManagedObject
                }

                func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
                return false
                }

                class GeneralPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
                private var itemProvider: ItemProvider?

                private var refresher: ((Any, (() -> ())?) -> ())?

                func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType {
                refresher = { sender, completion in
                itemProvider.refresh(self, completion: {
                completion?()
                })
                }
                self.itemProvider = (itemProvider as! ItemProvider)
                }

                func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType, PickerType: SyncableEntity {
                refresher = { sender, completion in
                itemProvider.refresh(self, completion: {
                completion?()
                })
                }
                self.itemProvider = (itemProvider as! ItemProvider)
                }

                func foo() {
                refresher?(self, {
                print("finished")
                })
                }
                }

                class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
                var pickerController = GeneralPickerViewController<T, ItemProvider>()
                }

                let pickerSectionProvider = PickerSectionProvider<ObservationType>()

                let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

                row.pickerController.setup(with: pickerSectionProvider)

                row.pickerController.foo()





                share|improve this answer













                I added two functions on GenericPickerViewController, one for setting it up with a PickerItemProvider whose PickerType simply conforms to Equatable, and another to set it up with a PickerItemProvider whose PickerType conforms to SyncableEntity. This way the compiler knows which refresh(:,completion:) to call. Here is the Playground code:



                import Foundation
                import CoreData

                protocol PickerItemProvider: class {
                associatedtype PickerType
                func itemAt(_ indexPath: IndexPath) -> PickerType?
                }

                extension PickerItemProvider {
                public func refresh(_ sender: Any, completion: (() -> Void)?) {
                print("the default refresh implementation")
                }
                }

                public class PickerSectionProvider<ProvidedType: Equatable> : PickerItemProvider {
                func itemAt(_ indexPath: IndexPath) -> ProvidedType? {
                return nil
                }
                }

                extension PickerItemProvider where PickerType: Equatable & SyncableEntity {
                func refresh(_ sender: Any, completion: (() -> Void)?) {
                print("we’re trying to have this implementation called instead of the above implementation of refresh")
                PickerType.startSync()
                completion?()
                }
                }

                protocol SyncableEntity {
                associatedtype EntityType
                static func startSync()
                }

                extension SyncableEntity {
                static func startSync() {
                print("starting sync")
                }
                }

                class ObservationType: Equatable, SyncableEntity {
                typealias EntityType = NSManagedObject
                }

                func ==(lhs: ObservationType, rhs: ObservationType) -> Bool {
                return false
                }

                class GeneralPickerViewController<PickerType: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == PickerType {
                private var itemProvider: ItemProvider?

                private var refresher: ((Any, (() -> ())?) -> ())?

                func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType {
                refresher = { sender, completion in
                itemProvider.refresh(self, completion: {
                completion?()
                })
                }
                self.itemProvider = (itemProvider as! ItemProvider)
                }

                func setup<T: PickerItemProvider>(with itemProvider: T) where T.PickerType == PickerType, PickerType: SyncableEntity {
                refresher = { sender, completion in
                itemProvider.refresh(self, completion: {
                completion?()
                })
                }
                self.itemProvider = (itemProvider as! ItemProvider)
                }

                func foo() {
                refresher?(self, {
                print("finished")
                })
                }
                }

                class PopupPickerRow<T: Equatable, ItemProvider: PickerItemProvider> where ItemProvider.PickerType == T {
                var pickerController = GeneralPickerViewController<T, ItemProvider>()
                }

                let pickerSectionProvider = PickerSectionProvider<ObservationType>()

                let row = PopupPickerRow<ObservationType, PickerSectionProvider<ObservationType>>()

                row.pickerController.setup(with: pickerSectionProvider)

                row.pickerController.foo()






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 16 '18 at 5:50









                Justin GarciaJustin Garcia

                1137




                1137






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53328770%2freimplementation-of-a-function-added-in-a-protocol-extension-isn-t-called%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Xamarin.form Move up view when keyboard appear

                    Post-Redirect-Get with Spring WebFlux and Thymeleaf

                    Anylogic : not able to use stopDelay()