Two distinct types of problems can arise while an iOS or OS X application is running. Exceptions represent programmer-level bugs like trying to access an array element that doesn’t exist. They are designed to inform the developer that an unexpected condition occurred. Since they usually result in the program crashing, exceptions should rarely occur in your production code.
int main(int argc, const char * argv[])
{ @autoreleasepool
{
//Exception implementation
NSArray *inventory =[NSArray arrayWithObjects:@"one",@"two",@"three",nil];
int selectedIndex = 3;
@try
{
NSString *number =[inventory objectAtIndex:selectedIndex];
NSLog(@"The selected object is: %@", number);
}
@catch(NSException *theException) //throws an exception
{
NSLog(@"An exception occurred: %@", theException.name);
NSLog(@"Here are some details: %@", theException.reason);
}
@finally
{
NSLog(@"Executing finally block");
}
}
return 0;
}
On the other hand, errors are user-level issues like trying load a file that doesn’t exist. Because errors are expected during the normal execution of a program, you should manually check for these kinds of conditions and inform the user when they occur. Most of the time, they should not cause your application to crash.
Exceptions:
Exceptions are represented by the
NSException
class. It’s designed to be a universal way to encapsulate exception data, so you should rarely need to subclass it or otherwise define a custom exception object. NSException
’s three main properties are listed below.Property | Description |
---|---|
name | An NSString that uniquely identifies the exception. |
reason | An NSString that contains a human-readable description of the exception. |
userInfo | An NSDictionary whose key-value pairs contain extra information about the exception. This varies based on the type of exception. |
It’s important to understand that exceptions are only used for serious programming errors. The idea is to let you know that something has gone wrong early in the development cycle, after which you’re expected to fix it so it never occurs again. If you’re trying to handle a problem that’s supposed to occur, you should be using an error object, not an exception.
Exceptions can be handled using the standard try-catch-finally pattern found in most other high-level programming languages. First, you need to place any code that might result in an exception in an
@try
block. Then, if an exception is thrown, the corresponding @catch()
block is executed to handle the problem. The @finally
block is called afterwards, regardless of whether or not an exception occurred.
The following
main.m
file raises an exception by trying to access an array element that doesn’t exist. In the @catch()
block, we simply display the exception details. The NSException *theException
in the parentheses defines the name of the variable containing the exception object.
#import
int main(int argc, const char * argv[])
{ @autoreleasepool
{
//Exception implementation
NSArray *inventory =[NSArray arrayWithObjects:@"one",@"two",@"three",nil];
int selectedIndex = 3;
@try
{
NSString *number =[inventory objectAtIndex:selectedIndex];
NSLog(@"The selected object is: %@", number);
}
@catch(NSException *theException) //throws an exception
{
NSLog(@"An exception occurred: %@", theException.name);
NSLog(@"Here are some details: %@", theException.reason);
}
@finally
{
NSLog(@"Executing finally block");
}
}
return 0;
}
You can observe the above program i am writing the code in try() block after executing my program i am getting the out put as shown below.
2013-07-19 13:51:45.186 Exception Handling[1313:303] An exception occurred: NSRangeException
2013-07-19 13:51:45.188 Exception Handling[1313:303] Here are some details: *** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]
2013-07-19 13:51:45.188 Exception Handling[1313:303] Executing finally block
we get the exception name and reason using NSException class properties.
In the real world, you’ll want your
@catch()
block to actually handle the exception by logging the problem, correcting it, or possibly even promoting the exception to an error object so it can be displayed to the user. The default behavior for uncaught exceptions is to output a message to the console and exit the program.
Objective-C’s exception-handling capabilities are not the most efficient, so you should only use
@try
/@catch()
blocks to test for truly exceptional circumstances. Do not use it in place of ordinary control flow tools. Instead, check for predictable conditions using standard if
statements.Built-In Exceptions
The standard iOS and OS X frameworks define several built-in exceptions. The complete list can be found here, but the most common ones are described below.
Exception Name | Description |
---|---|
NSRangeException | Occurs when you try to access an element that’s outside the bounds of a collection. |
NSInvalidArgumentException | Occurs when you pass an invalid argument to a method. |
NSInternalInconsistencyException | Occurs when an unexpected condition arises internally. |
NSGenericException | Occurs when you don’t know what else to call the exception. |
Errors :
Since errors represent expected problems, and there are several types of operations that can fail without causing the program to crash, they are much more common than exceptions. Unlike exceptions, this kind of error checking is a normal aspect of production-quality code.
The
NSError
class encapsulates the details surrounding a failed operation. Its main properties are similar to NSException
.Property | Description |
---|---|
domain | An NSString containing the error’s domain. This is used to organize errors into a hierarchy and ensure that error codes don’t conflict. |
code | An NSInteger representing the ID of the error. Each error in the same domain must have a unique value. |
userInfo | An NSDictionary whose key-value pairs contain extra information about the error. This varies based on the type of error. |
The
userInfo
dictionary for NSError
objects typically contains more information than NSException
’s version. Some of the pre-defined keys, which are defined as named constants, are listed below.Key | Value |
---|---|
NSLocalizedDescriptionKey | An NSString representing the full description of the error. This usually includes the failure reason, too. |
NSLocalizedFailureReasonErrorKey | A brief NSString isolating the reason for the failure. |
NSUnderlyingErrorKey | A reference to anotherNSError object that represents the error in the next-highest domain. |
Depending on the error, this dictionary will also contain other domain-specific information. For example, file-loading errors will have a key called
NSFilePathErrorKey
that contains the path to the requested file.
Note that the
localizedDescription
and localizedFailureReason
methods are an alternative way to access the first two keys, respectively. These are used in the next section’s example.Handling Errors :
Errors don’t require any dedicated language constructs like
@try
and@catch()
. Instead, functions or methods that may fail accept an additional argument (typically called error
) that is a reference to anNSError
object. If the operation fails, it returns NO
or nil
to indicate failure and populates this argument with the error details. If it succeeds, it simply returns the requested value as normal.
Many methods are configured to accept an indirect reference to an
NSError
object. An indirect reference is a pointer to a pointer, and it allows the method to point the argument to a brand new NSError
instance. You can determine if a method’s error
argument accepts a indirect reference by its double-pointer notation: (NSError **)error
.
The following snippet demonstrates this error-handling pattern by trying to load a file that doesn’t exist via
NSString
’sstringWithContentsOfFile:encoding:error:
method. When the file loads successfully, the method returns the contents of the file as anNSString
, but when it fails, it directly returns nil
and indirectly returns the error by populating the error
argument with a new NSError
object
#import
int main(int argc, const char * argv[])
{
@autoreleasepool
{
//Error implementation
NSString *fileToLoad = @"/Users/tekglintsoftsol/Desktop/mynote.rtf";
NSError *error;
NSString *content = [NSString stringWithContentsOfFile:fileToLoad
encoding:NSUTF8StringEncoding
error:&error];
if (content == nil)
{
// Method failed
NSLog(@"Error loading file %@!", fileToLoad);
NSLog(@"Domain: %@", error.domain);
NSLog(@"Error Code: %ld", error.code);
NSLog(@"Description: %@", [error localizedDescription]);
NSLog(@"Reason: %@", [error localizedFailureReason]);
}
else
{
// Method succeeded
NSLog(@"Content loaded!");
NSLog(@"%@", content);
}
}
return 0;
}
Notice how the we had to pass the
error
variable to the method using the reference operator. This is because the error
argument accepts a double-pointer. Also notice how we checked the return value of the method for success with an ordinary if
statement. You should only try to access the NSError
reference if the method directly returns nil
, and you should never use the presence of an NSError
object to indicate success or failure.
The above i am trying to access the file i.e mynotes.rtf but i am giving the file name as mynote.rtf we get the out put as like below.
2013-07-19 14:05:48.245 Exception Handling[1333:303] Error loading file /Users/tekglintsoftsol/Desktop/mynote.rtf!
2013-07-19 14:05:48.247 Exception Handling[1333:303] Domain: NSCocoaErrorDomain
2013-07-19 14:05:48.247 Exception Handling[1333:303] Error Code: 260
2013-07-19 14:05:48.260 Exception Handling[1333:303] Description: The file “mynote.rtf” couldn’t be opened because there is no such file.
2013-07-19 14:05:48.260 Exception Handling[1333:303] Reason: The file doesn’t exist.
In this case NSError will return nil or NO value because it is an error for loading file path. now i am changing the path as @"/Users/tekglintsoftsol/Desktop/mynotes.rtf" we get the out put as shown like below.
2013-07-19 14:09:17.591 Exception Handling[1349:303] Content loaded!
2013-07-19 14:09:17.593 Exception Handling[1349:303]
{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
\f0\fs24 \cf0 hai welcome to tekglint }
Errors represent a failed operation in an iOS or OS X application. It’s a standardized way to record the relevant information at the point of detection and pass it off to the handling code. Exceptions are similar, but are designed as more of a development aid. They generally should not be used in your production-ready programs.
No comments:
Post a Comment