I ran into the situation where my class is making one asynchronous web call and the user requests another one (by moving a map) and can't seem to properly cancel the NSURLConnection. I have seen some solutions to manage multiple async calls, but I do not want to do that because once the second request is made I no longer care about the first. I see that there is a cancel method, but I tried only calling it when the connection is nil, but the connection never seems to become nil despite a release on that object. Does anyone have a code sample of a proper cancel of an async NSURLConnect?
I don't think you understand Objective C message passing or retain/release. Sending a retain or a release to an object will never cause the pointer you are holding for that object to become nil (though the object may no longer be valid). In other words:
id a = b;
[a release];
//since release never changes the value of a
assert(a == b);
Okay, so having said that, if somehow a release code change the value of object pointer you called it against to nil, then sending a another message to it would do nothing. Messages to nil are silently dropped. Remember, what you are holding is a pointer to the object, not the object itself.
Having said that, if you want to cancel an NSURLConnection. You have to send it the cancel before you release it (in general it is never correct to send message to objects after you have released them).
I really recommend you read Apple's Memory Management documentation.
Related
I have a class that acts as a wrapper around AVPlayer, and one of the functions it serves is to post notifications every 1 and 10 seconds during playback (ie make addPeriodicTimeObserverForInterval: more convenient in the general case).
Previously, the object I was sending with this notification was the player wrapper itself (ie ABPlayer.sharedPlayer). Today I had the need to allow for some objects to only receive notifications about a specific media item's playback. This can be accomplished by sending [[someAVURLAsset URL] absoluteString] as the notification object (when the asset in the AVPlayer is an AVURLAsset, of course).
The prompted the question: is it appropriate for a single notification to, in different situations, post with different types of objects? I understand the value in sending specific objects or sending nil (catch-all), but I don't recall seeing a situation where an alternative type of object could be sent. In my case, though, it seems to make sense.
I could simply send two distinct notifications, but since these are always only ever being sent to notify observers of a single event, and they are always being sent from the same place in code, they simply feel like a single notification.
I realize what I have is possible and working, but I'm curious if there's a compelling reason to avoid this pattern.
As long as the scenarios in which the different object types will be sent to the observers are well understood and documented, there's no technical reason why you can't do it. It may make more contextual sense to post a different notification for each object type. It would certainly help any developers who may end up maintaining your code.
I need to send a server a set of requests with some data. The data in the subsequent requests will be determined based on the server response in the earlier requests. I do not want to use synchronous approach with NSURLConnection class, as it is very limiting (for one of the requests, for instance, i need to prevent redirects. According to Apple Dev documentation this can only be done with Delegate implementation).
Depending on which request in the chain it is, i need to be doing different things (send different messages to various classes).
The way i see it now, is that i have to either create n delegates for each of my requests, or create a delegate which would initWithFlag and then create the instances of that delegate with different flags, or i need to use something like a factory pattern which would be pretty similar solution to the second one.
I do not WANT to implement a delegate at all, i want to send requests with the least bit of coding possible.
I am also not looking at any frameworks (ASIHTTPRequest etc), i would like to do it with the native classes.
What would be the best approach?
I know you said you don't want to use third party frameworks, but I'd really suggest AFNetworking. With that said, you do not NEED AFNetworking or any third party library, it will just make your life easier IMHO.
So, what I have done in a similar scenario is essentially use the Command Pattern. When I want to send off one of these complicated "requests" I initialize a command object, set all of the necessary parameters and then call execute. My command object has completion and failure handlers/blocks and execute is an asynchronous call.
Within the command I have different 'steps' that are effectively synchronous and depend on each other. Let's say request A depends on B and B depends on C, the first step of the command is to execute A on it's own queue (I am using GCD with a private queue) and wait for it to finish. Once A finishes (successfully) I continue on to B and pass in any results I need from A into B. Likewise for B->C. If any of the intermediate requests fail throughout the process I can execute the failure block and handle it from where I executed the command (consumer end). If all finish successfully I execute the success block.
I prefer the encapsulation of this approach as it is very easy to re-use throughout the project, all of the intricacies are tucked away in the command's implementation.
Oh and the fact that I use callbacks/blocks I did not need to implement any delegates. In your case using the NSURL classes your command object would be the delegate of any of those instances.
I have settled on implementing the delegate after all.
The key things that tripped me were:
Do NOT declare the delegate methods in .h file. They won't work like that. Simply add them to implementation.
A delegate can be init'ed within the NSURLConnection initWithRequest method or it can be held as a property of the parent class, there is no difference.
The best way to handle multiple requests is the suggested initWithFlag. Therefore, it is best to create a delegate when initialising connection. The delegate lives long enough to perform full data transfer under ARC.
The most convenient way to cancel the redirect comes from Apple's Developer Library:
-(NSURLRequest *)connection:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse
{
NSURLRequest *newRequest = request;
if (redirectResponse)
{
newRequest = nil;
}
return newRequest;
}
Please note that this message is sent several times during the life of the connection for undisclosed reasons. However, if the response is not an actual redirect, the redirectResponse will be nil.
Setting the request to nil will cancel the redirect, but NSURLConnection will finish processing the original data (that is, connectionDidFinishLoading message will be sent).
You can cancel this behaviour by sending this message:
[connection cancel];
I found NSNotifications to be the best way to pass results to the parent class.
I have a singleton wrapper class called "Folio APIWrapperv2" that is responsible for handling all of my API data calls within my iPhone app.
This class implements ASIHTTPRequest in order to fetch JSON from my server. When an ASIHTTPRequest has finished, it calls requestFinished:. In this method, I have additional processing of the data that can take a couple of seconds to complete. It's not major, but it slows down the app slightly, as it's a blocking call. To fix this, I create a new thread using GCD. However, when this thread runs, I get the following error:
[FolioAPIWrapperv2 respondsToSelector:]: message sent to deallocated instance 0x245050
This function is being called in ASIHTTPRequest's "handleBytesAvailable" method at the line:
if ([[self delegate] respondsToSelector:[self didReceiveDataSelector]]) {
I'm not sure what's going on here. FolioAPIWrapperv2 is a singleton class, so it should never be deallocated. I've tried searching online to see what other issues people have had with threading and couldn't find a suitable solution. Does anyone have an ideas?
Are you setting the delegate to be an instance of the class or the class itself? The delegate must be an instance of a class.
Otherwise, if you're getting the output:
[FolioAPIWrapperv2 respondsToSelector:]: message sent to deallocated instance 0x245050
Then it seems likely that your class that should never be deallocated is getting deallocated.
Either way, at least one way to approach this is to add some debugging, eg, when you create the request:
NSLog("set delegate to %p", request.delegate);
and similar logging for self in the init/dealloc of your singleton.
I have a small confusion in my application.
How can I check whether an object was released or not in iPhone?
Sorry, but you're trying to solve the wrong problem.
If you follow some simple rules there is absolutely no need "find out" whether an object has been released or not; you will know.
The simple rules are:
If you alloc, copy or retain an object, then you are responsible for releasing it
Otherwise, you are not responsible for releasing it
Do not use retainCount. If the object has been deallocated (i.e., its retain count is zero), then you can't perform any operations on the object since it no longer exists! Also, even if it's currently one, what's to say that it's not in the autorelease pool and will be zero the next time you look?
If object was released then you cannot access its properties.
You can use Profiler (NSZombies) to detect which objects were released and then accessed.
any message to the object when zombies are enabled will suffice. if the program crashes because you messaged a zombie, then you know!
if you have enabled reference count tracking in instruments, then you can see each frame of each ref count event and find out where the invalid ref count offset has been introduced.
I have a Objective-C class that makes an HTTP request and, after receiving a response, calls methods on its delegate. The class provides some convenience methods around the built-in NSURLRequest for my application.
My question is: how do I ensure that I release this object? Normally, an object's owner is responsible for ensuring that an object gets released. In this case, there's no obvious owner. I want to create an instance of this class, set its delegate, fire off the HTTP request, and then forget about it (I could be making several of these requests, so the only way to give it an owner would be to keep a list of the request objects in the calling object, which seems suboptimal).
One approach I've considered: when the HTTP response comes in, my object calls its delegate and then does [self autorelease]. The problem is that all clients have to remember not to release this instance (or else my object needs to call retain before it returns to the user).
Anyone have any good patterns for this?
Apple have already thought of this pattern. On the assumption that you are using NSURLConnection, check out the documentation for -initWithRequest:delegate: Here is what it says about the delegate parameter:
The connection retains delegate. It releases delegate when the connection finishes loading, fails, or is canceled.
[my emphasis]
So when you create the connection, set your object as the delegate. It won't go away until the connection is terminated for whatever reason, even if no other object of yours retains ownership.
By the way, the statement
there's no obvious owner
is false. You say your object has a delegate. The delegate is the obvious candidate to be an owner.