5

バックグラウンドスレッドでいくつかの画像を作成する必要があるアプリケーションに取り組んでいます。プロセスのある時点で、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];

フォントを取得しても、テキストを取得する場合と同じ警告は表示されませんが、一貫性を保つことが最善であると考えました。

4

2 に答える 2

17

メタプログラミングはできるだけ避けています。これは、開始時にコードを再チェックするコンパイラーの機能を完全に損ない、読み取り不能になる傾向があります。

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

ARCを使用していない場合は、ブロック内の文字列、次にローカルスレッド内の文字列を使用することをcopyお勧めします。retainreleaseautorelease

于 2013-01-13T23:29:53.333 に答える
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、スレッド、プログラムフロー、UIの更新

于 2013-01-13T23:32:42.883 に答える