UIViewKit

UIViewKit 是一个 Swift 工具,它使得设计和设置 UIKit 视图就像使用 InterfaceBuilder 一样简单,但却拥有 Swift 强大的类型检查。它提供了类似于 SwiftUI 的外观,并具有许多用于属性、出口(outlet)和约束的简易方法。由于使用了 @resultBuilder 属性,代码编写速度更快,看起来更简洁,并且更赏心悦目。

主要特性

如何使用

定义 ViewController 的视图,带“Hello, world!”标签

class ViewController: UIViewController {

    var label: UILabel!
        
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view {
            UILabel().ibOutlet(&label).ibAttributes {
                $0.centerXAnchor.constraint(equalTo: view.centerXAnchor)
                $0.centerYAnchor.constraint(equalTo: view.centerYAnchor)
                
                $0.text = "Hello, world!"
            }
        }
    }
}

定义 ViewController 的视图,复杂示例

class ViewControllerComplex: UIViewController {
    
    var labelTitle: UILabel!
    var labelsText: [UILabel] = []
    var button: UIButton = .init()
    var heightConstraint: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view {
            UIStackView(axis: .vertical, spacing: 10, alignment: .center) { stackView in
                UILabel().ibOutlet(&labelTitle).ibAttributes {
                    $0.text = "Title"
                    $0.font = .init(name: "Arial", size: 30)
                }
                UIView() { superview in
                    UILabel().ibOutlet(in: &labelsText).ibAttributes {
                        $0.topAnchor.constraint(equalTo: superview.topAnchor)
                        $0.leftAnchor.constraint(equalTo: superview.leftAnchor)
                        $0.rightAnchor.constraint(equalTo: superview.rightAnchor)
                        $0.bottomAnchor.constraint(equalTo: superview.bottomAnchor)
                        
                        $0.text = "Label 1"
                        $0.textColor = .red
                    }
                }
                UILabel().ibOutlet(in: &labelsText).ibAttributes {
                    $0.text = "Label 2"
                }
                UIView().ibAttributes {
                    $0.leftAnchor.constraint(equalTo: stackView.leftAnchor)
                    $0.heightAnchor.constraint(equalToConstant: 50).ibPriority(.defaultHigh - 1).ibOutlet(&heightConstraint)
                    
                    $0.backgroundColor = .yellow
                }
                UILabel().ibAttributes {
                    $0.text = "Label 3 Without Outlet"
                }
                UIButton().ibOutlet(&button).ibAttributes {
                    $0.widthAnchor.constraint(equalToConstant: 300)
                    
                    $0.setTitle("Button", for: .normal)
                    $0.backgroundColor = .blue
                    
                    $0.addTarget(self, action: #selector(didTap), for: .touchUpInside)
                }
            }.ibAttributes {
                $0.centerXAnchor.constraint(equalTo: view.centerXAnchor)
                $0.centerYAnchor.constraint(equalTo: view.centerYAnchor)
            }
        }
        
        labelsText.forEach { $0.text = "toto" }
    }
    
    @objc func didTap() {
        print(#function)
    }
}

#if DEBUG

import SwiftUI

struct ViewControllerPreviews: PreviewProvider {
    static var previews: some View {
        IBRepresentableFreeFormViewController(ViewControllerComplex())
    }
}

#endif