StateView 2.0

StateView 2.0

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最新发布2016年9月
SPM支持SPM

Sahand Nayebaziz维护。



Views last updated: just now.

StateView是一个UIView替代品,当数据变化时,它会自动更新自己。

内容

概述

StateView是UIView的子类,它采用现代思维和灵感,从Facebook对React和DOM所做的工作中汲取灵感,使显示和更新视图变得更加简单、简单和愉快。

使用StateView……

  • 您的视图在数据发生变化时自动更新。
  • 在数据发生变化时,您的视图会自动添加、删除和更新其子视图。
  • 只有当它们需要时,您的视图才会更新自己。每个StateView都会在数据发生变化时计算一个差异(由名为Dwifft的出色包提供支持)来理解哪些子视图可以保留,哪些可以删除,哪些可以刷新。然后,您的StateView仅进行这些最小更改。
  • 您可以编写任何自定义视图作为StateView。
  • 您可以编写包含其他StateView、标准UIView或两者混合的StateView。
  • 您的StateView可以自动更新一个作为标准UIView的子视图,而无需任何新代码或在该UIView周围进行特殊包装。
  • 鼓励您在视图层次结构中的不同视图中保持状态。使用StateView管理此状态更为容易,无需考虑何时、何地以及如何调用诸如init、addSubview和removeSubview等方法。
  • 您无需重构应用程序,使其成为一个声明性、功能性的、事件流式、基于序列的、事件捕获的应用程序,即可享受响应性和所有都是其状态纯函数的视图家族的好处。

它是怎样的?

当您创建第一个StateView时,您将熟悉propsstaterender()

您可以使用props从一个StateView传递值到另一个StateView,使用state在StateView中私有地保持值,并使用render()来描述StateView的外观。StateView只是一个使用这三个来更新自己的UIView的子类,当您的数据发生变化时。

propsstate都允许类型为Any的值,以鼓励您保留和传递任何适用于您的值。

当您在render()内部向StateView添加第一个子视图时,您会熟悉place()的使用。

您可以使用place()将子视图添加到您的StateView中。然后,您的StateView将自动调用addSubviewremoveSubview,您无需手动操作。

render()中,只需查看您的state和任何传入的props,然后编写如下代码...

override func render() {

    if let selectedImage = self.state["selectedImage"] as? UIImage {
        place(ImageViewWithTags.self, "image") { make in
            make.size.equalTo(self)
            make.center.equalTo(self)
        }
    } else {
        place(PlaceholderImageView.self, "placeholder") { make in
            make.size.equalTo(self)
            make.center.equalTo(self)
        }
    }
}

如果在state中,键“selectedImage”包含一个UIImage,则放置一个‘ImageViewWithTags’,此键名为“image”,并提供一些AutoLayout约束(使用名为SnapKit的优秀库)。如果在state中,“selectedImage”为nil或完全缺失,则使用占位符ImageView代替。

简单地更新数据,视图将自动更新。

更改state中“selectedImage”的值,此StateView将显示或隐藏名为ImageViewWithTags的另一个自定义StateView。您的StateView将自动调用addSubviewremoveSubview以渲染更新的视图。

这样使用render()place(),是使用StateView最有趣的方面之一。

您用于决定添加到StateView的子视图的代码可以放在render()中,这将使数据更改时运行。然后,将render()的输出与上一轮render()的输出进行比较,您的StateView仅组成差异部分。

您可以使用props从一个StateView传递值到另一个StateView。您可以以此方式在StateView的state中传播新的数据到其子视图。在这个例子中,要将state中的新图片传递到ImageViewWithTags中,可以编写如下代码...

override func render() {

    if let selectedImage = self.state["selectedImage"] as? UIImage {
        let imageView = place(ImageViewWithTags.self, "image") { make in
            make.size.equalTo(self)
            make.center.equalTo(self)
        }
        imageView.prop(forKey: Home.image, is: selectedImage)
    } else {
        place(PlaceholderImageView.self, "placeholder") { make in
            make.size.equalTo(self)
            make.center.equalTo(self)
        }
    }
}

现在这个ImageViewWithTags实例将接收到props中的selectedImage。ImageViewWithTags可以访问selectedImage的新值,在任何方法中,特别是在其自己的render方法中更新一个UIImageView。

ImageViewWithTags可以通过使用在这里使用的相同键来访问selectedImage的值,即Home.image,这是一个枚举。您可以根据需要创建任意数量的自定义枚举来命名您的值。只要状态中的selectedImage有新的值,ImageViewWithTags就会接收到新值并更新自身。

放置函数中的第二个值是key,用于帮助理解渲染间相同视图。key的值可以是您想要的任何内容,只要那个StateView中的其他子视图没有相同的键。如果放置某个内容的key在渲染间发生变化,由于没有使用新的key放置的现有视图可以保留,StateView将从头开始渲染该子视图。

当您创建第一个StateView时,您将熟悉以下思路过程

  • 这个视图怎么变?我可以在state中留下变量来描述这些不同变化。
  • 现在在render()中,当state有该键的这个值时,我应该放置这个子视图,但如果它有该键的另一个值,我应该放置另一个。
  • 我可以列出我打算在这些视图间传递的所有值,这样我就可以在一个地方查看它们,并使其他人更容易理解应用程序中的数据流。
  • 该子视图将从父视图获取其props,因此我可以将此StateView接收到的两个props传递给该StateView。
  • 负责再次更改该state中值的代码是什么?哦,这里的回调。我应该在这个StateView的state中将此键的初始值添加,这样在回调返回之前,我的render就有了一个具体的使用来决定显示什么。
  • render中是否有其他我应该添加的内容?当我的数据显示这样而不是那样时,有没有需要在视图中微妙不同的地方?

有关StateView的完整文档和入门指南可在这里找到,以及入门指南

示例应用

Frame(Frame的GitHub链接)是使用StateView开发的首个应用。使用StateView,Frame只包含四个类,其中三个类的代码行数都不到一百行。

SwiftHub是一个iOS应用,用于展示GitHub上的Swift代码库。

它是如何工作的?

当您使用StateView时,有一个ShadowView在幕后帮助理解哪些子视图可以保留,哪些可以去除,以及哪些可以在调用render()之间进行刷新。

每个StateView实例都对应一个ShadowView实例,它使用轻量级的结构和引用来记录视图层次结构及其所表示的数据。

render()place()都紧密与StateView的ShadowView协作,以最少更改视图层次结构来更新屏幕上的显示。

当您的某个视图中的state发生变化时,ShadowView负责计算diff、添加或删除任何所需的或不再需要的子视图,并将props从StateView传递到其包含的StateView。

安装

您可以通过CocoaPods安装StateView。

pod 'StateView'

接下来是什么?

StateView旨在给iOS开发者提供一个安全、简单的方式来观察视图自行更新。最重要的是,目标是让StateView易于使用。

任何使StateView包含的方法、参数和模式更简单的努力都备受赞赏。同样,对StateView性能的提升也很受欢迎。

如果您想做出贡献,请查看wiki中已知的Issue列表,或在此项目的Issues中发起新的对话!

致谢

StateView由Sahand Nayebaziz编写。StateView受到了React和DOM的启发。

许可

StateView在MIT许可下发布。有关详细信息,请参阅LICENSE文件。