Skip to content
Aaron Schachter edited this page May 23, 2016 · 17 revisions

DoSomething iOS is a hybrid React Native app: we use React components to power the View components of some screens, rendered in native UIViewControllers.

Native components

  • Tab Bar, Navigation, Image Picker, Activity/Share View Controllers
  • Onboarding Views
  • Login, Register Views/Networking
  • Submit Reportback View/Networking
  • Settings View
  • Campaign Attachments View -- renders URL in UIWebView

React Native components

  • News Feed Views/Networking
  • Cause List, Detail Views/Networking
  • Reportback Gallery View/Networking
  • Campaign Detail, Action Guides Views/Networking
  • Profile View/Networking

Our LDTAppDelegate contains a public readonly RCTBridge *bridge property that all of our React Views (RCTRootView) are initialized with. Calling the [LDTAppDelegate.bridge.eventDispatcher sendAppEventWithName:body] allows us to send events from native code and create corresponding listeners (NativeAppEventEmitter) in React Native.

Networking

  • DSOAPI - subclass of AFHTTPSessionManager, handles all of our Objective C networking requests to the DS API and transforms response into relevant Model classes.

    • Ideally this class will moved out of this repo and into our SlothKit CocoaPod (inspired by Github's Octokit) to share networking code in multiple iOS projects
  • DSOUserManager - singleton class with a user property, which stores our logged in DSOUser (also referred to as Current User in documentation)

    • Also contains a campaigns property - an array of DSOCampaign objects loaded from DSOAPI. We store these in memory to avoid making extraneous network calls. This may get refactored to store in Core Data to further cut down on network calls (#734).
    • Calls DSOAPI methods on behalf of the Current User with various completion and error handlers, such as logging errors to Crashlytics or dispatching events to React Native.

Controllers

  • LDTTabBarController - Our LDTAppDelegate root view controller.

    • Presents modals for Authentication, Reporting Back, and Settings
    • Loads the Current User if app starts with a saved API session token
  • LDTReactBridge - implements RCTBridgeModule protocol to export methods that allow React Native to communicate back to our native code.

Building

In our [LDTAppDelegate application:didFinishLaunchingWithOptions:], we run React Native from either the local development server or from the offline bundle based on the environment.plist value for ReactNativeUseOfflineBundle (pull/#781).

  • When building to device or archiving, make sure your ReactNativeUseOfflineBundle is set to YES in your environment.plist, otherwise the build fails on device with a npm not running.

  • Alternatively, when developing locally and testing in iOS Simulator, ReactNativeUseOfflineBundle must be set to NO. Testing in Simulator with the value set to YES will result in a: Unable to execute JS call: __fbBatchedBridge is undefined error until we fix #920 -- this may be a local setup issue only.

Upgrading React Native

From the root project directory:

  1. Upgrade the React Native dependency. Example:
 npm install --save [email protected]
  1. npm update -- Updates node_modules accordingly (Refs pull#985)

  2. pod install -- Updates React Cocoapods

Notes

  • We have NSAllowsArbitraryLoads set to YES to allow the LDTNewsArticleViewController to load any given news article (pull#772) and support iOS8 (dropping iOS8 support would allow us to instead use a SafariWebController and keep NSAllowsArbitraryLoads set to NO for security)

  • React Native: Don't render a ListView within a View - it's a gotcha

Graveyard

Refactory

Our Profile and Campaign view were originally built in native code, but we refactored in React Native for faster view building, and easier dynamic heights (refs pull#687, pull#706)

Signups are currently modeled with the DSOSignup class -- originally was a DSOCampaignSignup class, before the Phoenix Signups API endpoint existed. (pull#917). We only use the DSOReportback and DSOSignup classes in our DSOAPI POST completion handlers, sending newly created entities to React Native via LDTAppDelegate.bridge.eventDispatcher.

RIP

  • DSOUser.campaignSignups pull#844 - array storing a User's DSOCampaignSignup's. Upon app launch, we'd load the Current User's campaignSignups to be able to indicate which Campaigns the Current User has signed up for when viewing a list of Campaigns. The visual indicator in the list of Campaigns has since been removed (see Main Feed below), we now query the Signups API on demand if we need to know the Current User's Signups (currently when either viewing a Campaign or Self Profile)

  • InterfaceBuilderView pull#886 - Helper class for creating a UIView from a xib with corresponding .h and .m files. Was used by the native LDTReportbackItemDetailView

  • LDTCampaignListViewController pull#725 - aka The Main Feed. Was our initial first screen in v1.0.0. Implemented a UICollectionView, which had 4 LDTCampaignCollectionViewCellContainer cells for 4 different taxonomy terms (aka Interest Groups). A LDTCampaignCollectionViewCellContainer also contained an inner UICollectionView that displayed Campaigns and Reportbacks for a given Taxonomy Term and scrolled vertically. The user could swipe left and right to view the different Terms, because the outer UICollectionView scrolled horizontally.

    • LDTReportbackItemDetailSingleViewController pull#831 - Single view of a Reportback Item the User would be presented with upon selecting an item in the Main Feed Reportback Gallery
Clone this wiki locally