Ios 第一次方法调用时已填充NSError对象
我在阅读G.Lee的《测试驱动的iOS开发》一书时,遇到了这个单元测试,我不理解。首先,如果你需要更多的代码,请马上告诉我Ios 第一次方法调用时已填充NSError对象,ios,objective-c,nserror,pointer-to-pointer,Ios,Objective C,Nserror,Pointer To Pointer,我在阅读G.Lee的《测试驱动的iOS开发》一书时,遇到了这个单元测试,我不理解。首先,如果你需要更多的代码,请马上告诉我 -(void)testDelegateNotifiedOfErrorWhenNewsBuilderFails { MockNewsBuilder *builder = [MockNewsBuilder new]; builder.arrayToReturn = nil; builder.errorToSet = underlyingError;
-(void)testDelegateNotifiedOfErrorWhenNewsBuilderFails
{
MockNewsBuilder *builder = [MockNewsBuilder new];
builder.arrayToReturn = nil;
builder.errorToSet = underlyingError;
newsManager.newsBuilder = builder;
[newsManager receivedNewsJSON:@"Fake Json"];
...
}
-(void)receivedNewsJSON:(NSString *)objectNotation
{
NSError *error = nil;
// As you see error is nil and I am passing in a nil error.
NSArray *news = [_newsBuilder newsFromJSON:objectNotation error:&error];
...
}
@implementation MockNewsBuilder
-(NSArray *)newsFromJSON:(NSString *)objectNotation error:(NSError **)error
{
// But once I arrive here, error is no longer nil.
// (NSError **) error = 0x00007fff5cb887f0 domain: @"Fake Json" - code: 0
...
}
错误是如何神奇地自动设置的
更新:
感谢大家的积极讨论和建议。答案解释了调用方是如何得到错误实例的,因为&,我很清楚这一点。我的问题仍然是,为什么被调用方端指向一个已填充的NSError实例,即使它必须是nil。我没有在newsFromJSON:error:
中设置错误实例,那么它是如何在那里填充的呢
我刚刚更改了[newsManager receivedNewsJSON:@“Fake Json1”]
和newsFromJSON:error:
中的错误实例立即反映出来
(NSError**)error=0x00007fff5b9b27f0域:@“伪Json1”-代码:0
。它非常令人困惑…这只是指针指向指针的概念。您正在将引用传递给reference error对象&error传递给方法-(NSArray*)newsFromJSON:(NSString*)objectNotation error:(NSError**)error代码>
这将更新您传递的内存指针处的错误对象
这就是指针对指针的概念
更新:
您的错误对象为零,是的,它是正确的。但是您没有将该错误对象传递给newsFromJSON
方法,而是传递错误对象的内存地址(&error
)。这是错误对象的内存地址。
这就是为什么在newsFromJSON
方法中得到非空值的原因
还有一件事,您可以使用operator(*
operator)的内容访问newsFromJSON
方法中的原始对象
比如,**错误=something代码>
这将更新您在调用方方法中声明的原始对象(NSError*error
)。
在C、CPP或Objective-C中,&是运算符的地址,*是运算符的内容
&obj->给出obj的内存地址
*obj->给出obj中内存地址的内容。error
是类型为NSError*
的变量,即“指向NSError的指针”(在objective-C中,所有对象都作为引用处理,而不是例如C++)
这意味着error
是一个(本地)变量,它存储实际NSError
对象的地址,最初为nil
您调用的方法将创建一个(自动删除的)NSError
实例。为了获得对该实例的引用,您需要向该方法传递指针的地址,或&error
,这反过来又是“指向NSError
的指针”(注意两级间接寻址)
这样做是因为C中函数的参数和Objective-C中方法的参数都是按值传递的:如果您只传递了error
,那么存储在那里的值(nil
)将被单独复制,并且无论被调用的方法做了什么,您(调用方)的变量error
的内容都无法修改。要实现这一点,您需要传递错误的地址,或&error
这样,被调用的方法可以“更改”error
(保存在那里的地址)的内容,以便它指向新创建的NSError
实例
这有意义吗
附录:这是Cocoa中常见的一种模式:被调用的方法可能会失败,而不仅仅是使用返回值来表示成功/失败,并传递额外的“in/out”参数以在失败时检索详细的错误信息。失败时,该方法可以返回false
(NO
,0
,等等),但除此之外,还可以在NSError
实例中提供更详细的错误报告(例如失败原因)
编辑:正如@Droppy所说,考虑到所有涉及的代码都是您自己的(即,不是第一方或第三方框架),除非您明确地将其分配到某个地方,否则不可能将error
设置为除nil
之外的任何其他值。也许您应该在调试器中“观察”它,以查看它的设置时间/位置。由于消息似乎被设置为@“Fake JSON”
,因此您可以做的第一件事是在项目(所有文件)中搜索该字符串 **是指向指针的指针。
这意味着您需要向函数或方法传递指针地址。
Objective-C是C的严格超集。
这意味着在C中,函数和方法只能返回一个值。
有两种方法。
一种是将所有的返回封装在结构、NSDictionary或其他集合中。
这种方式称为输出参数
它正在传入一个指针地址。
C是一种复制语言。但指针是可移植的黑洞,可以让你在C中做一些疯狂的事情。
ObjuleC和C++给你同样的野性。
该错误由苹果的框架代码设置。
Cocoa模式通常是返回BOOL并传入NSError指针地址。
如果布尔为否,则检查N错误。
Apple framework将在您的N错误指针地址框中放置一些礼物
有时它们不使用BOOL,而是返回一个对象或nil
核心基础C框架工作非常相似,大量使用内外参数。 这回答了您的问题。除非这不是第一次调用
newsFromJSON
,或者事先调用了其他东西,否则没有理由填充n错误。在您显示的代码中,它应该是nil
@Droppy感谢您引导讨论:我已经更新了问题的更多细节。但这对我来说仍然是个谜