氰化物 0.9.2

cyanic 0.9.2

Julio Alorro 维护。



 
依赖关系
LayoutKit>= 0
RxDataSources>= 0
RxSwift>= 0
Sourcery>= 0
 

cyanic 0.9.2

  • 作者
  • Feil, Feil, & Feil GmbH, Julio Alorro 和 Jonas Bark

Cyanic

Cyanic 是一个只为 iOS 平台开发的框架,由 Feil, Feil, & Feil GmbH 根据对状态驱动 UI 的需求创建。它大量借鉴了 Airbnb 的 MvRx 框架(我们的 Android 开发者正在使用这个框架)来创建一个与 Android 非常相似的代码库,从而统一了两个平台上的业务逻辑。我们使用这个框架来创建复杂、响应快且高性能的屏幕。

Cyanic 是一个完全使用 Swift 编写的框架。没有计划支持 Objective-C。

安装

CocoaPods

要求

  • Swift 5.0+
  • iOS 10.0+
  1. 将以下内容添加到您的 Podfile

    pod 'Cyanic'
    pod 'LayoutKit', :git => 'https://github.com/hooliooo/LayoutKit.git' // Use this fork until LayoutKit is updated
  2. 使用框架集成依赖项:在 Podfile 中添加 use_frameworks!

  3. 运行 pod install

为什么使用 LayoutKit 的分叉版本

LayoutKit 是负责 Cyanic 中大部分 UI 逻辑的库。然而,截至 2019 年 4 月 17 日,当前 LayoutKit 版本在 Cocoapods 中存在一些限制。

  1. 它并未更新以使用 Swift 5。
  2. Cyanic 需要访问允许您将 UIView 子类类型作为参数声明的 Layouts 内部初始化器。

如果不进行这些更改,Cyanic 将继续使用分支版本。

文档

请查看我们维基以获取完整文档。

简单示例

一个非常简单的带有可展开功能的示例

struct YourState: ExpandableState {
    
    enum Section: String, CaseIterable {
        case first
        case second
    }

    static var `default`: YourState { 
        return YourState(
            text: "Hello, World!",
            expandableDict: YourState.Section.allCases.map { $0.rawValue }
                .reduce(into: [String: Bool](), { (current: inout [String: Bool], id: String) -> Void in
                    current[id] = false
                }
        ) 
    } 

    var text: String
    var expandableDict: [String: Bool]
}

class YourViewModel: ViewModel<YourState> {
    func showCyanic() {
        self.setState { $0.text = "Hello, Cyanic!" }
    }
}

class YourComponentViewController: SingleSectionCollectionComponentViewController {
    
    private let viewModel: YourViewModel = YourViewModel(initialState: YourState.default)
    
    override var viewModels: [AnyViewModel] {
        return [self.viewModel.asAnyViewModel]
    }
    
    override func buildComponents(_ componentsController: inout ComponentsController) {
        withState(self.viewModel) { (state: YourState) -> Void in
            componentsController.staticTextComponent {
                $0.id = "title"
                $0.text = state.text
            }
            
            componentsController.buttonComponent {
                $0.id = "button"
                $0.onTap = { [weak self]
                    self?.viewModel.showCyanic()
                }
            }
            
            let firstExpandableID: String = YourState.Section.first.rawValue
            
            let yourExpandable = components.expandableComponent { [weak self] in
                guard let s = self else { return }
                $0.id = firstExpandableID
                $0.contentLayout = LabelContentLayout(text: Text.unattributed("Hello, World!"))
                $0.isExpanded = state.expandableDict[firstExpandableID] ?? false
                $0.setExpandableState = self.viewModel.setExpandableState
                $0.backgroundColor = UIColor.lightGray
                $0.height = 55.0
            }
            
            // These ButtonComponents will only show up when yourExpandable is expanded.
            if yourExpandable.isExpanded {
                for number in 1...5 {
                    componentsController.buttonComponent {
                        $0.id = "button\(number)"
                        $0.title = "\(number)"
                        $0.onTap = { [weak self]
                            print("Hello, World from Button \(number)")
                        }
                    }
                }
            }
        }
    }
}

贡献者