传递NSError
的一般用法模式是使用指向指针的指针:
- (id)doSomethingWithObj:(NSObject *)obj error:(NSError *__autoreleasing *)error
{
NSLog(@"error parameter: %p", error);
id object = obj;
if (object != nil)
{
return object;
}
else
{
NSError *tmp = [NSError errorWithDomain:@"after" code:0 userInfo:@{@"after": @"boris"}];
*error = tmp;
return nil;
}
}
我知道,因为传递外部error
指针的地址会分配或替换原始error
,所以上述模式可行。
但我关于NSError
或更通用的Objective-C
个对象的问题是,如果我写这样的话,为什么会出错:
我没有使用NSError **
,而是尝试NSError *
,我想的是,因为现在参数error
是NSError *
的类型,所以{{ 1}}应该是指针(错误)指向的内容,然后*error
可以替换*error = [NSError errorWith...];
内容之外的来源。
但它没有像我想的那样工作,但却出现了上述错误。
令我困惑的是,为什么*error
不适用于*error = [NSError errorWith...];
的类型,但适用于NSError *
。
答案 0 :(得分:1)
当您将参数传递给方法时,它会被复制,然后在您的方法中处理该副本:
- (void)changeA:(NSInteger)aToChange {
aToChange = 7;
}
然后,当您使用该方法时,您将无法更改从该方法内部传递的值:
NSInteger a = 42;
[smb changeA:a];
// a is still 42
那是因为你在-changeA:
里面处理了一个参数副本,即你做了类似的事情(伪代码):
// inside changeA:
NSInteger aToChange = a; // (value is copied)
aToChange = 7; // this does not modify a, right?
你甚至可以获得aToChange
的地址并尝试用它做点什么:
// inside changeA:
NSInteger aToChange = a; // (value is copied)
NSInteger *pointerToCOPY = &aToChange; // get address of aToChange
NSInteger *pointerToA = &a; // get address of a
// here pointerToCOPY != pointerToA
所以,回到你的代码:
NSError *error = nil; // outer error, passed as a parameter
...
- (id)doSomethingWithObj:(NSObject *)obj error:(NSError *)error
{
// NSError *error(local copy) = error(passed argument);
error = tmp; // here error is the pointer to the local error copy
return nil;
}
与aToChange
之前一样,您无法从方法内部修改外部NSError error *
。这就是使用双指针的原因,你向你的指针发送指针,这样你仍然可以访问外部error
引用并可以设置它。
- (id)doSomethingWithObj:(NSObject *)obj error:(NSError **)error
{
// NSError **error(local copy) = error(passed argument);
*error = tmp; // Here *error is the pointer to the local error copy,
// When you dereference error you get NSError *, which you can set,
// that's your external error.
return nil;
}
请注意,不可能这样做:
NSError *error = nil;
NSError *otherError = [NSError error with];
*error = otherError;
error
是指向结构的指针,*error
是一个结构,一个具有单个isa
字段的结构(从id类型defenition的角度来看)。将指向错误(otherError
,即平台指针大小为int)的指针分配给结构是不合适的。
然后,最后一个问题仍然存在,为什么不能:
NSError *error = nil;
NSError *otherError = [NSError error with];
*error = *otherError; // why can't I assign to structs?
我不完全确定,但是,也许内存管理和ABI会出现在游戏中,这里它可以将一堆字节从一个对象复制到另一个对象,因为它们只是一个C结构。
如您所知,Objective-C是C的超集,可以在那里分配结构:Assign one struct to another in C。我认为,目标C的特性处理对象。一切都非常动态,您可以在运行时创建类并添加实例变量(Mike Ash on that topic),因此在编译时不知道结构中isa
字段之外的是什么,实际上id
只是指向具有单个isa
的结构的指针。仅仅复制单个isa
结构并说你已经完成并不是一个好主意,事情会崩溃。