ios - Swift: Accept a closure with varying parameters -


suppose have function accepts callback with sender, this:

func performaction(anumber: double, completion: (sender: uibutton) -> void) {     // stuff here     let button = getabuttonfromsomewhere()     completion(button) } 

and 1 possible way call function passing an existing function callback, rather defining closure in-place:

performaction(10, completion: mycallback)  func mycallback(sender: uibutton) {     sender.settitle("foo", forstate: .normal) } 

back in definition performaction, how can define completion block accept uibutton or subclass of it?

as example, suppose have uibutton subclass called custombutton. in callback, i'm interested in accepting custombutton. i'd this:

performaction(10, completion: mycallback)  // produces compiler error: func mycallback(sender: custombutton) {     sender.settitle("foo", forstate: .normal) }  // works, forces me cast custom class: func mycallback(sender: uibutton) {     let realbutton = sender as! custombutton     realbutton.settitle("foo", forstate: .normal) } 

but compiler won't allow it, because definition of performaction requires callback accept uibutton (even though custombutton is uibutton subclass).

i'd performaction generic can packaged in library, , work uibutton subclass. possible in swift?

edit: tried simplify i'm doing example above, think caused confusion. here's actual code i'm trying make work, improvements @luk2302:

public extension uibutton {      private class action: anyobject {         private var function:         init(function: any) {             self.function = function         }     }      // trickery add stored property uibutton...     private static var actionsassockey: uint8 = 0      private var action: action? {         {             return objc_getassociatedobject(self, &uibutton.actionsassockey) as? action         }         set(newvalue) {             objc_setassociatedobject(self, &uibutton.actionsassockey, newvalue, objc_associationpolicy.objc_association_retain)         }     }      internal func performaction(sender: uibutton) {         if let function = self.action!.function as? () -> void {             function()         // things break now:         } else if let function = self.action!.function as? (sender: self.type) -> void {             function(sender: self)         }     }      public func addtarget(forcontrolevents event: uicontrolevents, action: () -> void) {         self.action = action(function: action)         self.addtarget(self, action: "performaction:", forcontrolevents: event)     }      public func addtarget<b: uibutton>(forcontrolevents: uicontrolevents, actionwithsender: (sender: b) -> void) {         self.action = action(function: actionwithsender)         self.addtarget(self, action: "performaction:", forcontrolevents: forcontrolevents)     } } 

the piece breaks line commented, @ (sender: self.type) (self being either uibutton, or subclass of it).

so deviates original question slightly, how can can cast function closure accepting sender of same type self? code works if hard-code type, should able work any uibutton subclass.

you can make uibutton subclass generic parameter performaction function, need cast button before passing callback, unless have generic way of "getting" right type of button.

// performaction() works type of uibutton func performaction<b: uibutton>(anumber: double, completion: (sender: b) -> void) {     // assuming getabuttonfromsomewhere returns uibutton, , not b, must cast it.     if let button = getabuttonfromsomewhere() as? b {         completion(sender: button)     } } 

Comments

Popular posts from this blog

get url and add instance to a model with prefilled foreign key :django admin -

android - Keyboard hides my half of edit-text and button below it even in scroll view -

css - Make div keyboard-scrollable in jQuery Mobile? -