ios NSString 和 NSDictionary valueForKey - 无?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7664602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:44:34  来源:igfitidea点击:

NSString and NSDictionary valueForKey - nil?

iphoneobjective-cioscocoa-touch

提问by spentak

How can I put a default value into my string if getting data from an empty key/value in a dictionary.

如果从字典中的空键/值获取数据,如何将默认值放入我的字符串中。

so [myObject setMyString:[dictionary valueForKey:@"myKey"]];

所以 [myObject setMyString:[dictionary valueForKey:@"myKey"]];

So then if I did NSString *newString = myObject.myStringI would get an unrecognized selector error.

所以如果我这样做了,NSString *newString = myObject.myString我会得到一个unrecognized selector error.

So again, I simply need a way to insert a default string if the key value is empty;

同样,如果键值为空,我只需要一种方法来插入默认字符串;

回答by Mattias Wadman

If dictionaryis a NSDictionaryyou should probably use objectForKeyas valueForKeyis used for KVC. It works for NSDictionarybut may bite you if the key collide with some NSDictionaryKVC key, e.g. "@allKeys" or "@count".

如果dictionary是一个,NSDictionary您可能应该objectForKeyvalueForKey用于KVC一样使用。它适用,NSDictionary但如果密钥与某些NSDictionaryKVC 密钥(例如“@allKeys”或“@count”)冲突,则可能会咬你。

I think the shortest is probably to do:

我认为最短的可能是这样做:

[dictionary objectForkey:@"myKey"] ?: @"defaultValue"

There is one terrible way of abusing the existing dictionary methods to produce a get by key or return a default value if you don't want to use a condition for some reason...

如果您出于某种原因不想使用条件,则有一种滥用现有字典方法来生成按键获取或返回默认值的可怕方法......

[[dictionary objectsForKeys:[NSArray arrayWithObject:@"myKey"]
             notFoundMarker:@"defaultValue"]
 objectAtIndex:0]

You did not hear it from me :)

你没有从我这里听到:)

回答by Nekto

What about this?

那这个呢?

NSString *value = [dictionary valueForKey:@"myKey"];
if (!value) value = @"defaultValue";
[myObject setMyString:value];

回答by Paul Lynch

Use [NSNull null]for the general case, and handle it when that is returned.

使用[NSNull null]对于一般情况,并处理它返回的时候。

In your question, you wouldn't get "unrecognised selector"; newStringwould be set to nil(as opposed to [NSNull null], so I suspect you might have meant something else - perhaps how to set defaults values for NSUserDefaults?

在您的问题中,您不会得到“无法识别的选择器”;newString将设置为nil(而不是[NSNull null],所以我怀疑您可能是其他意思-也许如何为 设置默认值NSUserDefaults

回答by Goz

I've done this with a simple NSDictionary extension.

我已经用一个简单的 NSDictionary 扩展完成了这个。

NSDictionary+NSDictionaryExtensions.h

NSDictionary+NSDictionaryExtensions.h

#import <Foundation/Foundation.h>

@interface NSDictionary (NSDictionaryExtensions)

- (id)objectForKey:(id)aKey defaultObject: (id) defObj;

@end

NSDictionary+NSDictionaryExtensions.m

NSDictionary+NSDictionaryExtensions.m

#import "NSDictionary+NSDictionaryExtensions.h"

@implementation NSDictionary (NSDictionaryExtensions)

- (id)objectForKey:(id)aKey defaultObject: (id) defObj
{
    id ret = [self objectForKey: aKey];
    if ( ret == nil )
        return defObj;
    else
        return ret;
}

@end

I can then access as follows:

然后我可以访问如下:

NSString* str = [dict objectForKey: @"a_key" defaultObject: @"default"];

回答by Mike M

As per @Paul Lynch you must check for [NSNull null] apart from nil. It is also advisable to check for the data type you are looking for:

根据@Paul Lynch,除了 nil 之外,您还必须检查 [NSNull null]。还建议检查您要查找的数据类型:

- (id) objectForKey: (id) key withDefault: (id) defaultValue
{
    id value = self[key];

    if (value == nil || [value isEqual: [NSNull null]] || ![defaultValue isKindOfClass: [value class]])
    {
        value = defaultValue;
    }

    return value;
}

回答by Dhaval H. Nena

You can manually check for nil values as below for different types:

您可以手动检查不同类型的 nil 值,如下所示:

extension NSDictionary {

func convertToString() -> String {
    let jsonData = try! JSONSerialization.data(withJSONObject: self, options: JSONSerialization.WritingOptions.prettyPrinted) as NSData!

    if jsonData  == nil{
        return "{}"
    }else {
        return String(data: jsonData as! Data, encoding: String.Encoding.utf8)!
    }
}

func object_forKeyWithValidationForClass_Int(aKey: String) -> Int {

    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return Int()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return Int()
        }
    } else {
        // KEY NOT FOUND
        return Int()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return Int()
    }
    else if(aValue.isKind(of: NSString.self)){
        return Int((aValue as! NSString).intValue)
    }
    else {

        if aValue is Int {
            return self.object(forKey: aKey) as! Int
        }
        else{
            return Int()
        }
    }
}

func object_forKeyWithValidationForClass_CGFloat(aKey: String) -> CGFloat {

    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return CGFloat()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return CGFloat()
        }
    } else {
        // KEY NOT FOUND
        return CGFloat()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return CGFloat()
    }
    else {

        if aValue is CGFloat {
            return self.object(forKey: aKey) as! CGFloat
        }
        else{
            return CGFloat()
        }
    }
}

func object_forKeyWithValidationForClass_String(aKey: String) -> String {

    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return String()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return String()
        }
    } else {
        // KEY NOT FOUND
        return String()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return String()
    }
    else if(aValue.isKind(of: NSNumber.self)){
        return String(format:"%f", (aValue as! NSNumber).doubleValue)
    }
    else {

        if aValue is String {
            return self.object(forKey: aKey) as! String
        }
        else{
            return String()
        }
    }
}

func object_forKeyWithValidationForClass_StringInt(aKey: String) -> String {

    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return String()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return String()
        }
    } else {
        // KEY NOT FOUND
        return String()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return String()
    }
    else if(aValue.isKind(of: NSNumber.self)){
        return String(format:"%d", (aValue as! NSNumber).int64Value)


    }
    else {

        if aValue is String {
            return self.object(forKey: aKey) as! String
        }
        else{
            return String()
        }
    }
}

func object_forKeyWithValidationForClass_Bool(aKey: String) -> Bool {
    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return Bool()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return Bool()
        }
    } else {
        // KEY NOT FOUND
        return Bool()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return Bool()
    }
    else {

        if aValue is Bool {
            return self.object(forKey: aKey) as! Bool
        }
        else{
            return Bool()
        }
    }
}

func object_forKeyWithValidationForClass_NSArray(aKey: String) -> NSArray {
    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return NSArray()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return NSArray()
        }
    } else {
        // KEY NOT FOUND
        return NSArray()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return NSArray()
    }
    else {
        if aValue is NSArray {
            return self.object(forKey: aKey) as! NSArray
        }
        else{
            return NSArray()
        }
    }
}

func object_forKeyWithValidationForClass_NSMutableArray(aKey: String) -> NSMutableArray {
    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return NSMutableArray()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return NSMutableArray()
        }
    } else {
        // KEY NOT FOUND
        return NSMutableArray()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return NSMutableArray()
    }
    else {

        if aValue is NSMutableArray {
            return self.object(forKey: aKey) as! NSMutableArray
        }
        else{
            return NSMutableArray()
        }
    }
}

func object_forKeyWithValidationForClass_NSDictionary(aKey: String) -> NSDictionary {
    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return NSDictionary()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return NSDictionary()
        }
    } else {
        // KEY NOT FOUND
        return NSDictionary()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return NSDictionary()
    }
    else {

        if aValue is NSDictionary {
            return self.object(forKey: aKey) as! NSDictionary
        }
        else{
            return NSDictionary()
        }
    }
}

func object_forKeyWithValidationForClass_NSMutableDictionary(aKey: String) -> NSMutableDictionary {
    // CHECK FOR EMPTY
    if(self.allKeys.count == 0) {
        return NSMutableDictionary()
    }

    // CHECK IF KEY EXIST
    if let val = self.object(forKey: aKey) {
        if((val as AnyObject).isEqual(NSNull())) {
            return NSMutableDictionary()
        }
    } else {
        // KEY NOT FOUND
        return NSMutableDictionary()
    }

    // CHECK FOR NIL VALUE
    let aValue : AnyObject = self.object(forKey: aKey)! as AnyObject
    if aValue.isEqual(NSNull()) {
        return NSMutableDictionary()
    }
    else {
        if aValue is NSMutableDictionary {
            return self.object(forKey: aKey) as! NSMutableDictionary
        }
        else{
            return NSMutableDictionary()
        }
    }
}

}

}

回答by ader

try

尝试

if ( myObject == nil ) {
   [myObject setMyString:@""];
}

or

或者

if ( [dictionary valueForKey:@"myKey"] == nil ) {
    [dictionary setObject:@"" forKey:@"myKey"];
}

回答by CRD

Whatever default value you assigned to your string it will not make myObject.myStringreturn "unrecognized selector error" - usually the property myStringeither exists or it does not ('usually' as you can dig into the guts of the Objective-C runtime and play games, but this is rarely (if ever) what you want to do!)

无论您分配给字符串的默认值是什么,它都不会myObject.myString返回“无法识别的选择器错误”——通常该属性myString要么存在,要么不存在(“通常”,因为您可以深入了解 Objective-C 运行时的内容并玩游戏,但是这很少(如果有的话)你想做!)

What are you trying to do? If your aim is to throw an exception on myObject.myStringnot being set then you can do that in the property implementation.

你想做什么?如果您的目标是在myObject.myString未设置时抛出异常,那么您可以在属性实现中执行此操作。

For example, valueForKey;will return nilif there is no value set for a given key, so you can check for that in your property:

例如,如果没有为给定键设置值,valueForKey;则将返回nil,因此您可以在您的属性中检查该值:

- (void) setMyString:(NSString *)value
{  myString = value;
}

- (NSString *) myString
{
   if (myString == nil)
      @throw [NSException exceptionWithName:@"UnrecognizedSelector" reason:@"No value set for myString" userInfo:nil];
   return myString;
}

Notes:

笔记:

  1. code typed at terminal, may contain typos

  2. code assumes garbage collection/ARC on, if not you need to add appropriate retain/copy/release

  1. 在终端输入的代码,可能包含拼写错误

  2. 代码假设垃圾收集/ARC开启,如果不是你需要添加适当的保留/复制/释放

But do you really want to throw an exception? You would normally only do so if the string shouldbe set and not being so is an exceptionalcondition - you don't throw for default values.

但是你真的想抛出异常吗?您通常只会在应该设置字符串并且不这样设置是例外情况时才这样做- 您不会为默认值抛出。