Is using respondsToSelector: good style? - objective-c

Is it "better style" to send a message and hope the object responds, or to check to see if it responds to a selector and have some sort of fallback if it doesn't.
For example:
- (NSString *)stringForObjectValue:(id)obj {
if ([obj respondsToSelector:#selector(intValue)]) {
NSString *roman = [self formatRomanNumber:[obj intValue] resultSoFar:#""];
return roman;
} else {
return [NSString stringWithFormat:#"can't format a %#", [obj class]];
}
}
vs.
- (NSString *)stringForObjectValue:(id)obj {
NSString *roman = format_roman(#"", [obj intValue]);
return roman;
}
(the example is from a NSNumberFormatter subclass...but it could be from a NSObjectFormatter subclass...)

If you're not 100% sure that all instances that come to your (stringForObjectValue) function respond to selector then you must perform that check to avoid crashes in runtime.
How to handle the cases when obj does not respond to intValue selector may depend on particular context where your method is used. For example you may return nil object from method in that case so you can easily see that something went wrong

If you don't know the exact type then using respondsToSelector: is definitely good style, because you risk an exception otherwise. And it's so important that there's a name for this technique: Duck Typing.

Related

What's the best way to protect against 'unrecognized selector' for objects returned from NSDictionary

I have the following bit of code where I'm getting a response from the server and trying to parse out error messages.
I notice that on occasion the message object isn't returning as type NSDictionary and will crash the application. I'm wondering what the best practice is to protect against that? In general I try to avoid doing instanceof checks. Likewise has selector checks. It feels like there should be a better way to do this than explicitly check I'm allowed to be using those methods / getting back type that I expect.
NSDictionary *message = [serverErrorJSON objectForKey:#"message"];
if (message != nil) {
return [message objectForKey:#"form"];
}
if ([serverErrorJSON isKindOfClass:NSDictionary.class]) {
return serverErrorJSON[#"message"][#"form"];
}
return nil;
Its good to use the literal syntax both syntactically and programatically.
You don't have to chain them together either, you might want to use another property of the JSON,
if ([serverErrorJSON isKindOfClass:NSDictionary.class]) {
NSDictionary *message = serverErrorJSON[#"message"];
//...
return message[#"form"];
}
return nil;
Your code:
NSDictionary *message = [serverErrorJSON objectForKey:#"message"];
if (message != nil) {
return [message objectForKey:#"form"];
}
The reason you are getting "unrecognized selector" here is that [serverErrorJSON objectForKey:#"message"] is not returning an NSDictionary as you expect. Since you are calling objectForKey: on that object, the recommended way to handle this is to wrap that call with respondsToSelector: :
id message = nil;
if ([serverErrorJSON respondsToSelector:#selector(objectForKey:)]){
message = [serverErrorJSON objectForKey:#"message"];
if ([message respondsToSelector:#selector(objectForKey:)]){
return [message objectForKey:#"form"];
}
}
This tests for the presence of the selector (method) you are calling, and is safer and more compatible than using isKindOfClass: and the like. It's always better to test for capabilities rather than class names, etc. You don't care if the object is an NSDictionary, you care if it can provide an object for a key using the method signature you are invoking.
The best way to protect against unrecognized selector errors is to check respondsToSelector or isKindOfClass depending on your use case.
Unfortunately your code can get pretty cluttered if you find yourself needing to verify that an object is a dictionary frequently, which can occur in your situation like yours with nested dictionaries in the data structure.
You can clean things up by adding a category:
#interface NSDictionary (Safe)
//Returns objectForKey if dictionary param is valid, else returns nil
+ (id) _safeObjectForKey: (NSString*) key
dict: (NSDictionary*) dictionary;
#end
#implementation NSDictionary (Safe)
+ (id) _safeObjectForKey:(NSString *)key
dict:(NSDictionary *)dictionary {
if ([dictionary isKindOfClass:[NSDictionary class]]) {
return [dictionary objectForKey:key];
}
return nil;
}
#end
and then to use it, given your example:
NSDictionary *message = [NSDictionary _safeObjectForKey: #"message"
dict: serverErrorJSON];
return [NSDictionary _safeObjectForKey:#"form"
dict:message];
You can do something similar for other common unrecognized selector error generators as well, like NSArray's objectAtIndex etc.

Objective C - caller Object of a method [duplicate]

Example: When my method -fooBar gets called, I want it to log in the console which other method of which other class called it.
Right now, I only know how to log the method name of fooBar itself and it's class, with this:
_cmd
[self class]
Is this possible to figure out?
In fully optimized code, there is no 100% surefire way to determine the caller to a certain method. The compiler may employ a tail call optimization whereas the compiler effectively re-uses the caller's stack frame for the callee.
To see an example of this, set a breakpoint on any given method using gdb and look at the backtrace. Note that you don't see objc_msgSend() before every method call. That is because objc_msgSend() does a tail call to each method's implementation.
While you could compile your application non-optimized, you would need non-optimized versions of all of the system libraries to avoid just this one problem.
And this is just but one problem; in effect, you are asking "how do I re-invent CrashTracer or gdb?". A very hard problem upon which careers are made. Unless you want "debugging tools" to be your career, I would recommend against going down this road.
What question are you really trying to answer?
How about this:
NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1];
NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:#" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:#""];
NSLog(#"Class caller = %#", [array objectAtIndex:3]);
NSLog(#"Method caller = %#", [array objectAtIndex:4]);
Credits to the original author, intropedro.
It's not possible in the general case without actually walking the stack. There's not even a guarantee that another object send the message that called the method. For example, it could be called from a block in a signal handler.
NSLog(#"Show stack trace: %#", [NSThread callStackSymbols]);
See backtrace(3).
User the below method
Pass index for which you want to display method and pass -1 if you want to display full stack of method
+(void) methodAtIndex:(int)index{
void* callstack[128];
int frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
if (index == -1) {
for (int i = 0; i < frames; ++i) {
printf("%s\n", strs[i]);
}
}
else {
if (index < frames) {
printf("%s\n", strs[index]);
}
}
free(strs);
}
This information can be obtained using DTrace.
Make a macro that adds the __FUNCTION__ to the function name to the function call. This macro will then call your function with an extra parameter of a char* to the target function.
I was trying to catch who, how and when changes window's size and did some handwork:
- (void)logWindowWidth:(NSString *)whoCalls {
NSLog(#"%#", whoCalls);
NSLog(#"self.window.size.width %f", self.window.size.width);
}
-(void)someMethod {
[self logWindowWidth:#"someMethod - before"];
...
[self logWindowWidth:#"someMethod - after"];
}
-(void)anotherMethod {
[self logWindowWidth:#"anotherMethod - before"];
...
[self logWindowWidth:#"anotherMethod - after"];
}

Objective-C dynamic properties at runtime?

Is it possible to create an Objective-C class that can have an arbitrary number of dynamic properties at runtime?
I want to be able to call mySpecialClass.anyProperty and intercept this inside my class to be able to provide my own custom implementation that can then return an NSString (for instance) at runtime with raising an exception. Obviously this all has to compile.
Ideal would be if I could refer to my properties using something similar to the new literal syntax, e.g. mySpecialClass["anyProperty"].
I guess in a way I want to create something like a dynamic NSDictionary with no CFDictionary backing store, that executes 2 custom methods on property getting and setting respectively, with the property name passed in to these accessor methods so they can decide what to do.
There are at least two ways to do this.
Subscripting
Use objectForKeyedSubscript: and setObject:forKeyedSubscript:
#property (nonatomic,strong) NSMutableDictionary *properties;
- (id)objectForKeyedSubscript:(id)key {
return [[self properties] valueForKey:[NSString stringWithFormat:#"%#",key]];
}
- (void)setObject:(id)object forKeyedSubscript:(id <NSCopying>)key {
[[self properties] setValue:object forKey:[NSString stringWithFormat:#"%#",key]];
}
Person *p = [Person new];
p[#"name"] = #"Jon";
NSLog(#"%#",p[#"name"]);
resolveInstanceMethod:
This is the objc_sendMsg executed by the runtime for all methods:
If you look at the bottom, you have the opportunity to resolveInstanceMethod:, which lets you redirect the method call to one of your choosing. To answer your question, you need to write a generic getter and setter that looks-up a value on a dictionary ivar:
// generic getter
static id propertyIMP(id self, SEL _cmd) {
return [[self properties] valueForKey:NSStringFromSelector(_cmd)];
}
// generic setter
static void setPropertyIMP(id self, SEL _cmd, id aValue) {
id value = [aValue copy];
NSMutableString *key = [NSStringFromSelector(_cmd) mutableCopy];
// delete "set" and ":" and lowercase first letter
[key deleteCharactersInRange:NSMakeRange(0, 3)];
[key deleteCharactersInRange:NSMakeRange([key length] - 1, 1)];
NSString *firstChar = [key substringToIndex:1];
[key replaceCharactersInRange:NSMakeRange(0, 1) withString:[firstChar lowercaseString]];
[[self properties] setValue:value forKey:key];
}
And then implement resolveInstanceMethod: to add the requested method to the class.
+ (BOOL)resolveInstanceMethod:(SEL)aSEL {
if ([NSStringFromSelector(aSEL) hasPrefix:#"set"]) {
class_addMethod([self class], aSEL, (IMP)setPropertyIMP, "v#:#");
} else {
class_addMethod([self class], aSEL,(IMP)propertyIMP, "##:");
}
return YES;
}
You could also do it returning a NSMethodSignature for the method, which is then wrapped in a NSInvocation and passed to forwardInvocation:, but adding the method is faster.
Here is a gist that runs in CodeRunner. It doesn't handle myClass["anyProperty"] calls.
You're asking different things. If you want to be able to use the bracket syntax mySpecialClass[#"anyProperty"] on instances of your class, it is very easy. Just implement the methods:
- (id)objectForKeyedSubscript:(id)key
{
return ###something based on the key argument###
}
- (void)setObject:(id)object forKeyedSubscript:(id <NSCopying>)key
{
###set something with object based on key####
}
It will be called everytime you use the bracket syntax in your source code.
Otherwise if you want to create properties at runtime, there are different ways to proceed, take a look at NSObject's forwardInvocation: method, or look at the Objective-C Runtime Reference for functions to dynamically alter a class...
Guillaume is right. forwardInvocation: is the way to go. This answer gives some more details: method_missing-like functionality in objective-c (i.e. dynamic delegation at run time)
This has even more details: Equivalent of Ruby method_missing in Objective C / iOS
And these are some other lesser known Obj-C features that might help you: Hidden features of Objective-C
Enjoy!

Why is it that sending any selector to a Nil object does nothing, but sending an "invalid" selector to any NSObject raises an exception?

Does anyone know why NextStep/Apple decided to take the "convenient method" of doing nothing when passing a Nil object a message, but the "Java method" of raising an exception when passing an instantiated object an invalid selector?
For example,
// This does "nothing"
NSObject *object = Nil;
[object thisDoesNothing];
object = [[NSObject alloc] init];
// This causes an NSInvalidArgumentException to be raised
[object thisThrowsAnException];
So on one hand, we have the convenience of not having to check for Nil (assuming we don't care too much about the result of the method call)--but on the other hand we have to check for an exception if our object doesn't respond to a method?
If I'm not sure if the object will respond, I either have to:
#try {
[object thisThrowsAnException];
} #catch (NSException *e){
// do something different with object, since we can't call thisThrowsAnException
}
Or,
if([object respondsToSelector:#selector(thisThrowsAnException)]) {
[object thisThrowsAnException];
}
else {
// do something different with object, since we can't call thisThrowsAnException
}
(The latter is probably the better way to do it, since if object is Nil, the selector would NOT raise an exception, thus your code might not behave the way you want it to).
My question is:
WHY did Apple decide to implement it this way?
Why not have the unrecognized selector call to an instantiated object not raise an exception?
Alternatively, why not have the Nil object raise an exception if you try to call a method on it?
I can't fully answer your question, but I can answer part of it. Objective-C allows you to send a message to nil because it makes code more elegant. You can read about this design decision here, and I will steal its example:
Let's say you want to get the last phone number that some person dialed on her office phone. If you can't send messages to nil, you have to write it like this:
Office *office = [somePerson office];
// Person might not have an office, so check it...
if (office) {
Telephone *phone = [office telephone];
// The office might not have a telephone, so check it...
if (phone) {
NSString *lastNumberDialed = [phone lastNumberDialed];
// The phone might be brand new, so there might be no last-dialed-number...
if (lastNumberDialed) {
// Use the number, for example...
[myTextField setText:lastNumberDialed];
}
}
}
Now suppose you can send messages to nil (and always get nil back):
NSString *lastNumberDialed = [[[somePerson office] telephone] lastNumberDialed];
if (lastNumberDialed) {
[myTextField setText:lastNumberDialed];
}
As for why sending an unrecognized selector to an object raises an exception: I don't know for sure. I suspect that it's far more common for this to be a bug than to be harmless. In my code, I only want an unrecognized selector to be silently ignored when I need to send an optional protocol message (e.g. sending an optional message to a delegate). So I want the system to treat it as an error, and let me be explicit in the relatively rare case when I don't want it to be an error.
Note that you can tinker (to some extent) with the handling of unrecognized selectors in your own classes, in a few different ways. Take a look at the forwardingTargetForSelector:, forwardInvocation:, doesNotRecognizeSelector:, and resolveInstanceMethod: methods of NSObject.
From the good ol' documentation:
In Objective-C, it is valid to send a message to nil—it simply has no
effect at runtime.
As for the other problem of the unrecognized selector behavior, an old implementation file of NSObject (from the MySTEP library) shows that the culprit is the NSObject method -doesNotRecognizeSelector:, which looks a bit as follows:
- (void) doesNotRecognizeSelector:(SEL)aSelector
{
[NSException raise:NSInvalidArgumentException
format:#"NSObject %#[%# %#]: selector not recognized",
object_is_instance(self)?#"-":#"+",
NSStringFromClass([self class]),
NSStringFromSelector(aSelector)];
}
Which means that ObjC methods could feasibly be tinkered with so that they do not in fact have to raise an error. Which means the decision was entirely arbitrary, just like the decision to switch to "method-eating" messages to nil. A feat which can be done through method swizzling NSObject (wholly dangerous, as it will raise an EXC_BAD_ACCESS, or EXC_I386_BPT on mac, but at least it doesn't raise an exception)
void Swizzle(Class c, SEL orig, SEL new)
{
Method origMethod = class_getInstanceMethod(c, orig);
Method newMethod = class_getInstanceMethod(c, new);
if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
else
method_exchangeImplementations(origMethod, newMethod);
}
-(void)example:(id)sender {
Swizzle([NSObject class], #selector(doesNotRecognizeSelector:), #selector(description));
[self performSelector:#selector(unrecog)];
}
The category:
#implementation NSObject (NoExceptionMessaging)
-(void)doesNotRecognizeSelector:(SEL)aSelector {
NSLog(#"I've got them good ol' no exception blues.");
}
#end
For everyone's amusement, due to the discussion CodaFi and I were having, here's a quickly-hacked-together way to eat normally unresponded-to messages and have them return nil:
#interface EaterOfBadMessages : NSObject
#end
#implementation EaterOfBadMessages
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature * sig = [super methodSignatureForSelector:aSelector];
if( !sig ){
sig = [NSMethodSignature signatureWithObjCTypes:"##:"];
}
return sig;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
id nilPtr = nil;
[anInvocation setReturnValue:&nilPtr];
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
EaterOfBadMessages * e = [[EaterOfBadMessages alloc] init];
// Of course, pre-ARC you could write [e chewOnThis]
NSLog(#"-[EaterOfBadMessages chewOnThis]: %#", [e performSelector:#selector(chewOnThis)]);
}
return 0;
}
Please don't use this in real life.

How to check object is kind of block or not

How can we identify any particular object is kind of block or not?
for example,
NSSet *set =[NSSet setWithObjects:
#"name1",
#"name2",
[^{ /* ..... some code */ } copy],
nil];
How can we find out which object from set is kind of block?
There is a safer way to determine if something is a block without actually using private api or constructing a class using the private string name:
- (BOOL)isBlock:(id)item {
id block = ^{};
Class blockClass = [block class];
while ([blockClass superclass] != [NSObject class]) {
blockClass = [blockClass superclass];
}
return [item isKindOfClass:blockClass];
}
Wrap your block in a class of your own:
BlockWrapper *blockWrapper = [BlockWrapper wrapperWithBlock:^{ … }];
Check for the type and extract the actual block:
if ([obj isKindOfClass:[BlockWrapper class]]) {
codeBlock = [(BlockWrapper*)obj block];
}
There is no supported way to do this. You must keep track of what objects are blocks, and what their type signatures are.
Do you have a practical use case for a set of mixed strings and blocks?
It's possible, but I wouldn't recommend doing this, because NSBlock is not a public class and its name might change in the future:
if ([obj isKindOfClass:NSClassFromString(#"NSBlock")]) {
NSLog(#"It's a block!");
}
If you only have strings and blocks, just check ![thing isKindOfClass:[NSString class]]. i.e. invert your test.
Likewise, if you have strings, numbers and blocks, check that thing is not a string or a number, and in that case it must (by deduction) be a block. Either that, or your program is incorrect and will crash.
I suppose that ![thing isKindOfClass:[NSObject class]], while not technically correct (you don't have to subclass NSObject), will probably get you want you want.