Java uses automatic garbage collection so that objects that are no longer "touchable" are deleted when memory runs low. So in Java we simply have:
MyClass mc= new MyClass();
iPhone Objective C uses reference counting so that we may need to manually manage retain counts. When the retain falls to zero, the object is eligible for deletion. In iOS we have:
NSObject *obj= [[NSObject alloc]init];
...
[obj release];
In iOS we can also do:
id classNameGetInstance(void) {
return [[NSObject new] autorelease];
}
What I find a bit confusing is that, apparently by convention, calls to retain and release are not necessary IF the object from the method classNameGetInstance is used only within a method, such that the object is referenced on the stack only. Apparently autorelease is smart enough to wait until the method returns before destroying the object. For what it is worth, the actual objects in Objective C are stored in the heap.
If you obtain an object using a "method" name with alloc, new, init or copy then you OWN the object and need to release it at some point. If you obtain an object with a convenience constructor with a "method" name that starts with the class name, then you do NOT own the object and may need to call retain/release if you want the object to persist off the stack such as an instance variable.
By corollary, if you write a class method with init in the name, then you need to call alloc init before returning the object. If you create a static class method that starts with the class name, you need to call alloc init autorelease before returning the object. If you create an object and use it all within a method you should be able to do:
SomeObject *so= [[[SomeObject alloc] init] autorelease];
It may be more efficient, however, to call [[SomeObject alloc] init] and [SomeObject release] within the method.
"Methods" that start with the className are considered convenience constructors. You do not own objects returned by convenience constructors so you may use them on the stack or you may retain/release them as instance variables. Objective C by convention supports the concept of a class convenience method that takes parameters and returns an autoreleased object as in:
+(id)classNameInitWithSomeValues ... {
id *temp= [[self alloc] init];
... init variables here
return [temp autorelease];
}
where (id) is similar to C++ (void*).
If you create an object as an instance variable then you must take ownership of the object and you should release the object in dealloc as in:
Model *model;
model= [[Model alloc]init];
- (void)dealloc {
[model release]; // works on nil
[super dealloc];
}
One weirdness in Objective-C is in self assignment. So the following snippet from Objective-C Phrasebook by David Chisnall will work even with self assignment given an instance variable string:
-(void)setStringValue: (NSString*)aString {
id tmp= [aString retain];
[string release]
string= tmp;
}
The following code may return nil on self assignment:
-(void)setStringValue: (NSString*)aString {
[string release]; // releases aString on self assignment!
string= [aString retain]; // aString is nil on self assignment!
}
Rather than get all tied up in knots, Objective C supports properties. You can use properties to set and get instance values using the dot notation as in:
myClass.myValue= someValue;
SomeValue *value= myClass.myValue;
When you use properties, you can let the compiler worry about calling retain and release on assignment. You still need to call release in dealloc on a property.
Further clarifications: In Objective C you may see:
NSUInteger myUInt= 1;
NSInteger mySignedInt= -1;
These are just cpu dependent type defs for primitives as in:
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
NSNumber, on the other hand, is a wrapper class for "C scalar numeric types."
Finally, here is some sample code that creates a buffer of unsigned char on the heap and wraps it in NSData:
+(NSData *)getRandomIV:(NSInteger)numBytes{
unsigned char *buffer = malloc(numBytes * sizeof(*buffer)); // sizeof(*buffer) is one!
NSUInteger i;
if (buffer == NULL) return nil;
for ( i = 0; i < numBytes; ++i ) buffer[i] = arc4random() % (255+1);
//NSData *data= [NSData dataWithBytesNoCopy:buffer length:numBytes freeWhenDone:YES];
NSData *data= [NSData dataWithBytesNoCopy:buffer length:numBytes];
//if ( buffer ) free( buffer ); // NSData will free buffer
return data;
}
In this example, the NSData object is responsible for calling free(buffer). It may be simpler to create a buffer on the stack and call NSData dataWithBytes and let NSData worry about copying the buffer to the heap!
You can append data by creating an NSMutableData object and then sending the message appendData:data. You can retrieve subdata by calling subdataWithRange: as in:
NSData* iv= [raw subdataWithRange:NSMakeRange(0,16)];
Where 0 is the start index and 16 is the numBytes to copy.