我正在开发一个应用程序,我需要在后台线程中构建一些图像。在这个过程中的某个时刻,我需要从UITextView获取文本。如果我调用UITextview.text,我会收到警告,我的辅助线程不应该纠缠UIKit
这一切都很好,但我需要文本,我无法找出从主线程中获取所述文本的合理方法。
我的问题是:有没有人想出一个很好的方法来从后台线程获取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];
获取字体并没有给出获取文本的相同警告,但我认为最好保持一致。
答案 0 :(得分:15)
我尽可能避免使用任何类型的元编程。它完全破坏了编译器重复检查代码的能力,对于启动,它往往是不可读的。
__block NSString* foo;
dispatch_sync(dispatch_get_main_queue(), ^{
foo = [textField ...];
});
请注意,如果不使用ARC,您可能希望copy
或retain
块中的字符串,然后是本地线程中的release
或autorelease
。< / p>
答案 1 :(得分: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
});
以下是有关该主题的相关帖子: