为你的应用程序选择一个好的框架是一个很重要的决定,当然你所选择的框架它有它的弊益。
HubSpot应用程序是一个全功能的应用程序。它是一个分析的应用程序,社交媒体程序,电子邮件和联系人管理应用程序 (将会有更多的惊喜)共存在一个屋檐下。当去年夏天我们开始着手建立这个相当复杂的应用程序,在建立之初我们觉得我们需要有一个好的框架去架构这个程序。
最后我们决定将每个子应用创建为一个独立的应用程序,然后使用CocoaPods把它们集成到主应用程序中。
在下面的截图,你可以看到每个应用程序其实都是子应用程序,你可以独立运行也可以到主程序红选择一个程序运行。
使用这种方式,给了我们一个巨大的优势:
最关键的是,我们很容易就可以确保每个子程序的分支准备合并,也可以立马添加一个特定的版本。
我们花了很多的时间去建设但是会用使用比较少的时间去合并,每个单独的应用程序的沙箱使得每个子应用程序很容易的迭代并且能够使用最少的时间来完成和其他应用程序的结成。如果你在一个或以上的iOS团队工作过,纳闷毫无疑问你肯定遇到过Xcodeproj合并,虽然它们是可以解决的,但是这仍然让人感觉很不好受,但是我们却几乎完全避免了这个。
我们能够在必要时单独部署的每个应用程序 - 很神奇的是我们可以单独测试每个应用程序的可用性。我们 可以更早个给测试人员提供更有针对性的的测试,所以我们可以得到高品质的,有针对性的反馈。
因为用户的子应用程序之间流动只与基于URL的路线进行(后面会详细讲解) ,这意味着路由内置和记录 - 而不是通过一堆UIViewControllers的寻找合适的方式来实例化一个特定的看来,有一个明确的路线。建设像演练教程或新的推送通知的元功能时,此功能非常有用。
这种架构一直是一个巨大的节省时间,我们在建立多层面的iOS应用程序与一队超过两个人。听起来像是你的困难?请继续阅读。
Learning from the Web
我们的将移动应用程序分为一个个子应用程序的灵感来自于我们已经看到了HubSpot的网络系结构的成功。
HubSpot的Web应用程序架构是发展的速度和可扩展性。正如我的同事写的,我们使用各种工具和技术,让我们共同部署,每天约300次collectively deploy about 300 times a day这是至关重要的,因为HubSpot的产品套件由几个松耦合但非常不同的应用程序 - 分析,社交媒体,电子邮件,博客,和报告工具的结合。
在网络上,我们可以构建,测试和部署应用程序HubSpot的小部分独立 - 包括后端API和工作用Java编写的,前端的CoffeeScript项目,以及Python项目。为什么移动不可以做?
CocoaPods: Use It.
CocoaPods 适用于iOS的出色依赖管理解决方案,是把一切融合在一起的关键。
一个多应用程序的架构可能是矫枉过正你的使用情况,但CocoaPods肯定是没有 - 即使你只是把在少数的第三方库的使用情况跟踪,视图组件,或联网 - 几分钟的设置时间是完全值得的。可以几乎无缝的利用开源组件完成一个应用程序。
核心库和共享资源,如登录,造型类,以及API /凭证的持久性和访问是建立与Kiwi测试和podspec文件的独立项目。我们把它们发布到我们的私人CocoaPods库,包括他们在我们的实际完全构建的应用程序。但是,我们把它更进一步,建立每个子应用程序 - 所有的社会媒体,电子邮件,或来源,例如 - 作为一个podspec一个单独的项目,然后使用CocoaPods组合成一个主应用程序。
这意味着我们可以在内部单独测试应用程序,并且可以在进行单一的修改,而不用担心其他子程序的完成。
该Podfile为我们的总的应用程序,因此,看起来就像下面的一样
platform :ios, '6.0'
# networking, slider navigation, routing
pod 'AFNetworking', '~> 1.2.1'
pod 'ViewDeck', '~> 2.2.11'
pod 'JLRoutes', '~> 1.2'
# sub-apps, pulling from the head of each repo for development. alternately, we can pin it to a release version like we do the other pods
pod 'HSAPIClient', :head
pod 'HSCommonResources', :head
pod 'HSMarketingGraderApp', :head
pod 'HSContactsApp', :head
pod 'HSDashboardApp', :head
pod 'HSLoginApp', :head
pod 'HSSocialApp', :head
pod 'HSSourcesApp', :head
pod 'HSSettingsApp', :head
pod 'HSSocialReach', :head
pod 'HSEmailApp', :head
Gluing it all Together
细心的读者会注意到,我们已经使用了一些开源的工具,我们的主要应用是在上胶子应用程序一起, IIViewDeck和JLRoutes.关键。
为了让这个我们没有提供的信息的基础应用程序对不同的菜单项和routes每个子应用程序可以处理,每个子应用程序提供了一个实现了一些方法的HSBaseApp协议的一个单独的类:
@protocol HSBaseApp <NSObject>
+ (UINavigationController *)baseNavigationController;
+ (NSArray *)menuItems;
+ (NSArray *)routesToRegister;
@end
一个简单的实现例子
+ (UINavigationController *)baseNavigationController {
return [[HSNavigationController alloc] initWithRootViewController:[[HSSocialViewController alloc] initWithNibName:@"HSSocialViewController" bundle:nil]];
}
+ (NSArray *)menuItems {
HSMenuItem *calendarMenuItem = [[HSMenuItem alloc] initWithTitle:@"Publishing" icon:@"\\" launchHubSpotApp:[HSSocial class]];calendarMenuItem.sectionTitle = @"Social";
return @[calendarMenuItem];
}
+ (NSArray *)routesToRegister {
HSRoute *newItemRoute = [HSRoute routeWithUrl:@"social/new" andAction:^BOOL(id<HSRoutingDelegate> routingDelegate, NSString *url, NSDictionary *parameters)
{// handle route, usually by suppying a UIViewController to the routingDelegate
}];
NSArray *routes = @[newItemRoute];// could be more routes here too
return routes;
}
我们使用的routes来处理传入的推送通知,我们使用相同的方案中的主要应用程序跨子应用程序的链接 - 这是当我们链接从源或社交媒体联络的情况下,例如。
HSRoutingDelegate有魔法在它身边掠过当前活动的UINavigationController所以我们可以把在顶部或基于上下文的路由创建一个模式,一点点但除此之外,它是一个简单的包装为JLRoutes “优秀的基于块的语法。
What else can we do?
从长远来看,我们希望过去的增长我们的简单Kiwi测试一些共享库,并建立在KIF测试,以便每个版本的子应用程序传递Kiwi和KIF测试是建立在一个持续集成的设置,我们可以选择已知的每到ship的主应用程序的每个发布版本。