In my app,everything works fine when run for first time.When I navigate through other views and went back to the same view,I used viewwillappear to call functions.
On this run,the connection request line gets executed but the connection delegates like didReceiveResponse,didreceivedata,didfinishloading,didFailWithError are not being called.
-(void)viewWillAppear:(BOOL)animated{
[self recentOrderselection];
[self recentOrderStatus];
[super viewWillAppear:animated];
[self.tableview reloadData];
}
-(void)recentOrderStatus{
..................
NSData *requestData = [NSData dataWithBytes:[json1 UTF8String] length:[json1 length]];
[request setValue:#"text/plain" forHTTPHeaderField:#"content-type"];
[request setHTTPBody: requestData];
connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
NSLog(#"URL>>>%#",url);//Got correct URL in log
}
You should always put [super viewWillAppear:animated]; at first line
And check whether the viewWillAppear function is called when you came back to same view
Related
I've been beating my head against a wall with this problem, and need some help.
I am trying to display a UIActivityIndicator while I load data in the background. I'm not sure if this is relevant or not, but I am loading a tableview. The indicator appears, but doesn't spin...unless I touch the screen, or something else happens while loading-like if I receive a text message. Here is the code:
UIActivityIndicatorView *av = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
av.frame=CGRectMake(145, 160, 25, 25);
av.tag = 1;
[self.mTableView addSubview:av];
[av startAnimating];
[self performSelectorInBackground:#selector(load) withObject:nil];
I've also tried this:
UIActivityIndicatorView *av = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
av.frame=CGRectMake(145, 160, 25, 25);
av.tag = 1;
[self.view addSubview:av];
[av startAnimating];
[self performSelectorInBackground:#selector(load) withObject:nil];
and have tried it with commenting out the last line-So not having the background thread run. I have tried both versions of the code in my viewDidLoad and viewDidAppear methods.
Any ideas?
Edit Here is my load method
- (void)load {
NSString *post = [NSString stringWithFormat:#"id[]=%#", [ids objectAtIndex:0]];
for(int i = 1; i < ids.count; i++){
post = [NSString stringWithFormat:#"%#&id[]=%#", post, [ids objectAtIndex:i]];
}
NSURL *url=[NSURL URLWithString:#"http://myurl/instructions"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
/* when we user https, we need to allow any HTTPS cerificates, so add the one line code,to tell teh NSURLRequest to accept any https certificate, i'm not sure about the security aspects
*/
//[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *data=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
[self parseData:data];
[spinner stopAnimating];
}
You didn't include enough code to see where you're stopping the UIActivityIndicator animation and what's going on while you're displaying it, but the problem almost certainly is one of the following:
1) You're expecting your code to wait for some asynchronous method, which is causing your activity indicator to get shut off prematurely,
or
2) Both the "background" task and the UIActivityIndicator are running on the same thread, and your "background" task is monopolizing the thread to the point where the activity indicator doesn't get enough time to animate.
This post provides an example of how to push the UIActivityIndicator into its own thread:
Activity Indicator doesn't spin
The UI needs time to load, and can't start the animation immediately. By starting it with an NSTimer in the viewDidLoad method, the problem was solved.
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(spin) userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:UITrackingRunLoopMode];
and the scan method:
spinner = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
spinner.center = self.view.center;
spinner.hidesWhenStopped = YES;
[spinner startAnimating];
[self.view addSubview:spinner];
if ([spinner isAnimating]) NSLog(#"animating");
else NSLog(#"not animating");
[self performSelectorInBackground:#selector(load) withObject:nil];
Hopefully this helps.
It's not clear where you're adding the activity indicator but, if it's not on the main thread, then UI calls to it may not work. I typically set up a separate routine to start & stop my activity monitors, so I can performSelectorInMainThread: them.
Not related to the activity indicator, but your load method rewrites the post variable in a loop. I think you intend to concatenate:
post = [post stringByAppendingFormat: ...]
Otherwise your web service will see only the last param.
Also, once you get your spinner animating, the next problem you'll have is that it won't stop because stopAnimating is being called off the main thread.
I've this code but I can't understand why I must run this on the main thread.
If I run this in the background It doesn't do the post request. Is it a bug?
How can I solve this problem?
- (void)setRead:(MWFeedItem *)entry
{ [self getToken:YES];
NSString *url=[NSString stringWithFormat:#"https://www.google.com/reader/api/0/edit-tag?a=user/-/state/com.google/read&i=%#&T=%#", entry.identifier, token];
[self postRequestWithURLState:url];
}
- (void)postRequestWithURLState:(NSString *)url
{
NSString *bodyRequest = nil;
NSURL *requestURL = [NSURL URLWithString:url];
NSMutableURLRequest *theRequest = [[NSMutableURLRequest alloc] init];
//NSLog(#"-------------- bodyRequest: %#", bodyRequest);
[theRequest setURL:requestURL];
[theRequest setTimeoutInterval:0.5];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody:[bodyRequest dataUsingEncoding:NSASCIIStringEncoding]];
[self.oauthAuthentication authorizeRequest:theRequest];
[NSURLConnection connectionWithRequest:theRequest delegate:self];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
this is my call:
-(void)segnaLettura:(MWFeedItem *)item{
[reader setRead:item];
}
- (void) segnaread:(MWFeedItem *)item{
[self performSelectorOnMainThread:#selector(segnaLettura:) withObject:item waitUntilDone:NO];
}
In order for an asynchronous NSURLConnection to function, it requires the thread's runloop to be processed. While new threads automatically get a runloop, it is up to you to run it.
You can learn how to do this in the Threading Programming Guide, and I can explain it more, but most of the time this isn't what you want. Most of the time in iOS, background threads should be managed with NSOperation or GCD. Generally, if you're manually spawning a thread on iOS 4+, you're doing it wrong. There are exceptions, but not often.
The first question here should be "why do I even have a background thread for this?"
If you really need a background thread, then the way you're doing segnaread is probably fine.
In one of my previous post someone suggest me to use the
NSURLConnection *conn = [NSURLConnection connectionWithRequest:theRequest delegate:self];
To make connection in a new thread to keep GUI working without freezing during the connection.
But It now I can realize that this doesn't work.
This is the whole method.
- (void)postRequestWithURLState:(NSString *)url
{
NSString *bodyRequest = nil;
NSURL *requestURL = [NSURL URLWithString:url];
NSMutableURLRequest *theRequest = [[NSMutableURLRequest alloc] init];
//NSLog(#"-------------- bodyRequest: %#", bodyRequest);
[theRequest setURL:requestURL];
[theRequest setTimeoutInterval:2.0];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody:[bodyRequest dataUsingEncoding:NSASCIIStringEncoding]];
[self.oauthAuthentication authorizeRequest:theRequest];
NSURLConnection *conn = [NSURLConnection connectionWithRequest:theRequest delegate:self];
self.web = conn;
}
That is part of a class called greader. So I use this method in this mode.
reader = [[greader alloc] init];
[reader setDelegate:self];
Than I call it [reader postRequestWithURLState:url].
But in this way it still freeze my app for some seconds. How can I execute this action without freezing my app for some seconds?
This is strange. I cannot see why this method would freeze your UI.
One simple solution is to call the method in separate thread. Make the reader a property (or pass it to the method below):
-(void)postReaderRequest:(NSURL)url {
[self.reader postRequestWithURLState:url];
}
and then
[self performSelectorInBackground:#selector(postReaderRequest)
withObject:[NSArray arrayWithObject:url]];
If the result is the same, it must have been something else.
Try using NSThread to execute your NSURLConnection
I have a problem with hiding modalviewcontroller when I connect to server with ASIHttpRequest.
I connect in background thread and show modalview in main thread.
This is my code:
[self performSelectorInBackground:#selector(loginServerRequest) withObject:nil];
- (void)loginServerRequest {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSURL *url = [NSURL URLWithString:#"https://11.111.111.11/api/login"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:[AccountSettings getCompany] forKey:#"companyName"];
[request setPostValue:[AccountSettings getEmail] forKey:#"email"];
[request setPostValue:[AccountSettings getPassword] forKey:#"password"];
[request setRequestMethod:#"POST"];
[request setTimeOutSeconds:10];
[request setValidatesSecureCertificate:NO];
[request setDelegate:self];
[request startSynchronous];
[pool drain];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
[self performSelector:#selector(hideServerConnectView) withObject:nil afterDelay:0.0];
int status = [request responseStatusCode];
NSLog(#"%i", status);
if ([self.nibName isEqualToString:#"RootViewController"]) {
if (status == 200) {
//some code
}
}
}
- (void)hideServerConnectView {
[self.parentViewController dismissModalViewControllerAnimated:NO];
}
If server responses immediately modalviewcontroller doesn't hide!
If pass some seconds then everything is okay.
What's the problem??
I changed my code like this:
[self loginServerRequest];
ServerConnectView *viewC = [[ServerConnectView alloc] init];
[self.view addSubview:viewC.view];
[self presentModalViewController:viewC animated:YES];
[viewC release];
- (void)loginServerRequest {
NSURL *url = [NSURL URLWithString:#"https://11.111.111.11/api/login"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:[AccountSettings getCompany] forKey:#"companyName"];
[request setPostValue:[AccountSettings getEmail] forKey:#"email"];
[request setPostValue:[AccountSettings getPassword] forKey:#"password"];
[request setRequestMethod:#"POST"];
[request setTimeOutSeconds:10];
[request setValidatesSecureCertificate:NO];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request{
[self hideServerConnectView];
int status = [request responseStatusCode];
NSLog(#"%i", status);
if ([self.nibName isEqualToString:#"RootViewController"]) {
if (status == 200) {
//some code
}
}
}
- (void)hideServerConnectView {
[self.parentViewController dismissModalViewControllerAnimated:NO];
}
And it didn't solve my problem.
Any ideas? Or something wrong?
You're mixing async and sync methods.
You set up the request as though it's an async request, but then call [request startSynchronous];.
Because of this, the delegate methods will not be called and your modal will not be dismissed.
The fix is to fire off the request async, using [request startAsynchronous];
This also means that you don't need to call performSelectorInBackground (or setup the autorelease pool in the loginServerRequest method).
In your asynchronous version, move [self hideServerConnectView]; just after [self loginServerRequest];
OR use - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait to invoke - (void)hideServerConnectView since UI update must occur on the Main Thread.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSString *country=[[NSUserDefaults standardUserDefaults]objectForKey:#"namecountry"];
//url's
NSURL *url = [NSURL URLWithString:#"someurl"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:country forKey:#"c_name"];
[request setRequestMethod:#"POST"];
[request setValidatesSecureCertificate:NO];
[request setDelegate:self];
[request startSynchronous];
NSString *response = [request responseString];
NSLog(#"%#",response);
res=[response componentsSeparatedByString:#","];
NSLog(#"%#",[res objectAtIndex:18]);
show=[NSString stringWithFormat:#"%#",[res objectAtIndex:18]];
float f=[show floatValue];
show=[NSString stringWithFormat:#"%.2f %%",f];
[self.tableView reloadData];
}
I've read posts and try lots of different ways but can't find the correct solution.So here is my problem: I have 3 tab bar items this one is the middle one.When i click it shows the tableview and it has detailTextLabel.text . I want to update the tableview when the user press the the tab bar i want him to see the updated one.
Now i try several ways as you can see [self.tableView reloadData]; i put it all the methods in the UITableView class can anybody tell me what is wrong i am doing in this?
in your .h file you have something like this: NSArray* myData
in the .m file the tableView gets data from this myData array
all you have to do is set the new data to the array your tableView uses as a datasource.
self.myData = res; right before you reload data