Making Toast Again
A quote from a slightly younger me quoting an even younger me:
Depression is one of those rare problems best solved by doing as little as possible. It is for this reason that one who is depressed needs friends so desperately. Without desire, the task of daily life becomes an unbearable burden. Even the will to make toast, for example, has disappeared. But the only way to keep one’s mind distracted from the recovering void is to press-on through all the mundanity of life. The act of making toast takes on a self-salvific importance it never had before. It is imperative that I make this toast in order that I avoid the temptation to try to resurrect my desire to make toast. It is making toast as an end in itself, which, as anyone who has been through depression can tell you, is no small task.
Almost every important lesson in life I end up forgetting and rediscovering and forgetting again. I’m getting really good at making the same mistakes with precision.
My Daily Habits Before and After the Apple Watch
TL;DR
Unless I’m an edge case, I think the Apple Watch is potentially a threat to businesses that depend on people filling idle time with their apps. Your mileage may vary.
Before the Apple Watch
Wake up around 8am.
Burn a few minutes looking at Twitter on my phone.
Before getting out of bed, triage a bunch of email and Slack messages I missed while asleep. Clear a bunch of other homescreen icon badges, oh my god.
Burn a few minutes looking at Twitter on my phone.
Dress and put my iPhone in my right pocket. The front one, because I’m not an animal.
Burn a few minutes looking at Twitter on my phone.
Join a series of Google Hangouts and Slack chats for work (we’re a distributed company). Between each one, look at Twitter.
Burn a few minutes looking at Twitter on my phone.
Write a bunch of code, answer a bunch of email, write some more code.
Burn a few minutes looking at Twitter on my phone.
Finish work for the day. Put on shoes and a jacket and walk to daycare to pick up the boy. While walking there, look at Twitter on my phone.
Play with the boy until he gets bored and sleepy, or until the wife takes over.
Burn a few minutes looking at Twitter on my phone.
Binge-watch something dumb like True Blood on the Apple TV while looking at Twitter on my phone.
Bed.
Burn a few minutes looking at Twitter on my phone.
Sleep.
After the Apple Watch
Wake up around 8am.
Take a few seconds to check my watch.
Before getting out of bed, triage a bunch of email and Slack messages on my iPhone which I missed while asleep. Ignore the homescreen badges because I barely see them anymore.
Dress and plug my iPhone into a spare charger on the kitchen counter because I forgot to charge it overnight.
Take a few seconds to check my watch.
Join a series of Google Hangouts and Slack chats for work (we’re a distributed company).
Take a few seconds to check my watch.
Write a bunch of code, answer a bunch of email, write some more code.
Take a few seconds to check my watch.
Finish work for the day. Put on shoes and a jacket. Grab the phone from the kitchen counter and drop it in my pocket. Walk to daycare to pick up the boy. While walking there, take a few seconds to check my watch.
Play with the boy until he gets bored and sleepy, or until the wife takes over.
Take a few seconds to check my watch.
Binge-watch something dumb like True Blood on the Apple TV while looking at Twitter on my phone.
Bed.
Take a few seconds to check my watch.
Sleep.
Jared’s Code Signing Tips: Apple Watch Edition
After much struggling and some good advice, I’ve finally managed to get an Apple Watch App/Extension running on an actual watch. Here’s some follow-up to my previous post on code signing woes.
How to Provision an Apple Watch
An Apple Watch has to be provisioned for development use in much the same way as an iPhone or iPad.
Pair your watch with your iPhone.
With both devices powered on and the watch nearby, connect your iPhone to your development Mac and launch Xcode.
Open the Devices window.
Copy the device identifier for the watch.
At the iOS Developer Center, add the watch to your development device list the same way you would add an iPhone or iPad.
Update any existing (relevant) provisioning profiles to include the new watch. Download them and double-click them to install them via Xcode. To be safe, consider deleting the older versions of the affected profiles from Xcode and from your phone prior to double-clicking the new profiles. See below for how to do this.
How to Install a Watch App/Extension on an Actual Damn Watch
When your watch app Xcode project is properly configured it will have a minimum of three targets:
- the host app
- the watch app
- the watch app extension
All three targets require the following:
- a unique app ID for that target
- a code signing identity (applies to all targets)
- a unique provisioning profile for that target.
If your app also has other extensions (like a Today widget, etc.), or if it uses a custom framework to share code between all targets — you may have many more targets. Other extensions require the same things as the watch app/extension above. A framework only requires a code signing identity.
Create app IDs and provisioning profiles at the iOS Developer Portal. Download and install the new profiles as described above.
Your app IDs will look something like this:
com.company.App-Name
com.company.App-Name.todaywidget
com.company.App-Name.watchkitapp
com.company.App-Name.watchkitextension
After having created and installed all the new profiles for all your required targets, specify the code signing identities and provisioning profiles using the same methods I recommended in my previous code signing post. Make sure that you have entered all the app IDs in their respective Info.plist
entries, and that the paths to the Info.plist
s in the Xcode build settings for each target are correct.1
After all this is complete, consider relaunching Xcode, your iPhone, and your Apple Watch to eliminate bugs related to caching issues (this happens a lot with Xcode in particular).
Debugging Tips
If you’re running out of ideas on what could be going wrong, try the following:
Look at the console logs on your iPhone. This OS X app by Lemon Jar is the easiest way to do this. I was able to find a little bit of info about an installation verification error in this way.
Look at the build logs in Xcode. Search for
Sign
(the word sign followed by a space) to see just the signing steps. Highlight a step to show the expansion button, and expand the log to see extra information. This is how you can verifiy which profile and signing identity were used for each target.
A Note About Entitlements
You are likely going to want to share application data between your host app and its extensions using a shared app group directory. This requires several things:
Enable the “App Group” entitlement for all of your app IDs (not just the host app, but all extensions, too) on the developer portal. I’m not sure, but I think you might need to regenerate provisioning profiles after adding this entitlement.
Update the Xcode “Capabilities” section for the host app and all extension targets to make sure that “App Groups” is enabled and the correct group name is checked.
By this point, Xcode should have automatically created
.entitlements
files for all your targets, and included them in the appropriate line in theCode Signing
section of the build settings for each target. Take heed: do not specify an entitlement for a watch app, only for a watch extension.Inspect your entitlements files to make sure they have the correct app group name(s). Also make sure that the paths to the entitlements files are correct in the build settings for each target. These can get out-of-sync with the actual path to the files on disk.
How to Delete Provisioning Profiles from Your Development Mac
Prior to getting started, I suggest doing some provisioning profile house cleaning. This process is so hard to discover that I’ve changed my mind about suggesting you just Google the answer. Here’s how to delete old profiles from your development Mac using Xcode 6:
Go to Preferences > Accounts. Select an Apple ID on the left, and double click the team name in the list of teams on the right (there may be only one team).
A modal sheet appears with a list of provisioning profiles installed on your Mac. Right click a profile and choose “Show in Finder.”
From the Finder, you can trash the profile as you would any other file. Bear in mind that the containing folder contains provisioning profiles from all of your developer accounts on your Mac, so take care not to trash the wrong profile.
Repeat as needed.
How to Delete Provisioning Profiles from Your iOS Device
It used to be possible to view and delete provisioning profiles directly on an iOS device via the Settings.app. I’m not sure which version of iOS changed this behavior, but now you’ll have to use Xcode in order to remove a profile.
Open the Devices window in Xcode.
Connect your iOS device and right click it in the devices list when it appears.
Choose “Show Provisioning Profiles”
Select a provisioning profile you want to delete, and then click the minus button.
Repeat one-at-a-damn-time as needed. Sigh. After a while your device may have many provisioning profiles, including numerous duplicates of the same profile as it gets updated with additional devices and certs, so this click-and-delete process can be tedious.
-
They must be manually updated if you reorganize the hierarchy of your project files on disk — something you might do when adding a bunch of new targets to your project. ↩
Follow These Guidelines and Never Struggle with Xcode Code Signing Again
For at least a year now I haven’t had any struggles with Xcode’s code signing, thanks to the following habits. Some of them seem like overkill, and all of them are a lot “harder” than using the built-in “support” in Xcode, but — fuck all that noise. Do these things1 and get back to work:
Never use Xcode’s built-in code signing helpers. Especially avoid any button that says Fix Issue. It fills your Developer portal with dozens of worthless “iOS Team Provisioning Profile Blah…” profiles and leads you towards Provisioning Profile Rot.
Never use wildcard app identifiers. These are especially problematic when you belong to multiple teams, each with multiple wildcard app identifiers. Take the extra few seconds it takes to log into the developer portal on the web and create an app-specific bundle ID for every app, even proofs-of-concept. By avoiding wildcard app identifiers you eliminate an entire vector of shit on the path to code signing hell. If you have any existing wildcard profiles, delete them all immediately. Modern versions of Xcode make this much harder to do than it used to be. Let me Google that for you. If you really need a wildcard app identifier, just create an identifer that is literally
com.company.Wildcard
(orcom.company.RadarSample
, etc.) and re-use it as needed.Use build configs and shared schemes. Make life easier on yourself and check the “Shared” box in the “Manage Schemes…” window next to at least two schemes. Have one for development and one for App Store releases at the very least. Consider adding a third for beta builds if necessary. Select the appropriate build config in the editing window for each scheme. If you use the default build configs provided by Xcode that’ll be
Debug
for your development scheme andRelease
for your release scheme.Use explicit code-signing identities, and automatic profile selection. Since you’re now using shared schemes linked to specific build configs, you can make your Xcode project settings even more helpful. In the Code Signing Identity and Provisioning Profile sections for your project settings, specify explicit signing identities for any build configs that require distribution certificates (Ad Hoc, Enterprise, or App Store distributions). You can also try the automatic
iOS Distribution
setting if you’re lazy, but I’m on too many teams and don’t trust Xcode to do the right thing. I do recommend using theiOS Developer
automatic setting for yourDebug
build configs, since this scales better when working with other developers. I have found that by using the above settings for signing identities, I can use theAutomatic
provisioning profile setting for all build configs without hiccups.Repeat your project-level settings at the target level. Another common problem is when project-level settings for code signing and profile selection don’t match the target-level settings. Unless you think you’ll never make this mistake (I used to think I could handle this. Now I know better.), manually set the code signing and provisioning profile settings at both project and target levels. Periodically check them to make sure they didn’t get out-of-sync.
Delete expired certificates from Keychain Access. Keychain Access makes this pretty easy to do. Most certificates (Ad Hoc, APN, and App Store) expire after 365 days. Some Enterprise certificates may last up to three years. Create calendar alerts the same day you create new distribution and APN certificates, to remind yourself to get them updated and ready to go ahead of time, before they expire and your APN server starts flaring up with signing errors.
Make sure you have all the certificates you need in Keychain Access. You will need at least two certificates for each team to which you belong: 1) A developer certificate that gives you permission to install apps on your own devices. 2) A distribution certificate that allows you to sign Ad Hoc and App Store builds. You might also need two additional certificates for push notifications (one for development and one for production builds). Developer and Distribution certificates apply to all apps on your team. APN certificates are specific to each application. Expand the carets to ensure that you also have the private keys for all these certificates. Store your certificate exports someplace that is both secure and convenient. Everyone on your team should be able to ship to the App Store in case all your senior engineers get serial-crushed by some huge friggin guy.
Relaunch Xcode whenever you install new profiles or certificates. Cached expired certificates are particularly prone to caching errors.
Update 1: I’ve posted a follow-up article with code sigining tips for Apple Watch apps. April 25, 2015 — JTS.
Update 2: If you use CocoaPods, you’ll need this post-install script to make sure all your dependency frameworks are using the correct code-signing identities for the current scheme/config. My script assumes that you are using a distribution identity for configs named Beta
and/or Release
.
-
Caveat: I only stand by this advice for iOS projects. I’ve no idea what kind of cowboy antics you’d have to do when shipping OS X binaries for both Mac App Store and direct sales distribution. ↩
Apple Watch Try-On, Unsorted Thoughts
The Milanese Loop is by far the most comfortable band. It drapes around the uneven curves of your wrist like a fabric, but feels cool to the touch like a metal band. The spaces between the links breathe more than any of the other bands. It’s trivial to change the tightness of the band while you’re wearing it. In the summertime, when you’re constantly going from steaming hot weather outside into shivering cold air-conditioned offices, I expect that this is the band that will feel the most comfortable, all the time. The magnetic clasp is stronger than I expected, and has a rubber gasket around the perimeter that enhances the grip and prevents slippage. I’m happy that I chose this one for myself.
The stainless steel Link Bracelet is beautiful, and one of the most comfortable metal bands I’ve ever tried. Both styles are darker than I’d expected. The regular stainless steel absorbs the ambient color around it: your skin tone, your clothes, the room. The result is a color that is darker and more subtle than you might guess from the photos online, which are bathed in unblemished electric white light. So unless you’re Powder and live in Jony Ive’s secret prison, expect the stainless steel Link Bracelet to look grey, not silvery, in most contexts.
The Space Black Link Bracelet is just what is says: black. It looks even darker in person than it does online, again because most everyday lighting isn’t as bright as the lighting used for the product photos. Get this one if you want a black watch. Don’t get it if you’re looking for tungsten/charcoal.
The brushed texture of the Link Bracelet looks bad in constrast with the mirrored finish of the Apple Watch face. Either one separately is beautiful, but side-by-side the two textures clash like stripes and plaids. The Space Black style hides this mismatch better than the regular style. The Classic Buckle, Milanese Loop, and Modern Buckle — which have a mirror finish for the metal components – all look better in practice than the Link Bracelet.
The Leather Loop feels cheaper than it should. It doesn’t have the supple, leathery feeling I was expecting. Those ridges are cored with hard magnetic rods. The result is a feeling of a thin leather coating around hard rods, not a leather band. Your fingers make you doubt you’re even touching genuine leather. I do like how easy it is to change the tightness of the band on the fly. Cheap feelings aside, it is a comfortable band. If you like the look I would not hesistate to get it.
The Sport Band felt luxurious and satiny under my finger tips, but around my wrist it felt pretty uncomfortable. No one’s wrist is a perfect oval. There are lumps and uneven curves where tendons shoot through fat and bone. The thickness of the Sport Band means that it applies uneven pressure against your wrist bones as it is tightened. Perhaps it will break-in over time, but I imagine it could feel uncomfortable after long periods, especially in hot, sticky weather. If I owned this one I’d be constantly adjusting where the pin is lodged. Speaking of which, it’s a little fiddly getting the sport band attached with one hand – lodge pin, bend remainder, tuck in the tip, flatten the remainder – but not bad. Your mileage may very. I’m a restless, fidgety person. It’s easy to make me physically uncomfortable.
The Modern Buckle is elegant. The leather is much thinner in person than it looks online, and in a good way. If was buying one as a gift for someone with a restrained taste, this is what I’d choose.