Blaze
使用 Blaze,我开发应用程序的速度比平常快70%。Blaze 不只是一个用于单一任务的框架,它是为开发应用程序而创建的大型的框架,可以快速开发应用程序。
何时应该使用 Blaze?
- 当你对设计师没有考虑较小的设备而感到厌烦时,因此每个屏幕都需要可滚动,从而产生了这个需求
- 当你喜欢自动布局(不在代码中)并想尽可能多地使用它
- 当你创建了很多具有不同设计的应用程序,你需要高度灵活性来支持这些设计
- 当你有文本框,而且你厌倦了确保键盘不会重叠文本框
- 当你厌倦了反复编写相同的样板代码
Blaze 已经有多版本了,但最终版本太棒了,以至于我(以及我所在的公司中的每个人)在每个应用程序的每个屏幕上都使用 Blaze 并且无法想象不再使用 Blaze。想了解我是如何创建 Blaze 以及它如何达到这一最终版本的完整故事?请点击这里阅读我的关于 Blaze 的博客!
非常简短的版本
- 新 iPhone6 和 6+ 尺寸引发了设计变更。设计师开始使用 iPhone6 作为基础分辨率进行设计。
- 这导致了问题,99% 的屏幕无法适应 iPhone4,因此几乎每个屏幕都需要可滚动。
- 在界面构建器中使用滚动视图进行自动布局是非常 惊人的。所以我必须使用集合视图或表视图,然后在单元格中使用自动布局。
- 只要设置好约束,UITableviewCells 与 UITableViewAutomaticDimension 结合起来是非常棒的。不幸的是,在集合视图中,这些自动维度计算仍然太 Buggy... 所以 UITableView 就是吧!
- 我不想使用像TPKeyboardAvoiding这样的框架来通过滚动内容避免键盘重叠,也不想自己编写版本,因为这太过脆弱,而且从未能够100%正确工作。因此,我不能使用包含table view的自定义UIViewController。UITableViewController自带完美的向上滚动内容功能,这样键盘就不会覆盖输入字段。所以,就是
UITableViewController
! - 因此,我开始为每个屏幕使用UITableViewController!(或者对于在某个地方始终可见的按钮的屏幕,使用-containing views)
- 结果是,我对于每个屏幕的庞大模板代码量感到烦恼...
- 我检查了可用的“表单框架”,这些框架可以快速基于对象创建table view controllers。但大多数这些问题框架都没有在Interface Builder中进行自定义设计的选择。常常,你所能做的就是通过代码更改标签的字体。但是,我必须创建具有如此不同设计的应用程序,因此我需要最高灵活性。另一方面,这些框架常常不兼容动态单元。例如,我需要一个当在单元格中的一个UISwitch上下文切换时,另一个单元格动态添加/删除的功能。
- 结论 - 我不得不创建自己的框架!所以我创建了Blaze,加入了许多疯狂快速的功能,我很难想象没有它的生活:
关于文档的说明
由于我一直在专注于开发,文档有点落后。我肯定会继续在接下来的几周内改进它!
基本功能
首次使用 CocoaPods 安装它
pod 'Blaze'
那么接下来做什么?
您通过创建BlazeTableViewController
的子类来使用Blaze。Blaze的基本思想是可以创建多个指向同一代码的XIB。是的,这是可能的,也是很棒的事情 :) 我有时需要创建有大量输入字段的App,所以我创建了几种基础输入单元格,您可以将XIB文件指向它们。就像上面说的,我这样设置是为了您能够有任何疯狂的设计,但仍然不需要编辑任何代码。因此,您可以创建XIB文件,并且玩转自动布局,这对很多人来说很有趣,对吧?所以,我为以下内容创建了基础单元格代码
- UITextField输入
- UITextView输入(是的,当输入很多时,自动增加行高)
- UISwitch输入
- UISlider输入
- UIDate输入(在键盘的inputView中使用)
- UIPickerview 输入(在键盘中使用 inputView)
- UISegmentedControl 输入
- 勾选输入
- 两个选项输入(例如选择性别 - 男性/女性)
- 等等,列表随我输入而增长 :)
Blaze 最酷的功能之一是,它可以根据 Xib 名称自动知道使用哪种代码为单元格。这是因为 XIB 可以指向你想要的任何代码文件,XIB 的名称不需要与代码文件同名。上面所有这些输入单元格都有强大的完成代码块,你不需要编写任何代码,就像 UITextField 代理一样。关于这一点,我稍后会详细说明。
我还发现,我常用的单元格没有输入。可能只是一个标签或两个和一些 imageView,也许是一个按钮。因此,我创建了一个基单元格 BlazeTableViewCell,它是所有输入单元格的子类。它有很多出口让你可以选择连接。目前支持:
- 3 个 UILabel(支持普通文本和属性文本)
- 3 个 UIImageView(支持 UIImage、NSData 和 NSURL - 对于 URL,它使用来自 AFNetworking 的令人惊叹的 UIImageview 分类)
- 3 个 UIView(支持 UIColor)
- 3 个 UIButton(当然带有完成代码块)应该覆盖大多数单元格了?你只需在 Interface Builder 中连接必要的 IBOutlets,忽略那些不使用的即可。如前所述,所有输入单元格都是这个类的子类,所以你总是会有一系列出口可用!如果这些出口不足以满足你超定制的单元格,你可以使用一个返回 UITableViewCell 的强大完成代码块来自定义它(请阅读后面的代码示例)
如何实际使用它?
我建议首先创建一个名为 BaseTableViewController 的子类,然后为你的应用程序中的每个屏幕创建此类的子类。这样,如果你有某些部分高度,你只需在一个位置设置即可。此外,你可以在一个地方注册所有在不同屏幕中使用的服务器单元格。
然后当你创建你的屏幕时,你可以使用几行创建部门和行。
BlazeSection *section = [[BlazeSection alloc] initWithHeaderXibName:xibName title:@"Title"];
[self addSection:section];
BlazeRow *row = [[BlazeRow alloc] initWithXibName:xibName title:@"Title"];
[section addRow:row];
就这样,你只用创建了一个带有部分标题和一个单元格的整个屏幕。这就是为简单单元格所需的所有代码。当然,还有大量关于 BlazeSection 和 BlazeRow 的附加选项。部分可以有标题和脚本文本以及 xib 名称,而行有众多选项,可以针对所有可能的单元格类型进行设置,对于文本字段,你可以设置键盘类型、大小写类型等。这里有更多示例(但一定要查看示例项目!)
无输入的静态单元格
如果你有不会重用的单元格,只需创建和设计 XIB,指向 BlazeTableViewCell 类即可。然后它只需一行代码
[section addRow:[BlazeRow rowWithXibName:xibName]];
不带输入的可重复使用的单元格
对于不带输入的可重复使用的单元格,您始终应该创建一个指向基本 BlazeTableViewCell 的 XIB 文件。然后在界面构建器中正确分配标签/图像,并按照以下方式设置行
BlazeRow *row = [BlazeRow rowWithXibName:xibName];
row.imageNameLeft = @"PictureImageFromBundle";
row.title = @"Title for the cell";
row.subtitle = @"Subtitle";
row.imageURLRight = @"Url for the image on the right";
[section addRow:row];
如果您对按钮或单元格选择具有操作,您可以添加简单的完成块
[row setButtonCenterTapped:^{
//Button tapped!
}];
[row setCellTapped:^{
//Cell tapped!
}];
带有输入/值的单元格
对于带有输入的单元格,您应首先检查 Blaze 是否已支持输入类型。大多数基本输入类型,如 UITextfield、UITextView、UISwitch 等,已支持并在代码中创建。因此,您只需创建 XIB、分配 IBOutlets 并指向正确的类即可。所有受支持的输入单元格都有返回值的完成块,这样您就不需要编写任何额外的代码。对于 UITextfield,您需要将 XIB 指向 BlazeTextFieldTableViewCell 类,并按以下方式设置
BlazeRow *row = [[BlazeRow alloc] initWithXibName:xibName];
row.title = @"Title possibly above textfield";
row.value = @"Current value for the textfield";
[row setValueChanged:^{
DLog(@"New value: %@", row.value);
}];
[section addRow:row];
自定义单元格
这并不常见,但有时我不得不创建一个基础单元格不支持内容的单元格。不要担心,无需重写 UITableViewDataSource 的 cellForRow 方法。BlazeRow 简单地通过完成块返回单元格,这样您就可以按需自定义所有内容
BlazeRow *row = [[BlazeRow alloc] initWithXibName:xibName];
[row setConfigureCell:^(UITableViewCell *cell) {
//Cast the row to your custom cell and customize all you need!
}];
如果您创建自定义单元格,别忘了将您的单元格设置为 BlazeTableViewCell 的子类!
自定义分区头部或尾部
头部和尾部的行为实际上与单元格相同。您可以创建任何自定义 XIB 并简单地指向基本类 BlazeTableHeaderFooterView。然后当在代码中创建分区时,您可以设置 headerTitle、footerTitle、headerXibname 和 footerXibname。此外,如果您有一个非常自定义的分区头部需要自定义,它也可以以与自定义单元格相同的方式返回
BlazeSection *section = [[BlazeSection alloc] initWithHeaderXibname:xibName];
[section setConfigureHeaderView:^(UITableViewHeaderFooterView *headerView) {
//Cast and customize!
}];
超酷功能
创建这个框架后,我开始在所有的应用中使用它。当然,过了一段时间,我发现了一些经常重复的功能。很明显,我必须将这些超酷的功能添加到框架本身中!这样就可以进一步消除更多的样板代码 :)
自动注册表头和单元格
通常,您必须使用以下行注册您使用的每个自定义表头和单元格
[self.tableView registerNib:[UINib nibWithNibName:xibName bundle:nil] forCellReuseIdentifier:xibName];
但这不再是必要的了!Blaze会自动检测您使用哪些单元格和表头,并为您注册它们!又一个节省时间的好方法! :)
动态添加/删除单元格
我希望我的表格视图尽可能灵活,所以我创建了多个函数,以便使用动画快速添加/删除单元格。与其使用索引,不如将ID分配给行,然后使用这些ID动态地添加/删除单元格更具可读性。
[self addRow:row afterRowID:RowID withRowAnimation:UITableViewRowAnimationLeft];
[self removeRowWithID:RowID withRowAnimation:UITableViewRowAnimationRight];
自动值设置器(在使用CoreData时非常出色)
对于输入单元格,我最初从完成块开始,使用返回值来设置CoreData对象的值,如上所述的基技能中解释。但如果我们简单地提供对象和属性名称给行,这会不会更简单?它能够自动更新对象而无需任何额外的代码!您不需要提供当前值(因为它从提供的内容和属性名称中检索它)并且可以移除完成块。只剩下1行代码!
[row setAffectedObject:object affectedPropertyName:propertyName)];
如果您不希望硬编码属性名称,因为它们可能会改变。这就是为什么Blaze提供了一个在NSObject上的类别,您可以使用它如下
[row setAffectedObject:object affectedPropertyName:[object stringForPropertyName:@selector(name)]];
这样,编译器会警告您,如果它没有识别到属性名称!
日期与选择视图
我想考虑到尽可能多的输入类型,所以我创建了日期选择器和选择视图单元格。它们都作为UITextField的输入视图实现。这样,用户可以保持对键盘的焦点,并快速提供他们的输入。当你有多个单元格和多种不同输入时,这一点尤其方便。
输入字段的自动上一个下一个箭头
Blaze支持许多始终使用键盘的输入字段,因为我相信这是最用户友好的方式。所以,无论是文本、日期还是选择视图,用户都可以保持对键盘的焦点。Blaze会自动为任何带有上一个/下一个箭头的左侧和右侧“完成”按钮的BlazeRow输入字段类型添加InputAccessoryView。用户可以使用这些箭头快速在不同字段之间切换,无论这些字段是在不同的部分或不同类型(日期、选择视图等)。
可拖动缩放的头部视图
每个人都见过那些当你向下拖动时会缩放的头部视图。这是一个非常酷的效果,而且设置起来并不困难。只是几行代码,但如果经常使用,则会变成样板代码。所以,在Blaze中,你只需一行代码就可以设置它!:)
只需创建XIB,设置正确的约束,然后使用这一行代码
self.zoomTableHeaderView = [[NSBundle mainBundle] loadNibNamed:@"ZoomHeaderView" owner:nil options:nil].firstObject;
空状态
你可能知道DZNEmptyDataSet cocoapod,可以轻松地为你的UITableView实现空状态。别担心自己实现它,Blaze已经为你做好了!所以现在,你可以轻松地将图像、背景色、标题等属性设置为你的BlazeTableViewController子类属性。
动态行高选项
Blaze的核心思想是使用UITableViewCells并正确设置约束,以便让UITableView自动计算正确的行高,使用UITableViewAutomaticDimension。然而,如果您需要特定的行高,有3种选项可供选择。
row.rowHeight = 30; //30 pixels high
row.rowHeightRatio = 0.3f; //30% of the total tableview's height
row.rowHeightDynamic = TRUE; //Calculates all other rowheights first and sets the remaining space to this row
下拉刷新
当然,Blaze支持UIRefreshControl。只需一行代码即可激活它,并通过完成块获取用户何时想要刷新的信息!
众多快速设置器
为了保持飞快的速度,Blaze提供了大量的快速设置器,您可以通过查看源文件来发现。例如,如果您为某个区的每一行使用相同的XIB文件,您可以简单地设置BlazeSection的rowsXibname属性。这比为每个BlazeRow输入相同的代码行要好得多。如果您为整个屏幕使用相同的xibName,请简单地设置子类BlazeTableViewController的rowsXibName。
任何能改进Blaze的出色想法吗?
告诉我,发送拉取请求,你喜欢的任何方式!我和Blaze一样,使用Blaze为每个屏幕、每个应用程序制作应用程序,而不会在未来的任何时间停止使用它。因此,我将尽可能更新它,使其更加出色!
使用的框架致谢
DNZEmptyDataSet - 拉取请求不接受,所以我已通过文件而不是子规范来实现。将来可能会改变这一点。