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.)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top