App Development

A Swift Developer’s React Native Experience

I began this Swift blog almost three years ago when I was a Swift-only mobile developer looking to become a full time iOS developer. I haven’t blogged for a long time here. Let’s just say…things are different now. 😁

I now write 99% JavaScript in React Native. 🤭

Here’s how I got there. And why I ❤️ it.

People Are Talking About React Native

React Native over the past month has had quite the rollercoaster ride. It started when this post appeared on Twitter:

It was quickly deemed to be an incorrect statement. Sophie Alpert, an Engineering Manager on React at Facebook, wrote a post about how React Native has a bright future and is being reworked under the hood to be even better. A few days later, another dip as Airbnb announced that it was going to stop using React Native. Ash Furrow, an engineer at Artsy working in React Native who previously worked in native iOS, wrote about The Case for React Native and Airbnb and React Native Expectations, which offered some great pro-React Native perspectives.

React Native at Skip

I’ve been working at SkipTheDishes in Winnipeg since March 2016 on the iOS team. When I started at Skip, the iOS and Android teams were programming purely in native with Swift and Java respectively. Late last summer in 2017, it was decided by the Senior mobile devs that we wanted to see how rewriting the app that our food couriers use in React Native would work. So the iOS and Android teams merged and together we all began learning JavaScript and React Native.

I’ll be honest–initially I was discouraged by the decision, and I struggled a lot with comprehending JavaScript and React for the first month or two so. It’s so completely different than creating apps natively. Swift and JS are pretty polar opposites, but JavaScript combined with a type system like flow or TypeScript takes much of the pain away from working with plain JavaScript. Another struggle for me was that I’m a highly visual person so doing UI layout in JSX markup using Flexbox rather than Xcode’s Interface Builder was really hard to adapt to at first (now I love it, though, and I can build pretty much anything! 😄).

Overall, I’ve really enjoyed learning React Native and everything that comes along with it. I’m glad I didn’t give up on it. I’ve been working exclusively with React Native at Skip for about a year now, and I actually prefer it to working natively on iOS 😱.

React Nativifying BB Links

My personal iOS app, BB Links, was written in Swift and launched while I was interviewing to work at SkipTheDishes back at the beginning of 2016. It’s now on version 5 after many, many improvements and redesigns. What I’ve learned at Skip has improved my software development skills in every way possible. My iOS app now has over 90K downloads and 23K monthly active users—I’m proud of how much it helps Beachbody Coaches run their home businesses!

Beachbody Coaches with Android devices have continuously asked me for an Android version of BB Links. I had only taught myself how to write apps for iOS in Swift, so writing an Android app in Java would be a completely different beast—and I wasn’t particularly keen on learning Android development from scratch in my evenings/weekends. So my answer to them was always “Sorry, but there won’t be an Android version of BB Links since I only know how to make iOS apps.”

At Skip, as I became more and more experienced with and confident using JS and React Native, I began pondering whether I had the ability to make a version of BB Links in React Native; It would allow me to make an Android version of BB Links without the need to learn native Android development. I knew it would be a challenge, but figured I’d give it a shot.

I made a quick MVP of my app in React Native and kept pushing myself piece by piece until I was sure building the full blown app was definitely something I was capable of. I bought a used Android device on Ebay, and went to work.

It wasn’t easy—there were many frustrations along the way—but the finished app has a 100% custom UI that matches the native iOS app, and has 95% of the same functionality. I decided to make the React Native version Android only, keeping the iOS app native in Swift as a way for me to have a project in Swift that I can continue to work on since my day job at Skip is all React Native now.

BB Links iOS vs Android React Native

BB Links on iOS (left) written in Swift in native iOS code compared to BB Links on Android (right) written in JavaScript in React Native. The Android app uses elevation with a more carded/paper look akin to Google’s Material Design.

This past week I published the completed Android app on Google Play. I’m proud of how it turned out—it functions great, looks like the iOS app, with some paper qualities that fit more on Android, and I’ve become an even better React Native developer while creating it. Having to do every single part of an app from start to finish makes you learn so much more than when you only work on pieces of an app.

Frameworks Used in BB Links React Native

The app uses some great React/React Native frameworks:

5 Things I Love About React Native

Here’s a list of five things I love about React Native overall:

  1. State management with Redux combined with Re-select is brilliant. Redux ensures unidirectional logic flow, which reduces bugs and makes for highly predictable reactive components. Combined with Reselect allows for memoization of logic to eliminate wasteful recalculations, improving performance.
  2. Reloading UI takes seconds with things like Hot Reloading. Change a colour, margin, text, etc. and you can see it updated in the simulator right away. This saves so. much. time.
  3. Creating React Components with Flexbox makes it so easy to make pretty much anything. It takes a while to learn, but once you do, it’s very flexible and intuitive.
  4. Once you learn React Native, you can create websites in React, the original version for web, with needing to learn only a handful of new things. At Skip, I’m now doing some web development in React as well, working on our Courier web portal redesign.
  5. Testing with Jest is great. Once you figure out the mocking part, testing UI, global state, and selector logic is quite easy. Using Enzyme (created by Airbnb), you can take snapshots of your UI with different properties applied to test how it renders and ensure it doesn’t unexpectedly change.

5 Things I Don’t Love About React Native

React Native isn’t perfect. Here are some things that need improvement.

  1. Getting an app started from scratch is complicated. There are things like Create React Native App which help, but if you need any frameworks with native code, which most apps will likely need, setup is much less straightforward.
  2. Needing to write native code that’s bridged to JS is a challenge. As Sophie wrote about in the article linked at the start of this post, Facebook is working to make this easier. Right now, it’s not fun. Also, the fact that a Swift iOS developer would now need to still learn some Android with Java to write the Android native code for the feature complicates things greatly. Now you need to know three languages to do a feature on your own.
  3. Plain JavaScript is too scary for the Swift/Java dev. Once you work with a type-safe language, moving to one that has zero type safety feel like you’re walking on thin ice. Using Flow and TypeScript help greatly with that. Flow is added via a framework, while TypeScript is a subscript of JavaScript and requires a bit more work to use (but greatly worth it in my opinion). The fact that there are two type systems used in the React ecosystem creates some fragmentation and incomplete typings that I wish was better.
  4. There is no official navigation library for React Native. You need to choose one of the externally maintained frameworks; either React Navigation, which is 100% JavaScript and thus very flexible yet has some performance issues, or React Native Navigation, which uses platform native navigation and thus has better performance, but weaker flexibility.
  5. React Native performance on Android isn’t as smooth as iOS. This page in the documentation has some info on how to improve performance of React Native overall.

What’s Next?

At Skip I now get to mentor new React/React Native developers who go through our Incubator program, as well as those on the Courier team who are learning the ropes. I love helping people learn about React and React Native, and I always learn something myself at the same time. Seeing them create things and be proud when they get it is awesome! ❤️

I’m also excited to work next on adding the remaining 5% functionality that I held back on for the Android app’s initial launch. It’s the more advanced stuff like in-app purchases for removing ads & tipping, and adding all 100+ themes like the iOS app has (I finished this, but it requires tipping to be released).

Overall, learning React Native has been great. React is an incredible skill I’ve been fortunate to have been able to learn in-depth working at Skip (we’re hiring Senior React developers, by the way). I know it has a bright future. And creating a React Native version of my personal application has been a fantastic experience filled with excitement, amazement that I could do it, and of course—frustration; but you can’t grow if you don’t fail and struggle. Taking the easy way out never has been much of an option for me in life, anyway.

Standard
Best Practices, Resources

🐤 Swift 3 Function [Re-]Naming Resource

With Swift 3 officially released, it may be time to start migrating Swift 2.2/2.3 Code to Swift 3. But as this article points out, there are some major changes in terms of best practices for naming functions in Swift 3. 

Definitely give this one a read; I really like how it takes you step by step to improve the function names using examples. 👌

http://inaka.net/blog/2016/09/16/function-naming-in-swift-3/

Standard
Best Practices, Tutorial Resources

Enumified TableView with Dynamic Prototype Cells in Swift

How I refactored my app’s Settings screen code to be much more flexible and readable, while unlocking a more complicated TableView at the same time! Win-Win!

I stumbled upon this amazing post by Frédéric Adda over at Nova Era called Structure Your UITableView Better with Structs and Enums in Swift as I was searching for a way to refactor the Settings page in my app, BB Links, to make it easier to add in new settings options anywhere, or change around any items/sections, without needing to manually worry about the section and row index numbers.

The linked post above explains how you can use enums and structs to replace the indexes for section and rows–it’s really cool!!! 😎 Exactly what I was looking for! Below is my implementation of it for my app’s Settings screen, and I took this concept even further later on in so I could easily have different Dynamic Prototype Cells! 😱

With this change, I can move any item to any section and change the order of sections and items all within a couple of seconds! To do that with section and row indexes requires a bunch of index changes which can get confusing to keep track of.

Here’s how I set it up in my app, first implementing the enums and structs, as Frédéric’s article suggested:

private enum SectionType {
  case Account
  case Other
}

private enum Item {
  case ManageAccounts
  case ActiveAccount
  case DefaultCountry
  case AboutMe
  case Donate
  case RateApp
  case ShareApp
}

private struct Section {
  var type: SectionType
  var items: [Item]
}

First, I created the SectionType enum which represents the different sections I want to have in the Settings screen. I have an Account section and Other.

Next, I create the Item enum which contains all of the different tableView rows I have in the Settings screen.

Lastly, a Section struct is created which is identified as containing a SectionType enum and an array of Item enums.

Once those three components were set up, the next step was to create an instance of an array of Section structs, which will hold the various sections in the Settings screen.

class SettingsViewController: UIViewController {
  private var sections = [Section]()
  ...
}

In the viewDidLoad() method, I assign the items that belong in each section:

override func viewDidLoad() {
  super.viewDidLoad()
  // Setup sections/rows for table
  sections = [
    Section(type: .Account, items: [.ManageAccounts, .ActiveAccount, .DefaultCountry]),
    Section(type: .Other, items: [.AboutMe, .Donate, .RateApp, .ShareApp])
  ]
  ...
}

The Account section contains the ManageAccounts, ActiveAccount and DefaultCountry tableview rows, and the Other section contains the remaining four rows.

Next up…the UITableViewDataSource implementation which I have as an extension to my SettingsViewController class.

// MARK: - UITableViewDataSource
extension SettingsViewController: UITableViewDataSource {
  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return sections.count
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return sections[section].items.count
  }

  func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch sections[section].type {
    case .Account:
      return "Account"
    case .Other:
      return nil
    }
  }
  ...
}

For tableView:numberOfSectionsInTableView:, you just return the count of your sections array, which will be 2 as it contains my two Section structs.

for tableView:numberOfRowsInSection:, return the count of items in each section, and for tableView:titleForHeaderInSection:, I setup a switch statement to switch through the types, returning the name for each section. (For Other, I just wanted it to be blank, so I didn’t return a title).

Before I show how I used these enums and structs to help me easily implement three different dynamic protoypes, here’s how I implemented the UITableViewDelegate methods:

// MARK: - UITableViewDelegate Methods
extension SettingsViewController: UITableViewDelegate {
  // Goes to product detail when cell tapped
  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    switch sections[indexPath.section].items[indexPath.row] {
    case .ManageAccounts:
      performSegueWithIdentifier("ManageCoachIDs", sender: self)
    case .ActiveAccount:
      performSegueWithIdentifier("DefaultCoachID", sender: self)
    case .DefaultCountry:
      performSegueWithIdentifier("DefaultCustomerCountry", sender: self)
    case .AboutMe:
      performSegueWithIdentifier("About", sender: self)
    case .Donate:
      performSegueWithIdentifier("Donate", sender: self)
    case .RateApp:
      rateApp()
    case .ShareApp:
      shareAppFrom(indexPath)
    }
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
  }
}

I just switch between the section and row using the sections array, and perform my segues or functions for each Item. It’s all very clear what is what thanks to the Item enum setup earlier! I love it! ❤️ Without this setup, you’d just have combinations of sections and row index numbers and you’d need to keep track of which is which with comments. And don’t even think it would be simple to switch them around. With the way this is setup, it really doesn’t matter which order you put the case Items…it’s all handled by the way you place them in your section variable up in the viewDidLoad()! Brilliant! 🙌

For the final part, I’ll show how I easily implemented my three dynamic prototype cells, which are just a simple Basic Cell, a Subtitle Cell and Right Detail Cell (setup as such in the storyboard with appropriate cell identifiers):

Here’s how my storyboard is setup:

Storyboard

And implementation of tableView:cellforRowAtIndexPath::

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  // Setup a cellIdentifer string to store the cell reuse identifier you want to use for each row.
  var cellIdentifier: String

  // Switch through each row and set the appropriate cell reuse identifier
  switch sections[indexPath.section].items[indexPath.row] {
  case .ManageAccounts, .AboutMe, .Donate:
    cellIdentifier = "BasicCell"
  case .RateApp, .ShareApp:
    cellIdentifier = "SubtitleCell"
  case .ActiveAccount, .DefaultCountry:
    cellIdentifier = "RightDetailCell"
  }

  // Populate your cell reuse identifier into the cell
  let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)

  // Switch through each cell, and implement the labels/setup for each row
  // The order of the cases is irrelevant!
  switch sections[indexPath.section].items[indexPath.row] {
  case .ManageAccounts:
    cell.textLabel?.text = "Manage Coach IDs"
  case .ActiveAccount:
    cell.textLabel?.text = "Active Coach ID"
    let coachID = dataModel.getActiveCoachID()
    if coachID != "" {
      cell.detailTextLabel?.text = coachID
    } else {
      cell.detailTextLabel?.text = ""
    }
  case .DefaultCountry:
    cell.textLabel?.text = "Default Country"
    cell.detailTextLabel?.text = dataModel.getDefaultCountry()
  case .AboutMe:
    cell.textLabel?.text = "About the Developer 💪🤓"
  case .Donate:
    cell.textLabel?.text = "☕️☕️☕️?"
  case .RateApp:
    cell.textLabel?.text = "Rate BB Links ⭐️⭐️⭐️⭐️⭐️"
    if let reviewCount = reviewCount {
      cell.detailTextLabel?.text = "\(reviewCount) people have rated this version"
      UIView.animateWithDuration(0.3, animations: {
        cell.detailTextLabel?.alpha = 1.0
      })
    } else {
      cell.detailTextLabel?.text = " "
      cell.detailTextLabel?.alpha = 0.0
    }
    cell.accessoryType = .None
  case .ShareApp:
    cell.textLabel?.text = "Share BB Links 🗣👥"
    cell.detailTextLabel?.text = "Know a coach who would love this app?"
    cell.accessoryType = .None
  }

  // Return the cell
  return cell
}

I love the way this worked because it’s clear exactly which row I’m working with, and I can quickly change the cell type by moving around the row Item where the cellIdentifier variable string is set in the first switch statement and changing its cell implementation details! So. Much. Clearer! 🙌

With all of this setup the way it is, adding new sections or rows is a cinch! I could totally rearrange this tableView to look completely different switching a couple of lines of code. The normal way would be way more difficult.

Here’s the finished result in-app:

Settings Screen Result

It’s now setup for quick modifications in the future! 🎉

If you ask me, enumified tableViews with dynamic prototype cells rock! 😎

Standard
Best Practices

Thomas Hanning outlines how to use the new defer keyword in Swift in his blog post.

Essentially, the defer keyword executes its block before exiting the scope it is contained within. It’s a great tool to ensure you do any clean-up code required, even if an error is thrown.

It’s almost like a deinit() block for your own functions!

Check out his full post here: http://www.thomashanning.com/swift-2-0-defer/

Link
Best Practices

radex.io has an excellent explanation of when you should AND shouldn’t use ‘guard’ in Swift. 🙌

‘Guard’ has quickly become one of my favourite way to help simplify my code by getting rid of lots of pyramids of doom! If if if 🙅.

Example:

guard !array.isEmpty else { return }

replaces the need to do an if statement around the entire code block that relies on the array not being empty and just returns from the function as soon as it finds an empty array without executing any further code in the function! 🎉

Make sure to check it out and try guard out in your code!

http://radex.io/swift/guard/

Link
Design

Designing My First iOS App’s Icon

Designing an app icon is not such an easy task! You’ve got to make sure it’s unique and sticks out in the sea of other apps, and is appealing to the eye. The icon needs to represent in some way what your app is about.

I’ve been working on my first iOS app, BB Links (short for Beachbody Links), and this weekend I decided to work on its icon after watching Michael Flarup‘s great video called Designing Better App Icons (which has an awesome 80s vibe!!!).

I’m not that great with Photoshop. I’ve only ever used it for editing video and for making somewhat hacked logos before for my Beachbody business. After watching Michael’s video, I picked up some functions of Photoshop that I didn’t really realize I could use for making logos, such as smart objects using shapes.

original BB Links app icon

The first version, created a month ago

I whipped out Photoshop last night afterwards and started working with shapes to come up with a logo that incorporated the letter b. Here’s the first iteration after deciding that my original logo above which had just the app’s name in text was not good enough.

BB Links app icon version 1

Redesign, iteration #1

This first version I used shares to create a B (a rectangle and a circle), and then added a shadow behind it. This created a double B in a way, which fit the BB Links app name.

This is the second iteration:

BB Links app logo version 2

Redesign, iteration #2

I experimented with using some linear shapes with gradients to simulate a block shadow, however, this how meant there was only a single B present. That’s not a bad thing, but my husband said that something was off with the shadow (I’m assuming since I didn’t create a vanishing point…I tried but couldn’t figure out out with Photoshop 🙃). He also said that the ‘b’ should have a circle inside it–I’d tried to go without just to make it different, but agreed that it just looked “off.”

So with a (BUNCH) of more fiddling around, here’s the final app icon I’ve come up with!

BB Links app logo current version

Redesign, iteration #3 (final…for now)

I changed up the blues in the background a bit so they’re brighter, added the inside of the ‘b’, doubled up the ‘b’s, added a slight shadow to the ‘b’s to give them a bit of POP and added a line underneath to play tribute to the fact that hyperlinks have underlines often so that plays on the BB Links name. 😁

I used Michael’s awesome iOS App Icon Template (FREE/Donationware) to export all of the sizes required to include in the app’s assets for all of the iOS icon sizes for all of the different iOS devices. It’s great…get it! And support him as well so he keeps it updated and keeps improving it.

For now I’m happy with the way it looks. Much better than I’ve done in the past as most of what I’d made was very flat and didn’t have much depth. I’ll probably play around with it some more after a while to tweak it, but I think this is now close to the final version!

Let me know what you think, and feel free to leave some suggestions for improving it if you want! I’m an amateur and love learning new tips/tricks. 🙂

Standard