我一直在研究Apple低级文件部分Using a Directory Enumerator中的示例。
以下是代码段:
for (NSURL *url in enumerator) {
// Error-checking is omitted for clarity.
NSNumber *isDirectory = nil;
[url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:NULL];
if ([isDirectory boolValue]) {
NSString *localizedName = nil;
[url getResourceValue:&localizedName forKey:NSURLLocalizedNameKey error:NULL];
NSNumber *isPackage = nil;
[url getResourceValue:&isPackage forKey:NSURLIsPackageKey error:NULL];
if ([isPackage boolValue]) {
NSLog(@"Package at %@", localizedName);
}
else {
NSLog(@"Directory at %@", localizedName);
}
}
}
为什么localizedName
,isPackage
和isDirectory
在nil
方法的相关调用之前设置为getResourceValue
?这只是一个过分谨慎还是需要这个?
正如我为getResourceValue:forKey:error:
阅读the docs一样,这似乎是多余的:
如果值为,则返回值YES 成功填充;否则,没有。
如果是,讨论值设置为nil 请求的资源值不是 为URL定义。在这种情况下, 方法仍然返回YES。
我错过了什么吗?
答案 0 :(得分:5)
此代码不检查getResourceValue:forKey:error:
方法是否实际成功。相反,假设传递的变量在方法失败时设置为nil或保持不变。这可能不是一个有保证的假设;似乎没有记录失败时的行为。
如果它们未事先初始化,“保持不变”将通过使用未初始化的堆栈变量导致未定义的行为。
答案 1 :(得分:1)
最好永远不要将变量保留为未定义。此外,我认为如果你这样做,你会收到一个编译器警告,如果你只修复它们,那么更容易确保没有坏警告。
答案 2 :(得分:1)
如果未将对象变量设置为nil,则其值未定义。如果您随后在未设置其值的情况下访问该变量,则您的应用程序可能会出现异常或可能发生异常或崩溃。
如果首先将值设置为nil,则不会发生这种情况。将局部对象变量初始化为nil总是很好的做法。这不适用于实例变量,因为它们始终保证始终初始化为nil。
答案 3 :(得分:1)
在C NULL指针类型下输入文件。
以下是一个例子:
#import <Foundation/Foundation.h>
void test(void){
NSString *test1, *test2, *test3;
test1=nil;
// Note: NSString would USUALLY be aloc then init before use...
[test1 isEqual:@"static object string"];
[test2 isEqual:@"static string"];
[test3 isEqual:test1];
}
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
test();
[pool drain];
return 0;
}
现在在xcode中的test1=nil
上放置一个断点并运行。在我的机器上,我得到:
test1=(NSString *) 0x0 <nil>
test2=(NSString *) 0x0 <nil>
test3=(NSString *) 0x7fff84db7dd7 Invalid
如果您运行它,则会在尝试执行EXC_BAD_ACCESS
时获得[test3 isEqual:test1]
并终止。您可以使用test1的nil值和test2的(偶然?)nil值,但使用test3中的随机值:death。
现在将该行更改为test1=test2=test3=nil;
再次运行它。效果很好。
一个重要的概念:Objective-C中的You can validly send a message to nil。
正如在不使用时将C指针指向安全值可能是一种好的做法一样,nil
在Objective-C中是一个安全值,直到它被分配给其他东西。对于编写该示例的程序员来说,这可能是肌肉记忆。在特定情况下不必要,但比随机值更安全。
答案 4 :(得分:1)
如果检查了-getResourceValue的返回值,那将是多余的。因为它不在上面的代码中,所以nil是必要的。
id aLocalVar;
// 1
[ob maybeAssignAValueToPassedInPointer:&aLocalVar];
// 2
在上面的代码 // 1 aLocalVar指向内存中的随机位垃圾 - 可能是任何东西。
因为我们不知道 -maybeAssignAValueToPassedInPointer:是否分配了一个值我们不知道 // 2 如果aLocalVar仍然包含垃圾(可能是一个数字,或一个字符串,或其他什么,但垃圾不是更少)或有效值。如果我们尝试使用它,我们可能会崩溃,或者我们的值可能不正确。