加载我的UIViewController时,我基本上在页面中间放置一个微调器,直到内容加载,然后返回主线程添加子视图:
- (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 recursiveDescription]来检查是否所有内容都存在,即使我没有看到它们,它们也都是正确的框架。
任何指针? - layoutSubviews没有帮助! - 将背景颜色放在发票视图中显示背景颜色
答案 0 :(得分:3)
我怀疑这一行是你的问题:
UIView *v_invoice_content = [[BRNetwork sharedNetwork] invoiceViewForBooking:locBooking.objectId];
当您在后台调度队列中调用它时。任何涉及UIKit的工作都应该在主队列/线程上完成。将其移动到主线程块中,或者如果构建视图依赖于来自网络调用的数据,请更改invoiceViewForBooking
方法以首先返回数据,并使用该数据在主线程中构建视图。 / p>
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 :(得分: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]];
});
这样做的技巧,viewcontroller的视图可以在不等待视图加载远程数据的情况下出现!
答案 2 :(得分:-1)
您应该将代码放在viewDidAppear
而不是viewDidLoad
。与显示相关的内容(甚至启动异步块)应始终位于viewWillAppear
或viewDidAppear
。
此外,我建议您使用dispatch_async(dispatch_get_main_queue(), ^{})
而不是dispatch_sync
,因为您仍希望块执行异步(但在主线程上)。
别忘了在viewDidAppear
中调用超级方法。