iOS 字符串枚举

974 阅读2分钟

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」。

我们日常开发中常见或者常用的枚举都是整数型,类似于这样的:

typedef NS_ENUM(NSUInteger, HPTodayWeatherType) {
    /// Sunny:晴天;
    HPTodayWeatherTypeSunny = 0,
    /// Rain:雨天;
    HPTodayWeatherTypeRain,
    /// Windy:大风天
    HPTodayWeatherTypeWindy,
};

其实,iOS系统代码里面有这样一个宏定义:

#define NS_STRING_ENUM _NS_TYPED_ENUM

我们可以利用这个宏定义去实现字符串枚举,在HPStringEnum.h文件中添加以下代码:

/// 定义一个HPTodayWeatherStateMsg的字符串类型作为枚举类型
typedef NSString *HPTodayWeatherStateMsg NS_STRING_ENUM;
/// 声明以下三个枚举值
/// Sunny:晴天
FOUNDATION_EXPORT HPTodayWeatherStateMsg const HPTodayWeatherStateMsgSunny;
/// Rain:雨天
FOUNDATION_EXPORT HPTodayWeatherStateMsg const HPTodayWeatherStateMsgRain;
/// Windy:大风天
FOUNDATION_EXPORT HPTodayWeatherStateMsg const HPTodayWeatherStateMsgWindy;

然后在HPStringEnum.m文件中添加以下代码:

NSString * const HPTodayWeatherStateMsgSunny = @"晴天";
NSString * const HPTodayWeatherStateMsgRain  = @"雨天";
NSString * const HPTodayWeatherStateMsgWindy = @"大风天";

这样就可以了,我们看个简单的使用例子,将枚举作为类方法的参数使用,代码如下:

+ (void)hpReadWeatherStateMsg:(HPTodayWeatherStateMsg)weatherStateMsg {

    NSLog(@"字符串枚举值为-->%@",weatherStateMsg);
}

其实细心查看就会发现,字符串枚举的定义,和定义一个全局字符串常量一样,我们来看以下全局字符串常量的定义,先在HPStringEnum.h文件中添加以下代码:

/// Snowy:雪天
FOUNDATION_EXPORT NSString * const HPTodayWeatherStateMsgSnowy;

然后在HPStringEnum.m文件中赋值:

NSString * const HPTodayWeatherStateMsgSnowy = @"雪天";

我们现在回看一下上面定义字符串枚举的代码部分,发现不过是用HPTodayWeatherStateMsg替换了NSString *** 。而HPTodayWeatherStateMsg**就是通过以下这句代码:

/// 定义一个HPTodayWeatherStateMsg的字符串类型作为枚举类型
typedef NSString *HPTodayWeatherStateMsg NS_STRING_ENUM;

被我们定义为了**NSString *** 的别名。

关于NS_STRING_ENUM

在 Xcode 8 中,苹果为 Objective-C 提供了全新的 Macro: NS_STRING_ENUM 和 NS_EXTENSIBLE_STRING_ENUM,让这些字串常量使用起來更像是 Swift 原生的 string enum。

NS_STRING_ENUM 需要搭配 typedef 使用。首先使用之前先用 HPTodayWeatherStateMsg 的作为 **NSString *** 的別名,并标记为 NS_STRING_ENUM,

接下来就如以下这样的代码去使用:

/// Sunny:晴天
FOUNDATION_EXPORT HPTodayWeatherStateMsg const HPTodayWeatherStateMsgSunny;

OK ,这就是字符串枚举的简单定义和使用了。

最佳方法

苹果文档推荐的方法:

You use the NS_TYPED_ENUM to group constants with a raw value type that you specify. Use NS_TYPED_ENUM for sets of constants that can't logically have values added in a Swift extension, and use NS_TYPED_EXTENSIBLE_ENUM for sets of constants that can be expanded in an extension.
Apple docs