2013-01-07 57 views
1

我想調用一個類方法,它需要一個字符串並將其發佈到一個網站以接收JSON響應(在我存儲在DataClass中的一些其他變量中)。我被困在試圖以響應的形式返回數據,並且在這一點上甚至無法NSLog返回的數據。現在的問題是,現在我調用了我的類方法,類方法如何等待返回來自HTTP POST的響應以返回數據?一旦我返回我的JSON,我可以將其擴展爲字典並從那裏進行處理。幫助表示讚賞:)iOS應用程序在調用方法時等待HTTP響應?

類方法:

// 
// APISample.m 
// 
// Created by Sam on 1/6/13. 
// Copyright (c) 2013 Sam. All rights reserved. 
// 
#import "APISample.h" 
#import "DataClass.h" 
@implementation APISample 

@synthesize first_name = _first_name; 
@synthesize last_name = _last_name; 
@synthesize profile_pic_url = _profile_pic_url; 
@synthesize responseData; 
-(id)init 
{ 
    self = [super init]; 
    return self; 
    NSLog(@"Loaded APISample and fetching"); 
} 
+(id)getDataAboutUser:(NSString *)user_request_id; 
{ 
    DataClass *userdata=[DataClass getInstance]; 
NSLog(@"Loaded APISample and fetching %@", user_request_id); 
NSMutableURLRequest *user_fetch_details = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://10.0.23.161/users/user_fetch_details.php"]]; 
    [user_fetch_details setHTTPMethod:@"POST"]; 
    NSMutableString *postString = [NSMutableString stringWithString:@"id=123"]; 
    [postString appendString:@"&userrequest_id="]; 
    [postString appendString:[userdata.str_userid copy]]; 
    [postString appendString:@"&user_id="]; 
[postString appendString:[userdata.str_userid copy]]; 
    [postString appendString:@"&identifier="]; 
[postString appendString:[userdata.str_identifier copy]]; 
    [user_fetch_details setValue:[NSString stringWithFormat:@"%d", [postString length]] forHTTPHeaderField:@"Content-length"]; 
    [user_fetch_details setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]]; 
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:user_fetch_details delegate:self]; 
NSMutableData *responseData=[NSMutableData data]; 
[responseData appendData:[NSURLConnection connection:didReceiveData]; 


if (connection) { 
    // Create the NSMutableData that will hold 
    // the received data 
    // receivedData is declared as a method instance elsewhere 
    NSMutableData *responseData=[NSMutableData data]; 
} else { 
    // inform the user that the download could not be made 
} 


NSLog(@"Received Data %@", [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding]); 
return [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding]; 
} 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
[responseData appendData:data]; 
NSString *receivedDataString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; 
    if ([receivedDataString isEqualToString: @"error"]) { 
     UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Error" 
                   message:@"An error has occured. The application will now exit. Unexpected Response!" 
                   delegate:nil 
                 cancelButtonTitle:@"Close" 
                 otherButtonTitles:nil]; 
     [errorAlert show]; 
     exit(0); 
    }else{ 
     NSError* error; 
     NSDictionary* json = [NSJSONSerialization 
           JSONObjectWithData:responseData 
           options:kNilOptions 
           error:&error]; 
     NSString *firstnameResponse = [json objectForKey:@"first_name"]; 
     NSString *lastnameResponse = [json objectForKey:@"last_name"]; 
     NSString *profile_pic_urlResponse = [json objectForKey:@"profile_pic_url"]; 

     NSLog(@"didReceiveData %@ analysed " , firstnameResponse); 
    } 
} 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    NSLog(@"connectionDidFinishLoading"); 
    NSLog(@"Succeeded! Received %d bytes of data",[self.responseData length]); 
} 
@end 

我收到日誌中沒有數據「接收數據」後,並沒有看到我的錯誤消息。謝謝

回答

3

您所描述的設計模式稱爲CallBack。您需要收到將來發生的事件通知。在objective-c中有四種主要的回調形式。

目標操作配對(這是使用的按鈕,和類似的東西。「當按下這個按鈕,通知我目標,並告訴他們要執行此行動」)

代表團(你在上面的代碼中使用了NSURLConnection的代表形式,當你看到'delegate'這個詞時,我想讓你想'helper object',你說:'嗨NSURLConnection,當重要事件發生時,我想你告訴這個代表(幫手對象)關於這些事件)

通知

終於......一個我會建議爲你的目的......

塊(與不斷變化的模型對象打交道時,這些都採用了大量)。

塊是一個非常酷的變量。大多數變量保存數據。塊是一個變量,用於保存將來要執行的代碼。所以在你的情況下,你可以傳遞一個完成塊以及方法getDataAboutUser:(NSString *)user_request_id。所以它看起來像這樣。

getDataAboutUser:(的NSString *)字符串withCompletion:(無效(^)(NSData的* finishedData))CBLOCK

商店是一個cblock作爲instanceVar。然後,當NSURLConnection完成下載其所有數據時,您將執行cBlock,並將完成的數據作爲參數傳遞。

如果您之前沒有使用過這些模塊,模塊是一件相當複雜的事情,所以我建議您花20分鐘閱讀this

+0

我會盡力你們倆給我的建議和報告今晚回來!感謝您的詳細信息和幫助。一個快速跟進,因爲我將在運行時調用多個連接來獲取用戶界面的不同部分,並且不希望我的用戶在每個人獨立加載時等待,對於這些類進行線程化會更好嗎?或者是塊變量提到最好的方法?再次感謝! – user1955162

+0

你當然想要在後臺線程上做任何耗時的事情。主線程發生的任何事情都將阻止所有用戶交互以及UI更新。但是親自產生NSThreads是很少必要的。因爲NSURLConnection會自動創建和管理自己的線程。所以我只想讓它做它自己的事情 – bturner

1

由於您需要您的方法在返回之前等待響應,您可以使用NSURLConnection的便捷類方法sendSynchronousRequest來執行同步請求,而不是異步創建和管理NSURLConnection實例。

所以不是你的[[NSURLConnection的頁頭]初始化...]行,你可以這樣做:

NSURLResponse *response = nil; 
NSError *error = nil; 
NSData *responseData = [NSURLConnection sendSynchronousRequest:user_fetch_details returningResponse:&response error:&error]; 

關注,你可以立即從responseData解析的,而不是做的JSON,在連接:didReceiveData代表。

編輯:剛剛看到user698846的建議,修改您的方法簽名採取完成塊。如果您可以隨意更改您的方法簽名(即沒有人要求您的函數同步返回),那麼這也是一種更好,更清潔的方法來處理您的問題。無論哪種方式,sendSynchronousRequest可能是最簡單的方法,並且沒有什麼羞恥,特別是如果有什麼也沒有您的應用程序,也沒有您的用戶可以在等待請求完成時執行此操作。

+0

我會嘗試你給我的建議,並在今晚向我彙報!感謝您的詳細信息和幫助。一個快速跟進,因爲我將在運行時調用多個連接來獲取用戶界面的不同部分,並且不希望我的用戶在每個人獨立加載時等待,對於這些類進行線程化會更好嗎?或者是塊變量提到最好的方法?再次感謝! – user1955162

+0

如果重要的是不要阻止UI,我會避免使用同步方法,因爲這會在加載時凍結UI,除非它在自己的線程中。如果你使用異步請求,你可能沒有線程問題,以及隨之而來的開銷和線程安全問題。 – nioq

0

這是一些代碼:

NSURLResponse *response = nil; 

NSError *error = nil; 

NSData *responseData = [NSURLConnection sendSynchronousRequest:user_fetch_details returningResponse:&response error:&error]; 
+0

如果您決定發佈代碼,請確保包含說明。 – Mark