尝试将数据从异步调用传输到另一个类



我知道这是一个愚蠢的问题,但我找不到解决方案。

这是我的代码:
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);
}

我做错了什么?

附言编程目标-c不到一个月,所以是的...谢谢你的代表。

你对这个异步问题的看法是错误的 - 但你离得不远了。以下是您的代码现在正在执行的操作:

  1. 创建 LaunchScreenViewController 的实例。

  2. LaunchScreenViewController 的实例创建 ConnectionService 的实例

  3. 连接异步数据的服务查询

  4. 返回数据时,它会创建一个 LaunchScreenViewController 的全新实例并向其传递数据。

  5. 您检查原始 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!");
    }
}

在您的连接服务中。

-(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];

}

注意:您也可以使用委托来完成此操作,它更复杂但更可靠。你可以在这里找到克里斯米尔斯的一个很好的教程:https://coderchrismills.wordpress.com/2011/05/05/basic-delegate-example/

您的代码不起作用,因为使用 alloc init 创建的LaunchScreenViewController实例不是在情节提要/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...
}]; 

}

-(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];
}

最新更新