简体   繁体   English

如何在iOS Objective-C中比较两个数字

[英]How to compare two numbers in iOS Objective-C

What is the safe way to compare to NSNumbers? 与NSNumbers比较的安全方法是什么? If I do isEqualToNumber: and one of the numbers is nil, I still get an 如果我执行isEqualToNumber:并且其中一个数字为nil,我仍然会得到一个

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber compare:]: nil argument'

I thought nil defaulted to zero in iOS? 我以为nil在iOS中默认为零? Please help me understand some fundamentals if possible. 如果可能,请帮助我了解一些基本知识。 Thanks. 谢谢。

my code is 我的代码是

numberB=[numberB isKindOfClass:[NSNull class]]?0: numberB;
if([numberA isEqualToNumber: numberB]){...}

It seems that the NSNull check is ignored because my logging shows that numberB is still (null) instead of 0. I am really trying, here. 似乎NSNull检查被忽略了,因为我的日志记录显示numberB仍然是(null)而不是0。我确实在这里尝试。 So thanks for any help. 因此,感谢您的任何帮助。

If the argument might be nil , use isEqual: , not isEqualToNumber: . 如果参数可能为nil ,请使用isEqual:而不要使用isEqualToNumber: The isEqual: method is documented to accept a nil argument. isEqual:方法已记录为接受nil参数。

What defaults to nil (or a zero-like quantity) in Objective-C is the return value of a message when you send the message to nil . 当您将消息发送给nil时,在Objective-C中默认为nil (或类似零的数量)是消息的返回值。 For example, [nil isEqualToNumber:@7] returns NO ; 例如, [nil isEqualToNumber:@7]返回NO [nil copy] returns nil ; [nil copy]返回nil [nil integerValue] returns 0. Thus it is generally safe to send any message to nil . [nil integerValue]返回0。因此, 任何消息发送 nil通常是安全的。 It is not necessarily safe to pass nil as an argument to a message if the message isn't documented to accept nil as an argument. 不一定是安全的传递nil作为参数传递给一个消息,如果没有记录的消息,接受nil作为参数。

UPDATE 更新

Based on the code you added, you could do this: 根据您添加的代码,您可以执行以下操作:

numberB = (numberB == [NSNull null]) ? @0 : numberB;
if ([numberA isEqualToNumber:numberB]) {
    ...
}

Note that @0 represents an NSNumber with value 0. Also, there is only one instance of NSNull , so you can check for it with == . 请注意, @0代表一个NSNumber ,值为0。此外,只有一个NSNull实例,因此可以使用==进行检查。

UPDATE 2 更新2

If NSLog is printing (null) , then numberB is nil , which is different that [NSNull null] . 如果NSLog正在打印(null) ,则numberBnil ,这与[NSNull null] You can check for both possibilities like this: 您可以像这样检查两种可能性:

numberB = (numberB == nil || numberB == [NSNull null]) ? @0 : numberB;
if ([numberA isEqualToNumber:numberB]) {
    ...
}

Nil defaults to zero (or the boolean NO) in logical statements. 逻辑语句中的Nil默认为零(或布尔NO)。 So for example if(nilObject) will evaluate to false. 因此,例如if(nilObject)将评估为false。 Nil arguments by default do not evaluate as 0. It's up to the specific method's implementation. 默认情况下,nil个参数的求值结果不为0。这取决于特定方法的实现。

In this case, NSNumber compare: expects the argument to be non-nil. 在这种情况下, NSNumber compare:期望参数为非nil。 It's not a universal rule in Objective-C, just an NSNumber implementation detail. 这不是Objective-C中的通用规则,而只是NSNumber实现细节。

You could first convert your NSNumber objects into primitive types, eg by calling [myNumber doubleValue] and then compare those. 您可以先将NSNumber对象转换为原始类型,例如,通过调用[myNumber doubleValue] ,然后进行比较。 By the way, getting the primitive value from a nil NSNumber will give you 0. 顺便说一句,从零NSNumber获取原始值将得到0。

If you are just worried that numberB could be nil and want to ignore that case: 如果您只是担心numberB可能为nil并且想忽略这种情况:

if([numberA isEqualToNumber:numberB?: @(NSIntegerMax)]){...};

Note that this will also ignore any case where numberA is nil. 注意,这也将忽略numberA为nil的任何情况。

NSLog for numberB is null cause numberB is nil. numberB的NSLog为null,因为numberB为nil。

Make a test: 做一个测试:

NSLog(@"NumberB is nil? %@", numberB == nil ? @"YES":@"NO"); --> displays 'NumberB is nil? YES'

when you compare a nil to [NSNull null], it returns NO 当您将nil与[NSNull null]比较时,它返回NO

I suppose that you get numberB from a code like: 我想您是从类似的代码中获取numberB的:

NSNumber *numberB = (NSNumber*)[[NSUserDefaults standardUserDefaults] valueForKey:@"numberB"];

it returns 'nil' value. 它返回“ nil”值。 you should then compare numberB to nil, but not to [NSNull null]. 然后应将numberB与nil进行比较,但不能与[NSNull null]进行比较。

Example

numberB = numberB != nil? numberB : @0;
if ([numberA isEqualToNumber:numberB) {
...
}

I finally got it to work by doing 我终于做到了

numberB= (numberB == nil)?[NSNumber numberWithLongLong:0]:numberB;

So the problem seems that @0 or simple 0 was being converted to nil. 因此,问题似乎是@0或简单0被转换为nil。 I don't quite understand it, but now it works. 我不太了解,但是现在可以了。 Thanks and +1 for everyone for all the help. 多谢大家的支持,并为他们+1。

While the other answers are correct, let me add some more basic explanation: 尽管其他答案是正确的,但让我添加一些更基本的解释:

In programming we're dealing with values and pointers. 在编程中,我们正在处理值和指针。 A value is a piece of data such as a numeric value or a string of characters. 值是一条数据,例如数字值或字符串。 A pointer is a value too, but a specialized one - it is the address of a value in memory. 指针也是一个值,但也是专门的一个-它是内存中值的地址。 Hence the name - it points to a piece of usable data. 因此,名称-指向一条可用数据。

If you do something like NSNumber *happyNumber = @7; 如果您执行NSNumber *happyNumber = @7; , happyNumber is a pointer and it points to the value 7. Well, not exactly, because your 7 is actually wrapped in an object, but that's another story. ,happyNumber是一个指针,它指向值7。恩,不完全是,因为您的7实际上包裹在一个对象中,但这是另一回事了。

Now, sometimes a pointer is still around while the value it pointed to became invalid or is about to. 现在,有时指针仍然在指针所指向的值变为无效或即将变为值的时候。 Or the value doesn't even exist yet. 或者该值甚至不存在。 But a pointer can never be "empty" and will always point at some memory address, so using such a pointer may result in undefined and random behavior. 但是指针永远不能为“空”,并且始终指向某个内存地址,因此使用此类指针可能会导致未定义和随机的行为。 And to prevent this, we're using nil to give the pointer something meaningful to point to. 为了防止这种情况,我们使用nil赋予指针一些有意义的指向。 It is sort of a placeholder, representing the "empty" state for a pointer and at the same time makes accidential use of the pointer relatively safe. 它是一种占位符,代表指针的“空”状态,同时使指针的意外使用相对安全。

This means that you can throw messages at a nil object and quite literally, nothing happens. 这意味着您可以在nil对象上抛出消息,从字面上看,什么也没有发生。 If you feed a nil pointer or object to another object though, it might not be prepared or able to handle "emptiness". 但是,如果将nil指针或对象提供给另一个对象,则可能未准备好或无法处理“空”。 This is what happened with isEqualToNumber: : it makes no sense to compare two numbers if one isn't even a number. 这就是isEqualToNumber:发生的事情isEqualToNumber:如果两个数字都不是数字,则比较两个数字是没有意义的。 In this case even just returning a boolean NO would be wrong in a way too, because it would imply that we are dealing with two perfectly healthy numbers which just happen to be different. 在这种情况下,即使只是返回布尔值NO在某种程度上也是错误的,因为这意味着我们正在处理两个恰好不同的完全健康的数字。 So instead, NSNumber resolves the situation by throwing an exception. 因此,NSNumber通过引发异常来解决这种情况。

NSNull is similar to nil in that it represents absence of something useful, however it is not the same. NSNull与nil相似,因为它表示缺少有用的东西,但是并不相同。 NSNull is a class and you can get a (singleton) instance of it. NSNull是一个类,您可以获取它的一个(单个)实例。 It is used where the absence of something needs to be represented by an actual, live object. 它用于需要通过实际的活动对象来表示不存在的情况。

That's why the first version of your ternary operation failed - numberB was nil, not [NSNull null] so you where just checking for the wrong type of "emptiness" (@0 results in a perfectly fine NSNumber, not nil). 这就是为什么您的三元运算的第一个版本失败的原因-numberB为nil,而不是[NSNull null]因此您只需要检查错误类型的“空”(@ 0会得到一个很好的NSNumber,而不是nil)。

You can of course check for both possibilities, but if you default on using nil for yourself (which you should) this will seldom be necessary. 您当然可以检查这两种可能性,但是如果您默认自己不使用nil(应该这样做),则几乎没有必要。

Hope that helps. 希望能有所帮助。 Cheers! 干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM