iOS @resultBuilder 结果构造器

2023-01-31  本文已影响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(_:)

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

let flag1: Int = 0
if flag1 == 0 {
   Factory(name: "option 1")
}
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(_:) 结果的再包装。例如,让结果构建器隐藏一些它并不想对外的类型(转换成可对外的类型)。

上一篇下一篇

猜你喜欢

热点阅读