As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I read Apple's recommendation on exception usage and NSError usage:
Also, I read several similar stack overflow questions which discuss whether to use or not exception.
Exception Handeling in iOS
Using exceptions in Objective-C
Objective-C Exceptions
I am trying to figure out pros and cons of usage exception as error notification/handling method in iOS (Frankly, I am no satisfied with Apple's sentence (it says what to do, but it doesn't say why we should do it):
You should reserve the use of exceptions for programming or
unexpected runtime errors such as out-of-bounds collection access,
attempts to mutate immutable objects, sending an invalid message, and
losing the connection to the window server. You usually take care of
these sorts of errors with exceptions when an application is being
created rather than at runtime.
Exception usage pros:
It doesn't require to modify all intermediate code between error generating code and error handling code
It doesn't pollute arguments and return values for methods
Cons:
For all manually managed memory code we will have to be extra careful (we will need to wrap it in autoreleasing objects to make sure that resources are released).
We need to be careful with the border between our code and framework. If our exceptions leave our code, we could be in trouble (because frameworks may manually manage memory)
Did I miss anything? Are there additional cons/pros?
It looks like exceptions should be fine for library like code (when we have quite big amount of tightly packaged code, which doesn't communicate a lot with external systems/frameworks. And it looks like exception are hard to use for the code which actively interacts with other frameworks.
Does your experience prove this theory?
I appreciate any additional info on this subject.
tl;dr Exceptions should be used for fatal/non-recoverable/programmer error(s) only. Attempting to use them a la Java or other exceptions-are-recoverable environments will result in code that is more fragile, harder to maintain, and difficult to refactor while also limiting your ability to leverage system frameworks.
Con: If you use exceptions for flow control and/or recoverable errors in your code, your code will be, by design, different from Apple's design patterns.
End result?
• You can't use Apple's APIs at all in your code unless the border between your code and Apple's always isolates the exception behavior
• Every time your refactor, you'll have to refactor a mass of exception handling code
• Many things that should be trivial will be very complex; for example, you won't be able to put your objects into an enumerable collection and enumerate them without that enumeration -- block, for loop, whatever... -- also having exception processing at the boundaries.
Consider:
NSArray *a = #[yourExceptionfulInstance, yourExceptionfulInstance, yourExceptionfulInstance];
#try {
for(id k in a) { [k doSomething]; }
} #catch(...) {
}
If doSomething might raise, for any reason, the above is violation of the documented design patterns of the framework because you'll be throwing an exception across frames within Apple's framework(s).
That is one mighty big con. Big enough that I can't imagine a set of pros to outweigh it.
Related
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am an average iOS developer. The first design pattern that I saw heavily being used was Delegation pattern which was mostly being used for callback functionality.
Now that blocks are there in Objective C and I am seeing more and more libraries heavily using them and avoiding delegates, I am wondering, are blocks permanent replacement for delegate pattern using protocols ?
I recently used MKNetworkKit in a project, I created a wrapper class on top of it, the library is block based so all my code that would encapsulate a call to one of there block based code turned ot to be another block based code.
I found that it was very convenient initially, but was difficult to debug and modify as the code looked complex (callback inside callback inside callback!)
Any tips on when to use what and certain best practices ?
Delegates and blocks are both used for something to "call back" the result, usually to the thing that created it. There are some differences:
Using a delegate protocol, the method names you must implement to receive the callback are fixed. That means, if you need to receive callbacks from multiple possible actions using the same delegate protocol, you must somehow distinguish them. With blocks, there are no fixed names; you simply pass a block object with a particular signature. You can pass different block objects to different actions.
Delegate protocols often (but not always) contain more than one callback method, e.g. a "success" and a "failure" callback. Each block can only serve as one callback. Many libraries try to "combine" multiple delegate callbacks into a single block callback, by using multiple arguments, e.g. the block has two arguments (result, error), where if "error" is nil it corresponds to the original "success" callback, with "result" being the data; and if "error" is not nil, it corresponds to the original "failure" callback. Another option would be to give multiple blocks separately to the action (e.g. it has a "success block" property, and "failure block" property, which you can set). This is more general, and will work as a one-to-one replacement of a delegate protocol with any number of methods.
Memory management: Delegates are usually weakly-referenced, since the delegate is usually a "parent" object that owns the delegator. However, blocks are strongly referenced, since blocks are one-use things that are not needed anymore once passed to the delegator. However, if you think about it, it is not really different. With delegates, typically the delegate method will perform some action on itself (the parent object). With blocks, in order to do this, the block would need a reference to the "parent". It is then this reference that needs to be a weak reference, to emulate the memory management of the delegate pattern. With blocks, the parent object code has more control over how the delegate will reference it, because it sets up the block.
In conclusion, it is possible to systematically convert any API using a delegate protocol into one that uses blocks, with what I described above -- for each delegate method, add one block property on the delegator.
Protocols and the designated delegate objects they talk to are quite different than block-based code, which is usually used to encapsulating a task and/or shipping it off to GCD.
I do see one place in the Apple's Block documentation that appears to match some of the functionality that delegates provide:
Blocks are particularly useful as a callback because the block carries
both the code to be executed on callback and the data needed during
that execution.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
The performance overhead of calling methods/properties in Objective-C is killing the performance of my iOS app; the Xcode profiler (aka, Instruments) attributes 70% of the latency to objc_msgSend, _retain, and _release.
In my code, so far, I make about 1100 calls to my XROpenGL class's instance method renderSprite(XRSprite) which is an overloaded method of renderSprite(XRSprite,int,int,int) which in turn invokes no less than five other methods, many of which access properties from XRSprite. As you can imagine, there's ALOT of messages being sent around.
Do I have any options apart from rewriting the critical sections of the code in C++?
Is that 6,600 calls per frame? I'll assume so for the sake of discussion, at 60 FPS for a total call count of 396,000 just for your explicit method calls. If you assume the pessimistic case, objc_msgSend's overhead (versus a C function call) is still only O(100) cycles. So on a modern iDevice you're looking at ~4% of your CPU time, very roughly. Not a huge deal. You might get a retain or two and corresponding releases for each call, but retain/release are relatively fast so we'd again be talking single-digit percentages. "Runtime overhead" of this nature of up to ~10% isn't considered egregious, generally, though it's not optimal.
So, the questions I have for you are:
Can you post your code?
Can you post more detailed profile information (e.g the exact breakdown between the various top 10 methods, as well as perhaps callstacks for the major ones)?
Are you sure the time is actually spent in objc_msgSend et al, and not merely in its children?
How many calls are you really making? As in measured, not assumed.
Can you use ivars instead of #properties, to remove some of the method calls?
Along those lines, are you caching the properties you do access when using them multiple times in one method?
Can you refactor to reduce the number of method calls, and/or use vanilla C functions for some things?
Obviously yes, you can rewrite key code in C++. But for mid-level drawing code you shouldn't have to; C++ is usually left to low-level constructs like vectors and quaternions and other such primitives.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I find myself often writing complex GCD / block based methods (comparable to the code snippet shown below).
How would you break up this kind of method in smaller
portions?
Would you rather GCD-enable the parsing methods in the managed
objects' code or would you rather keep the GCD code in the view
controller?
How can I run the NSURL request in the code below in the background
queue ([NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue] When I use NSOperationQueue
currentQueue, the completion handler does not get called.
Use a C function or a instance method to delegate certain processes (such as saving to the XML file).
Definitely keep it in the object's code. You are breaking MVC too much as it is,
Don't use NSURLRequest, use AFNetworking or RestKit instead.
I would separate that so you can actually see the MVC design in it. So I would have:
The UIViewController
A Manager Class to handle the interactions between the UIViewController, the NSURLConnection and the XML Parser
A class to handle the NSURLConnection (or any 3rd party you would like).
A class to handle the XML Parsing and posterior writing.
To establish communication I would use delegation. This way you would have different blocks of work. So when you need to change the XML Parse, just switch the class; if you need to use this logic somewhere else, just switch the UIViewController. Keep it simple and clean.
P.S: Sometimes, no matter what you do, the code just is, by it's nature, complex, please use comments, you will thank yourself later...
I recently started learning Objective-C, and I am working on an iOS app as an exercise, anyway, I want to handle overflow by throwing exception (I come from a Java background), I searched the reference there is only NSException, but then I read in the section that say topics about exception handling, and they said to use NSError, I read the reference but they had the same protocol and methods, so what's the difference between them? And which is better?
Also, I want to create my own exception or error class, are there any methods or fields that I should include? (Like when implementing the Exception interface in Java).
Thanks
NSError is designed for non-fatal, recoverable errors. The problems that are designed to be captured by an NSError are often user errors (or are errors that can be presented to the user), can often be recovered from (hence -presentError: and NSErrorRecoveryAttempting), and are usually expected or predictable errors (like trying to open a file that you don't have access to, or trying to convert between incompatible string encodings).
NSException is designed for potentially fatal, programmer errors. These errors are designed to signify potential flaws in your application where you have not correctly checked the pre-conditions for performing some operations (like trying to access an array index that is beyond its bounds, or attempts to mutate an immutable object). The introduction to the Exception Programming Guide explains this a little bit.
What’s the rationale behind the Cocoa exception policy - or why use exceptions only for programmer errors?
I understand that exception used to be rather expensive so one would not want to overuse them. But that changed with the modern runtime and it’s zero-cost exceptions. I also understand that the use of exceptions to do general control flow is not a good idea because it could lead to code that is rather hard to understand.
But why should one use exceptions to signal programmer errors? For that case logging a message followed by abort() should be enough. Why should I write a #catch(...) block to handle a programmer error instead of fixing the actual mistake? I’ve been thinking about this a lot and I haven’t found any reasonable use of an exception for a programmer error.
(As a side note/question: I’ve written a recursive descent parser, and I’m planning on using exceptions in there for handling errors. Seems to be much more reasonable to me than adding an out parameter to every single function in there and manually check for an error everywhere. Of course I’ll catch any exceptions I throw in the top level methods that get called from the outside. Anyone think that’s a bad use for exceptions?)
Update: The real question
Thanks for all the answers so far. They all are true, but they don’t actually answer my question. So I guess I wasn’t really clear about it, sorry for that. So here’s the real question:
Why does Cocoa throw exceptions for programmer errors (or assertions) at all? One isn’t supposed to catch them, and actually writing code that handles a programmer error somewhere down the call stack is not a good idea anyways. Seems to me that exceptions there are a wasted effort. Simply logging the error and calling abort() (which exits the program) should be enough. So what’s the advantage there of actually having an exception thrown?
I understand why exceptions are not generally used and discouraged - most parts of Cocoa are just not exception safe. And that’s not the question here. I hope I made this clear now.
Why should I write a #catch(...) block to handle a programmer error instead of fixing the actual mistake?
In most cases, you wouldn't. In Objective-C, you generally don't handle exceptions. If an exception occurs, it causes a crash, and then you fix the bug -- hopefully you catch this during testing.
Of course, in some cases this doesn't work out. Maybe you do except an exception and you can workaround it, so you catch it. Or there's there rare API that'll throw exceptions instead of using error objects.
To be honest, I very, very rarely use try/catch in my Objective-C code.
As for the rationale, I think it's largely due to Objective-C's C heritage. Back in the early 80s when Objective-C was developed, exceptions were kind of "new" (i.e., not in many mainstream languages yet), and Objective-C catered more to the C tradition of using NULL or an out parameter to signal errors.
Your question explicitly assumes that "one isn’t supposed to catch them." This is incorrect. The programmer isn't expected to catch them under normal circumstances, but that isn't to say that they must never be caught for any purpose.
Example: I'm not sure if it does anymore since it's much less buggy these days, but I know it at least used to be the case that Xcode would catch exceptions and put up a dialog saying, "Such-and-such happened. It doesn't appear to be a critical problem, but you should probably save and restart the program to avoid any trouble in the future."
Why does Cocoa throw exceptions for
programmer errors (or assertions) at
all? One isn’t supposed to catch them,
and actually writing code that handles
a programmer error somewhere down the
call stack is not a good idea anyways
Ah!
Three reasons leap to mind.
One, if you catch an exception more or less at your main run loop you could autosave state to a temporary location, crash, and on restart have a "try to restore from just before the crash, warning: may cause another crash and you should check your data very carefully" dialog/sheet/thingie. Or even just catch the exception and tell the user to do a "Save As", quit and restart.
Two, things like the unit test framework make good use of exceptions to abort the current test (logging a failure), and continuing with the rest of the tests. This lets you see if a change you made has one regression (that happens to index a NSArray out of bounds), or if you have six regressions (one or more of which throw an exception).
Three, maybe when added to ObjC it was intended to handle many kinds of errors with exceptions, and after real world experience the useful scope was determined to be "nearly fatal errors only".
The main reason for avoiding throwing exceptions is that you may accidentally throw them through stack frames that are not exception aware. For instance, if a data source for a table view throws an exception, that is not caught and handled before the delegate method returns control to the table view, it might cause all sorts of trouble as it unwinds the table view's stack frames, side stepping various releases of temporary objects and other resources.
Having said that, I personally like exceptions and use them wherever I think they are the natural thing to do, but with the caveat of never allowing them to propagate to code that is not documented as exception aware.
There are likely a lot of reasons. The "historical reasons" others have covered is sufficient to explain the current state of affairs, but there are other possibilities.
Another possibility is Objective C is not typically a "Resource Acquisition Is Initialization" kind of language (yes this is more a library issue then a language issue, but it is real). So most Objective C code that has an error thrown through it will leave invalid program state (things still locked, over retained objects). All things you could deal with if you were thinking about it, and not all things RAII would magically fix (there is a lot of exception unsafe C++ code out there, and C++ is largely RAII).
As noted above stating that you do handle an exception is free(ish), but actually having one thrown is costly (maybe an order of magnitude or two more costly then an extra parameter and a conditional check). So if your parser (for example) uses them to signal errors in parsing, being given a document with a lot of errors can take a LOT longer to parse then if you had explicit checks for an error parameter.
Personally I like exceptions, and would prefer to throw exceptions from my libraries when things "go wrong", but that isn't the Cocoa way, so I use exceptions to handle programmer errors and an error indication and NSError** for other things. It isn't great, but it makes it so other people can use my libraries without having to learn a new way to write Objective C code.
The modern runtime does not give you zero-cost exceptions, it gives you exceptions that only incur their cost if an exception is thrown.