Pregunta de entrevista de GREE International Entertainment

Here's an Objective C category extension. What's wrong with this code? @interface UIImage (RemoteImage) { NSURL * url; UIImage * image; } - (id) initWIthURL: (NSURL *) _url; @end @implementation UIImage (RemoteImage) - (id) initWithURL: (NSURL *)_url { self = [super init]; if( self != nil ) { url = _url; NSURLResponse * response = [NSURLResponse new]; NSURLRequest * request = [[NSURLRequest alloc] initWithURL: url]; NSData * data = [NSURLConnection sendSynchronousRequest: request returningResponse: response error: nil]; image = [UIImage imageWithData: data]; return image; } return self; } - (void) dealloc { [super dealloc]; [url release]; [image release]; } @end

Respuesta de la entrevista

Anónimo

31 oct 2012

//I went through and debugged this and only at the end realized that categories can't //declare new instance variables (the "url" and "image" bits). This code would be better done as a subclass @interface RemoteImage : UIImage { NSURL * url; UIImage * image; } - (id) initWithURL: (NSURL *) _url; @end @implementation RemoteImage // Since the point of the exercise was to point out what was wrong with the // code, I didn't go all the way in refactoring the nasty code below // // - (id) initWithURL: (NSURL *)_url { self = [super init]; if( self != nil ) { url = _url; // we need to keep a copy of url around to release later, apparently [url retain]; // I'm not accustomed to instantiating via "new", but // the interviewer said this was the same thing as a // traditional "alloc" + "init" NSURLResponse * response = [NSURLResponse new]; NSURLRequest * request = [[NSURLRequest alloc] initWithURL: url]; // doing synchronous anything can be potentially super slow // // which would block the UI if this were on the main thread NSData * data = [NSURLConnection sendSynchronousRequest: request returningResponse: response error: nil]; image = [UIImage imageWithData: data]; // don't forget to release whatever was allocated [request release]; [response release]; // returning like this leaks memory (the orphaned "self") return image; } return self; } - (void) dealloc { [super dealloc]; [url release]; // // can't release an object set as autorelease //[image release]; } @end