如何在Objective-C中创建内联条件赋值?

如何在Objective-C中创建内联条件赋值?,objective-c,if-statement,syntax,conditional-statements,Objective C,If Statement,Syntax,Conditional Statements,MyPet类有两个属性:BOOLisHungry和NSNumber*age。 我想把宠物myPet的属性放入NSMutableDictionary*myMap 这是我的代码是Java。我正试图用Objective-C写一个等价物 myMap.put("isHungry", myPet == null ? null : myPet.isHungry); myMap.put("age", myPet == null ? null : myPet.age);

My
Pet
类有两个属性:BOOL
isHungry
和NSNumber*
age
。 我想把宠物myPet的属性放入NSMutableDictionary*myMap

这是我的代码是Java。我正试图用Objective-C写一个等价物

myMap.put("isHungry", myPet == null ? null : myPet.isHungry);
myMap.put("age", myPet == null ? null : myPet.age);
这是我当前的Objective-C版本:

[myMap addEntriesFromDictionary:@{
    @"isHungry" : myPet ? myPet.isHungry : (NSInteger)[NSNull null],
    @"age" : myPet ? myPet.age : [NSNull null],
}];
第二行的错误如下:

Incompatible operand types ('int' and 'NSNull * _Nonnull')
当我添加(NSInteger)时,编译器停止抱怨第一行。 如果我在第二行输入相同的代码,错误会消失,但编译器会再次抱怨第一行:

Collection element of type 'long' is not an Objective-C object

我是Obj-C的一个疯子,我完全迷路了。我还想知道Obj-C的最佳实践。

因为您有一个带有
@property BOOL-isHungry的
宠物类
@property NSNumber*年龄
而您的
myMap
NSMutableDictionary
您的解决方案应该是这样的

Pet *myPet = [[Pet alloc] init];
myPet.age = @(2);
myPet.isHungry = YES;

NSMutableDictionary *myMap = [[NSMutableDictionary alloc] init];
if (myPet!=nil) {
    [myMap addEntriesFromDictionary:@{
        @"isHungry" : @(myPet.isHungry),
        @"age" : myPet.age
    }];
}
// with this you store only the values of Pet
NSLog(@"%@",myMap.description);

// but that goes even easier..
NSMutableDictionary *myDict = [NSMutableDictionary new];
myDict[@"Pet1"] = myPet;
NSLog(@"%@",myDict.description);

Pet *petInDict = myDict[@"Pet"];
NSLog(@"age=%@ isHungry=%@",petInDict.age, (petInDict.isHungry ? @"YES":@"NO") );
// should be age=(null) isHungry=NO
// because we stored with key myDict[@"Pet1"] and not myDict[@"Pet"]

// ok lets take the key we used
Pet *pet1 = myDict[@"Pet1"];
NSLog(@"age=%@ isHungry=%@",pet1.age, (pet1.isHungry ? @"YES":@"NO") );
由于存在非NSObject子类的泛型数据类型,因此如果不将它们存储到对象中,就无法将它们存储在字典中

@(yournumber)     // converts to NSNumber
@(YES)            // converts to NSNumber = 1
@(NO)             // converts to NSNumber = 0
@[@(1),@(2),@(3)] // converts to an NSArray with 3 NSNumbers
@{}               // this one you know allready, its a NSDictionary
@"hello"          // well NSString of course
@selector(name:)  // thats a pointer to a method with name:, of type SEL
...
@{@"key1":@YES, @"key2":@NO}
// it is possible to convert BOOL directly
你也可以用这种方式开始,但你会发现它看起来很奇怪

NSMutableDictionary*syntaxsugar=[({“isHungry”:(myPet.isHungry),“age”:myPet.age})mutableCopy]


mutableCopy
生成前导数据类型NSDictionary的可变副本。

目标C中的字典只能存储对象,也只能存储现有对象

通过写入@(myPet.isHungry),可以将布尔值或算术值(如myPet.isHungry)转换为NSNumber对象。您可以通过写入[NSNull]来创建一个可以代表nil的对象

当您试图从字典中提取一个值时,会得到一个object或nil。您可以通过检查来检查对象是否表示nil

if (value == nil || value == [NSNull null])
第二个比较有效,因为始终只有一个NSNull对象


如果您知道该值是NSNumber对象,则可以使用布尔值或整数值等来提取该值。

您的
isHungry
是布尔值。数组和字典只能存储对象。但是
BOOL
NSInteger
是基本类型,而不是对象(这就是为什么会出现错误)。但您可以将其转换为对象(
NSNumber
),并将其添加到字典中

您可以通过两种方式将
BOOL
值转换为
NSNumber
,方法是在值前面添加
@
,或使用
numberwhithbool:

例如:

NSNumber *isHungry = @(myPet.isHungry); // OR

NSNumber *isHungry = [NSNumber numberWithBool:myPet.isHungry];
您可以内联执行此操作,这样您的代码看起来(和工作方式)如下:

当您从字典中检索数据时,您将获得以前存储的NSNumber。但是如果需要的话,你可以把它转换回BOOL

// getting BOOL back    
NSNumber *isHungryObj = myMap[@"isHungry"]; // it must be NSNumber not NSNull!
BOOL isHungry = isHungry.boolValue; 
但在上述情况下,您必须确保存储的对象实际上是
NSNumber
,而不是
NSNull
。因为在
NSNull
的情况下,应用程序将崩溃,因为
NSNull
不是
NSNumber
并且不响应
boolValue
。 为了避免这种情况,您可以:

  • 始终必须根据
    NSNull
    检查返回的对象(这不是最佳解决方案,在字典中的同一个键下存储两种不同类型的对象也不是最佳做法)
  • 根据您的需要,在没有myPet的情况下,最好存储一些默认值,而不是
    NSNull
    。例如为iHungry设置
    @NO
    ,为age设置
    @0
  • 或者你可以在添加值之前检查myPet是否存在,如果它不存在,就不要向myMap添加任何内容。在这种情况下,如果您没有向myMap添加任何内容,那么调用
    myMap[@“isHungry”]
    将返回
    nil
    。 它是Objective-C中
    null
    的另一个变体。检查
    nil
    NSNull
    更容易,即使您向
    nil
    发送一些消息,也不会发生任何不好的事情。在Objective-C中,允许向
    nil
    发送消息。不能像使用
    NSNull
    那样将
    nil
    存储在字典中,但可以将对象与
    nil
    进行比较
第三个选项的示例代码:

// adding to a dictionary, does the same thing as your code
if (myPet != nil) // OR if (myPet)
{
    myMap[@"isHungry"] = @(myPet.isHungry);
    myMap[@"age"]  = myPet.age;
}

// retrieving
if (myMap[@"age"])
{
    // number exists, you can do something with it
}
由于
nil
可以毫无问题地向其发送消息,因此有时您甚至不需要检查
nil
,例如在这种情况下:

if ([myMap[@"age"] integerValue] == 5) // returns YES if it's 5 and NO in any other case even if @"age" wasn't set and is nil

希望这有帮助。

有很多教程。。这里有一个。。什么是我的地图?一本易变字典?或者您想定义一个类?@OlSen myMap是NSMutableDictionaryo您有一个属性为BOOL isHungry的类宠物;和财产编号*年龄@奥尔森:是的,没错。
if ([myMap[@"age"] integerValue] == 5) // returns YES if it's 5 and NO in any other case even if @"age" wasn't set and is nil