试图从异步调用传输数据到另一个类
我知道这是一个愚蠢的问题,但我找不到解决方案。
这里是我的代码:
ConnectionService.h
试图从异步调用传输数据到另一个类
#import "LaunchScreenViewController.h"
@interface ConnectionService : NSObject
-(void)getsFeaturedProducts;
@end
ConnectionService.m
-(void)getsFeaturedProducts {
NSString *urlString = [NSString stringWithFormat:@"my-url",[[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];
_featuredProducts = [[NSDictionary alloc]initWithDictionary:value];
NSLog(@"Featured products: %@", _featuredProducts);//not empty
LaunchScreenViewController *lsvc = [[LaunchScreenViewController alloc]init];
lsvc.featuredProducts = self.featuredProducts;
NSLog(@"Featured products: %@", lsvc.featuredProducts);//not empty
}];
[getData resume];
}
LaunchScreenViewController.h
#import "ConnectionService.h"
@interface LaunchScreenViewController : UIViewController
@property(nonatomic,strong) NSDictionary *featuredProducts;
@end
LaunchScreenViewController.m
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:YES];
ConnectionService *connectionService = [[ConnectionService alloc]init];
[connectionService refreshProducts];
self.featuredProducts = [[NSDictionary alloc]init];
NSLog(@"featuredProducts: %@", self.featuredProducts);//empty
NSArray *keys = [[NSArray alloc]initWithArray:[self.featuredProducts allKeys]];
NSLog(@"All featured product keys: %@", keys);
}
我做错了什么?
P.S.编程objective-c少于一个月,所以是的...谢谢你的-rep。
你的代码不起作用,因为用alloc init
创建的LaunchScreenViewController
实例不是在Storyboard/XIB文件中创建的实例。
从另一个类异步检索数据的推荐方法是完成处理程序。
ConnectionService.m使用完成处理程序实现该方法并在.h文件中相应地声明它。
- (void)getsFeaturedProductsWithCompletion:(void (^)(NSDictionary *products))completion
{
NSString *urlString = [NSString stringWithFormat:@"my-url",[[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];
}
备注:强烈建议在数据任务中添加错误处理!
在LaunchScreenViewController.h声明为ConnectionService
实例
#import "ConnectionService.h"
@interface LaunchScreenViewController : UIViewController
@property(nonatomic,strong) NSDictionary *featuredProducts;
@property(nonatomic,strong) ConnectionService *connectionService;
@end
一个属性在LaunchScreenViewController.m呼叫的方法
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:YES];
connectionService = [[ConnectionService alloc]init];
[connectionService getsFeaturedProductsWithCompletion:^(NSDictionary *products) {
self.featuredProducts = products;
NSLog(@"featuredProducts: %@", self.featuredProducts);//empty
NSArray *keys = [[NSArray alloc]initWithArray:[self.featuredProducts allKeys]];
NSLog(@"All featured product keys: %@", keys);
connectionService = nil; // release the connectionService instance if needed
}];
}
您需要将结果返回给您的控制器。
你需要做的是给你的 - (void)getsFeaturedProducts函数添加一个完成块,然后一旦结果返回,你就调用它传回结果。
在同一功能中,您可以使用正确的数据重新加载视图。
服务:
-(void)getsFeaturedProducts:(void (^)(NSDictionary *featuredProducts))completionHandler {
NSString *urlString = [NSString stringWithFormat:@"my-url",[[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 *featuredProducts = [rawJson JSONValue];
completionHandler(featuredProducts);
}];
[getData resume];
}
控制器:
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:YES];
ConnectionService *connectionService = [[ConnectionService alloc]init];
[connectionService refreshProducts:^(NSDictionary *featuredProducts) {
self.featuredProducts = featuredProducts;
NSLog(@"featuredProducts: %@", self.featuredProducts);
NSArray *keys = [[NSArray alloc]initWithArray:[self.featuredProducts allKeys]];
NSLog(@"All featured product keys: %@", keys);
//Reload data here...
}];
}
我不按任何控制器,LaunchScreenViewController是我的应用程序启动时显示的第一个ViewController。 – Ookey
不适当回复...等待:) – mt81
这个答案有可能成为最习惯和最简洁的解决方案。但是,@ mt81,请添加更多代码。 ;) – CouchDeveloper
-(void)getsFeaturedProducts {
NSString *urlString = [NSString stringWithFormat:@"my-url",[[AppDelegate instance] getUrl]];
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionDataTask *getData = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData* data, NSURLResponse *response, NSError* error){
dispatch_async(dispatch_get_main_queue(), ^{
NSString* rawJson = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *value = [rawJson JSONValue];
_featuredProducts = [[NSDictionary alloc]initWithDictionary:value];
NSLog(@"Featured products: %@", _featuredProducts);//not empty
LaunchScreenViewController *lsvc = [[LaunchScreenViewController alloc]init];
lsvc.featuredProducts = self.featuredProducts;
[[[UIApplication sharedApplication] keyWindow] setRootViewController:lsvc];
})
}];
[getData resume];
}
你在想这个同步的问题错了 - 但你并不远关闭。以下是您的代码现在正在执行的操作:
LaunchScreenViewController的实例已创建。
这LaunchScreenViewController的实例创建ConnectionService实例
为您的异步数据ConnectionService查询
当返回数据,它创建LaunchScreenViewController的全新实例,并通过它的数据。
您检查数据的原始LaunchScreenViewController,但没有任何 - 它进入新的实例。
您想要将数据传回原始的LaunchScreenViewController。有几种方法可以做到这一点。我会告诉你一个,并链接到第二个。
让我们做如何通过NSNotificationCenter数据传回给原来的控制器的例子:
LaunchScreenViewController.m
- (void)viewDidLoad:(BOOL)animated{
//Your current code....
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(receiveConnectionData:)
name:@"ConnectionDataReceived"
object:nil];
}
- (void) receiveTestNotification:(NSNotification *) notification
{
// [notification name] should always be @"ConnectionDataReceived"
// unless you use this method for observation of other notifications
// as well.
if ([[notification name] isEqualToString:@"ConnectionDataReceived"]){
self.featuredProducts = [[NSDictionary alloc]init];
NSLog(@"featuredProducts: %@", self.featuredProducts);//empty
NSArray *
NSArray *keys = [[NSArray alloc]initWithArray:[notification.object allKeys]];
NSLog(@"All featured product keys: %@", keys);
NSLog (@"Successfully received the test notification!");
}
}
在你ConnectionService.h
-(void)getsFeaturedProducts {
NSString *urlString = [NSString stringWithFormat:@"my-url",[[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];
_featuredProducts = [[NSDictionary alloc]initWithDictionary:value];
NSLog(@"Featured products: %@", _featuredProducts);//not empty
//Pass the NSDictionary back to the ORIGINAL LaunchViewController
[[NSNotificationCenter defaultCenter] postNotificationName:@"ConnectionDataReceived" _featuredProducts];
}];
[getData resume];
}
注意:您也可以使用委托来完成此任务,这更复杂但更强大。你可以在这里找到Chris Mills的一个很好的教程:https://coderchrismills.wordpress.com/2011/05/05/basic-delegate-example/
谢谢,它的帮助! – Ookey
'[[洗衣机。 chScreenViewController alloc] init]'创建一个新的对象。然后你更新它的属性,但是你永远不会呈现它,所以这个对象的视图永远不会出现。如果您已在屏幕上显示'LaunchScreenViewController',则需要使用它。 –
这是我第一次建议,但它没有奏效。 – Ookey