【问题标题】:Is it possible to shorten conditional statements in cocoa to not re-state the variable name?是否可以缩短可可中的条件语句以不重新声明变量名?
【发布时间】:2013-02-16 19:40:51
【问题描述】:

想知道是否有办法简写这些条件。我正在处理数据包,有时条件会变得有点笨拙。这是一个基本示例:

我写:

if (message->messageType != kMessageTypeCutCardsArray && message->messageType != kMessageTypeQuit) {
    MessageInt message;
    message.message.messageType = kMessageTypeReceivedData;
    NSData *packet = [NSData dataWithBytes:&message length:sizeof(message)];
    [_game sendData:packet];
}

我宁愿写:

if (message->messageType != (kMessageTypeCutCardsArray || kMessageTypeQuit)) {
    MessageInt message;
    message.message.messageType = kMessageTypeReceivedData;
    NSData *packet = [NSData dataWithBytes:&message length:sizeof(message)];
    [_game sendData:packet];
}

【问题讨论】:

  • 对不起,我刚刚对你的回答评论了“不正确”,但我觉得我读得太快了。 if kMessageTypeCutCardsArray 是正确的,另一个是位标志 - 单管道是二进制 OR 并且 组合两个(互斥)标志,以便您可以同时检查它们。但是,在检查这样的掩码时,您通常应该使用 & 而不是 ==
  • 您能说明您要比较的事物的类型吗?
  • 您可以将值复制到具有较短名称的变量中以简化,即sometype val = mess->of.an[expression]->goes.here; if((val == this) || (val == that)) {...(无论如何,您的邻居编译器可能会在您背后自己这样做)
  • 乔希,我认为你是对的,我错了。我正在评估 typedef 结构中定义的消息类型,如下所示: typedef enum { ... } MessageType; typedef struct { MessageType messageType; } 消息;

标签: objective-c cocoa


【解决方案1】:

一般来说,不会。这正是 C(以及 Objective-C)的工作方式。

在这种特定情况下,您可以使用switch 语句:

switch (message->messageType)
{
    case kMessageTypeCutCardsArray:
    case kMessageTypeQuit:
        break;
    default:
        MessageInt message;
        message.message.messageType = kMessageTypeReceivedData;
        NSData *packet = [NSData dataWithBytes:&message length:sizeof(message)];
        [_game sendData:packet];
        break;
}

该语法是否是一种改进取决于您。

【讨论】:

  • 我就是这么想的。感谢您的切换想法,但在这种情况下,如果除了这两种消息类型之一之外,我想做点什么。
  • 糟糕!我误读了。您仍然可以使用开关来表达该逻辑,我已经更新了我的答案以说明如何。 (不过,这会使语法变得更不紧凑和更麻烦。)
【解决方案2】:

如果您定义 enum 使得值具有互斥位模式,如下所示:

typedef enum : NSUInteger {
    kMessageTypeLoveLetter = 1 << 0,
    kMessageTypeBirthdayCard = 1 << 1,
    kMessageTypeVacationPostcard = 1 << 2,
    kMessageTypeCreditApplication = 1 << 3,
    kMessageTypeCharitySolicitation = 1 << 4
} MessageType;

然后您可以使用二进制 OR | 和二进制 AND &amp; 一次测试多个值:

MessageType msgType = kMessageTypeCreditApplication;

if( !(msgType & (kMessageTypeLoveLetter | kMessageTypeBirthdayCard)) ){
    // Nobody loves you.
}
if( (msgType & (kMessageTypeCreditApplication | kMessageTypeCharitySolicitation) ){
    // Someone wants your money.
}

但是,如果您为enum 使用编译器生成的连续值,这将不起作用,因为这些值将作为标志重叠——例如,2 和 3 都设置了最低位——并且 ORing它们通常会最终只测试其中一个标志。

【讨论】:

  • 这个技巧不是我编出来的;它大约和 C 一样古老!
  • 我以前见过按位运算,但是我没有在 typedefs 中定义位模式。虽然,绝对可能是我对直接 C 的相对较小的经验。感谢您的回答。
  • 很高兴它有帮助!在我的脑海中,你会在 Cocoa 中看到位掩码的一个地方是用于键盘处理——修饰键在 NSEvents 和设置键等效项时用掩码表示。
【解决方案3】:

您可以将值装箱并使用临时数组。这实现了去除条件中重复的目标,但不太可能对编译器进行优化。

if (message->messageType != kMessageTypeCutCardsArray && 
    message->messageType != kMessageTypeQuit) {

应该相当于:

if(![@[@(kMessageTypeCutCardsArray),@(kMessageTypeQuit)] 
     contains:@(message->messageType)]) {

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2016-12-10
    • 2011-11-10
    • 1970-01-01
    相关资源
    最近更新 更多