David McGraw http://www.xmcgraw.com Learn and how to build better mobile products Wed, 12 Jul 2017 14:59:08 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.10 Communication Tactics For Remote Companies http://www.xmcgraw.com/communication-tactics-for-remote-companies/ http://www.xmcgraw.com/communication-tactics-for-remote-companies/#respond Fri, 17 Feb 2017 03:15:53 +0000 http://www.xmcgraw.com/?p=878 In 2003 I was serving in the Marine Corps as my team rolled across the line of departure into Iraq. We trained exceptionally hard to minimize communication failures, but we expected them to happen and trained for it. The phrase “communication kills” was often used among us during training to lay emphasis on the importance. […]

The post Communication Tactics For Remote Companies appeared first on David McGraw.

In 2003 I was serving in the Marine Corps as my team rolled across the line of departure into Iraq. We trained exceptionally hard to minimize communication failures, but we expected them to happen and trained for it. The phrase “communication kills” was often used among us during training to lay emphasis on the importance. If we failed to transmit information in a timely manner people could get hurt or killed. And despite being part of a team behind the front line responsible for keeping communication going between the front and rear, my brush with that phrase reared it’s ugly head a few weeks into our march to Baghdad.

This wasn’t when bullets were flying through the air. This was much simpler. This was a logistics communication failure preventing food and water from reaching our location until well beyond our need–forcing us to become a little creative.

Of all of my moments in the military I often reflect back to the moments where communication broke down. They tend to correlate well to the remote office and the startup lifestyle I live now. As a remote contractor everything revolves around communication. What methods do I use to reach my team? Are the right stakeholders being informed? Where are inefficiencies that make what I do difficult? When do I need to be annoying in order to motivate progress?

Over the years I’ve experienced my share of communication breakdowns that led to angry clients, failed startups, and a mountain of thoughts on how I’d do it if I was 100% in charge. I know how important it is to hit the communication mark and what happens when the team misses it in a remote environment.

Read on to learn about
  • Why transparency, leadership, and even celebrating play a critical role
  • The value of consistency by formalizing communication channels
  • How employees and leaders might suggest ways to improve the current virtual environment

I plan to share more thoughts on remote working so be sure to subscribe to my newsletter if this, startups, or mobile development interests you. Let’s dive in.

Being Present Within a Remote World

An inherent issue with a remote culture is that team members do not get authentic face time with the people they work with until the company begins to invest in bringing people together. This lack of face time makes it much harder to build meaningful relationships filled with true camaraderie–the foundation of loyalty.

Remote employees begin within an isolated circle and effort must be made, by all parties, to pull each other closer. The result from not putting effort into this creates a team that’s further disconnected from the company and vice versa-—making it much easier for either party to part ways or disconnect.

Additionally, this lack of face time puts a lot of pressure on trust. When leaders cannot see the day-to-day behavior of an employee, or the employees cannot see the actions of their leaders, the door is wide open to alienation.

I’ve worked with founders who lacked desire to work with remote contractors but they felt it necessary. This lack of desire created extreme distrust out of the gate. What worked well for the employer didn’t work well with remote employees. They found more value from face-to-face meetings than technology tools like Google Hangouts or Skype, which created unnecessary burden flying people in for meetings. They tended to rely too heavily on those meetings which were not happening that frequently.

I’ve also worked with startups who were 100% invested in the remote way but were not being operated by founders who understood the lifestyle. Companies worry about employees not fitting the remote culture. It works the other way around as well. If contacting founders, and other leaders, is a chore during an interview or trial employment be careful.

Here is how I’d advise one thinking of improving this issue:

  • Daily stand ups are a great way to get the team together, but difficult to scale as the team becomes global. Given the required coordination, gathering everyone is something that should be done sparingly, perhaps once a week (minimally). Stand ups should become focused on a team-by-team basis when the overall size gets large enough.
  • Create a channel in your chat application called #CHICO, where team members check-in / check-out during the week. The check-in consists of 1-3 items they plan to attack that day. The check-out consists of how well the day went. They are freely able to @ team members to alert them that something is blocking them. If further discussion is needed jump on Google Hangout or Skype. Alternatively, check out iDoneThis or WorkingOn.
  • Pair team members up on a weekly basis. This can be a very simple 1:1 Skype or Google Hangout where people get an opportunity to get to know someone else within the company. People are going to get stuck with the same group and this will facilitate outreach. Help spark the conversation by creating a few non-work related talking points.
  • When money is less of an issue get everybody in the same location at least once a year. I’ve seen companies to this 2x. The goal is to pull the team outside of their comfort bubble and used as a team-building opportunity. Half of the time is used for work and half is used to enjoy time together. Think Camp No Counselors. Make sure there are things that a wide range of people would like to do (from extroverts to introverts).
  • If you are operating a hybrid business (remote + on-site), I encourage giving on-site employees a day where they work from home. I’ve seen some dedicate 1 week in the year. It’ll provide perspective that could be valuable to the company at large.
  • Hire (or promote) someone to assist with culture building. While it’s true some of this will be organic, having a dedicated mind thinking about this will help facilitate communication. This person should focus on making sure the team is finding tools that work well, organizing events, interacting and answering any questions or concerns among employees.

At the end of the day employees will feel isolated from the business unless effort is put into bringing them into the fold. Transparency goes a long way to help.

Open The Curtains

Companies who open the door to the virtual office must come to understand the value of transparency. The more that’s hidden the less investment a company will get from a remote employee. Companies must create processes that facilitate opening the company up for the viewing of others and trust that they can handle such data. Aim for Buffer.com-level internal transparency, while understanding that nobody outside of the business needs to know what’s going on.

Help employees answer the questions:

Why are we here? Where is the company vision and purpose? How well is the business aligned today with the current direction? What values guide us?

Where are we going? What are we researching and building?

Who do I work with? Who are my colleagues? Where can I find an org chart that shows who is remote vs. on-site, contact and timezone information, and other relevant information?

How is the business doing? How are revenue streams looking? Where can I read about latest funding rounds?

The founders I’ve worked with who held company information as sacred were difficult to trust. You could tell they were not running a well-oiled operation and it made me and other contractors less invested with where the business was going. People left far too easily since they couldn’t see how their work impacted the business.

Enjoy The Moments

All too often teams do not stop to appreciate what was accomplished; at the company level or the employee level.

Every employee, remote or on-site, needs to feel a sense of worth. However, remote employees don’t have the luxury of hallway high-fives or a team lunch that they may receive praise from. This impacts one at a psychological level and matters more than leaders think. Think about it. If you’re never praised or rewarded for the effort it’ll be impossible to feel that you’re impacting the business or that your effort is valued. That makes it much easier to walk away from the position. Who cares about my work?

Find ways to celebrate victories of the business and those deserving team members. Here are a few ideas:

  • Highlight wins (small and large) during team meetings; call people out
  • Use a point system in Slack that let’s people share praise by @x++ or by throwing microbonuses via Bonusly
  • Encourage that those at the top of the org chart provide individualized praise
  • If your product receives physical recognition, like an Award, send a replica to every employee
  • For team members who value monetary rewards create a cash or option bonus

Celebrating or sharing praise is something I rarely see founders build into a remote environment. It’s not the easiest to cultivate, but has a serious opportunity to motivate folks to care more about the company, founders, and their team. Team members are paying attention when their leadership is or is not valuing the effort they put forward.

Standardize Communication Channels

Communication happens all over the place with a remote team. For mismanaged teams this can become a massive headache.

The one place communication should be discouraged is e-mail. While some members need to use e-mail to communicate with external vendors, it has no place for 99% of the team. The information transmitted between team members have enormous value to the entire team. Companies feel that impact the most when a critical team member leaves and nobody has record of how they do anything. The newcomer shoved in the position is left with a mess of a situation to untangle.

Discussing code-related bugs should happen on a ticket inside of a source control product like JIRA or Github.

Virtual meetings should have someone dedicated to recording notes for everyone to review (including those who couldn’t make the meeting).

Design should stay within a prototyping tool like InVision, Sketch, Photoshop — with those files available via Dropbox or OneDrive.

Road-mapping should happen in a project management tool like Asana, Basecamp, or JIRA.

Casual discussion should stay within a communication platform like Slack or Fleep.

I’ve worked with founders who made it very difficult to standardize things like this. If you’re a founder don’t push back on the thought of bringing structure into the fold otherwise everyone is going to suffer on the communication end. Things will become so disorganized that you’ll waste effort on needless catch up. Keeping content organized will benefit the entire team long after it’s written. If there is no structure you can bet team members will follow suit, do whatever they please, and focus on the wrong communication channels that create headaches later (email, text message, phone conversations).

I’ve worked with founders who only used text messages. Let me tell you… actually, I’m not–that was a nightmare.

It Starts At The Top

Have you noticed a theme yet? I put a lot of pressure on the leadership team in this article. Great communication is guided from the top and carried from there. What leaders care or don’t care about trickles down to every member around them. The identity of a business is largely formed around the identity of the founding team. This is exactly why we create a set of values which guide how we operate. Leadership cannot expect every employee to buy into the mission like they do, thus structure is required (how flat organizations ever gained traction is beyond me).

A great remote working environment starts with leaders who have experience with the remote lifestyle. If the current team does not have direct experience they should be curious enough to learn in order to emphasize and adjust strategy. These people will set the example and push where necessary in order to keep things on track.

Leaders who fails to communicate regularly will make it tough on the team to do so effectively, which is a big problem when remote employees don’t have a large net of people to speak to. The behavior of employees directly reflect the leadership team around them, which will help or hurt the entire team. We can’t expect an individual to carry the load by themselves. I’ve tried multiple times and it never works.

Finally, the leadership team must be willing to accept when someone does not work within the expected communication framework. Move on. An employee could be in the top 1% in skill set, but lack the mindset that works well within a virtual office. This should strike the same vein hire slow, fire fast. If you hire someone and they are difficult to reach then you should immediately feel that it’s not the right fit. I’ve seen founders “suck it up” and deal with remote employees who pulled their chain; I’m moving… I’ve got code coming… I’ve hit a snag and can’t push the code to Github… I’ve… You should never be chasing employees or buying into excuses as to why they didn’t deliver what they said they would–move on! Period. I understand having heart and empathy, but good remote employees understand the value of being on time, delivering results, and showing you very real reasons why they couldn’t do what they said they would–that’s why we’re still remote!

Strive for Strong Communication

We’re nothing without effective communication. Startups die, ideas fade, relationships sour, and progress comes to a halt without it. Thankfully nobody will die, but companies who do fail to build a remote team almost always reflect back on things that could have been solved with better communication.

Remote working takes serious effort on all sides, which is why we need to hire people suitable for the job. Remote workers need experience juggling various communication streams. Leaders need to understand the lifestyle. Minimize and standardize the process to reduce this burden to maximize the value the remote worker can emit.

Distance is not the problem. A lack of communication is.

If you got any value from this post I need your help. Here’s a handy pre-populated Tweet to help you share it via Twitter. Share it with colleagues or even your community on Reddit.

The post Communication Tactics For Remote Companies appeared first on David McGraw.

http://www.xmcgraw.com/communication-tactics-for-remote-companies/feed/ 0
Early Apple Watch Thoughts http://www.xmcgraw.com/early-apple-watch-thoughts/ http://www.xmcgraw.com/early-apple-watch-thoughts/#respond Thu, 30 Apr 2015 15:49:40 +0000 http://www.xmcgraw.com/?p=840 I’m a huge fan of wearable technology. Not every piece of wearable, sorry Glass, but anything that I can wrap around my wrist. Up until this point I’ve used various fitness trackers to monitor my activity throughout the day. These days I prefer the Misfit Shine to anything else and continue to wear it. I […]

The post Early Apple Watch Thoughts appeared first on David McGraw.

I’m a huge fan of wearable technology.

Not every piece of wearable, sorry Glass, but anything that I can wrap around my wrist. Up until this point I’ve used various fitness trackers to monitor my activity throughout the day. These days I prefer the Misfit Shine to anything else and continue to wear it. I once mourned the loss of my shine and they reached out to replace it for free. It says a lot about a company who reaches out to you before you even try.

Given my fascination with wearables I had to give the Apple Watch a spin. This is my first watch simply because the urge to buy an alternative never materialized. That’s not a jab at the other players, but they all operate in a completely different realm. The only one I was close to buying was the Microsoft Band, which I would have if I didn’t know about the Apple Watch.

I’m very curious to see if this watch will become more than a development device. If it’s something I’ll continue to wear or rest on my desk for development.

The early signals are mostly positive.

The watch is surprisingly comfortable to wear

While I notice it’s there, especially compared to my Misfit, the band material is so smooth it doesn’t become a distraction. I originally ordered a 38MM given how small my wrists are (152mm), but had the opportunity to receive an expedited 42MM. The size looks just fine on these skinny wrists.

The watch is confusing

It’s no wonder Apple created the retail store experience the way they did. People would have been absolutely lost.

Given the constraints, and as a developer, I understand that there is a lot to pack in here. That said it requires patience until Apple irons out a better onboarding experience. For instance, it took me a while to change the watch face despite seeing it done in videos in the past… Given how new force touch is you’d expect it, plus changing the watch face, to be part of onboarding. It also took me a while to realize I could double press the side buttons — the top taking you to a previous app, the bottom opening Apple Pay. Or, discovering that swiping your finger edge-to-edge (back 2 screens) is different than swiping from the center of the screen (back 1 screen). I’m also aware of areas that require a triple-tap…

Then, all of your notifications are enabled by default, which will be a nightmare if you don’t obsessively block them like I do. So the first few things you’ll want to trim are notifications, glances, and apps you feel are important to have on your wrist. 

Nothing here is a deal breaker, it just requires patience on the end user and more fine-tuning by Apple.

The watch does have apps worth having immediate access to

I’ve seen folks say how useless a watch like this is when their phone is nearby. I can safely say that I’ve noticed a handful of apps that just simplify the experience (for me). I’ll discover more as I spend more time with this, but a few very useful apps:

  • Alarm.com — easy on/off switch
  • Personal Capital — easily check weekly / monthly spending
  • Nike+ — Fire up a new run
  • Activity — Remind me to stand up at my desk (which is surprisingly nice)
  • Watchface Widgets — easy access to the date, temperature, sunset time
  • Now Playing — More easily control your music

These are just a few that I’m finding extremely useful to have access to. Again, this really requires patience to set the experience that fits your style. You can have 20 glances, but do you need 20 glances? Probably not. I’m going to stick around 10, with the first 5 being super important. I don’t need all notifications on, I need a handful. I don’t need all apps installed, I need the ones that make sense. This is an entirely different experience we’re getting used to.

An interesting observation is that I find myself focused on glances much more than going to the field of circles to open an app. I rarely see the need.

The watch is not every app’s playground

If you’re reading this as a developer it would be wise to consider what value your app could bring to the watch. Does the experience make sense? Crafting a good watch experience should take time. Given most use cases, most apps will not make sense on a Watch. It’s one thing to build a watch extension for fun, but it’s something entirely different if you expect it will magically drive sales. From my usage I only care about the apps installed on my phone already. I’m seeking a closer relationship with apps I’m familiar with. The trust and loyalty is already there. You’re really building an extension for your current base. This may change when apps go native, but I’m doubtful unless the watch app simply doesn’t have an iPhone app.

Closing Thoughts

My time is early with this watch, but things are looking good. Do you need to buy an Apple Watch and ignore alternatives like the Pebble or Moto360? Not at all. What I hope to convey is the value of having a wearable. There are great use-cases for it. Playing Angry Birds is not one of them, but keeping track of your spending, activity, most important tasks, and other things may be very valuable to you. There’s no need to dig for your phone for some of these things. Customize the experience that works for you.

The post Early Apple Watch Thoughts appeared first on David McGraw.

http://www.xmcgraw.com/early-apple-watch-thoughts/feed/ 0
13 Xcode Tips That Will Help You Conquer Xcode http://www.xmcgraw.com/13-xcode-tips-that-will-help-you-conquer-xcode/ http://www.xmcgraw.com/13-xcode-tips-that-will-help-you-conquer-xcode/#comments Tue, 17 Mar 2015 11:00:58 +0000 http://www.xmcgraw.com/?p=795 When it comes to iOS development tools there is one that every iOS developer is intimately familiar with. Xcode is the driving force that makes all of the amazing iOS apps possible. What is less-than-comforting—especially to newcomers—is the sheer amount of things that Xcode can help us do. To those new in this area Xcode […]

The post 13 Xcode Tips That Will Help You Conquer Xcode appeared first on David McGraw.

When it comes to iOS development tools there is one that every iOS developer is intimately familiar with. Xcode is the driving force that makes all of the amazing iOS apps possible.

What is less-than-comforting—especially to newcomers—is the sheer amount of things that Xcode can help us do. To those new in this area Xcode can feel incredibly overwhelming. To those with years of Xcode experience still find themselves learning little details that improve their productivity. My message to those new to this space is to not drown yourself out by learning everything there is to know about Xcode. Focus on the important elements that matter today and let your experience guide you to new areas of the tool.

In this article I’m going to cover several elements of Xcode that will help increase your productivity. A few of the things we’ll cover are a set it and forget it, while others aim to reduce daily headaches.

  • You’ll learn how to customize Xcode to improve your productivity
  • You’ll learn a few features of Xcode that will help manage your code
  • You’ll learn a few tips that will help your overall project development

Xcode Behaviors

Behaviors are an amazing way to automatically have Xcode perform actions based on your actions. Imagine if you are running your project and hit a breakpoint or error. By default Xcode will automatically open the debugger windows, navigate to the code in error, and completely throw your editor out of sync. Let’s explore creating a new behavior to stop that from happening.

Xcode Behavior

Navigate to Xcode Preferences and you’ll see a tab called Behaviors. Here we can define what happens when we experience various state changes. What happens when a build start? What happens if it succeeds or fails? You can have Xcode play a sound, open new tabs, show navigators, and much more.

For this example, we want to perform behaviors when our app is running. When the app pauses, due to a breakpoint or error, we would like to do the following:

  • Play a sound (Hero sounds good to me, but you can switch it to something else—including custom)
  • Show a new tab called debug
  • Show the debug navigator
  • Show the debugger with Variables & Console

Xcode Pause Behavior

The reason I want this behavior to open a new tab is that I don’t want Xcode to step on my current working state. I can easily switch back to where I was coding with my source file and cursor where it should be. I’m also not closing a bunch of panes that Xcode opened for debugging. That entire experience is focused inside of a separate tab.

Take some time to explore the possible behaviors to fit your own development style. You may find that certain things happen by default to be annoying. This is how you could possibly turn that off.

Manage Devices & Simulators

Have you ever wondered if you can manage the device list that shows up in the Xcode device drop down?

Xcode Devices

How about accessing that database you have on your device so you can verify tables populated properly? Have you ever opened that drop down and noticed that Xcode lost all of your simulators? Navigate to Window > Devices.

Xcode Device Window

Here you can see our connected devices and available simulators. If you need to add or remove simulators press the + button on the lower left. As a warning, Xcode likes to lose simulators so you’d restore them by visiting this area.

Xcode Device Simulators

Finally, one other useful thing in this area is the ability to download app containers.

Xcode Device Container

You’re probably used to accessing data through the simulator directories, but what about the device? You can sense how useful it would be to easily access saved photos, database files, etc. To access that data on the device you can download a container containing the documents, library, and tmp directories.

Update App Display Name

One common issue folks run into is that they create a project only to find out that your display name isn’t what you want. I’ll often see people renaming and refactoring their entire project name to show the proper display name. You’ll be happy to know that there is a key you can add to your project info plist. Add a new key Bundle display name.

Xcode Display Name

Improve Readability & Extend Xcode

There are some great plugins available for Xcode that provide a boost to productivity. Folks are even creating very nice custom themes that replace the default presentation of Xcode. Because, let’s be honest, the default theme is painful. So how can we more easily discover what is available? Make the jump over to alcatraz.io to install a very nice package manager for Xcode.

Xcode Alcatraz

Here are a few that I currently use:

  • SCXcodeMinimap : This may look familiar from your Sublime Text usage! Easily see and scroll through your code
  • RevealPlugin : If you use Reveal this is a great way to hook into and launch Reveal
  • RealmPlugin : Realm model object template file
  • VVDocumenter-Xcode : Helps to quickly generate comments for a method
  • AdjustFontSize : When showing code off you may want to quickly increase font size, simply use CMD +/- with this plugin
  • Lin : Shows code-completion for NSLocalizedString

A localization plugin under development, Rephrase, is worth watching. This looks like it will be a great time saver once it’s launched.

My current theme is Dusk, which is a default theme I believe. There are a lot of color themes you can download via Alcatraz to explore.

Download Documentation and Older Simulators

When you install a new version of Xcode you may notice that you don’t have simulators available for older iOS versions. This can be a problem when it comes to testing. You can install these through the preferences download area.

Xcode Downloads

Here you can download the older simulators and manage them through Window > Devices. You also have access to documentation that doesn’t come pre-loaded with Xcode.

Organize Source Files

When navigating a source file you can access all of the properties and methods via a drop down above the source file.

Xcode Bar

When you click the above area a drop down will appear revealing details about that file. Within your source code you can leave markers such as // FIXME: or // TODO: or // MARK:.

Xcode Bar Expand

Quick Open Files

You may find yourself needing to open a new file, but wanting to keep your current file open at the same time. There are a few ways to do this.

You could open your assistant editor and switch files from there. Go to View > Assistant Editor > Show Assistant Editor.

You could double-click on the file you wish to open. This will quickly open a separate window entirely.

You can have a little more flexibility by pressing Option + Shift + Click. This will pop up a useful window that lets you choose where to open the file.

Xcode Open File

Jump To Definition

Being able to quickly jump to the documentation you’re working with is a time saver. You may be working with a UITableViewDelegate and forget all of the methods associated with it. You can quickly jump to a symbol by pressing Command + Click.

Documentation Generation

Instead of manually typing out comment blocks download and install the plugin VVDocumenter-Xcode. This will let you quickly generate comments by just typing three slashes (///).

Xcode Comment

The side benefit from doing this is that Xcode will use these comments to show preview documentation of the method. By pressing Option + Click on the method you’ll see a documentation quick look.

Xcode Doc Quick Look

Creating Code Snippets

Code snippets are extremely valuable where you see yourself routinely typing the exact same format over-and-over again. For example, I have snippets that automatically fill out a new table or collection class with the delegate methods I care about. I also have smaller snippets that help me quickly create typealias, singleton, gdc calls, and others.

To create a snippet open the snippet panel from the file inspector.

Xcode Snippets

You’ll type out the code you wish to create a snippet from. An important note that if you need placeholders you’ll type <#placeholder-name#>. You’ll then click, hold for a second, then drag the code into the snippet area.

Xcode Snippet Edit

You’ll then be able to edit the snippet to add more details. The most important detail would be the Completion Shortcut. This will be the keyword you type in your editor to be able to use it. Alternatively, you can click + drag the snippet out of the snippet area.

One of these days I’ll gather up all of my snippets and share them.

Enhanced Debugging With Chisel

Facebook built a collection of LLDB commands to help make debugging a little more enjoyable. If you don’t have these take the time to jump to Github to install them. To give you a sense of what this provides here is a list of a few favorite commands. These commands save a ton of time and brain power trying to remember the syntax.

  • views : print the recursive view description for the key window
  • visualize : open a UIImage, CGImageRef, UIView, or CALayer in Preview.app on your Mac
  • show/hide : show or hide the given view or layer
  • border/unborder : show or hide a border to a view or layer to visualize where it is

There is a lot more to chisel so jump into lldb and type help to review a list of user-defined commands.

Version Editor

If you quickly need to check what all you’ve changed in a file you can take advantage of the built in version editor instead of messing with Git.

Xcode Version Editor

You can quickly open the version editor by pressing the arrows on the top-right of the window or going to View > Version Editor > Show Version Editor. You could imagine having a lot more test code that you have no desire to commit. The version editor will show those changes while allowing you to quickly discard them. You could clearly use your source control UI to do this, but this is easy enough.

6 Key Commands Worth Memorizing & Setting

Some of these commands are not set by default, but I encourage you to open Preferences > Key Bindings to modify them as needed.

  • Command + / : comment/uncomment code
  • Command + [ or ] : indent/unindent code
  • Command + Left/Right Arrow : navigate to the beginning or end of line
  • Control + s : select word
  • Option + Command + e : edit the selected word based on the current scope
  • Option + Left/Right Arrow : navigate words
  • esc : bring up possible auto-completion choices

There are many, many more key commands. Find the commands that fit your style and roll with it.


In article we covered several practical bits of information related to tool you’ll use the most—Xcode. Much of what I’ve showed here are things that I constant take advantage of to improve my productivity. I don’t strive to be recklessly fast (you won’t see me only using a keyboard), but I do strive to spare myself repeated headaches. As you gain more experience you’ll find what works best for you. That’s the key. Soak in what you will from this article and apply it to your own process.

The post 13 Xcode Tips That Will Help You Conquer Xcode appeared first on David McGraw.

http://www.xmcgraw.com/13-xcode-tips-that-will-help-you-conquer-xcode/feed/ 1
How To Build An iOS Spotify App With A WatchKit Extension http://www.xmcgraw.com/how-to-build-an-ios-spotify-app-with-a-watchkit-extension/ http://www.xmcgraw.com/how-to-build-an-ios-spotify-app-with-a-watchkit-extension/#comments Tue, 24 Feb 2015 12:00:26 +0000 http://www.xmcgraw.com/?p=773 [alert color=”yellow”]Heads up! I have a couple of special surprises for the next Discover iOS Letter (hint: tools + savings + ???). Learn more about the letter. It’ll be in your inbox March 1st![/alert] Time is flying! I last wrote about WatchKit when it was introduced back in November of 2014. Around the same time […]

The post How To Build An iOS Spotify App With A WatchKit Extension appeared first on David McGraw.

[alert color=”yellow”]Heads up! I have a couple of special surprises for the next Discover iOS Letter (hint: tools + savings + ???). Learn more about the letter. It’ll be in your inbox March 1st![/alert]

Time is flying! I last wrote about WatchKit when it was introduced back in November of 2014. Around the same time I started this little site of mine! If you’re one of the many returning visitors, thanks for sticking around!

Tim Cook confirmed during an earnings call in January that the Apple Watch would ship to consumers in April. If you haven’t spent any time with WatchKit it’s never to late to dive in! I’m picturing a lot of companies thinking about their iOS project in 2 lights. How can we provide a great experience on the user’s iPhone? How can we provide an complementary experience for those using the Apple Watch?

In this article we’ll explore building an iOS Spotify music player with an Apple Watch extension. You’ll be able to control the player in the iOS app and the Apple Watch extension. By the time you finish the article you’ll have great foundation for building your own experience.

  • You’ll learn how to integrate the Spotify iOS SDK into your app
  • You’ll learn how we can use that integration via an Extension, allowing you to pause, play, skip tracks, and view track metadata
  • You’ll understand how communication can flow between an Apple Watch extension and the parent app

Important Spotify SDK Note

The Spotify SDK is currently in beta. As of this article they are at Beta 6.

If you’d like to stream audio with the example app you’ll need a Spotify Premium account. If you don’t have an account you’ll still be able to get a sense for how all of the pieces fit together between an iOS app and an Apple Watch extension.

Without Spotify Premium you can only move through the authorization process… Not that exciting? Sorry! You can TRY Spotify Premium for 30 days just by creating a new account (nope, not sponsored for saying that… though it would be nice! Love Spotify).

Getting Started

[alert color=”blue”]Download and explore the example project on Github[/alert]

To get this party started we’ll create an application with Spotify in order to get the required credential information for the SDK. Jump over to the Spotify developer area and login.

Spotify Applications

In order to create a new app you’ll click Create An App. You already see this example app in the list, let’s take a closer look.

Spotify Example App

Here you’ll want to create a redirect URI to use in the iOS app. In this case I’m using spottifywatchexample://. I purposely removed the Client ID and Client Secret from the image, but you should see those when you create the app.

The iOS App

Now that we have an application created with Spotify we can begin working on the iOS app. Here is what we’re building.

Spotify iOS Auth

Spotify iOS Player

We’ve kept it pretty basic for this example. You’ll be able to authorize with Spotify and play a preset album that I’ve added to the project. We’ll then fetch metadata for the track and display it.

Download & Integrate The Spotify SDK

In order to integrate Spotify you’ll have to download the latest version of their SDK from their Github page. Unzip that file and you’ll be able to add Spotify.framework to your project. You’ll also need to link against AVFoundation.framework.

If you’re not already linking to -ObjC, you’ll want to add that under your Build Settings. Search for Other Linker Flags and add it there.

From there we add a URL Scheme so Spotify can open our app when it’s done authorizing the user. You can see this under the dojo-apple-watch target. Select Info and expand URL Types.

Spotify URL Type

In the image above you can see that spotifywatchexample matches the name we provided when we created our app on Spotify.

Token Exchange Service

In order for the Spotify SDK to complete the authorization process it uses a small HTTP service called a token exchange service. You’ll see this in the demo project that was included in the Spotify SDK download. Open spotify_token_swap.rb and you’ll see CLIENT_ID, CLIENT_SECRET, CLIENT_CALLBACK_URL. You’ll want to replace those values with the values from your own app that you created with Spotify.

Once those values are in place you can run the script from Terminal by calling ruby spotify_token_swap.rb. If you don’t have sinatra and/or encrypted_strings you’ll need to call sudo gem install sinatra encrypted_strings before running the script.

When the service is available you’ll reach the swap endpoint at http://localhost:1234/swap and the refresh endpoint at http://localhost:1234/refresh. The refresh endpoint is how we’ll refresh an existing session that has expired.


When the app first launches it’ll check to see if we have a valid SPTSession object. If the session object exists, it may have expired, forcing us to authorize. Otherwise, if it hasn’t expired, we can renew our session.

// If we have a valid session then we can login
if XMCSpotifyPlayer.sharedPlayer.isAuthenticated() {
} else {
    // If not, try to renew our session
    XMCSpotifyPlayer.sharedPlayer.renewSession({ (success) in
        if success {
        } else {
            // The user needs to go through the authentication process

If this is the first time authenticating the session object won’t exist at all so you’ll need to go through the login flow to authorize. Once Spotify auth returns to our app we can archive the session object away for future reference.

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
    if SPTAuth.defaultInstance().canHandleURL(url, withDeclaredRedirectURL: NSURL(string: kCallbackURL)) {
        SPTAuth.defaultInstance().handleAuthCallbackWithTriggeredAuthURL(url, tokenSwapServiceEndpointAtURL: NSURL(string: kTokenSwapUrl), callback: { (error, session) in
                if error != nil {
                    println("Authorization Error: \(error.localizedDescription)")
                } else {
                    // Store our session away for future usage
                    let sessionData = NSKeyedArchiver.archivedDataWithRootObject(session)
                    NSUserDefaults.standardUserDefaults().setObject(sessionData, forKey: kSessionObjectDefaultsKey)
                    // Update our shared player
                    XMCSpotifyPlayer.sharedPlayer.session = session
                    // Notifiy our main interface
                    NSNotificationCenter.defaultCenter().postNotificationName(kSessionWasUpdated, object: session)
    return false

Once we have a valid session we can login to the service.

func loginSession(#playbackDelegate: SPTAudioStreamingPlaybackDelegate?, delegate: SPTAudioStreamingDelegate?, completed: (success: Bool) -> Void) {
    assert(session != nil, "Don't call login if a session hasn't been created!")
    player = SPTAudioStreamingController(clientId: kClientId)
    player?.playbackDelegate = (playbackDelegate != nil) ? playbackDelegate : self
    player?.delegate = (delegate != nil) ? delegate : self
    player?.loginWithSession(session, callback: { (error) in
        if error != nil {
            println("Enabling playback failed: \(error.localizedDescription)")
            completed(success: false)
        } else {
            completed(success: true)

Playing Audio

The Spotify SDK will let you play an individual track, album, or a playlist. In this example we’re going to request an album. Once we have that album we’re going to queue it up for playing.

func queueDefaultAlbum(completed: (success: Bool) -> Void) {
        SPTRequest.requestItemAtURI(NSURL(string: "spotify:album:1ZuyuaB3hzsew72bxgCv5E"), withSession: session, callback: { (error, album) in
            if error != nil {
                completed(success: false)
            } else {
                self.player?.queueTrackProvider(album as SPTAlbum, clearQueue: true, callback: { (error) in
                if error != nil {
                    println("Couldn't queue tracks: \(error.localizedDescription)")
                    completed(success: false)
                } else {
                    completed(success: true)
                // Don't start immediately

From there we have access to a few methods available on a SPTAudioStreamingController object. You can read about several more over on the documentation.

  • skipNext : Moves to the next track
  • skipPrevious : Moves to the previous track (note: during my testing this actually cut off audio)
  • queuePlay : Begins playing back the queued items
  • stop : Stops playback and clears the queue

Track Metadata

When you begin playing a track your streaming object will contain a currentTrackMetadata property that will tell you about the track. The dictionary includes several valuable keys:

  • SPTAudioStreamingMetadataTrackName : Track name
  • SPTAudioStreamingMetadataTrackURI : Track URI on Spotify
  • SPTAudioStreamingMetadataArtistName : Artist’s name
  • SPTAudioStreamingMetadataArtistURI : Artist URI on Spotify
  • SPTAudioStreamingMetadataAlbumName : Album name
  • SPTAudioStreamingMetadataAlbumURI : Album URI on Spotify
  • SPTAudioStreamingMetadataTrackDuration : Track duration as an NSTimeInterval boxed in an NSNumber

In the example we’re taking advantage of the track name and duration. How do we get the album cover image? First you’ll need to grab the album from the URI provided, and then you’ll be able to get a URL to the cover. In the example app we refresh this when a track begins playing.

func getAlbumArtForCurrentTrack(largestCover: Bool, completed: (image: UIImage?) -> Void) {
    getAlbumArtDataContent(largestCover, completed: { (data) in
        dispatch_async(dispatch_get_main_queue()) {
            if data != nil {
                completed(image: UIImage(data: data!))
            } else {
                completed(image: nil)

private func getAlbumArtDataContent(largestCover: Bool, completed: (data: NSData?) -> Void) {
    if player?.currentTrackMetadata == nil {
        completed(data: nil)
    } else {
        let albumUri = player?.currentTrackMetadata[SPTAudioStreamingMetadataAlbumURI] as String
        SPTAlbum.albumWithURI(NSURL(string: albumUri), session: session, callback: { (error, obj) in
            if error != nil {
                println("Something went wrong when trying get the album: \(error.localizedDescription)")
                completed(data: nil)
            } else {
                let album = obj as SPTAlbum
                var imagePath: NSURL?
                if largestCover {
                    imagePath = album.largestCover.imageURL
                } else {
                    imagePath = album.smallestCover.imageURL
                if let path = imagePath {
                    // Jump into the background to get the image
                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
                        if let data = NSData(contentsOfURL: path) {
                            completed(data: data)

The Apple Watch Extension

Spotify WatchKit Player

As a reminder, the Apple Watch is a fairly limited device. It must take advantage of an existing connection with an iPhone to exchange and update data.

That said, this will change in future version where we’ll likely see native running watch apps. For now, however, that means our Apple Watch app is no more than a window into the iOS app sitting in our pocket. Not all is lost! This still makes for a fair amount of valuable use cases for those who own both devices.

In our case, we’re already listening to a Spotify track on our iPhone. Say we’re out on a run. Instead of reaching for the iPhone in your pocket or on your shoulder you could flip over your wrist to display a quick window into the app. That’s exactly what we’re doing here. You can open up our extension and transmit commands to the iOS app.

When your extension needs to contact the iOS app we can call openParentApplication from the WKInterfaceController class. In our case this is all we’re doing in our extension. We’re transmitting commands to the iOS app to trigger our audio player. In the simulator this works well, but I’m curious to see how it works with live devices.

When openParentApplication is called we provide a dictionary that the iOS app can then example. For example, we call to the iOS app when our extension launches in order to verify we’re authenticated. If we’re not authenticated we need to inform the user that they need to.

Spotify WatchKit Auth Needed

// Extension: Call the parent iOS app
WKInterfaceController.openParentApplication(["trigger" :"auth"], reply: { (replyInfo, error) in
    if let value = replyInfo["value"] as? String {
        if value == "true" {
        } else {

// iOS App: Handle incoming request and provide a reply
func application(application: UIApplication!, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!, reply: (([NSObject : AnyObject]!) -> Void)!) {
let trigger = userInfo["trigger"] as String
    if trigger == "auth" {
        let value = XMCSpotifyPlayer.sharedPlayer.isAuthenticated()
        if value == false {
            reply(["value": "false"])
        } else {
            reply(["value": "true"])
    // … (lots of other code removed, review the AppDelegate.swift from the repository)

We check our model object and fire a response back to the extension.

Here is our flow when the extension is launched:

  • Check that we have an authorized session object
  • Perform login
  • Add our album to the queue

Once the user taps play in the extension:

  • Begin playing the queue
  • Fetch metadata (title, duration)
  • Fetch album artwork

Ideally this would include a step that simply checks the iOS app to see if a track is currently playing. If so, display metadata and open up control to pause and skip tracks. At the moment that interaction is difficult to test because of the way the simulators work. Having an iOS app and an extension active at the same time doesn’t work right now. So, for now, I’ve just made the watch perform the same actions as the iOS app.

When we go to fetch the album cover from the extension we’ll pass through the same code block as before, but we’ll do 2 things differently.

  • We’ll fetch the smaller album cover so we’re not transmitting so much data
  • We’ll skip converting the data object to a UIImage (the extension can handle that)

If you haven’t explored the example app I encourage you to do so in order to see how all of this looks in practice.


Creating an Apple Watch app can be a great way to encourage more user engagement. Making things much easier is a simple recipe for sticking out in the mind. Find a way to compliment an existing app and explore WatchKit a little more next weekend!

The post How To Build An iOS Spotify App With A WatchKit Extension appeared first on David McGraw.

http://www.xmcgraw.com/how-to-build-an-ios-spotify-app-with-a-watchkit-extension/feed/ 4
What You Need To Know To Start Learning How To Code http://www.xmcgraw.com/what-you-need-to-know-to-start-learning-how-to-code/ http://www.xmcgraw.com/what-you-need-to-know-to-start-learning-how-to-code/#comments Tue, 17 Feb 2015 11:00:22 +0000 http://www.xmcgraw.com/?p=766 There is something very special about creating an experience that another human can be entertained by or that makes their life a little easier . The desire to learn how to code came from a deeper desire to be in full control. Instead of relying on others to make things happen I would have the […]

The post What You Need To Know To Start Learning How To Code appeared first on David McGraw.

There is something very special about creating an experience that another human can be entertained by or that makes their life a little easier . The desire to learn how to code came from a deeper desire to be in full control. Instead of relying on others to make things happen I would have the ability to get the ball rolling. I knew from an early age that this would become a huge asset as I began creating a company.

Why did I learn the language I use today, Objective-C & Swift? It’s easy. I fell in love with the idea of creating interactive experiences on mobile devices. That fire was enough to get me to focus on the iOS path 110%.

I’ve given you a short tour of why I started because it’s something you should ask yourself. There are 2 simple questions:

  • Why do you want to learn to code?
  • What kind of things do you picture yourself coding?

This article is not directly targeted to those who usually find their way to this site. The keys below will still help open doors on the path you’ve decide to take.

Identify Your Passion

It may not be nearly as clear, as it was for me, what you are truly passionate about. The key is being curious. Overtime something may click that drives you in a particular direction. Find a place to begin your exploration that sounds interesting and let fate take control.

What kind of things do you picture yourself building? A highly scientific or mathematical minded individual may have a huge desire to write code for NASA. Alternatively, someone who is very social or athletic may want to build fitness products that leverages social graphs. Maybe they really love playing video games. Identify what you love in life and let that become a guiding light. Remember that nothing is forever. I started writing games, but now I’m building more social, educational, and productivity products.

If you’ve began your journey with Swift you may recognize that it’s not the language for you. For example, maybe you wanted to learn how to build games for the iPad using SpriteKit and Swift. Later in your journey you decided to experiment with Unity3D and fell in love. Remain cautiously optimistic while staying open minded. Keep experimenting if you haven’t found a language or platform that you truly enjoy working with.

If you don’t have any passion for the space then you may have to step back and reevaluate the path. Cringing each time you sit in front of a set of monitors isn’t how you want to live. Life is short. Enjoy it!

Starting Out

I have a pretty easy guide to follow when it comes to beginning leaning a new language. While I enjoy learning platforms like Tree House or video tutorials from Lynda, I whole heartedly recommend reading a couple of books. They’re often highly focused, well guided, and remove all potential distractions. It’s just you, the book, and your code editor.

Supplementing books with a learning platform or video tutorials is fine, but going through a couple of books cover-to-cover will help dramatically. Once you’ve identified a language to study:

  • Buy a book focused on the language and only the language
  • Buy a book focused on teaching you how to use the language within a particular environment

Remember, what works for me or your friends may not work for you. We all learn differently and it takes a bit of self awareness to help get us on the right track. If you don’t have that awareness books are a safe first bet.

Let’s say you really wanted to learn how to build apps for Apple devices. You’ve decided on Swift instead of Objective-C. Go out and find a book that just teaches you Swift and read the book cover-to-cover. Once you’ve finished find a book that explores using Swift to build apps on iOS.

What if you wanted to build web applications? You’ve decided on learning Ruby on Rails since you’ve heard so much about it. The language there is Ruby. Rails is a framework written with Rails. So grab a book that just focuses on teaching Ruby and then buy a book that focuses on Rails.

If you wanted to build games with Unity3D? You guessed it. Buy a book that just focuses on C#, and then jump into Unity3D.

This language + environment book strategy will help you focus while minimizing the potential distractions and overwhelming situations. You may still feel overwhelmed, but not nearly as much as you would if you were to go through an online course that had to limit what they taught you because their platform couldn’t support it.

Removing Training Wheels

I can promise that the most challenging jump you will make will not be picking up a book and finishing it. It’ll be the transition from finishing a book to building a project on your own. You could go through all of the examples you wanted to, but books rarely challenge people in a way that make that jump comfortable. So how can you better manage that jump?

  • Find an idea and keep the scope incredibly small so you don’t have to spend more time thinking about how the app will work than just building it. If the app does 2-3 things you’re in good territory for the first app.
  • Don’t give in under the pressure—find a way. When all else fails use a lifeline (call a friend, submit a post to Stack Overflow or Reddit).
  • Adjust the idea if needed. Did you start a small game project and feel completely overwhelmed? Games are extremely hard. Step back and build a far more easier game (2D instead of 3D, small Puzzle instead of an RPG).

The last thing you really want to do is chase yourself in learning circles. Bouncing from books, to online learning platforms, to courses at a local college, to video courses, to… Figuring things out will take time and a lot of practice. It’s best to set a foundation (through a few books) and just begin building.

Joining A Team

One of the best ways to pick up great coding habits or learn new concepts is to be thrown into a team environment. This environment will push you in directions you may not even considered. It will also surround you with people who have been playing the game much longer than you have. These people are insanely valuable. Don’t feel like you need an intense portfolio in order to join a team. Plenty of teams are looking for highly motivated junior developers. Get a few projects under your belt and go after them.

If you can’t get into a team right away consider finding a friend or mentor to lean on. If you’re at a university network with your peers. These people will make the experience much more enjoyable since they’ll help you navigate the wild waves that you’ll run up against.

If you’re not around a university, or technology hub, then invest your time into attending developer events. The iOS community hosts a lot of great events, such as RWDevCon and 360iDev. Don’t feel intimidated. These are some friendly folks who would love to play a small part in your future success.

Finally, immerse yourself in Twitter, Github, answering questions on Stack Overflow, Quora, and wherever else you can find developers hanging out.

Fight Back Against Self-Doubt

The only thing you need is the passion. If you really want to build apps for mobile devices don’t let your mind tell you otherwise. If you enjoy being around computers, writing code, and experimenting you’ll be just find. The doubt will inevitably show up—I guarantee it. Don’t let it beat you back down.

Be honest with yourself. Maybe you really enjoy the low level technical coding experience. Great! You’ll have a lot of fun crunching on really challenging problems thrown your way. Maybe you’ve found that you like writing code and designing apps. Great, I know plenty of developers who have become a solid resource that can handle the first stage of development. Maybe you like writing code and handling business aspects. Great, you’ll be a solid technical leader someday! Being a generalist isn’t a bad thing. There are so many flavors of a coder. I’m willing to bet there is a style for you.

What if you really don’t enjoy coding? You’ve given it a good try for 6 months or so, but are just not having any fun. Don’t sweat it & don’t force it. Life is too short. Step back and re-evaluate your path. You’ll be much happier jumping on a path that you really enjoy. Don’t let society force your hand—it’s your life.

Build, Build, and Build

I’ve invested so much time it’s slightly maddening. When I began learning how to code for iOS I spent 2 or 3 weeks, 12 hour days, highly focused on learning how to use a Mac, write Objective-C code, and use the iOS SDK.

Do yourself a favor and commit to learning how to code. Set aside 30 minutes to just sit in front of your books and the monitor. Once you’re done with books, focus on writing code and thinking about development. Make it a daily habit. If you really enjoy coding this will be very easy. If you’ve set a goal for yourself, like release an iPhone app in 6 months, it’ll be easy.

Overtime you’ll eventually want to begin exploring uncharted territory. That’s to be expected. What you want to avoid is overwhelming yourself by adding too much to your plate all at once. Focus on a small subset of areas that you enjoy and Introduce new concepts overtime to keep yourself frosty. Don’t be in any rush. Focus.


I don’t want to sugar coat this—everyone is different. Nobody will have the perfect answer for you. Based on what I’ve seen and experienced this article outlines some of things I would tell myself if I were to start all over again. Ideally, I would have joined a team much quicker or I would have found a mentor. Even today I still feel like I should find a mentor to lean on for business.

Dive in! You can absolutely do it. All you really need is a little bit of fire in that belly.

The post What You Need To Know To Start Learning How To Code appeared first on David McGraw.

http://www.xmcgraw.com/what-you-need-to-know-to-start-learning-how-to-code/feed/ 2
Learn How To Create An iOS App Using HomeKit http://www.xmcgraw.com/learn-how-to-create-an-ios-app-using-homekit/ http://www.xmcgraw.com/learn-how-to-create-an-ios-app-using-homekit/#comments Thu, 12 Feb 2015 13:00:30 +0000 http://www.xmcgraw.com/?p=751 Back in early 2014 I had an opportunity to work on my first hardware project that went into production. The project was incredibly interesting. All of a sudden I had to build an app that interfaced with a piece of hardware that triggered set events. Those events would be customizable through the app. It’s one […]

The post Learn How To Create An iOS App Using HomeKit appeared first on David McGraw.

Back in early 2014 I had an opportunity to work on my first hardware project that went into production.

The project was incredibly interesting. All of a sudden I had to build an app that interfaced with a piece of hardware that triggered set events. Those events would be customizable through the app. It’s one thing to build an app just for the device. To create an app that interfaced with an external device was a welcome change of scenery.

Given that we are all shifting into what’s being called “The Internet Of Things,” it’s well worth your time to explore the hardware side of the house. I didn’t have the luxury of HomeKit to leverage when I worked on my hardware project. I wish I did. One of the roughest aspects of that contract was establishing a communication layer that worked well. The company I worked for had to create their own standard, which involved a lot of trial and error.

Well, HomeKit is here to help guide new hardware projects. I can’t speak for the hardware development side of the house, but I can speak to the software side. If you want to build an app for a HomeKit enabled device, or you’re just curious, then this article is for you.

  • You’ll learn how HomeKit works at the foundation
  • You’ll discover how to create your own accessories to experiment with
  • You’ll explore an app that creates a solid foundation to work from

Introducing HomeKit

HomeKit provides a common protocol that home automation devices can adhere to, making the life of the software developer much easier. Since the hardware creator follows such a protocol you really don’t have to concern yourself with the firmware of the device. You can use HomeKit to easily configure and communicate with supported devices.

There are three major functions that HomeKit provides:

Device Discovery

Anyone who has built an iOS app for a piece of hardware can tell you many horror stories about device discovery. You’re always on the edge of what is acceptable. Is Apple going to care if I scan the network for Mac Addresses? What about wireless signals? HomeKit handles all of this for you. Even better is that they add discovered accessories to a persistent, cross-device home configuration database. So the accessory you set up on your iPhone could instantly show up on your iPad.


HomeKit provides very easy access to the information related to your accessories. This makes it nearly trivial to display, edit, and respond to the data from the accessory.


Since HomeKit establishes a clear protocol you don’t have to worry about how the communication is sent to the device or confirming that the device even received it. You avoid a lot of low-level headaches that interfacing with hardware can bring. Stability can easily falter without a standard communication protocol. This was probably the worst part of the contract I worked on.

Finally, the configuration database is not only available to third-party apps, it’s also available to Siri. This lets you operate very sophisticated operations with voice control.

Home Configuration

Before you can get started with HomeKit it pays to understand a few ways you can configure accessories. It’s unlikely that you will impose your will by dictating how the configuration process happens. Most likely you’ll leverage the following as a way to help the customer better define their own experiences.

HMHome: Say you have a customer with a primary residence and a vacation home. Allowing them to group accessories under a given home will help them organize each area.

HMRoom: A home can have several rooms. While this is an optional part of your home, you can provide the customer with a way to better organize the area of their home. If you don’t create any rooms a default room will be provided. All of the new accessories simply attach to it.

HMAccessory: These are installed into homes and assigned to rooms. Think of these as your physical automation device, such as a light bulb. Again, if you don’t create any rooms new accessories will be assigned to a a default room.

HMService: Accessories provide user-controllable services, like a light. Accessories can have many services. So a fancy light bulb could have a service that turns it on or off and a different service that turns it blue.

Zones: These are optional groupings of rooms in a home. For example, grouping all of the lights in your basement under a zone allows you to control the entire zone with a single service.

It’s important to note that meaningful names enable commands like, “Siri, turn on the kitchen lights.” Or if you have a zone downstairs, “Siri, turn off all of the lights downstairs.”

Example Walkthrough

In this example we’re going to walk through an example that will give you a clear window into how HomeKit functions. Building apps for hardware products can be really fun. HomeKit makes the process much more enjoyable.

[alert color=”yellow”]Follow along by downloading the source from Github[/alert]

The Hardware

I’m guessing that you don’t have a HomeKit supported device handy. Not to worry. Apple provides a simulator that lets us build our own accessory to interface with. The simulator does not come with Xcode so you’ll have to navigate to Apple’s download center to get the Hardware IO Tools for Xcode. Search for HomeKit.

HomeKit Hardware Tools

After downloading the Hardware IO tools you can move the HomeKit Accessory Simulator to your application or development folder.

HomeKit Simulator Icon

When you launch the simulator you’ll see a whole lot of nothing.

HomeKit Blank Simulator

Adding a new accessory is easy enough. Click the (+) button on the lower-left. A bridge is a middle-man. Instead of your app interfacing directly with the accessory, communication flows through a bridge. In this example we’re just worried about creating an accessory.

HomeKit Accessory Details

In this example I’ve kept it pretty simple. We have 2 services included in our accessory. One is a simple toggle (on or off) and is labeled internally as an EMServiceTypeLightbulb. The other is a service called EMServiceTypeAccessoryInformation. Here is a full list of supported service types:

  • EMServiceTypeLightbulb
  • EMServiceTypeSwitch
  • EMServiceTypeThermostat
  • EMServiceTypeGarageDoorOpener
  • EMServiceTypeAccessoryInformation
  • EMServiceTypeFan
  • EMServiceTypeOutlet
  • EMServiceTypeLockMechanism
  • EMServiceTypeLockManagement

You are not forced to use the pre-defined characteristics of a service type. For example, if we pressed Add Characteristic you would see a list like such:

HomeKit Simulator Options

The Project

When you create a new project designed for HomeKit you’ll need to jump into your target capabilities section to turn on HomeKit. This will inform you again about needing the HomeKit Accessory Simulator. Once it’s enabled you’ll have the proper entitlements and framework to begin.

HomeKit Xcode Capabilities

The Base Controller

What you don’t want to be doing is continually searching for nearby accessories. This becomes a drain on the system while wasting a lot of unnecessary cycles. You really just need to guide customers to an accessory discovery area so they can select which accessories they wish to add to their configuration.

Before we begin adding devices we initialize our home with a single room.

// Create our primary home if it doens't exist yet
private func initialHomeSetup() {
    homeManager.addHomeWithName("Porter Ave", completionHandler: { (home, error) -> Void in
        if error != nil {
            println("Something went wrong when attempting to create our home. \(error.localizedDescription)")
        } else {
            // Add a new room to our home
            home.addRoomWithName("Office", completionHandler: { (room, error) -> Void in
                if error != nil {
                    println("Something went wrong when attempting to create our room. \(error.localizedDescription)")
                } else {
            // Assign this home as our primary home
            self.homeManager.updatePrimaryHome(home, completionHandler: { (error) -> Void in
                if error != nil {
                    println("Something went wrong when attempting to make this home our primary home. \(error.localizedDescription)")

The home manager informs us when we’ve added, removed, and updated a home. It also informs us when we’ve designated a home as our primary home.

In the code above we’re adding a new home called “Porter Ave.” You could name this whatever you’d like. In a production app you would likely hand off control to the customer to determine what name they’d like to give their home.

Once we’ve successfully created a home we add a room called ‘Office.” Again, this is something you’d likely let the customer control.

When the home and room is complete, we set the home as our primary home.

One key thing to be aware of with the home manager is that it does not immediately reveal the homes available. This is where homeManagerdidUpdateHomes: comes into play. When we launch the app this method will be called shortly after. When this happens we’ll have access to the primaryHome and homes properties.

The Discovery Controller

As I mentioned earlier, continually searching for accessories is a waste of time. So we have a controller designed just for that process. When you come into the discovery controller we immediately begin searching for new accessories with a timeout of 10 seconds. It’s as easy as creating an instance of HBAccessoryBrowser and calling startSearchingForNewAccessories. You don’t have to worry about the lower logic, you just become a delegate to catch the discovery signals.

There are two methods to the browser delegate.

// Informs us when we've located a new accessory
optional func accessoryBrowser(browser: HMAccessoryBrowser!, didFindNewAccessory accessory: HMAccessory!)

// Informs us when a device, that was previously reachable, is no longer reachable
optional func accessoryBrowser(browser: HMAccessoryBrowser!, didRemoveNewAccessory accessory: HMAccessory!)

When we discover new accessories we load them up in the table which the customer can then select to add to their configuration.

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let accessory = accessories[indexPath.row] as HMAccessory
    if let room: HMRoom = homeManager.primaryHome.rooms.first as? HMRoom {
        homeManager.primaryHome.addAccessory(accessory, completionHandler: { (error) -> Void in
            if error != nil {
                println("Something went wrong when attempting to add an accessory to our home. \(error.localizedDescription)")
            } else {
                self.homeManager.primaryHome.assignAccessory(accessory, toRoom: room, completionHandler: { (error) -> Void in
                    if error != nil {
                        println("Something went wrong when attempting to add an accessory to our home. \(error.localizedDescription)")
                    } else {

Here you’ll see that we take the selected accessory and add it to our primary home. This will prompt the customer to enter an identification number provided by their device. In our case it’s in the simulator near the top left.

HomeKit Setup

Enter the code as you see it there, including the dashes, and you’ll be good to go. When we get confirmation that the customer successfully added the accessory we can then assign it to a specific room. In the example above I assign it to the the Office we created.

The Accessory Controller

Here we drill down into the services provided by the accessory we added. As a reminder, our example provides 2 services. One is simply informational and one is a switch for a lightbulb. You can see that I don’t care about the informational services so I only load the light bulb service into a data array.

A service for an accessory contains several characteristics.

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("serviceId") as UITableViewCell
    let service = data[indexPath.row] as HMService
    for item in service.characteristics {
        let characteristic = item as HMCharacteristic
        println("value \(characteristic.value) : \(characteristic.metadata)")
        let metadata = characteristic.metadata as HMCharacteristicMetadata
        if metadata.format == HMCharacteristicMetadataFormatBool {
            if characteristic.value as Bool == true {
                cell.detailTextLabel?.text = "ON"
            } else {
                cell.detailTextLabel?.text = "OFF"
            characteristic.enableNotification(true, completionHandler: { (error) -> Void in
                if error != nil {
                    println("Something went wrong when enabling notification for a chracteristic. \(error.localizedDescription)")
        else if metadata.format == HMCharacteristicMetadataFormatString {
            cell.textLabel?.text = characteristic.value as? String
    return cell

You can see that I’m parsing the characteristics of the only HMService we’ve loaded into the data array. In order to properly layout the cell we need to check the characteristic metadata for the format. There are several formats that you can check for:

  • HMCharacteristicMetadataFormatBool
  • HMCharacteristicMetadataFormatInt
  • HMCharacteristicMetadataFormatFloat
  • HMCharacteristicMetadataFormatString
  • HMCharacteristicMetadataFormatArray
  • HMCharacteristicMetadataFormatDictionary
  • HMCharacteristicMetadataFormatUInt8
  • HMCharacteristicMetadataFormatUInt16
  • HMCharacteristicMetadataFormatUInt32
  • HMCharacteristicMetadataFormatUInt64
  • HMCharacteristicMetadataFormatData
  • HMCharacteristicMetadataFormatTLV8

While the service I added didn’t have them, you can also check the metadata for unit characteristics:

  • HMCharacteristicMetadataUnitsCelsius
  • HMCharacteristicMetadataUnitsFahrenheit
  • HMCharacteristicMetadataUnitsPercentage
  • HMCharacteristicMetadataUnitsArcDegree

Again, you mainly need to do this when you want to determine what should be displayed to the customer. In my example I inspected the characteristics that came with my service and noticed that there will be a bool value (on or off) and a string value (the name of the service).

In order to monitor state changes for your device you’ll want to enable notification on the characteristic you want to monitor. In this example we care about the value changing. The delegate HMAccessoryDelegate will handle passing on the message.

func accessory(accessory: HMAccessory!, service: HMService!, didUpdateValueForCharacteristic characteristic: HMCharacteristic!) {
    println("Accessory characteristic has changed! \(characteristic.value)")

Finally, when the customer selects are service we want to send data to the device so we can toggle it’s state. We do that by writing data to the characteristic.

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
    let service = data[indexPath.row] as HMService
    let characteristic = service.characteristics[0] as HMCharacteristic
    let toggleState = (characteristic.value as Bool) ? false : true
    characteristic.writeValue(NSNumber(bool: toggleState), completionHandler: { (error) -> Void in
        if error != nil {
            println("Something went wrong when attempting to update the service. \(error.localizedDescription)")


[alert color=”blue”]Even though I delete the app from the simulator I still see accessories show up in my list. What’s going on?[/alert]
HomeKit is a global configuration system that will persist even if you delete your app. You’ll need to call the appropriate methods to delete the existing configuration or you can clear all of your settings from the simulator. Click the iOS Simulator’s main menu and then click Reset Content and Settings.


While there is a plenty more to cover, writing a basic HomeKit app is pretty straightforward. Having a standard protocol to work from makes the process so much more smooth. Not worrying about device discovery is very nice. Avoiding low-level communication logic is also a nice win. Grab the sample project, create your own accessory, and experiment!

[alert color=”yellow”]Enjoy the content? Consider learning more about my Discover iOS Letter![/alert]

The post Learn How To Create An iOS App Using HomeKit appeared first on David McGraw.

http://www.xmcgraw.com/learn-how-to-create-an-ios-app-using-homekit/feed/ 4
6 Simple Tips To Help Generate More Ideas http://www.xmcgraw.com/6-simple-tips-to-help-generate-more-ideas/ http://www.xmcgraw.com/6-simple-tips-to-help-generate-more-ideas/#respond Tue, 10 Feb 2015 13:00:42 +0000 http://www.xmcgraw.com/?p=744 So you’ve learned how to write code with Swift, but you have no idea what product to build. Let me assure you that this is a pretty common experience. Few begin learning a language with the intent to build a product. The good news is that you’re well ahead of the pack. I assume you […]

The post 6 Simple Tips To Help Generate More Ideas appeared first on David McGraw.

So you’ve learned how to write code with Swift, but you have no idea what product to build.

Let me assure you that this is a pretty common experience. Few begin learning a language with the intent to build a product. The good news is that you’re well ahead of the pack. I assume you have a few books under your belt, example apps written, and a hunger to build something. The key now is to keep building.

Break away from everything to give yourself space to think

It’s next to impossible to form new ideas if you mind is churning against the daily grind. Give your mind space to breathe. There are a few good ways to do this. Meditating in the morning can give your mind the space to pause. This can help you focus, raise your energy, and lower your stress levels. A lack of focus, energy, and high stress kills any hope to come up with new ideas.

Going for walks also provide ample time to rest your mind. Observe nature, follow the random thoughts that show up, and just relax. What you’re aiming to do is disconnect. Get away from the screens, the wife & kids, work, or whatever else causes daily stress in your life. You want to find the best way for your mind to relax. If you’re mind isn’t grinding on problems then it can spark curious thoughts to explore.

Write down every idea that crosses your mind

The worst thing you can do is not write down your thoughts. Our mind isn’t so great at record keeping when it comes to this. It won’t take long before you forget what you were thinking about.

I’m often at my desk working on contracts or product development, so I have a stack of 5×7 blank note cards that I keep at arms reach. This makes it easy to sketch thoughts that pop up during the day.

If a thought strikes when I’m about to fall asleep, I send myself an e-mail. If I’m traveling I carry a small moleskin notebook. If I’m out for a walk or run, I have my phone with me so I toss an e-mail or write details in the iOS notes app. Find what works for you.

You don’t need anything complicated to do this. Just be mindful that thoughts are fragile and lost easily. If something strikes write it down.

Leaning on others in the market

While you’re waiting for an idea to strike you need to keep moving. Find an app that you love and then rebuild a version of it. This will keep you frosty until it’s time to use those skills. The iOS SDK is massive. Find pieces that you like and continue exploring.

Leverage this as a way to build your own product. Do you think you could do something different or make an existing app a much better experience? Don’t be afraid to leverage an existing idea and make it even better.

Your Own Behaviors & Likes

Some of the best ideas are born when someone recognizes that something is missing from their life. They tried to complete a task and the product just didn’t exist or the existing solutions were too cumbersome. So they set out to fill the hole. Watch your own behaviors and identify when you’ve told yourself, “I wish this was easier to do.” At the same time, what can you simplify in your own life? Have you caught yourself performing a manual task several times? Consider making an app to simplify your own processes.


So maybe you’re not oozing ideas left and right. While we all are capable of becoming idea people, it just may not be your moment. If you’re finding it difficult to generate ideas consider collaborating. A friend could be itching to build an idea they have in their mind.

If you’re already senior enough and are contracting for others, hello! Contracting can open so many possibilities. You get direct insight into how a company operates. This can lead to bottleneck discoveries that could warrant optimization.

Have fun and enjoy the process

Don’t take this stuff too seriously. If you sit and obsess about every detail of an idea nothing will get done. Find ideas that bring excitement into your mind. Find ideas that sound fun. Find ideas that let you explore and doesn’t stress you out. You don’t need a $100m exit nor do you need an exit at all. You just need to build something you felt compelled to build.


It takes time to turn your mind into one that observes the world in an opportunistic way. The key is to keep a fresh and open mind. If you don’t let your mind stop then it’ll make the discovery process much more difficult. So go out for a walk, be mindful of what’s going on around you, and write everything down.

Finally, don’t feel like you need to answer everything at the onset. Ideas themselves rarely morph into a final product directly. What usually happens is that you begin working on a product and evolve it overtime as you learn more about the customer and the problem you’re actually solving. So dive in!

The post 6 Simple Tips To Help Generate More Ideas appeared first on David McGraw.

http://www.xmcgraw.com/6-simple-tips-to-help-generate-more-ideas/feed/ 0
Let’s Walk Through The Apple TestFlight Experience http://www.xmcgraw.com/lets-walk-through-the-apple-testflight-experience/ http://www.xmcgraw.com/lets-walk-through-the-apple-testflight-experience/#comments Thu, 05 Feb 2015 13:21:57 +0000 http://www.xmcgraw.com/?p=706 If you needed a free way to distribute and test your app in the past, testflightapp.com was the place. Is the new TestFlight still the place? While there are other great alternatives, like Hockey App, it isn’t a perfect solution for those who can’t add a recurring expense to their development cycle. That’s just not […]

The post Let’s Walk Through The Apple TestFlight Experience appeared first on David McGraw.

If you needed a free way to distribute and test your app in the past, testflightapp.com was the place. Is the new TestFlight still the place?

While there are other great alternatives, like Hockey App, it isn’t a perfect solution for those who can’t add a recurring expense to their development cycle. That’s just not an option for plenty of people out there. While there are a few other free alternatives, I’ve really enjoyed my time with Beta by Crashlytics. That said, Apple will shut down the old TestFlight and encourage everyone to move to the new experience under iTunes Connect on February 26th, 2015. To prepare you for that this post will dive into the TestFlight experience so you can determine if it is something you’d like to pursue, or if Crashlytics or Hockey App is where you should go. By the time you finish this article you’ll have a pretty good idea which road to take.

  • You’ll understand what makes these services different
  • You’ll walk through the TestFlight experience with me as I deploy a test build of my weekend project, Tomorrow
  • You’ll get try the first part of Tomorrow, joining my TestFlight beta testing group

Comparing Services

Right now we’ve got 3 services high on the radar.

Here is a high-level overview of my thoughts on these services.

Service Comparison

Test The Experience

Has anyone sent you a TestFlight build from the new iTunes Connect? Well, here is your chance to walk through the experience of downloading, providing feedback, and feeling how the process works.

For a quick backstory, Tomorrow is an app I’m building as a way to just have fun beyond the serious stuff. It’s purpose is deviously simple—to help you manage the massive task list you are working with. I will share more about this entire process in a future article!

If you are on my Discover iOS Letter you should have my e-mail. Toss me one and I’ll add you to the beta so you can check things out from an end-user perspective. If you’re not on the list, consider subscribing.

Preparing For Upload

First you’re going to need to make sure that you have an app created in iTunes Connect with the bundle id of your app. If you have yet to generate provisions for your app you’ll want to do that first. Once you have the provisions jump into iTunes Connect and add a New iOS App.

iTunes Connect Add App

You’ll then need to fill out all the important details. Your bundle id should match the id you’ve used in your provisions.

New App Details

Once you have the app created you’re ready to start testing. You don’t need to fill out any of the app details right now (screenshots, description, etc).

Uploading A Build

When you’re ready to upload a build be sure that your provisions are set properly for release. If you open your app target, select Build Settings, and navigate to the Code Signing Identity area you should see the provision you’ve created that matches your bundle id.

Once you archive your app you can click Submit in the organizer that pops up (Window > Organizer). Choose your team. And, before you submit, verify that Xcode pulled in the provision you expected. The first few times I tried this Xcode didn’t find the right one. If you go to Xcode > Preferences > Accounts, you can double-click your team and refresh your provisions.

TestFlight Upload

You also need to make sure that your iOS Deployment Target is not set to a beta version of iOS.

Minimum OS

Unlike the old TestFlight, which would just add #x if build/version were the same, you also have to make sure you update them in the new TestFlight. You’ll see this great looking error if you don’t.

Redundant Upload

If the provisions are correct, and the two errors above are not hit, you should be good to go!

Upload Success

Enable TestFlight & Invite Testers

Once your build is uploaded you should now see it listed under the Prerelease tab in iTunes Connect. It’ll take a few minutes to go through Processing.


You’ll need to turn TestFlight Beta Testing on before a build will be available.
Enable TestFlight

Once the processing is completed your build will be available.Internal Only

Wait… a triangle? That doesn’t look good. And Submit For Beta App Review is disabled…

Build Not Available

There you have it. If you’ve uploaded a build with a beta version of Xcode you can’t distribute builds externally. You’ll be locked to you own team (25 members). In this case I just created a build from the non-beta Xcode and uploaded it again. I didn’t have anything that required that I used the beta version.

Begin External Testing

Once you’re ready for external testing you’ll need to fill out a few details and then you’ll be ready to add people to the test. Until then you’ll have to wait for the Apple review team to work their magic.

waiting for review

In this test it took less than a business day to get it approved. The only thing that was active in the build was the onboarding experience. Thankfully they didn’t reject the build for that…

Once approved, you can invite individuals under the External Testers tab.

Test List

Invited Email

Test Feedback

The TestFlight app makes it easy to let the tester know what to test. Additionally, they can quickly send feedback from the app as well.

Send Feedback

The app will automatically include device information to the e-mail.

Feedback Email

Crash Reports

I purposely added a selector crash to the build so I could see what happens when the app crashed. Yeah, they don’t provide a way to view them in TestFlight yet. It’s nowhere to be found, including under the Versions details.

Additional Information

That’s unfortunate, but not all is lost. You can still take advantage of TestFlights extremely painless invite system while leveraging Crashlytics for reporting.


[alert color=”blue”]What if I have an enterprise developer account?[/alert]
If you’re using an enterprise account you can’t distribute apps to the app store. Well, Apple has also made it clear that TestFlight is not for enterprise accounts.

No Enterprise

This is a bit of an annoyance for those of you who may be using your enterprise account as a way to glide past restrictions. Apple clearly wants you to be using internal distribution methods.

Read more of their FAQ here.

[alert color=”blue”]How long does it take for subsequent builds?[/alert]
From what I’ve seen this takes about 30 minutes.


At this point the real value in TestFlight comes from the invite system. Having the ability to bring in 1000 testers by simply requesting an e-mail address is fantastic. Adding Crashlytics is a breeze, and the experience is really nice. But if you don’t mind paying a bit, Hockey App is where you want to go. If you want a full suite of tools, for free, give Fabric a spin.

Having to wait even 30 minutes to kick a build to external testers is slightly annoying, but I don’t think it’s enough to keep me away. If anything keeps me away it’s the lack of usage data.

Thanks for reading. If you’ve enjoyed this content learn about my monthly Discover iOS Letter!

Best wishes for a productive day!

The post Let’s Walk Through The Apple TestFlight Experience appeared first on David McGraw.

http://www.xmcgraw.com/lets-walk-through-the-apple-testflight-experience/feed/ 3
How To Manage Dependencies with CocoaPods http://www.xmcgraw.com/how-to-manage-dependencies-with-cocoapods/ http://www.xmcgraw.com/how-to-manage-dependencies-with-cocoapods/#respond Tue, 03 Feb 2015 13:00:54 +0000 http://www.xmcgraw.com/?p=653 There are great open source projects out there maintained by dedicated individuals and companies. One big problem you may face when bringing these projects into yours is managing them. When you bring in a 3rd party library you inherit a certain amount of risk. The biggest, of which, is that you can bring something in […]

The post How To Manage Dependencies with CocoaPods appeared first on David McGraw.

There are great open source projects out there maintained by dedicated individuals and companies. One big problem you may face when bringing these projects into yours is managing them.

When you bring in a 3rd party library you inherit a certain amount of risk. The biggest, of which, is that you can bring something in that could break your app. You download a new update, add files to your project, configure build settings, run your app, and then discover nothing works. You then panic, trace your steps backwards, and finally revert to the previous version… if you can remember which version you were using.

Dependency managers help solve some of this pain. You no longer need to worry so much about adding, removing, or updating 3rd party libraries manually.

By the time you finish this article you’ll learn about a widely used dependency manager called CocoaPods.

  • You’ll understand what CocoaPods does
  • You’ll learn how to integrate CocoaPods into your project
  • You’ll see a few tips that should help you on your journey
  • You’ll familiarize yourself with the process by walking through an example

Introducing CocoaPods

CocoaPods helps you focus on building apps instead of wrestling with 3rd party libraries. You avoid having to do so much manual work that can be error prone. This does mean you do give up some control in order for CocoaPods to work it’s magic. It’ll be up to you to decide if that’s good or bad.

The podspec

CocoaPods relies on a central library to manage what dependencies are available to install. You’ll often see a podspec file in a repository, like this one from the Alamofire repo.

Pod::Spec.new do |s|
  s.name = 'Alamofire'
  s.version = '1.1.4'
  s.license = 'MIT'
  s.summary = 'Elegant HTTP Networking in Swift'
  s.homepage = 'https://github.com/Alamofire/Alamofire'
  s.social_media_url = 'http://twitter.com/mattt'
  s.authors = { 'Mattt Thompson' => 'm@mattt.me' }
  s.source = { :git => 'https://github.com/Alamofire/Alamofire.git', :tag => s.version }
  s.ios.deployment_target = '8.0'
  s.osx.deployment_target = '10.9'
  s.source_files = 'Source/*.swift'
  s.requires_arc = true

One of the disadvantages of CocoaPods is that a repo needs to have this file available and be included in the central spec repo. At this point there are 6,836 specs so it’s very likely that the repo you want is there. However, at the end of the day you can actually create your own spec repo if you need to. I’ll cover that a little later.

In order for CocoaPods to know what dependencies you use for your project it reads a Podfile. The Podfile describes what repo to download from and how to configure your project.

Podfile Layout

A Podfile defines what your project depends on. Here we’ll review some of the more common things that make up a Podfile. These are highly configurable files, so reference the syntax over at CocoaPods for more.


platform :iOS, '8.0'

In order for CocoaPods to set things up properly it needs to know what platform you’re targeting. This currently defaults to iOS 4.3, but you’ll want to default to 8.0 in order to work with Swift.


source 'https://github.com/CocoaPods/Specs.git'

The line above shows CocoaPods where to look for the pods you list. As I mentioned above, you could also include another source line that points to your own spec repo.


pod 'Alamofire'

The previous line will be the most common line you’ll be working with in the Podfile. If you scan back to the Alamofire podspec you’ll see that we add the name from line #2. This will install the most recent version of Alamofire. Sometimes, that’s not what we want to have happen. We can specify the version we would like to use by explicitly pointing out what we need. For example, here we do not want pods beyond version 1.0 installed.

pod 'Alamofire', '1.0'

This makes sure that we don’t accidentally update our pods and install a future version that we didn’t want. Here are a few other ways to define the version number:

  • ‘> 1.0’ – Install versions greater than 1.0
  • ‘>= 1.0’ – Install 1.0 and future versions
  • ‘< 1.0' - Install versions less than 1.0
  • ‘<= 1.0' - Install any version before 1.0, and including 1.0

Most of the time I either leave the version off so I have the latest and greatest, or I explicitly note that I want a version.

Sometimes you need to use a specific version of a repository. To do that you’ll append where the repository is and what you’re looking for.

pod 'Alamofire', :git => 'https://github.com/Alamofire/Alamofire.git', :commit => '410e866'

This will grab a specific commit from the provided repository location. You can also use :branch or :tag instead of :commit.

pod :podspec

It’s important to point out that you may run into situations that warrant the need of using pods not available in the central repository. You could host your own repository on Github or just keep them local to your own network. This task is far beyond the scope of this article, but I want to make it clear that this is possible.



Since you have little control of the library you depend on it can help to silence warnings emitted. You can also do this on a per pod basis:

pod 'Alamofire', :inhibit_warnings => true

If you’re the kind of developer who likes a clean workspace this is helpful.

pre_install and post_install

Hooks give you the ability to make changes to Pods before and after they’ve been downloaded. You may need to do this if you need to configure additional build settings or other build-related tasks.

For example, maybe you want to use the Facebook pod Tweaks and you want to make sure the preprocessor macro FB_TWEAK_ENABLED is available and set to 1. You could use a post_install hook to make sure that’s configured properly.

post_install do |installer_representation|
    installer_representation.project.targets.each do |target|
        if target.name == "Pods-Tweaks"
            target.build_configurations.each do |config|
                if config.name == 'Release-Tomorrow-AdHoc'
                    config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'FB_TWEAK_ENABLED=1']

A Quick Example

To give you a little taste of what it is like dealing with CocoaPods we’ll run through a quick example. We won’t dive into everything above, but you’ll be well equipped to begin using CocoaPods. At the end of the day I don’t stray too far away from just using the pod statement.

Install CocoaPods

CocoaPods is built with Ruby and will be installable with the default Ruby version available on your machine. To install CocoaPods open up the command line and type the following:

sudo gem install cocoapods

Swift Support

Support for CocoaPods + Swift is still under development, but they’ve recently released CocoaPods 0.36 beta. This introduced support for Swift and Frameworks. In order to update to this version you’ll want to append the —pre flag.

sudo gem install cocoapods —pre

At this point you’ll want to watch out for pods not being updated to handle being a framework. You’ll notice issue if you add a pod that requires being a framework because all of the other pods will become a framework. You may run into issues with files not being found if a pod isn’t ready to become a framework.

New Project

Now that CocoaPods is installed let’s create a new project.

New Project

Nothing fancy here, we’re just going to create a single view application.

Dojo Dependencies

Now that we have a project we need to add a few dependencies to it! In this example I’ll be adding a few of my favorites. First, we’ll need to create a Podfile to let CocoaPods know what we need. So right click on your project name in the file navigator and select New File. We want to create an empty file so navigate to iOS > Other > Empty. Save the Podfile at the root of your project.

Save Podfile

Now let’s edit the Podfile to include our desired pods, along with a few more details.

Edit Podfile

It’s time to install them! Close your project because from now on we’ll need to use a workspace that CocoaPods generates. Jump over to the Terminal and navigate to your project directory. Once you get there type pod install.

Pod Install

Don’t worry about the git repository error. Things will still work as expected.

Once CocoaPods completes the process it’s time to open the new workspace. You can type open dojo-dependencies.xcworkspace or navigate to the file via Finder.

Pod Install Verify

Reviewing our new workspace we can see that pods were added and that one of the pods we used required iOS 8.0 frameworks (Alamofire). We know this because we’re seeing *.framework under the Products group. Previously you would see static libraries (*.a) listed. You should be fine unless the owner of one of the pods you’re using failed to test their pod. It is a beta so your milage may vary (I’ve been fine).

You can now verify that things are in place by experimenting with the pods.

import UIKit

import pop
import Alamofire
import SlackTextViewController

// We'll subclass SLKTextviewcontroller
class ViewController: SLKTextViewController {
    var ball = UIView(frame: CGRectMake(0, 0, 100, 100))
    override func viewWillAppear(animated: Bool) {
        ball.center = CGPointMake(view.bounds.size.width/2, 200)
        ball.backgroundColor = UIColor.blueColor()
        ball.layer.cornerRadius = ball.bounds.size.width/2
        ball.layer.masksToBounds = true

    override func viewDidAppear(animated: Bool) {

        // POP
        let anim = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
        anim.toValue = NSValue(CGPoint: CGPointMake(2.0, 2.0))
        anim.springBounciness = 20
        anim.springSpeed = 10
        ball.layer.pop_addAnimation(anim, forKey: "grow-ball")
        // Alamofire
        Alamofire.request(.GET, "http://httpbin.org/get").responseString { (_, _, string, _) in
            self.textInputbar.textView.text = string

CocoaPods and Source Control

A common question that I see relates to source control. CocoaPods generates a few things that you may or may not want to store in your repository.

  • Podfile – Include this or else people will have trouble installing the dependencies.
  • Podfile.lock – This file tracks the latest versions used on a project. If you grab the project and run pod install CocoaPods will inform you that a version has changed. I would check this in.
  • Workspace – No need to check this in. This’ll be generated when pod install is called.
  • Pods Directory – No need to check this in. Checking it in will help review changes to your 3rd party libraries, but is a bit overkill for everyday use cases.

A caveat to all of this is when you’re done with a project. Feel free to check everything in so you know you’ll have a copy of everything in the future.

Note For The Future You

Experienced developers likely know this already, but if you’re just getting started it pays to know that you don’t have to release full control to CocoaPods. Some favor having 100% control with how dependencies are managed and integrated. That’s fine. You can install pods with a —no-integrate flag that will keep CocoaPods from messing with your project.

pod install —no-integrate


If you run into any trouble visit the troubleshooting section at cocoapods.org.

As you can see using CocoaPods is pretty straightforward. It’s value really shines when you need to easily switch between library versions or point to a specific commit. You may find yourself doing this a lot since you can’t really push library owners to work the way you work. If they’re slow to pull a change of yours then you can just point the pod to your location. If you’re trying to stay bleeding edge, and a recent commit breaks something, then point the pod to a commit before the change.

Hope you enjoyed this article! Be sure to join the Discover iOS Letter.

The post How To Manage Dependencies with CocoaPods appeared first on David McGraw.

http://www.xmcgraw.com/how-to-manage-dependencies-with-cocoapods/feed/ 0
How To Quickly Add Touch ID Using Local Authentication API http://www.xmcgraw.com/how-to-quickly-add-touch-id-using-local-authentication-api/ http://www.xmcgraw.com/how-to-quickly-add-touch-id-using-local-authentication-api/#respond Thu, 29 Jan 2015 13:00:00 +0000 http://www.xmcgraw.com/?p=610 [alert color=”yellow”]Friendly reminder: My first newsletter drops at the end of the month! Issue #1! Subscribe to get it, free guides, and more![/alert] There is something to be said about convenience when logging into a service. I personally love using Facebook or Twitter authentication when using apps since it lets me get to where I […]

The post How To Quickly Add Touch ID Using Local Authentication API appeared first on David McGraw.

[alert color=”yellow”]Friendly reminder: My first newsletter drops at the end of the month! Issue #1! Subscribe to get it, free guides, and more![/alert]

There is something to be said about convenience when logging into a service. I personally love using Facebook or Twitter authentication when using apps since it lets me get to where I want to go quicker. With the introduction of iOS 8, Apple opened the doors for third-party apps to utilize Touch ID. Instead of requiring a passcode to resume an app session you can easily request that the user authenticates via Touch ID.

By the time you finish this article you’ll understand how to integrate Touch ID into your app.

  • You’ll be introduced to the Local Authentication Framework
  • You’ll understand how to request authentication with Touch ID
  • You’ll see how to handle the use case of the user denying Touch ID authentication, instead opting for the regular password entry
  • You’ll learn if there is more we can do with the sensor, such as knowing if it’s being touched and if we can identify which print was used in the event you have user profiles

[alert color=”yellow”]Download the example project from Github to see this in action[/alert]

Introducing The Touch ID Framework

Touch ID is accessed via the Local Authentication Framework, which facilitates the authentication process. This framework is very straightforward and provides just one class, the LAContext.

LAConext does two things for you during this process. First, it verifies that an authentication is even possible. This can fail if the customer has not set any fingerprints. If it does fail then you need to have a backup route available, which you will likely already have in the vent the user chooses not to use their fingerprint.

If biometric authentication is possible then the authentication process will proceed and your customer will see the fingerprint alert view.

There are a few error codes to be aware of during this process.

  • LAErrorAuthenticationFailed : The customer failed to provide valid credentials
  • LAErrorUserCancel : The customer pressed Cancel
  • LAErrorUserFallback : The customer pressed Enter Password
  • LAErrorSystemCancel : The system cancels the process (usually encountered when the app is pushed to the background)
  • LAErrorPasscodeNotSet : Authentication could not begin due to the passcode not being set on the device
  • LAErrorTouchIDNotAvailable : Authentication could not begin due to the device not having Touch ID
  • LAErrorTouchIDNotEnrolled : Authentication could not begin due to no existing fingerprints

Implementing Authentication

To add Touch ID to your app you’ll need to add LocalAuthentication.framework:

Touch ID Framework

Now, we must consider the use case where the customer cancels our authentication and/or decides not to use Touch ID. It’s important to provide a fall back authentication method. In this example I use a custom keypad. You could also use an Alert View. It all really depends on the design you’re going for.

Here I advance the customer to the keypad view automatically upon launching our main view. This is because we want to make sure they are verified before we let them take any actions within our app. The convenience with pushing the customer here is that we can easily fall back to the text entry if they choose to not use Touch ID.

// MARK: Touch ID
func userAuthenticationRequired() {
    let context: LAContext = LAContext()
    // Reference the error codes listed in the tutorial
    var error: NSError?
    // What the customer will see in the alert view
    var description = "Authenticate To Access Journal"
    if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &amp;error) {
        context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: description, reply: { (success, error) -&gt; Void in
            if success {
            } else {
                println("Something went wrong! \(error.localizedDescription)")
                // Observe the error code to see what went wrong &amp; guide the user to the
                // appropriate area. For now we assume cancelation and let them proceed
                // with entering a code.
    if error != nil {
        println("Something went wrong! \(error?.localizedDescription)")

In the code above we’re doing several things.

  • Line 4 : Here we create our LAContext object that will let us verify authentication is available and to execute authentication
  • Line 7 : Review the error codes above. If we hit an error they’ll be tucked inside this NSError object
  • Line 10 : This text will be revealed within the alert view. Don’t worry about including your app name here, it’ll already be part of the title.
  • Line 12 : Here we verify that authentication is possible
  • Line 13 : We kick off the authentication process, which opens the Touch ID alert view

Common Questions

I’ve seen a few questions pop up over my time observing Twitter and listening to folks out there. I thought I’d outline them here.

[alert color=”blue”]I have multiple profiles in my app. Is there a way to detect which finger was used?[/alert]
No. The local authentication framework is extremely limited for security and privacy reasons.

[alert color=”blue”]Is there a way to detect when the user touches the sensor?[/alert]
No. Again, it’s a very limited framework.

[alert color=”blue”]The response time for Touch ID seems very sluggish. Is there anything I can do?[/alert]
Not that I’m aware of. You’re at the mercy of the framework and device.

[alert color=”blue”]What do I do when the user presses ‘Enter Password'[/alert]
You’ll need to move back to a text-based authentication. In the above example I’m using the keypad to handle this use case. You could use an alert view here instead. In order to do that you’ll want to set the UIAlertViewStyle to UIAlertViewStyleSecureText.

[alert color=”blue”]What’s the best way to handle authentication on application launch?[/alert]
In this example I wait for the main view to load and check if the user has authenticated. If they haven’t I present a modal controller. You don’t necessarily need to present a modal controller, but I did so in this example so that the transition from canceling to passcode input would be easier.

[alert color=”blue”]The Touch ID alert view is not showing up! What’s wrong?[/alert]
Check the error code, and be sure you have fingerprints added!


As you can see, implementing Touch ID is very straightforward. It’s a great way to provide convenience without sacrificing your user experience too much. While I opted to present a modal controller right away you could easily get away without doing so. Just hide the main content and reveal the Touch ID prompt.

The post How To Quickly Add Touch ID Using Local Authentication API appeared first on David McGraw.

http://www.xmcgraw.com/how-to-quickly-add-touch-id-using-local-authentication-api/feed/ 0