ViewDSL 0.0.6

ViewDSL 0.0.6

Muhammad Muizzsuddin 维护。



ViewDSL 0.0.6

  • 作者
  • Muhammad Muizzsuddin

ViewDSL

深受 UIKitDSL 启发,但希望添加一些功能。

您是否知道 Anko?这就是将 DSL 作为一等公民的美妙之处。

CocoaPod

ViewDSL 可通过 CocoaPod 获取!太棒了!

pod "ViewDSL"

约束?

不,ViewDSL 不为您处理约束。它让您选择任何可用的约束方法或者使用其他第三方库。

基本 DSL

使用 ViewDSL,您可以以声明的方式构建 UI。

UIView().add { (v: UIView) in
  
}

不幸的是,ViewDSL 迫使我们显式声明要添加实例的类型。这并不比 UIKitDSL 好多少。我同意。

让我们看看下面的例子。ViewDSL 为您提供了以一些有趣的方式来初始化您的 UIView 的功能。

class EqualStackView: UIStackView {
  func layoutSubviews() {
    super.layoutSubviews()
    distribution = .fillEqually
    spacing = 10
  }
}

let stack = EqualStackView { s in
  s.axis = .vertical
  
  s.add { (s: EqualStackView) in
    s.axis = .horizontal
    
    s.add { (b: UIButton) in
      b.setTitle("Yes", for: .normal)
      b.backgroundColor = .green
    }
    s.add { (b: CustomButton) in
      b.title = "No"
      b.bgColor = .red
    }
  }
}

这就是 ClosureInit 的力量!但您必须在您的自定义类中实现 init() 方法才能获得它的支持。很有趣,因为所有的 NSObject 类及其派生类都必须实现 init(),对吧?所以 UIView 类!

ViewDSL请求您显式地声明要添加的实例的类型,这使您有权使所有自定义类都能够无缝与ViewDSL一起工作。当然,您也可以自定义功能使您的DSL更类似Anko或UIKitDSL。

extension ViewDSL {
  @discardableResult
  func stack(_ closure: (UIStackView) -> Void) -> UIStackView {
     return add { (s: UIStackView) in
       closure(s)
     }
  }
}

提供给您UIKitDSL类似实现。但默认情况下并未将其包含在库中。您必须手动将其复制粘贴到您的应用程序中。所有方法前缀为u,表示它产生UIKit类实例。

DelegatedDSL

您想将您的通用按钮分离出来以供以后重用?遇见DelegatedDSL了!

// Look Here I'm using my custom DSL from previous code
view.stack {
  $0.axis = .vertical
  
  // And I want to added by common button to current view
  $0.dsl(delegatedTo: blueButton(_:))
}

// I'm using function to put my common button implementation
func blueButton(_ dsl: ViewDSL) {
    dsl.add { (b: UIButton) in
        b.backgroundColor = .blue
    }
}

LayoutBuilderDSL

如果需要将复杂的UI实现放入不同的文件中,此协议将适合您。

class ProfileLayout: LayoutBuilderDSL {
    let name: UITextField
    let email: UITextField
    let saveButton: UIButton

    init(name: String, email: String) {
        name = UITextField {
          $0.text = name
        }
        email = UITextField {
          $0.text = email
        }
        saveButton = UIButton {
          $0.setTitle("Save", for: .normal)
        }
    }

    func layout(_ dsl: ViewDSL) {
        dsl.add(name)
        dsl.add(email)
        dsl.add(saveButton)
    }
}

stack.dsl(delegatedTo: ProfileLayout(name: "Egg-boy", email: "[email protected]"))

如果您想使用*.self样式,可以实现InitializableLayoutBuilderDSL

extension ProfileLayout2: ProfileLayout, InitializableLayoutBuilderDSL {
  init() {
    super.init(name: "", email: "")
  }
}

stack.dsl(withInstanceOf: ProfileLayout2.self)

太棒了!

您也许可以在示例项目中找到它!试试看!

支持第三方库

此库AloeStackView模拟了UIStackView并增加了功能。它是UIScrollView的子类,使得默认的ViewDSL.put(_:)实现对UIView或UIStackView无效。您应自行支持它。这可能吗?

在进行之前,您可能想阅读这篇帖子Swift中覆盖协议扩展的默认实现

ViewDSL使用动态分发来确定要调用哪种put(_:)实现。由于协议及其要求都使用@objc,因此我们可以为AloeStackView覆盖put(_:)

extension AloeStaskView {
  @objc
  public override put(_ view: UIView) {
    addRow(view, animated: true)
  }
}

view.add { (aloe: AloeStackView) in
  aloe.add { (b: UIButton) in
    b.setTitle("Click Me!", for: .normal)
  }
}