开始之前...

这是一个正在进行中的项目,主要因为我感觉它仍然可以改进,并且尚未完全测试其用例。

TypeFamily

一个 Swift 包,以及一种创建类型组的方法,以便可以使用编译时检查来寻址它们。它可以用于类型擦除,在这种情况下,您始终可以返回到原始类型,因为您始终知道其特定类型的所有可能类型。如果添加了新类型,编译器会通知您是否有任何 switch 没有处理这个新的子类型。它通过 Swift 宏和一些协议来实现所有这些。

import TypeFamily

protocol ArtistGroup: TypeFamilyChild, Equatable {
    var memberCount: Int { get }
}

@TypeFamily(.keyPathed) @dynamicMemberLookup
enum MusicGroup: Equatable {
    typealias TypeChild = ArtistGroup
    
    @TypeFamilyChild
    struct Orchestra: TypeChild {
        let director: String
        let memberCount: Int
    }
    
    @TypeFamilyChild("popArtist")
    struct PopProducingTeam: TypeChild {
        let vocalist: String
        let presentedAsSolo: Bool
        let teamMembersCount: Int
        var memberCount: Int {
            presentedAsSolo ? 1 : teamMembersCount + 1
        }
    }
}

let presentations: [MusicGroup] = [
    .orchestra(.init(director: "A", memberCount: 20)),
    .popArtist(.init(vocalist: "B", presentedAsSolo: true, teamMembersCount: 20)),
]

for presentation in presentations {
    print("Members in main scenario: \(presentation.memberCount)")
    switch presentation {
    case .orchestra(let val):
        print("Everyone besides \(val.director) need to enter stage in advance")
    case .popArtist(let val):
        print("\(val.vocalist) needs help entering stage at the start of the show")
    }
    let value = presentation.childValue
    print(presentation == .wrapping(value)) // true
}

如何将其包含在我的项目中?

这是一个 Swift Package。如果您使用的是 Xcode 项目/工作区,请检查项目的 Package Dependencies,或者如果您正在编写 Swift Package,请检查您的 Package.swift 文件。 Xcode 将要求您启用 TypeAlias 的宏扩展。 这使得编译器生成代码,因此请启用它。 此外,某些版本的 Xcode 似乎需要重新启动(完全关闭 Xcode,再次打开 Xcode)才能识别宏。

使用方法

首先,声明父类型。 这将始终是一个 enum,并在其开头具有宏 @TypeFamily

@TypeFamily
enum ExampleParent {

}

编译器会要求您为子类型指定一个在它们之间共享的类型,在类型别名 TypeChild 下指定

protocol ExampleProtocol {
    var aMethodThatAllChilrenHave: Bool { get }
}
@TypeFamily
enum ExampleParent {
    typealias TypeChild = ExampleProtocol
}

现在您可以添加任何您需要的子类型。 子类型需要声明在父类型内部,以继承/遵守 TypeChild 协议,并具有宏 @TypeFamilyChild

// ...
    @TypeFamilyChild
    struct ExampleChild: TypeChild {
        let aMethodThatAllChilrenHave: Bool
        let somethingOnlyThisChildHas: Int
    }
// ...

... 就是这样!

宏生成的内容