2016-03-07 58 views
3

剛剛開始對objective-c進行編程,現在我遇到了無法自行處理的問題。我收到來自異步請求的數據,並嘗試將其解析爲單例,但沒有更改。嘗試在單例中更改變量,但它保持爲空

這就是我想要存儲我的數據
Data.h

#import <Foundation/Foundation.h> 
@interface Data : NSObject 
@property (nonatomic, strong) NSDictionary *products; 
-(void)setProducts:(NSDictionary *)value; 
@end 

Data.m

#import "Data.h" 

@implementation Data 

+(Data *)sharedInstance 
{ 
    static Data *_sharedInstance = nil; 
    static dispatch_once_t oncePredicate; 
    dispatch_once(&oncePredicate, ^{ 
     _sharedInstance = [[Data alloc] init]; 
    }); 
    return _sharedInstance; 
} 

- (id)init { 
    self = [super init]; 
    if (self) 
    { 
     _products = [[NSDictionary alloc] init]; 
    } 
    return self; 
} 

@end 

這是類,在那裏我從服務器接收數據:
ConnectionService.m

- (void)getProductsWithCompletion:(void (^)(NSDictionary *products))completion 
{ 
    NSString *urlString = [NSString stringWithFormat:@"serverurl", [[AppDelegate instance]getUrl]]; 
    NSURL *url = [NSURL URLWithString:urlString]; 

    NSURLSessionDataTask *getData = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ 
     NSString *rawJson = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
     NSDictionary *value = [rawJson JSONValue]; 
     completion(value); 
    }]; 
    [getData resume]; 
} 

這是我打電話請求,並嘗試提供它獨居類:
viewController.m

- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:YES]; 
    [[ConnectionService instance] getProductsWithCompletion:^(NSDictionary *products) { 
     [Data sharedInstance].products = products; 
     NSLog(@"products: %@", [[Data sharedInstance] products]);//all is working, products contains data 
    }]; 
    // checking received data 
    NSDictionary *tmp = [[Data sharedInstance] products]; 
    NSLog(@"tmp: %@", tmp); //now it's null 
} 
+1

也許是因爲你的電話是異步?首先打印什麼'NSLog()'行? – Larme

回答

6

問題的事實是,請求是異步的,事情並沒有按順序發生你期望:

- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:YES]; 
    [[ConnectionService instance] getProductsWithCompletion:^(NSDictionary *products) { 
     // (2) 
     [Data sharedInstance].products = products; 
     NSLog(@"products: %@", [[Data sharedInstance]products]);//all is working, products contains data 
    }]; 


    // (1) 
    NSDictionary *tmp = [[Data sharedInstance]products]; 
    NSLog(@"tmp: %@", tmp); //now it's null 
} 

在您發佈,(1)(2)之前發生的代碼。這是因爲(2)是完成塊的一部分,並且在網絡請求完成並且所有數據已經​​被解析並準備使用時設置爲運行。在異步請求已準備好並在後臺線程中運行的同時,主線程((1))會在請求發生之前繼續並執行。

要解決此問題,請將日誌記錄移入完成例程,或者直接刪除(1)

1

另一種方法是使用協議,通知您完成塊finished.So,你可以簡單地做:

[[ConnectionService instance] getProductsWithCompletion:^(NSDictionary *products) { 
     if(self.delegate){ 
       [self.delegate myNotifyMethod:products]; 
     } 

    }]; 

和你的協議方法:

-(void)myNotifyMethod:(NSDictionary *)items{ 
      [Data sharedInstance].products = products; 
      NSLog(@"products: %@", [[Data sharedInstance]products]); 
    } 

可以聲明協議爲:

@protocol MyProtocol <NSObject> 

- (void)myNotifyMethod: (NSDictionary *)items; 

@end 

並將代表屬性設置爲:

@property (nonatomic, weak) id<MyProtocol> delegate; 
相關問題