NSThread is failing to load Selector method - objective-c

So, I am trying to connect to a remote server to get and show data. in viewDidLoad I use an NSThread to call a function called doSomething
- (void)doSomething
{
#autoreleasepool
{
NSMutableURLRequest *httpRequest = [NSMutableURLRequest requestWithURL:someURL];
[httpRequest setHTTPMethod:#"POST"];
[httpRequest setValue:[NSString stringWithFormat:#"%d", httpRequestParametersClean.length] forHTTPHeaderField:#"Content-Length"];
[httpRequest setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[httpRequest setHTTPBody:httpRequestParametersClean];
(void)[[NSURLConnection alloc] initWithRequest:httpRequest delegate:self];
for (NSString* key in response)
{
// loop through returned values
}
}
}
The code in viewDidLoad is
[NSThread detachNewThreadSelector:#selector(someURL) toTarget:self withObject:nil];
Then I have a REFRESH button which when clicked calls doSomething as well
by simply saying [self doSomething]
My problem is that when view is loaded, the response from server comes empty. I still get no response until I click on the refresh button. Strange! What am I doing wrong?

A NSURLConnection created with initWithRequest:delegate: works asynchronously, calling the delegate functions connection:didReceiveResponse:, connection:didReceiveData:, ... later, when data is read from the server. Your code does not even start the connection, so nothing will happen anyway.
The easiest way to fix your problem is to use the synchronous version
sendSynchronousRequest:returningResponse:error:
of NSURLConnection. If doSomething is executed in a separate thread, this will not block the UI.
Added: (Thanks to #geowar for mentioning this.) Note that you can also use the delegate-based NSURLConnection methods. These are more flexible (see e.g. https://stackoverflow.com/a/15591636/1187415 for a comparison). Another good choice is sendAsynchronousRequest:queue:completionHandler:, which creates a background thread automatically.

Related

App not waiting for method to finish executing

I have a method getnamefornumbers which call a soap based web service(sudzc generated), which return a some data which i store in array to use.
But problem is that when i call the method it takes its time to execute and code after this method also executing, this result in null array.
what can i do so when this method completes its work then rest of the code executes.
You have to use custom delegates.You should define the protocol and delegate the current class to responsible for the class which performs getnamefornumbers. Once the operation done , you should return to caller class.
Here is the example of protocols http://mobiledevelopertips.com/objective-c/the-basics-of-protocols-and-delegates.html
You should use the NSURLConnection delegation methods. In an async environment that's the normal behavior:
You make a call (in an async way)
The application keeps running (after you make the 1. call the program continues with the rest of the instructions)
So you have to two solutions, make it sync, so you will only continue after an answer comes (in your case the array is filled), which I would probably disencourage. Or, you make it async, and use the array when you actually have it.
As for specifics in how to implement this, more details must be provided, in order for me to advise you.
Update 1.0
-(void)requestConnectionToServer{
NSURL *url= [NSURL URLWithString:#"myWebServiceURL"];
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:url];
self.reference=aReference;
[theRequest setHTTPMethod:#"GET"];
[theRequest setTimeoutInterval:20.0];
[NSURLConnection connectionWithRequest:theRequest delegate:self];
}
#pragma mark NSURLConnectionDelegate Implementation
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(#"Response:%#",[[NSString alloc] initWithData:webData encoding:NSASCIIStringEncoding]);
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"ERROR with theConenction %#",error);
}
Update 2.0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
myArray = [MyWebServiceAccess getnamefornumbers];
dispatch_sync(dispatch_get_main_queue(), ^{
[myArray makeSomething];
});
});

Cancel NSURLConnection Objective-C

I have a tableviewapplication, wich when the user select one view it needs to parse some XML to display information.But sometimes the XML is not finished downloading and the user can press the button to select the other view,generating a crash.I think i need to cancel the connection or something to dont cause any conflitct with the new connection,but i dont know exactly how,it suppose to be in ViewWillDisappear correct?
Heres how i start the connection on ViewDidAppear:
NSMutableURLRequest * req = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:#"http://Adress"]
cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0f];
conn = [NSURLConnection connectionWithRequest:req delegate:self];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
if(conn)
{
receivedData = [[NSMutableData alloc]init];
[DSBezelActivityView newActivityViewForView:self.view withLabel:#"Loading..."];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if(conn) [conn cancel];
}
You can call NSURLConnection's cancel method and it will prevent your connections delegate from being called with any more data. You could do this in viewWillDisappear if that's when it makes sense given how your app works.
Absolutely you can cancel NSURLConnection.
But you should be careful in cancelling it too.
If you decide to cancel it in viewWillDisappear,
then
You should not do,
autorelease
and also you should not,
release it anywhere.
Here below the brief explaination:
Do cancel your NSURLConnection delegate in viewWillDisappear
[nsurlconnection cancel];
and also you should release it here not anywhere,
[nsurlconnection release];
If you release the connection in somewhere like after your xml response received then,
It will call the viewWillDisappear method anyway,
here you are cancelling it , then it will lead your app to crash.
"deallocated objects will not be cancelled"
.
And also another situation will occurs while cancelling,
If user comes and immediately navigates other view first time, your nsurlconnection will be cancelled in viewWillDisappear method.
Again the user comes to the view and escapes immediately before your nsurlconnection initialized or allocated, also your app will be crashed because,
"deallocated objects will not be cancelled".
So, check your connection != nil before you cancel it
and also don't forgot to do
nsurlconnection = nil;
in the same time.
So that you can avoid the immediate calls [nsurlconnection cancel] crashes.
SO Finally , in your viewWillDisappear method you have to do is,
Need to check nsurlconnection != nil
Need to cancel it
Need to allocate null to your nsurlconnection
Need to release it in the same method.
Sample code will be like the following,
- (void) viewWillDisappear:(BOOL)animated
{
if (nsurlconnection != nil)
{
[nsurlconnection cancel];
[nsurlconnection release];
nsurlconnection = nil;
}
}
Hope it's helpful... Happy coding ...

NSURLConnection synchronous problem

I am writing an iPhone app which will call a webservice method by using soap message format.
I need a synchronous process because table view needs those data before it can be displayed.
So I use [NSURLConnection sendSynchronousRequest:returningResponse:error:]
The problem is, the whole program will exit without any error message after the method call.
Even I put a NSLog statement just after the
[NSURLConnection sendSynchronousRequest:returningResponse:error:],
there is no any output so I am sure the program exit during that method call. Actually during
that HTTP request and response stuff.
However, if I set a breakpoint before that method call, and run the program in debug mode,
everything runs well, the program will not exit, and I got my results as well.
Can anyone figure out what is going on?
Thanks.
- (void) sendSyncHTTPRequest:(NSString *)request_data operation:(ServOperationSync *)serv_ops {
id<ServiceData> serv_data = serv_ops.dataDelegate;
NSURL *urlAddr = [NSURL URLWithString:[serv_data getServURL]];
urlRequest = [NSMutableURLRequest requestWithURL:urlAddr
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:90];
NSData *requestData = [request_data dataUsingEncoding:NSUTF8StringEncoding];
[urlRequest setValue:#"MobilePortal" forHTTPHeaderField:#"User-Agent"];
[urlRequest setValue:[serv_data getSoapAction] forHTTPHeaderField:#"SOAPAction"];
[urlRequest setValue:[NSString stringWithFormat:#"%u", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[urlRequest setValue:urlAddr.host forHTTPHeaderField:#"Host"];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:requestData];
NSLog(#"just before sending http request");
[serv_ops.responseData setData:[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&urlResponse error:&urlError]];
NSLog(#"after sending http request");
}
Note that urlResponse and urlError are declared as instance variables.
You didn't provide us enough code to find out why your app doesn't behave correctly.
Using [NSURLConnection sendSynchronousRequest:returningResponse:error:] is generally a bad idea, because it blocks the current thread. You are probably calling it from the main thread, this will block the UI. The app won't respond to touches and feels like frozen, when the request takes long (especially on low bandwidth connection like EDGE).
The nature of networking is asynchronous. So I'd advise you to make an asynchronous request instead or use GCD. Update the Tableview in delegate methods (connection:didReceiveData: etc.). You may save the tableview data in an NSMutableArray and call [tableView reloadData] after modifying the array. The tableview would then be constructed from that array in the UITableViewDataSource delegate methods.
You need:
a run loop on your code
and don't forget your NSURLConnection
delegates

Wait for code to finish execution

I would like to know the easiest way to wait for code to finish execution within an objective c project because I am calling a webservice and retrieving the results and instead it is retrieving the results before the webservice has finished being called and filled.
Any suggestions please?
Btw this is my webservice code:
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:tmpURl];
[theRequest addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[theRequest addValue:#"http://tempuri.org/GetCategory" forHTTPHeaderField:#"SOAPAction"];
NSString *msgLength=[NSString stringWithFormat:#"%i",[soapMessage length]];
[theRequest addValue:msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody:[soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *conn=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
and the code I am using to call this method from the other class:
images = [ws callWebService:api :data];
images = [ws returnArray];
now the problem is, that the second line is being executed before the first has finished
You do it easily as below,
-(void)aFunc {
Do Asynchronous A job...
while (A is not finished) {
// If A job is finished, a flag should be set. and the flag can be a exit condition of this while loop
// This executes another run loop.
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
Do things using the A's result.
}
You could use one of many of the Cocoa design patterns (Delegate, Notification, etc).
For instance you would trigger the method and wait until you receive a response back.
It looks like you are using an asynchronous request and for this case, you would need to wait until one of the delegate methods get notified that the request has finished (with error or success).
BTW, what does your request look like? Could you share some code to explain how you do the request and when and what you want to do?
Edited after the code was inserted:
You set self as the delegate of the request, and so you should be able to handle the responses.
Have a look at the NSURLConnection Class Reference. You will need to trigger your parser when the request finishes on these methos, for example:
– connection:didReceiveResponse:
– connection:didReceiveData:
– connection:didFailWithError:
Cheers,
vfn

Why release the NSURLConnection instance in this statement?

I read this in a book.
-(IBAction) updateTweets
{
tweetsView.text = #"";
[tweetsData release];
tweetsData = [[NSMutableData alloc] init];
NSURL *url = [NSURL URLWithString:#"http://twitter.com/statuses/public_timeline.xml" ];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
[activityIndicator startAnimating];
}
In this statement,is that correct to release the "connection" instance at that time? After releasing it which means this NSURLConnection instance will be destroyed since it's reference count is 0 ,how are we going to make this connection operation work after release this instance? THANKS.
I thought we should release it in one of the following callback methods,right?
connectionDidFinishLoading:
connection:didFailWithError:
It's actually fine to release it there, once the connection is sent out via initWithRequest, the only thing that matters is that the delegate exists or I believe the response will just be silently lost.
From what I can tell, the only reason to not release it there is if you want to call [connection cancel] at some point in one of the delegate functions, in which case it would be best to do what you suggest and release it in BOTH connectionDidFinishLoading and didFailWithError since only one of them will be called (right?).
Edit: For a more thorough answer, NSURLConnection initWithRequest is an asynchronous request. So it actually spawns it's own thread (but calls the delegate functions on the thread that called initWithRequest). So basically, on the thread that calls initWithRequest you are actually done with the connection object and you can release it. All the while it's doing stuff on some other thread that you don't need to be concerned with.
Also I should note that if you do release it there, make sure you DON'T release it in the finish/fail methods, because it won't be a valid object.