Topics

#171: App Launch Checklist ✅

Topics

Launching an app can be a huge undertaking. Today we'll break it down, and make ourselves a quick checklist:

1.) Create our app in iTunes Connect

Pro Tip: We can save ourselves time and trouble by using produce for this. (Bite #114).

2.) Compose our app’s description & metadata

Entire books can be written about how best to optimize these bits, but in short, we should strive to be unique, direct and fun.

3.) Capture and produce screenshots

We'll use snapshot (Bite #110) for this. Not only will we save our sanity, but we'll end up with UI Tests to boot!

4.) Upload & Submit

Again, we'll lean on the amazing fastlane tools. We'll set our app to be "manually released" so we control when it goes live.

5.) Create a Press Kit

This step is crucial! We'll assemble a press kit: Icons, screenshots, logos, videos, frequently asked questions, etc. and host it on our app's website.

6.) Promote & Launch!

Once approved, we'll reach out to all our favorite blogs and influencers offering them promo codes + a link to our press kit.

Weekly Sponsor: Hired 🏢

Big thanks to the folks at Hired.com for sponsoring this week's bites. Finding a good job can be a daunting task. Today we'll take a look at how we can use Hired.com to save our sanity, and find a great job in the process. Let's dive in.

We'll start by entering our email and answering some basic questions:

That's it. Hired will then work with over 3,000 pre-screened companies (both big and small) in 13 major metro areas (North America & Europe) to try find us a great job. Software engineers and designers on Hired can get 5+ job offers in a single week. Each offer will include salary and equity details upfront.

We can view interview requests and accept or reject them before talking to any company. If we get a job through Hired, they'll give us a $1,000 "thank you" bonus!

Even better, if we sign up through this link: littlebitesofcocoa.com/hired, they'll double our bonus to $2,000!

More Reasons to Use Hired

  • Full time or contract opportunities are available
  • View offers and accept or reject them without talking to anyone.
  • Completely FREE + no obligations ever.

Hired is the real deal. They have solved some very real problems and fixed this historically messy process. Looking for a job? Don't waste time, sign up for Hired today so you can get back to work!

Topics

#170: Swift Tricks Revisited 🎩

Topics

Today we'll look at a few more interesting Swift tips and tricks. Let's get started.

Multiple Switch Cases

We'll start with a simple one. We can simplify messy switch statements by combining the similar cases. This is similar to how we can use multiple case statements in other languages, but a bit less wordy:

extension FirstOrderAPI {
  var method: HTTPMethod {
    switch self {
    case .Spaceships,
         .Crew,
         .Stormtroopers,
         .Planets: return .GET

    case .AddSpaceship,
         .AddCrewMember,
         .AddStormtrooper,
         .AddPlanet: return .POST

    case .RemoveSpaceship,
         .RemoveCrewMember,
         .RemoveStormtrooper,
         .DestroyPlanet: return .DELETE
    }
  }
}

Operator Parameters

We can actually pass literal operators in as a parameter, for example:

[1, 2, 3, 4].reduce(0, combine: +)

This works because the + operator is actually a function under the hood:

public func +(lhs: Int, rhs: Int) -> Int

Simpler Reuse Identifiers

In Objective-C, It's quite common to use NSStringFromClass to use a cell's class name as it's reuseIdentifier. In Swift though:

let reuseIdentifier = String(SpaceshipTableViewCell)

Shout out to Natasha for pointing this one out!

Breakpoints in Xcode are a great way to pause execution and poke around at what's going on in our app. Today we'll look at some ways we can use them without pausing execution. Let's dive in.

We'll start by pressing (while editing) to set a breakpoint:

Then, we can right click to edit the breakpoint. The popover that appears may appear simple, but it's packing tons of power.

We'll enable that last checkbox straight away, then click Add Action to see our available options.

We can add a Debugger Command action to (for example) print a value whenever the breakpoint hits. We now have a dynamic log statement we can easily enable/disable.

The last option, "Sound", might not seem that useful at first glance. We can use this to (for example) debug high performance code, or whenever we'd like to hear an audible "ding" when a certain code path is hit.

After adding an action, we'll see a couple +/- buttons, this means we can actually pair both these techniques together, neat. Happy debugging!

Today we'll checkout another great library from Alexander Schuch called StatefulViewController.

It can help us add loading, empty, and error states to our view controllers. Let's get started:

Most apps we build must load data before showing it to the user. Those apps will also need to handle the case where there's no data available, or when something goes wrong.

StatefulViewController allows us to easily add all of this functionality to our view controllers.

While this might seem trivial, there's actually quite a bit of logic and state management involved. StatefulViewController helps eliminate boilerplate and help us focus on building the parts of our app that make it unique and useful.

Let's try it out. First, we'll make a view controller, and adopt the protocol:

class ViewController: UIViewController, StatefulViewController { }

Then we'll need to set up our placeholder views:

// inside viewDidLoad
loadingView = LoadingView(frame: view.frame)
emptyView = EmptyView(frame: view.frame)
errorView = ErrorView(frame: view.frame)

Next, we'll need to set up the initial state when the view controller's view is about to appear:

override func viewWillAppear(animated: Bool) {
  super.viewWillAppear(animated)
  setupInitialViewState()
}

Now we can visually start and stop loading when we need:

startLoading()
endLoading(error: nil)

Lastly, we'll need to implement one more function to let the library know when there's content available:

func hasContent() -> Bool {
  return spaceships.count > 0
}

More info about StatefulViewController can be found at git.io/stateful

Parallax headers have become very common in iOS apps. They're a great way to (for example) show off large graphical content, or summarize/focus a screenful of content.

Today we'll look at a fantastic library from Maxime Epain called MXParallaxHeader. Let's go:

A parallax header essentially involves displaying a view above a scroll view, which grows and shrinks as the user scrolls the scroll view.

It's also common to see the content of the parallax header view re-center itself as the user scrolls, so the content is visible for as long as possible while scrolling up.

MXParallaxHeader offers a few different options that make customizing this behavior quite simple.
We can center, fill, or lock our content to the top or bottom. Neat!

Let's use MXParallaxHeader to add a simple parallax header to a scroll view:

scrollView.parallaxHeader.view = headerView
scrollView.parallaxHeader.height = 150
scrollView.parallaxHeader.mode = .Fill
scrollView.parallaxHeader.minimumHeight = 20

Even cooler than that, MXParallaxHeader extends UIViewController to add a couple extra properties that allow us to easily add parallax header to any view controller.

Header views can optionally adopt the MXParallaxHeaderProtocol to implement custom parallax animations based on the user's scroll progress:

func parallaxHeaderDidScroll(parallaxHeader: MXParallaxHeader) {
  let angle = parallaxHeader.progress * CGFloat(M_PI) * 2
  self.falcon.transform = CGAffineTransformRotate(CGAffineTransformIdentity, angle)
}

More info about MXParallaxHeader can be found at git.io/mxparallaxheader

Today we'll look at a fun and interesting library that can help improve how users navigate around in our apps.

It comes to us from Taiki Suzuki and it's called SAHistoryNavigationViewController.

It works by augmenting UINavigationController's traditional interactions to add a gesture to view each of the view controller's that have been pushed on to it. We can use it just like a regular navigation controller:

let vc = SpaceshipsViewController()
let nc = SAHistoryNavigationViewController(rootViewController: vc)

presentViewController(nc, animated: true, completion: nil)

The library will handle showing the history scroll view when the user long presses the back button. If the user's device supports 3D Touch, the history scroll view activate with that gesture instead.

We can also trigger the history view to be shown at anytime like this:

navigationController?.showHistory()

We can customize the background color shown behind all the “zoomed out” view controller easily:

navigationController?.setHistoryBackgroundColor(.blackColor())

We can also customize the background view by subclassing, and overriding the contentView function.

More info about SAHistoryNavigationViewController can be found at git.io/historync

Weekly Sponsor: Hired 🏢

Big thanks to the folks at Hired.com for sponsoring this week's bites.

Finding a good job can be a daunting task. Today we'll take a look at how we can use Hired.com to save our sanity, and find a great job in the process. Let's dive in.

We'll start by entering our email and answering some basic questions:

That's it. Hired will then work with over 3,000 pre-screened companies (both big and small) in 13 major metro areas (North America & Europe) to try find us a great job.

Software engineers and designers on Hired can get 5+ job offers in a single week.

Each offer will include salary and equity details upfront.

We can view interview requests and accept or reject them before talking to any company.

If we get a job through Hired, they'll give us a $2,000 "thank you" bonus!

More Reasons to Use Hired

  • Full time or contract opportunities are available
  • View offers and accept or reject them without talking to anyone.
  • Completely FREE + no obligations ever.

Hired is the real deal. They have solved some very real problems and fixed this historically messy process.

Looking for a job? Don't waste time, sign up for Hired today so you can get back to work!

Try Hired right now at littlebitesofcocoa.com/hired

Today we'll check out a library called Shoyu that aims to make setting up UITableViews a breeze. Let's dive in:

Shoyu works as a sort of DSL. It adds a source property on to UITableView, then gives as a few functions like createSection and createRow to fill the table view with content. Let's see what it takes to add a section and a row:

tableView.source = Source() { source in
  source.createSection { section in
    section.createRow { (row: Row<SpaceshipTableViewCell>) in
      row.reuseIdentifier = "SpaceshipCell"
      row.height = 52
      row.configureCell = { cell, _ in cell.nameLabel.text = "Tantive IV" }
    }
  }
}

We can use a similar technique to create and attach headers and footers to sections:

section.createHeader {
  $0.reuseIdentifier = "SpaceshipHeader"
  $0.height = 120
  $0.configureView = { view, _ in
    view.backgroundColor = .blackColor()
  }
}

There's also a few other functions to help us do things like dynamically set a row's height, or run some code when a row is selected:

section.createRow { row in      
  row.didSelect = { _ in /**/ }
  row.heightFor = { indexPath -> CGFloat? in
    return calculateHeight(indexPath)
  }
}

Last but not least, we can pass in an array of our model objects, then easily configure our cells with them:

section.createRows(spaceships) { (spaceship, row: Row<SpaceshipTableViewCell>) in
  row.height = 52
  row.configureCell = { cell, _ in cell.configure(spaceship) }
}

More info about Shoyu can be found at git.io/shoyu

Topics

#164: Swift Tricks 🐇🎩

Topics

In Bite #159, we started looking at some syntactic shortcuts in Swift. Today we'll continue by looking at a few (perhaps) lesser-known Swift tricks, and their effects. Let's get started.

@autoclosure

This attribute can help save space when writing simple closures:

func cache(key: String, @autoclosure cacheIf: () -> Bool)

Now, the compiler will infer the curly braces {} around our statement:

cache("spaceships", cacheIf: ships.count > 0)

private(set)

struct Spaceship { private(set) var name = "Untitled" }

With the private(set) declaration, we're telling the compiler this property has the default access-level of internal for reads, but writes can only happen in the source file where it's declared.

For frameworks, we can configure both the getter/setter explicitly:

public struct Droid {
  public private(set) var number: String
}

final

When optimizing performance-critical code, dynamic dispatch can be our enemy.

If our class's properties and functions can be overridden by subclasses, we're going to pay the performance cost of an indirect call or access every time we use one of those functions or properties.

We can easily prevent this by declaring a property or function final.

This way, any attempts to override it will result in a compile-time error. We can also declare a class final, which applies the final keyword to all the class's functions and properties.

Page 20 of 38