Swift 声明式配置

Test SwiftPM 5.6 Platforms @capture_context

Swift 声明式配置 (简称 SDC) 是一个小型库,它使您能够以声明式、一致且易于理解的方式配置对象,并兼顾人体工程学。它可以用于在任何平台上配置任何对象,包括服务端 Swift。

产品

基本用法

更多内容请参见测试

没有 SDC

class ImageViewController: UIViewController {
  let imageView: UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFit
    imageView.backgroundColor = .black
    imageView.layer.masksToBounds = true
    imageView.layer.cornerRadius = 10
    return imageView
  }()
    
  override func loadView() {
    self.view = imageView
  }
}

FunctionalConfigurator

注意: 这种方式是 推荐的,但请记住,即使超类已经有无参数初始化器,自定义类型必须实现无参数初始化器,否则你会得到一个崩溃。

import FunctionalConfigurator

class ImageViewController: UIViewController {
  let imageView = UIImageView { $0 
    .contentMode(.scaleAspectFit)
    .backgroundColor(.black)
    .layer.scope { $0
      .masksToBounds(true)
      .cornerRadius(10)
    }
  }
    
  override func loadView() {
    self.view = imageView
  }
}

FunctionalBuilder

注意: 这种方式也推荐使用,而且更 安全,因为它修改的是现有对象。

import FunctionalBuilder

class ImageViewController: UIViewController {
  let imageView = UIImageView().builder
    .contentMode(.scaleAspectFit)
    .backgroundColor(.black)
    .layer.masksToBounds(true)
    .layer.cornerRadius(10)
    .build()
    
  override func loadView() {
    self.view = imageView
  }
}

FunctionalClosures

没有 SDC

声明

public class TapGestureRecognizer: UITapGestureRecognizer {
  var onTapGesture: ((TapGestureRecognizer) -> Void)?
    
  init() {
    super.init(target: nil, action: nil)
    commonInit()
  }
    
  override public init(target: Any?, action: Selector?) {
    super.init(target: target, action: action)
    commonInit()
  }
    
  private func commonInit() {
    self.addTarget(self, action: #selector(handleTap))
  }
    
  @objc private func handleTap(_ recognizer: TapGestureRecognizer) {
    onTapGesture?(recognizer)
  }
}

用法

let tapRecognizer = TapGestureRecognizer()

// handler setup
tapRecognizer.onTapGesture = { recognizer in
	// ...
}

// call from the outside
tapRecognizer.onTapGesture?(tapRecognizer)

使用 SDC

声明

public class TapGestureRecognizer: UITapGestureRecognizer {
  @Handler<TapGestureRecognizer>
  var onTapGesture
    
  init() {
    super.init(target: nil, action: nil)
    commonInit()
  }
    
  override public init(target: Any?, action: Selector?) {
    super.init(target: target, action: action)
    commonInit()
  }
    
  private func commonInit() {
    self.addTarget(self, action: #selector(handleTap))
  }
    
  @objc private func handleTap(_ recognizer: TapGestureRecognizer) {
    _onTapGesture(recognizer)
  }
}

用法

let tapRecognizer = TapGestureRecognizer()

// handler setup now called as function
tapRecognizer.onTapGesture { recognizer in
	// ...
}

// call from the outside now uses propertyWrapper projectedValue API, which is not as straitforward
// and it is nice, because:
// - handlers usually should not be called from the outside
// - you do not lose the ability to call it, but an API tells you that it's kinda private
tapRecognizer.$onTapGesture?(tapRecognizer)

您还可以使用 Configurator 创建这样的实例

let tapRecognizer = TapGestureRecognizer { $0 
  .$onTapGesture { recognizer in 
    // ...
  }
}

更多

Builder

通过将初始值传递给构建器来定制任何对象

let object = Builder(Object())
  .property.subproperty(value)
  .build() // Returns modified object

对于类,您可以通过调用 apply 方法而不是 build 来避免返回值

let _class = _Class()
Builder(_class)
  .property.subproperty(value)
  .apply() // Returns Void

在 Builders 和 Configurators 中,您都可以使用作用域

let object = Object { $0
  .property.subproperty(value)
}

使您自己的类型符合 BuilderProvider 协议以访问 builder 属性。

import CoreLocation
import DeclarativeConfiguration

extension CLLocationCoordinate2D: BuilderProvider {}
// Now you can access `location.builder.latitude(0).build()`

Configurator

注意: 你的 NSObject 类 必须 实现 init() 才能使用 Configurators。 这是为方便你的代码库所做的一点点权衡,请参见tests 中的示例。

DataSource

OptionalDataSourceDataSource 类型与 Handler 非常相似,但如果 Handler<Input> 有点像 OptionalDataSource<Input, Void>,则第二个可能具有不同的输出类型。 用法相似,提供不同的类型只是为了更好的语义。

安装

基本

您可以通过将 DeclarativeConfiguration 作为软件包依赖项添加到 Xcode 项目。

  1. 文件 菜单中,选择 Swift Packages › 添加 Package Dependency…
  2. 在软件包存储库 URL 文本字段中输入 "https://github.com/makeupstudio/swift-declarative-configuration"
  3. 选择您需要的产品以将它们链接到您的项目。

推荐

如果您使用 SwiftPM 进行项目结构,请将 DeclarativeConfiguration 添加到您的软件包文件中。

.package(
  url: "git@github.com:capturecontext/swift-declarative-configuration.git", 
  .upToNextMinor(from: "0.3.0")
)

或者通过 HTTPS

.package(
  url: "https://github.com:capturecontext/swift-declarative-configuration.git", 
  .exact("0.3.0")
)

不要忘记目标依赖项

.product(
    name: "DeclarativeConfiguration", 
    package: "swift-declarative-configuration"
)

许可证

该库是在 MIT 许可下发布的。 有关详细信息,请参见LICENSE