2

メインスレッドでアニメーションを実行したいのですが(UIKitオブジェクトはスレッドセーフではないため)、別のスレッドで準備します。私は持っています(baAnimation-CABasicAnimationは以前に割り当てられ、初期化されています):

SEL animationSelector = @selector(addAnimation:forKey:);
NSString *keyString = @"someViewAnimation";

NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[workView.layer methodSignatureForSelector:animationSelector]];
[inv setTarget:workView.layer];
[inv setSelector:animationSelector];
[inv setArgument:baAnimation atIndex:2];
[inv setArgument:keyString atIndex:3];
[inv performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO];

私は得る:

***+ [NSCFStringの長さ]:認識されないセレクターがクラス0x1fb36a0に送信されました

呼び出し:

>     #0 0x020984e6 in objc_exception_throw
>     #1 0x01f7e8fb in +[NSObject doesNotRecognizeSelector:]
>     #2 0x01f15676 in ___forwarding___
>     #3 0x01ef16c2 in __forwarding_prep_0___
>     #4 0x01bb3c21 in -[CALayer addAnimation:forKey:]
>     #5 0x01ef172d in __invoking___
>     #6 0x01ef1618 in -[NSInvocation invoke]

しかし、[workView.layer addAnimation:baAnimation forKey:@"someViewAnimation"];正常に動作します。私は何が間違っているのですか?

4

3 に答える 3

6

[inv holdArguments](Chris Suterが述べたように)に加えて、引数を基になるメモリへのポインタとして渡す必要もあります。APIの引用:

"引数値がオブジェクトの場合、オブジェクトのコピー元の変数(またはメモリ)へのポインタを渡します。

NSArray *anArray;  
[invocation setArgument:&anArray atIndex:3];  

「」

于 2010-09-16T19:21:22.200 に答える
4

NSInvocationに1つ以上の引数がある場合は、メインスレッドでセレクターを呼び出す新しいカテゴリを作成することをお勧めします。これが私がこれを解決した方法です:

NSInvocation+MainThread.hの

#import <Foundation/Foundation.h>

@interface NSInvocation (MainThread)
- (void)invokeOnMainThreadWithTarget:(id)target;
@end

NSInvocation + MainThread.m

#import "NSInvocation+MainThread.h"

@implementation NSInvocation (MainThread)

- (void)invokeOnMainThreadWithTarget:(id)target {
    [self performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:target waitUntilDone:YES];
}

@end
于 2011-12-08T16:20:34.303 に答える
2

[inv retainArguments]waitUntilDoneパラメーターを追加するかYESに変更する必要がありますが、それを行う前に、あなたが行ったことはかなり読めないことを言っておきます。

私がすることは、必要な状態をインスタンス変数に格納し、準備ができたら、次のことを実行することです。

[self performSelectorOnMainThread:@selector (startAnimation) withObject:nil waitUntilDone:NO];

また、スレッドでのCABasicAnimationの割り当てと初期化は不要であり(メインスレッドで行うのに目立った時間はかかりません)、それでも潜在的に危険です。プロセッサを集中的に使用する作業は別のスレッドで行いますが、それ以外は行いません。

于 2010-06-03T07:38:50.833 に答える