Gtdjedi Podcast - Ep012 - Notification Organization

Hosts: Clay Russell, Jerry Goldbaum & Timothy Broder

Jedi Tricks from Around the Web (check out our website for links to all these GTDJedi Tricks)

Secret Safari Shortcuts by Rene Ritchie

How Email to 2Do Has Improved My Daily Email Workflow by Federico Viticci

Ultimate Omnifocus Evernote Integration That Actually Works by Alpha Efficiency

How to Master Slack at the Office by Jessica Plautz

If you, our listeners, have at trick you would like to share with us, simply tweet us @GTDJedi.

The Big Discussion

Notification Management

Jedi Weapons of Choice

Clay - my Apple Watch

Jerry - Notify, Apple Watch, Outlook

Tim - Slack, General iOS/Mac practices

Activist Engineering

What matters is that you’re the engineer that’s noticed this capital-B Bad Idea. You know why it’s a problem. This time it’s not just the technical debt or the time it’d take to implement. This idea is bad because it trades a worse product for a better “business”: revenue, eyeballs, impressions, you know the drill.

You have a choice in this moment. You can stay quiet and hope it goes away or point it out, question it, and even argue against it

Giving Better Code Reviews

Great read. I would have ended up quoting most of it. Enjoy

Your team is only as good as your weakest reviewer.

Trust no one

Giving a valuable code review requires that pull requests are small (<200 lines as a rough gauge)

Testing UIViewController Transitions with Quick and Swift

The examples below are using the Quick test framework, but the principals we're going to talk about can be used in any setup.

We have some complicated logic further down our user registration flow. I want to make sure that the right UIViewControllers are appearing when they are supposed to. I've been reading a few different approaches on how to handle this. Below is where I've ended up, and I'm pretty happy with it.

For simplicity's sake, I'm going to show how to test if the user has tapped "Login" or "Register" on our opening screen. We can assume we have a LoadingViewController which represents the first screen. On this screens are two buttons, which correspond to these actions:

@IBAction func tapLogin(sender: AnyObject) {
    self.navigationController?.pushViewController(self.storyboard?.instantiateViewControllerWithIdentifier("loginview") as! LoginViewController, animated: true)
}

@IBAction func tapRegister(sender: AnyObject) {
    self.navigationController?.pushViewController(self.storyboard?.instantiateViewControllerWithIdentifier("registerview") as! RegisterViewController, animated: true)
}

We also have a UINavigationController taking care of the view hierarchy. I also want to use the transitions and IDs already set up in the Storyboard.

Let's start by referencing the UINavigationController and the UIViewController we're going to start with.

class LandingScreenUITests: QuickSpec {
    override func spec() {
        describe("Landing Screen") {

            var viewController: LoadingViewController!
            var navigationController: UINavigationController!


        }
    }
}

Next, we're going to instantiate the storyboard, both controllers, and push the VC onto the view hierarchy

beforeEach {
    let storyboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))
    viewController = storyboard.instantiateViewControllerWithIdentifier("loadingview") as! LoadingViewController
    navigationController = storyboard.instantiateViewControllerWithIdentifier("navigationcontroller") as! UINavigationController

    navigationController.pushViewController(viewController, animated: false)

    let _ =  viewController.view
}

Two gotchas to watch out for here:

  1. Make sure Main.Storyboard is available in your Test target
  2. Make sure to use the self.dynamicType bundle above

Missing either of these may result in a weird casting error:

Could not cast value of type 'MyApp.LoadingViewController' (0x10b9f5e50) to MyAppUITests.LoadingViewController' (0x11f894370).

Finally, lets call the appropriate methods on our initial UIViewController, and test the type of the UIViewController that has been put on the top of the hierarchy. Note: I use toEventually here to wait for the transition animation

describe("User wants to log in") {
    it("taps Login") {
        viewController.tapLogin(self)
        expect(navigationController.visibleViewController).toEventually(beAKindOf(LoginViewController))
    }
}

describe("User wants to register") {
    it("taps Register") {
        viewController.tapRegister(self)
        expect(navigationController.visibleViewController).toEventually(beAKindOf(RegisterViewController))
    }
}

For reference, here is the whole test class together:

import Foundation
import Quick
import Nimble
@testable import MyApp

class LandingScreenUITests: QuickSpec {
    override func spec() {
        describe("Landing Screen") {

            var viewController: LoadingViewController!
            var navigationController: UINavigationController!

            beforeEach {
                let storyboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))
                viewController = storyboard.instantiateViewControllerWithIdentifier("loadingview") as! LoadingViewController
                navigationController = storyboard.instantiateViewControllerWithIdentifier("navigationcontroller") as! UINavigationController

                navigationController.pushViewController(viewController, animated: false)

                let _ =  viewController.view
            }

            describe("User wants to log in") {
                it("taps Login") {
                    viewController.tapLogin(self)
                    expect(navigationController.visibleViewController).toEventually(beAKindOf(LoginViewController))
                }
            }

            describe("User wants to register") {
                it("taps Register") {
                    viewController.tapRegister(self)
                    expect(navigationController.visibleViewController).toEventually(beAKindOf(RegisterViewController))
                }
            }
        }
    }
}

Many thanks to the blog posts referenced at the top of this post

Tektok Podcast - Ep023 - Overly Connected

I had the pleasure of joining the Tektok podcast this week

Episode #: 23

Date: 01/25/16

Hosts: Brian Feldhaus,Timothy Broder & Clay Russell

TEK Topics

Brian: Android in more places. How do you feel about this??

JetBlue entertainment system, Clover payments, etc.

Tim: Communication: we are way past email and texting with slack, hangouts, Facebook groups, basecamp, hip chat, etc.

What is everyone using to communicate at home and at work?

Clay: Getting to Know our Panelists:

Name one app, movie, TV show, book and album that best define who you are.

Sweet & Sour TEK

Tim: Nuzzle for iOS

Clay: Interact for iOS (Universal $4.99)

The Wertzone: A History Of Epic Fantasy - Part 1

Rather than simply throw up my own list (although I may put together a Gratuitous List of such in the coming weeks), I thought it might be more interesting to look at epic fantasy, or at least the modern interpretation of the subgenre, through a chronological perspective. This has the benefit of allowing works to be listed without too much regard for whether they're any "good" or not, but more by their importance in the development of the field.

I'm only about 1/4 way through reading this blog series but it's very well written, I'm learning new things, and adding PLENTY to my goodreads list.

Highly recommend if you are a fan of the genre

Vagrant 1.8 is out! Linked clones, snapshots, port, ansible and more!

Vagrant 1.8 is out and it's a huge update. My 3 favorite features are below. Click through above for the full list

Snapshots are a feature of hypervisors that allow the point-in-time state of a virtual machine to be saved and restored

This is awesome. No more copy disks around or worrying you forgot to back up the DB or git stash!

New command: port - This will display a list of forwarded ports to the guest machine. This is especially useful if Vagrant is auto-correcting ports in the case of collisions.

New provisioner: ansible_local - This executes Ansible on the guest machine rather than on the host machine.

Why Quizup Turned The Fastest-Growing Game In History Into A Social Platform

Being data-driven helped grow QuizUp from a hot new game that could acquire users into a social platform that could keep them around. They worked to understand how people were using their app, and what actions lead a user to be retained. Then they worked as a team to develop QuizUp’s social features and solve the second half of the growth formula. In the process, by utilizing usage data throughout the development process, they created the thing that their customers had been telling them they wanted all along.

Installing Vagrant and other Hashicorp products using brew cask on OSX

Came accross this awesome gem today while setting up a new laptop

➜  ~  vagrant
zsh: command not found: vagrant
➜  ~  brew cask install vagrant
==> Downloading https://releases.hashicorp.com/vagrant/1.7.4/vagrant_1.7.4.dmg
Already downloaded: /Library/Caches/Homebrew/vagrant-1.7.4.dmg
==> Running installer for vagrant; your password may be necessary.
==> Package installers may write to any location; options such as --appdir are ignored.
==> installer: Package name is Vagrant
==> installer: Installing at base path /
==> installer: The install was successful.
🍺  vagrant staged at '/opt/homebrew-cask/Caskroom/vagrant/1.7.4' (6 files, 82M)
➜  ~  vagrant
Usage: vagrant [options] <command> [<args>]

    -v, --version                    Print the version and exit.
    -h, --help                       Print this help.

Common commands:
     box             manages boxes: installation, removal, etc.
     connect         connect to a remotely shared Vagrant environment
     destroy         stops and deletes all traces of the vagrant machine
     global-status   outputs status Vagrant environments for this user
     halt            stops the vagrant machine
     help            shows the help for a subcommand
     init            initializes a new Vagrant environment by creating a Vagrantfile
     login           log in to HashiCorp's Atlas
     package         packages a running vagrant environment into a box
     plugin          manages plugins: install, uninstall, update, etc.
     provision       provisions the vagrant machine
     push            deploys code in this environment to a configured destination
     rdp             connects to machine via RDP
     reload          restarts vagrant machine, loads new Vagrantfile configuration
     resume          resume a suspended vagrant machine
     share           share your Vagrant environment with anyone in the world
     ssh             connects to machine via SSH
     ssh-config      outputs OpenSSH valid configuration to connect to the machine
     status          outputs status of the vagrant machine
     suspend         suspends the machine
     up              starts and provisions the vagrant environment
     version         prints current and latest Vagrant version

For help on any individual command run `vagrant COMMAND -h`

Additional subcommands are available, but are either more advanced
or not commonly used. To see all subcommands, run the command
`vagrant list-commands`.

➜  ~