This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Using -performSelector: vs. just calling the method
I can accomplish the same task in my application by doing:
[self performSelector:#selector(displayOneLife)];
and:
[self displayOneLife];
Is it better to use one or the other depending on the situation? If so, can someone elaborate for me? I would just like to use Objective-C best practices.
Thank you,
Joey
The -performSelector approach is usually used when you would like to invoke some selector not known at compilation time. For instance, UIButton uses it to invoke the action you wire it up to when a user hits it (the button knows the name of the method it is hooked up in IB and the class it it hooked up to).
For all other cases you should go with the latter as you don't want to convert your code into an unreadable puzzle.
P.S. -performSelector + dynamic selector name construction can be used to work around Apple's static analyzer which seeks the binary for prohibited invocations :)
You can store a selector in a variable, so performSelector: is useful for when you don't know at compile-time what message you want to send. For example, the target-action system is based on selectors. Here's a rudimentary implementation of a control:
#interface FakeControl : NSObject
#property(nonatomic, strong) id target;
#property(nonatomic, assign) SEL action;
- (void)click;
#end
#implementation FakeControl
- (void)click {
[target performSelector:action];
}
#end
By using a selector, we can have the control send any message we want at runtime when it's clicked.
#selector has a very specific use, and you should not use it to call known methods.
You use #selector to inform other classes of one of your methods that should be called.
For example you can pass the class countNumber a selector to your method #selector(result:) so that the other class will call your method when it has completed its task.
example code:
- (void)calculateANumber
{
[NumbersClass countNumber:myNumber withResult:#selector(result:)];
}
//This method will get called by NumbersClass, even tho it didnt know its existence before
- (void)result:(int)countResult
{
myResult = countResult;
}
Just an example, obviously, it does nothing
If you have to do some thing inline especially on the same thread
[self displayOneLife]
is good enough
But there are many instances, where you want to do the execution on another thread, or after a delay etc. If you just type, [self perform ...], you will see so many suggestions for methods available for performSelector, each of the method signatures will help you understand what it does.
Select one of the methods and just command click on the method name. It will show you details about what the method does etc.
It is a very good question but has many answers. Runloops, threads, delays, asynchronous operations are all reasons.
Related
If I am using a custom UITableViewCell I can use the following methods to change the cell's appearance when transitioning state:
- (void)willTransitionToState:(UITableViewCellStateMask)state
- (void)didTransitionToState:(UITableViewCellStateMask)state
Is there a way to achieve this if I'm not using a custom tableview cell?
Edit: Please see Daniel Hanly's comment. Categories may be selectively applied using #import. My apologies to anyone that may have been misled by this answer. Relevant sections will be redacted for future reference.
Okay, attempt number two. As far as I am aware, there is no other documented way to implement the functionality you require without subclassing UITableViewCell. It's worth noting that Apple's docs on UITableViewCell specifically mention that the state transition methods are meant to be implemented by subclasses. That having been said, If you absolutely need to implement them without a subclass, there are a couple of less conventional solutions. Each comes with its own issues, and it may end up being unfeasible for you to implement them, but it's an interesting question nonetheless.
Disclaimer
If you only want a sane and relatively simple explanation, then consider the answer to your question to be "no, there is no way to do what you want." I only present the options below with the assertion that they will work. In no way do I endorse actually using them. Consider this my penance for providing my first answer with such an obvious flaw.
Option One - Categories
It is possible to get the functionality you're looking for by overriding the methods you listed in a custom UITableViewCell category.
The problem is that this approach would be a pretty bad idea 99% of the time. Once you define the category on UITableViewCell, those methods would be defined for all UITableViewCell objects throughout the app. Unless you want the exact same state transition functionality for every single table cell in the app, this approach isn't very helpful.
Option Two - Runtime magic
You can use the low-level Objective-C runtime functions to change the implementation of any method on the fly. Unlike the categories option, this approach is flexible enough to redefine the intended behavior whenever you need to, instead of being a one-shot deal.
For example, if you're trying to manage state transitions from a UITableViewController, you could do this:
CustomTableViewController.m
#import <objc/runtime.h>
- (void) customStateWillChange:(UITableViewCellStateMask)state
{
//custom UITableViewCell code
}
- (void) viewDidAppear:(BOOL)animated
{
//Store the original implementation
Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], #selector(willTransitionToState:));
originalStateWillChangeImplementation = method_getImplementation(originalStateWillChangeMethod); //variable declared in header file as type IMP
//Get the new implementation
Method newStateWillChangeMethod = class_getInstanceMethod([self class], #selector(customStateWillChange:));
IMP newStateWillChangeImplementation = method_getImplementation(newStateWillChangeMethod);
//Replace implementation
method_setImplementation(originalStateWillChangeMethod, newStateWillChangeImplementation);
//the rest of your viewDidAppear code
[super viewDidAppear:animated];
}
- (void) viewDidDisappear:(BOOL)animated
{
//restore the original implementation
Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], #selector(willTransitionToState:));
method_setImplementation(originalStateWillChangeMethod, originalStateWillChangeImplementation);
//rest of viewDidDisappear code
[super viewDidDisappear:animated];
}
This code may not suit your exact purposes, but I think it provides a useful example.
It's incredibly ugly though because the customStateWillChange: method defined here is only intended to be run as a part of the UITableViewCell class, but in this example it will be compiled as though it were part of the CustomTableController class. Among other annoyances, you would have to eschew the property dot notation, ignore compiler warnings and give up most if not all compile-time checks for that method's body.
Option 3 - Category with runtime magic
Exactly what it sounds like. Define any custom state change methods you like within a category (or several categories) on UITableViewCell. Be sure that each one has a separate name - adding two categories that each have a method of the same name will result in undefined behavior. Also, each one needs to have the same return type and argument types as the method it is intended to replace.
Then the references to [self class] in the above code would be replaced with [UITableViewCell class], and the customStateWillChange: method would be moved to the custom category. While still ugly, you can at least rely on the compiler to interpret the method bodies properly.
Of course, messing with the runtime adds a whole lot of complexity to keep track of. It could work fine, but it's not good design, it would take serious effort to ensure it worked safely and correctly, and it would be likely to bring anguish and despair to anyone maintaining it.
References
The Objective-C Programming Language - Categories and Extensions
Objective-C Runtime Reference
Absolutely. The UITableViewDelegate protocol specifies a number of methods to manage state transitions for the table view's cells. Take a look at the UITableViewDelegate Class Reference, specifically the methods listed under the heading "Editing Table Rows".
Edit
Sorry, you're right. The UITableViewDelegate methods don't respond to direct changes to the cell's properties. I've found a way that does work, but I'm going to put it in a different answer to avoid confusion.
I am trying to reduce ceremony and out of academic curiosity I want to know how to do the following without the IBAction method defined in the .m file to use a closure whenever an Interface Builder wired action occurs such as a button press. You could say that I want to imply the cancelButtonPress method below instead of having to define it. A UIViewController subclass or some magic stored in a category would be quite acceptable.
#interface MyViewController : UIViewController
{
void(^doOnCancel)(void);
}
#property (nonatomic, copy) void(^doOnCancel)(void);
- (IBAction)cancelButtonPress:(id)sender;//I want this gone!
#end
I tried changing void to IBAction in the property and variable with no luck.
Edit: Alternative patterns that also reduce repetition in using closures for actions would also be useful.
The bounty is for a good pattern that will allow for closures to be arbitrarily used to service actions defined in IB in a way that could be used to reduce ceremony. The "can't do it" comments so far might or might not be correct.
Ahruman's approach is good, but it's probably relying too much on the runtime. Other than performance issues, Swizzling and using initialize is more susceptible to bugs if someone else wants to play with the runtime at the same time. I suggest using C macros.
Define these macros at the top of your class (or anywhere, really):
typedef void(^BlockAction)(id sender);
#define BlockActionProperty(ACTION) #property (copy) BlockAction ACTION;\
- (IBAction) ACTION:(id)sender;
#define BlockActionSynthesize(ACTION) #synthesize ACTION;\
- (IBAction) ACTION:(id)sender {\
if (ACTION) ACTION(sender);\
}
Now to create a new action, all you need to do is replace the #property ... in the header with the following (for example):
BlockActionProperty(testAction);
and "synthesize" it in implementation with:
BlockActionSynthesize(testAction);
At anytime if you want to override this and use the normal action method, all you need to do is synthesize and implement the action as usual.
This is faster (and in my view cleaner) than doing it at runtime, and since the IBAction is defined Interface Builder can "see" its definition.
Here you go, a hack to allow any block-typed property to be used as an action: http://gist.github.com/589740
It is, as you say, of academic curiosity. I really don’t recommend using it for reals.
Also, it doesn’t strictly live up to your requirement, since the action is declared in an unimplemented category. This is purely so that Interface Builder can find it automatically by scanning headers. You can delete that and add the action manually in IB’s inspector, but that seems like a loss to me since keeping it in sync properly is harder that way.
Without resorting to something like "Put the code that would normally be in cancelButtonPress: in forwardInvocation:," you can't. Interface Builder actions send messages. Calling a block cannot be the direct result of an action message.
It is possible to extend a control so that it calls a block instead of sending a normal action method to your controller, but that would require much more code, and it wouldn't magically make Interface Builder support it.
In winforms/C# most all UI Controls have a .Tag tag, so like myButton.Tag = myObject; where the Tag property is an 'object' type so you can basically store any type of object. How might I accomplish this in Objective-C/Cocoa? do all UI elements have something like .Tag where I can store an NSObject or something? If so, can you please provide an example. Thanks so much!
Note: I did see the integer .Tag there, but I wanted an object tag. But I guess that doesn't exist. hoo well.
As Georg said, you can associate whatever object to another object using the Objective-C runtime, so you can associate an Object to a control if you really want.
But that is not really how a standard Cocoa program works. Instead, in Cocoa, the Model-View-Controller pattern and the Delegation are the standard idiom, and associating an object directly to a widget or a view is discouraged. Even for a very small program, you would at least create a Model-Controller (called usually the application delegate in the Cocoa jargon) which manages the data, and keep the view composed of the standard controls as is. Then the view and the model-controller interact via target/action and delegation.
Apple has a very nice discussion of design patterns prevalent in Cocoa, see here.
In general, when you move from one API(Winforms/C#) to another API(Cocoa/Objective-C), there are some similarities but also some differences. It is usually worth learning how things are done in that API, rather than trying to shoehorn what you're used to into a new situation. (Just to be clear, I'm not saying which API is inherently better; this discussion goes both ways!)
So, when you are in a situation:
To do X in API A, I know the idiom P works. I now want to do X in API B. How can I directly implement idiom P in API B?
I recommend you to ask
To do X in API B, what should I do? What's the idiom in API B?
instead.
NSControl does have a tag and related setTag: method. It's not used internally so you can store whatever you like in it - it only stores NSInteger values though.
All Cocoa controls inherit from NSControl.
There is the possibility to add a tag, it's an integer if I remember correctly.
This said, I'm pretty sure one never needs this functionality in Cocoa, because it just doesn't work this way.
If you really want to add information you might be interested in the runtime's ability to associate an object with another object.
CALayers have the ability to store arbitrary keys as part of their key-value coding machinery. Example:
CALayer *myLayer = [button layer];
// Storing a value
[layer setValue:#"World!" forKey:#"hello"];
// Retrieving a value
NSLog(#"Hello %#", [layer valueForKey:#"hello"]);
That being said, storing objects against user-interface elements violates the principle of the Model-View-Controller pattern; I would advise against it--a UIView or UIControl subclass would likely be better suited.
Yep. You can add your own property to all UIControls if you like.
Just add the following to your code.
#import <objc/runtime.h>
/* -------- The Following Code adds an objectData property for every UIControl ----------- */
#interface UIControl (UIControlAdditions)
#property (nonatomic, retain) id objectData;
#end
static char const * const ObjectDataKey = "MyObjectDataKey";
#implementation UIControl (UIControlAdditions)
#dynamic objectData;
-(id)objectData {
return objc_getAssociatedObject(self,ObjectDataKey);
}
- (void)setObjectData:(id)newObjectData {
objc_setAssociatedObject(self, ObjectDataKey, newObjectData, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
/* -------- The Above Code adds an objectData property for every UIControl ----------- */
Credits to Ole Begemann: http://oleb.net/blog/2011/05/faking-ivars-in-objc-categories-with-associative-references/
Is there any Aspect-Oriented Objective-C library that I could perhaps use for iPhone development?
There is an old project called AspectCocoa, this might be what you are searching for.
Otherwise Í would suggest rolling your own. Either proxy based AOP by subclassing NSProxy for a change. Or you could do some method swizzling with the quite cool Obj-C run-time function method_exchangeImplementations().
But unless you are looking for a fun exercise, ask yourself what you want to achieve, and if there is an existing perfectly working Objective-C way to do it.
Check out my article about a possible solution:
http://codeshaker.blogspot.com/2012/01/aop-delivered.html
The base idea is to make a hook into the message sending mechanism and force it to the message forwarding route:
So A brief explanation about how it works:
At registration of a method call of a specific class it creates a method wrapper (AOPMethod) object and stores every information in it
about that specific method along with the block that will be used upon
interception.
Changes the implementation of the method to _objc_msgForward or _objc_msgForward_stret respectively using method_setImplementation. This is the point where we route message sending to the forwarding
mechanism. The next time the message is called on the base class, it
will return the _objc_msgForward implementation as if it not found the
implementation. So it starts to resolve it by going through the
message forwarding steps. Nice.
We add the forwardingTargetForSelector: method to the base class using class_addMethod to point to our implementation in the AOPAspect
class. Also we add the original method implementation and selector
(with an extended name to prevent conflicts between classes) to our
AOPAspect instance.
In the forwardingTargetForSelector: method we give back our AOPAspect instance. With this we route the message forwarding from the
base object to our AOPAspect object.
This forwardingTargetForSelector: method will be called again on AOPAspect as we don't have that selector implemented. This case we
return nil, so message forwarding steps further and will check for the
methodSignatureForSelector: and forwardInvocation: methods on
AOPAspect.
In methodSignatureForSelector: we gave back the correct message signature that is already stored in a dictionary in a method wrapper
object.
At the time it arrives to our implementation of forwardInvocation: in AOPAspect we have a fully configured NSInvocation instance and the
only thing we have to do is to change the selector to the extended
version we added to AOPAspect class. Here we can run the blocks
registered for the given method before/after or even instead of the
method call. And of course we can run the original method by calling
[anInvocation invoke].
For simplicity, we just pass the NSInvocation object to the blocks registered for the method, so they can access all arguments and the
return value as well through the getArgument:atIndex: and
getReturnValue: methods.
And that's it. It works with all kind of return types, argument types
and any variation of arguments.
You can find the concrete example on the above link. Please feel free to use it.
The question is old but I discovered this project today and it might be helpful to someone in the future.
https://github.com/steipete/Aspects
Also you might want to check out the library at https://github.com/moszi/AOP-in-Objective-C which is a very simple NSProxy subclass allowing you to intercept the beginning and the end of the method calls.
With this you can even create a proxy class for you objects to make sure messages sent to your object are serialized over one single thread, regardless of the invoking thread.
All still interested people should take a look at https://github.com/mgebele/MGAOP
This seems to be a new project with future potential.
Check out this one https://github.com/pvantrepote/FlexOC
It's an alpha version and uses (for now) the Proxy implementation. It does also dependency injections.
Another one is Aspect Objective-C: https://github.com/tomdalling/AspectObjectiveC
With Objective-C i would suggest to go with the here much used Category- and Delegate-Pattern. These can be more useful than AOP.
Don't try and solve your problems with solutions you learned for other languages.
I made some rudimentary aop pre and post process function on an NSObject category
#implementation NSObject (AOP)
- (void)preprocess:(SEL)sel with:(void (^)(id obj, id param))implementingBlock{
Method m1 = class_getInstanceMethod(self.class, sel);
IMP imp1 = method_getImplementation(m1);
SEL replacement = sel_registerName( [[[NSString stringWithUTF8String:sel_getName(sel)] stringByAppendingString:#"pre"] cStringUsingEncoding:NSUTF8StringEncoding]);
class_addMethod(self.class,replacement, imp1, nil);
method_setImplementation(m1, imp_implementationWithBlock(^(id x, id param){
implementingBlock(x,param);
[x performSelector:replacement withObject:param];
}));
}
- (void)postprocess:(SEL)sel with:(void (^)(id obj, id param))implementingBlock{
Method m1 = class_getInstanceMethod(self.class, sel);
IMP imp1 = method_getImplementation(m1);
SEL replacement = sel_registerName( [[[NSString stringWithUTF8String:sel_getName(sel)] stringByAppendingString:#"post"] cStringUsingEncoding:NSUTF8StringEncoding]);
class_addMethod(self.class,replacement, imp1, nil);
method_setImplementation(m1, imp_implementationWithBlock(^(id x, id param){
[x performSelector:replacement withObject:param];
implementingBlock(x,param);
}));
}
#end
I'm working on a real (it is more than method-swizzling) AOP-Framework for Objective-C. An alpha will be released soon. You can listen to my german presentation on the Macoun'09 conference here:
http://www.macoun.de/video2009ts6.php
If you're still interested in AOP for Objective-C you can send me a mail to negm-awad#cocoading.de or simply visit this site:
aspective-c.com/index.html
in a few weeks. There will be an english version (yup, not translated by me ;-)) of the site and the manual in a few weeks.
https://github.com/eleme/Stinger
Stinger is a high-efficiency library with great compatibility, for aop in Objective-C, using libffi.
I am writing an iPhone application which in numerous places needs to perform non HTTP or FTP networking of a very simple request response type.
I've wrapped all this up into a SimpleQuery class that integrates with the run loop.
SimpleQuery *lookup = [[SimpleQuery alloc] init];
[lookup setDelegate:self];
[lookup doQueryToHost:queryServer port:queryPort query:queryString ];
As you can see the calling object sets itself as a delegate. When the results are complete it then calls a method on the delegate with the results.
[delegate simpleQueryResult:resultString simpleQuery:self];
I am now in a position where I have a user of SimpleQuery that has two types of query so I need to extend SimpleQuery to support this.
I can think of two sensible ways of doing this.
Firstly passing a selector into doQueryString, or a seperate doQueryStringWithSelector.
[lookup doQueryToHost:queryServer port:queryPort query:queryString selector:#SEL ];
Secondly passing a tag into doQueryString so that when the delegate is called it can query the tag, as the simpleQuery is passed, to find out what the results are for.
[lookup doQueryToHost:queryServer port:queryPort query:queryString withTag:tag ];
I'm just wondering which is best from a coding style perspective, the first seems simpler but tagging seems more in keeping with the iPhone SDK and Interface Builder
An option which is used commonly in Apple's code (for example, in UIControl) is to provide both a target object and a selector. This works only if there is a single callback, and is more appropriate than a delegate in that case. (If there are multiple callbacks, then you'll probably have to go with a delegate and the tag approach.)
If you go this route, then you do away with the delegate altogether and instead have a method with a signature like this:
doQueryToHost:(id)queryServer port:(int)queryPort query:(NSString*)queryString target:(id)target action:(SEL)action
Note that "action" is typically preferred over "selector" in methods arguments in this case. The query would simply call the selector on the target when done. This would allow your clients to have multiple selectors, and also multiple target objects; this can help clean up code because you don't need to shove everything into a single delegate object.
If you want to go with your tag route, you should call it "context", which is what Apple uses (for example, in addObserver:forKeyPath:options:context).
There's a third option that's a common pattern in the kits, which is to use #protocols.
For example:
#protocol QueryCompleteHandlerProtocol
- (void)queryType1Complete:(int)intStuff;
- (void)queryType2Complete:(float)floatStuff;
#end
What this does is declare a set of method calls that an object adopting the protocol has to conform to (the compiler will actually enforce this).
So your SimpleQuery object will hold on to something like the delegate pointer, which you might declare like this among the ivars:
NSObject<QueryCompleteHandlerProtocol> *callback;
What this tells the compiler is that callback is an object that descends from NSObject and adopts the QueryCompleteHandlerProtocol protocol. Sometimes you see this written as:
id<QueryCompleteHandlerProtocol> callback;
When you want to call the callback there's nothing special about them, SimpleQuery's methods will just call:
[callback queryType1Complete:1];
[callback queryType2Complete:2.0];
Finally you client for the procotol class will declare itself as adopting the protocol:
#interface MyClass : NSObject<QueryCompleteHandlerProtocol>
...
#end
And will set itself as the callback with some code like:
[lookup setCallback:self];
This is where the compiler checks that MyClass conforms to QueryCompleteHandlerProtocol, meaning it has implemented queryType1Complete: and queryType2Complete:.
I'm not sure I understand the problem here. Can't SimpleQuery's user just set another delegate object for the second query, or branch on the simpleQuery: parameter? That's a basic part of the delegate pattern, just like having two UIActionSheets for one view controller.