首页 > 解决方案 > 在 Objective C 中用关联值表示枚举

问题描述

在 Swift 中有关联值的枚举:

enum Coffee {
    case Black
    case BlackWithSugar(spoons: Int)
    // ....
}

显然,这里的目标是:

在Objective C中表达相同内容的最接近/最优雅的方式是什么?

注意:我看到了这个问题,但是 2 个答案并没有说明如何在 Objective C 中表达相同的意图。我可以使用枚举以外的东西,并且使用 Swift 不是一种选择。

谢谢

标签: objective-cenums

解决方案


虽然有可能通过大量工作来完成与 Swift 的枚举与 Objective-C 中的关联类型非常相似的事情(请参阅我在上面评论中链接的博客文章),但它需要一堆难以理解的代码。

我建议采用更自然的 Objective-C 风格的方法。你会失去 Swift 提供的一些类型安全性,但 ObjC 自然是一种类型安全性较低的语言。

例如:

// Create an options enum. Bridges into Swift as an OptionSet
typedef NS_OPTIONS(NSInteger, CoffeeOptions) {
    CoffeeOptionsBlack = 0,
    CoffeeOptionsWithSugar = 1 << 0,
    CoffeeOptionsWithCream = 1 << 1
};

// Create a (non-extensible) string-typed "enum". Bridges into Swift as an enum-style struct with string "raw values"
typedef NSString *CoffeeQuantityKey NS_TYPED_EXTENSIBLE_ENUM;
static CoffeeQuantityKey const CoffeeQuantityKeySpoonsOfSugar = @"SpoonsOfSugar";
static CoffeeQuantityKey const CoffeeQuantityKeyTeaspoonsOfCream = @"TeaspoonsOfCream";

@interface CoffeeMachine : NSObject
- (void)makeCoffeeWithOptions:(CoffeeOptions)options quantities:(NSDictionary<CoffeeQuantityKey, NSNumber *> *)quantities;
@end

@implementation CoffeeMachine

- (void)makeCoffeeWithOptions:(CoffeeOptions)options quantities:(NSDictionary<CoffeeQuantityKey, NSNumber *> *)quantities
{
    // Make coffee
    if (options & CoffeeOptionsWithSugar) {
        NSNumber *sugarAmount = quantities[CoffeeQuantityKeySpoonsOfSugar] ?: @1; // Default to 1 spoon
        NSLog(@"Adding %@ spoons of sugar", sugarAmount);
    }

    if (options & CoffeeOptionsWithCream) {
        NSNumber *creamAmount = quantities[CoffeeQuantityKeyTeaspoonsOfCream] ?: @1; // Default to 1 teaspoon
        NSLog(@"Adding %@ teaspoons of cream", creamAmount);
    }
}

@end

这也有一个优势,可以相对很好地桥接到 Swift 中:

let cm = CoffeeMachine()
cm.makeCoffee(options: [.withSugar, .withCream], quantities: [.spoonsOfSugar : 3])

推荐阅读