开发者

NSString and NSDictionary valueForKey - nil?

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"]];

So then i开发者_如何学JAVAf I did NSString *newString = myObject.myString I would get an unrecognized selector error.

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


If dictionary is a NSDictionary you should probably use objectForKey as valueForKey is used for KVC. It works for NSDictionary but may bite you if the key collide with some NSDictionary KVC key, e.g. "@allKeys" or "@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 :)


What about this?

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


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

In your question, you wouldn't get "unrecognised selector"; newString would 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?


I've done this with a simple NSDictionary extension.

NSDictionary+NSDictionaryExtensions.h

#import <Foundation/Foundation.h>

@interface NSDictionary (NSDictionaryExtensions)

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

@end

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"];


try

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

or

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


Whatever default value you assigned to your string it will not make myObject.myString return "unrecognized selector error" - usually the property myString either 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!)

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

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

- (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

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


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:

- (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;
}


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

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()
        }
    }
}

}

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜