3

2つの変数を渡したい:

UIImage * img
int i

(void *)のみを取る別のメソッドに

imgとiの両方を含むC構造体を作成してみました

struct MyStruct {
    UIImage *img;
    int i;
}

しかし、xcodeは「ARCは構造体または共用体のObjective-Cオブジェクトを禁止している」というエラーを表示します

次に試したのは、imgとiを含むObjective-cクラスMyStruct2を作成し、そのインスタンスを割り当てて、メソッドに渡す前に(__bridge void *)として型キャストすることです。私のユースケースにはほとんど関与していないようです。より良い方法があるはずだと思われます。

これを達成するための最も簡単な方法は何ですか?

ありがとうございました。

コメントに基づいて編集:UIView APIで必要とされるため、void*を使用する必要があります。UIVIewAPIで言及されているようにセレクターを作成しました

+ (void)setAnimationDidStopSelector:(SEL)selector

setAnimationDidStopSelectorのドキュメント(http://developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html )を参照してください。それは言う...セレクターは次の形式でなければなりません:

    - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context 

imgとiの両方を(void *)context引数に渡したい。

4

2 に答える 2

4

あなたはこれを行うことができます:

struct MyStruct {
    __unsafe_unretained UIImage *img;
    int i;
}

ただし、これを行う場合、imgフィールドは自動的にそのを保持および解放しないことに注意する必要がありますUIImage

「(void *)のみを使用する方法」についての詳細を投稿すると、より良いアドバイスを提供できる可能性があります。

編集

void *質問を更新して、animationDidStop:finished:context:セレクターにを渡す必要があると言いました。ARCを使用しているので、iOS 4.0以降をターゲットにしていることはわかっているので、 animateWithDuration:animations:completion:代わりに使用する必要があります。次に、を渡す必要はありませんvoid *

UIImage *img = someImage();
int i = someInt();

[UIView animateWithDuration:2.0 animations:^{
    // set the animatable properties here
} completion:^(BOOL finished) {
    doSomethingWithImageAndInteger(img, i);
}];
于 2012-06-23T20:35:43.883 に答える
3

ARCは、単純な古いC構造体のObjCオブジェクトを追跡できません。スタック上、またはObjCおよびC ++オブジェクト内のポインターを追跡します。これらのオブジェクトは、明示的または暗黙的なメソッドを使用してコピーされますが、とにかくコンパイラーの制御下にあります。

だから...クラスを使用します。気に入った場合はC++、または:

@interface MyNotSoPlainStruct

@property ( nonatomic, strong ) UImage* image;
@property ( nonatomic ) int i;

@end

@implementation MyNotSoPlainStruct
@end

MyNotSoPlainStruct* foo = [MyNotSoPlainStruct new];
foo.image = …
foo.i = …

そこに行きます。

このソリューションにはより多くの行が必要ですが、それは事実ですが、画像のライフサイクルなど、処理方法をより適切に制御できます。強力なポインターを使用することも、ニーズに適している場合は弱いポインターを使用することもできます。

もちろん、辞書または配列のいずれかを使用することもできます。リテラルはそれを特に簡単にします:

NSDictionary* arguments = @{ @"image" : <image>, @"i" : @( <int> ) };
arguments[@"i"].intValue returns the int you need.

とても簡単。

編集

転送部分を忘れました、おっと:)。それで:

次の注釈を使用する必要があります。

void* argumentsPointer = (__bridge_retained void*) arguments;

引数は保持され、その参照はARCによって管理されなくなります。

ポインタを受け取ったら、それを変換する必要があります。

NSDictionary* arguments = (__bridge_transfer NSDictionary*) argumentsPointer;

__bridgeのみを使用すると、最後の既知の参照が消えた場合にダングリングポインタが発生する可能性があります。そのvoid*で辞書を保持したい場合は、最初に__bridge_retainedを使用し、次に__bridge_transferを使用する必要があります。

于 2012-06-23T20:45:49.180 に答える