Objective C - Which syntax? - objective-c

What syntax do you think is better/more readable?
if(!myViewController.view.superview)
or:
if(myViewController.view.superview == nil)
Thanks!!

The two are very close, it comes down to personal taste or the conding standards of the project in question.
Saying !myViewController.view.superview meaning "no superview" is very clear.
Saying myViewController.view.superview == nil meaning superview is nil is also very clear.
I'd probably favor the former since if I was writing in English, I'd say:
if there is no superview then
I wouldn't say
if the superview is nothing then
But they are so close, and entirely equivalent, that it is hardly worth even being consistent with. Don't get me wrong, I'm all for consistency in general, it is just there really is no difference in readability between the two.

I use the second form because the intention is more clear that way.

Here is a link to Google's Objective C coding standards:
http://google-styleguide.googlecode.com/svn/trunk/objcguide.xml
They don't explicitly say which way they prefer but they do say to only use nil for logic checks, of which your example above would qualify.

Personally for a long time I used the latter expression, but reversed. Using "foo == nil" (or nil == foo, to avoid bugs caused by forgetting one '=') is more pedantic. Eventually you will get tired of typing it, and the first version is also immune to the accidental nil assignment bug.
It's good for new coders to be verbose in what they're coding, as it provides practise at forcing them to think about what's really going on, but later, of course switch to a version that is faster if it is equivalent.
If for some insane reason, nil pointers were not 0 anymore, but some other invalid value (there's entire gigantic regions of memory which are invalid as pointers), then using '!' wouldn't work anymore, but that will never happen (or if it did, they'd add support to the compiler to overload '!' so that it meant "not invalid" when used with an object pointer and would do the right thing anyway, or else the Objective-C developers of the world would go crazy).
The only subtle problem with this is that it can start to train you to confuse the value of C's boolean expressions with the values of other types, which they aren't the same thing. So, if you start to think a boolean expression is just a BOOL, say, you might assume that assigning any non-zero value to a BOOL variable will do what you want, but it won't. Since a BOOL is just a char (currently), if you do something like:
- (BOOL)checkFoo {
BOOL foo = [bar count]; // imagine count is > 255
if(foo)
[self doSomething];
return foo;
}
where implicitly casting 256 or higher to BOOL gets you zero (NO) by truncation, not YES, which is what you want, versus
- (BOOL)checkFoo {
BOOL foo = ([bar count] > 0);
if(foo)
[self doSomething];
return foo;
}
or
- (BOOL)checkFoo {
if([bar count]) {
[self doSomething];
return YES;
}
return NO;
}
All I'm saying is, make sure you understand the background and the subtleties.

Related

Explicit check in method returning if object is nil?

If I have a method like below:
-(BOOL)shouldResize {
return _view != nil;
}
where _view is a pointer to an object, is the explicit nil check necessary/recommended, or is it sufficient to simply do:
-(BOOL)shouldResize {
return _view;
}
I'm wondering if any strange behavior might pop up in casting the pointer to a BOOL, like in the example here: https://developer.apple.com/documentation/objectivec/bool?language=objc
(I guess you could also do return !!_view, right?)
Depending on platform or architecture, BOOL may be equivalent to signed char. Therefore, return _view is not safe. The actual pointer value of _view will be truncated to a single byte. This byte is quite likely to be 0 even if _view is not nil. In that case, the code would return false when it should be true.
return _view != nil is safe and reasonable. Using return !!_view is correct and may or may not be suitable depending on the coding standards of your team. In some places it's the idiomatic way of "normalizing" a boolean expression. Others may find it too-clever-by-half and "ugly" (as expressed in other answers here).
I prefer "return _view != nil" for readability. The method returns a boolean and so I prefer that that is obvious from the code in the method.
In your case the second option (return _view) will work too.
"return !_view" I find ugly.
The type BOOL is defined differently in 32 bit and 64 bit modes, so the behaviour is different. Therefore returning _view instead of _view != nil is a bug.
Take a hint from Swift (which you will have to do soon anyway). In Swift, self.view != nil would be the only legal way. Thank heavens.
As an example how dangerous being clever can be, "return !_view" is not just ugly, it is wrong. It does the opposite of what was requested.
Simply returning the View will automatically handle if the view is nil or not. If its nil it will return 'NO' and 'YES' otherwise.So the second version of the shouldResize is enough.
As per me the best practice is to have an explicit nil check in order to have a clear understanding, better maintainability and avoid surprise.

Try to understand the Objective-C block example

I read some Objective-C code example, and found some code which uses "block" in the the code. I simplify the example a bit so that it is easy to describe.
Given a block in Objective-C
(void)(^myblock)(int num) = ^{
//do something
}
// somewhere in the code
if(myblock) myblock(3);
// do something
My question:
What is the if(myblock) here?
From the protocol of the block which is return void
I would like someone can explain what is the if(myblock) here for?
First of all: Your example is syntactically incorrect. It should be:
void(^myblock)(int num) = // No parenthesis around void
^{
//do something
}
To your Q:
While it is legal to send a message to a nil object reference, it is illegal to call a NULL block pointer. Please, keep in mind that blocks are an extension to (plain) C and such a call would be a dereference of a NULL pointer, which is illegal in C. Therefore such a code would cause a NULL pointer exception. (On OS X EXC_BAD_ACCESS):
void(^myblock)(int num) = NULL;
myblock(3);
Obviously the developer of the snippet could not guarantee that myblock is different from NULL, so he has to check for it. (Or he is simply afraid of this possibility. In such a case I would prefer to have an exception or at least a log message. However, you find that kind of code fuses, that makes things worse instead of better, many, many times.)
It simply tests if myblock is not nil
myblock is a pointer to the lambda function in modern terminology, it's just kind of hidden by the opaque syntax ObjC uses.
So the if tests if the pointer isn't nil. Whether or not that makes sense or if it's superfluous depends on the missing code. Maybe it overwrote the pointer to nil depending on some condition.

Objective-c pointers magic. Type protection

I have a dictionary.
I extract one of its values as follows:
NSString *magicValue= [filterDict valueForKey:[filterDict allKeys][0]];
[SomeClass foo: magicValue];
And foo is:
- (void)foo:(NSString*)magicValue
{
NSLog("magicValue is string:%#",[magic isKindOfClass:[NSString class]] ? #"YES" : #"NO");
NSLog("magicValue is number:%#",[magic isKindOfClass:[NSNumber class]] ? #"YES" : #"NO");
}
If the dictionary value is number magicValue will be NSNumber. So the defined string pointer will be pointing to an NSNumber. The log will return yes for the number check.
I never added protection to such methods, to check what class "magicValue" is. I assumed that when I define a method with string parameter it will be string.
Should I start accounting for such behavior and always add checks, or is it the fault of the guy that assigned that dictionary value to magic in such a way and used my method. I need some best practices advice and how to handle this.
This question could have already been answered but I didn't know how to search for it.
Short answer: No, do not check that, if there is no special reason.
Long answer:
You have to differentiate between two cases:
A. Using id
You have a variable or a return vale of the type id. This is in your example -valueForKey:. The reason for that typing is to keep the method generic. Even it is theoretically possible, in practice a type mismatch in such situation is very rare and detected fast in development. With a different motivation I asked the audience (>200) in a public talk, how many times they had such a typing error in production. For all listeners, all of their apps in all of the app's versions there was 1(in words: one!) case. Simply forget about that risk. It is the anxiety of developers using statically typing languages (Java, C++, Swift).
B. Wrong assignment
If you do not have an id type, it is still possible to do such tricks. (And sometimes you want to do that. That is a strength of dynamic typing.) There are two subcategories:
You can do it implicitly:
NSString *string = [NSNumber numberWithInt:1];
The compiler will warn you about that. So everything is fine, because the developer will see his mistake. You do not have to protect him or your code.
One can do it explicitly:
NSString *string = (NSString*)[NSNumber numberWithInt:1];
In such a case, code can break. But he did it explicitly. If it is wrong, the developer had criminal energy to do so and you do not have to protect him from himself.
Most of the time you should know what class you're referencing, or at least what you intend it to be. On the occasions where you have an uexpected class which can cause a crash depending on what messages you send to it, you can then debug your code and get the correct reference.
There are times, usually when dealing with inheritance, when you need to determine the class at runtime rather than at compile time. This is when, isKindOfClass: can be useful. If you know that a value could be one of many classes, I would extract it as an id and then cast it at the last moment e.g.
id value = [[NSUserDefaults standardUserDefaults] valueForKey:aKey];
if ([value isKindOfClass:[MyClass class]]) {
// Do one thing
}
else {
// Do another
}

Set a BOOL right after checking it

I'm working through someone else's codebase and there are several lines like this:
if (self.aBooleanProperty) {
self.aBooleanProperty = YES;
// Do some stuff
}
Is there any point to setting it to YES right after checking it? Is there something I'm missing here?
if (self.aBooleanProperty) {
self.aBooleanProperty = YES;
// Do some stuff
}
In properly written code, you aren't missing anything and that setter line increases the billable lines of code by one with a no-op.
There are two reasons, though, that this could be done for misguided reasons.
As #HotLicks said, there may be side effects to the setter that might need to be triggered. But they should have been triggered on set unless the developer had the misguided notion of setting the ivar directly everywhere and then using the above to coalesce the cost of setting to one spot. But that'd be a remarkably fragile and silly thing to do.
The other reason is because, traditionally, Objective-C's BOOL is a glorified char. Only it isn't so glorified. Thus, comparing a BOOL to YES is actually dangerous because YES has an explicit value.
BOOL mmmmmK = 2; // this is valid
if (mmmmmK == YES) { /* this won't execute */ }
Sort of like when climbing a cliff and something starts falling, you don't yell "bottle", "shoe", "pebble", or "prosthetic limb", but you always yell ROCK.
So, maybe the developer was thinking of normalizing the affirmative with an explicit YES. Again, quite doubtful and, even if that is the case, then it should raise suspicion about the quality of the rest of the codebase.
Ouch.
This is difficult to tell without having more code. I think everybody will agree the code appears to be wrong, however, what we are seeing is an obj-c property - the previous programmer could do some "clever" thing, e.g. it's possible that the getter of aBooleanProperty sets itself to NO when you call it.
Before modifying the code, check the getters. This reminds me of schrödinbug
I think the person miswrote YES, instead should've written NO as it already is YES when it checked in the condition. Or otherwise there isne any point to that line.
if
self.aBooleanProperty = YES;
is included in the braces,it is not needed and if it is
self.aBooleanProperty = NO;
is included ,then it is logical

Sending a message to nil in Objective-C

As a Java developer who is reading Apple's Objective-C 2.0 documentation: I wonder what "sending a message to nil" means - let alone how it is actually useful. Taking an excerpt from the documentation:
There are several patterns in Cocoa
that take advantage of this fact. The
value returned from a message to nil
may also be valid:
If the method returns an object, any pointer type, any integer scalar
of size less than or equal to
sizeof(void*), a float, a double, a
long double, or a long long, then a
message sent to nil returns 0.
If the method returns a struct, as defined by the Mac OS X ABI Function
Call Guide to be returned in
registers, then a message sent to nil
returns 0.0 for every field in the
data structure. Other struct data
types will not be filled with zeros.
If the method returns anything other than the aforementioned value
types the return value of a message
sent to nil is undefined.
Has Java rendered my brain incapable of grokking the explanation above? Or is there something that I am missing that would make this as clear as glass?
I do get the idea of messages/receivers in Objective-C, I am simply confused about a receiver that happens to be nil.
Well, I think it can be described using a very contrived example. Let's say you have a method in Java which prints out all of the elements in an ArrayList:
void foo(ArrayList list)
{
for(int i = 0; i < list.size(); ++i){
System.out.println(list.get(i).toString());
}
}
Now, if you call that method like so: someObject.foo(NULL); you're going to probably get a NullPointerException when it tries to access list, in this case in the call to list.size(); Now, you'd probably never call someObject.foo(NULL) with the NULL value like that. However, you may have gotten your ArrayList from a method which returns NULL if it runs into some error generating the ArrayList like someObject.foo(otherObject.getArrayList());
Of course, you'll also have problems if you do something like this:
ArrayList list = NULL;
list.size();
Now, in Objective-C, we have the equivalent method:
- (void)foo:(NSArray*)anArray
{
int i;
for(i = 0; i < [anArray count]; ++i){
NSLog(#"%#", [[anArray objectAtIndex:i] stringValue];
}
}
Now, if we have the following code:
[someObject foo:nil];
we have the same situation in which Java will produce a NullPointerException. The nil object will be accessed first at [anArray count] However, instead of throwing a NullPointerException, Objective-C will simply return 0 in accordance with the rules above, so the loop will not run. However, if we set the loop to run a set number of times, then we're first sending a message to anArray at [anArray objectAtIndex:i]; This will also return 0, but since objectAtIndex: returns a pointer, and a pointer to 0 is nil/NULL, NSLog will be passed nil each time through the loop. (Although NSLog is a function and not a method, it prints out (null) if passed a nil NSString.
In some cases it's nicer to have a NullPointerException, since you can tell right away that something is wrong with the program, but unless you catch the exception, the program will crash. (In C, trying to dereference NULL in this way causes the program to crash.) In Objective-C, it instead just causes possibly incorrect run-time behavior. However, if you have a method that doesn't break if it returns 0/nil/NULL/a zeroed struct, then this saves you from having to check to make sure the object or parameters are nil.
A message to nil does nothing and returns nil, Nil, NULL, 0, or 0.0.
All of the other posts are correct, but maybe it's the concept that's the thing important here.
In Objective-C method calls, any object reference that can accept a selector is a valid target for that selector.
This saves a LOT of "is the target object of type X?" code - as long as the receiving object implements the selector, it makes absolutely no difference what class it is! nil is an NSObject that accepts any selector - it just doesn't do anything. This eliminates a lot of "check for nil, don't send the message if true" code as well. (The "if it accepts it, it implements it" concept is also what allows you to create protocols, which are sorta kinda like Java interfaces: a declaration that if a class implements the stated methods, then it conforms to the protocol.)
The reason for this is to eliminate monkey code that doesn't do anything except keep the compiler happy. Yes, you get the overhead of one more method call, but you save programmer time, which is a far more expensive resource than CPU time. In addition, you're eliminating more code and more conditional complexity from your application.
Clarifying for downvoters: you may think this is not a good way to go, but it's how the language is implemented, and it's the recommended programming idiom in Objective-C (see the Stanford iPhone programming lectures).
What it means is that the runtime doesn't produce an error when objc_msgSend is called on the nil pointer; instead it returns some (often useful) value. Messages that might have a side effect do nothing.
It's useful because most of the default values are more appropriate than an error. For example:
[someNullNSArrayReference count] => 0
I.e., nil appears to be the empty array. Hiding a nil NSView reference does nothing. Handy, eh?
In the quotation from the documentation, there are two separate concepts -- perhaps it might be better if the documentation made that more clear:
There are several patterns in Cocoa that take advantage of this fact.
The value returned from a message to nil may also be valid:
The former is probably more relevant here: typically being able to send messages to nil makes code more straightforward -- you don't have to check for null values everywhere. The canonical example is probably the accessor method:
- (void)setValue:(MyClass *)newValue {
if (value != newValue) {
[value release];
value = [newValue retain];
}
}
If sending messages to nil were not valid, this method would be more complex -- you'd have to have two additional checks to ensure value and newValue are not nil before sending them messages.
The latter point (that values returned from a message to nil are also typically valid), though, adds a multiplier effect to the former. For example:
if ([myArray count] > 0) {
// do something...
}
This code again doesn't require a check for nil values, and flows naturally...
All this said, the additional flexibility that being able to send messages to nil does come at some cost. There is the possibility that you will at some stage write code that fails in a peculiar way because you didn't take into account the possibility that a value might be nil.
From Greg Parker's site:
If running LLVM Compiler 3.0 (Xcode 4.2) or later
Messages to nil with return type | return
Integers up to 64 bits | 0
Floating-point up to long double | 0.0
Pointers | nil
Structs | {0}
Any _Complex type | {0, 0}
It means often not having to check for nil objects everywhere for safety - particularly:
[someVariable release];
or, as noted, various count and length methods all return 0 when you've got a nil value, so you do not have to add extra checks for nil all over:
if ( [myString length] > 0 )
or this:
return [myArray count]; // say for number of rows in a table
Don't think about "the receiver being nil"; I agree, that is pretty weird. If you're sending a message to nil, there is no receiver. You're just sending a message to nothing.
How to deal with that is a philosophical difference between Java and Objective-C: in Java, that's an error; in Objective-C, it is a no-op.
ObjC messages which are sent to nil and whose return values have size larger than sizeof(void*) produce undefined values on PowerPC processors. In addition to that, these messages cause undefined values to be returned in fields of structs whose size is larger than 8 bytes on Intel processors as well. Vincent Gable has described this nicely in his blog post
I don't think any of the other answers have mentioned this clearly: if you're used to Java, you should keep in mind that while Objective-C on Mac OS X has exception handling support, it's an optional language feature that can be turned on/off with a compiler flag. My guess is that this design of "sending messages to nil is safe" predates the inclusion of exception handling support in the language and was done with a similar goal in mind: methods can return nil to indicate errors, and since sending a message to nil usually returns nil in turn, this allows the error indication to propagate through your code so you don't have to check for it at every single message. You only have to check for it at points where it matters. I personally think exception propagation&handling is a better way to address this goal, but not everyone may agree with that. (On the other hand, I for example don't like Java's requirement on you having to declare what exceptions a method may throw, which often forces you to syntactically propagate exception declarations throughout your code; but that's another discussion.)
I've posted a similar, but longer, answer to the related question "Is asserting that every object creation succeeded necessary in Objective C?" if you want more details.
C represents nothing as 0 for primitive values, and NULL for pointers (which is equivalent to 0 in a pointer context).
Objective-C builds on C's representation of nothing by adding nil. nil is an object pointer to nothing. Although semantically distinct from NULL, they are technically equivalent to one another.
Newly-alloc'd NSObjects start life with their contents set to 0. This means that all pointers that object has to other objects begin as nil, so it's unnecessary to, for instance, set self.(association) = nil in init methods.
The most notable behavior of nil, though, is that it can have messages sent to it.
In other languages, like C++ (or Java), this would crash your program, but in Objective-C, invoking a method on nil returns a zero value. This greatly simplifies expressions, as it obviates the need to check for nil before doing anything:
// For example, this expression...
if (name != nil && [name isEqualToString:#"Steve"]) { ... }
// ...can be simplified to:
if ([name isEqualToString:#"Steve"]) { ... }
Being aware of how nil works in Objective-C allows this convenience to be a feature, and not a lurking bug in your application. Make sure to guard against cases where nil values are unwanted, either by checking and returning early to fail silently, or adding a NSParameterAssert to throw an exception.
Source:
http://nshipster.com/nil/
https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocObjectsClasses.html (Sending Message to nil).