2011-04-18 56 views
2

我對這兩個的使用略有困惑。代表和performSelectorOnMainThread

我有一個後臺線程,負責下載數據並將其應用到iOS設備中的核心數據數據庫。

後臺線程中的代碼調用共享實例類ProgressController來更新UI(我知道它在主線程中運行)的進度。然後ProgressController擁有一個由View Controller分配的委託。

它的所有工作都很好,除了一旦後臺線程啓動後UI不更新。我知道委託人被調用,因爲我有NSLogs正在通過正在傳遞的文本射擊。

現在我讀了,我應該使用performSelectorOnMainThread,但這似乎是多餘的,因爲委託正在發射。

我應該使用performSelectorOnMainThread,而不是完全不使用委託。

我錯過了什麼嗎?

如果有人能解釋,我會很感激。

謝謝,

Chris。

在後臺線程

progressController = [ProgressController sharedInstance]; 
[progressController open]; 

....

[progressController updateProgress:NSLocalizedString(@"Update text here", @"Update text here")]; 

在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 

在ProgressControll er.m #進口「ProgressController.h」

@implementation ProgressController 

@synthesize progressOnDisplay; 
@synthesize delegate; 

static ProgressController *sharedInstance; 

+ (ProgressController *)sharedInstance { 
    @synchronized(self) { 
     if (!sharedInstance) 
     [[ProgressController alloc] init];    
    } 
    return sharedInstance; 
} 

+(id)alloc { 
    @synchronized(self) { 
     NSAssert(sharedInstance == nil, NSLocalizedString(@"Attempted to allocate a second instance of a singleton ProgressController.", @"Attempted to allocate a second instance of a singleton ProgressController.")); 
     sharedInstance = [super alloc]; 
    } 
    return sharedInstance; 
} 
-(id) init { 
    if (self = [super init]) { 
     [self open]; 
    } 
    return self; 
} 

// Ask delegate to show new Progress Label 
-(void) open { 
    progressOnDisplay = TRUE; 
    currentProgress = @""; 
    [self.delegate showProgress]; 
} 

// Ask delegate to update and display Progress text 
-(void) updateProgress:(NSString *)text { 
    currentProgress = text; 
    [self.delegate displayProgress:currentProgress]; 

} 

// Ask delegate display existing Progress text if any 
-(void) reDisplayProgress { 
    if (currentProgress != @"") { 
     [self.delegate displayProgress:currentProgress]; 
     [self.delegate showProgress]; 
    } 
} 

// Ask delegate to clear and hide Progress Label 
-(void) close { 
    progressOnDisplay = FALSE; 
    currentProgress = @""; 
    [self.delegate hideProgress]; 
} 


@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; 

} 
+0

請在後臺線程中顯示調用ProgressController方法的代碼。 – Eiko 2011-04-18 11:33:39

回答

1

您插入的代碼顯示您直接從後臺線程調用委託方法。要在主線程上執行GUI工作(您應該這樣做),您需要直接調用委託方法或委託方法本身時使用performSelectorOnMainThread:。如果您想在這些更新期間停止後臺線程,則可以使用waitUntilDone:YES的變體。

+0

謝謝Eiko。因此,例如在委託(ProgressController.m)內,應該 [self.delegate displayProgress:currentProgress];變成 [self.delegate:currentProgress] performSelectorOnMainThread:@selector(displayProgress :) withObject:currentProgress waitUntilDone:NO]]; ? – Chris 2011-04-18 14:04:37

+0

它應該變成類似[self.delegate performSelectorOnMainThread:@selector(displayProgress :) withObject:currentProgress]; (未經測試,只是在這裏輸入) – Eiko 2011-04-18 15:00:25

+0

你是Eiko明星。謝謝!我在委託中需要的行格式爲[self.delegate performSelectorOnMainThread:@selector(displayProgress :) withObject:currentProgress waitUntilDone:NO];正如你所說,這意味着委託從主線程被調用並且UI現在更新。現在都在工作。 – Chris 2011-04-18 16:59:58

-1

你應該異步使用NSURLConnection的類,那麼你可以使用它的委託方法來更新下載數據您的用戶界面

請參閱此代碼 -

// 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.. 

} 
+1

真的很討厭downvote沒有評論... – Saurabh 2011-04-18 12:20:33

+0

t'wasnt我Saurabh - 謝謝你的回答 – Chris 2011-04-18 15:16:38

1

委託方法對自己有一個線程沒有特定的關係。它只是一個對象發送消息給另一個對象。如果該委託方法碰巧在後臺線程上調用,則任何UI交互都必須在主線程上完成。

欲瞭解更多信息,請參閱文檔:http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/CommunicateWithObjects.html%23//apple_ref/doc/uid/TP40002974-CH7-SW18

一些對象相關聯的委託調用特定線程。例如,NSURLConnection的+ connectionWithRequest:delegate:,其文檔狀態爲:

到委託的消息將在調用此方法的線程上發送。爲了使連接正常工作,調用線程的運行循環必須以默認運行循環模式運行。

因此,簡而言之,是的,它很有可能使用這兩種委託方法和performSelectorOnMainThread來更新您的用戶界面。這樣做沒有任何問題。

相關問題