Objective C not going in if else statement - ios

I have this piece of code
RCT_EXPORT_METHOD(open:(NSString *)path invocation:(nonnull NSNumber *)invocationId
options:(NSDictionary *)options)
{
NSString *displayName = [RCTConvert NSString:options[#"displayName"]];
DyteFile *file = [[File alloc] initWithPath:path title:displayName];
QLPreviewController *controller = [[CustomQLViewController alloc] initWithFile:file identifier:invocationId];
controller.delegate = self;
typeof(self) __weak weakSelf = self;
BOOL canOpenFile = [QLPreviewController canPreviewItem:file];
if(canOpenFile) {
[[RNFileViewer topViewController] presentViewController:controller animated:YES completion:^{
[weakSelf sendEventWithName:OPEN_EVENT body: #{#"id": invocationId}];
}];
} else {
[weakSelf sendEventWithName:OPEN_EVENT body: #{#"id": invocationId, #"error": #"File not supported"}];
}
} //last line
Here the code doesn't execute if-else statement i.e, it goes till this line
BOOL canOpenFile = [QLPreviewController canPreviewItem:file];
and then to the last line i.e
} //last line
any idea why this could be happening?

Related

Using of activity indicator in second viewController to load lot of data in Objective C

How can I use activity indicator in second view controller to let data to be complete load
first VC
- (IBAction)btnOpenHTML:(id)sender {
RecievVC *obj = [self.storyboard instantiateViewControllerWithIdentifier:#"RecievVC"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:lblName.text forKey:#"lblname"];
//........Lots of Data........(then in the end of 1st VC)........//
obj.dicData = dict;
[self.navigationController pushViewController:obj animated:true];
}
#end
the 2nd VC Code after viewdidload
- (void)viewDidLoad {
[super viewDidLoad];
[self->webView.scrollView setScrollEnabled:true];
[self->webView loadHTMLString:[self getHTMLStirng] baseURL:[NSURL URLWithString:#""]];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(NSString *)getHTMLStirng {
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"resumeT" ofType:#"html"];
NSString *strHTML = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
if (self.dicData) {
strHTML = [strHTML stringByReplacingOccurrencesOfString:#"#NAME" withString:[_dicData valueForKey:#"lblname"]];
//...............Lots of Data......Then at the end of 2nd VC............//
}return strHTML;
}
what I main by lots of data, it's around 150 of keys and value have to be send from 1st VC to 2nd VC.
any idea?
You could try GCD:
// instantiate the activity indicator
UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleGray];
activity.center = self.view.center;
// start your activity indicator
[activity startAnimating]
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// load data on background thread
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:lblName.text forKey:#"lblname"];
//........Lots of Data........(then in the end of 1st VC)........//
// update UI on main thread
dispatch_async(dispatch_get_main_queue(), ^{
// stop your activity indicator
[activity stopAnimating]
RecievVC *obj = [self.storyboard instantiateViewControllerWithIdentifier:#"RecievVC"];
obj.dicData = dict;
[self.navigationController pushViewController:obj animated:true];
});
});

CBLQueryEnumerator count returns nil for first time, second time works correct

when I launch App for first time (App is not installed perviously) on simulator, the instance of CBLQueryEnumerator count returns nil.
I found it by placing breakpoints and executing
po enumeratorResult
but the enumerator object seems to be allocated.
When I launch App for second time (in this case App is already installed on simulator) the instance of CBLQueryEnumerator count returns 5 (I have 5 documents in DB).
Am I making mistake in using CBLQuery or CBLQueryEnumerator please guide me correct.
viewContoller.m
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.progressView.progressViewStyle = UIProgressViewStyleBar;
[self.progressView setProgress:2.5 animated:YES];
self.cbObject = [CouchBaseObject sharedInstance];
self.syncURLLabel.text = [NSString stringWithFormat:#"%#",self.cbObject.syncURL];
self.documentList = [NSMutableArray array];
[self addDocumentToTicketModel:self.cbObject.database];
if(self.cbObject.pull.status == kCBLReplicationOffline || self.cbObject.pull.status != kCBLReplicationActive){
[self performSelector:#selector(pushTicketDetailViewController) withObject:self afterDelay:2.5];
}
}
-(void)addDocumentToTicketModel:(CBLDatabase*)database{
CBLView* view = [database viewNamed:#"_temp_view"];
if (!view.mapBlock) {
[view setMapBlock:MAPBLOCK({
if (doc) {
emit(doc,#"1");
}
})version:#"1.0"];
}
CBLQuery* query = [view createQuery];
[query runAsync:^(CBLQueryEnumerator * enumeratorResult, NSError * error) {
if(!error){
for (CBLQueryRow* row in enumeratorResult) {
CBLDocument* document = [database documentWithID:row.documentID];
Ticket* ticket = [Ticket modelForDocument:document];
NSLog(#"Ticket ; %#",ticket.propertiesToSave);
[self.documentList addObject:ticket];
}
}
}];
}
#end
CouchBaseObject.m
#implementation CouchBaseObject
-(instancetype)init{
self = [super init];
if(self){
NSError* error;
self.manager = [CBLManager sharedInstance];
if(!self.manager){
NSLog(#"manager fail");
return nil;
}
self.database = [self.manager databaseNamed:#"couch_sample_one" error:&error];
if(!self.database){
NSLog(#"database fail");
return nil;
}
[self initReplication];
}
return self;
}
+(CouchBaseObject*)sharedInstance{
static CouchBaseObject* sharedInstance = nil;
if(sharedInstance == nil){
sharedInstance = [[CouchBaseObject alloc]init];
}
return sharedInstance;
}
-(void)initReplication{
self.syncURL = [[NSURL alloc]initWithString:#"http://***.***.***.***:5984/couch_sample_one"];
self.pull = [self.database createPullReplication:self.syncURL];
self.push = [self.database createPushReplication:self.syncURL];
self.pull.continuous = NO;
self.push.continuous = NO;
[self startReplication];
}
-(void)startReplication{
[self.push start];
[self.pull start];
}
-(void)stopReplication{
[self.push stop];
[self.pull stop];
}
#end
For first time the control will not enter into for in loop
for (CBLQueryRow* row in result)
and for second time control will be in that loop.
This also happens when on just on launch.
Scenario.
Run App (Freshly installed app)
Navigate from initialViewController to viewController.
First time control does not enter into for loop, CBLQueryEnumerator Object.count returns nil.
pop to initialViewController
Push viewController, but this time controls enter into for in loop and CBLQueryEnumerator object.count returns 5
Hierarchy (Push).
initialViewContoller -> ViewContoller -> ListViewController

How to display UIActivityIndicatorView while fetching JSON data asynchronously to be populated in UITableView?

I am calling a GET API , that takes a string keyword and returns me JSON data , which i parse and display in my UITableView
While the API returns data , I am displaying UIActivityIndicatorView, this is working fine.
However , as soon as the data is recieved the UIActivityIndicatorView disappears as expected but data does not show in the UITableView, but if i touch anywhere on the screen the data gets visible in the UI TableView.
This is my code:
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[indicator startAnimating];
indicator.hidesWhenStopped = YES;
dispatch_queue_t queue = dispatch_queue_create("ID", NULL);
dispatch_async(queue, ^{
NSString *searchText=searchBar.text;
NSString *trimmedString = [searchText stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
if (trimmedString.length==0) {
isFilter=NO;
UIAlertView *noConn = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Please enter something in search bar" delegate:self cancelButtonTitle:nil otherButtonTitles:#"ok", nil];
[noConn show];
} else {
NSString *searchNew = [trimmedString stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
isFilter=YES;
#try {
[label removeFromSuperview];
_Title1 = [[NSMutableArray alloc] init];
_Author1 = [[NSMutableArray alloc] init];
_Images1 = [[NSMutableArray alloc] init];
_Details1 = [[NSMutableArray alloc] init];
_link1 = [[NSMutableArray alloc] init];
_Date1 = [[NSMutableArray alloc] init];
NSString* myURLString = [NSString stringWithFormat:#"www.example.com=%#", searchNew];
NSURL *url = [NSURL URLWithString:myURLString];
NSData* data = [NSData dataWithContentsOfURL:url];
if ((unsigned long)data.length > 3) {
NSArray *ys_avatars = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if(ys_avatars) {
for (int j=0;j<ys_avatars.count;j++) {
if( ys_avatars[j][#"title"]==[NSNull null] ) {
[_Title1 addObject: #""];
} else {
[_Title1 addObject:ys_avatars[j][#"title"]];
}
if( ys_avatars[j][#"author"]==[NSNull null] ) {
[_Author1 addObject: #""];
}
[_Author1 addObject: ys_avatars[j][#"author"]];
if( ys_avatars[j][#"featured_img"]==[NSNull null] ) {
[_Images1 addObject: #""];
} else {
[_Images1 addObject: ys_avatars[j][#"featured_img"]];
}
if( ys_avatars[j][#"content"]==[NSNull null] ) {
[_Details1 addObject: #""];
} else {
[_Details1 addObject:ys_avatars[j][#"content"]];
}
if( ys_avatars[j][#"permalink"]==[NSNull null] ) {
[_link1 addObject: #""];
} else {
[_link1 addObject:ys_avatars[j][#"permalink"]];
}
if( ys_avatars[j][#"date"]==[NSNull null] ) {
[_Date1 addObject: #""];
} else {
NSString *newStr=[ys_avatars[j][#"date"] substringToIndex:[ys_avatars[j][#"date"] length]-3];
[_Date1 addObject:newStr];
}
}
} else {
NSLog(#"error");
}
[self.myTableView reloadData];
} else {
if(IDIOM == IPAD){
[self.myTableView reloadData];
self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0];
label = [[UILabel alloc] initWithFrame:CGRectMake(150, 200, 200, 100)];
label.text=#"No Article Found";
label.backgroundColor = [UIColor clearColor];
[self.view addSubview:label];
} else {
[self.myTableView reloadData];
self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0];
label = [[UILabel alloc] initWithFrame:CGRectMake(90, 100, 200, 100)];
label.text=#"No Article Found";
label.backgroundColor = [UIColor clearColor];
[self.view addSubview:label];
}
}
}
#catch (NSException *exception) { }
}
dispatch_async(dispatch_get_main_queue(), ^{
[indicator performSelectorOnMainThread:#selector(stopAnimating) withObject:nil waitUntilDone:YES];
});
});
[self.mySearchBar resignFirstResponder];
}
Your basic problem is that you are trying to update the UI from background threads. All UI updates must be done on the main thread / queue.
Usually the easiest way to do that is by using:
dispatch_async(dispatch_get_main_queue(), ^{
// code to run on the main queue
});
I actually see that you're using that when you stop the UIActiviteIndicatorView here:
dispatch_async(dispatch_get_main_queue(), ^{
[indicator performSelectorOnMainThread:#selector(stopAnimating) withObject:nil waitUntilDone:YES];
});
But, in that case, you're actually dispatching the stopAnimating method to the main queue twice. You only really need this:
dispatch_async(dispatch_get_main_queue(), ^{
[indicator stopAnimating];
});
As for your table not updating, that's because you need to dispatch all your reloadData calls to the main queue.
There are quite a few places in your code that need to be dispatched back to the main queue but, instead of wrapping all of those in a dispatch_async to the main queue, there's an easier way. The only place I see where you are actually doing something that should be done on a background thread is this line:
NSData* data = [NSData dataWithContentsOfURL:url];
Which means you can get rid of the dispatch_async(queue, ^{...}); at the beginning of your method and, instead, only do that just before you call [NSData dataWithContentsOfUrl:url]. Then, dispatch_async back to the main queue immediately after.
Like this:
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[indicator startAnimating];
indicator.hidesWhenStopped = YES;
NSString *searchText=searchBar.text;
NSString *trimmedString = [searchText stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
if (trimmedString.length==0) {
isFilter=NO;
UIAlertView *noConn = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Please enter something in search bar" delegate:self cancelButtonTitle:nil otherButtonTitles:#"ok", nil];
[noConn show];
} else {
NSString *searchNew = [trimmedString stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
isFilter=YES;
#try {
[label removeFromSuperview];
_Title1 = [[NSMutableArray alloc] init];
_Author1 = [[NSMutableArray alloc] init];
_Images1 = [[NSMutableArray alloc] init];
_Details1 = [[NSMutableArray alloc] init];
_link1 = [[NSMutableArray alloc] init];
_Date1 = [[NSMutableArray alloc] init];
NSString* myURLString = [NSString stringWithFormat:#"www.example.com=%#", searchNew];
NSURL *url = [NSURL URLWithString:myURLString];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData* data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
if ((unsigned long)data.length > 3) {
NSArray *ys_avatars = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if(ys_avatars) {
for (int j=0;j<ys_avatars.count;j++) {
if( ys_avatars[j][#"title"]==[NSNull null] ) {
[_Title1 addObject: #""];
} else {
[_Title1 addObject:ys_avatars[j][#"title"]];
}
if( ys_avatars[j][#"author"]==[NSNull null] ) {
[_Author1 addObject: #""];
}
[_Author1 addObject: ys_avatars[j][#"author"]];
if( ys_avatars[j][#"featured_img"]==[NSNull null] ) {
[_Images1 addObject: #""];
} else {
[_Images1 addObject: ys_avatars[j][#"featured_img"]];
}
if( ys_avatars[j][#"content"]==[NSNull null] ) {
[_Details1 addObject: #""];
} else {
[_Details1 addObject:ys_avatars[j][#"content"]];
}
if( ys_avatars[j][#"permalink"]==[NSNull null] ) {
[_link1 addObject: #""];
} else {
[_link1 addObject:ys_avatars[j][#"permalink"]];
}
if( ys_avatars[j][#"date"]==[NSNull null] ) {
[_Date1 addObject: #""];
} else {
NSString *newStr=[ys_avatars[j][#"date"] substringToIndex:[ys_avatars[j][#"date"] length]-3];
[_Date1 addObject:newStr];
}
}
} else {
NSLog(#"error");
}
[self.myTableView reloadData];
} else {
if(IDIOM == IPAD){
[self.myTableView reloadData];
self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0];
label = [[UILabel alloc] initWithFrame:CGRectMake(150, 200, 200, 100)];
label.text=#"No Article Found";
label.backgroundColor = [UIColor clearColor];
[self.view addSubview:label];
} else {
[self.myTableView reloadData];
self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0];
label = [[UILabel alloc] initWithFrame:CGRectMake(90, 100, 200, 100)];
label.text=#"No Article Found";
label.backgroundColor = [UIColor clearColor];
[self.view addSubview:label];
}
}
[indicator stopAnimating];
});
});
}
#catch (NSException *exception) { }
}
[self.mySearchBar resignFirstResponder];
}
Note: You are doing quite a bit in that one method. I'd suggest splitting that up in to multiple methods to make your code more readable and maintainable.
try to use NSURLConnection that would save a lot of headache and make your URL requests more manageable
#interface myTableView : UITableViewController<NSURLConnectionDelegate>{
NSMutableData *_responseData;
}
and then use the delegate methods to parse data received,stop your indicatorview,and reload your tableview
#pragma mark NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// A response has been received, this is where we initialize the instance var you created
// so that we can append data to it in the didReceiveData method
// Furthermore, this method is called each time there is a redirect so reinitializing it
// also serves to clear it
_responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// Append the new data to the instance variable you declared
[_responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
// Return nil to indicate not necessary to store a cached response for this connection
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// The request is complete and data has been received
// You can parse the stuff in your instance variable now
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// The request has failed for some reason!
// Check the error var
}
and make your URL request wherever you want
// Create the request.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.com"]];
// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
source

UIImagePickerController startVideoCapture with native controls?

I'm using Phonegap's implementation to use the video capture and can't seem to get startVideoCapture to work. I'm a novice when it comes to Objective C, so I apologize if I'm off base here. Sounds like startVideoCapture is mainly for custom UI's. Is there something I can do to auto start the video recording (since I'm starting the video interface from another action). Here's a link to the full file:
https://github.com/apache/cordova-plugin-media-capture/blob/master/src/ios/CDVCapture.m
Thanks,
Steve
- (void)captureVideo:(CDVInvokedUrlCommand*)command
{
NSString* callbackId = command.callbackId;
NSDictionary* options = [command.arguments objectAtIndex:0];
NSLog(#"hereeeee");
if ([options isKindOfClass:[NSNull class]]) {
options = [NSDictionary dictionary];
}
// options could contain limit, duration and mode
// taking more than one video (limit) is only supported if provide own controls via cameraOverlayView property
NSNumber* duration = [options objectForKey:#"duration"];
NSString* mediaType = nil;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
// there is a camera, it is available, make sure it can do movies
pickerController = [[CDVImagePicker alloc] init];
NSArray* types = nil;
if ([UIImagePickerController respondsToSelector:#selector(availableMediaTypesForSourceType:)]) {
types = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
// NSLog(#"MediaTypes: %#", [types description]);
if ([types containsObject:(NSString*)kUTTypeMovie]) {
mediaType = (NSString*)kUTTypeMovie;
} else if ([types containsObject:(NSString*)kUTTypeVideo]) {
mediaType = (NSString*)kUTTypeVideo;
}
}
}
if (!mediaType) {
// don't have video camera return error
NSLog(#"Capture.captureVideo: video mode not available.");
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NOT_SUPPORTED];
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
pickerController = nil;
} else {
pickerController.delegate = self;
pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
pickerController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
pickerController.allowsEditing = NO;
// iOS 3.0
pickerController.mediaTypes = [NSArray arrayWithObjects:mediaType, nil];
if ([mediaType isEqualToString:(NSString*)kUTTypeMovie]) {
if (duration) {
pickerController.videoMaximumDuration = [duration doubleValue];
}
// NSLog(#"pickerController.videoMaximumDuration = %f", pickerController.videoMaximumDuration);
}
// iOS 4.0
if ([pickerController respondsToSelector:#selector(cameraCaptureMode)]) {
pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
// pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
// pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear;
// pickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
}
// CDVImagePicker specific property
pickerController.callbackId = callbackId;
SEL selector = NSSelectorFromString(#"presentViewController:animated:completion:");
if ([self.viewController respondsToSelector:selector]) {
[self.viewController presentViewController:pickerController animated:YES completion:nil];
} else {
// deprecated as of iOS >= 6.0
[self.viewController presentModalViewController:pickerController animated:YES];
}
// Auto start capture
[pickerController startVideoCapture];
}
}
My problem wasn't the use of startVideoRecording, it was when:
[self.viewController presentViewController:pickerController animated:YES completion:^(){
[pickerController startVideoCapture];
}];
Hope this helps someone else.
Thanks,
Steve

Performing operations on background threads and update the UI from a different class

I have a class called APICalls that manages the calls to the API. Every View Controller calls the appropriate method (createUsername, getStates...) and pass the parameters required. When the data is received and parsed, it calls back the viewcontroller to update the UI with the info downloaded. The following code is working but I would like to know if there is an easier or more flexible/appropriate way of doing this, specially when I update the UI in the viewcontroller. Perhaps with protocols and delegates? Any suggestion is welcomed.
-(void) getObjects:(id)returnObject ofClass:(Class)returnClass fromUrl:(NSString *)urlString withPost:(NSString *)post orPut:(NSString *)put token:(NSString *)token callName:(NSString *)call andAlertTitle:(NSString *)alertTitle
{
// NSString *className = NSStringFromClass([object class]);
__block NSObject *object = returnObject;
__block Class class = returnClass;
__block NSMutableArray *array = [[NSMutableArray alloc]init] ;
__block BOOL dataReceived = NO;
[SVProgressHUD showWithStatus:#"Connecting to the server"];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
ServerConnection *sc = [[ServerConnection alloc] init]; //post/get/put
NSDictionary *jsonDict;
if ( ([post isEqualToString:#""] || !post ) && ([put isEqualToString:#""] || !put ) )
jsonDict = [sc getFromUrl:urlString withToken:token];
else if ([put isEqualToString:#""] || !put)
jsonDict = [sc postToUrl:urlString withPost:post andToken:token];
else
jsonDict = [sc putToUrl:urlString withPut:put andToken:token];
if (jsonDict)
{
NSLog(#"API: json received");
//parse the received json
NSObject *data = [self parseJson:jsonDict alertTitle:alertTitle];
if ([data isKindOfClass:[NSArray class]]) {
NSLog(#"API: Array");
dataReceived = YES;
// Iterate through the array of dictionaries
for(NSDictionary *dict in (NSArray *) data) {
object = [[class alloc] initWithJSONDictionary:dict];
[array addObject:object];
}
}
else if ([data isKindOfClass:[NSDictionary class]]){
NSLog(#"API: Dictionary");
dataReceived = YES;
object = [[class alloc] initWithJSONDictionary:(NSDictionary *)data];
if ([array count]> 0)
[array addObject:object];
}
else
NSLog(#"API: Error from API"); //alertview is shown from HandleError class
}
else{
NSLog(#"no json received");
dispatch_async(dispatch_get_main_queue(), ^(void){
[self alertStatus:#"Error when connecting to the server, please try it again" :alertTitle];
});
}
if (dataReceived)
{
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
[SVProgressHUD dismiss];
if ([call isEqualToString:#"getStates"])
{
if ([self.currentViewController isKindOfClass:[SignUpViewController class]])
{
SignUpViewController *signup = (SignUpViewController *) self.currentViewController;
[signup updateStatesList:array];
}
else if ([self.currentViewController isKindOfClass:[MyProfileViewController class]])
{
MyProfileViewController *profileVC = (MyProfileViewController *) self.currentViewController;
[profileVC updateStatesList:array];
}
}
else if ([call isEqualToString:#"getPoints"])
{
PromotionSelectionViewController *promotionVC = (PromotionSelectionViewController *) self.currentViewController;
[promotionVC updatePoints:object];
}
else if ([call isEqualToString:#"getPromotions"])
{
PromotionSelectionViewController *promotionVC = (PromotionSelectionViewController *) self.currentViewController;
[promotionVC updatePromotionsList:array];
}
});
}
});
}
//CreateUser: creates an user when this sign up
-(void)createUserWithUsername:(NSString *)username name:(NSString *)name surname:(NSString *)surname birthdate:(NSString *)birthdate address:(NSString*) address city:(NSString *)city state:(int)state country:(int)country zipCode:(int)zipCode email:(NSString *)email password:(NSString *)password fromViewController:(UIViewController *)currentViewController
{
self.currentViewController = currentViewController;
//Create the post with the username and password
NSString *post =[[NSString alloc] initWithFormat:#"username=%#&name=%#&surname=%#&address=%#&city=%#&state=%d&country=%d&zipcode=%d&birthdate=%#&email=%#&password=%#&",username, name, surname, address, city, state, country, zipCode, birthdate,email,password];
NSLog(#"post: %#", post);
User *user;
[self getObjects:user ofClass:NSClassFromString(#"User") fromUrl:signupURL withPost:post orPut:nil token:nil callName:#"createUser" andAlertTitle:#"SignUp Failed"];
}
-(void) getPointsWithToken:(NSString *)token fromViewController:(UIViewController *)currentViewController{
self.currentViewController = currentViewController;
[self getObjects:nil ofClass:nil fromUrl:getPointsURL withPost:nil orPut:nil token:token callName:#"getPoints" andAlertTitle:#"Get Proints Number Failed"];
}
-(void)getStatesforCounry:(int)idCountry fromViewController:(UIViewController *) currentViewController
{
self.currentViewController = currentViewController;
NSString *url = [NSString stringWithFormat:#"%#%d", getStatesURL, idCountry];
// NSLog(#"url: %#", url);
State *state;
[self getObjects:state ofClass:NSClassFromString(#"State") fromUrl:url withPost:nil orPut:nil token:nil callName:#"getStates" andAlertTitle:#"States not loaded"];
}
...
Using a delegate protocol pattern might help, but in this situation, I think my preference would be to pass a completion-handling block into the method, then call that completion handler block on the main thread to handle the results of the API call—it feels like there's a bit too much view-controller logic going on in the API method and using a completion-handling block (or a delegate callback method) would help move that logic back to the view controller.
Also, though it doesn't really change anything, you can replace the calls
dispatch_async(dispatch_get_main_queue(), ^(void){
...
});
with
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
...
}];
(It is generally preferable to use higher-level APIs, such as NSOperationQueue, over lower-level APIs, like dispatch_async, when they are equivalent.)

Resources