Search code examples
iosswiftprotocols

optional delegates with struct types - swift


I am getting below error while making protocol as optionals.

Method cannot be marked @objc because the type of the parameter 1 cannot be represented in Objective-C

My code :

@objc protocol PopupDelegate : class {
    @objc optional func popupItemSelected(item : PopupItem, identifier : String)
    @objc optional func popupItemMultipleSelected(item : [PopupItem], identifier : String)
}

struct PopupItem : Hashable {
    var name : String
    var id : Int
    var isSelected : Bool

    init(name: String, id: Int, isSelected : Bool = false) {
        self.name = name
        self.id = id
        self.isSelected = isSelected
    }
}
  • I got one post with same issue in swift 2, but I can't implement this solution as Inheritance not allowed in struct.

  • I tried to add @objc flag to my struct but got below error

Only classes (and their extensions), protocols, methods, initializers, properties, and subscript declarations can be declared @objc


Is there any way to implement optional delegates with struct types?


Solution

  • I think the error messages you posted are self explanatory, Struct is not available in Objective-C runtime so when you annotate a protocol with @objc compiler gives you warning that struct can't be passed as an argument to such protocol.

    How to achieve optional behaviour in pure swift? Officially there is no equivalent of objective-C optional in swift. But empty default extensions will help you achieve the same behavior.

    protocol PopupDelegate {
        func popupItemSelected(item : PopupItem, identifier : String)
        func popupItemMultipleSelected(item : [PopupItem], identifier : String)
    }
    
    extension PopupDelegate {
        func popupItemSelected(item : PopupItem, identifier : String) { }
        func popupItemMultipleSelected(item : [PopupItem], identifier : String) { }
    }
    

    Now whoever confirms to PopupDelegate need not implement methods as default implementation is already provided and because its empty implementation it's almost same as optional.

    One caveat of this approach would be though, if you call respondsToSelector this will return true as there exists a default implementation but with optional you would get appropriate response.