2013-01-13 69 views
4

我正在研究一個應用程序,我需要在後臺線程中構建一些圖像。在這個過程中的某個時刻,我需要從UITextView中獲取文本。如果我打電話給UITextview.text,我得到了我的輔助線程不應該糾纏的警告UIKit從主線程中返回值objective-c

這一切都很好,但我需要的文本,我不能找出合理的方式來獲取說文字主線程。

我的問題是:有沒有人想出一個很好的方式來從後臺線程獲取UI元素的屬性,或者,首先避免這樣做的好方法?

我一起扔了這件事情,它是卓有成效的,但它並不感到很正確:

@interface SelectorMap : NSObject 

@property (nonatomic, strong) NSArray *selectors; 
@property (nonatomic, strong) NSArray *results; 

@end 


@interface NSObject (Extensions) 
- (NSArray *)getValuesFromMainThreadWithSelectors:(SEL)selector, ...; 
- (void)performSelectorMap:(SelectorMap *)map; 
@end 

和實現:

#import "NSObject+Extensions.h" 

@implementation SelectorMap 
@synthesize selectors; 
@synthesize results; 
@end 

@implementation NSObject (Extensions) 

- (void)performSelectorMap:(SelectorMap *)map 
{ 
    NSMutableArray *results = [NSMutableArray arrayWithCapacity:map.selectors.count]; 

    for (NSString *selectorName in map.selectors) 
    { 
     SEL selector = NSSelectorFromString(selectorName); 
     id result = [self performSelector:selector withObject:nil]; 
     [results addObject:result]; 
    } 

    map.results = results.copy; 
} 

- (NSArray *)getValuesFromMainThreadWithSelectors:(SEL)selector, ... 
{ 
    NSMutableArray *selectorParms = [NSMutableArray new]; 

    va_list selectors; 
    va_start(selectors, selector); 

    for (SEL selectorName = selector; selectorName; selectorName = va_arg(selectors, SEL)) 
     [selectorParms addObject:NSStringFromSelector(selectorName)]; 

    va_end(selectors); 

    SelectorMap *map = [SelectorMap new]; 
    map.selectors = selectorParms.copy; 

    [self performSelectorOnMainThread:@selector(performSelectorMap:) withObject:map waitUntilDone:YES]; 

    return map.results; 
} 

@end 

我這樣稱呼它:

NSArray *textViewProperties = [textView getValuesFromMainThreadWithSelectors:@selector(text), @selector(font), nil]; 

獲取字體並沒有給出獲取文本的相同警告,但我認爲這是最好的 始終如一。

回答

14

我儘可能地避免了任何類型的元編程。它徹底破壞了編譯器仔細檢查代碼的能力,對於開始而言,它往往是不可讀的。

__block NSString* foo; 
dispatch_sync(dispatch_get_main_queue(), ^{ 
     foo = [textField ...]; 
    }); 

注意如果不使用ARC,你可能會想copyretain該塊中的字符串,然後releaseautorelease在您的本地線程。

+0

嚴重的是,這是更好的方式!我尋找了幾個小時試圖找出正確的方法來做到這一點。 –

+0

+1用於指出內存管理和關於元編程的觀點。 – bryanmac

+0

很久以前我才知道笑容比我聰明。隨着靜態分析儀的進步,它似乎也在更快地學習。 :) – bbum

2

您可以在主線程上使用performSelector,也可以使用GCD在主隊列上進行分派。

[self performSelectorOnMainThread:@selector(updateText:) withObject:nil waitUntilDone:YES]; 

GCD看起來像:

dispatch_queue_t main = dispatch_get_main_queue(); 

dispatch_sync(main, ^{ 
    // read and assign here 
}); 

下面是關於該主題的相關文章:

GCD, Threads, Program Flow and UI Updating