一个用于使用可重用组件创建用户界面的 Swift 库。
Blocks 是一个 Swift 库,用于简化 iOS 应用程序中用户界面的创建。它允许开发者在同一个 UITableView 中使用 SwiftUI 组件和传统的 UITableView cells、headers 和 footers。这种方法方便了声明性 UI 的构建,同时保持了在必要时编写自定义代码的灵活性。受 React 启发,Blocks 鼓励开发可重用组件,促进更抽象和模块化的代码,这在大型和复杂项目中尤其有益。该库利用 UIKit 的 UITableView 作为组件的容器来渲染,并支持 MVVM 设计模式。
您可以使用以下任一方式安装 Blocks...
将以下行添加到您的 Podfile 中,并在终端中运行 pod install
pod 'Blocks', '~> 0.0.1'
将以下行添加到您的 Carthage,并在终端中运行 carthage update
github "billp/Blocks" ~> 0.0.1
转到 文件 > Swift 包 > 添加包依赖项,并添加以下 URL
https://github.com/billp/Blocks
通过将其初始化器中的 table view 实例传递给一个新的 TableViewRenderer 实例来创建一个新TableViewRenderer实例。
// Create a lazy var for UITableView. You can also create the TableView in any way you want (Storyboard, Nib, etc.)
lazy var tableView: UITableView = {
let tableView = UITableView()
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
view.topAnchor.constraint(equalTo: tableView.topAnchor),
view.leftAnchor.constraint(equalTo: tableView.leftAnchor),
view.bottomAnchor.constraint(equalTo: tableView.bottomAnchor),
view.rightAnchor.constraint(equalTo: tableView.rightAnchor),
])
return tableView
}()
// Create the Table View renderer and pass it a UITableView instance.
lazy var renderer = TableViewRenderer(tableView: tableView)
Blocks 通过定义符合 Component
协议的视图模型来启用创建灵活和可重用的 UI 组件。这些组件可以使用各种视图类型进行渲染,包括传统的 nib 文件(用于 UITableViewCell
和 UITableViewHeaderFooterView
),基于类的视图(用于无 nib 初始化),或 SwiftUI 类类型。这种方法允许在应用程序的 UI 中集成 UIKit 和 SwiftUI 元素,为 UI 开发提供了一整套灵活的工具。
定义一个符合 Component
协议的视图模型。
struct EmptyResultsComponent: Component {
var title: String
}
实现一个符合 ComponentViewConfigurable
的 UITableViewCell
子类,用于使用视图模型配置单元格。
class EmptyResultsViewCell: UITableViewCell, ComponentViewConfigurable {
@IBOutlet weak var resultLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
selectionStyle = .none
}
func configure(with viewModel: any Component) {
guard let component = viewModel.as(EmptyResultsComponent.self) else { return }
resultLabel.text = component.title
}
}
关联 xib 文件: EmptyResultsViewCell.xib
。
将组件注册到渲染器来连接视图模型和相应的视图。
renderer.register(viewModelType: EmptyResultsComponent.self, nibName: String(describing: EmptyResultsViewCell.self))
此注册方法适用于使用 nib 文件的头和脚部。
创建一个包含 SwiftUI 视图所用的属性的符合 Component
协议的视图模型。
class TodoComponent: ObservableObject, Component {
var id: UUID = .init()
@Published var title: String
init(title: String) {
self.title = title
}
}
构建一个符合 ComponentSwiftUIViewConfigurable
的 SwiftUI 视图,使用视图模型进行 UI 配置。
import SwiftUI
struct TodoView: View, ComponentSwiftUIViewConfigurable {
@ObservedObject private var viewModel: TodoComponent
init(viewModel: any Component) {
self.viewModel = viewModel.as(TodoComponent.self)
}
var body: some View {
// SwiftUI view layout using viewModel properties
}
}
SwiftUI 组件通过渲染器进行注册,以将视图模型与其 SwiftUI 视图连接起来,确保在基于 UIKit 的表格或集合视图中正确管理和渲染。
renderer.register(viewModelType: TodoComponent.self, viewType: TodoView.self)
本策略用于定义和注册组件,为构建应用的UI提供了一种模块化和可重用的方法,充分利用了UIKit和SwiftUI框架的优点。
要使用renderer.updateSections更新UI,将TodoComponent与示例数据相结合,并使用EmptyResultsComponent处理空状态,可以遵循以下简化的步骤:
// Example method to update sections with todos and handle empty states
private func updateUI(withActiveTodos activeTodos: [TodoComponent], completedTodos: [TodoComponent]) {
let activeSectionRows: [any Component] = activeTodos.isEmpty ? [EmptyResultsComponent(title: "No active todos.")] : activeTodos
let completedSectionRows: [any Component] = completedTodos.isEmpty ? [EmptyResultsComponent(title: "No completed todos.")] : completedTodos
let sections = [
Section(id: "activeTodos", rows: activeSectionRows),
Section(id: "completedTodos", rows: completedSectionRows)
]
renderer.updateSections(sections, animation: .fade)
}
// Sample usage with active and completed todos
private func sampleUpdate() {
let activeTodos = [
TodoComponent(title: "Buy groceries"),
TodoComponent(title: "Read a book")
]
let completedTodos = [
TodoComponent(title: "Workout"),
TodoComponent(title: "Call mom")
]
updateUI(withActiveTodos: activeTodos, completedTodos: completedTodos)
}