Let’s start with two exotic strings (console output is in the code comments):
NSString* apples = NSGetFrenchWord(); NSString* oranges = NSGetFrenchWord(); NSLog(@"apples == '%@'", apples); //apples == 'café' NSLog(@"oranges == '%@'", oranges); //oranges == 'café'
They look identical, but looks can be deceiving.
NSLog(@"isEqual? %@", [apples isEqual:oranges] ? @"YES" : @"NO"); //isEqual? NO NSLog(@"[apples length] == %lu", [apples length]); //[apples length] == 4 NSLog(@"[oranges length] == %lu", [oranges length]); //[oranges length] == 5
So you’re implementing a new notification and you want the name to be a constant. Easy, right?
const NSString* VTMyNewNotification;
If that’s how you do constants, you’re not doing it quite right. Try assign a new value to the alleged constant and watch in horror as the compiler doesn’t stop you.
This is because when you type const NSString*, the compiler interprets that as a pointer to a constant NSString. NSString is already an immutable object, so making a constant NSString doesn’t do anything except maybe cause some compiler errors/warnings later when you try to use it. What you’re really after is a constant pointer to an NSString. It’s ever so subtly different, and written like so:
NSString* const VTMyNewNotification;
Don’t feel bad. It’s a common mistake. I used to do it until Rob Napier schooled me, and now I’m passin’ on the learnin’ to you.
Consider the following if statement:
if(dragOperation != NSDragOperationCopy && NSPointInRect(currentMouseLocation, self.bounds)){
//do something
}
Even though you may have worked out what the condition represents, it probably took you a little longer than it should. It’s complicated, making it time consuming to read, and prone to bugs upon modification. Thankfully, there is an easy remedy:
Read full post →
The ternary conditional operator (?:) can be used as a short-hand version of an if statement. It is a feature of many languages.
For example, this code:
int height;
if(isTall)
height = 50;
else
height = 10;
can be better written as:
int height = isTall ? 50 : 10;
The ?: operator is good for replacing very simple if statements, but is bad for complicated if statements as it can harm readability.
Can you tell what is wrong with the abstraction in this class interface?
@interface EmployeeList -(void) addObject:(Employee*)anEmployee; -(void) removeObject:(Employee*)anEmployee; -(NSUInteger) numberOfEmployees; @end
Here is the answer:
Read full post →
Having one exit point (return) from a function is a good thing. Here is an example of a single exit point:
int MyArray::indexOfElement(int elementToFind){
int foundIndex = ELEMENT_NOT_FOUND;
for(int i = 0; i < m_numberOfElements; ++i){
if(this->elementAtIndex(i) == elementToFind){
foundIndex = i;
break;
}
}
return foundIndex;
}
Having multiple exit points can be bad. Here is an example of multiple exit points:
int MyArray::indexOfElement(int elementToFind){
for(int i = 0; i < m_numberOfElements; ++i){
if(this->elementAtIndex(i) == elementToFind){
return i;
}
}
return ELEMENT_NOT_FOUND;
}
Why are multiple exit points bad? Because I say so. They are also bad for these two reasons: