我有一个类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
但问题仍然存在
答案 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
指针)。