美文网首页
iOS @resultBuilder 结果构造器

iOS @resultBuilder 结果构造器

作者: 迷路的小小 | 来源:发表于2023-01-31 10:01 被阅读0次

    @resultBuilder结果构造器,以注释器的方式优雅的实现工厂模式。
    类:

    struct Factory {
        var name: String
    }
    

    一、buildBlock(_:)

    @resultBuilder必须实现的方法,是结果构造器的主体方法;

    @resultBuilder
    struct FactoryBuilder {
        static func buildBlock(_ singles: Factory...) -> [Factory] {
            return singles
        }
        
        static func buildBlock(_ components: String...) -> [Factory] {
            return components.map({ Factory(name: $0) })
        }
    }
    

    用法:

    @FactoryBuilder
    static func factories() -> [Factory] {
        Factory(name: "option 1")
        Factory(name: "option 2")
    }
    @FactoryBuilder
    static func factoriesUseString() -> [Factory] {
        "option 1"
        "option 2"
    }
    

    二、buildEither(first:)buildEither(second:)

    此二方法需同时实现,主要用于实现if-elseswitch条件语句,如:

    static func buildEither(first component: [Factory]) -> [Factory] {
        component
    }
    static func buildEither(second component: [Factory]) -> [Factory] {
        component
    }
    

    用法:

    @FactoryBuilder
    static func factories() -> [Factory] {
      if flag1 == 0 {
        Factory(name: "option 1")
      } else {
        Factory(name: "option 2")
      }
    }
    

    三、buildArray(_:)

    此方法用于实现for、while等循环语句,如:

    static func buildArray(_ components: [[Factory]]) -> [Factory] {
        components.flatMap({ $0 })
    }
    

    使用时可以发现,Cannot pass array of type '[Factory]' as variadic arguments of type 'Factory'
    分析后可以看到,需要实现一个可以接收数组的buildBlock(_:)方法

    如:

    static func buildBlock(_ components: [Factory]) -> [Factory] {
        return components
    }
    

    但实际操作下来,使用协议统一传参是最好的方案,如:

    protocol Factoryer {
        var asFactories: [Factory] { get }
    }
    @resultBuilder
    struct FactoryBuilder {
        static func buildBlock(_ singles: Factoryer...) -> [Factory] {
            return singles.flatMap({ $0.asFactories })
        }
        
        static func buildArray(_ components: [[Factory]]) -> [Factory] {
            return components.flatMap({ $0 })
        }
    }
    

    用法:

    @FactoryBuilder
    static func factoriesUseArray() -> [Factory] {
        for i in 0..<3 {
            Factory(name: "option \(i)")
        }
    }
    

    四、buildOptional(_:)

    该方法主要用于实现可选项。如:

    • Factory对象非一定存在
    let flag1: Int = 0
    if flag1 == 0 {
       Factory(name: "option 1")
    }
    
    • Factory对象非一定存在,但存在else if
      需要注意的是,如果有二种以上的结果,需要同时实现buildEither(first:)buildEither(second:)。如:
    let flag1: Int = 0
    if flag1 == 0 {
       Factory(name: "option 1")
    } else if flag1 == 1 {
       Factory(name: "option 2")
    }
    

    五、buildExpression(_:)

    buildExpression(_:)会在buildBlock(_:)之前执行。
    它允许结果构建器区分表达式类型和组件类型,为语句表达式提供上下文类型信息。如:

    static func buildExpression(_ expression: String...) -> [Factory] {
        return expression.map({ Factory(name: $0) })
    }
    static func buildExpression(_ expression: Factoryer...) -> [Factory] {
        return expression.flatMap({ $0.asFactories })
    }
    

    用法:

    @FactoryBuilder
    static func factoriesUseString() -> [Factory] {
        "option 1"
        "option 2"
        "option 3"
    }
    

    六、buildLimitedAvailability(_:)

    用于将 buildBlock(_:) 在受限环境下(例如if #available)产生的部分结果转化为可适合任何环境的结果,以提高 API 的兼容性。

    七、buildFinalResult(_:)

    用于对最外层的 buildBlock(_:) 结果的再包装。例如,让结果构建器隐藏一些它并不想对外的类型(转换成可对外的类型)。

    相关文章

      网友评论

          本文标题:iOS @resultBuilder 结果构造器

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