for
loop caught my eye. You know the kind:for (int i = 0; i < someArray.length; i++) {It turns out that if
// do something with someArray[i]
}
someArray
is an NSArray
, there is API defined to help with this:[someArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {Note: Yes, I'm aware that there is also syntax for this in Objective-C 2.0, in the form of fast enumeration. The code I was converting was specifically interested in returning the index of a particular object in the array, which is why I went with this form.
// do something with obj
// set stop to true if you want to skip the remaining objects for some reason
}];
Anyway, further reading in the
NSArray
API led me to another fun method: indexOfObjectPassingTest
. It also takes a block, which returns a boolean value indicating whether or not the current object passes the test. If it does, you get the index back and move on with your life. This turned out to be exactly what I needed to port the original bit of code to full modernity.I also came across an example of code that was using
NSString +stringWithFormat
. It would create the original format string, conditionally modify it based on the presence of some optional data, then pass all available data in to format the final string. Something like this:NSString *formatString = @"required: %@";This seemed potentially error-prone to me; I didn't like the idea of always passing in the (potentially nil) optional data, even if I was convinced there would be no placeholder for it in the format string.
if (optionalData) {
formatString = [formatString stringByAppendingString:@", optional: %@"];
}
NSString *result = [NSString stringWithFormat:formatString, requiredData, optionalData];
A quick read through the
NSString
class reference led to the instance method stringByAppendingFormat
. This allowed for a workflow more like the following:NSString *result = [NSString stringWithFormat:@"required: %@", requiredData];This way I did not have to dance around getting the format string just right before populating it; I could tack on the extra bits on the fly, which just seems cleaner.
if (optionalData) {
result = [result stringByAppendingFormat:@", and optional:%@", optionalData];
}