如何在Objective C中使用ARC声明一个指针成员变量?

时间:2012-05-09 03:20:09

标签: objective-c ios memory pointers automatic-ref-counting

我有一个类RemoteImageLoader,它有一个方法loadImage:

- (void) loadImage: (NSString*) url setTarget:(NSData **)target;

我在这里使用了NSData **,因为我需要间接返回NSData *,就像一些典型的方法一样:

- (BOOL)save:(NSError**)

因为该方法实际上会调用另一个异步方法,所以我必须将目标保存为成员变量,以便以后可以访问它。但是当我定义NSData **成员变量时:

@interface RemoteImageLoader : NSObject    
@property NSData** target;
@end

编译器抱怨“指向非const类型的'NSData *'没有明确的所有权”。我在google上做了一些搜索,但没有找到答案。任何人都可以帮我这个吗?非常感谢

我试图将声明替换为

@interface RemoteImageLoader : NSObject    
@property NSData * __autoreleasing * target;
@end

但问题仍然存在

4 个答案:

答案 0 :(得分:1)

我无法确定您在没有看到代码的情况下尝试做什么,但为什么要尝试创建指向NSData对象的指针(指向NSData的指针)。因为您正在创建指向指针的指针,这可能是您收到错误的原因。尝试删除其中一个指针,看看会发生什么。

答案 1 :(得分:1)

ARC Transition Notes建议你使用__autoreleasing声明你的NSData和NSError对象的间接指针,如(NSData * __autoreleasing *)target;

__ autoreleasing被称为生命周期限定符,它告诉编译器返回该对象的自动释放实例。

因此,需要重写方法签名。

- (void) loadImage: (NSString*) url setTarget:(NSData* __autoreleasing *)target;

警告,__自动释放的对象非常短暂。将您的NSData **声明为__strong,以覆盖默认的__autoreleasing,延长使用寿命。

答案 2 :(得分:1)

我认为你的方法签名会带来麻烦。一旦调用方法返回,调用者很可能会认为指向指针已填充。类似地,它们很可能传递堆栈变量的地址,该变量长时间无效。最后,您的方法无法让调用者知道指向指针何时填充了值。

从调用者处获取完成块可能会更好。完成块将接收NSData指针作为参数。类似的东西:

- (void) loadImage: (NSString*) url completionHandler:(void (^)(NSData* data))block;

这也反映了我认为你正在使用的底层框架API,这总是有助于减少“阻抗不匹配”。

至于您从编译器遇到的特定狭窄问题,我怀疑问题是编译器在分配给*target时无法知道它是否应该发出保留和释放。它希望您明确声明指向指针的所有权特征。我现在无法检查,但我想将其声明为__strong NSData** target会起作用。也就是说,它对target是否拥有它所指向的内容并不感兴趣,因为一个人不能拥有一个指针。它感兴趣的是NSData*指向target点的指针是否拥有它所指向的NSData对象。

答案 3 :(得分:0)

通常,当您在ARC之外执行此类操作时,您会执行以下操作:

NSData* returnedParm;
[someObj doSomething:&returnedParm];
打电话的一方是

。我没有看到你的上述returnedParm的等价物。 (我从未尝试使用ARC,但我认为基础知识必须类似。)

将属性声明为NSData**,声明指向非对象的指针,并且不会保留该指针(因为没有要保留的对象)。

我的猜测是你应该将你的功能原型化为:

-(void)doSomething:(NSData* __autoreleasing*)theReturnParm

并使用*theReturnParm = something;在该函数内分配给它。

然后在调用方面,您将returnedParm作为自动释放的值(因此,如果您想保留它,则应该相对快速地将其指定为strong指针)。