2014-05-13 34 views
0

我有一個名爲APICalls的類,它管理對API的調用。每個View Controller都會調用相應的方法(createUsername,getStates ...)並傳遞所需的參數。當數據被接收和解析時,它會回調視圖控制器以更新下載的信息的UI。下面的代碼正在工作,但我想知道是否有一個更簡單或更靈活/適當的方式來做到這一點,特別是當我更新視圖控制器中的用戶界面時。也許有協議和代表?歡迎任何建議。對後臺線程執行操作並從不同類更新UI

-(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"]; 
} 

...

回答

0

使用一個委託協議模式可能會有所幫助,但在這種情況下,我認爲我的偏好將完成處理塊傳遞到方法,然後調用完成處理程序塊在處理API調用結果的主線程上 - 感覺就像在API方法中發生了太多的視圖控制器邏輯,並且使用完成處理塊(或委託回調方法)將有助於移動該邏輯回到視圖控制器。

此外,雖然它並沒有真正改變任何東西,你可以用

[[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
    ... 
}]; 

更換電話

dispatch_async(dispatch_get_main_queue(), ^(void){ 
    ... 
}); 

(通常最好使用更高級別的API,如NSOperationQueue ,比dispatch_async等更低級別的API)。

+0

我試圖在我的類中實現完成處理塊,但由於所有方法(getObjec t,createUserWithUsername ...,getStates)在同一個類中,我從不同的ViewController調用它不工作...可能我正以錯誤的方式實現它。你能給我更多的細節,或者是一個簡單的例子嗎? – nabrugir

+0

@nabrugir:將完成塊作爲最後一個參數傳入方法 - 在方法簽名的末尾添加類似'completion:(void(^)(id data,NSError * error))completion'的東西,然後執行類似如果(完成)完成(數據,無);'在主線程上成功或'如果(完成)完成(無,錯誤);'在主線程上出錯。 – Isaac