Objective C - kgleong/software-engineering GitHub Wiki
Objective-C
Objective-C runtime
References
Initializers
id
The id
type is a pointer to any Objective-C class, which must respond to retain
and release
messages.
new
keyword
The new
keyword can be used instead of alloc
and init
.
[MyClass new]; // equivalent to [[MyClass alloc] init]
References
Properties
#import <Foundation/Foundation.h>
#import "Address.h"
@interface Person : NSObject
/**
Defaults:
readwrite, atomic, strong
As opposed to:
readonly, nonatomic, weak
*/
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) Address *address;
@end
The @synthesize
keyword in the .m
file is implied, and automatically generates setters and getters for each property.
Instance Variables
Similarly, the following attributes can be assigned to instance variables if the @property
directive is not used:
@implementation
NSString __weak *someText;
NSString __strong *otherText; // ivars are strong by default.
@end
The atomic
keyword is not supported for instance variables. Thread safety must be manually managed using locks. E.g., the @synchronized
directive.
References
Constants
Header file:
#import <Foundation/Foundation.h>
#import "Address.h"
@interface Person : NSObject
/**
extern keyword makes the constant available to other classes.
const keyword makes the pointer immutable.
constants are not namespaced in Objective-C.
*/
extern NSString* const PERSON_NAME_KEY;
extern NSString* const PERSON_ADDRESS_KEY;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) Address *address;
- (id)initWithDictionary:(NSDictionary*) dict;
@end
Implementation:
#import "Person.h"
@implementation Person
NSString* const PERSON_NAME_KEY = @"name";
NSString* const PERSON_ADDRESS_KEY = @"address";
- (id)initWithDictionary:(NSDictionary *)dict {
self = [super init];
// Returns false if self is nil.
if(self) {
self.name = dict[PERSON_NAME_KEY];
self.address = dict[PERSON_ADDRESS_KEY];
}
return self;
}
- (NSString *)description {
NSArray* personDetails = @[self.name, self.address.description];
return [personDetails componentsJoinedByString:@"\n"];
}
@end
Categories and Extensions
A category allows a class to be modularized into separate files.
Each category contains a header and implementation file, and must be imported by clients in addition to importing the header for the original class.
Extensions can only be added to a class's implementation .m
file.
Extensions allow the addition of private variables and properties, and are syntatically equivalent to categories, but without the category name.
@interface MyClass : NSObject
// Only allows clients to read this property.
@property(readonly) NSString *myString;
@end
// Extension definition. Note the blank category name.
@interface MyClass()
// Exposes a writable property to the implementation only.
@property(readwrite) NSString *myString;
@end
@implementation MyClass
@end
References
Blocks
@interface Block : NSObject
- (void)doSomething;
@end
@implementation Block
- (void)doSomething {
// Define myBlock variable of type block.
NSString* (^myBlock)(NSString *, int) = ^(NSString* myString, int repeatCount) {
NSMutableString *result = [[NSMutableString alloc] init];
// Repeats myString n times.
for(int i = 0; i < repeatCount; i++) {
[result appendString:myString];
}
return result;
};
// Prints foofoofoofoofoo
NSLog(@"myBlock result: %@", myBlock(@"foo", 5));
// Prints barbarbarbarbar
[self runBlock:myBlock];
}
- (void)runBlock: (NSString* (^)(NSString *, int)) someBlock {
NSLog(@"%@", someBlock(@"bar", 5));
}
@end