刚刚开始编写
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 }
解决方法
问题在于请求是异步的,并且事情没有按照您期望的顺序发生:
- (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))会在请求发生之前继续并执行.