• ios Using CocoaPods to Modularize a Big iOS App->使用CocoaPods来进行模块化开发


    Selecting the right architecture for your mobile app is a pretty big deal. It will shape your daily workflow, frame the problems you face, and can be a huge asset or huge liability.

    HubSpot's app is fully-featured. It's an analytics app, a social media app, an email app and a contacts management app (with more to come) all coexisting under one roof. As we set out to build this fairly complex app last summer, we knew we had to have an architecture that'd scale with it.

    We actually build each sub-app as a fully complete standalone app, then use CocoaPods to integrate them into the main app.

    In the screenshots below, you can see how each sub-app - Sources, Dashboard, Social Media, is actually both a standalone iPhone app as well as an app that can be brought into the menu of the main app.

    app_example

    This gives us a few huge advantages:

    • Most critically, we're very easily able to ensure that the master branch of each sub-app is ready to ship, and can pull in specific versions of sub-apps in a snap.
    • We spend a lot more time building and a lot less time merging. Each individual app's sandbox makes it very easy to iterate within the sub-apps and spend minimal time integrating with other apps. If you've worked on an iOS team of more than one, you've undoubtedly had gross .xcodeproj merges. While they are resolvable, they're a pain -- this lets us sidestep them almost completely.
    • We are able to individually deploy each app if necessary -- this is amazing for doing usability testing on an individual app level. We could ship the app to our testers earlier before “glue” features like navigation were complete so we could get high quality, targeted feedback.
    • Because user flows between sub-apps are only done with URL-based routes (more about this later), it means that routes are built-in and documented -- instead of searching through a pile of UIViewControllers for the right way to instantiate a particular view, there’s a well-defined route. This is useful when building meta-functionality like walkthrough tutorials or new push notifications.

    This architecture has been a huge timesaver for us in building multifaceted iOS apps with a team of more than two people. Sound like your jam? Read on.

    Learning from the Web

    The inspiration for splitting up our mobile app into sub-apps came from the successes we've seen with HubSpot's web architecture.

    HubSpot's web app architecture is built for development-speed and scalability. As my colleagues have written, we use a variety of tools and techniques to let us collectively deploy about 300 times a day. This is critical, as HubSpot's product suite consists of several loosely coupled but very different applications -- analytics, social media, email, blogging, and reporting tools.

    On the web, we can build, test, and deploy small sections of the HubSpot app independently -- including backend APIs and jobs written in Java, front end CoffeeScript projects, and Python projects. Why not do the same for mobile?

    CocoaPods: Use It.

    CocoaPods, the excellent dependency management solution for iOS, is key in bringing everything together.

    A multi-app architecture may be overkill for your use case, but CocoaPods certainly is not -- even if you're just bringing in a handful of 3rd party libraries for usage tracking, view components, or networking -- investing the few minutes to set it up is fully worth your time. The ruby gem-like syntax makes integrating open source components into an app nearly seamless.

    Core libraries and shared resources like login, styling classes, and API/credential persistence and access are built as independent projects with Kiwi tests and a podspec file. We publish them to ourprivate CocoaPods repository and include them in our actual fully-built applications. However, we take it a step further by building each sub-app -- all of Social Media, Email, or Sources, for example -- as a separate project with a podspec, then build them all into a single app using CocoaPods.

    This means we can ship test versions of a single feature internally, and can move quickly with breaking changes in a single app without worrying about breaking the big build for other developers working in other unrelated sub-apps.

    The Podfile for our aggregate app, therefore, looks like:

    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
    view rawHubSpot Podfile hosted with ❤ by GitHub

    Gluing it all Together

    Astute readers will notice we've used a couple of open source tools in our main application that are key in gluing the sub-apps together,IIViewDeck and JLRoutes.

    To make it so that we don't have to provide information in the base app about the different menu items and routes each sub-app can handle, each sub-app provides a single class that implements an HSBaseApp protocol with a few methods:

    @protocol HSBaseApp <NSObject>
    + (UINavigationController *)baseNavigationController;
    + (NSArray *)menuItems;
    + (NSArray *)routesToRegister;
    @end
    view rawHSBaseApp.h hosted with ❤ by GitHub

    An example implementation is:

    + (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;
    }
    view rawHSSocial.m hosted with ❤ by GitHub

    We use routes to handle incoming push notifications, and we use the same scheme to link across sub-apps within the main app -- as is the case when we link to Contacts from Sources or Social Media, for example.

    HSRoutingDelegate has a little bit of magic in it for passing around the currently active UINavigationController so we can push on top or create a modal in a route based on context, but otherwise it's a simple wrapper for JLRoutes' excellent block-based syntax.

  • 相关阅读:
    bzoj3675 [Apio2014]序列分割
    bzoj4010 [HNOI2015]菜肴制作
    bzoj4011 [HNOI2015]落忆枫音
    bzoj100题
    JSP—内置对象
    集合框架—常用的map集合
    集合框架—HashMap
    集合框架—代码—用各种集合进行排序
    集合框架—2种排序比较器
    array
  • 原文地址:https://www.cnblogs.com/tinkl/p/3668487.html
Copyright © 2020-2023  润新知