StackUI 0.0.16

StackUI 0.0.16

pujiaxin 维护。



StackUI 0.0.16

  • 作者:
  • pujiaxin33

StackUI

中文文档

SwiftUI 一样使用 UIStackView

使用 @propertyWrapper@resultBuilder、链式语法以及 SwiftUI 中使用的其他特性,使 UIStackView 更容易使用。对于如 LabelButtonImageView 这样的类,仍然使用 UIKit,但通过链式语法进行了封装。

由于 SwiftUI 需要 iOS 13+ 系统才能使用,因此几乎不可能在实际项目中使用 SwiftUI。但 SwiftUI 的特性确实很吸引人,所以 StackUI 是在 UIStackView 范围内实现的 SwiftUI。您可以在 StackUI 中体验一些 SwiftUI 的特性,这样您就可以尽早学习新特性。

如果您厌倦了配置 UIKit 的约束,那么 StackUI 将为您提供很好的帮助。声明式布局让世界更美好。

特性

  • 类似 SwiftUI 的声明式语法;
  • 数据驱动 UI,更新数据后 UI 自动更新;
  • 支持 HScrollStackVScrollStack,当内容超出堆栈的宽度和高度时,自动开启滚动;
  • 链式语法配置 UIKit;
  • 可以灵活扩展自定义类以支持 StackUI

要求

  • iOS 9.0+
  • XCode 13.0+
  • Swift 5.4+

安装

CocoaPods

target'<Your Target Name>' do
    pod'StackUI'
    //If you want to use RxSwift
    pod'StackUI/RxSwift'
end

首先执行 pod repo update,然后执行 pod install

SPM

  • 文件 > Swift 包 > 添加包依赖
  • 添加 https://github.com/pujiaxin33/StackUI.git
  • 使用 "0.0.5" 选择 "到下一个主要版本"}
  • 如果您想使用 RxSwift 特性,选择 StackUISwithRxSwift 产品

示例

HStack

    HStack(alignment: .center, spacing: 5) {
        ImageView().image(UIImage(named: "avatar")).size(width: 40, height: 40)
        Label("user nickname").font(.systemFont(ofSize: 18, weight: .medium))
    }

VStack

    VStack {
        Label("user nickname").font(.systemFont(ofSize: 18, weight: .medium))
        Label().text("The user is lazy, nothing left!").font(.systemFont(ofSize: 12)).textColor(.gray)
    }

HScrollStackForIn

    var users = [UserModel]()
    for index in 0...25 {
        let model = UserModel(avatar: "avatar", name: "user\(index)", desc: "user description\(index)")
        users.append(model)
    }
    HScrollStack() {
        for model in users {
            HStack(alignment: .center, spacing: 5) {
                Spacer(spacing: 12)
                ImageView().image(UIImage(named: model.avatar)).size(width: 80, height: 80)
                VStack {
                    Label(model.name).font(.systemFont(ofSize: 18, weight: .medium))
                    Label().text(model.desc).font(.systemFont(ofSize: 12)).textColor(.gray)
                }
                Divider()
            }.size(width: 300)
        }
    }

@Live

在属性前添加 @Live,在使用时添加 $ 前缀。在更新属性时,关联的 UIKit 会自动更新界面。

    //definition
    @Live var nickName: String? = "User nickname"
    @Live var desc: String? = "The user is lazy, and nothing is left!"
    
    //use
    HStack(distribution: .equalCentering, alignment: .center) {
        HStack(alignment: .center, spacing: 5) {
            ImageView().image(UIImage(named: "avatar")).size(width: 40, height: 40)
            VStack {
                Label($nickName).font(.systemFont(ofSize: 18, weight: .medium))
                Label().text($desc).font(.systemFont(ofSize: 12)).textColor(.gray)
            }
        }
        ImageView().image(UIImage(named: "arrow_right"))
    }
    
    //update
    nickName = "Jay Chou"
    desc = "Ouch, not bad ❤️"

RxSwiftDriver

    //definition
    var nickName = PublishSubject<String?>()
    var desc = PublishSubject<String?>()
    
    //use
    HStack(distribution: .equalCentering, alignment: .center) {
        HStack(alignment: .center, spacing: 5) {
            ImageView().image(UIImage(named: "avatar")).size(width: 40, height: 40)
            VStack {
                Label(nickName.asDriver(onErrorJustReturn: nil)).font(.systemFont(ofSize: 18, weight: .medium))
                Label().text(desc.asDriver(onErrorJustReturn: nil)).font(.systemFont(ofSize: 12)).textColor(.gray)
            }
        }
        ImageView().image(UIImage(named: "arrow_right"))
    }
    
    //update
    nickName.onNext("Jay Chou")
    desc.onNext("Ouch, not bad ❤️")

自定义视图支持 StackUI

您可以自定义父类

ViewLabel 等继承,然后扩展自定义属性。

class CustomView: View {
    var customColor: UIColor = .black
    
    func customColor(_ customColor: UIColor) -> Self {
        self.customColor = customColor
        self.backgroundColor = customColor
        return self
    }
}
class CustomLabel: Label {
    var customColor: UIColor = .black
    
    func customColor(_ customColor: UIColor) -> Self {
        self.customColor = customColor
        self.textColor = customColor
        return self
    }
}

如果语句

     var isShowInfo: Bool = false
     HStack(distribution: .equalCentering, alignment: .center) {
         HStack(alignment: .center, spacing: 5) {
             ImageView().image(UIImage(named: "avatar")).size(width: 40, height: 40)
             if self.isShowInfo == true {
                 VStack {
                     Label("User nickname").font(.systemFont(ofSize: 18, weight: .medium))
                     Label().text("The user is lazy, nothing left!").font(.systemFont(ofSize: 12)).textColor(.gray)
                 }
             }else {
                 Label("No Information")
             }
         }
         ImageView().image(UIImage(named: "arrow_right"))
     }

父类不可修改,则符合协议

符合如 StackUIViewStackUILabel 的协议,然后扩展自定义属性。

class CustomViewFromProtocol: UIView, StackUIView {
    var customColor: UIColor = .black
    
    func customColor(_ customColor: UIColor) -> Self {
        self.customColor = customColor
        self.backgroundColor = customColor
        return self
    }
}
class CustomLabelFromProtocol: UILabel, StackUILabel {
    var customColor: UIColor = .black
    
    func customColor(_ customColor: UIColor) -> Self {
        self.customColor = customColor
        self.textColor = customColor
        return self
    }
}

链式语法暂不支持属性配置

通过应用闭包进行统一配置

HStack(alignment: .center, spacing: 5) {
     Label().text(model.desc).apply {label in
         //If there are attributes that are not defined by the chain syntax, they can be configured in the apply closure, or they can be submitted to Issue for support.
         label.font = UIFont.systemFont(ofSize: 10)
         label.textColor = .gray
     }
}

ViewBox 使用

有时视图需要外边距。此时,您可以将在 ViewBox 中的视图,并设置填充,这样就可以间接设置视图的上、下、左、右边距。如下代码所示:Label 的边距为 top: 10, left: 20, bottom: 10, right: 20

ViewBox(paddings: .init(top: 10, left: 20, bottom: 10, right: 20)) {
     Label("Hobbies: writing code;").font(. systemFont(ofSize: 15)).numberOfLines(0)
}.backgroundColor(.lightGray)

当前支持的类

  • Layer:在 View 类中配置 Layer 的相关属性
  • View
  • ImageView
  • Control
  • Label
  • Button
  • TextField
  • 文本视图
  • 步进器
  • 切换UI
  • 页面控制
  • 滑动条
  • 间隔空间
  • 分隔线
  • 活动指示器
  • 滚动视图
  • 表格视图
  • 收集视图

如果需要支持其他类和属性,请提交问题或拉取请求。