NSString и NSDictionary valueForKey — ноль?

#iphone #objective-c #ios #cocoa-touch

#iPhone #objective-c #iOS #cocoa-touch

Вопрос:

Как я могу поместить значение по умолчанию в свою строку, если получаю данные из пустого ключа / значения в словаре.

итак [myObject setMyString:[dictionary valueForKey:@"myKey"]];

Итак, если бы я это сделал NSString *newString = myObject.myString , я бы получил unrecognized selector error .

Итак, мне просто нужен способ вставить строку по умолчанию, если значение ключа пустое;

Комментарии:

1. Я не уверен, о чем вы спрашиваете, можете ли вы уточнить?

2. Вы не можете получить нулевое значение из словаря. Если возвращается значение nil, это означает, что ключ не существует в словаре. Если вы хотите сохранить (концептуальное) нулевое значение в словаре, вы должны использовать объект NSNull .

Ответ №1:

Если dictionary это a NSDictionary , вам, вероятно, следует использовать objectForKey as valueForKey используется для KVC. Это работает NSDictionary , но может вас укусить, если ключ столкнется с каким NSDictionary -либо ключом KVC, например, «@allKeys» или «@count».

Я думаю, что самое короткое, вероятно, сделать:

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

Существует один ужасный способ злоупотребления существующими методами словаря для получения ключа get by или возврата значения по умолчанию, если вы по какой-либо причине не хотите использовать условие…

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

Вы не слышали это от меня 🙂

Ответ №2:

Что насчет этого?

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

Комментарии:

1. Также можно сделать [myObject setMyString:[dic...Key:@"myKey"] ?: @"defaultValue"];

2. Я знаю, что этот метод работает, но искал более однострочный MyObject.myString = [dictionary valueForKey@»MyKey»] ? [словарь valueForKey@»MyKey»]: @»»; Похоже, это не работает. Если для ключа есть значение, используйте значение для ключа, иначе сделайте @»»

3. Всегда можно создать категорию для NSArray, что-то вроде objectForKey:(id)key withDefault:(id)defaultObject . Это позволило бы выполнить операцию «один лайнер».

Ответ №3:

Используйте [NSNull null] для общего случая и обработайте его, когда он будет возвращен.

В вашем вопросе вы не получили бы «нераспознанный селектор»; newString будет установлено значение nil (в отличие от [NSNull null] , поэтому я подозреваю, что вы могли иметь в виду что-то другое — возможно, как установить значения по умолчанию для NSUserDefaults ?

Ответ №4:

Я сделал это с помощью простого расширения NSDictionary.

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
  

Затем я могу получить доступ следующим образом:

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

Ответ №5:

попробуйте

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

или

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

Ответ №6:

Какое бы значение по умолчанию вы ни присвоили своей строке, оно не myObject.myString вернет «нераспознанную ошибку селектора» — обычно свойство myString либо существует, либо его нет («обычно», поскольку вы можете копаться в недрах среды выполнения Objective-C и играть в игры, но это редко (если вообще когда-либо) то, что вы хотитечто делать!)

Что вы пытаетесь сделать? Если ваша цель состоит в том, чтобы создать исключение myObject.myString , если оно не установлено, вы можете сделать это в реализации свойства.

Например, 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;
}
  

Примечания:

  1. код, введенный на терминале, может содержать опечатки

  2. код предполагает сборку мусора / ARC, если нет, вам нужно добавить соответствующее сохранение / копирование / выпуск

Но вы действительно хотите создать исключение? Обычно вы делаете это только в том случае, если строка должна быть установлена, а отсутствие этого является исключительным условием — вы не используете значения по умолчанию.

Ответ №7:

Согласно @Paul Lynch, вы должны проверить наличие [NSNull null], кроме nil. Также желательно проверить тип данных, который вы ищете:

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

Ответ №8:

Вы можете вручную проверить наличие нулевых значений, как показано ниже, для разных типов:

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

}