viewDidAppear being called before WebService connection methods - iphone

ViewDidAppear method I put breakpoint in the last step of the operation, but the breakpoint viewDidAppear method of putting at first, trying to run it directly.
Are emerging in connection using WebService. Be the first breakpoint while running webservice connections, calling the latest viewDidAppear. However, prior to providing breakpoint viewDidAppear when calling WebService connection, and this causes the value NULL to return.
In short, I would like to be called viewDidAppear method, after obtaining all the webservice connections. Breakpoint when it's like this, but when I want to work in the same way.
- (void)viewDidAppear:(BOOL)animated
{
[self LabelYukle];
[super viewDidAppear:animated];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if(theConnection)
[webData setLength:0];
}

viewDidAppear is called by iOS system on its own just before view is going to be appeared.
If you want to perform some functions after didReceiveResponse method, there is a method in NSURLConnectionDelegate that can help you.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
This method is used when a connection has finished loading successfully and you can write the functions you want to perform after didRecieveRespose here in this method.
You can read more about NSURLConnectionDelegateProtocol methods here.

Related

Update ULabel immediately while downloading files

I am using NSURLConnection to download the files . I have a UILabel in my View which has to display the currently downloading files. The UILabel is getting updated at the starting and the end. Lets say I am download 10 files. I am able to set the Label text before start downloading and after completing the download.
I can understand that, the method which I am trying to call is not running in main thread,
So I have used the following code to make it run in the main thread ,
[_myHome performSelectorOnMainThread:#selector(updateLabel) withObject:nil waitUntilDone:YES];
and method is
- (void) updateLabel
{
_fileName.text =[NSString stringWithFormat:#"%#",fileName];
}
This also seems to be not working. Am I doing anything wrong here ?
Can anyone tell me how to update the label immediately ??
SOLVED : I used NSNotificationCenter to send notifications to other class, which will update the labels immediately. I tried with performSelectorOnMainThread, even if both the updateProgress, performSelectorOnMainThread is in same class.
Any reasons for why it didn't worked out , is most welcome.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//update your label
}

Detecting when Asynchronous Connection has completed

I have a class with a method (getAndPlaySong) that gets an text file from a server, gets a specific string from the text, and uses the string (a URL) to get a music file from the server. The first server call to get the text file is quick so I implemented it synchronously. The second takes longer and I want to update the display while it is occurring.
I want the method to wait for the asynchronous request to finish before it proceeds. I have tried putting a BOOL in the connectionDidFinishLoading method:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[_receivedData length]);
[AppDelegate playAudioWithData: _receivedData];
_dataIsReceived = YES; //BOOL
// release the connection, and the data object
[connection release];
[_receivedData release];
}
And then putting a while loop in the getAndPlaySong method:
[self startRequest: correctSongURL]; starts the request asynchronously
while (!_dataIsReceived) {
//do stuff
}
The result is that the app hangs when it reaches the loop. The loop never terminates and I never get the "Succeeded..." output. I am a little confused and would be grateful for some input.
I don't wish to sound rude, but what you have done is the worst possible thing. Of course the app hangs because it has an infinite loop. Even if the loop terminates eventually, while its in the loop your app is stuck - what if the user tries to do something with your app while its in the middle of the loop?
You need to change your mindset and learn how to use event driven programming with a state machine. That's the paradigm of iOS, you have to knuckle down and do some reading and learning and change the way you think about and construct your programs.
After you make the request you do nothing, i.e. there is no code coming next in your code snippet. Instead your app sits there doing nothing (but still responsive) waiting for the connection to finish (while your app is doing nothing, the OS has created a thread on your behalf and the connection code is executing inside it, when its finished your connection code needs to inform the rest of your code it has finished, you could do this via a delegate for example, or via a notification).
And that is not the only thing it needs to sit and wait for - what if the user taps on the screen? What if the user exits your app? What if ...
Your app needs to be able to responde to all possible events and respond quickly, the connection is just one more event it must listen for and respond to. It can't do that if its in a loop.
Never use loops anywhere like this.
"I want the method to wait for the asynchronous request to finish before it proceeds." No you don't - you can never do anything like this in an application with a GUI. The function must finish executing. You need to implement a state machine, every iOS is a state machine, the application delegate is the main thing driving the state machine, then you add more states and transitions between the state as more events get added to the program.
Look at the app delegate and its methods that tell your code the app entered the foreground, or the background, or there is a low memory situation etc. That's event driven programming, and you need to extend and build on that principle to take into consideration your connection events and any other events.
Sorry if I sound a bit harsh.
Your app is hanging on the Loop because it is infinite.
On iOS, NSURLConnectionDelegate is the way to get a call back when data is received on the connection and to be notified when it is done. And EVERYTHING should be done asynchronously and via the Delegate. That is THE way it is done on iOS.
The results as it streams in should be stored in an NSData object in the didRecieveData method.
Look at the docs on NSURLConnectionDelegate, but here is an outline example:
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
int statusCode = [(NSHTTPURLResponse *)response statusCode];
if(statusCode == 404) {
// Post notification and let concerned parties know something went wrong.
[self cleanupConnection];
}
else if( statusCode == 200) {
// Success do something with the data.
requestData = [[NSMutableData alloc] init];
}
else {
[self cleanupConnection];
}
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[requestData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self finishedLoadingAppData];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Connection Attempt Failed with Error:%#", [error localizedDescription]);
}
Two quick options come to mind:
Create a method to call to handle the completed connection
Use the NSNotification API to send a notification when the load is complete
Additionally, you can use the method for NSURLConnection didReceiveData to handle data coming incrementally from the server.

Cocoa Touch - Display an Activity Indicator while loading a UITabBar View

I have a UITabBar Application with two views that load large amounts of data from the web in their "viewWillAppear" methods. I want to show a progress bar or an activity indicator while this data is being retrieved, to make sure the user knows the app isn't frozen.
I am aware that this has been asked before. I simply need some clarification on what seems to be a rather good solution.
I have implimented the code in the example. The question's original asker later solved their problem, by putting the retrieval of data into another "thread". I understand the concept of threads, but I do not know how I would impliment this.
With research, I have found that I need to move all of my heavy data retrieval into a background thread, as all of the UI updating occurs in the main thread.
If one would be so kind as to provide an example for me, I would be very appreciative. I can provide parts of my existing code as necessary.
If you use NSURLConnection it runs on another thread automatically.
in your viewDidLoad:
NSURLRequest *req = [NSURLRequest requestWithURL:theURL];
NSURLConnection *conn = [NSURLConnection connectionWithRequest:req delegate:self];
then you need some custom methods. If you type in -connection and press Esc you'll see all the different methods you can use. There are three you will need with this:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// this is called when there is a response
// if you're collecting data init your NSMutableData here
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// each time the connection downloads a
// packet of data it gets send here
// so you can do [myData appendData:data];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
// the connection has finished so you can
// do what you want with the data here
}
That is basically all there is to it. NSURLConnection handles all the multithreading itself and you don't have to worry. Now you can create an activity indicator and display it and it will work because the main thread is empty. :)

iPhone - How to find NSURLConnection started or not?

There's a delegate in NSURLConnection "- (void)connectionDidFinishLoading:(NSURLConnection *)connection"
This will be called when the connection finishes.
But is there any delegate or way to know when the connection has started.
What you're looking for is the NSURLConnection delegate method connection:willSendRequest:redirectResponse:. It will be called once when the connection starts, but be warned that it will be called again for every redirect response (if there are any).
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
can be used.

My delegate's methods never get called when I use connectionWithRequest:delegate

I'm making an asynchronus POST request in an iPhone app with this call:
[NSURLConnection connectionWithRequest:req delegate:self];
The request seems to get to the server just fine, but none of the delegate methods get hit. I've implemented:
- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
and
- (void) connection:didFailWithError:(NSURLConnection *)connection
None of the log messages for these methods ever appear. The documentation for connectionWithRequest:delegate: says:
delegate
The delegate object for the connection. The delegate will receive delegate messages as the load progresses. Messages to the delegate will be sent on the thread that calls this method. For the connection to work correctly the calling thread’s run loop must be operating in the default run loop mode.
I think the call is being made off of the main thread (is the assumption that, if I didn't start a new thread explicitly, everything runs in one thread correct?), and I checked the thread with this:
CFRunLoopRef loop = CFRunLoopGetMain();
CFStringRef modeString = CFRunLoopCopyCurrentMode(loop);
NSLog(#"The main loop is running in mode: %#", modeString);
Which creates this console output:
2009-09-13 13:32:05.611 Stock Footage[686:20b] The main loop is running in mode: kCFRunLoopDefaultMode
So, that sounds like it is in the default run loop mode. Is there anything else I should look at that could tell me why my delegate methods aren't hit? The delegate is definitely not dying before the request is complete.
Update: CFRunLoopGetCurrent has the mode kCFRunLoopDefaultMode.
Update (5:40 PM Eastern): Well, I've switched to using initWithRequest:delegate: startImmediately in order to get the callbacks going, but I'd still love to see an example of connectionWithRequest:delegate that actually hits the delegate up.
I had a similar problem. The reason my delegates were not being called is that after I called connectionWithRequest, I started a loop that was checking if the data from the connection had been sent. Since I never returned the control to the RunLoop code, the messages left in the queue were never processed, and therefore the delegate's methods were not called either...
Just make sure that you do not do anything heavy after calling connectionWithRequest and everything should work nicely.
Two things jump out at me:
You have the wrong prototype for your error method (should still get called, however):
connection: (NSURLConnection *) connection didFailWithError: (NSError *) error
You should check to make sure you're getting a valid connection back from + connectionWithRequest:delegate:. It's possible it's not even starting the request.