2013-12-12 39 views
1

加載我的UIViewController時,我基本上把一個微調器在頁面中間,直到內容加載,然後再回到主線程添加子視圖:異步UIView內容沒有顯示當回到主線程

- (void)viewDidLoad { 

    [super viewDidLoad]; 

    UIActivityIndicatorView *aiv_loading = ... // etc 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Load content 
     NSString *s_checkout = [[BRNetwork sharedNetwork] getCheckoutInstructionsForLocation:self.locBooking.location]; 
     UIView *v_invoice_content = [[BRNetwork sharedNetwork] invoiceViewForBooking:locBooking.objectId]; 

     // Display the content 
     dispatch_sync(dispatch_get_main_queue(), ^{ 

      if (s_checkout && v_invoice_content) { 
       [aiv_loading removeFromSuperview]; 
       [self showContentWithText:s_checkout AndInvoice:v_invoice_content]; 
      } else { 
       NSLog(@"No data received!"); // is thankfully not called 
      } 
     }); 
    }); 
} 

- (void) showContentWithText:(NSString *)s_checkout AndInvoice:(UIView *)v_invoice { 

    [self.view addSubview:[self checkoutTextWithText:s_checkout]]; // Most of the time displayed text 
    [self.view addSubview:[self completeCheckout]]; // always Displayed UIButton 
    [self.view addSubview:[self divider]]; // always displayed UIImageView 

    // Summary title 
    UILabel *l_summary = [[UILabel alloc] initWithFrame:CGRectMake(0, [self divider].frame.origin.y + 6 + 10, self.view.bounds.size.width, 20)]; 
    l_summary.text = NSLocalizedString(@"Summary", nil); 
    [self.view addSubview:l_summary]; 

    CGRect totalRect = CGRectMake([self divider].frame.origin.x, [self divider].frame.origin.y + 6 + 30, self.view.bounds.size.width - [self divider].frame.origin.x, 90); 
    _v_invoice = v_invoice; 
    _v_invoice.frame = totalRect; 
    [self.view addSubview:[self v_invoiceWithData:v_invoice]]; // THIS Pretty much never displayed 

    UITextView *l_invoice = [[UITextView alloc] initWithFrame:CGRectMake(0, _v_invoice.frame.origin.y + _v_invoice.frame.size.height + offset, 320.0, 50)]; 
    l_invoice.text = NSLocalizedString(@"summary_emailed", nil); 
    [self.view addSubview:l_invoice]; // Always displayed 
} 

然而,並非顯示的所有內容。發票永遠不會在那裏,但會在幾分鐘後顯示出來。另一個異步創建的字符串s_content有時不顯示。

這似乎與內容創建隨機。最終結果非常簡潔,但對於生產版本來說不可靠。

我用未記錄的[self.view遞歸描述]來檢查一切是否存在,即使我沒有看到它們,它們都與那裏似乎是正確的幀。

任何指針? - layoutSubviews沒有幫助! - 在發票視圖中放置背景顏色顯示背景顏色

回答

3

我懷疑這條線是你的問題:

UIView *v_invoice_content = [[BRNetwork sharedNetwork] invoiceViewForBooking:locBooking.objectId]; 

如你在後臺調度隊列調用此。任何涉及UIKit的工作都應該在主隊列/線程上完成。將其移入主線程塊,或者如果構建視圖取決於來自網絡調用的數據,請更改您的方法以首先返回數據,然後使用該數據在主線程中構建視圖。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Load content 
     NSString *s_checkout = [[BRNetwork sharedNetwork] getCheckoutInstructionsForLocation:self.locBooking.location]; 
     id someData = [[BRNetwork sharedNetwork] invoiceDataForBooking:locBooking.objectId]; 

     // Display the content 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      UIView *v_invoice_content = [invoiceViewWithData:someData]; 
     }); 
    }); 

我也建議在主隊列使用dispatch_async代替dispatch_sync

-1

您應該將代碼放在viewDidAppear而不是viewDidLoad。無論與顯示有關(甚至啓動異步塊),應始終在viewWillAppearviewDidAppear

此外,我建議您使用dispatch_async(dispatch_get_main_queue(), ^{})而不是您的dispatch_sync,因爲您仍然希望您的塊執行異步(但在主線程上)。

不要忘記調用超級方法在viewDidAppear

+0

在'viewDidLoad'你的觀點應該已經被加載這樣就可以顯示你想要有和任何特別是如果你不希望每次顯示您的視圖的時間來重新顯示的東西,你應該** **使用'viewDidLoad' 。你在哪看到這個建議? –

+0

剛剛嘗試,但不幸的是沒有改變任何東西!真正難以理解的是,當檢查self.view,右邊框,右邊文本的子視圖時,內容就在那裏,但沒有任何顯示。 –

+1

@Ivan Genchev在'viewDidLoad'中存在視圖框架不準確的情況。 ,layoutSubviews尚未被調用。此外,還有一些UIView動畫由iOS執行,同時呈現可能縮短放置在'viewDidLoad'中的演示代碼的視圖。我同意,只有一次性代碼應該在其他地方,或者包含在像if(isFirstAppearance)這樣的檢查中,因爲只要視圖回到焦點時就執行viewDidAppear。 – Rufel

0

解決!我結束了去除dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 僅讓異步塊上的主隊列:

// Display the content from a new async block on the main queue. 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [aiv_loading removeFromSuperview]; 
    NSString *s_checkout = [[BRNetwork sharedNetwork] getCheckoutInstructionsForLocation:self.locBooking.location]; 
    [self showContentWithText:s_checkout AndInvoice:[[BRNetwork sharedNetwork] invoiceViewForBooking:locBooking.objectId]]; 
}); 

其中的伎倆,視圖控制器的視圖可以無需等待視圖加載遠程數據出現!