I have this method:
-(void)updateSomething
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSURL *url = [NSURL URLWithString:#"some url"];
ASIFormDataRequest *httpRequest = [ASIFormDataRequest requestWithURL:url];
[httpRequest startSynchronous];
//some other stuff
[pool drain];
}
I call this method onapplicationDidFinishLaunching
IF i call it on the main thread it works fine
[self getMyItems];
But when I call it on a separate thread I get a "Program received signal: "EXC_BAD_ACCESS"
[self performSelectorInBackground:#selector(getMyItems) withObject:nil];
Any idea how to resolve this issue?
Why perform individual requests on separate threads when you can use ASINetworkQueue?
ASINetworkQueue *aQueue = [[ASINetworkQueue alloc] init];
[aQueue addOperation:requestToAdd];
[aQueue setDelegate:self];
[aQueue setRequestDidFinishSelector:#selector(requestFinished:)];
[aQueue setRequestDidFailSelector:#selector(requestFailed:)];
[aQueue setQueueDidFinishSelector:#selector(queueFinished:)];
[aQueue go];
ASINetworkQueue is a subclass of NSOperationQueue and ASI*Requests are run on separate threads.
Related
I have the following timer:
uploadGPS_timer=[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(uploadGPS_tick:) userInfo:nil repeats:YES];
[self uploadGPS_tick:nil];
And here is the callback: uploadGPS_tick():
-(void)uploadGPS_tick:(NSTimer*)timer{
if(!lat || !lng){
//do nothing
}else{
NSString *urlStr=[[NSString alloc] initWithFormat:#"http://www.example.com/ajax/updateCoords.php"];
NSURL *url=[NSURL URLWithString:urlStr];
__block ASIFormDataRequest *request=[[ASIFormDataRequest alloc ]initWithURL:url];
[request setPostValue:lat forKey:#"lat"];
[request setPostValue:lng forKey:#"lng"];
NSLog(#"EOH: %#",lat);
[request setDelegate:self];
[request setCompletionBlock:^{
NSString *response=[request responseString];
NSLog(#"%#",response);
if([response isEqualToString:#"LO"]){
[self.navigationItem setBackBarButtonItem:nil];
DriverLogin *x= [[DriverLogin alloc] initWithNibName:nil bundle:nil];
[[self navigationController]pushViewController:x animated:NO];
}
SBJsonParser *parser=[[SBJsonParser alloc]init];
NSMutableDictionary *obj=[[NSMutableDictionary alloc]init ];
obj=[[parser objectWithString:[request responseString] error:nil]retain];
credits.text=[[obj objectForKey:#"credits"] stringValue]; //this won't show...
creditsUsed.text=[[obj objectForKey:#"creditsUsed"] stringValue]; //this won't show...
NSInteger timeLeftSecs=[[obj objectForKey:#"creditTimeLeft"] intValue];
NSInteger timeLeftMins=(int)(timeLeftSecs/60);
creditTimeLeft.text=[[NSString alloc]initWithFormat:#"%d",timeLeftMins]; //this won't show...
NSLog(#"xxx:%#",obj);
}];
[request setFailedBlock:^{
NSError *error =[request error];
NSLog(#"%#",error);
//do nothing
}];
[request startAsynchronous];
}
}
As you can see, every five seconds, a JSON object is sent from the server. This JSON object is then parsed and three UILabels are set based on this JSON data.
The trouble I'm having is that the UILabels aren't getting their text set! Even though I can clearly see NSLog(#"xxx:%#",obj); in the debugger. The UILabels are connected properly in the .xib.
Any help greatly appreciated.
You should do it from main thread. Replace the label text assignment with following code:
dispatch_async(dispatch_get_main_queue(), ^{
creditTimeLeft.text=[NSString stringWithFormat:#"%d",timeLeftMins];
});
In my application i am using ASINetworkQueue method for downloading files. I have n number of buttons and for each button click different Queues will be created with multiple Requests, and starts download asynchronously (multiple download). It is working fine, but I couldn't track when each Queue completes. I have used,
[self.myQueue cancelAllOperations];
[self.myQueue setDownloadProgressDelegate:currentProgress];
[self.myQueue setDelegate:self];
[self.myQueue setShowAccurateProgress:YES];
[self.myQueue setRequestDidFinishSelector:#selector(requestFinished:)];
[self.myQueue setQueueDidFinishSelector:#selector(queueComplete:)];
and added requests as,
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:str]];
[request setDownloadProgressDelegate:currentProgress];
[request setShowAccurateProgress:YES];
[request setDelegate:self];
[request shouldContinueWhenAppEntersBackground];
[request allowResumeForFileDownloads];
[request startAsynchronous];
[self.myQueue addOperation:request];
and last, [self.myQueue go];
and the delegate method is
- (void)queueComplete:(ASINetworkQueue *)queue
{
NSLog(#"Queue completed");
}
but its not called at the end. What went wrong here? Any idea?
And also, if there are multiple Queues performing at the same time, how can we differentiate which queue is completed at the end?
Edit:
- (void)download{
UIImageView *image = (UIImageView *)[mainView viewWithTag:selectedTag];
for (UIProgressView *currentProgress in [image subviews]) {
if ([currentProgress isKindOfClass:[UIProgressView class]]) {
NSLog(#"Prog tag: %d",currentProgress.tag);
if(currentProgress)
{
currentProgress.progress = 0.0;
[[self myQueue] cancelAllOperations];
[self setNetworkQueue:[ASINetworkQueue queue]];
[[self myQueue] setDownloadProgressDelegate:currentProgress];
[[self myQueue] setDelegate:self];
[[self myQueue] setShowAccurateProgress:YES];
ASIHTTPRequest *request;
[myQueue setQueueDidFinishSelector:#selector(queueComplete:)];
for (int h = 0; h < [urlArray count]; h++) {
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:[urlArray objectAtIndex:h]]];
[[self myQueue] addOperation:request];
}
[[self myQueue] go];
}
}
}
}
You are starting the request before adding it to the queue.
[request startAsynchronous];
The starting of the request should only be handled by the queue. So remove that line and the complete callback should be called.
When you have more than one queue, you should keep a reference to each queue. You could put them in an NSMutableArray. Then in the complete callback you can check which queue is complete by checking them against the queues in your array.
EDIT:
It seems that you forget to set your myQueue iVar, so it was nil and ignored all method calls. So add:
self.myQueue = [ASINetworkQueue queue];
To have more than one queue in an array:
self.queues = [NSMutableArray array] // queues is a retained property
ASINetworkQueue *queue = [ASINetworkQueue queue];
[queues addObject:queue];
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.
I am making one application in which one webservices need to be called, is it possible to call webservices related to JSON in background,when user press homebutton in iPhone
You can call asynchronous request using
NSMutableURLRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"Your webservice URL here"]];
[[NSURLConnection alloc]initWithRequest:request delegate:self];
where you can implement delegate methods
In your Button Method
//yourURL is the webservice URL
[self performSelectorInBackground:#selector(loadDataFromWebservice:) withObject:yourURL];
-(void) loadDataFromWebservice : (NSString *)strUrl
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSURL *url=[[NSURL alloc] initWithString:strUrl];
NSData *data = [NSData dataWithContentsOfURL:imgUrl];
//Do your manipulations with data
//If you want to update any UI with the webservice data
[self performSelectorOnMainThread:#selector(assignDataViews:) withObject:responseObject waitUntilDone:YES];
[pool release];
}
//Return any object which you are comfortable with. I returned NSArray
-(void)assignDataViews : (NSArray *) yourObject
{
//Do all your UI changes here
}
Am working on an iPhone app,everything was going fine until I faced this crash, tiny_malloc_from_free_list. I am not sure why this crash is happening all of a sudden.Tried to google it but seems there aint enough suggestions to fix this one.
Please suggest any ideas how I can fix this problem.
Thanks,
Manoj
for reference here are some methods:
-(void) fetchProfileData
{
// Implemented ASIHTTP Request APIs
NSURL *url = [[NSURL URLWithString:SERVICE_NAME_PROFILEMANAGER] autorelease];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setValidatesSecureCertificate:NO];
[request setUsername:[[LoginManager sharedInstance] userName]];
[request setPassword:[[LoginManager sharedInstance] passWord]];
[request setDelegate:self];
[self.view addSubview:autheticateIndicator];
[autheticateIndicator startAnimating];
[authenticationLabel setHidden:NO];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSData *responseData = [request responseData];
NSString *theXml = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
[NSThread detachNewThreadSelector:#selector(parseXML:) toTarget:self withObject:theXml];
[autheticateIndicator stopAnimating];
[theXml release];
}
-(void) parseXML:(NSString *)xmlData
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[profilePersonnelNumber removeAllObjects];
// Load and parse the string data
tbxml = [[TBXML tbxmlWithXMLString:xmlData] retain];
// If TBXML found a root node, process element and iterate all children
if (tbxml.rootXMLElement) {
[self traverseElement:tbxml.rootXMLElement];
}
if ([profilePersonnelNumber count] > 0 ) {
NSDictionary *dict = [profilePersonnelNumber objectAtIndex:0];
if ([dict objectForKey:#"PersonnelNumber"])
{
[array release];
array = [[NSMutableArray arrayWithObjects:[dict valueForKey:#"PersonnelNumber"], nil] retain];
NSMutableString * result = [[NSMutableString alloc] init];
for (NSObject * obj in array)
{
[result appendString:[obj description]];
[[LoginManager sharedInstance] personnelNumber:[obj description]];
}
[result release];
}
}
[tbxml release];
[pool release];
//TODO: Uncomment this part, must required
if ([profilePersonnelNumber count] > 0) {
UITabBarController *controller = self.tabBarController;
[self presentModalViewController:controller animated:YES];
}
}