method_missing-like functionality in objective-c (i.e. dynamic delegation at run time) - iphone

I'm trying to transform one method call into another dynamically (at runtime).
For instance, I'd like the following:
[obj foo]
to delegate to:
[obj getAttribute: #"foo"]
(I'd like to do this dynamically as I don't know ahead of time what those method names or attributes are going to be).
I see that there's a hook into:
- (id) forwardingTargetForSelector: (SEL) aSelector
That only seems to work for delegation, though, I want to keep the object as "self" and transform the method arguments.
Where should I look for this sort of behavior? Is it even possible in obj-c?

You can use the method -forwardInvocation: for that. It takes a full NSInvocation object which represents the method call, and you can handle it however you wish. If you do this, you should also override -methodSignatureForSelector: to return the correct NSMethodSignature (required for -forwardInvocation: to work on unknown selectors). It's also recommended that you override -respondsToSelector: to declare that you can handle the selector in question.

Related

Best way to do init without repeating code?

Each view class has multiple init methods - ones already included as part of UIView, and then additional ones - and each of them set up the same elements in the same way. I therefore usually have them all running a [self initialSetup]; method, which includes the setting up of all of these elements.
The problem i've ran into is that if a subclass also has an initialSetup method, it would override the superclass initialSetup method, and thus the superclass would have to have the method be public in order to still function. This causes problems with organisation, as the method should never be called other than from init, so has no reason to be public.
You've hit upon a problem that there's no perfect fix for. What you'd ideally have is a method that can't be subclassed in the normal sense, that's accessible only to instances of that exact type of class.
Where this is a risk, the normal practice seems to be to incorporate the class name into the setup method. So instead of initialSetup you'd have something like myViewSubclassInitialSetup.
You can also add something like this at the top of your method:
NSAssert([self isMemberOfClass:[ThisClass class]],
#"IniitalSetup called by sub- or superclass")
Then your debug builds will raise an exception if a subclass or superclass ends up calling your init method. That'll give you a place for a breakpoint and a stacktrace that should allow you to find the problem very quickly.
It won't add any code to your release builds.
Change the name of initialSetup to something like initialSetupClassName - subclasses, even if they accidentally used the same pattern, would not use the same name as they had a different class name.
You can also use an "_" prefix for private methods you would rather not be called, but the subclasser may do that also.
It sounds like you are missing a designated initializer. Designate one initializer as the official one that actually performs the setup, and have all the others just call that with some degree of customization. Usually the designated initializer will be the one with the most detail — for example, if you have init, initWithName:, initWithName:age: and initAsFiveYearOldNamed:, the designated initializer will be initWithName:age: and the other initializers would just call that method with the arguments filled in appropriately.
Unfortunatly Objective C doesn't provide a way to achieve that in a "clean" way. The ideal solution would be a protected method. But that's not possible in Objective C
Apple had this problem, when they were creating the UIGestureRecognizer. There were some methods they really didn't want to get called by somebody, but which had to be overwritten by subclasses. The way they chose to deal with this, was to create a seperate header file (UIGestureRecognizerSubclass.h), that contains a category to the original UIGestureRecognizer with those "protected" methods. The additional header is only to be imported by subclasses (i.e. for subclassing purposes). See UIGestureRecognizer Class Reference for some details.
Of course that doesn't prevent anybody from misusing the additional header file, but at least it clearly states your intention and keeps your code well structured. Also you won't be "bothered" by autocompletion for the additional methods, when just using the class.
Personally I only use an additional header, if it is extremely important that nobody calls it directly. In most cases I think it's ok to use public methods and make a note for what it's inteded. The iOS Framework also has many of these cases. F.e. many methods of UIViewController's viewDidLoad etc.

Can someone tell me the difference between the call in IOS

I have a method called Display. Can somebody explain me the difference of calling the same method in the following two ways.
[self Display];
[self performselector:#selector(Display)]
- (void)Display {
NSlog(#"Data");
}
both are basically the same with one minute difference.. #selector gives a name to your method which you can pass around as an attribute to other objects or in other function calls.
Like if you want to send a message to other object and you want to send display as an attribute then you will have to give it a name using #selector and thus you can send it.. its a pretty vague concept.. hope this helps.
and to quote apple documents...
"However, the performSelector: method allows you to send messages that
aren’t determined until runtime. A variable selector can be passed as
the argument:
SEL myMethod = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector:myMethod];
The aSelector argument should identify a method that takes no
arguments. For methods that return anything other than an object, use
NSInvocation."
[self Display] is shorter and easier to read, write and comprehend.
[self performSelector:#selector(Display)] makes it possible to execute arbitrary selectors. If you save the selector in a variable, then you can execute it later on without knowing the method you invoke. It is therefore more flexible. Even better: you can pass selectors and objects to other objects and let them invoke it for you when necessary. An example why you want to use this is the NSUndoManager which simple invokes a selector to undo an action if the user executes the Undo command.
I do not think that there is a big difference between examples you provided, but perform selector is very useful when you for instance wanna move execution of your method to the background thread.
[self Display]; is a call to a known method on a known object.
It's easy to give it some params if your want : [self DisplayWithParam1:(NSString*)aString param2:(int)aNumber param3:(NSDictionary*)aDict
[self performselector:#selector(Display)] is a call that allows you to call a possibly not known method on a possibly not known object type.
Let's imagine you have many kind of classes that all respond to a given protocol that require to have the Display method implemented. You put some objects of thoses different classes in an NSMutableArray. When parsing the array later, you will get id typed objects.
So calling[myArrayObject Display]; will work at runtime but will generate a warning at compile time as id does not support any method of course, even if you know that this object supports the method.
To prevent thoses warning, call [myArrayObject performselector:#selector(Display)];.
The problem with that call is that is harder to pass some parameters.
performSelector:withObject:withObject:
Sends a message to the receiver with two objects as arguments.
- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject
Parameters
aSelector
A selector identifying the message to send. If aSelector is NULL, an NSInvalidArgumentException is raised.
anObject
An object that is the first argument of the message.
anotherObject
An object that is the second argument of the message
Return Value
An object that is the result of the message.
Discussion
This method is the same as performSelector: except that you can supply two arguments for aSelector. aSelector should identify a method that can take two arguments of type id. For methods with other argument types and return values, use NSInvocation.
Availability
Available in Mac OS X v10.0 and later.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html
The #select call is faster. Generally the uglier (and less dynamic) the code you have in Objective-C, the faster it runs. Here, the selector call bypasses the usual call to objc_msgSend().
I wouldn't recommend writing code like this if you can avoid it. Selectors are somewhat common in Cocoa, but if you're using it for a speedup it's really not worth it. objc_msgSend() is highly optimized and very fast.

vs [mpk5 weaponAttachments]

I'm able to make the method for the call [self weaponAttachments:mpk5] but I don't like having to call self. I think [mpk5 weaponAttachments] is more natural and is easier to read.
The problem I'm having is I need to pass in the weapon (mpk5) in order to use it, which I can do with the first method but not with the second one. Does this mean that I need to subclass NSDictionary in order to be able to use a statement like [mpk5 weaponAttachments]? If so, how do I get ahold of the caller "mpk5" so that I can use it inside the method?
EDIT
I apologize for not putting this in the first time but my objective is to have [mpk5 weaponAttachments] return an NSDictionary or NSArray. Right now I have NSDictionary *attachments = [self weaponAttachments:mpk5]; which works but it just doesn't seem like the best approach.
So firstly, your two calls are a little mixed up:
[self weaponAttachments:mpk5] calls the weaponAttachments method, passing in the variable mpk5.
But [mpk5 weaponAttachments] is either asking the mpk5 object to return the weaponAttachments property or is asking the mpk5 object to run a method called weaponAttachments (I'm simplifying here - it's always a method, but if you're using properties you probably won't realise this as Objective-C will create them for you).
These are fundamentally different things.
On to the brunt of your question:
I don't like having to call self
...unfortunately, if you're working in an object-oriented language you're going to have to get used to this. Say I have a class called mySimpleClass, and a method inside that class called doSomething. Writing this:
[mySimpleClass doSomething] would be what we call a static method. Whereas calling [self doSomething] from within an instance of mySimpleClass would be an instance method.
If you're unsure of the difference between static and instance methods you should probably step back and take a look at some of the basic guides out there.

performSelector:withObject:, but not with an object

I want to do performSelector:withObject: but where the object is a CGFloat. So it's not actually an object. How can I do this?
the object I am performing the selector on is not mine, I can't modify it.
eg
[xyz performSelector:#selector(setOffset:) withObject:2];
(after posting I changed what I need to slightly to this:
[xyz performSelector:#selector(setOffset:) withObject:CGSizeMake(2,0)];
If you're trying to invoke an arbitrary selector against an object you don't have control over, you could use an NSInvocation to set up the selector, target, and arguments, and obtain the return value after the method has been executed.
Generally, though, there are simpler solutions.
try use IMP (A pointer to the start of a method implementation.)
SEL setOffsetSEL = #selector(setOffset:);
IMP setOffsetIMP = [XYZClass instanceMethodForSelector:setOffsetSEL];
setOffsetIMP(xyz, setOffsetSEL, 2);
You need an object to message. When I've needed to do something like this, I'll create a simple container class, shove the data in an instance and then perform a selector (often #selector(doIt:)) when needed.
If you can target 4.x, you can use blocks for this, too, typically.
(Without knowing more about what exactly you are trying to do, hard to get any more specific.)
object passed is a CGFloat. So it's not actually an object.
As you wrote immediately after, if you're passed an object, it can't be a CGFloat, as CGFloat is a typedef'ed primitive (float or double).
If you've been passed a number value as an object, likely you were passed an NSNumber somehow.
With zero context to your question, there's no way to be sure.
You can use:
[NSNumber numberWithFloat:(float)value]

Call back style

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.