将目标c对象和原始类型传递给void *

时间:2012-06-23 20:29:49

标签: objective-c ios

我想传递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 *)。似乎很少涉及我的用例。似乎应该有更好的方法。

实现这一目标的最简单方法是什么?

谢谢。

根据评论进行编辑:我必须使用void *,因为UIView API需要它。我创建了一个UIVIew API

提到的选择器
+ (void)setAnimationDidStopSelector:(SEL)selector

请参阅http://developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html的setAnimationDidStopSelector文档。它说...选择器应该是以下形式:

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

我想将img和i都传递给(void *)context参数。

2 个答案:

答案 0 :(得分:4)

你可以这样做:

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

但是,如果您这样做,则必须牢记img字段不会自动保留并释放其UIImage

如果您发布有关“仅采用a(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);
}];

答案 1 :(得分: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.

非常简单。

修改

忘记转移部分,oops :)。那么:

您必须使用以下注释:

void* argumentsPointer = (__bridge_retained void*) arguments;
保留

参数,并且该引用不再由ARC管理。

当您接收指针时,必须转换它:

NSDictionary* arguments = (__bridge_transfer NSDictionary*) argumentsPointer;

如果最后一个已知引用消失,则仅使用__bridge可能会导致悬空指针。如果您希望void *保留字典,则必须先使用__bridge_retained,然后使用__bridge_transfer。