iOS: EXC_BAD_ACCESS Error NSString length and setHTTPBody - ios

When I start the simulator and the application starts and I click on the UI I get EXC_BAD_ACCESS for NSString *strLength = [NSString stringWithFormat:#"%d", [postStr length]]; and for [req setHTTPBody:[_postStr dataUsingEncoding:NSUTF8StringEncoding. I dont know why this happens. If I uninstall the app but keep the simulator open and run it again I get no errors. Any help would be great. Code is below.
#import "LocavoreRetroAPIAdapter.h"
//Class extention declares a method that is private to the class
#interface LocavoreRetroAPIAdapter ()
-(NSMutableURLRequest *)initRequest:(NSURL *)url method:(NSString *)method;
#end
#implementation LocavoreRetroAPIAdapter
//Called when this class is first initialized
-(id) initWithName:(NSString *)postStr webService:(NSString *)webService spinner: (UIActivityIndicatorView *)spinner{
if(self = [super init]){
_postStr = postStr;
_baseURL = #"http://base/api/";
_webService = webService;
_spinner = spinner;
_result = nil;
}
return self;
}
//Request to Locavore API restful web services
-(void) conn:(NSString *)method{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
__block NSDictionary *resultBlock = nil;
dispatch_sync(concurrentQueue, ^{
/* Download the json here */
//Create webservice address
NSString *webService = [_baseURL stringByAppendingString:_webService];
//Create the url
NSURL *url = [NSURL URLWithString:webService];
//Create error object
NSError *downloadError = nil;
//Create the request
NSMutableURLRequest *req = [self initRequest:url method:method];
if(req != nil){
//Request the json data from the server
NSData *jsonData = [NSURLConnection
sendSynchronousRequest:req
returningResponse:nil
error:&downloadError];
NSError *error = nil;
id jsonObject = nil;
if(jsonData !=nil){
/* Now try to deserialize the JSON object into a dictionary */
jsonObject = [NSJSONSerialization
JSONObjectWithData:jsonData
options:NSJSONReadingAllowFragments
error:&error];
}
//Handel the deserialized object data
if (jsonObject != nil && error == nil){
NSLog(#"Successfully deserialized...");
if ([jsonObject isKindOfClass:[NSDictionary class]]){
resultBlock = (NSDictionary *)jsonObject;
//NSLog(#"Deserialized JSON Dictionary = %#", resultBlock);
}
else if ([jsonObject isKindOfClass:[NSArray class]]){
NSArray *deserializedArray = (NSArray *)jsonObject;
NSLog(#"Deserialized JSON Array = %#", deserializedArray);
} else {
/* Some other object was returned. We don't know how to deal
with this situation, as the deserializer returns only dictionaries
or arrays */
}
}
else if (error != nil){
NSLog(#"An error happened while deserializing the JSON data.");
}else{
NSLog(#"No data could get downloaded from the URL.");
[self conn:method];
}
}
});
dispatch_sync(dispatch_get_main_queue(), ^{
/* Check if the resultBlock is not nil*/
if(resultBlock != nil){
/*Set the value of result. This will notify the observer*/
[self setResult:resultBlock];
[_spinner stopAnimating];
}
});
});
}
//Configure the request for a post/get method
- (NSMutableURLRequest *)initRequest:(NSURL *)url method:(NSString *)method{
//Create the request
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
//Get the string length
NSString *strLength = [NSString stringWithFormat:#"%d", [_postStr length]];
//Specific to requests that use method post/get
//Configure the request
if([method isEqualToString:#"POST"]){
[req addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content- Type"];
[req addValue:strLength forHTTPHeaderField:#"Content-Length"];
[req setHTTPMethod:#"POST"];
}else if([method isEqualToString:#"GET"]){
[req addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[req addValue:strLength forHTTPHeaderField:#"Content-Length"];
[req setHTTPMethod:#"GET"];
}else{
return nil;
}
//Set the HTTP Body
[req setHTTPBody:[_postStr dataUsingEncoding:NSUTF8StringEncoding]];
//Return the request
return req;
}
//Called when this object is destroyed
- (void)dealloc {
NSLog(#"DEALLOC LocavoreRetroAPIAdapter");
[super dealloc];
[_baseURL release];
[_result release];
}
#end

Familiarize yourself the with memory management and object lifetime rules. Your code is crashing because you do not retain (or copy) the arguments within your init... method, and they are being deallocated. Change your init... method to:
-(id) initWithName:(NSString *)postStr webService:(NSString *)webService spinner: (UIActivityIndicatorView *)spinner{
if(self = [super init]){
_postStr = [postStr copy];
_baseURL = #"http://base/api/";
_webService = [webService copy];
_spinner = [spinner retain];
}
return self;
}
Be sure to release the three instance variables you are now copying or retaining in your dealloc method. Also call [super dealloc] as the last step in that method but that's not the source of your problem right now.
//Called when this object is destroyed
- (void)dealloc {
NSLog(#"DEALLOC LocavoreRetroAPIAdapter");
[_postStr release];
[_webService release];
[_spinner release];
[_result release];
[super dealloc];
}
Notice I removed the call to [_baseURL release] from your dealloc as you did not retain it so you do not own the object. If you didn't create an object with alloc or new, and didn't call retain or copy on it, then you don't own the object, so you must not release it.

Related

How to pass data to the View Controller using asynchronous NSURLConnection

I have View Controller where I get data from web, parse Json, and pass string to another View Controller. If I use synchronous NSURLConnection, everything works just fine.
But if I switch to the asynchronous, then method (void)prepareForSegue:(UIStoryboardSegue *) calls before parsing Json data which I got from web.
Just jump over _jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil] method. Any thoughts? Thank you in advance for your help. Here is my code:
-(void)getClothInfo {
NSString *allowedClothSizeToServer = [_foreignSizeToServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *getDataURL = [NSString stringWithFormat:#"http://xsdcompany.com/jsoncloth.php?foreignSize=%#",allowedClothSizeToServer];
NSURL *url = [NSURL URLWithString:getDataURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler: ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) {
[self showAlertWithMessage2:#"Server is Unavialable"];
} else {
_jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Loop trough our jsonArray
for (int i=0; i<_jsonArray.count; i++) {
//Create our size object
_usSizeFromServer = [[_jsonArray objectAtIndex:i] objectForKey:#"usSizeCloth"];
}
}
}];
}
- (IBAction)getIt:(id)sender {
// Validate data
if ([self validData] == NO)
{
return;
}
[self getClothInfo];
[self showNextViewController];
}
-(void) showNextViewController {
[self performSegueWithIdentifier:#"GetCLothInfo" sender:nil];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
ResultViewController *resultViewController = [segue destinationViewController];
resultViewController.foreignSizeToResult = [[NSString alloc] initWithFormat:#"%# size for %# is %#", [_pickerProcessor selectedCountry].countryName, [_pickerProcessor selectedCloth].clothName, [_pickerProcessor selectedSize].sizeName];
resultViewController.dataForUsSize = [[NSString alloc] initWithFormat:#"Your US size for %# is %#", [_pickerProcessor selectedCloth].clothName, _usSizeFromServer];
}
You have two options. You could call showNextViewController from the completion block inside the getClothInfo method. Or better, add a completion block parameter to your getClothInfo method and call that from the completion block for the NSURLConnection.
Something like this:
-(void)getClothInfo:(void ^(void))completion {
NSString *allowedClothSizeToServer = [_foreignSizeToServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *getDataURL = [NSString stringWithFormat:#"http://xsdcompany.com/jsoncloth.php?foreignSize=%#",allowedClothSizeToServer];
NSURL *url = [NSURL URLWithString:getDataURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler: ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) {
[self showAlertWithMessage2:#"Server is Unavialable"];
} else {
_jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Loop trough our jsonArray
for (int i=0; i<_jsonArray.count; i++) {
//Create our size object
_usSizeFromServer = [[_jsonArray objectAtIndex:i] objectForKey:#"usSizeCloth"];
}
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion();
});
}
}
}];
}
- (IBAction)getIt:(id)sender {
// Validate data
if ([self validData] == NO)
{
return;
}
[self getClothInfo:^ {
[self showNextViewController];
}];
}
It seems like you want your json data to be downloaded before you segue, in that case the synchronous NSURLConnection makes sense
When you make an asynchronous NSURLConnection call, it means that the subsequent code will be executed ( in this case the performSegue).
It would help if you could explain what your expected behavior is
Register for notification when response is obtained from the connection using
[[NSNotificationCenter defaultCenter] postNotificationName:#"ResponseObtained" object:_jsonArray];
in the second view controller add observer for notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleResponse:)
name:#"ResponseObtained"
object:nil];
You can access _jasonArray in handleResponse method with
- (void)handleResponse:(NSNotification *)notif{
NSDictionary *result = [notif object]; }

IOS getting response null in http request

I'm sending a request to a server to test a specific situation. The response is a custom 510 http error and the content is the info of the error.
The web service works fine the first time a send the request. The next time I tried to replicate the error the response is nil. But, if I change the request avoiding the error, it works fine and the response is what it is supposed to be.
I'm executing the request with a brand new object each time.
#interface SCBaseConnection()
#property (strong, nonatomic) NSURLSessionDownloadTask *task;
#end
#implementation SCBaseConnection
- (instancetype) initWithUrl:(NSString *)url
path:(NSString *)path
body:(NSString *)body
headers:(NSDictionary *)headers
method:(NSString *)method
requestCode:(NSInteger)requestCode
{
self = [super init];
NSLog(#"%#", headers);
NSURL *uri = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", url, path]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:uri];
request.HTTPMethod = method;
if (body) {
request.HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];
}
if (headers) {
NSArray *keys = [headers allKeys];
for (NSString *key in keys) {
[request setValue:[headers objectForKey:key] forHTTPHeaderField:key];
}
}
NSURLSession *session = [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration]];
self.task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
int statusCode = (int)[response getStatusCode];
NSLog(#"%#", #(statusCode));
if (HTTP_UNAUTHORIZED == statusCode) {
[[NSNotificationCenter defaultCenter] postNotificationName:kUnauthorizedHttpRequest object:response];
}
if (error) {
[MCMGeneralUtils logError:error];
NSLog(#"%#", error.userInfo);
NSLog(#"%#", error);
}
NSData *res = [self dataFromFile:location];
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate didConnectionFinished:self
statusCode:statusCode
response:res
requestPath:path
requestCode:requestCode];
});
}];
return self;
}
This is the content of the error.userInfo after the second request.
NSErrorFailingURLKey = "http://192.168.1.201:23111/api/paciente";
NSErrorFailingURLStringKey = "http://192.168.1.201:2311/api/paciente";
NSLocalizedDescription = "The requested URL was not found on this server.";
The first time the request has no errors.
UPDATE
- (IBAction)save:(UIBarButtonItem *)sender
{
MCMPatientNew *patient = [MCMPatientNew new];
patient.name = self.name;
patient.lastname = self.lastname;
patient.fullname = [NSString stringWithFormat:#"%# %#", self.name, self.lastname];
patient.email = self.email;
patient.phones = [self extracPhones];
patient.patientNew = YES;
NSError *error = nil;
if ([patient assertPatient:&error]) {
MCMUser *user = [MCMUser loadUserInManagedContext:self.managedContext];
patient.delegate = self;
[patient storePatientInManagedContext:self.managedContext];
if ([MCMGeneralUtils isInternetRechable]) {
[self presentViewController:self.serverConnectionAlert animated:YES completion:nil];
[patient postPatientWithToken:user.token doctorId:user.userId];
} else {
[self storeInRequestLogWithRequestCode:REQUEST_CODE_PACIENTE_INSERT
appId:patient.appId
ready:YES
inManagedContext:self.managedContext];
[self cancel:nil];
[self postNotificationWithObject:patient];
}
} else {
[self displayErrorMessageWithErrorInfo:error.userInfo];
}
}
UPDATE 2
- (void)postPatientWithToken:(NSString *)accessToken doctorId:(NSNumber *)doctorId
{
NSMutableDictionary *mutable = [NSMutableDictionary dictionaryWithDictionary:[self jsonToPost]];
[mutable setObject:doctorId forKey:#"doctorId"];
NSDictionary *body = #{#"obj" : mutable};
[self connectToServerWithAccessToken:accessToken
body:body
path:PATH_PACIENTE_INSERT
method:HTTP_METHOD_POST
requestCode:REQUEST_CODE_PACIENTE_INSERT
delegate:self];
}
-
- (void)connectToServerWithAccessToken:(NSString *)accessToken
body:(NSDictionary *)body
path:(NSString *)path
method:(NSString *)method
requestCode:(NSInteger)requestCode
delegate:(id<SCBaseConnectionDelegate>)delegate
{
NSString *authenticator = [NSString stringWithFormat:#"Bearer %#", accessToken];
NSDictionary *headers = #{HEADER_CONTENT_TYPE : CONTENT_TYPE_APPLICATION_JSON,
HEADER_AUTHORIZATION : authenticator};
NSString *bodyStr = body ? [SCJson jsonFromDictionary:body] : #"";
SCBaseConnection *connection = [[SCBaseConnection alloc] initWithUrl:API_URL
path:path
body:bodyStr
headers:headers
method:method
requestCode:requestCode];
connection.delegate = delegate;
[connection execute];
}
-
- (BOOL)execute
{
if (self.task) {
[self.task resume];
return YES;
}
return NO;
}

iOS: Unrecognized selector sent to instance

I have a class where I request information from a provider class, in which after finalizing the job (asynchronous httpRequest block) needs to invoke a method [- (void) updateCountries] in the requester class. If I am not wrong this code worked in iOS 7, but now in iOS 8 it does not.
Can you please help me to understand why?
Methods in requester class:
- (void) viewWillAppear:(BOOL)animated {
//get countries to pickerView
webAPI = [[WebAPI alloc] init];
[webAPI retrieveCountries:self];
}
- (void) updateCountries {
//update countries content for pickerView
locationDAO = [[LocationDAO alloc] init];
countriesArray = [locationDAO getCountries];
[pickerView reloadAllComponents];
}
Lines in method in provider class where error happens:
SEL updateCountries = sel_registerName("updateCountries:");
[requester performSelectorOnMainThread:updateCountries withObject:nil waitUntilDone:YES];
If you need to checkout the entire method in the provider class, here it is:
- (void) retrieveCountries:(id)requester {
// NSLog(#"engine report: firing retrieveCountries http get");
NSString *urlAsString = kRetrieveCountriesListAPI;
NSURL *url = [NSURL URLWithString:urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:#"GET"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ([data length] >0 && error == nil){
NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"engine report: retrieveCountries server response: %#", response);
NSArray *level0 = [[NSArray alloc] initWithObjects:[NSJSONSerialization JSONObjectWithData:[[NSData alloc] initWithData:data] options:kNilOptions error:&error], nil];
NSArray *level1 = [level0 objectAtIndex:0];
LocationDAO *locationDAO = [[LocationDAO alloc] init];
[locationDAO deleteAllFromCountries];
for (int i = 0; i < [level1 count]; i++) {
CountryVO *countryVO = [[CountryVO alloc] init];
countryVO.myID = [[[level1 objectAtIndex:i] objectForKey:#"id"] integerValue];
countryVO.name = [[level1 objectAtIndex:i] objectForKey:#"country_name"];
[locationDAO saveCountryToDatabase:countryVO];
}
SEL updateCountries = sel_registerName("updateCountries:");
[requester performSelectorOnMainThread:updateCountries withObject:nil waitUntilDone:YES];
dispatch_async(dispatch_get_main_queue(), ^(void){
});
} else if ([data length] == 0 && error == nil){
NSLog(#"Nothing was downloaded.");
} else if (error != nil) {
NSLog(#"Error happened = %#", error);
} }];
}
THANK YOU A WHOLE LOT
Remove the : from the selector specification:
SEL updateCountries = sel_registerName("updateCountries");
Your method updateCountries doesn't take any arguments. So, when creating the selector, you should only write updateCountries (instead of updateCountries: which would indicate that this method takes an argument).
The reason why your app crashes is that when you try to perform this selector, the internals of your app are looking for a method called updateCountries on requester that takes one argument. This method doesn't exist, which is why the app crashes.

delegate method cannot callback

delegate method cannot callback
This is my .h file
#protocol ServiceAPIDelegate <NSObject>
#optional
- (void) onRequestLoginFinish:(NSDictionary*) dict;
#end
#interface ServiceAPI : NSObject
+ (id)shareAPI;
#property (nonatomic, weak) id <ServiceAPIDelegate> delegate_service;
;
#end
and this is .m file, i use ASIFORMData request and it is callback to requestFinished after get a response from server. but ater that, i want to send data to myviewcontroler use [self.delegate_service onRequestLoginFinish:result]; after this line. my program run normaly not bugs, not callback to function. I cannot see where errors are.
- (void) requestLoginWithUserName:(NSString*) username andPassWord:(NSString*) password {
NSString* urlString = [PublicInstance API_LOGIN];
NSArray *keys = PARAMS_ARRAY;
NSArray *objects = [NSArray arrayWithObjects:username, password, [#((int)En) stringValue], APPID, [PublicInstance getDevideID], DEVIDEOS, nil];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjects:objects forKeys:keys];
NSString* signData = [PublicInstance signData:dict];
[dict setObject:signData forKey:signKey];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:urlString]];
[request addRequestHeader:#"Content-Type" value:#"application/json"];
[request setValidatesSecureCertificate:NO];
[request setRequestMethod:#"POST"];
NSData *jsonDataToPost = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
[request appendPostData:jsonDataToPost];
[request startAsynchronous];
[request setDelegate:self];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSError* error = [request error];
if(!error) {
NSString* responseString = [request responseString];
NSDictionary *result = [NSJSONSerialization JSONObjectWithData;
[self.delegate_service onRequestLoginFinish:result];
}else{
NSLog(#"%#", [error description]);
}
}
ServiceAPI *ShareServiceAPI;
- (id) init {
if ([self init]) {
ShareServiceAPI = [ServiceAPI shareAPI];
ShareServiceAPI.delegate_service =self;
}
}
- (void) requestLoginWithUserInfor:(UserInfor*) _userinfor {
[ShareServiceAPI requestLoginWithUserName:_userinfor.username andPassWord:_userinfor.password];
}
#####################
and this is delegate method - but never callback (O^-oO)
- (void) onRequestLoginFinish:(NSDictionary *)dict {
if ([[dict objectForKey:Key_Status] intValue] == 1) {
NSLog(#"login successful");
}
else {
NSLog(#"login fail....");
}
}
Could anyone please help me?. Thank you for your time
You should always check if the delegate is nil or not and also check if the delegate responds to the selector as :
if(self.delegate_service){
if([self.delegate_service repondsToSelector:#selector(onRequestLoginFinish:)]){
[self.delegate_service onRequestLoginFinish:result];
}
}
Through the way you can make your program safe and found the reason that the method is not called.

Update the UI of the View Controller and then dismiss it

I have a view controller, that loads some an array. While everything is loading, I need to present another view controller (with the UIProgressView) and update it's UI (the progress property of a UIProgressView) and then dismiss and present first vc with downloaded data. I'm really struggling on it and I've tried delegation, but nothing worked for me.
- (void)viewDidLoad
{
[super viewDidLoad];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"downloaded"]) {
} else {
NSLog(#"First time Launched");
ProgressIndicatorViewController *progressVC = [ProgressIndicatorViewController new];
progressVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self syncContacts];
[self presentViewController:progressVC animated:YES completion:nil];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"downloaded"];
[progressVC release];
}
}
sync contacts method:
- (void)syncContacts
{
NSLog(#"Sync data");
NSMutableArray *allContacts = [ContactsOperations getAllContactsFromAddressBook];
NSInteger allContactsCount = [allContacts count];
if (allContactsCount > 0) {
for (ContactData *contact in allContacts) {
NSMutableArray *phoneNumbersArray = [[NSMutableArray alloc] init];
NSString *nospacestring = nil;
for (UserTelephone *tel in [contact.abonNumbers retain]) {
NSArray *words = [tel.phoneNumber componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceCharacterSet]];
NSString *nospacestring = [words componentsJoinedByString:#""];
[phoneNumbersArray addObject:nospacestring];
}
contact.abonNumbers = phoneNumbersArray;
if (phoneNumbersArray != nil) {
NSLog(#"NOT NULL PHONENUMBERS: %#", phoneNumbersArray);
}
NSDictionary *dataDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:contact.abonNumbers, #"phoneNumbers", contact.contactName, #"fullName", [NSNumber numberWithBool:contact.isBlackList], #"blacklist", [NSNumber numberWithBool:contact.isIgnore], #"ignore", contact.status, #"status", nil];
NSLog(#"dictionary: %#", dataDictionary);
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:dataDictionary options:0 error:&error];
NSLog(#"POST DATA IS : %#", postData);
NSMutableURLRequest *newRequest = [self generateRequest:[[NSString stringWithFormat:#"%#c/contacts%#%#", AVATATOR_ADDR, SESSION_PART, [[ServiceWorker sharedInstance] SessionID]] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding] withHTTPMethod:#"POST"];
[newRequest setHTTPBody:postData];
[newRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
//__block NSMutableData *newData;
[NSURLConnection sendAsynchronousRequest:newRequest queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if (!connectionError) {
NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"alldata from contacts: %#", allData);
//NSInteger errorCode = [[allData objectForKey:#"CommandRes"] integerValue];
//if (errorCode == 0) {
NSInteger remoteId = [[allData objectForKey:#"contactId"] integerValue];
contact.remoteId = remoteId;
NSLog(#"remote id is from parse content : %d", remoteId);
[[AvatatorDBManager getSharedDBManager]createContactWithContactData:contact];
} else {
NSLog(#"error");
}
}];
//Somewhere here I need to update the UI in another VC
[phoneNumbersArray release];
[dataDictionary release];
}
} else {
}
}
generate request method:
- (NSMutableURLRequest *)generateRequest:(NSString *)urlString withHTTPMethod:(NSString *)httpMethod
{
NSLog(#"url is :%#", urlString);
NSURL *url = [NSURL URLWithString:urlString];
request = [NSMutableURLRequest requestWithURL:url];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[request setHTTPMethod:httpMethod];
return request;
}
ProgressViewController is just an empty VC with the progress bar. No code yet.
In the view controller that will display the progress view expose a method like this...
- (void)updateProgress:(float)progress;
Its implementation will look like this...
- (void)updateProgress:(float)progress {
[self.progressView setProgress:progress animated:YES];
}
On the main view controller you need to execute the long-running process on a background thread. Here's viewDidLoad for the main view controller. This example code uses a property for the progress view controller (you may not require this) and assumes your are in a navigation controller...
- (void)viewDidLoad {
[super viewDidLoad];
// Create and push the progress view controller...
self.pvc = [[ProgressViewController alloc] init];
[self.navigationController pushViewController:self.pvc animated:YES];
// Your long-running process executes on a background thread...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Your long-running process goes here. Wherever required you would
// call updateProgress but that needs to happen on the main queue...
dispatch_async(dispatch_get_main_queue(), ^{
[self.pvc updateProgress:progress];
});
// At the end pop the progress view controller...
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController popViewControllerAnimated:YES];
});
});
}

Resources