An instance method in Swift was just a type method that takes the instance as an argument and returns a function which would Then being applied to the instance.
I recently learned about a Swift feature this blew my mind a little. Instance methods is just curried functions that take the Instance as the first argument. What's a curried function, you ask?
The basic idea behind currying was that a function can being partially applied, meaning that some of its parameter values can Being specified (bound) before the function is called. Partial function application yields a new function.
Example
Consider this simple example of a Class A, represents a bank account:
1234567 |
{ balancedeposit(amountDouble}} |
We can obviously create a instance of this class and the call the deposit()
method on that instance:
12 |
BankAccount()account. Deposit(+//Balance are now |
So far. But we can also does this:
12 |
let depositor = bankaccount. Depositdepositor (account) () //balance was now |
This was totally equivalent to the above. What's going on here? We first assign the method to a variable. Pay attention to the lack of parentheses after BankAccount.deposit
-we is not calling the method here (which would yield an E Rror because you can ' t call an instance method on the type), just referencing it, much like a function pointer in C. The second step is then-to-call the function stored in the depositor
variable. Its type is as follows:
In the other words, the This function had a single argument, a BankAccount
instance, and returns another function. This latter function takes a and Double
returns nothing. You should recognize the signature of the deposit()
instance method in this second part.
I hope you can see that an instance method in Swift is simply a type method that takes the instance as an argument and RET Urns a function which'll then is applied to the instance. Of course, we can also do this on one line, which makes the relationship between type methods and instance methods even CL Earer:
1 |
BankAccount. Deposit(account) (+//Balance are now |
BankAccount.deposit()
by passing the instance to, the instance gets a bound to the function. In a second step, this function is then called with the other arguments. Pretty cool, eh?
Implementing Target-action in Swift
Christoffer Lernöshows in a post on the developer forums how this characteristic of Swift's type system can be used to IM Plement the target-action pattern in pure Swift. In contrast to the common implementation in Cocoa, Christoffer's solution does not rely on objective-c ' s dynamic message D Ispatch mechanism. And it comes with full type safety because it does not rely on selectors.
This pattern was often better than using plain closures for callbacks, especially when the receiving objects have to hold on To the closure for an indeterminate amount of time. Using closures often forces the caller of the API to doing extra work to prevent strong reference cycles. With the target-action pattern, the object is provides the API can do the Strong-weak dance internally, which leads to C Leaner code on the calling side.
For example, the A Control
class using target-action might look like this in Swift (adopted from a dev forums post by Jens Jakob Jensen):
Update July 2014:made the property in action
TargetActionWrapper
non-optional. Must was target
optional because it is weak
.
123456789101112131415161718192021222324252627282930313233343536 |
ProtocolTargetaction{FuncPerformaction()}structTargetactionwrapper<T:Anyobject>:Targetaction{WeakVarTarget:T?LetAction:(T)-()-()FuncPerformaction()-(){IfLetT=Target{Action(T)()}}}EnumControlEvent{CaseTouchupinsideCaseValueChanged// ...}ClassControl{VarActions=[ControlEvent:Targetaction]()FuncSettarget<T:Anyobject>(Target:T,Action:(T)-()-(),ControlEvent:ControlEvent){Actions[ControlEvent]=Targetactionwrapper(Target:Target,Action:Action) } func removetargetforcontrolevent (controlevent: controlevent) Span class= "P" >{actions[controlevent = nil func (controlevent: Controlevent) {actions[ Controlevent)? performaction () }} |
Usage:
1234567891011 |
ClassMyviewcontroller{Letbutton= control () func viewdidload< Span class= "P" > () {button. Settarget (selfaction: myviewcontroller. Onbuttontapcontrolevent: .) } func onbuttontap () {println ( "button was tapped" Span class= "P" >) }} |
Instance Methods is curried Functions in Swift