Developing For CloudKit- Part 2

Read Part 1 in series on Developing for CloudKit

It's been a week since my first post on developing an iOS app that uses CloudKit as a syncing solution to work with Core Data. Creating a mediation layer between Core Data and CloudKit has been no walk in the part but it's simpler than it first seemed.

My app, for now, doesn't need to make changes to its data objects. I'm constricting myself to the creation and deletion of objects in CloudKit. That decision has taken a load off my plate as I, for the first time, tackle sync totally by myself.

I started with converting NSManagedObjects to CKRecords. After the upload is complete, I use the (NSString *)recordName from CKRecord's (CKRecordID *)recordID returned from the completion handler and save that back to the NSManagedObject. This allows me to keep a local reference matching an NSManagedObject to the corresponding CKRecord stored in CloudKit. For local objects that don't have a valid recordName, I'll get to that in a bit.

Next is delete, very similar, I first delete the matching CKRecord in CloudKit (if there is one) and then delete my local copy once the server deletion is finished. CloudKit has extremely useful block callback and I highly suggest you use them!

Run that on 2 devices, add an object on the first device and... nothing happens. What?

We'll have to create a CKSubscription that will send a Push Notification to other devices signed into the same iCloud account when a CKRecord was uploaded, deleted, or updated in CloudKit. I won't go into detail about APNS here but it's not entirely complicated. Each notification will (for the most part) give you a reference to the changed object in its payload. Use that to update the corresponding NSManagedObject.

Now we have an app that syncs out locally saved data but for a device to get changes, it has to be on, open to the app. An app that isn't running will never know about changes. Next we have to add a way for our app to query the server when launched. This is a little more difficult than the steps I've covered so far.

Checking for changes that occurred while offline or in airplane mode will be done in 3 stages.

The first, to backtrack a bit, we need to keep track of objects that were deleted while offline. and delete them before the next steps. If we forget this, any offline deletions will be re-added later and create a frustrating problem for the user.

Second, we check for any CKRecords in CloudKit that we don't have a matching copy of on our local device. Start by getting a list of all CKRecordIDs, compare that to all objects we have locally, and remove the matches. Now, you're left with a list of CKRecords to download.

After that, check for local objects with a valid recordName property. Local objects with a recordName that no longer exists on the server means that object has been deleted on another device. You can safely remove those objects.

Once that's complete, you've successfully updated your device with changes made on CloudKit's server, but that's only half the story. We finish by reversing that process and updating CloudKit with changes to out local objects that happen while offline. 

This process is a little faster than the last. Start by creating an array of local objects that have a nil recordName. These have either never been synced or the upload wasn't successful. Either way, they need to be uploaded, do that now.

After that, you're done. (I say that knowing I've probably forgotten a step and will feel pretty foolish when my inbox fills up. Email Marco.)

I hope this has helped you, writing it all out helped me realize I forgot a step in my code. Bonus points if you can figure out what step I added at the last minute.

Check back next week for Part 3!

Ambiguous App Store Guidelines

Panic's Transmit 1.1.1 is the latest app to fall victim to Apple's ambiguous App Store Guidelines. We have an exceptional app, made by talented and bright individuals, receiving a rejection because it violated a vague clause in the App Store Guidelines.

PCalc, another great calculator app, was recently rejected for adding calculation functionality into their iOS Today Widget even though Apple's Calculator app for OS X includes the same functionality.

Transmit, according to the App Store Review Team, was in violation because it sent data to other services that wasn't created in the app itself. Bah-humbug.

Transmit and PCalc aren't alone in trying to McGiver the increasingly vague guidelines, these are simply recent entries in a long list.

Apple seemed to be embracing developers at this year's WWDC, it seemed as though they were on our side. Looks like we jumped the gun. They have their own interests, of course, but it seemed we were in a new age of transparency.

iOS developers are now increasingly apprehensive to push the envelope on what's possible and that can only result in a poorer user experience.

Final note: as we steadily march forward to feature parity between iOS and OS X, why hinder the iOS platform? What division within Apple is reigning developers back?

The infighting within Apple is becoming clear and users and developers are taking the brunt end.


Debugging Apps on Apple Watch

With iOS 8.2 beta and WatchKit, we now have a way to create apps (sort of) for Apple Watch. With Apple Watch not actually going on sale until some time in 2015, developers can only test their apps in the Watch simulator on their Mac.

This isn't the first time developers are tasked with creating software for a device they haven't seen in person. In 2010, developers began writing apps for iPad which, at that time, wouldn't ship until months later.

There's nothing wrong with this approach. In fact, it's great that Apple gives early API access to developers so their apps will be ready on launch day.

One issue we encountered while testing on iPhone OS 3.2 was we had little knowledge of the original iPad's performance capabilities. We over-estimated what that device was capable of. Software that ran smoothly in the Simulator on a Mac with access to, at that time, a blazing-fast dual-core Intel CPU ran slow and choppy on the iPad's A4. Surprise.

With iOS 8.2's WatchKit, it's a little different this time around. Instead of running native apps on the Watch, we're only able to create extension-like software that runs primarily on iPhone. By using the iPhone's processor, Apple is able to maximize Apple Watch battery life. In addition, WatchKit doesn't yet allow for the creation of full/native Watch apps as you would think of them for the iPhone.

Native Apple Watch apps are coming sometime next year, most likely at June's WWDC. And that's when the Watch Simulator won't be enough and developers will need to test their apps on an actual device. 

So how will that actually work? With iPhone and iPad app development, you connect your iOS device to your Mac and run a project in Xcode. But, the Apple Watch doesn't have a Lightening port.

While it's somewhat of a mystery, my best guess is Xcode will bring back wireless device testing. It was a seldom talked about feature in Xcode 5 that took some tinkering to enable, but it used to be possible to wirelessly test an app on an iOS device without connecting it directly to your Mac via USB. At some point, it seems, the Xcode Team removed the feature as I can't find any trace of it in Xcode 6.1.

The possibility of wirelessly debugging an app on a device that I don't have to plug in to a computer is enticing. I would also imagine any content syncing to the device will be done wirelessly through iTunes.

If that's true, this is one developer that hopes wireless testing/debugging is supported for all iOS devices, not just the Apple Watch.

Marketing Resource for iOS Bundles

If you've recently put together an iOS App Bundle, like I have, you may be wondering where you can find the Marketing Resources.

For iOS apps, Apple provides us with guidelines and image resources for marketing purposes. This includes assets and user guidelines for the App Store Badge, psd files for currently supported iOS devices for dropping screenshots into, App Banners, and the like.

Head over to Apple's Developer Page for an explanation of iOS Bundles. Apparently though, that's it. 

How are developers supposed to advertise their Bundles?

I tried to create and then hack an App Banner (link) using the Bundle's Apple ID. The result was a blank frame. Using the Link Maker tool returned no results for my bundle.

Let's try creating something simple - an image of the bundle and an App Store link for my website.

Since the bundle icons seem to be generated though iTunes Connect, can I download a high-res version? I haven't yet found a way. Perhaps the App Store is laying out the individual icons rather than flattening them into a single bundle icon image. So far, I haven't been able to find any information. 

iTunes Connect does provide the App Store url for the bundle. So that's one step in the right direction.

It's odd Apple has so little guidance on the subject. I'm left with two conclusions. Either developers are not intended to specifically advertise their App Bundles on their website or it's an oversight on Apple's part. I'm getting the feeling the former is true.

If you've come across anything useful, let me know at w.dyson [at] me dot com.


Xcode 6 missing iOS 8 Simulators

From the xcode beta’s pull down menus, Xcode > Open Developer Tool > iOS Simulator (if you get a pop up error just dismiss it)
Once in the Simulator go to Hardware > Device > Manage Devices.
Delete everything listed under simulator.
Reboot your machine.

After that navigate back to Manage Devices in the simulator and click the plus to add back your simulators. Then the iOS 8 simulators will show up. Hope that also helps you.

I recently had to reinstall my system after a hard drive corruption and when I opened Xcode, my simulators were gone. Thanks to Reddit contributor uipoptart for this great solution for getting those simulators back.

Bug Trackr 2.0 Public Beta

I'm rounding out development on Bug Trackr 2.0 and thanks to Apple's new TestFlight service, I'm accepting 1000 helpful iOS 8 users to try out the new version.

Bug Trackr 2 adds a new Today Widget, Notes and Screenshots in each bug report, and support for iO8, iPhone 6, and iPhone 6 plus. 

If you'd like to sign up for the beta, head over to the Bug Trackr Home Page.

Please note the beta requires an iOS device running iOS 8 and later. Be sure to backup your device before installing the beta as you may have to re-install the app when the final version is released.

Thank you!

iPad Stagnating or Iteration by Design?

This year's iPad announcement was, by most accounts, received by tech media as a hum-drum affair. The iPad 2 came with a significant speed boost, Touch ID, and fancy new gold option. Not enough, however, for members of the press to wet their pants and sing the praises of Cook and co.. Some view the iPad as losing steam while others feel Apple has run out of ideas. The iPad Air 2 at this point is regarded by some as a rare gaff and oversight of Apple's upper management.

While Apple may be a company that creates a revolutionary product every 4-5 years, what they truly excel at product iteration. Apple's ability to continually improve a product year over year, work out kinks, and pick low-hanging fruit while making said product faster and more efficient is unparalleled. That may sound like I've downed the preverbal kook-aid but name one company that does it better.

Make no mistake about Apple's iterative process - it's neither by accident nor the natural progression of product creation - it's by design and completely intentional. Apple isn't a company that ships a product only to then think about the next one. Apple may have just shipped iPhone 6 but plans at this point are almost certainly finalized for iPhone 6S and well underway for iPhone 7. Apple sees products like iPhone,  iPad, and Mac not as silo'ed creations but as platforms. Platforms that grow over time and continue to improve. Platforms that have a roadmap and a story.

Look at this year's iPad Air 2 against the previous model. The addition of Touch ID is low-hanging fruit. A year ago, everyone including myself was both disappointed about the lack of Touch ID while knowing it would be in the next version of the device. The gold option is a nice addition but certainly not reason to upgrade from the iPad Air. Lastly, we have a sizeable speed boost and the move to 2GB ram but that was expected. Every year, Apple improves the performance and (usually) efficiency of their devices.

This year, there was nothing out of the ordinary. All that was delivered was expected but that's apparently a disappointment.

To add insult to injury, we have Apple's latest earnings call. iPad sales, for the first time in its short 4 year life, were down. But that was last quarter and I would attribute much of that to pent up demand from customers waiting to buy the successor to the iPad Air. I expect iPad's current quarter sales to be better than last years. But add the predictable iPad update to shallow sales numbers and the tech press will pounce.

Alas, much to do about nothing.

iPad hasn't been around long enough to be predictable. With iPhone, customers are aware they're eligible to upgrade every 2 years and most plan to. With Macs, folks rarely replace less than every 3 years. Which side does the iPad tend to lean toward?

iPad is a special beast that has never played by traditional tech wisdom. After 4 years, we're starting to see patterns emerge that move it closer to the Mac in upgrade cycle than iPhone but it's still too early to tell.

Apple isn't aiming the iPad Air 2 at iPad Air owners. It's aimed at (roughly) iPad 2 owners - an iPad released in 2011, getting long in the tooth, and most likely not eligible for next year's iOS 9.

As for features the iPad Air 2 is lacking? What were you expecting? A "Retina HD" display, if following past iOS device improvements will stay exclusive to the iPhone for a year so don't expect an @3x iPad until 2015 at the earliest. 

Apple moved the benchmark for iOS performance with the A8X chip, something that's been wildly underestimated. Currently, software isn't available to take full advantage of the new 3-core A8X or the 2GB of ram. If Pixelmator's demo is any indication, the iPad Air's speed boost is a really big deal.

If rumours are accurate, we could be seeing a new 'Pro' iPad in the near future with a larger screen and support for running multiple apps at once on the same display. As to why we didn't see such a device at this month's event is anyone's guess but, where there's smoke, there's fire. 

iPad is a device that Apple clearly has a plan for. After all, iPad is in all regards a platform and has defined what it means to be a tablet. I take Tim Cook at his word that the current state of iPad is a merely a bump in the road. This year's iPad Air 2 lays the groundwork for next year's iPad Air 3 ( or 'the new iPad Air') and so on. 

Reports of the iPad's demise are greatly exaggerated.

Creating iSource 2.5 for iOS 8

Tonight I finished work on the latest version of iSource APA (2.5). It supports and now requires iOS 8 and is currently awaiting review.

iOS 8 brings great new features and fixes many bugs introduced with iOS 7's interface redesign. Along with iOS 8 is Swift and Xcode 6.

The biggest features that users will notice first are Today and Sharing widgets. Shortly after WWDC14, I decided not to include support for these in apps that didn't absolutely need them. In the case of iSource, what was I going to include in a Today widget? A fancy slogan? An inspirational quote? Nope. I didn't want to take up people's time with a Today widget unless it provided real value.

Take the Clear Today widget. If you remove all the content in the app, it decides to give you a *cough* inspirational quote. I didn't ask for it but there it is. 

You also may notice a beta version of the Today widget I'm including in Bug Trackr 2.0. It tells you what you need to know while using the minimum amount of screen real estate possible.

Below, you'll see Pedometer++'s Today widget. Short and to the point, I like it.

iOS 8's Today view is still very much a UI playground and I realize developers are often scratching their heads about what to include there. Sometimes, the best thing to do is do nothing at all. 

Sharing widgets are another story all together. I would love to be able to create a resource share sheet, basically the same text entry you see in the app, but available through other apps. There would be a relatively low amount of apps you would want access to iSource's Share widget in but it could still be useful.

The problem is iOS 8's sharing data flow paradigm. The way iOS 8 works is that you select the data you want to share, tap the share button, and select the place or service you want to share to. An iSource share sheet would make sense in a scenario where the user, from anywhere in iOS, wants to add an entry, they bring up the iSource Share Sheet and enter in the resources parameters. But that reverses Apple's data flow in iOS 8's share sheets. It would be confusing to the user even if Apple approved it in App Review.

So for now, we're going to stay away from Today and Sharing widgets.

Also new in iSource 2.5 are completely redesigned resource icons. They fit in a whole lot better with the iOS ⅞ aesthetic and they're included as @1x/@2x/@3x (and @4x for then that day arrives) assets. The icon redesigns were something I had started last year when I added more assets but, since the introduction of @3x assets (which I didn't have), I decided to start from scratch on a new set.

iSource text Entry Sheet in Portrait with keyboard cropped.

iSource text Entry Sheet in Portrait with keyboard cropped.

iSource text Entry Sheet in Landscape with keyboard.

iSource text Entry Sheet in Landscape with keyboard.

With this version and unrelated to iOS 8 I decided to reintroduce landscape support for iPhone. This was only because of the new display sizes in the iPhone 6 and iPhone 6 plus. In the 1.0 version of iSource, I enabled landscape support because text entry was done directly in the table view. When I added the Entry Sheet around iSource 2.0, I removed landscape because springs and struts in Interface Builder didn't allow me to configure the sheet view as I wanted when displayed in landscape with the keyboard visible. With the addition of Size Classes in Xcode 6, its now possible for me to create different configurations of the entry sheet based on its size class.

Top right you'll see the traditional version of the Entry Sheet in iSource 2.5, complete with blurred background. Bottom right is the Entry Sheet in it's new landscape configuration. Nice eh? Thanks Size Classes!

At WWDC14, I was highly interested in playing around with iOS 8's new Embedded Framework support. iSource 2.5 includes the new iSourceKit framework and it's where I've put a lot of code and resources that I share between iSource APA and MLA. Without going into too much boring nitty gritty about maintaining two versions of the same app, frameworks are a godsend. For code within iSourceKit, I've been able to cut debug time in half and every minute saved debugging is one I can now spend on making great feature. Thank you Embedded Frameworks engineers at Apple!

iOS 8 App Extension Development Tips

Great insight from Tom Harrington on developing iOS 8 app extensions. For developers, Extensions are still very much uncharted territory and Tom breaks down some of the gotchas you'll come across when in Xcode.

Recently I’ve been working on some iOS 8 app extensions, and I’ve run into a few non-obvious details that might come in handy for anyone else in the same situation. Some of the following relates to bugs still in the system, and so will probably only be relevant for a limited time.