I am sending a request and on receiving the response i need to check the condition and only then navigate to the next screen but then this condition is checked even before i receive the response. How can i check the condition only after receiving the response. Thanks in advance.
Are you using NSURL Connection or any Component??
Try using NSURL Connection delegates. Check out this link:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/occ/cl/NSURLConnection .
I think any of the two methods will work.
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data OR
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
I would consider using the ASI library. It is nicer to use than NSURLConnection.
Either way, you should start the request asynchronously and set the delegate to self.
When you receive the response in the delegate callback you can then continue to the next screen.
For ASI you would do ...
- (void)dorequest
{
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
// Do no do anything else in this method.
// wait for the response to call your delegate method
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
[self loadNextScreen];
}
NSURLConnection would use similar code. Just make sure you use the asynchronous method.
i feel the problem wasn't explained properly because it was misunderstood. I am using NSURLConnection and the request is an asynchronous one, so that was not the question. I needed some code to be executed only after the data download was completed.
I got an answer; by using NSNotifications. In my parser class within connectionDidFinishLoading:(NSURLConnection *)connection method i post Notifications. In my viewcontroller class i added an observer where i execute the needed code.
For more help see : http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/Reference/Reference.html
Thanks
Related
in my app, I'm loading a detailsView from a tableView. I need to get an XML document (with SOAP), parse it, and then display the informations I got in my detailsView. So, when loading my detailsView I want to wait for the parser to parse the entire document BEFORE displaying my detailsView.
In my parser I'm using a NSURLConnection, and methods of NSXMLParserDelegate like parserDidStartDocument, etc...
I've thought of using threads but I'm not getting anything conclusive.
I'm trying to be clear on what I want to do but it's pretty hard :s
I'll provide more infos if needed.
You can do it in either viewDidLoad or viewWillAppear Method but you have to make all your detailview's control hidden until it loads data from the server and then show it when you get response from the parser with the value you get in response. You can show loading indicator while you are parsing your response. You need to call your url Asynchronously.
Do something like this in your viewWillAppear Method :
NSURL *url = [NSURL URLWithString:#"www.yourwebserviceurlhere.com"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
Implement Connection delegate methods.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
After you FinishLoadingData and you got response you need to parse your data by implementing XMLParser delegate method and when you finished parsing you need to show your detailview.
That's it. Hope this help.
I'm working on a TableView which controller downloads data from a web feed, parse and populate its content in this TableView. The feed provides data in chunks of 10 items only. So, for example loading data when there are 112 items could require about 12 requests to server. I would like to make these requests without blocking user screen and it should load data in order, like it can't load items on page 5 unless it has already fetched previous one (1,2,3,4 in this exact order for the example).
Any idea on how to implement this ?
Thx in advance for your help,
Stephane
Make your web calls asynchronous. Dont do web calls on the main UI thread...
For example if you are using ASIHttp library to make http calls (this is built on top of Apple's NSURLConnection), making an async request is as simple as -
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
And when the data is fetched these selector callbacks are invoked -
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
This will definitely make your UI responsive...
Also keep in mind to update UI elements only on the main thread. It's easy to start updating ui elements from background threads. So keep in mind...
You do not need to use another API and can use Apple's own NSURLConnection. It can retrieve the data synchronously or asynchronously. Of course the latter is necessary in your case. You save the data in the requests's delegate methods.
– connection:didReceiveResponse:
– connection:didReceiveData:
– connection:didFailWithError:
– connectionDidFinishLoading:
Also, see my recent more complete answer to this question.
I am having problems in my iphone application due to weak wifi signals. My application uses webservice to retireve data from our server but when Wifi signals are weak the response never comes back and user gets stuck on "Loading..." overlay screen. Finally the application crashes at the end. How can i handle this situation gracefully. Is there a way to set TimeOut for my webservice calls or something like this?
Thanks, Asif.
try to use ASIHTTP lib
http://allseeing-i.com/ASIHTTPRequest/How-to-use
You might want to learn about ASIHTTPRequest as it features much more than the standard CFNetwork api. The code is straight forward, error handling as well:
- (IBAction)grabURLInBackground:(id)sender
{
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
You can set the NSURLConnection timeout and a delegate to respond to connection:didFailWithError: selector. See this S.O. topic.
if your delegate is never being called, this is a somehow known issue.
The only workaround seems to be setting your own NSTimer to fire after some time and cancel the request. It is definitely awkard, but it should not be that complex.
If you are curious about the reason behind the issue with timeout, it seems to be related to the slow starting of the 3G subsystem in an iPhone.
I am loading an image from an API in my tableviewcell, it downloads the image everytime I scroll down the UITableView. So what is the best way to save this image and so it doesn't have to download the image again if it is already there?
Same thing for text, how can I save the text...
If it's not very big, you can download it once and save it into user preferences (NSUserDefaults) as NSData object. Works for me.
Alternatively, you can use asynchronous requests with NSUrlConnection and implement caching in any way you like. (For example, update image only once a week.)
Moreover, even default cache settings of NSUrlConnection might work good enough.
More on caching
edit
An example of asynchronous request.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: url]];
URLConnectionDelegate *delegate = ...;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:delegate];
if (!connection) {
// something went wrong
}
In delegate, you mainly need methods to handle received data and to finish connection.
Assume you have NSMutableData *receivedData object.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// success, do whatever you want with data
[receivedData release];
[connection release];
}
The link above and API documentation provide more details about delegate structure.
Look at the LazyTableImages sample application in the iOS site sample code section. It has a great example of how to download images for a table cell using NSUrlConnection asynchronous calls and storing the images (and text) in an NSMutableArray.
This sample demonstrates a multi-stage
approach to loading and displaying a
UITableView. It begins by loading the
relevant text from an RSS feed so the
table can load as quickly as possible,
and then downloads the images for each
row asynchronously so the UI is more
responsive.
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. :)