NS_STRING_ENUM - ShenYj/ShenYj.github.io GitHub Wiki

NS_STRING_ENUM

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

Apple 建议弃用 NS_STRING_ENUM/NS_EXTENSIBLE_STRING_ENUM 而改用 NS_TYPED_ENUM/NS_TYPED_EXTENSIBLE_ENUM,本质上都一样, 就是一套旧的一套新的

  • 目前在最新的 SDK 中,无论你使用那种方式来定义,最终都是 NS_TYPED_ENUMNS_TYPED_EXTENSIBLE_ENUM

    // Note: NS_TYPED_ENUM is preferred to NS_STRING_ENUM
    #define NS_STRING_ENUM _NS_TYPED_ENUM
    // Note: NS_TYPED_EXTENSIBLE_ENUM is preferred to NS_EXTENSIBLE_STRING_ENUM
    #define NS_EXTENSIBLE_STRING_ENUM _NS_TYPED_EXTENSIBLE_ENUM
    
    #define NS_TYPED_ENUM _NS_TYPED_ENUM
    #define NS_TYPED_EXTENSIBLE_ENUM _NS_TYPED_EXTENSIBLE_ENUM
    

NS_STRING_ENUM 需要搭配 typedef 使用。

  • OCClass.h

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    typedef NSString * Week NS_STRING_ENUM;
    FOUNDATION_EXPORT Week const WeekMonday;
    FOUNDATION_EXPORT Week const WeekTuesday;
    FOUNDATION_EXPORT Week const WeekWendesday;
    FOUNDATION_EXPORT Week const WeekThursday;
    FOUNDATION_EXPORT Week const WeekFriday;
    FOUNDATION_EXPORT Week const WeekSaturday;
    FOUNDATION_EXPORT Week const WeekSunday;
    
    @interface OCClass : NSObject
    
    + (void)test_OCStringEnumFunc:(Week)week;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
  • OCClass.m

    #import "OCClass.h"
    
    NSString * const WeekMonday     = @"WeekMonday";
    NSString * const WeekTuesday    = @"WeekTuesday";
    NSString * const WeekWendesday  = @"WeekWendesday";
    NSString * const WeekThursday   = @"WeekThursday";
    NSString * const WeekFriday     = @"WeekFriday";
    NSString * const WeekSaturday   = @"WeekSaturday";
    NSString * const WeekSunday     = @"WeekSunday";
    
    @implementation OCClass
    
    + (void)test_OCStringEnumFunc:(Week)week
    {
        NSLog(@"%@", week);
    }
    
    @end
    
  • OC 内使用

    .

    本质上还是一个别名,如图所示,我随意传递字符串是不会有任何报错的,不过在书写时还是提高了便利性,对具有指定的原始值类型的常量进行分组定义还是很不错的

  • Swift 混编中使用

    public class SwiftClass: NSObject {
        
        @objc
        static func swiftFunc() {
            OCClass.test_OCStringEnumFunc(.friday)
        }
    }

    如果 OC 中仍然使用 FOUNDATION_EXPORT NSString * const WeekMonday; 这种写法,那么在换到Swift中使用时也要使用 WeekMonday

  • 查看编译器为 Objective-C 接口自动生成的 Swift 接口

    选中 OCClass.h 文件,点击左上角的 Related Items 按钮,将光标移动到 Generated Interface 那一栏,右边就会出现不同版本的 Swift 接口文件。

    .

    选择一个点开后,就可以查看对应版本的 Swift 接口文件了

    查看编译器为 Objective-C 接口生成的 Swift 接口

    • e.g. OCClass.h (Swift 5 Interface)

      import Foundation
      
      public struct Week : Hashable, Equatable, RawRepresentable {
          public init(rawValue: String)
      }
      extension Week {
          public static let monday: Week
          public static let tuesday: Week
          public static let wendesday: Week
          public static let thursday: Week
          public static let friday: Week
          public static let saturday: Week
          public static let sunday: Week
      }
      
      open class OCClass : NSObject {   
          open class func test_OCStringEnumFunc(_ week: Week)
      }
  • Swift中为其扩展新增值

    public extension Week {
        // NS_TYPED_ENUM
        static var freeDay: Week { Week(rawValue: "WeekFreeDay") }
        // NS_TYPED_EXTENSIBLE_ENUM
        //static var freeDay: Week { Week("WeekFreeDay") }
    }
  • 在 OC 与 Swift 混编时带来的改善,可以阅读 字符串枚举

参考资料: Grouping Related Objective-C Constants

⚠️ **GitHub.com Fallback** ⚠️