我是Objective C的新手,来自.NET和java背景.
所以我需要异步创建一些UIwebviews,我在自己的队列中使用
dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL);
dispatch_async(queue, ^{
// create UIwebview, other things too
[self.view addSubview:webView];
});
Run Code Online (Sandbox Code Playgroud)
正如你所想象的那样会抛出一个错误:
bool _WebTryThreadLock(bool), 0xa1b8d70: Tried to obtain the web lock from a thread other
than the main thread or the web thread. This may be a result of calling to UIKit from a
secondary thread. Crashing now...
Run Code Online (Sandbox Code Playgroud)
那么如何在主线程上添加子视图呢?
这个后台线程代码安全吗?
let viewController = MyViewController(nibName: nil, bundle: nil)
viewController.title = "My Title"
viewController.myProperty = true
dispatch_async(dispatch_get_main_queue(), {
self.navigationController?.pushViewController(viewController, animated: true)
})
Run Code Online (Sandbox Code Playgroud) 我想在线程中加载一些视图以避免UI冻结等待加载结束.
我不习惯穿线,所以我做了一个快速测试.我的代码只是尝试在线程中创建视图,并在主线程的当前viewcontroller视图中添加此视图.
我的UIView正在工作,但对于我的UILabel,我必须等待20-60秒才能将它放在屏幕上.
我使用UIButton进行测试,在这种情况下,按钮会立即显示,但按钮内的标签显示的延迟与我的UILabel相同.
让它按我想要的方式工作的唯一方法是添加一个[lbl setNeedsDisplay]; 在主线程中强制UILabel立即显示.为什么?没有这条线可以完成这项工作吗?
dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL);
dispatch_async(queue, ^{
// NEW THREAD
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 48)];
lbl.text = @"FOO";
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
view.backgroundColor = [UIColor redColor];
// MAIN THREAD
dispatch_async(dispatch_get_main_queue(), ^{
[self.view addSubview:lbl];
[lbl setNeedsDisplay]; // Needeed to see the UILabel. WHY???
[self.view addSubview:view];
});
});
dispatch_release(queue);
Run Code Online (Sandbox Code Playgroud) 我读了一些UI接口只在MainThread上更新的信息.
我需要异步更新一些UIButtons,所以我使用performSelectorInBackground它,它在模拟器和设备(iPad4)上工作正常.
[self performSelectorInBackground:@selector(toggleToUpperWhenSingleShift) withObject:nil];
- (void)toggleToUpperWhenSingleShift{
shiftStateIndicator = 1;
for (UIView *aPad in self.subviews) {
if ( [aPad isKindOfClass:[UIButton class]] ) {
UIButton *aButPad = (UIButton *)aPad;
NSMutableString *currentTitle = [NSMutableString stringWithString:[aButPad titleForState:UIControlStateNormal]];
NSString *firstChar = [currentTitle substringToIndex:1];
[currentTitle replaceCharactersInRange:NSMakeRange(0, 1) withString:[firstChar uppercaseString]];
[aButPad setTitle:currentTitle forState:UIControlStateNormal];
[aButPad setTitle:currentTitle forState:UIControlStateHighlighted];
currentTitle = [NSMutableString stringWithString:[aButPad titleForState:UIControlStateSelected]];
firstChar = [currentTitle substringToIndex:1];
[currentTitle replaceCharactersInRange:NSMakeRange(0, 1) withString:[firstChar uppercaseString]];
[aButPad setTitle:currentTitle forState:UIControlStateSelected];
}
}
}
Run Code Online (Sandbox Code Playgroud)
我担心如果我保留我的代码会发生一些不需要的功能.谁能解释一下我的细节performSelectorInBackground?
为什么不用它来更新UI以及为什么我的应用程序没问题?无论如何调试问题都会欣赏!
HomeViewController.h
#import "DataParser.h"
@interface HomeViewController : UIViewController <DataParserDelegate>
{
UILabel *theLabel;
}
Run Code Online (Sandbox Code Playgroud)
HomeViewController.m
#import "HomeViewController.h"
@implementation HomeViewController
-(void)viewDidLoad
{
theLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 100, 30)];
theLabel.text = @"Bob";
theLabel.font = [UIFont italicSystemFontOfSize:20.0];
theLabel.textColor = [UIColor whiteColor];
theLabel.backgroundColor = [UIColor blueColor];
[self.view addSubview:theLabel];
UIButton *theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[theButton addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
[theButton setTitle:@"Big Button" forState:UIControlStateNormal];
theButton.frame = CGRectMake(100,100,200,50);
[self.view addSubview:theButton];
}
-(void)clicked:(id)sender
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0),
^{
DataParser *data = [[DataParser alloc] init];
data.delegate = self;
[data loadSomething];
dispatch_async(dispatch_get_main_queue(),
^{ …Run Code Online (Sandbox Code Playgroud)