2016-03-04 48 views
-4

我知道這是一個愚蠢的問題,但我找不到解決方案。

這裏是我的代碼:
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。

+0

'[[洗衣機。 chScreenViewController alloc] init]'創建一個新的對象。然後你更新它的屬性,但是你永遠不會呈現它,所以這個對象的視圖永遠不會出現。如果您已在屏幕上顯示'LaunchScreenViewController',則需要使用它。 –

+0

這是我第一次建議,但它沒有奏效。 – Ookey

回答

0

你的代碼不起作用,因爲用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 
    }]; 
} 
0

您需要將結果返回給您的控制器。

你需要做的是給你的 - (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... 
}]; 

}

+0

我不按任何控制器,LaunchScreenViewController是我的應用程序啓動時顯示的第一個ViewController。 – Ookey

+0

不適當回覆...等待:) – mt81

+0

這個答案有可能成爲最習慣和最簡潔的解決方案。但是,@ mt81,請添加更多代碼。 ;) – CouchDeveloper

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

我使用UI的故事板,所以我不使用segues。但是這個'[[[UIApplication sharedApplication] keyWindow] setRootViewController:lsvc];'不會改變任何東西。 – Ookey

+0

我想將'NSObjec'轉換成'ViewController',而不是'ViewController-> ViewController' – Ookey

+0

它的一個難題! –

1

你在想這個同步的問題錯了 - 但你並不遠關閉。以下是您的代碼現在正在執行的操作:

  1. LaunchScreenViewController的實例已創建。

  2. 這LaunchScreenViewController的實例創建ConnectionService實例

  3. 爲您的異步數據ConnectionService查詢

  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!"); 
    } 
} 

在你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/

+0

謝謝,它的幫助! – Ookey

相關問題