Iphone 为什么延迟线程响应可以修复视图损坏?
我的非常简单的iPhone应用程序10次中有6次在启动时显示损坏或随机崩溃。但它在模拟器中表现良好。显示损坏看起来像是字体颜色错误、字体文本不合适、背景颜色错误等 我在附近找到了一份奇怪的工作。。当我的线程在调用“完成”通知之前延迟2秒时,一切都很顺利。线程读取网页,“完成”通知加载带有字符串的PickerView。那么是什么原因呢?我能否从viewDidLoad安全地启动线程化任务Iphone 为什么延迟线程响应可以修复视图损坏?,iphone,cocoa-touch,multithreading,viewdidload,Iphone,Cocoa Touch,Multithreading,Viewdidload,我的非常简单的iPhone应用程序10次中有6次在启动时显示损坏或随机崩溃。但它在模拟器中表现良好。显示损坏看起来像是字体颜色错误、字体文本不合适、背景颜色错误等 我在附近找到了一份奇怪的工作。。当我的线程在调用“完成”通知之前延迟2秒时,一切都很顺利。线程读取网页,“完成”通知加载带有字符串的PickerView。那么是什么原因呢?我能否从viewDidLoad安全地启动线程化任务 - (void) loadWebPage:(NSString *)urlAddition { NSA
- (void) loadWebPage:(NSString *)urlAddition {
NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init];
NSString *pageSource;
NSError *err;
NSString *urlString = [NSString stringWithFormat:@"http://server/%@",
urlAddition];
pageSource = [NSString stringWithContentsOfURL:[NSURL URLWithString: urlString]
encoding:NSUTF8StringEncoding
error:&err];
[NSThread sleepForTimeInterval:2.0]; // THIS STOPS THE DISPLAY CORRUPTION
[[NSNotificationCenter defaultCenter] postNotificationName:@"webDoneNotification"
object:nil];
[subPool drain];
}
- (void) webDoneNotification: (NSNotification *)pNotification {
[mediaArray release];
mediaArray = [[NSArray arrayWithObjects:
[NSString stringWithString:@"new pickerview text"],
nil] retain];
[mediaPickerView reloadAllComponents];
[mediaPickerView selectRow:0
inComponent:0
animated:NO];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
mediaArray = [[NSArray arrayWithObjects:
[NSString stringWithString:@"init pickerview text"],
nil] retain];
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
myWebThread = [[WebThread alloc] initWithDelegate:self];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(webDoneNotification:)
name:@"webDoneNotification"
object:nil];
[myWebThread performSelectorInBackground:@selector(loadWebPage:) withObject:@""];
}
谢谢
更新:即使延迟0.1秒也足以完全修复问题。您正在从后台线程更新视图。这就是造成你问题的原因;UIKit视图不是线程安全的。当您需要更改视图时,请在主线程中执行此操作。您正在从后台线程更新视图。这就是造成你问题的原因;UIKit视图不是线程安全的。当您需要更改视图时,请在主线程中执行。我无法帮助您解决核心问题,但我相信您使用的
stringWithString
是不正确的。如果要使用“%@”作为格式说明符,则应使用stringWithFormat
。啊,是的。当试图简化此问题的代码时,这是一个复制/粘贴错误。我编辑了这篇文章。谢谢。我无法帮助您解决核心问题,但我相信您使用的stringWithString
是不正确的。如果要使用“%@”作为格式说明符,则应使用stringWithFormat
。啊,是的。当试图简化此问题的代码时,这是一个复制/粘贴错误。我编辑了这篇文章。谢谢。不要从后台线程发布通知,而是使用对象为nil waitUntilDone:NO的[self-performSelectorOnMainThread:@selector(webDone)]代码>这将安排在下一次通过主线程的运行循环时调用选择器。这非常有效!非常感谢。这只虫子已经缠着我好一阵子了。我需要保留通知,因为我需要在线程完成执行(并自动删除我的数据)之前将一些数据从web线程类复制到MainViewController。但是,在通知之后添加performSelectorOnMainThread调用对于更新UI非常有用。不要从后台线程发布通知,而是执行[self-performSelectorOnMainThread:@selector(webDone)with Object:nil waitUntilDone:NO]代码>这将安排在下一次通过主线程的运行循环时调用选择器。这非常有效!非常感谢。这只虫子已经缠着我好一阵子了。我需要保留通知,因为我需要在线程完成执行(并自动删除我的数据)之前将一些数据从web线程类复制到MainViewController。但是在通知之后添加performSelectorOnMainThread调用对于更新UI非常有用。