iOS App Basecamp 3: 混合架构

iOS App Basecamp 3: 混合架构

以前, 我们已经写了很多篇关于如何构建混合移动应用方法的文章. Basecamp3 项目代表了混合移动架构的最新版本, 并且它从过去的版本中吸收了很多精华.

Basecamp 2项目的第一个App仅仅适用于iPhone, 它是利用RubyMotion作为UIWebView的封装器来进行编写的. 之后, 我们又通过Xcode+Objective-C, UIWebView以及更多原生代码的方式去构建一个通用型的App. 对于Basecamp 3, 我们使用Swift和WKWebView代替Objective-C和UIWebView, 新增了Turbolinks, 并且使用了更多的原生代码. 这是原生App和web App的一次更加深入的融合.

混合的定义

首先, 我们需要清楚理解什么是”混合”. 这个词在很多不同的场合中被使用, 但这对于我们而言几乎没有任何意义. 在我们的开发中, 我们所指的”混合”是具有大量web渲染内容的标准原生应用. 在这个定义中, 我明确地指出内容是因为这是一个非常重要的区别. 我们没有使用通过HTML/CSS来模拟原生控件的框架, 也没有使用将另一种编程语言编译成原生开发语言的框架, 亦或者是通过一份代码库开发一个跨平台的App的框架.

对于我们而言, 这意味着我们需要使用Xcode+Swift, 并且要遵守开发平台关于导航和展示的所有规范. 在App中构建的内容大多由UINavigationController, UIViewController, UITabViewController, UISplitViewController等组成. 在这些容器中, 有很多内容是通过UITableView或UICollectionView组建的, 当然了更多的是通过WKWebView.

深入理解

在iOS版本的Basecamp 3 App 中我们使用的全部是Swift 3.1, 并且通过最新版本的Xcode进行编译. 我们只有很少的依赖, 并且这些都是通过Carthage进行管理的. Turbolinks是我们能够使用混合架构的核心库. Turbolinks不仅可以用在Web上, 在iOS和Android的原生应用上也可以进行使用. 此框架主要解决了原生应用和Turbolinks.js之间的通讯问题, 并且允许开发者在多个界面间共享单个WKWebView.

路由/导航

除了Turbolinks, 我们还需要许多其他的组建进行支持. 在iOS应用中大多数都是通过URL进行的导航. 一个URL可以有很多来源(web链接, 推送通知, 来自另一个App的通用链接, 本地跳转等), 但是它们都要通过路由进行中转. 路由需要清楚地知道对于一个给定的URL下一步操作是什么. 如果URL是另一个域, 应用还可能打开Safari; 如果是图像/视频, 则需要展示一个媒体视图, 又或者是在大多数情况下, 应用都是创建一个新的控制器进行展示. 大多数的控制器都需要被推入当前导航控制器的栈中, 但是我们也支持通过模态的方式弹出一个视图(类似新的/编辑视图) 以及在合适的时候替换当前视图.

桥接

组成混合架构的最后一个组件是桥接(尽管我们有许多其他的组件, 但它们都和混合模块没关系). 这是一个在App不同部分之间进行通讯的统称术语, 比如原生->web通讯(或web->原生). 其中最核心的代码是一份嵌入到本地App的JavaScript文件(用TypeScript编写)并且通过WKUserScript注入到web视图中. 这种桥接方式给原生代码提供了一个在不需要直接查询DOM和进行复杂JS操作的情况下与web视图进行通讯的API. 利用WKScriptMessageHandler, 我们可以通过桥接来响应从Web发送的消息.

Bridge in action. The mobile web is on the left, the app is on the right. The bridge hides the top nav, breadcrumbs, and other elements we want render differently in the app

以上是一个关于桥接的例子. 我们使用桥接来隐藏一些在web上需要显示但在Basecamp界面中不需要的元素. 由于我们给顶层导航控制器提供了一个标签条, 所以我们需要隐藏web界面最下面的部分. 同时, 也不需要web的导航记录了因为我们已经有了一个导航控制器. 最后, 我们隐藏了Web的编辑/书签/动作菜单并且提供了一个原生版本的界面.

案例

通过下面几个例子我们将在实际中更加容易感受到上面所说的意思. 在下面的图片中, 我将用一个紫色的叠加层来标示web视图, 一个绿色的叠加层来标示原生UI.

主标签

iOS版本的Basecamp 3有四个主标签(Home, Hey!, Activity, 和Find). 这些标签每一个都是100%原生的. 由于这些标签是App中主要的交互点, 因此我们希望它们能够尽可能的快速响应用户交互. 另外我们也十分想提供一个与桌面应用不同的体验, 我们认为这个在移动端上更加具有意义. 比如Hey标签和最近的所有通知.
Basecamp 3 for iOS — Main tabs

消息

当你点击Hey标签的通知, 想要获取一个新消息时, 我们将在导航控制器的栈中推入一个TurbolinksViewController控制器.
From left to right: Hey! screen, viewing a message, actions menu, tools menu

这是一个典型的所有内容都是web的视图. 我们在页面中通过桥接方式取出数据并展示在导航条上. 同样地, 当你点击按钮的时候, 我们将从DOM中取出数据并填充一个原生的弹出菜单. 由于在这种混合架构中都是由界面提供的动态性数据, 于是我们可以在服务端随时更改数据. 最终, 当你点击导航条标题时, 我们将展示一个原生的工具菜单, 给用户提供项目导航的快速访问功能.

在线交流系统营火

我们也有一些由原生和web混合的视图. 下面是Campfire的一个例子:
From left to right: Hey! screen, viewing a campfire, completing a mention, attaching a file

主要的聊天界面是web构成的, 但是我们决定使用原生视图进行输入. 这样可以修复一些由web输入造成的问题, 比如滚动时保持正确的位置, 同时也可以更好地控制交互式键盘的消失. 当输入某人名字的时候, 我们可以使用一个原生的自动补全器. 点击回形针按钮可以显示一个原生的附件选择器, 这使我们在整个应用中使用了一些很好的触摸, 比如快速挑选醉经拍摄的照片. 这些组件可以在同一个视图中无缝衔接.

总结

下面是几个例子演示了这种方式的灵活性. 这种架构的关键是我们没有被限制在一种方式或者框架中. Native和Web并不是非此即彼的选择, 而是一种类似光谱的范围选择.
Web → Native spectrum
对于App的每一个视图, 我们都可以调整Web和原生开发的比例. 我们认为, 如果一个原生视图很少被使用并且不值得维护, 我们会将它改成Web形式. 如果一个web视图没有提供一个最好的用户体验, 我们将用原生替待. 我们可以尝试React Native或者将其混合使用. 无论何时Apple发布新的API, 我们都可以立即对其支持, 因为我们不依赖第三方框架进行更新.
在Basecamp中我们非常看重的一件事就是团队的独立性。如果我们必须协调web, iOS和Android开发团队中每一个新特性的开发和发布工作, 我们将永远不能够前进. 这种架构模式允许web开发团队构建一个新特性并且在所有平台上同时发布. 在Basecamp 3中我们默认有一个展示任何URL的视图控制器, 所以在App中任何新的URL可以正常工作. 我们可以在web上迭代和实验, 立即在全平台发布, 之后如果我们觉得可以提升它的用户体验, 我们会用原生替代它.
这也使我们的移动团队专注于如何最好的服务平台。 我们的目标之一是在手机应用中覆盖100%,因为应用不支持某些功能,因此您不必进入桌面。 凭借网络提供的坚实基础,我们可以实现这一目标,然后将重点放在平台特定的改进上。 这些功能包括丰富的内容推送通知,通用链接,切换支持,iCloud Keychain支持,共享扩展,今天的小部件等功能。 如果我们没有完全的本地支持,那些这些事情将是不可能的或不平凡的。如果没有100%原生的支持, 这些改进中的部分功能将不可能实现或者变得卓越.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值