SymbiOSis 0.3.3

SymbiOSis 0.3.3

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
发布最后发布2015年4月

Dan HallDaniel Hall维护。



SymbiOSis 0.3.3

SymbiOSis 是一个受 MVVM 启发的框架,用于以更少的代码、更少的错误和更短的时间构建应用程序。

虽然 MVVM 致力于使用视图模型和绑定来创建更小、更简单的视图控制器,但现有 iOS 上对 MVVM 的实现存在很多问题

  • 视图控制器必须了解其视图模型的方法和属性,这使得它们紧密耦合。这意味着视图模型很难重用。
  • 试图让视图模型充当表格视图、收集视图等的数据源,将导致与单个视图控制器的耦合更加紧密。
  • 如果视图模型要重用,则视图控制器被迫具有相同的表现/格式化逻辑以使重用工作。或者,作为替代,每个视图模型都必须成为服务于多个视图控制器用例的庞大类。
  • 视图控制器中仍然有大量的粘合代码,用于 segue、IBAction 等,这些代码既难以测试,又无法重用。

Symbiosis 提供以下功能和优势

  • 您不必编写自定义视图控制器或视图模型,尽管您的应用程序仍然像往常一样使用故事板、场景和 segue。
  • 您不必再编写另一个 UITableViewDataSource、UITableViewDelegate 或另一个 UITableViewCell 子类,尽管您可以完全控制 UITableView、它们的样式、头部和尾部、原型单元格和内容,从故事板开始。
  • SymbiOSis 使用绑定和单向不可变数据以确保最大的安全性和最小的错误。改变数据源中的值,所有绑定到该数据源的标签、按钮、图像和其他视图都会自动并立即更新。
  • SymbiOSis 设计为与 Interface Builder 和故事板无缝协作。这允许视图容易被看到和修改,同时保持与其业务逻辑和其它代码完全解耦。使用 SymbiOSis 创建的每个组件都可通过 Interface Builder 连接起来(尽管如果您愿意,也可以通过代码创建连接)
  • 根据您的需要使用 SymbiOSis 的多少。没有任何强制要求您“全面投入”。相反,您可以使用 SymbiOSis 构建单个新的视图控制器/场景,或者逐渐将现有的场景转换过来。
  • SymbiOSis 架构促进最大程度的可测试性和可重用性。您使用 SymbiOSis 编写的应用程序代码容易测试,只需测试一次,而且它可以被像将组件拖放到故事板并连接插座一样轻松重用。
  • SymbiOSis基础框架旨在以任何方式扩展以满足您的需求。您可以添加或修改任何您希望的功能。

入门指南

这是对SymbiOSis框架和架构的简要概述。具体组件的更深入了解将添加到维基中。

除了本指南之外,还有一个完整的示例应用程序,它演示了如何使用SymbiOSis构建数据驱动的iOS应用程序。该示例应用程序的仓库位于此处

https://github.com/daniel-hall/SymbiOSisDemoApp

此外,代码在头文件中有完整的文档说明,或者在以下更整洁的版本中也可以找到:http://cocoadocs.org/docsets/SymbiOSis

关键概念

在MVVM中,视图模型的作用是持有视图控制器所需的所有数据,并对这些数据执行任何所需的转换(如格式化姓名或日期)。视图控制器仍然作为事件的接收者,负责管理转场等。

Symbiosis将这些责任拆分成更小且更明确的部分——具体来说:数据源、绑定和响应者。

数据源

在SymbiOSis中,数据源要么持有数据对象,要么持有数据对象数组。数据源只有一项必要的工作:检索和/或过滤数据,并设置数据到其“value”属性。只要数据源的“value”属性发生变化,相关的绑定就会自动更新视图以反映新值。

要创建自己的数据源,您需要创建一个SYMDataSource的子类,并用代码加载相关数据来重写-(void)awakeFromNib方法。例如:

@interface PhotosDataSource : SYMDataSource

@end

@implementation PhotosDataSource

-(void)awakeFromNib {
 NSArray *arrayOfPhotos = //Download a bunch of photos from a server or service;
 self.value = arrayOfPhotos;
}

@end

数据源只需要做到这些。

绑定

SymbiOSis框架中的第二种组件是绑定。绑定的作用是从数据对象转换或转换值到视图对象的属性或值。

例如,假设有一个名为“Person”的模型对象类,具有诸如firstName、middleName、lastName、age、height等属性。在应用程序内的不同位置,您可能希望根据该数据填充各种用户界面元素。也许应该有一个UILabel来展示用户的完整姓名(名字、中间名和姓氏)。可能还有一个看起来像垂直标杆的控件,带有滑动指示器来指示用户的高度。绑定将从Person对象中读取相关属性,并相应地配置标签和控件。

名为“PersonHeightYardstickBinding”的绑定可能看起来像这样:

@interface PersonHeightYardstickBinding : SYMBinding

@property (nonatomic) Person *value; //override the SYMBinding value property definition with the specific type of data object

@property (nonatomic, weak) IBOutlet YardstickView *view; //override the SYMBinding view property definition with the specific type of view to be updated

@end

@implementation PersonHeightYardstickBinding

-(void)update {
 [self.view setHeightInInches: self.value.height]; // remember that self.view is of the type YardstickView*, and self.value is of the type Person*, which give proper code completion and compiler checking here.
}

@end

以上是需要编写的所有代码。SYMBinding超类处理监视数据源变化并调用更新方法。要使用此绑定,您只需将一个此PersonYardstickBinding的实例添加到故事板中,以及一个具有Person对象作为其值的SYMDataSource的实例。当然,您还需要将YardstickView添加到场景中,并放置在您想要的位置。从那时起,只需从绑定的“dataSource”输出连接到数据源,并从绑定的“view”输出连接到YardstickView。从那时起,每当Person发生变化时,绑定将自动更新Yardstick视图以反映应显示的当前高度。

请注意,在这种特定的架构安排中,视图本身并不知道它是如何或从哪里获取其值的。这些“愚昧视图”非常适合轻松重用或用不同的值重新填充,而无需对代码进行任何修改。

绑定集

对于数据对象(如上面的“Person”示例)有许多可能的绑定是非常常见的。可能会有用年龄、姓名等填充标签的绑定,以及将视图的背景颜色设置为匹配某个人的最喜欢的颜色等。为了简化使用和重用绑定,建议您创建“绑定集”来收集相关的绑定。

绑定集是SYMBindingSet的子类,它具有与常规绑定相同的数据源。但是,绑定集公开了许多不同的视图出口或出口集合,并将它们映射到集合内收集的各个绑定。这种方式,您不需要将多个绑定放置在Storyboard中,例如PersonFirstNameLabelBinding,PersonFullNameLabelBinding,PersonAgeLabelBinding和PersonHeightYardstickViewBinding,然后将它们绑定到相同的数据源及其相应的视图,而是在Storyboard上放置一个“PersonBindingSet”,将其连接到一个Person数据源,然后将绑定集的属性/出口连接到每个相关的视图。例如,绑定集将包含firstNameLabel,fullNameLabel,ageLabel和yardstickView的出口,并将通过接口构建器与场景中匹配的标签和视图连接起来。

响应器

SymbiOSis中的响应器封装了一个单例例程或方法,该方法会根据某些用户的交互运行。响应器可能执行的操作示例包括:当按下“完成”栏按钮项时关闭模态视图控制器,当触摸按钮时拨打电话号码或链接到网页,从屏幕上的文本字段或控件中收集信息并将值发送到数据库,当用户按下或与屏幕上的特定项交互时提交分析事件。

尽可能使用响应器而不是在视图控制器中使用IBActions(尽管响应器可以包含IBActions)。这样做的原因是可重用性。当视图控制器加载了IBActions和响应用户交互的代码时,通常需要将相同的代码复制和粘贴或重新创建在具有类似功能的其他视图控制器中。但是,当每个行为都被封装进SYMResponder子类时,这些行为可以通过将响应器作为自定义对象放入Storyboard来重复使用,并将其连接到控制事件、栏按钮项等。