I have been learning Objective C on my own for some time already and still don’t quite get the hang of memory management. When should I release properties?
Example, I have a class that will handle 2 (register & updateParticulars) different URLRequest connections. updateParticularsConnection will be performed when registerConnection finishes.
@interface ConnectionViewController : UIViewController {
}
@property (nonatomic, retain) NSURLConnection *registerConnection;
@property (nonatomic, retain) NSURLConnection *updateParticularsConnection;
@property (nonatomic, retain) NSMutableData *responseData;
@property (nonatomic, retain) NSMutableURLRequest *requestURL;
@end
@implementation ConnectionViewController
@synthesize registerConnection, updateParticularsConnection, responseData, requestURL,
(void)performRegistration {
// other here to prepare the data.
requestURL = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"myURL"]];
registerConnection = [[NSURLConnection alloc] initWithRequest:requestURL delegate:self startImmediately:YES];
}
(void)updateParticulars {
// other here to prepare the data.
[requestURL setURL:[NSURL URLWithString:@"http:myURL.com"]];
updateParticularsConnection = [[NSURLConnection alloc] initWithRequest:requestURL delegate:self startImmediately:YES];
}
Handling delegate callbacks
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[SVProgressHUD dismissWithError:@"Unable to connect"];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if (responseData == nil) {
responseData = [[NSMutableData alloc] init];
}
[responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (connection == registerConnection) {
NSMutableString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(@"Register connection recieved data reads : %@", responseString);
if ([responseString isEqualToString:@"-1"]) { // error. stop connection
[self.requestURL release]; // remember to release requestURL since we would not be continuing on.
}
else if ([responseString isEqualToString:@""]) { // error. stop connection
[self.requestURL release]; //remember to release requestURL since we would not be continuing on.
}
else {
[self updateParticulars]; // perform next connection, updateParticulars
}
responseData = nil; // clear the current stored data in preparation for the next connection.
[self.registerConnection release];
[responseString release];
} // end of definition for register connection
else if (connection == updateParticularsConnection) {
// do stuff with data received back here
self.responseData = nil;
[self.requestURL release];
[self.updateParticularsConnection release];
}
}
My question is should I be releasing my properties as soon as I can, which is what I think I am doing now? Or only during the dealloc method? Do advise if I am not doing it right.
you sort of need to take it on a case by case basis. the general answer is “as soon as you are done with it”, unless it is a trivial allocation. for trivial allocations (e.g.
NSString * firstName), you can just wait until dealloc or it is replaced (e.g.setFirstName:). this merely simplifies the implementation.your example is slightly different.
and
important: you are handling your instance’s ivars directly in the OP – use the accessors, they will save you a ton of headaches. these are the changes you’d make to write your program using the accessors: