2013-11-15 84 views
3

我有一個問題。也許2個問題。AFNetworking 2.0 responseObject處理

首先一個涉及這段代碼:

-(void)isLoggedIn { 
NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUserIsLogged]; 
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments]; 
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"JSON: %@", responseObject); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    NSLog(@"Error: %@", error); 
}]; 
} 

我想,這種方法是不是一個空白,我想它被返回BOOL或東西,我可以使用像:用戶是登錄>確定在應用程序中的某處執行某些操作;用戶未登錄> OK提示用戶在屏幕上,在那裏他可以介紹他的憑據,並登錄

第二個問題是有關這段代碼:

-(void)detail { 
NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUser]; 
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments]; 
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"JSON: %@", responseObject); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    NSLog(@"Error: %@", error); 
}]; 
} 

我想,這種方法返回給我一個解析的JSON的NSArray,我可以在任何地方使用它。

該方法包含在名爲NetworkModel(NSObject子類)的模型中。我只是想知道爲什麼我應該在街區內做所有事情。我應該有與整個地方的網絡互動的部分,而不是組織在一個獨特的地方/類。有沒有辦法做到這一點。我不希望每個ViewController有5行請求。我想定義我可以從任何ViewController調用的方法(顯然在需要的地方導入頭文件)。

有什麼建議嗎? 謝謝您的建議!

回答

3

你可以用2名的方法做到這一點,一個改變以使用塊或使用信號量等待異步請求的方法:

隨着信號量(THE UGLY WAY)

-(BOOL)isLoggedIn { 

__block BOOL isLoggedIn; 
dispatch_semaphore_t waiter = dispatch_semaphore_create(0); 

NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUserIsLogged]; 
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments]; 
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"JSON: %@", responseObject); 
    isLoggedIn = YES; 
    dispatch_semaphore_signal(waiter); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    NSLog(@"Error: %@", error); 
    isLoggedIn = NO; 
    dispatch_semaphore_signal(waiter); 

}]; 

dispatch_group_wait(waiter, DISPATCH_TIME_FOREVER); 
return isLoggedIn; 
} 

正確的方式做到這一點

-(void)isLoggedIn:(void(^)(BOOL isLoggedIn))completionBlock { 
NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUserIsLogged]; 
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments]; 
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"JSON: %@", responseObject); 
    completionBlock(YES); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    NSLog(@"Error: %@", error); 
    completionBlock(NO); 
}]; 
} 

關於第二個問題,你可以設置你的網絡類塊變量請求完成或失敗時將被調用。

無論如何,我認爲你不是很熟悉塊(因爲你的第二個問題),我想在幾個塊之後,你會開始喜歡它們,如果你有一小段代碼片段,你會發現代碼並不複雜執行請求&解析的代碼,您也會看到它很容易調試它們並發現問題,我的意思是,當我開始使用塊時,這也是我的情況。

使用塊變量

@interface YourNetworkClass:NSObject { 
void(^resultHandlerBlock)(NSArray *results); //this block has as param a NSArray, you can change it to whatever you want 
} 

-(void)setResultHandlerBlock:(void(^)(NSArray *array))handlerBlock; 

@implementation YourNetworkClass 

-(void)setResultHandlerBlock:(void(^)(NSArray *array))handlerBlock { 
resultHandlerBlock = block; 
} 

-(void)anotherMethodThatDoesNetworkOperationsAndReturnsAnArray { 
.... 
resultHandlerBlock(arrayOfResults); 
} 


@interface AViewControllerThatUseNetwork: UIViewController { 
} 

@implementation AViewControllerThatUseNetwork 

-(void)initNetworkClass { 
    YourNetworkClass *networkClass = [[YourNetworkClass alloc] init]; //or other init methods 
    [networkClass setResultHandlerBlock:^(NSArray *results) { 
    //do whatever you want with the array 
}]; 
} 
+0

我會檢查一下。關於我對塊的熟悉程度,你是完全正確的。此外,當我需要它時,我已經習慣了數據,而這種異步的東西現在正在混淆我的頭......但我會習慣它。我只需要首先理解:這就是爲什麼我問了一個虛擬問題。 – user1447316

+0

因此,關於第二個問題,您建議我創建一個塊變量,然後在成功塊中設置:blockVariable = responceObject? – user1447316

+1

@ user1447316檢查我編輯的答案 – danypata

1

您的方法應該包含一個將從AFNetworking成功(或失敗)塊中執行的塊(或兩個)。這種方法包含了你想要做的事情的異步性。由於這種異步性,您無法將返回值添加到方法中。


所以,你要讓你的方法更改爲:

-(void)isLoggedInWithCompletion:(LoginCompletionBlock)completion { 
    ... 

    [manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
     NSLog(@"JSON: %@", responseObject); 
     completion(/* whatever parameters your block specifies */); 
    } ... 
} 
+0

我意識到這種異步性,這就是爲什麼我要求最好的方式來做到這一點,尊重這一事實。你能告訴我一個我用代碼問的例子嗎?謝謝你的建議。 – user1447316

1

我問類似的東西而回。我相信你會在那裏找到你的解決方案。 Passing blocks to a AFNetworking method?

一般情況下,你需要改變你的思考,你應該從獲取數據的方式「如果登錄回報BOOL」,以「檢查,如果我可以登錄,如果失敗的AFNetworking塊內做一些事情。

上面還鏈接回答你的第二個問題

+0

有趣的建議!謝謝!嗯..我的問題是,如果我「檢查,如果我可以登錄」,我的服務器將根據我是否真的登錄或不真實回答成功塊中的TRUE或FALSE。我應該如何處理?如果用戶是IN或OUT,它將會成功。只有在服務器出於某種原因而關閉的情況下才會失敗,或者我查詢了無效的鏈接或其他內容。 – user1447316

+1

如果登錄成功或不成功,您需要向用戶發送一個請求,登錄密碼並在成功塊內獲得響應。例如,發送[email protected] 123到服務器,服務器將返回:嗨!我知道那傢伙!你將進入成功模塊。然後你可以移動到Logged In ViewController。 – Segev

+0

謝謝!這正是我所做的。我發佈了一個我的問題的答案。 – user1447316

0

因此,在不大的情況下更新(所有珍貴suggestions..thanks傢伙謝謝!)。現在,我的代碼看起來像這樣(在我NetworkModel.m,很明顯,我已經添加了方法NetworkModel.h,這樣我可以在任何地方調用它):

-(void)isLoggedIn:(void(^)(BOOL isLoggedIn))completionBlock { 
NSString *urlString = [NSString stringWithFormat:@"%@%@%@", kBaseURL, kAPI, kUserIsLogged]; 
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments]; 
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"JSON: %@", responseObject); 
    if ([[NSString stringWithFormat:@"%@", responseObject] isEqualToString:@"true"]) { 
     completionBlock(YES); 
    } else { 
     completionBlock(NO); 
    } 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    NSLog(@"Error: %@", error); 
    completionBlock(NO); 
}]; 
} 

在我AppDelegate.h我包括我的NetworkModel .h和我的AppDelegate.m我現在有以下代碼:

[[self model] isLoggedIn:^(BOOL isLoggedIn) { 
    if (isLoggedIn == YES) { 
     UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 
     UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"Start01"]; 
     [self.window setRootViewController:controller]; 
    } else { 
     UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 
     UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"Start00"]; 
     [self.window setRootViewController:controller]; 
    }  
}]; 

它的工作原理還不錯。但是現在我對此有另一個問題。當我運行該應用程序時,發生了一些奇怪的事情。只要它檢索到有關用戶登錄狀態的信息,它就會從VC(指定的InitialView控制器 - Storyboard上的Start00)跳轉到VC(loggedInVC - Storyboard上的Start01)。有沒有辦法不向用戶展示這種有點跳躍?或者這是一個正常的行爲?現在用戶會看到第一個屏幕,然後是他應該看到的屏幕(因爲他已登錄)。

但我想最簡單的方法來處理塊,所有這一切都是在我需要它們的地方使用它們。而不是試圖將它們封裝到方法或類或其他類中。只要數據在那裏,我就會直接在成功或失敗塊中做我所擁有的。我在想對嗎?