2012-06-16 60 views
0

我想要做的是創建一個類,該類在調用時返回Json數據的NSDictionary。我過去用圖像做了同樣的事情,但是我對如何用NSDictionary實現它有點困惑。從異步NSURLConnection返回NSDictionary /類

我想要做的是加載一個視圖,然後在後臺發送請求以獲取一些Json數據(異步)並返回字典與要使用的數據。我將在很多不同的視圖中加載很多Json數據,所以它應該是一個可重用的類。

- (id)initWithURL:(NSURL *)url 
{ 
    self = [self init]; 

    if (self) 
    { 
     receivedData = [[NSMutableData alloc] init]; 
     [self loadWithURL:url]; 
    } 

    return self; 
} 

- (void)loadWithURL:(NSURL *)url  
{ 
    NSURLConnection *connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url]delegate:self]; 
    [connection start]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    [receivedData setLength:0]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [receivedData appendData:data]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 

    NSError *error = nil; 

    jsonReturn = [NSJSONSerialization JSONObjectWithData:receivedData options:kNilOptions error:&error]; 

} 

我想過只是將結果添加到視圖可以訪問的協議中,但是必須有更簡單/更清晰的方式嗎?有沒有辦法讓它像這樣返回NSdictionary:

NSDictionary * dictionary = [LoadURLJSon initWithURL:myurl];

它獲取NSDictionary?

+0

你想要的是在異步API(特別是'[NSURLConnection start]')之上的同步操作。沒有一些沉重的線程雜耍,你無法做到這一點,無論如何這是一個壞主意 - 異步是真的要走。不要把異步性扔掉。 –

+0

我知道你是對的我一直在自己辯論 - 所以你認爲我應該去協議路由,並使所有需要它的類符合協議? – KDM

回答

0

你想要的是在異步API(特別是,[NSURLConnection start])之上的同步操作。沒有一些沉重的線程雜耍,你無法做到這一點,無論如何這是一個壞主意 - 異步是真的要走。不要把異步性扔掉。

執行一次性異步檢索方法的最佳方法是構建一個方法,該方法將URL,NSObject和選擇器作爲參數,一旦請求完成,就調用所述對象上的所述選擇器,提供NSDictionary作爲參數。這是Objective C做回調的方式。

該方法將內部實例化您的類,傳遞迴調信息,併發起請求。一旦完成請求並將JSON解析爲NSDictionary,就可以在回調NSObject上調用[performSelector:]

如果您想要同步操作,請使用[NSURLConnection sendSynchronousRequest]而不是[NSURLConnection start]

+0

謝謝!請參閱下面的使用協議的完整實現。 – KDM

0

這就是我結束的!這對未來通過這些人來說應該是有用的。

#import <Foundation/Foundation.h> 

@protocol LoadJsonDelegate <NSObject, NSURLConnectionDelegate> 
@optional 
- (void) downloadFinished; 
- (void) downloadReceivedData; 
- (void) dataDownloadFailed: (NSString *) reason; 
@end 

@interface LoadURLJson : NSObject 
{ 
    NSMutableData *receivedData; 
    int expectedLength; 
} 

@property (nonatomic, strong) NSMutableData *receivedData; 
@property (strong) NSString *urlString; 
@property (weak) id <LoadJsonDelegate> delegate; 

-(void)start; 
-(void)cancel; 

+ (id)download:(NSString *)aURLString withDelegate:(id <LoadJsonDelegate>)aDelegate; 

@end 

的.M

#import "LoadURLJson.h" 
#define SAFE_PERFORM_WITH_ARG(THE_OBJECT, THE_SELECTOR, THE_ARG) (([THE_OBJECT respondsToSelector:THE_SELECTOR]) ? [THE_OBJECT performSelector:THE_SELECTOR withObject:THE_ARG] : nil) 

@implementation LoadURLJson 

@synthesize receivedData, delegate, urlString; 

+ (id) download:(NSString *)aURLString withDelegate:(id <LoadJsonDelegate>)aDelegate 
{ 
    if (!aURLString) 
    { 
     NSLog(@"Error. No URL string"); 
     return nil; 
    } 

    LoadURLJson *loadJson = [[self alloc] init]; 
    loadJson.urlString = aURLString; 
    loadJson.delegate = aDelegate; 
    [loadJson start]; 

    return loadJson; 
} 

-(void)start 
{ 
    receivedData = [NSMutableData data]; 
    NSURL *url = [NSURL URLWithString:urlString]; 

    NSURLConnection *connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url]delegate:self]; 
    [connection start]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    [receivedData setLength:0]; 

    // Check for bad connection 
    expectedLength = [response expectedContentLength]; 
    if (expectedLength == NSURLResponseUnknownLength) 
    { 
     NSString *reason = [NSString stringWithFormat:@"Invalid URL [%@]", urlString]; 
     SAFE_PERFORM_WITH_ARG(delegate, @selector(dataDownloadFailed:), reason); 
     [connection cancel]; 
     [self cleanup]; 
     return; 
    } 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [receivedData appendData:data]; 
    SAFE_PERFORM_WITH_ARG(delegate, @selector(downloadReceivedData), nil); 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    SAFE_PERFORM_WITH_ARG(delegate, @selector(downloadFinished), nil); 
} 

-(void)cleanup 
{ 
    self.urlString = nil; 
} 

-(void)dealloc 
{ 
    [self cleanup]; 
} 

-(void)cancel 
{ 
    [self cleanup]; 
} 

@end 

使用率 - 在yourView.h

#import "LoadURLJson.h" 

@interface ViewController : UIViewController <LoadJsonDelegate> 
{ 
    LoadURLJson *loadJson; 
} 

youView.m

隨着電話:

loadJson = [LoadURLJson download:@"url" withDelegate:self]; 

然後實現

-(void)downloadFinished 
{ 
    NSData *data = [[NSData alloc] initWithData:loadJson.receivedData]; 

    NSError *error = nil; 
    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error:&error]; 

    NSLog(@"%@",dictionary); 
} 

基於關閉DownloadHelper這裏:https://github.com/erica/iOS-5-Cookbook

BSD許可證。