2014-10-29 16 views
-2

關於互聯網上的每一個教程和示例,我都會看到如何從某個URL獲取JSON並在Tableview中顯示它。這不是我的問題我知道如何用AFNetworking框架或本地API來做到這一點。如何在UIView標籤中顯示JSON數據

我的問題是,我已經下載了JSON後,我想在我的UIView標籤中顯示它。當我試圖找到解決NSURLSession無法在iOS 8中緩存的方法時,我實際上成功地做到了這一點。但是我沒有意識到它是同步的。

Factory.m

+ (Factory *)responseJson 
{ 
    static Factory *shared = nil; 

    shared = [[Factory alloc] init]; 

    NSHTTPURLResponse *response = nil; 
    NSString *jsonUrlString = [NSString stringWithFormat:@"http://urltojson.com/file.json"]; 
    NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 
    NSError *error = nil; 

    NSURLRequest *request = [NSURLRequest requestWithURL:url 
              cachePolicy:NSURLRequestReturnCacheDataElseLoad 
             timeoutInterval:10.0]; 
    NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

    if (error) { 
     NSLog(@"error"); 
    } else { 
     //-- JSON Parsing 
     NSDictionary *result = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil]; 
     //NSLog(@"Result = %@",result); 
     shared.responseJson = result; 
    } 

    return shared; 
} 

我的問題是有可能使用例如AFNetwoking做同樣的事情?我失去了一些方法,我需要在類似的情況下調用的TableView

[self.tableView reloadData]; 
我想是因爲我需要檢查可達性,它似乎已經實現了它使用的框架。

編輯爲要求出示更多的代碼

ViewController.m

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [self factoryLoad]; 
    [self setupView]; 
} 
- (void)factoryLoad 
{ 
    Factory *shared = [Factory responseJson]; 
    self.titles = [shared.responseJson valueForKeyPath:@"data.title"]; 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self.collectionView reloadData]; 

    }); 
} 

- (void)setupView 
{ 
    self.issueTitleLabel.text = [self.titles objectAtIndex:0]; 
} 
+1

所以,你在哪裏試圖把數據放到標籤這種方法嗎? – 2014-10-29 18:20:15

+0

在viewDidLoad中。使用異步提取方法,我嘗試將提取方法放在viewWillAppear中,並設置viewDidLoad中的所有標籤,但這並不奏效。 – Pahnev 2014-10-29 18:25:07

+1

你能編輯你的問題並顯示用於設置標籤文本的代碼嗎?如果您正在異步提取數據並將標籤文本設置爲完成處理程序之外,則可能會嘗試將文本設置爲一個實際不存在的值,因爲數據尚未提取。 – 2014-10-29 18:33:40

回答

0

好的,我對Morgan Chen的回答以及如何阻止進行了深入調查。

該示例代碼進行了一些修改,但我認爲它的工作原理應該是更好的代碼。

在Factory.m

+ (Factory *) sharedInstance 
{ 
    static Factory *_sharedInstance = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     _sharedInstance = [[self alloc] init]; 
    }); 
return _sharedInstance; 
} 

-(void)fetchDataInBackgroundWithCompletionHandler: (void(^)(BOOL success, NSDictionary  *data, NSError *error)) block 
{ 
    NSString * baseURL = @"http://jsonurl.com/file.json"; 
    AFHTTPRequestOperationManager * manager = [[AFHTTPRequestOperationManager alloc] init]; 

    __weak AFHTTPRequestOperationManager *weakManager = manager; 

    NSOperationQueue *operationQueue = manager.operationQueue; 
    [manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { 
    switch (status) { 
     case AFNetworkReachabilityStatusReachableViaWWAN: 
     case AFNetworkReachabilityStatusReachableViaWiFi: 
      NSLog(@"internet!"); 
      [weakManager.requestSerializer setCachePolicy:NSURLRequestReloadIgnoringCacheData]; 

      [operationQueue setSuspended:NO]; 
      break; 
     case AFNetworkReachabilityStatusNotReachable: 
      NSLog(@"no internet"); 
      [weakManager.requestSerializer setCachePolicy:NSURLRequestReturnCacheDataElseLoad]; 
      [operationQueue setSuspended:YES]; 
      break; 
     default: 
      break; 
    } 
}]; 

[manager.reachabilityManager startMonitoring]; 


manager.responseSerializer = [AFJSONResponseSerializer serializer]; 
[manager GET:baseURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 

    if (responseObject && [responseObject isKindOfClass:[NSDictionary class]]) { 

     block(YES, responseObject, nil); 

    } 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { // invalid request. 
    NSLog(@"%@", error.localizedDescription); 
    block(NO, nil, error); 
}]; 

} 

在ViewController.m我呼籲viewDidLoad中

-(void)factoryLoad 
{ 
    [[Factory sharedInstance] fetchDataInBackgroundWithCompletionHandler:^(BOOL success, NSDictionary *data, NSError *error) { 
    if (success) { 
     NSLog(@"we have stuff"); 
     self.responseData = data; 

     self.titles = [self.responseData valueForKeyPath:@"data.title"]; 
     [self setupView]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self.collectionView reloadData]; 

     }); 

    } 
}]; 
} 
0

有你發佈的代碼一對夫婦的古怪。

  • 工廠應該在dispatch_once中實例化,以確保線程安全。
  • ViewController.m中,您在主線程上調用factoryLoad,主線程隨後在主線程上調用sendSynchronousRequestApple's NSURLConnection Documentation警告不要在主線程上調用此函數,因爲它阻塞了線程,導致您的應用程序無法響應用戶輸入。
  • 作爲NSJSONSerialization JSONObjectWithData:中的錯誤參數,您不應傳入nil

在你的情況,我會建議分離從你的單身物體的建設中獲取數據。

Factory.m

+(Factory *)sharedFactory { 
    static Factory *sharedFactory = nil; 
    dispatch_once_t onceToken; 
    dispatch_once(&onceToken, { 
     sharedFactory = [[Factory alloc] init]; 
    }); 
} 

-(void)fetchDataInBackgroundWithCompletionHandler:(void(^)(NSURLResponse *response, 
                  NSData *data, 
                  NSError *error) 
                  completion { 
    NSHTTPURLResponse *response = nil; 
    NSString *jsonUrlString = [NSString stringWithFormat:@"http://urltojson.com/file.json"]; 
    NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 

    NSURLRequest *request = [NSURLRequest requestWithURL:url 
              cachePolicy:NSURLRequestReturnCacheDataElseLoad 
             timeoutInterval:10.0]; 

    NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init]; 
    [NSURLConnection sendAsynchronousRequest:request 
             queue:downloadQueue 
          completionHandler:completion]; 
} 

現在,你應該能夠創建一個參考的數據有保證的下載請求已完成,因此數據會存在。

ViewController.m

-(void)factoryLoad { 
    [[Factory sharedFactory] fetchDataInBackgroundWithCompletionHandler:^(void)(NSURLResponse *response, NSData *data, NSError *error){ 
     if(!error) { 
      NSError *error2; 
      NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error2]; 

      if(error2){ /* handle error */ } 

      self.titles = [serializedData valueForKeyPath:@"data.title"]; 
      [Factory sharedFactory].responseJSON = serializedData; 
     } 
     else { 
      // handle error 
     } 
    }]; 
} 

這將保證下載完成後您嘗試訪問任何下載的信息之前。但是,我在這裏留下了一些內容,包括向用戶顯示該應用在後臺執行重要事情的任何類型的活動指示器。其餘的,呃,留給讀者作爲練習。

+0

是的,我知道在主線程上進行同步調用是不好的,但在這種情況下,我只在應用程序啓動時獲取數據並緩存它,所以它不會阻止任何事情。 無論如何,這個代碼並沒有真正幫助我,因爲我試圖實現AFNetworking的可達性方法。 – Pahnev 2014-10-29 21:21:12