美文网首页
Swift 枚举示例

Swift 枚举示例

作者: 大成小栈 | 来源:发表于2024-03-04 01:06 被阅读0次
1. 带关联属性的枚举

定义一个枚举类型:

    enum ContentState: Equatable {
        case `default`
        case text(text: String, language: String)
        case voice(path: String)
        
        var name: String {
            switch self {
            case .default:
                ""
            case .text:
                "text"
            case .voice:
                "voice"
            }
        }
    }

实例化一个枚举类型的变量:

var contentState: ContentState = .default

switch-case 一个枚举变量:

func updateTemplate(state: ContentState) -> Template? {
            guard let template else { return nil }
            switch state {
            case .default:
                break
            case let .text(text, language, voice):
                template.ptInfos = [PTInfo(audioUrl: "", context: text, voiceEgineId: voice?.engineId ?? "", type: state.name, language: language)]
            case let .audio(_, serverPath):
                template.ptInfos = [PTInfo(audioUrl: serverPath, context: "", voiceEgineId: "", type: state.name, language: "")]
                
            }
            return template
        }

其主要作用是,可携带多个关联属性,而enum中的“var name:”才是最终的枚举实际值。
注意:其中枚举的关联属性、关联参数的使用,对应和传递的恰到好处。

示例:

import Foundation

public enum AspectRatio {
    case original
    case freeForm
    case square
    case ratio(width: Int, height: Int)

    var rotated: AspectRatio {
        switch self {
        case let .ratio(width, height):
            return .ratio(width: height, height: width)
        default:
            return self
        }
    }

    var description: String {
        switch self {
        case .original:
            return "ORIGINAL"
        case .freeForm:
            return "FREEFORM"
        case .square:
            return "SQUARE"
        case let .ratio(width, height):
            return "\(width):\(height)"
        }
    }
}

// MARK: Codable

extension AspectRatio: Codable {
    enum CodingKeys: String, CodingKey {
        case description
    }

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        guard let desc = try container.decodeIfPresent(String.self, forKey: .description) else {
            self = .freeForm
            return
        }
        switch desc {
        case "ORIGINAL":
            self = .original
        case "FREEFORM":
            self = .freeForm
        case "SQUARE":
            self = .square
        default:
            let numberStrings = desc.split(separator: ":")
            if numberStrings.count == 2,
                let width = Int(numberStrings[0]),
                let height = Int(numberStrings[1]) {
                self = .ratio(width: width, height: height)
            } else {
                self = .freeForm
            }
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(description, forKey: .description)
    }
}

extension AspectRatio: Equatable {
    public static func == (lhs: AspectRatio, rhs: AspectRatio) -> Bool {
        switch (lhs, rhs) {
        case (let .ratio(lhsWidth, lhsHeight), let .ratio(rhsWidth, rhsHeight)):
            return lhsWidth == rhsWidth && lhsHeight == rhsHeight
        case (.original, .original),
             (.freeForm, .freeForm),
             (.square, .square):
            return true
        default:
            return false
        }
    }
}

// 调用
cropper.setAspectRatio(AspectRatio.ratio(width: ratioW, height: ratioH))
2. 普通的枚举

枚举中定义的是变量:

public enum Config {
    public static var croppingImageShortSideMaxSize: CGFloat = 1280
    public static var croppingImageLongSideMaxSize: CGFloat = 5120 // 1280 * 4

    public static var highlightColor = UIColor(red: 249 / 255.0, green: 214 / 255.0, blue: 74 / 255.0, alpha: 1)

    public static var resourceBundle = Bundle(for: CropperViewController.self)
}

// 用法
button.setTitleColor(ImageCropper.Config.highlightColor, for: .normal)

枚举定义错误,用于 throw :

enum AlertType {
        case alertStr1
        case alertStr2
    }

// 定义
enum Checked: Swift.Error {
    case network
    case paramsInvalid
    case alert(AlertType) // enum可嵌套啊!
}

// throw
private func preCheckNetwork() throws { // 网络判断
    guard HXNetworkingManager.checkNetworkEnable() else {
        throw Checked.network
    }
}

private func preCheckParams(_ config: SynthesizingConfig) throws { // 入参判断
    guard config.isValidFaceInfos() else {
        throw Checked.paramsInvalid
    }
}

// try-catch 刚刚定义的 throw 方法
do {
    // 可连续try 
    try preCheckNetwork()
    try preCheckParams(config)
    
    // 继续其他操作
    await start(with: navigationController, config: config, isNeedAD: false)
} catch Checked.network {
    await CommonAlertView(messageWaningOfflineAlert: ()).show()
} catch Checked.paramsInvalid {
    await MainActor.run {
        MBProgressHUD.showMessage("Please choose appropriate photo again.".localized)
    }
} catch {
    
}

基于moya-alamofire的api封装:

enum CreativeWorkAPI {
    
    /// 删除作品
    case delete(workId: String)
    
}

extension CreativeWorkAPI: APITarget {
    
    var route: APIRoute {
        switch self {
        case .delete:
            return .post("/work/delete_work")
        }
    }
    
    var parameters: APIParameters? {
        switch self {
        case let .delete(workId):
            return ["id": workId]
        }
    }
    
}

extension CreativeWorkAPI: APIProviderSharing {
    
    static var shared = APIProvider<CreativeWorkAPI>()
    
}

// 调用
// 服务端
CreativeWorkAPI.shared
    .publisher(.delete(workId: workId), type: APIEmptyResult.self)
    .loading("")
    .receive(on: DispatchQueue.main)
    .sink(
        // 回调
    )
    .store(in: &cancellables)

数据 model 的解析:

struct UserVoiceList: Decodable {
    
    @Default<Int> var createNumLeft: Int = 0
    @Default<[String]> var languageList: [String] = []
    @Default<[String]> var languageAlertList: [String] = []
    var voiceList: [VoiceItem]? = []
    
    private enum CodingKeys: String, CodingKey {
        case createNumLeft = "create_num_left"
        case languageList = "language_list"
        case languageAlertList = "language_alert_list"
        case voiceList = "voice_list"
    }
}

struct VoiceItem: Decodable {
    
    @Default<String> var audioId: String = ""
    @Default<String> var name: String = ""
    @Default<String> var audioUrl: String = ""
    @Default<String> var cover: String = ""
    @Default<String> var voicEngineId: String = ""
    @Default<String> var status: String = "" //"SUCCESS"  ||  "ERROR" || "DEMO_ERROR"
    
    let id = UUID()
    
    var isNew: Bool = false
    
    var audioState: VoiceAudioActionType = .paused
    
    private var _synthesisState: VoiceSynthesisStateType = .success
    var synthesisState: VoiceSynthesisStateType {
        get {
            if audioUrl.isEmpty {
                return status == "SUCCESS" ? .training : .failed
            } else {
                return _synthesisState
            }
        }
        set {
            _synthesisState = newValue
        }
    }
    
    private enum CodingKeys: String, CodingKey {
        case audioId = "audio_id"
        case name
        case audioUrl = "audio_url"
        case cover
        case voicEngineId = "voice_engine_id"
        case status
    }
    
    init() {
        
    }

}

枚举也是可以遵循协议:

protocol LogMonitorKeyProtocol where Self: RawRepresentable, RawValue == String {
    static var prefix: String { get }
}

extension LogMonitorKeyProtocol { // 协议还可以被扩展
    var value: String {
        "app_monitor" + "_dreamface_" + Self.prefix + "_" + self.rawValue
    }
}

struct LogMonitorKey {
        
    enum launch: String, LogMonitorKeyProtocol {
        static var prefix = "launch"
        case launch      // ✅
    }
    
    enum stable: String, LogMonitorKeyProtocol {
        static var prefix = "stable"
        case crash      // ✅
        case catch_crash      // ✅
        case stuck      // ❌
    }
    
    enum performance: String, LogMonitorKeyProtocol {
        static var prefix = "performance"
        case cpu      // ❌
        case memory      // ❌
    }
}

如果想兼容oc中的枚举:

@objc public enum PlayerState: Int {
    case resetted = 0
    case playing = 1
    case paused = 2
    case finished = 3
}

定义 enum 时,后面的关键字:

类型:空、Error、Int、String 等
协议:Equatable、Comparable、Identifiable、CodingKey、Hashable等

// 1. 以Identifiable协议为例
enum Sheet: String, Identifiable {
    case autoTranslate, speechVoice, languageMismatch
    
    var id: String { rawValue }
}

struct ContentView: View {
    let sheets: [Sheet] = [.autoTranslate, .speechVoice, .languageMismatch]

    var body: some View {
        List(sheets) { sheet in
            Text(sheet.rawValue)
        }
    }
}


// 2. 以Equatable协议为例
enum CropType: Equatable {
    case normal
    case bust(isPet: Bool)
    case aigcVideoPag(ratio: CGFloat)
    case aigcVideo(renderWidth: CGFloat)
    case aigcImagePag(ratio: CGFloat)
    // case aigcImage(renderWidth: CGFloat)
    case pag(ratio: CGFloat)
    case anything
    case aigc(ratio: CGFloat, isPickHead: Bool)
    
    var value: String {
        switch self {
        case .bust(let isPet):
            return isPet ? "pet" : "person"
        default:
            return "nothing"
        }
    }
    
    static func == (lhs: CropType, rhs: CropType) -> Bool {
        // 如果使用了value,作为最终值
        return lhs.value == rhs.value
        
        // 如果仍然按照类型、参数逐一比对
//            switch (lhs.value, rhs.value) {
//            case (.normal, .normal):
//                return true
//            case let (.bust(isPet1), .bust(isPet2)):
//                return isPet1 == isPet2
//            // ... 其他枚举成员的比较逻辑 ...
//            default:
//                return false
//            }
    }   
}
  • 对于 Identifiable :

在 Swift 中,Identifiable 是一个协议,它要求遵循它的类型必须提供一个属性 id,用于标识该类型的唯一性。通常,id 属性是一个可以唯一标识该类型的值,比如字符串、整数或者其他可哈希的类型。

在你的例子中,你的枚举类型 Sheet 遵循了 Identifiable 协议,并提供了一个计算型属性 id,该属性返回枚举成员的原始值(raw value)。这意味着每个枚举成员都有一个唯一的标识符,其取值即为对应的原始值。

这对于在 Swift 中使用涉及到 Identifiable 的视图或集合类型时非常有用。例如,如果你想要在 SwiftUI 中使用 List 或者 ForEach 来显示枚举类型的值,或者在其他需要唯一标识的场景中使用该枚举类型,遵循 Identifiable 协议可以使得操作更加方便。

  • 对于 Equatable:

在这个 CropType 枚举中,虽然它遵循 Equatable 协议,但并没有显式地提供对应的 static func == (lhs: Self, rhs: Self) -> Bool 方法。在 Swift 中,当你的类型遵循 Equatable 协议时,编译器会自动生成默认的相等性判断方法。这个默认的实现会逐一比较类型的每个成员。

在你的 CropType 中,由于每个成员都是可以比较的(例如,CGFloat 和 Bool 都是可比较的),Swift 编译器能够为你的枚举类型自动生成默认的相等性判断方法。

如果你的枚举类型包含自定义的非可比较类型成员,或者你希望进行更复杂的相等性判断,你可以选择手动提供 static func == 方法,覆盖默认的实现。

相关文章

网友评论

      本文标题:Swift 枚举示例

      本文链接:https://www.haomeiwen.com/subject/ycplzdtx.html