0

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

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

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

- (BOOL)save:(NSError**)

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

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

编译器抱怨“指向非常量类型'NSData *'的指针没有明确的所有权”。我在谷歌上做了一些搜索,但没有找到答案。谁能帮我解决这个问题?非常感谢

我试图将声明替换为

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

但问题依然存在

4

4 回答 4

1

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

于 2012-05-09T03:28:41.380 回答
1

ARC 过渡说明建议您在使用 __autoreleasing 的情况下声明指向 NSData 和 NSError 对象的间接指针,例如(NSData * __autoreleasing *)target;

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

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

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

请注意,__autoreleasing 对象的寿命极短。将您的 NSData** 声明为 __strong 以覆盖默认的 __autoreleasing 以获得更长的生命周期。

于 2012-05-09T03:30:11.590 回答
1

我认为您的方法签名会造成麻烦。调用者很可能会假设一旦您的方法返回,指向的指针就会被填充。同样,它们很可能会传递一个不会长期有效的堆栈变量的地址。最后,您的方法无法让调用者知道指向的指针何时被填充了值。

您最好从调用者那里获取完成块。完成块将接收一个 NSData 指针作为参数。就像是:

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

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

至于您从编译器遇到的具体狭窄问题,我怀疑问题是编译器不知道它是否应该在您分配到时发出保留和释放*target。它希望您显式声明指向指针的所有权特征。我目前无法检查,但我想将其声明为__strong NSData** target可行。也就是说,它对是否target拥有它所指向的东西不感兴趣,因为一个人不能拥有一个指针。NSData*它对指向哪个指针的指针是否target拥有NSData它指向的对象感兴趣。

于 2012-05-09T07:18:32.253 回答
0

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

NSData* returnedParm;
[someObj doSomething:&returnedParm];

在来电者一侧。我没有看到你的相当于我returnedParm上面的。(我从来没有在 ARC 上试过这个,但我认为基础必须是相似的。)

声明一个属性就像NSData**声明一个指向非对象的指针并且它不会被保留(因为没有要保留的对象)。

我的猜测是你应该将你的函数原型化为:

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

并在该函数内使用*theReturnParm = something;.

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

于 2012-05-09T20:22:25.450 回答