Xcode 4 warning "Expression result unused” for NSURLConnection - iphone

I'm just trying to do my usual data transfert. I define my NSMutableURLRequest then call
[[NSURLConnection alloc] initWithRequest:request delegate:self];
This used to be ok with Xcode 3 but Xcode 4 warns me about "Expression result unused" on that line.
The request does work but I would like to find a way to get rid of the warning.
I suppose I could store the connection in a variable but I don't really need it and I can't see the point of setting it to nil the next line (although this would remove the warning)
Please note: I'm not 100% sure if it's Xcode 4 or the fact ARC is enabled.

When a function returns a result that you don't need you can cast it to void to eliminate the compiler warning:
(void) [[NSURLConnection alloc] initWithRequest:request delegate:self];
I haven't used ARC yet so I can't say if this is a good idea, before ARC you would need to keep this pointer result somewhere so you could release it.

progrmr's answer is correct, but here's an even cleaner way to do it:
[NSURLConnection connectionWithRequest:request delegate:self];
This doesn't cause a warning, even if you don't cast the result to void.

Someone should be responsible for that NSURLConnection. It is not needed to store the connection but it is better coding if you do. The problem is that after you created our NSURLConnection no one has a pointer to that created instance which should not be the case.
Let's assume the following example:
your instance of ClassA is creating an instane of NSURLConnection
your instance of ClassA is beeing released and dealloced
NSURLConnection is still alive and will fire the delegate to your deallocated instance.
To solve that problem you should store the instance of NSURLConnection and should release that connection if your instance of ClassA is being dealloced which results in deallocating the instance of NSURLConnection as well.

Related

Why does using __weak not cause local variable to nil out immediately?

I've been working on the same project for some time now, and my understanding of Objective-C and Cocoa has evolved a little through time. Looking back in some parts of my code, I see this:
__weak ASIFormDataRequest *serverQueueRequest = [ASIFormDataRequest requestWithURL:url2];
[serverQueueRequest setCompletionBlock:^{
NSLog(#"%#", serverQueueRequest.responseString);
}];
[serverQueueRequest startAsynchronous];
And that's how I've been processing all my server requests. I think I did that to suppress a warning, namely that "capturing request in block may lead to a retain cycle". So I made it weak, and that seems to have solved all my issues. I haven't noticed any real problems with this.
However, looking at the code now, it seems a little odd that it works. When I declare the request as __weak, shouldn't it immediately zero out since no one is holding on to it? Why does this code work?
Also, although this code works, I just recently discovered a case where it doesn't: when calling the method that contains this code several times in succession, say 5 times within the span of a second, 3/5 requests will have a NULL response. This is consistently the case. Removing the __weak qualifier solves this issue. What's the explanation for that?
And so finally, what is the correct way to declare a local request like this?
Update: According to this question, the correct way to do it is like so:
ASIHTTPRequest *_request = [[ASIHTTPRequest alloc] initWithURL:...
__weak ASIHTTPRequest *request = _request;
Edit: actually the fix above does not fix the issue where calling the code 5 times results in NULL responses. That problem still exists. The only way that problem goes away is by capturing the request strongly and not using any qualifiers.
Now the question is why my original code still worked..
Quoting from Apple's Programming with ARC Release Notes:
Take care when using __weak variables on the stack. Consider the
following example:
NSString __weak *string = [[NSString alloc] initWithFormat:#"First Name: %#", [self firstName]];
NSLog(#"string:%#", string);
Although string is used after the initial assignment,
there is no other strong reference to the string object at the time of
assignment; it is therefore immediately deallocated. The log statement
shows that string has a null value.
The obj C stack will always retain pointers in scope. _weak does not mean release right now it means release when the stack goes out of scope.
When you declare a var and then make calls on it in the same stack scope it will not be released until after (minimally) the stack is cleaned up.
Blocks extend method scope since they imply potentially asynchronous behavior and they utilize the stack that was present when they were invoked.
I believe it is because you are running the weak variable in a block. The block holds onto the state of the weak variable which In turn causes it to work. I'm betting much work on the variable once the block is complete may cause issues.
My guess in why it fails if you run it many times is because the asynchronous asi call stack gets to high and bombs. I've seen this before and if you are very patient you can catch the asi blow up in the debugger.

Variable released prematurely during asynchronous request

My memory-management and threading knowledge is very limited, so I may be missing something really basic. I've found a work-around for this problem, but it really, really bothers me that I can't see what's happening.
I have a class that makes two asynchronous HTTP requests, one for an XML configuration file and another for an image. Because there are two asynchronous requests going on in the same class, I'm reusing the same NSURLConnectionDelegate methods (maybe factor). I first asynchronously fetch the configuration file and extract two urls, stored as sponsorImage and sponsorUrl. Then I use the value of sponsorImage to asynchronously fetch image data. I've found, though, that after I've got my image (after the second asynchronous event has completed), sponsorUrl has been released.
I accidentally found that I can prevent sponsorUrl from getting released if I "do something to it" in the method where the image request is created -- and by "do something", I mean just that. Basically, my code looks like this:
- (void) loadImage
{
sponsorUrl = [sponsorUrl stringByAppendingString:#""];
NSURL *url = [NSURL URLWithString:sponsorImage];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:dateString forHTTPHeaderField:#"If-Modified-Since"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
[connection release];
}
If I remove the first line of this method (where I'm adding "" to the url), the variable is retained. If I remove it, it gets released. This makes no sense to me at all.
I've tried declaring sponsorUrl with #propterty (nonatomic, retain); I've tried declaring sponsorUrl statically; I've tried adding [sponsorUrl retain] where I set it, but it doesn't make a difference. The only thing that works is "touching" the variable before making the second request.
What am I missing?
As your are using a convenience constructor the variable is autoreleased! Only if you are using methods like alloc, copy or new they are retained implicitly.
Secondly, by writing sponsorUrl = .... your are not using the generated setter but the generated instance variable. You will need to write self.sponsorUrl = #"Blah"; or [self setSponsorUrl:#"blah"] in order to have the setter retain the variable.
Indeed, it seems you have some issues with memory management.
It is pretty difficult to explain what is happening because you are not providing the full code that uses your variables. Just as an example, take the statement:
sponsorUrl = [sponsorUrl stringByAppendingString:#""];
what you do is assigning to sponsorURL a new value; the old value (the one you initialized the variable with in the first place, i.e., the one that got the retain you mention) is released (stringByAppendingString forges a new object); the new object that sponsorURL points to is an autoreleased object whose lifetime is not exactly known: we only know that at some point it will be freed (possibly at the next main loop iteration). So, by "touching" the variable, you are assigning a new value to it which has a lifetime starting with the point where you touch the variable... pretty unreliable, in any case.
My suggestion is the following:
define two properties in your class to handle sponsorURL and sponsorImage;
make them of the retain kind;
assign value to them only through their accessor methods, i.e, self.sponsorURL = [...]
make sure that any objects you assign to the properties are autoreleased objects (or else, do a release with the assignment).
If you provide more code, then it would be possible to review it more thoroughly, but if you follow the guidelines above, you will have no problems at all (approx...)

iPhone NSURLConnection initialization problem

What is difference between this two lines, they are in different apps but first one seems to work and I have problems with the second one; and which one should i choose over another? my app will constantly receive and send back data with a webservice.
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
NSURLConnection *theConnection = [NSURLConnection connectionWithRequest:request delegate:self];
And where should I release the connection object, after every didFinishLoading? but then doesn't it take much time on every request to connect?
The first one is an instance of NSURLConnection where you take ownership of the object, so you have the responsibility and hence must release it. Details on ownership reference.
The second one is an auto-released object so you dont need to release it. It will be released automatically when the auto-release pool is drained.
The second creates an auto-released connection, so if you don't explicitly retain it, it will disappear and your application will probably crash.
You can use either, you just need to understand objective-c memory management on the iPhone.
There is, as ever, a good explanation on the Apple site, it really is worth reading and understanding as once the penny drops, you'll never make the same mistake again.
with first line you create an object with init method , which make you the owner of the object , so you must release it . The second line you use a convenient constructor, which does not make you owner of that object.in this case, if you want to manipulate with life-cycle of that object you must send another message to retain it : NSURLConnection *theConnection = [[NSURLConnection connectionWithRequest:request delegate:self] retain], and the count of object will be 2 .. even if in the second line your object automatically receive a autorelease message , the count after that will be 1 .. so if you retain object you must release it ...
you asked : And where should I release the connection object ? i think in method called connectionDidFinishLoading:connection or in the method connection:didFailWithError:

Memory leak found with clang but cant release and autorelease crashes

I have a class that builds a request based on a few passed in variables. The class also has all the delegate methods to receive the data and stores it in a property for the calling class to retrieve.
When the class initializes it creates a connection and then returns itself:
NSURLConnection *connection;
if (self = [super init]) {
self.delegate = theDelegate;
...some code here...
connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
}
return self;
So I can't release it normally and if I autorelease it crashes. Is it the job of the calling class to release? And if so does just releasing the initilised object also release connection or do you have to release it specifically? If so how would you?
Thanks
Make connection an instance variable and release it on-demand. The question "who" should release the object depends strictly on your object semantics and hierarchy.
Why are you opening an NSURLConnection within a constructor?
Typically, your constructor shouldn't perform this type of work. If the connection is associated to the object, I would make connection a property of the object and [connection release]; within the object's dealloc method.
Remember that you shouldn't place all your faith in Clang. It can and does report false negatives and false positives.
Clang is getting better every day, but it still in its infancy right now. It's great that it's integrated with Xcode so nicely, but just keep in mind that it does have some flaws.
In this case, it depends on the scope of the variable you're storing the connection object in. If it's declared as an instance variable, then it should be ok, as long as you release it in dealloc or at some other point when you're done with it.
If, like you've posted in your question, the declaration of connection is local to your init method, then Clang is correctly reporting a leak. You should make connection an instance variable or property and ensure you release it in dealloc or when you're finished with it.

Downloading multiple files in iphone app(Objective c)

In my iPhone app I want to download multiple files which are on IIS with authentication. On a button click i want to start the downloading process.
I know how to download a file with authentication.
NSURLRequest* request =
[NSURLRequest requestWithURL:mMovieURL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
movieConnection =
[[NSURLConnection alloc] initWithRequest:request delegate:self ];
and i have couple of delegate methods with the above code.
But how to do it with mutliple downlaods going at the same time.
Thanks,
I'm not familiar with MultipleDownload, but in case it doesn't meet your needs, the issue I take it is that you have a single object that is the delegate to many NSURLConnections, and you want to know how to keep them straight.
The delegate methods all return the NSURLConnection itself as their first parameter. So you can keep track of which data goes where by testing which NSURLConnection is calling you back. One way to do this is with an NSDictionary that maps the connection to its NSMutableData object. Now the trick is that you can't make an NSURLConnection be the key in a dictionary because it doesn't conform to NSCopying (and you wouldn't want it to). One way to work around this is to use the address of the connection such as:
NSString *key = [NSString stringWithFormat:#"%p", connection];
This will return a unique key for any object (the hex representation of its address). Some people use description for this purpose, but I don't like that because it's not a well defined interface. There's no promise that it be unique. In systems where I do this a lot, I implement the above -stringWithFormat: in a method called -uniqueIdentifier and make it a category on NSObject so anything can be tracked in a dictionary.
I often find it's easier just to create a small wrapper object so that each object controls its own NSURLConnection, much as I'm sure MultipleDownload is doing, but still this technique is useful in a variety of cases, whether you're managing multiple tableviews, or anything else that has a delegate.
EDIT: Replaced %x I had above with %p as noted by Peter. He's right, and I wasn't thinking correctly. Double-checking my code, I actually have been using %p, having run into this error before....
I've done this before when I wanted to download 10 XML files at the same time (it was much faster than queuing them to download one after the other). I used the libraries found here:
http://github.com/leonho/iphone-libs/tree/master
They were easy to implement and there's some example code on the front page to get you started.
self.urls = [NSMutableArray arrayWithObjects:
#"http://maps.google.com/maps/geo?output=json&q=Lai+Chi+Kok,Hong+Kong",
#"http://maps.google.com/maps/geo?output=json&q=Central,Hong+Kong",
#"http://maps.google.com/maps/geo?output=json&q=Wan+Chai,Hong+Kong",
nil];
self.downloads = [[MultipleDownload alloc] initWithUrls: urls];
self.downloads.delegate = self;
Good luck.
I think the simplest way to do this is to use NSOperation - and a NSOperationQueue.
This will mean that you can specifiy if each operation should happen sequentially or in parallel. You can even limit the number of parallel operations - so that there are a max of 5 (say) running at one time time and then other operations queue up behind.
This really is a great way of letting the OS handle multiple activities - and works well with the lazy loading type philosophy of the iPhone OS.
You can then get each operation to make a call back as it finishes - or even make progress callbacks on the main thread.
I have changed my code to all work this way now and found it to be much more robust and user firendly.
I'm not familiar with
MultipleDownload, but in case it
doesn't meet your needs, the issue I
take it is that you have a single
object that is the delegate to many
NSURLConnections, and you want to know
how to keep them straight.
The delegate methods all return the
NSURLConnection itself as their first
parameter. So you can keep track of
which data goes where by testing which
NSURLConnection is calling you back.
One way to do this is with an
NSDictionary that maps the connection
to its NSMutableData object. Now the
trick is that you can't make an
NSURLConnection be the key in a
dictionary because it doesn't conform
to NSCopying (and you wouldn't want it
to). One way to work around this is to
use the address of the connection such
as:
NSString *key = [NSString
stringWithFormat:#"%p", connection];
A better way would be to use NSValue with the valueWithNonretainedObject constructor. That way you can access the key object from the NSDictionary if you have to.
NSURLConnection is asynchronous and init exits immediately. Just run it multiple times.
NSArray *connections = [[NSArray alloc] initWithObjects:
[[NSURLConnection alloc] initWithRequest:request1 delegate:self ],
[[NSURLConnection alloc] initWithRequest:request2 delegate:self ],
[[NSURLConnection alloc] initWithRequest:request3 delegate:self ],
[[NSURLConnection alloc] initWithRequest:request4 delegate:self ],
nil];