I've noticed some really serious issues with using any of the NS classes. The problem is that if you are trying to keep track of retain counts, you SIMPLY CANNOT because instantiating objects using another object AUTOMATICALLY creates a reference to it and bumps its retain count.
Take, for instance, the following code
A URL is passed to the method "load" and the url is stored in a class property I named "fileurl". That's fine. The output of the following NSLog is as expected: 1
So, I call "NSURLRequest" and its "requestWithURL" method, and the retain count bumps up to "2". Fine. It makes sense because the object probably needs to use the URL, and I expect the coders of the class to release my URL when it is done with it.
Problem is, the next NSLog outputs are as follows, "5", "10", and "10". Wow, this is really fantastic. Hundreds of built-in classes for us to use and NONE of them cleanup their references. NONE.
I've even used this code:
ANY, and I mean EVERY class included in XCode I've used that has an "init" method where you pass an object to it--it not only bumps the retain count of that object to keep it, but has no intention of cleaning that up. Instead they are automatically retained and you must release the object yourself.
For instance, the following code outputs as follows:
2010-11-01 16:12:30.128 Keeola[16629:207] data... 1
2010-11-01 16:12:30.129 Keeola[16629:207] data... 2
2010-11-01 16:12:30.130 Keeola[16629:207] data... 2
2010-11-01 16:12:30.130 Keeola[16629:207] data... 2
2010-11-01 16:12:30.131 Keeola[16629:207] data... 2
Meanwhile, the authors of the "UIImage" class appear to attempt to cover up their poor management skills by adding a release of the "data" object IF you do NOTHING with it. For instance,
Outputs
data... 1
data... 2
data... 1
So, ya, deallocating a UIImage object when I make absolutely no use of it does indeed release the "NSData" object sent to it, but there's not much good considering you aren't viewing the object.
Am I missing something here? I'm following the rules of keeping track of memory, but when I start trying to do anything that's worth anything, suddenly my memory is getting tossed around and stolen by god knows what. How do you POSSIBLY manage memory?
Take, for instance, the following code
Code:
- ( BOOL )load:( NSURL * )purl
{
fileurl = purl;
NSLog( @"%d", [ fileurl retainCount ] );
NSURLRequest* request = [ NSURLRequest requestWithURL:purl ];
NSLog( @"%d", [ fileurl retainCount ] );
NSURLConnection* conn = [ NSURLConnection connectionWithRequest:request delegate:self ];
NSLog( @"%d", [ fileurl retainCount ] );
if ( conn )
{
data = [ [ NSMutableData alloc ] init ];
}
else
{
[ conn release ];
NSLog( @"Failed to connect to file: %@", filename );
return FALSE;
}
return TRUE;
}
- ( void )connection:( NSURLConnection * )pconnection didReceiveResponse:( NSURLResponse * )response
{
NSLog( @"%d", [ fileurl retainCount ] );
[ data setLength:0 ];
NSLog( @"Loading file: %@", filename );
}
- ( void )connection:( NSURLConnection * )pconnection didReceiveData:( NSData * )pdata
{
[ data appendData:pdata ];
NSLog( @"Downloading data... %d", [ data length ] );
}
- ( void )connectionDidFinishLoading:( NSURLConnection * )pconnection
{
[ self process ];
NSLog( @"Succeeded! Received %d bytes of data", [ data length ] );
NSLog( @"%d", [ fileurl retainCount ] );
}
A URL is passed to the method "load" and the url is stored in a class property I named "fileurl". That's fine. The output of the following NSLog is as expected: 1
So, I call "NSURLRequest" and its "requestWithURL" method, and the retain count bumps up to "2". Fine. It makes sense because the object probably needs to use the URL, and I expect the coders of the class to release my URL when it is done with it.
Problem is, the next NSLog outputs are as follows, "5", "10", and "10". Wow, this is really fantastic. Hundreds of built-in classes for us to use and NONE of them cleanup their references. NONE.
I've even used this code:
Code:
UIImage* bitmap = [ [ UIImage alloc ] initWithData:data ];
[ bitmap release ];
ANY, and I mean EVERY class included in XCode I've used that has an "init" method where you pass an object to it--it not only bumps the retain count of that object to keep it, but has no intention of cleaning that up. Instead they are automatically retained and you must release the object yourself.
For instance, the following code outputs as follows:
Code:
NSLog( @"data... %d", [ data retainCount ] );
UIImage* bitmap = [ [ UIImage alloc ] initWithData:data ];
NSLog( @"data... %d", [ data retainCount ] );
image = [ [ UIImageView alloc ] initWithImage:bitmap ];
NSLog( @"data... %d", [ data retainCount ] );
[ bitmap dealloc ];
NSLog( @"data... %d", [ data retainCount ] );
[ image dealloc ];
NSLog( @"data... %d", [ data retainCount ] );
2010-11-01 16:12:30.129 Keeola[16629:207] data... 2
2010-11-01 16:12:30.130 Keeola[16629:207] data... 2
2010-11-01 16:12:30.130 Keeola[16629:207] data... 2
2010-11-01 16:12:30.131 Keeola[16629:207] data... 2
Meanwhile, the authors of the "UIImage" class appear to attempt to cover up their poor management skills by adding a release of the "data" object IF you do NOTHING with it. For instance,
Code:
NSLog( @"data... %d", [ data retainCount ] );
UIImage* bitmap = [ [ UIImage alloc ] initWithData:data ];
NSLog( @"data... %d", [ data retainCount ] );
[ bitmap dealloc ];
NSLog( @"data... %d", [ data retainCount ] );
Outputs
data... 1
data... 2
data... 1
So, ya, deallocating a UIImage object when I make absolutely no use of it does indeed release the "NSData" object sent to it, but there's not much good considering you aren't viewing the object.
Am I missing something here? I'm following the rules of keeping track of memory, but when I start trying to do anything that's worth anything, suddenly my memory is getting tossed around and stolen by god knows what. How do you POSSIBLY manage memory?