Iphone 委托并执行SelectorOnMainThread
我对这两个词的用法有点困惑 我有一个后台线程,负责下载数据并将其应用到iOS设备内的核心数据数据库 后台线程中的代码调用共享实例类ProgressController来更新UI上的进度(我知道它在主线程中运行)。ProgressController然后有一个委托,该委托由顶部的视图控制器分配 除了后台线程启动后UI不会更新之外,一切正常。我知道正在调用委托,因为我有NSLogs,其中包含正在传递的文本 现在我读到我应该使用performSelectorOnMainThread,但考虑到委托正在触发,这似乎是多余的 我应该改用performSelectorOnMainThread,而不使用委托吗 我错过什么了吗 如果有人能解释,我会非常感激 谢谢 克里斯 在后台线程中Iphone 委托并执行SelectorOnMainThread,iphone,multithreading,uiview,delegates,nsnotifications,Iphone,Multithreading,Uiview,Delegates,Nsnotifications,我对这两个词的用法有点困惑 我有一个后台线程,负责下载数据并将其应用到iOS设备内的核心数据数据库 后台线程中的代码调用共享实例类ProgressController来更新UI上的进度(我知道它在主线程中运行)。ProgressController然后有一个委托,该委托由顶部的视图控制器分配 除了后台线程启动后UI不会更新之外,一切正常。我知道正在调用委托,因为我有NSLogs,其中包含正在传递的文本 现在我读到我应该使用performSelectorOnMainThread,但考虑到委托正在触
progressController = [ProgressController sharedInstance];
[progressController open];
在ProgressController.h中
#import <Foundation/Foundation.h>
@protocol ProgressControllerDelegate
@required
- (void) displayProgress:(NSString *)text;
- (void) showProgress;
- (void) hideProgress;
@end
@interface ProgressController : NSObject {
NSString *currentProgress;
BOOL progressOnDisplay;
id delegate;
}
+ (ProgressController *)sharedInstance;
@property (nonatomic) BOOL progressOnDisplay;
@property (nonatomic, assign) id delegate;
-(void) open;
-(void) updateProgress:(NSString *)text;
-(void) reDisplayProgress;
-(void) close;
@end
视图控制器内部
- (void)viewDidLoad {
[super viewDidLoad];
progressController = [ProgressController sharedInstance];
progressController.delegate = self;
[progressController reDisplayProgress]; // In case progress has been updated prior to the view load
}
// Delegate method to show Progress Label
- (void) showProgress {
progressView.hidden = FALSE;
}
// Delegate method to display specific text in Progress label
- (void) displayProgress:(NSString *)text {
[progressLabel setText:text];
[progressView setNeedsDisplay];
DLog(@"Reporting - %s", [text UTF8String]); // I can see that this is firing successfully
}
// Delegate method to hide Progress Label
- (void) hideProgress {
progressView.hidden = TRUE;
}
您应该使用NSURLConnection类异步下载数据,然后可以使用其委托方法更新UI 请参阅本守则-
// create the URL
NSURL *postURL = [NSURL URLWithString:@"http://twitpic.com/api/uploadAndPost"];
// create the connection
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:postURL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
// change type to POST (default is GET)
[postRequest setHTTPMethod:@"POST"];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:postRequest delegate:self];
if( theConnection )
{
webData = [[NSMutableData data] retain];
}
委托方法-
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// update your UI here..
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"ERROR with theConenction");
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// your data downloaded completely.. do you code here..
}
委托方法本身与线程没有特定的关系。它只是一个对象向另一个对象发送消息。如果该委托方法恰好在后台线程上被调用,那么任何UI交互都必须在主线程上完成 有关更多信息,请参阅文档: 某些对象将委托调用与特定线程相关联。例如,NSURLConnection的
+connectionWithRequest:delegate:
,其文档说明:
发送给委托的消息将在调用此方法的线程上发送。要使连接正常工作,调用线程的运行循环必须在默认运行循环模式下运行
因此,简而言之,是的,可以同时使用委托方法和
performSelectorOnMainThread
来更新UI。这样做没有错。插入的代码显示您直接从后台线程调用委托方法。要在主线程上执行GUI工作(您应该这样做),您需要在调用委托的方法时直接使用performSelectorOnMainThread:
,或者在委托方法本身中使用。如果您想在这些更新过程中停止后台线程,您可以使用带有waitUntilDone:YES
的变体。请在后台线程中显示调用ProgressController方法的代码。谢谢Eiko。例如,在委托(ProgressController.m)中,应该[self.delegate displayProgress:currentProgress];成为[self.delegate:currentProgress]执行SelectorOnMainThread:@selector(displayProgress:)with object:currentProgress waitUntilDone:NO]?它应该类似于[self.delegate performselectornmainthread:@selector(displayProgress:)withObject:currentProgress];(未经测试,仅在此处键入)你是明星Eiko。非常感谢。我在委托中需要的行的格式为[self.delegate performSelectorOnMainThread:@selector(displayProgress:)withObject:currentProgress waitUntilDone:NO];正如您所说,这意味着从主线程调用委托,UI现在更新。现在都在工作。
// create the URL
NSURL *postURL = [NSURL URLWithString:@"http://twitpic.com/api/uploadAndPost"];
// create the connection
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:postURL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
// change type to POST (default is GET)
[postRequest setHTTPMethod:@"POST"];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:postRequest delegate:self];
if( theConnection )
{
webData = [[NSMutableData data] retain];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// update your UI here..
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"ERROR with theConenction");
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// your data downloaded completely.. do you code here..
}