Objective c 如何允许NSMutableDictionary接受';无';价值观
我有以下声明:Objective c 如何允许NSMutableDictionary接受';无';价值观,objective-c,Objective C,我有以下声明: [custData setObject: [rs stringForColumnIndex:2] forKey: @"email"]; 其中,从SQLite3 d/b获取的[rs stringForColumnIndex:2]的值为nil。应用程序崩溃,出现以下错误: NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: email)' 有没有办法防止这种情况?(如NSMutableDic
[custData setObject: [rs stringForColumnIndex:2] forKey: @"email"];
其中,从SQLite3 d/b获取的[rs stringForColumnIndex:2]
的值为nil
。应用程序崩溃,出现以下错误:
NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: email)'
有没有办法防止这种情况?(如NSMutableDictionary
?)的设置)
更新:这是我最后做的:
[custData setObject: ([rs stringForColumnIndex:2] != nil? [rs stringForColumnIndex:2]:@"") forKey: @"email"];
有一个名为非
nil
的对象,该对象专门用于在不接受“普通”nil
的情况下表示nil
s。如果将nil
s替换为[NSNull]
对象,NSDictionary
将接受它们。不过,您需要在退出时检查NSNull
请注意,只有当您必须区分未设置的值和设置为
nil
的值时,这才很重要。如果您的代码可以将缺少的值解释为nil
,则根本不需要使用NSNull
。使用纯NSMutableDictionary是不可能的,在大多数情况下,您希望将nil值转换为[NSNull null]
,或者从字典中省略它们。不过,有时(很少)允许nil值是很方便的,在这种情况下,您可以将CFMutableDictionary与自定义回调一起使用
如果您这样做,我建议您对所有访问使用CoreFoundation API,例如CFDictionarySetValue
和CFDictionaryGetValue
但是,如果您知道自己在做什么,您可以使用免费桥接并将该CFMutableDictionary转换为NSMutableDictionary或NSDictionary。如果您有一组接受NSDictionary的帮助程序,并且希望在修改后的支持nil的字典上使用它们,那么这可能很有用。(当然,请确保助手不会对零值感到惊讶。)
如果您进行桥接,请注意:
1) NSMutableDictionary setter在桥接之前引发关于nil值的错误,因此您需要使用CFDictionarySetValue来设置可能为nil的值
2) 从技术上讲,我们在这里违反了NSMutableDictionary的合同,事情可能会破裂(例如,在未来的操作系统更新中)
3) 很多代码在字典中发现nil值时会非常惊讶;您应该只将桥接的FrankenDictionary传递给您控制的代码
有关桥接CFDictionary与NSDictionary行为不同的原因的解释,请参阅
例如:
#import <Foundation/Foundation.h>
const void *NullSafeRetain(CFAllocatorRef allocator, const void *value) {
return value ? CFRetain(value) : NULL;
}
void NullSafeRelease(CFAllocatorRef allocator, const void *value) {
if (value)
CFRelease(value);
}
const CFDictionaryValueCallBacks kDictionaryValueCallBacksAllowingNULL = {
.version = 0,
.retain = NullSafeRetain,
.release = NullSafeRelease,
.copyDescription = CFCopyDescription,
.equal = CFEqual,
};
int main(int argc, const char * argv[])
{
@autoreleasepool {
CFMutableDictionaryRef cfdictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kDictionaryValueCallBacksAllowingNULL);
CFDictionarySetValue(cfdictionary, @"foo", @"bar");
CFDictionarySetValue(cfdictionary, @"boz", nil);
NSMutableDictionary *dictionary = CFBridgingRelease(cfdictionary);
NSLog(@"dictionary[foo] = %@", dictionary[@"foo"]);
NSLog(@"dictionary[foo] = %@", dictionary[[@"fo" stringByAppendingString:@"o"]]);
NSLog(@"dictionary[boz] = %@", dictionary[@"boz"]);
NSLog(@"dictionary = %@", dictionary);
NSLog(@"(dictionary isEqualTo: dictionary) = %d", [dictionary isEqualToDictionary:dictionary]);
}
return 0;
}
我需要将
NSDictionary
值设置为NSUserDefaults
中可能设置或可能尚未设置的值
我所做的是在stringwithFormat
调用中包装这些值。尚未设置这两个值,因此开始时为null。当我在没有stringwithFormat
调用的情况下运行时,应用程序崩溃。所以我这样做了,在我的情况下工作
-(NSDictionary*)userDetailsDict{
NSDictionary* userDetails = @{
@"userLine":[NSString stringWithFormat:@"%@",[[NSUserDefaults standardUserDefaults]stringForKey:kSelectedLine] ],
@"userDepot":[NSString stringWithFormat:@"%@",[[NSUserDefaults standardUserDefaults]stringForKey:@"kSelected Duty Book"]]
};
return userDetails;
}
我正在NSMutableDictionary中设置值,以便将数据数组传递给方法(Objective-c)。因此,该方法可以处理nil,但字典显然不能。所以我不能设置为允许“零”键,是吗?可能必须使用条件运算符?@spokane dude不,不幸的是,没有设置允许您在cocoa集合中存储
nil
。如果您使用条件运算符,那么有一个扩展可以让您稍微缩短代码(请参阅)。这就是我最后所做的(请参阅上面更新的问题),它是有效的(至少可以防止应用程序崩溃;我会在方法一侧检查是否有空键。感谢您抽出时间。@斯波坎·杜德您还应该看看另一个答案,它实际上回答了您的问题。这对我来说是一个很好的解决方案。@“”是在没有有效值时维护键的占位符的好方法,否则以后访问键的值时可能会遇到同样的问题。作为快捷方式:custData[@“email”]=[rs stringForColumnIndex:2]?:@“”;CFEqual将使用NULL参数崩溃;如果外部代码在调用该函数之前检查指针相等性,则您的示例可能会起作用,但是如果您要创建上述字典的副本,但将boz键设置为有效值,然后比较这两个字典,我相信它将崩溃而不是返回false。您需要一个NULL安全包装器我认为,对于CFEqual分配给ValueCallBacks属性,我认为这只是将nil
值转换为空字符串。您还可以执行value?:@“
(这是value?value:@”的缩写)。
-(NSDictionary*)userDetailsDict{
NSDictionary* userDetails = @{
@"userLine":[NSString stringWithFormat:@"%@",[[NSUserDefaults standardUserDefaults]stringForKey:kSelectedLine] ],
@"userDepot":[NSString stringWithFormat:@"%@",[[NSUserDefaults standardUserDefaults]stringForKey:@"kSelected Duty Book"]]
};
return userDetails;
}