Returning errors in objective-c - objective-c

Im newish to objective-c and am starting to wonder what is the common/standard/proper way for handling and catching errors?
It seems like it might be possible to use NSError to do this, is that a good idea or a hijack of cocoa?

I'm pretty sure that's what the NSError class is there to do - give details about errors. The most common pattern you'll see is a method that takes a pointer to an NSError object, as in:
- (id)doSomethingWithArgument:(id)arg error:(NSError **)error
The method returns some value (or possibly nil) for the result of doing something, but if the call failed will place an NSError object at the pointer passed with details about the failure. Your documentation is responsible for specifying what gets returned if the method does encounter an error.
The other method that comes to mind is the #throw-#catch block; however, in Objective-C #throwing an exception can be rather computationally expensive, and it's usually only recommended to do so in truly exceptional situations.
Edit: wow, turns out a lot of people have really strong opinions about #throwing exceptions. To sum up the (quite helpful) commentary on the issue:
Throwing exceptions should most often deal with programmer error (situations that should never happen, and the like); exceptions should not be used for ordinary error handling. Instead, use the error method demonstrated above or post instances of NSNotification.
If you do wind up making extensive use of #throw/#catch blocks, be very careful about the logic surrounding them. Objective-C provides a lot of ways to detach methods to run in other threads, or delay execution, etc. Be very careful to account for all those possibilities when you write your code.
Finally, another very valid point:
If you do use the error object passed to a method, the return value should indicate it. Don't try to do both (return a partially valid object and set the error object).

Related

objective-c difference between x.y and [x y]? [duplicate]

I am going through some walkthroughs fpr Objective-C and I got to many places where I raised my eyebrows. I would love to get them down.
Is there a fundamental difference in message sending and method calling? Objective-C lets me do both: object.message yields the same result as [object message]. I think maybe nested messages cannot be created using the dot operator strategy?
I created an NSArray object, now I am about to print results for this using an NSEnumerator:
id myObject = [object objectEnumerator];
in a while loop iterating and printing results. The type of myObject is id, which means it's resolved at runtime and not compile time. I know very clearly what kind of objects are stored in my NSArray—they are NSStrings—so by changing the type of myObject to
NSString * myObject, it works just fine. However, I experimented and found out that myObject can be of any type, be it NSString or NSArray or NSEnumerator, and any of these work just fine, perfectly iterating the NSArray object and yielding the same results.
What's up with that?
I'm not sure what kind of distinction you're trying to make between "message sending" and "method calling", since they're two ways of describing the same thing. The dot syntax is just a shortcut for calling getters and setters, that is:
[foo length]
foo.length
are exactly the same, as are:
[foo setLength:5]
foo.length = 5
You should generally only use the dot syntax when you're using getters and setters; use the square bracket syntax for all of your other method calls.
For your second question: this is how dynamic typing works. Any type declarations you put in your code are hints to the compiler; your Objective-C method calls will always work as long as the objects respond to them.
It's a distinction oriented at the person reading your code. Dot syntax indicates state (I'm accessing an ivar), method syntax indicates behavior (I'm performing some action). To the runtime, both are the same.
I think Apple's intention is to show accessors as an implementation detail you shouldn't worry about. Even when they could trigger side effects (due to some additional code in the accessor), they usually don't, so the abstraction is imperfect but worth it (IMHO). Another downside of using dot notation is that you don't really know if there is a struct or a union behind it (which unlike message sending, never trigger side effects when being assigned). Maybe Apple should have used something different from a dot. *shrugs*
I think maybe nested messages cannot be created using the dot operator strategy?
Dot notation can be used to nest calls, but consider the following:
shu.phyl.we.spaj.da
[[[[[shu]phyl]we]spaj]da]
In this case, the uglier, the better. Both are a code smell because one object is creating dependencies to another object far far away, but if use brackets to pass messages you get that extra horrible syntax from the second line, which makes the code smell easier to notice. Again, convention is to use dots for properties and brackets for methods.
1: Your terminology is incorrect. The dot operator is not "method calling", a different operation. It's just a different visual appearance for message sending. There's no difference between [x y] and x.y. The dot syntax can only take one argument though, as it's intended to be used only for property access.
2: The static (compile-time) type of an object has no effect on its behavior at runtime. Your object is still an NSEnumerator even if you're calling it something else.
1) They're both message sending, just different syntax. [object message] is traditional syntax, object.message is the "dot notation", but means exactly the same thing. You can do some kinds of nesting with dot notation, but you can't do anything with methods that take complex arguments. In general, old hand Obj-C programmers don't use dot notation except for simple accessor calls. IMHO.
2) The runtime is really smart and can figure it out on the fly. The type casting of pointers is really just a clue to the compiler to let you know when you messed up. It doesn't mean a thing (in this case) when the message is sent to the array to fetch a value.
Message sending is the preferred way of doing this. It's what the community uses and reinforces the concept of objects sending messages to one another which comes into play later when you get into working with selectors and asking an object if it responds to a selector (message).
id is basically a pointer to anything. It takes some getting used to but it's the basis for how Objective-C handles dynamic typing of objects. When NSLog() comes across the %# format specifier, it sends a description message to the object that should should replace the token (This is implemented in the superclass NSObject and can be overridden in the subclass to get the desired output).
In the future when you're doing this, you might find it easier to do something like this instead:
for (NSString *s in YourNSArrayInstance) //assuming they are NSStrings as you described
{
NSLog(#"%#", s);
}
Or even simply just:
for (NSString *s in YourNSArrayInstance) //assuming they are NSStrings as you described
NSLog(#"%#", s);
You'll learn to like message sending eventually.

NSKeyedUnarchiver - try/catch needed?

As I understand, the use of #try/#catch blocks is discouraged, because exceptions should only be thrown at unrecoverable, catastrophic errors (refer to this discussion with a nice answer by #bbum: Exception Handeling in iOS).
So I looked through my code and found a #try/#catch block that I don't know how to get rid of:
NSData *fileData = [NSData dataWithContentsOfFile: ....];
NSDictionary *dictionary;
#try {
dictionary = [NSKeyedUnarchiver unarchiveObjectWithData: fileData];
}
#catch (NSException *exception) {
//....
}
#finally {
//...
}
The problem is that (as stated in the documentation) +unarchiveObjectWithData: raises an NSInvalidArchiveOperationException if the NSData doesn't contain a valid archive.
Since the data is provided by a file the user chose, it is not guaranteed that it contains a valid archive, and thus the application would crash if a incorrect file was chosen.
Now two questions:
Why doesnt +unarchiveObjectWithData: just return nil (Edit: and an NSError**) if the archive is not valid (this doesn't seem to qualify as a catastrophic or unrecoverable error).
Is the pattern above correct (using #try)? I have found no method that lets us check if the data contains a valid archive beforehand and have found no possibility to handle this case using the delegate protocol. Antyhing I overlooked?
Note that the code above of course works, I just wonder if its the best practice.
There was a new method added in iOS 9 to NSKeyedUnarchiver that now returns an error:
Swift:
public class func unarchiveTopLevelObjectWithData(data: NSData) throws -> AnyObject?
Objective-C:
+ (nullable id)unarchiveTopLevelObjectWithData:(NSData *)data error:(NSError **)error;
However, this is not backwards compatible with previous versions of iOS, so you will need to check for framework availability.
NSKeyedArchiver is built by Apple. They control the code that is performed while unarchiveObjectWithData: executes so they also control resource management during exception handling (which is the source of trouble behind exceptions in Objective-C).
If they can guarantee that in between your call to unarchiveObjectWithData: and the point in code where they raise the exception is no foreign code (neither third party nor your app's code) it is in theory possible to safely use an exception, as long as calling code takes care of cleaning up correctly.
The problem is that this assumption might not be the case: It is common to use NSKeyedArchiver to serialize custom objects. Usually the custom class implements initWithCoder: to read the classes data (by using the archiver's methods like decodeObjectForKey:).
If the archiver throws an exception in one of these methods there's no way to fix resource handling for the archiver. The exception will be thrown through the custom object's initWithCoder:. The archiver does not know if there's more stuff to clean up than the deserialized objects. So in this scenario the occurrence of the exception means that the process is in a dangerous state and unwanted behavior may result.
Regarding your questions:
Why doesn't [NSKeyedArchiver use proper Cocoa error handling]?
Only the Apple engineers who built the archiver know. My guess is that exception handling and keyed archiving were built at roughly the same time (around 2001) and at that point it wasn't yet clear that exception handling would never be a first class citizen in Objective-C.
Is the #try pattern correct?
With the limitation of the caveats described above it is correct. If Apple's code handles the exception cases properly and your own serialization code does the same the #try pattern might be correct.
It is very difficult to achieve full correctness, though. You'd have to make sure all executed code is aware of the exceptions and does cleanup correctly.
ARC, for instance, does no exception cleanup for local variables and temporary objects by default (you would have to enable -fobjc-arc-exceptions to do this).
Also, there's no documentation on exception safety of the accessors of #synthesized properties (when atomic they might leak a lock).
Conclusion:
There are a myriad of subtle ways of how exceptions can break stuff. It is difficult and requires in depth knowledge of the implementation of all involved parts to build exception safe code in Objective-C.
All this leads to the conclusion. If you want to handle errors gracefully while loading possibly corrupted archives and continue normal execution afterwards: Do not use NSKeyedArchiver.

how to use pointers in Objective c

I have seen some iOS developpers using code like this :
- (void)setupWebView:(UIWebView**)aWebView {
UIWebView *webview = [[UIWebView alloc] init];
.....
if (*aWebView) {
[*aWebView release];
}
*aWebView = webview;
}
Do you know what'is this mean and why we use this ? thanks
- (void)setupWebView:(UIWebView**)aWebView {
That is awful. You should never have a method that returns void, but sets an argument by reference unless:
• there are multiple arguments set
• the method is prefixed with get
That method should simply return the created instance directly. And this just makes it worse -- is flat out wrong:
if (*aWebView) {
[*aWebView release];
}
*aWebView = webview;
it breaks encapsulation; what if the caller passed a reference to an iVar slot. Now you have the callee managing the callers memory which is both horrible practice and quite likely crashy (in the face of concurrency, for example).
it'll crash if aWebView is NULL; crash on the assignment, specifically.
if aWebView refers to an iVar slot, it bypasses any possible property use (a different way of breaking encapsulation).
It is a method to initialize a pointer. The first line allocates the object. The if statement makes sure that the passed in pointer-to-a-pointer is not already allocated, if it is it releases it. then it sets the referenced pointer to the newly allocated object.
The answer by #bbum is probably correct, but leaves out one aspect to the question that I see there. There are many examples in Foundation which use pointer-pointers in the method signature, so you can say it is a common pattern. And those are probably not a beginners mistake.
Most of these examples are similar in that they fall into one category: the API tries to avoid the usages of exceptions, and instead use NSError for failures. But because the return value is used for a BOOL that signals success, an NSError pointer-pointer is used as output parameter. Only in the probably rare error case an NSError object is created, which can contain error code and error descriptions, and localized descriptions and possibly even more information (like an array of multiple errors in the case of bulk operations). So the main success case is efficient, and the error case has some power to communicate what went wrong, without resorting to exceptions. That is the justification behind these signatures as I understand it.
You can find examples of this usage in both NSFileManager and NSManagedObjectContext.
One might be tempted to use pointer-pointers in other cases where you want multiple return values and an array does not make sense (e.g. because the values are not of same type), but as #bbum said, it is likely better to look hard for alternatives.

Using exceptions in Objective-C

I'm new to Objective-C world. What I have noticed while studying some iOS/Mac apps is that try -catch is rarely used, if used at all.
For example in Java it is used almost all the time.
Why isn't it so common in Objective-C ?
Exceptions in Objective-C are generally to be used for truly exceptional circumstances and almost always programmer error. To convey a recoverable error use the NSError** pattern.
There are a lot of SDK methods that take an NSError** parameter and return BOOL. To indicate an error they return false and feed an error back through the error parameter to communicate info.
Exceptions are used, but generally for cases in which there is some failure at the runtime level - e.g. some object can't handle a selector. Although it may seem contrary to what I just wrote, exceptions tend to indicate an error in design rather than a runtime error.
The NSError** idiom is all you need for things such as failed URL connections, data conversions, etc, where an error condition exists but a program really shouldn't be killed outright.
Start reading: Error Handling Programming Guide

Is asserting that every object creation succeeded necessary in Objective C?

I have recently read Apple's sample code for MVCNetworking written by Apple's Developer Technical Support guru Quinn "The Eskimo!". The sample is really nice learning experience with what I guess are best development practices for iOS development.
What surprised me, coming from JVM languages, are extremely frequent assertions like this:
syncDate = [NSDate date];
assert(syncDate != nil);
and this:
photosToRemove = [NSMutableSet setWithArray:knownPhotos];
assert(photosToRemove != nil);
and this:
photoIDToKnownPhotos = [NSMutableDictionary dictionary];
assert(photoIDToKnownPhotos != nil);
Is that really necessary? Is that coding style worth emulating?
If you're used to Java, this may seem strange. You'd expect an object creation message to throw an exception when it fails, rather than return nil. However, while Objective-C on Mac OS X has support for exception handling; it's an optional feature that can be turned on/off with a compiler flag. The standard libraries are written so they can be used without exception handling turned on: hence messages often return nil to indicate errors, and sometimes require you to also pass a pointer to an NSError* variable. (This is for Mac development, I'm not sure whether you can even turn exception handling support on for iOS, considering you also can't turn on garbage collection for iOS.)
The section "Handling Initialization Failure" in the document "The Objective-C Programming Language" explains how Objective-C programmers are expected to deal with errors in object initialization/creation: that is, return nil.
Something like [NSData dataWithContentsOfFile: path] may definitely return nil: the documentation for the method explicitly says so. But I'm honestly not sure whether something like [NSMutableArray arrayWithCapacity: n] ever returns nil. The only situation I can think of when it might is when the application is out of memory. But in that case I'd expect the application to be aborted by the attempt to allocate more memory. I have not checked this though, and it may very well be that it returns nil in this case. While in Objective-C you can often safely send messages to nil, this could then still lead to undesirable results. For example, your application may try to make an NSMutableArray, get nil instead, and then happily continue sending addObject: to nil and write out an empty file to disk rather than one with elements of the array as intended. So in some cases it's better to check explicitly whether the result of a message was nil. Whether doing it at every object creation is necessary, like the programmer you're quoting is doing, I'm not sure. Better safe than sorry perhaps?
Edit: I'd like to add that while checking that object creation succeeded can sometimes be a good idea, asserting it may not be the best idea. You'd want this to be also checked in the release version of your application, not just in the debug version. Otherwise it kind of defeats the point of checking it, since you don't want the application end user to, for example, wind up with empty files because [NSMutableArray arrayWithCapacity: n] returned nil and the application continued sending messages to the nil return value. Assertions (with assert or NSAssert) can be removed from the release version with compiler flags; Xcode doesn't seem to include these flags by default in the "Release" configuration though. But if you'd want to use these flags to remove some other assertions, you'd also be removing all your "object creation succeeded" checks.
Edit: Upon further reflection, it seems more plausible than I first thought that [NSMutableArray arrayWithCapacity: n] would return nil rather than abort the application when not enough memory is available. Basic C malloc also doesn't abort but returns a NULL pointer when not enough memory is available. But I haven't yet found any clear mention of this in the Objective-C documentation on alloc and similar methods.
Edit: Above I said I wasn't sure checking for nil is necessary at every object creation. But it shouldn't be. This is exactly why Objective-C allows sending messages to nil, which then return nil (or 0 or something similar, depending on the message definition): this way, nil can propagate through your code somewhat similar to an exception so that you don't have to explicitly check for nil at every single message that might return it. But it's a good idea to check for it at points where you don't want it to propagate, like when writing files, interacting with the user and so on, or in cases where the result of sending a message to nil is undefined (as explained in the documentation on sending messages to nil). I'd be inclined to say this is like the "poor man's" version of exception propagation&handling, though not everyone may agree that the latter is better; but nil doesn't tell you anything about why an error occurred and you can easily forget to check for it where such checks are necessary.
Yup. I think it's a good idea.. It helps to filter out the edge cases (out of memory, input variables empty/nil) as soon as the variables are introduced. Although I am not sure the impact on speed because of the overhead!
I guess it's a matter of personal choice. Usually asserts are used for debugging purpose so that the app crashes at the assert points if the conditions are not met. You'd normally like to strip them out on your app releases though.
I personally am too lazy to place asserts around every block of code as you have shown. I think it's close to being a bit too paranoid. Asserts might be pretty handy in case of conditions where some uncertainity is involved.
I have also asked this on Apple DevForums. According to Quinn "The Eskimo!" (author of the MVCNetworking sample in question) it is a matter of coding style and his personal preference:
I use lots of asserts because I hate debugging. (...)
Keep in mind that I grew up with traditional Mac OS, where a single rogue pointer could bring down your entire machine (similarly to kernel programming on current systems). In that world it was important to find your bugs sooner rather than later. And lots of asserts help you do that.
Also, even today I spend much of my life dealing with network programs. Debugging network programs is hard because of the asynchrony involved. Asserts help to with this, because they are continually checking the state of your program as it runs.
However, I think you have a valid point with stuff like +[NSDate date]. The chances of that returning nil are low. The assert is there purely from habit. But I think the costs of this habit (some extra typing, learning to ignore the asserts) are small compared to the benefits.
From this I gather that asserting that every object creation succeeded is not strictly necessary.
Asserts can be valuable to document the pre-conditions in methods, during development, as design aid for other maintainers (including the future self). I personally prefer the alternative style - to separate the specification and implementation using TDD/BDD practices.
Asserts can be used to double-check runtime types of method arguments due to the dynamic nature of Objective C:
assert([response isKindOfClass:[NSHTTPURLResponse class]]);
I'm sure there are more good uses of assertions. All Things In Moderation...