尝试在单例中更改变量,但它保持为空
问题描述:
刚刚开始对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)
)会在请求发生之前继续并执行。
要解决此问题,请将日志记录移入完成例程,或者直接删除(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;
也许是因为你的电话是异步?首先打印什么'NSLog()'行? – Larme