Let's take this method as an example:
+ (void)animateWithDuration:(NSTimeInterval)duration
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion
It's simple enough to swizzle in a different or modified implementation of animatedWithDuration:animations:completion: method itself. What if I am instead interested in doing this for the completion block?
Swizzling refers to modifying the class or object meta data in order to call different implementation for a given selector. (It is a very fragile, and somewhat dangerous technique that should generally be be avoided in production code unless you are very aware of what you're doing, and if you are, you'll probably avoid it anyway. When it blows up, it blows up gloriously and makes code incredibly difficult to understand. It is useful for debugging and exploration, however.)
A block is a value. It is a function literal, just a like "1" is an integer literal or #"string" is a string literal. There is no object or class to swizzle. If you want to modify the value, you have to modify the value, just like you would modify the duration in your example.
As others have pointed out, "swizzle" is used to refer to changing a method implementation, so you've the wrong term but that's not major.
I'm guessing what you want to do is either: pass a different block to animatedWithDuration:animations:completion: than the caller supplies; or wrap the block the caller supplies in your own block - which amounts to much the same thing.
If my guess is correct then you can swizzle the method replacing it by one which calls the original passing blocks of your choice, which could be wrappers around the blocks the caller supplied.
HTH
Related
I am learning objective c and swift. i didn't get what is difference between block and method or function in Objective c or in Swift.
int mutiplier=10;
int (^myBlock)(void)=^{
return 10 *3;
};
NSLog(#"%d",myBlock());
Or can write method/function like this
-(int)function:(int)num{
return num* 10;
}
Blockquote
Short and simple:
Block of code - just a block of code. You can declare it, define types of blocks(then make an instances), call blocks one by one, etc. Blocks can take parameters, can return something, It`s quite convenient to use them along with a Grand Central Dispatch. Blocks can declared right in the middle of the code, as an instance variable or as a property. They can also be passed as an arguments to a method/function call. After block has done its work you can call the 'completion' part to run some specific code, which is convenient in some cases. In a swift language similar to blocks (but not equal) thing is a closure. Would like to add that there is a block-based enumeration approach available in Objective-c which is almost as fast as Fast enumeration. Would recommend fast enumeration for most cases, but sometimes (rare) block enumeration is better. Other loops usually is not as fast as this two ones. One more important thing we should keep in mind is that the blocks are Objective-C objects while functions and methods are not. Blocks can capture values from the variables from the enclosing scope while to get the same values inside of a function/method you need to pass these variables as an arguments. Using blocks you can even change these variables using f.e.
__block int anInteger = 123;
syntax before the block call.
Keep in mind you avoid strong reference to a self when capturing it inside of a block to avoid retain cycles. Use weakSelf in that case.
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html
Function should have name, return something or be void.
Method is a function of a class.
Blocks are a way of wrapping up a piece of code and effectively storing it for later use. A block is commonly used in place of a call back function. Newer APIs in the iPhone SDK use blocks this way. The API will take a "block" of code that it will run on completion. And Blocks are presented in swift as a Closure.
In swift it's little tough syntax to learn closure. but trust me it's very handy way when you start to use it.
It saves you having to create your own threads and maintain the state of each thread, manage locks, setup autorelease pools etc.
Also, when used with the Grand Central Dispatch (GCD) API blocks can be run on queues and entire portions of code can be made to run asynchronously with very little effort, but still keeping the robustness that is required for multithreaded code.
The question here is more of an educational one. I began to think of this an hour ago while
flipping around a lego block (silly, I know).
A block is an object created on stack, from what I understand.
Let say A is an object, which means we can do:
[A message];
Based on that, if a block is an object, we could also do:
[block message];
Am I correct?
And when the runtime sees that, it would call:
objc_msgSend(block, #selector(message), nil);
So my question is, how can we send a block a message?
And if that is possible, I would imagine that it would also be possible to send a block a message with the arguments being blocks as well?
And, if we could call a block by doing:
block();
Does that mean we could even make a block as a message (SEL) as well, because blocks have the signature void (^)(void) which resembles that of a method?
Because if it would be possible, then the following would really surprise me:
objc_msgSend(block, #selector(block), block);
or:
objc_msgSend(block1, #selector(block2), block3);
I hope my imagination is not running a bit wild and that my understanding is not off here (correct me, if it is).
Blocks are objects only for the purposes of storage and referencing. By making them objects, blocks can be retain/release'd and can, therefore, be shoved into arrays or other collection classes. They also respond to copy.
That's about it. Even that a block starts on the stack is largely a compiler implementation detail.
When a block's code is invoked, that is not done through objc_msgSend(). If you were to read the source for the block runtime and the llvm compiler, then you'd find that:
a block is really a C structure that contains a description of the data that has been captured (so it can be cleaned up) and a pointer to a function -- to a chunk of code -- that is the executable portion of the block
the block function is a standard C function where the first argument must always be a reference to the block. The rest of the argument list is arbitrary and works just like any old C function or Objective-C method.
So, your manual calls to objc_msgSend() treat the block like any other random ObjC object and, thus, won't call the code in the block, nor, if it did (and there is SPI that can do this from a method... but, don't use it) could it pass an argument list that was fully controllable.
One aside, though of relevance.
imp_implementationWithBlock() takes a block reference and returns an IMP that can be plugged into an Objective-C class (see class_addMethod()) such that when the method is invoked, the block is called.
The implementation of imp_implementationWithBlock() takes advantage of the layout of the call site of an objective-c method vs. a block. A block is always:
blockFunc(blockRef, ...)
And an ObjC method is always:
methodFunc(selfRef, SEL, ...)
Because we want the imp_implementationWithBlock() block to always take the target object to the method as the first block parameter (i.e. the self), imp_implementationWithBlock() returns a trampoline function that when called (via objc_msgSend()):
- slides the self reference into the slot for the selector (i.e. arg 0 -> arg 1)
- finds the implementing block puts the pointer to that block into arg 0
- JMPs to the block's implementation pointer
The finds the implementing block bit is kinda interesting, but irrelevant to this question (hell, the imp_implementationWithBlock() is a bit irrelevant, too, but may be of interest).
Thanks for response. It's definitely an eye opener. The part about
blocks calling is not done thru objc_msgSend() tells me that it is
because blocks are not part of the normal object-hierachry (but coda's
mentioning of NSBlock seems to refute what I understand so far,
because NSBlock would make it part of the object-hierachy). Feel free
to take a stab at me, if my understanding is still off so far. I am
very interested in hearing more about the followings 1: the SPI and
the way (how) to call that method. 2: the underlying mechanisms of:
sliding the self reference into the slot. 3: finds the implementing
block and puts the pointer to that block into arg 0. If you have time
to share and write a bit more about those in detail, I am all ears; I
find this all very fascinating. Thanks very much in advance.
The blocks, themselves, are very much just a standard Objective-C object. A block instance contains a pointer to some executable code, any captured state, and some helpers used to copy said state from stack to heap (if requested) and cleanup the state on the block's destruction.
The block's executable code is not invoked like a method. A block has other methods -- retain, release, copy, etc... -- that can be invoked directly like any other method, but the executable code is not publicly one of those methods.
The SPI doesn't do anything special; it only works for blocks that take no arguments and it is nothing more than simply doing block().
If you want to know how the whole argument slide thing works (and how it enables tail calling through to the block), I'd suggest reading this or this. As well, the source for the blocks runtime, the objc runtime, and llvm are all available.
That includes the fun bit where the IMP grabs the block and shoves it into arg0.
Yes, blocks are objects. And yes, that means you can send messages to them.
But what message do you think a block responds to? We are not told of any messages that a block supports, other than the memory management messages retain, release, and copy. So if you send an arbitrary message to a block, chances are that it will throw a "does not recognize selector" exception (the same thing that would happen if you sent an arbitrary message to any object you don't know the interface of).
Invoking a block happens through a different mechanism than message sending, and is magic implemented by the compiler, and not exposed to the programmer otherwise.
Blocks and selectors are very different. (A selector is just an interned string, the string of the method name.) Blocks and IMPs (functions implementing methods) are somewhat similar. However, they are still different in that methods receive the receiver (self) and the selector called as special parameters, whereas blocks do not have them (the function implementing the block only receives the block itself as a hidden parameter, not accessible to the programmer).
I'm new to using blocks, and they really seem like a great alternative to delegate methods. I implemented a simple block to do some simple math after watching a few tutorials, but I'm really struggling in being able to get them to do much more than that thanks to their wacky syntax.
Could someone help explain how I'd implement a block in objective-c that would do something similar to the pseudo code below?
Call block from within a method
The block looks at a class array and notifies the caller if it is populated (has a count of > 0)
If the array's count is 0, the block will notify the caller when it has something added to it and the block will then stop
Thanks!
You're imputing too much power and flexibility to Blocks. They're just functions. They get called, they run, they return a value.
The only difference between a Block and a plain function that does the same work is that a Block can be treated as an object for purposes of being put into collections like arrays. They're easier to use for things like delegation because they can be defined in a scope other than file-level, and they'll capture variables from that scope. The Block syntax is so confusing because it's based on function pointers, famously the most gnarly part of C syntax.
There's no "Block notifies caller" functionality inherent to Blocks. You can only pass a return value back.
I understand that these both are bit similar, but there must be any internal difference between two,
[anObject performSelector:#selector(thisMethod:) withObject:passedObject];
is equivalent to:
[anObject thisMethod:passedObject];
Please tell me what is the differnce in terms of compilation, memory etc.
The performSelector family of methods are for special cases, the vast majority of method invocations in Obj-C should be direct. Some differences:
Indirect: When using performSelector to invoke a method you have two method invocations; that of performSelector and the target method.
Arguments are objects: When invoking via performSelector all arguments must be passed as objects, e.g. if invoking a method which takes a double then that value must be wrapped as an NSNumber before being passed to performSelector. The performSelector methods unwraps non-object arguments before calling the target method. In direct invocation no wrapping or unwrapping is required.
Only two arguments: The performSelector family only includes variants which pass 0, 1 or 2 arguments so you cannot use them to invoke a method which takes 3 or more arguments.
You probably see most of the above as negatives, so what are the benefits?
Dynamic selector: The performSelector family allow you to invoke a method which is not known until runtime, only its type need be known (so you can pass the right arguments and get the right result); in other words the selector argument may be an expression of type SEL. This might be used when you wish to pass a method as an argument to another method and invoke it. However if you are compiling with ARC using dynamic selectors is non-trivial and usually produces compiler warnings, as without knowing the selector ARC cannot know the ownership attributes of the arguments.
Delayed execution: The performSelector family includes methods which invoke the method after a delay.
In general use direct method invocation, only if that does not give you what you require do you need to consider the performSelector family (or its even more esoteric cousins).
performSelector:withObject: will be slightly slower than calling the method directly. The indirection also means that the compiler can't do proper type checking. With ARC enabled, you'll also run into issues where the compiler will complain because it is impossible to determine exactly what the memory management policy might be.
In general, such indirection -- often called reflection but more accurately referred to as meta-programming -- is to be avoided exactly because it moves what should be compile time detectable failures to runtime failures.
Such dynamism is only needed when the name of the selector -- the name of the method -- being called cannot be determined at compile time. It should not be used for #optional methods in protocols nor should it be used during delegation (in both cases, respondsToSelector: + a direct method call are a far better pattern to employ).
The performSelector: method allows you to send messages that aren’t determined until runtime. For more info read this.
If your app wants to make use of reflection, where in by changing some values in configuration file you want to invoke a different method (Different adapters). Or based on object type you would like to invoke a different method on runtime.
If you developing a customizable product this a powerful feature.
I like to use [id performSelecter:selector withObject] when declare and implements a custom protocol,and delegate pattern, its also an use case, where we should use performselector rather then direct calling the method...
I have heard people state that method swizzling is a dangerous practice. Even the name swizzling suggests that it is a bit of a cheat.
Method Swizzling is modifying the mapping so that calling selector A will actually invoke implementation B. One use of this is to extend behavior of closed source classes.
Can we formalise the risks so that anyone who is deciding whether to use swizzling can make an informed decision whether it is worth it for what they are trying to do.
E.g.
Naming Collisions: If the class later extends its functionality to include the method name that you have added, it will cause a huge manner of problems. Reduce the risk by sensibly naming swizzled methods.
I think this is a really great question, and it's a shame that rather than tackling the real question, most answers have skirted the issue and simply said not to use swizzling.
Using method sizzling is like using sharp knives in the kitchen. Some people are scared of sharp knives because they think they'll cut themselves badly, but the truth is that sharp knives are safer.
Method swizzling can be used to write better, more efficient, more maintainable code. It can also be abused and lead to horrible bugs.
Background
As with all design patterns, if we are fully aware of the consequences of the pattern, we are able to make more informed decisions about whether or not to use it. Singletons are a good example of something that's pretty controversial, and for good reason — they're really hard to implement properly. Many people still choose to use singletons, though. The same can be said about swizzling. You should form your own opinion once you fully understand both the good and the bad.
Discussion
Here are some of the pitfalls of method swizzling:
Method swizzling is not atomic
Changes behavior of un-owned code
Possible naming conflicts
Swizzling changes the method's arguments
The order of swizzles matters
Difficult to understand (looks recursive)
Difficult to debug
These points are all valid, and in addressing them we can improve both our understanding of method swizzling as well as the methodology used to achieve the result. I'll take each one at a time.
Method swizzling is not atomic
I have yet to see an implementation of method swizzling that is safe to use concurrently1. This is actually not a problem in 95% of cases that you'd want to use method swizzling. Usually, you simply want to replace the implementation of a method, and you want that implementation to be used for the entire lifetime of your program. This means that you should do your method swizzling in +(void)load. The load class method is executed serially at the start of your application. You won't have any issues with concurrency if you do your swizzling here. If you were to swizzle in +(void)initialize, however, you could end up with a race condition in your swizzling implementation and the runtime could end up in a weird state.
Changes behavior of un-owned code
This is an issue with swizzling, but it's kind of the whole point. The goal is to be able to change that code. The reason that people point this out as being a big deal is because you're not just changing things for the one instance of NSButton that you want to change things for, but instead for all NSButton instances in your application. For this reason, you should be cautious when you swizzle, but you don't need to avoid it altogether.
Think of it this way... if you override a method in a class and you don't call the super class method, you may cause problems to arise. In most cases, the super class is expecting that method to be called (unless documented otherwise). If you apply this same thought to swizzling, you've covered most issues. Always call the original implementation. If you don't, you're probably changing too much to be safe.
Possible naming conflicts
Naming conflicts are an issue all throughout Cocoa. We frequently prefix class names and method names in categories. Unfortunately, naming conflicts are a plague in our language. In the case of swizzling, though, they don't have to be. We just need to change the way that we think about method swizzling slightly. Most swizzling is done like this:
#interface NSView : NSObject
- (void)setFrame:(NSRect)frame;
#end
#implementation NSView (MyViewAdditions)
- (void)my_setFrame:(NSRect)frame {
// do custom work
[self my_setFrame:frame];
}
+ (void)load {
[self swizzle:#selector(setFrame:) with:#selector(my_setFrame:)];
}
#end
This works just fine, but what would happen if my_setFrame: was defined somewhere else? This problem isn't unique to swizzling, but we can work around it anyway. The workaround has an added benefit of addressing other pitfalls as well. Here's what we do instead:
#implementation NSView (MyViewAdditions)
static void MySetFrame(id self, SEL _cmd, NSRect frame);
static void (*SetFrameIMP)(id self, SEL _cmd, NSRect frame);
static void MySetFrame(id self, SEL _cmd, NSRect frame) {
// do custom work
SetFrameIMP(self, _cmd, frame);
}
+ (void)load {
[self swizzle:#selector(setFrame:) with:(IMP)MySetFrame store:(IMP *)&SetFrameIMP];
}
#end
While this looks a little less like Objective-C (since it's using function pointers), it avoids any naming conflicts. In principle, it's doing the exact same thing as standard swizzling. This may be a bit of a change for people who have been using swizzling as it has been defined for a while, but in the end, I think that it's better. The swizzling method is defined thusly:
typedef IMP *IMPPointer;
BOOL class_swizzleMethodAndStore(Class class, SEL original, IMP replacement, IMPPointer store) {
IMP imp = NULL;
Method method = class_getInstanceMethod(class, original);
if (method) {
const char *type = method_getTypeEncoding(method);
imp = class_replaceMethod(class, original, replacement, type);
if (!imp) {
imp = method_getImplementation(method);
}
}
if (imp && store) { *store = imp; }
return (imp != NULL);
}
#implementation NSObject (FRRuntimeAdditions)
+ (BOOL)swizzle:(SEL)original with:(IMP)replacement store:(IMPPointer)store {
return class_swizzleMethodAndStore(self, original, replacement, store);
}
#end
Swizzling by renaming methods changes the method's arguments
This is the big one in my mind. This is the reason that standard method swizzling should not be done. You are changing the arguments passed to the original method's implementation. This is where it happens:
[self my_setFrame:frame];
What this line does is:
objc_msgSend(self, #selector(my_setFrame:), frame);
Which will use the runtime to look up the implementation of my_setFrame:. Once the implementation is found, it invokes the implementation with the same arguments that were given. The implementation it finds is the original implementation of setFrame:, so it goes ahead and calls that, but the _cmd argument isn't setFrame: like it should be. It's now my_setFrame:. The original implementation is being called with an argument it never expected it would receive. This is no good.
There's a simple solution — use the alternative swizzling technique defined above. The arguments will remain unchanged!
The order of swizzles matters
The order in which methods get swizzled matters. Assuming setFrame: is only defined on NSView, imagine this order of things:
[NSButton swizzle:#selector(setFrame:) with:#selector(my_buttonSetFrame:)];
[NSControl swizzle:#selector(setFrame:) with:#selector(my_controlSetFrame:)];
[NSView swizzle:#selector(setFrame:) with:#selector(my_viewSetFrame:)];
What happens when the method on NSButton is swizzled? Well most swizzling will ensure that it's not replacing the implementation of setFrame: for all views, so it will pull up the instance method. This will use the existing implementation to re-define setFrame: in the NSButton class so that exchanging implementations doesn't affect all views. The existing implementation is the one defined on NSView. The same thing will happen when swizzling on NSControl (again using the NSView implementation).
When you call setFrame: on a button, it will therefore call your swizzled method, and then jump straight to the setFrame: method originally defined on NSView. The NSControl and NSView swizzled implementations will not be called.
But what if the order were:
[NSView swizzle:#selector(setFrame:) with:#selector(my_viewSetFrame:)];
[NSControl swizzle:#selector(setFrame:) with:#selector(my_controlSetFrame:)];
[NSButton swizzle:#selector(setFrame:) with:#selector(my_buttonSetFrame:)];
Since the view swizzling takes place first, the control swizzling will be able to pull up the right method. Likewise, since the control swizzling was before the button swizzling, the button will pull up the control's swizzled implementation of setFrame:. This is a bit confusing, but this is the correct order. How can we ensure this order of things?
Again, just use load to swizzle things. If you swizzle in load and you only make changes to the class being loaded, you'll be safe. The load method guarantees that the super class load method will be called before any subclasses. We'll get the exact right order!
Difficult to understand (looks recursive)
Looking at a traditionally defined swizzled method, I think it's really hard to tell what's going on. But looking at the alternative way we've done swizzling above, it's pretty easy to understand. This one's already been solved!
Difficult to debug
One of the confusions during debugging is seeing a strange backtrace where the swizzled names are mixed up and everything gets jumbled in your head. Again, the alternative implementation addresses this. You'll see clearly named functions in backtraces. Still, swizzling can be difficult to debug because it's hard to remember what impact the swizzling is having. Document your code well (even if you think you're the only one who will ever see it). Follow good practices, and you'll be alright. It's not harder to debug than multi-threaded code.
Conclusion
Method swizzling is safe if used properly. A simple safety measure you can take is to only swizzle in load. Like many things in programming, it can be dangerous, but understanding the consequences will allow you use it properly.
1 Using the above defined swizzling method, you could make things thread safe if you were to use trampolines. You would need two trampolines. At the start of the method, you would have to assign the function pointer, store, to a function that spun until the address to which store pointed to changed. This would avoid any race condition in which the swizzled method was called before you were able to set the store function pointer. You would then need to use a trampoline in the case where the implementation isn't already defined in the class and have the trampoline lookup and call the super class method properly. Defining the method so it dynamically looks up the super implementation will ensure that the order of swizzling calls does not matter.
First I will define exactly what I mean by method swizzling:
Re-routing all calls that were originally sent to a method (called A) to a new method (called B).
We own Method B
We dont own method A
Method B does some work then calls method A.
Method swizzling is more general than this, but this is the case I am interested in.
Dangers:
Changes in the original class. We dont own the class that we are swizzling. If the class changes our swizzle may stop working.
Hard to maintain. Not only have you got to write and maintain the swizzled method. you have to write and maintain the code that preforms the swizzle
Hard to debug. It is hard to follow the flow of a swizzle, some people may not even realise the swizzle has been preformed. If there are bugs introduced from the swizzle (perhaps dues to changes in the original class) they will be hard to resolve.
In summary, you should keep swizzling to a minimum and consider how changes in the original class might effect your swizzle. Also you should clearly comment and document what you are doing (or just avoid it entirely).
It's not the swizzling itself that's really dangerous. The problem is, as you say, that it's often used to modify the behavior of framework classes. It's assuming that you know something about how those private classes work that's "dangerous." Even if your modifications work today, there's always a chance that Apple will change the class in the future and cause your modification to break. Also, if many different apps do it, it makes it that much harder for Apple to change the framework without breaking a lot of existing software.
Used carefully and wisely, it can lead to elegant code, but usually, it just leads to confusing code.
I say that it should be banned, unless you happen to know that it presents a very elegant opportunity for a particular design task, but you need to clearly know why it applies well to the situation, and why alternatives do not work elegantly for the situation.
Eg, one good application of method swizzling is isa swizzling, which is how ObjC implements Key Value Observing.
A bad example might be relying on method swizzling as a means of extending your classes, which leads to extremely high coupling.
Although I have used this technique, I would like to point out that:
It obfuscates your code because it can cause un-documented, though desired, side effects. When one reads the code he/she may be unaware of the side effect behavior that is required unless he/she remembers to search the code base to see if it has been swizzled. I'm not sure how to alleviate this problem because it is not always possible to document every place where the code is dependent upon the side effect swizzled behavior.
It can make your code less reusable because someone who finds a segment of code which depends upon the swizzled behavior that they would like to use elsewhere cannot simply cut and paste it into some other code base without also finding and copying the swizzled method.
I feel that the biggest danger is in creating many unwanted side effects, completely by accident. These side effects may present themselves as 'bugs' which in turn lead you down the wrong path to find the solution. In my experience, the danger is illegible, confusing, and frustrating code. Kind of like when someone overuses function pointers in C++.
You may end up with odd looking code like
- (void)addSubview:(UIView *)view atIndex:(NSInteger)index {
//this looks like an infinite loop but we're swizzling so default will get called
[self addSubview:view atIndex:index];
from actual production code related to some UI magic.
Method swizzling can be very helpful is in unit testing.
It allows you to write a mock object and have that mock object used instead of the real object. Your code to remain clean and your unit test has predictable behavior. Let's say you want to test some code that uses CLLocationManager. Your unit test could swizzle startUpdatingLocation so that it would feed a predetermined set of locations to your delegate and your code would not have to change.