Archive
Exceptions and error handling in Objective-C
Compiler directives that are used for exception handling:
1. @try
: block of code that can throw an exception.
2. @catch
: define block of code to handle exception thrown by try block, this is usually an NSException object.
3. @finally
: defines a block of code that executed whether an exception is thrown or not.
4. @throw
: once your program detects an exception, it must propagate the exception to code that handles it. This code is called the exception handler. This entire process of propagating an exception is referred to as “throwing an exception”.
@try { NSLog(@"trying..."); [object objectForKey:@"yeah"]; } @catch (NSException * e) { NSLog(@"catching %@ reason %@", [e name], [e reason]); } @finally { NSLog(@"finally"); }
For more informations have a look at the documentation here.
NSString Basics
Creating strings
NSString *myFirstString = @"foo";
NSString *mySecondString = [[NSString alloc] initWithFormat:
@"%@%@%@i", myFirstString, @"bar", 1];
Comparing strings
NSString *myString = @"foo"; if([myString isEqualToString:@"foo"]) { NSLog (@"Strings are equal!"); }
Finding strings within strings
NSString *myString = @"foo"; NSString *searchForMe = @"Howdi"; NSRange range = [myString rangeOfString : searchForMe]; int location = range.location; int length = range.length; if (location != NSNotFound) { NSString *locationAndLength = [[NSString alloc] initWithFormat: @"Location: %i, length: %i",location, length];
NSLog(@"I found something."); NSLog(locationAndLength
); }
Replacing strings within strings
NSString *myString = @"foo"; myString = [myString stringByReplacingOccurancesOfString:@"oo" withString:@"uu"];
Extracting substrings from strings
There are 3 methods that allow to extract substrings from a parent string:
- -substringToIndex:
- -substringWithRange:
- -substringFromIndex: (which respectively take a substring from the beginning, middle, and end of a parent string)
The first method substringToIndex
returns a new string which is composed of the characters from the beginning of the receiver string up to (but not including) the character at the specified index:
NSString *aString = @"Running out of ideas for strings.";
NSString *substring = [aString substringToIndex:7];
// result: @"Running"
The method substringFromIndex
works in the same way, except now the substring starts at the specified index of the receiver (including the character at the index) and includes all the characters to the end of the receiver:
NSString *substring = [aString substringFromIndex:25]; // result: @"strings"
Finally, we have the method which lets us arbitrarily extract a substring from anywhere within the parent string substringWithRange
. The argument to this method is an NSRange
:
NSString *substring = [aString substringWithRange:NSMakeRange(15, 5)]; // result: @"ideas"
Here the range starts with the 15th character, “i”, and extends to include the next four characters, giving us a length of 5, “ideas”.
How to find class type of an object
NSLog(@"Is of type: %@", [myObject class]);
NSLog(@"Is of type NSString?: %@", ([[myObject class] isMemberOfClass:
[NSString class]])? @"Yes" : @"No");
NSLog(@"Is a kind of NSString: %@", ([[myObject classForCoder]
isSubclassOfClass:[NSString class]])? @"Yes" : @"No");
Objective-C Structs
struct ExampleStruct { NSString* something; NSInteger somethingElse; ... }; // useage: // struct ExampleStruct Struct; // Struct.something = @"foo"; // Struct.somethingElse = 2; // or //struct ExampleStruct Struct = { @"foo", 2, ... };
Location via GPS with iOS
First add the Core Location framework:
- right click on the “Frameworks” group and go to Add > Existing Frameworks…
- select the CoreLocation.framework
Then you can use the framework in your app:
#import <CoreLocation/CoreLocation.h>
@interface MyLocation : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
}
@end
#import "MyLocation.h"
@implementation MyLocation
- (id) init {
if ((self = [super init])) {
// Custom initialization
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
}
return self;
}
- (void) locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
int degrees = newLocation.coordinate.latitude;
double decimal = fabs(newLocation.coordinate.latitude - degrees);
int minutes = decimal * 60;
double seconds = decimal * 3600 - minutes * 60;
NSString *lat = [NSString stringWithFormat:@"%d° %d' %1.4f\"",
degrees, minutes, seconds];
degrees = newLocation.coordinate.longitude;
decimal = fabs(newLocation.coordinate.longitude - degrees);
minutes = decimal * 60;
seconds = decimal * 3600 - minutes * 60;
NSString *lon = [NSString stringWithFormat:@"%d° %d' %1.4f\"",
degrees, minutes, seconds];
}
@end
Private method in Objective-C
There are no private methods in Objective-C like e.g. in C# .NET. Though you can create a category with an empty name (class continuation) in Objective-C 2.0 (i.e. @interface MyClass ()
). With this category you can create the private method implementations in the same @implementation MyClass
file as the public methods.
With an addition like “__” at the start of your “private” methods you should bring in this naming convention to prevent your classes from being breakable in a too easy way. The possibility that someone will override some of your “private” methods by accident is then on a much lower value. Apple reserved names with a leading underscore for its own uses, so prefer an addition like “__”.
Create your classes for example like this:
In the header file:
@interface MyClass {
// My Instance Variables
}
- (void)myPublicMethod;
@end
And in the implementation file:
@interface MyClass(
/* Private methods */) - (void)__myPrivateMethod; @end @implementation MyClass - (void)myPublicMethod { // Implementation goes here } - (void)__myPrivateMethod { // Implementation goes here } @end
The second alternative is to put the category into its own .h file. You can name such a file after its class and category with a + separating them, so @interface MyClass (PrivateMethods)
can be found in MyClass+PrivateMethods.h
. With this convention you can import the header in your unit test classes.
NSNotificationCenter – Custom events to implement Observer Pattern
Here’s how it would look in Cocoa —
// Send a notification [[NSNotificationCenter defaultCenter] postNotificationName: @"GotInformationsNotification" object:nil]; // Register an observer [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) name:@"GotInformationsNotification" object:nil]; // Handle the notification - (void) doSomething:(NSNotification*) notification { ... } // Remove an observer [[NSNotificationCenter defaultCenter] removeObserver:self name:@"GotInformationsNotification" object:nil];
// Use the object attribute of the postNotificationName // method to pass data/objects with your event NSDictionary *userInfoDictionary = [NSDictionary dictionaryWithObject: @"the object" forKey:@"object"]; [[NSNotificationCenter defaultCenter] postNotificationName: @"GotInformationsNotification" object:self userInfo:userInfoDictionary]; // Handle the notification - (void) doSomething:(NSNotification*) notification { //Get the content of the notification data NSDictionary *userInfo = [notification userInfo]; if (userInfo != nil) { NSString* data = [userInfo objectForKey:@"object"]; } }
Here’s how it would look in AS3 —
View 1:
this.addEventListener("buttonClicked", gotoNextView);
...
View 2:
//..inside button click handler..
dispatchEvent(new Event("buttonClicked));