Developing for CloudKit - Part 4

Read Part 1 in series on Developing for CloudKit

Read Part 2 in series on Developing for CloudKit

Read Part 3 in series on Developing for CloudKit

In the first 3 parts of Developing for CloudKit, I walk through creating a sync layer for Core Data that uses CloudKit as its backend.

I mentioned at the end of part 3 that I wanted to “abstract the sync layer so it's independent of your data model. I hope to open source it at some point in 2015”.

In the past year, I improved and made many changes to the sync layer (called SSCloudManager) and it shipped as the syncing mechanism in Screenshot++.

The main issue is SSCloudManager is still tightly coupled to the Screenshot++ data model. Creating a version of SSCloudManager that’s data model agnostic would require substantial time to invest that I simply do not have. Because of that, I began searching for a SSCloudManager replacement that didn’t involve months of my time that I would rather spend elsewhere.

Currently, I’m using Ensembles 2 as a replacement for SSCloudManager in development of a few projects. It’s everything I envisioned SSCloudManager to be and then some. I love it.

I’ll be posting in future about adopting Ensembles 2 into my projects. In the mean time, if you’ve created your own sync layer, I would love to hear about it.

Sunset for Parse

Allen Pike’s piece on the Parse shutdown is insightful, in-depth, and a great read. Marco’s response adds his thoughtful perspective.


In early 2013, I began looking for a syncing service to use in multiple iOS apps. I was one in a long list of developers who viewed sync as an add on, that sync should be as easy as adding another project dependancy. Parse added much of the functionality I was looking for. It was easy, cheap, and the company seemed to understand the needs of their customers.

It wasn’t long after I began testing Parse integration in a sample project that news broke of the Facebook acquisition. Parse promised that with Facebook’s backing, Parse would be able to grow faster and not worry about monetization. All in the name of good will for developers.

While I applauded their enthusiasm, the acquisition meant that from that day forward, Parse would be acting in Facebook’s best interests, leaving developers in second place.

Because I have zero faith in Facebook, I could not have faith in Parse as a product or a company and began exploring alternatives.

That decision paid off this week. Instead of scrambling to figure out a new backend as a service (BaaS) and migration strategy, I can instead use that time and effort to continue building new apps and making improvements to existing products.

The Parse shutdown has brought the BaaS debate back to the forefront in the developer community. That is, should developers roll their own BaaS or migrate to a Parse alternative like CloudKit?

Instead of relying on Parse, I jumped into Apple’s CloudKit over a year ago. It’s baked into Apple’s platforms and (for now) has Apple’s support. I use CloudKit as a back-end for Screenshot++ and in unannounced projects.

Allen and Marco lay out the two sides of this debate quite well. For many developers who have experience in running their own servers, this has always an easy decision. Experienced backend developers like Marco haven’t had to rely on 3rd party solutions. For them, it’s relatively easy to roll their own solution and today they’re in the clear; it’s hard not to hear the smug comments coming from atop their high horses.

For the rest of us, Parse was the solution to a problem that few app developers have the experience or resources to properly solve. I don’t view Parse as a shortcut and I don’t think the objective should be to rely on a service like Parse until you can create something better in-house.

For the 600,000 apps that used Parse, they’re in a tight spot and most of those will end up abandonware if they’re not already. To insinuate their developers should have all created custom backends is out of touch with today’s App Store economic reality.

With Parse out of the picture and the app BaaS market underserved, now is the perfect time for a new competitor to fill the void.

Trials with UISplitViewController (iOS 8 and later)

I'm currently writing an updated version of a popular app that will take advantage of split views on iPhone and iPad.

With iOS 8, Apple made considerable changes to UISplitViewController (details can be found at developer.apple.com). It now respects size classes and presents master and detail view controllers at the same time on iPhone 6/6S plus.

I ran into an issue where, on the iPhone 6 Plus, if you ran the app in portrait, it would open to the detail view. This isn't want I wanted (and don't think this is what other developers expect to be default behaviour). When I began implementing the new UISplitViewController delegate methods, I put them into the app delegate until I had a better place to put them and thought nothing of it.

The problem lies in placing view controller delegate methods in an app delegate - they weren't called until the app's UI was visible and responsive.

The solution (sort of) is to place UISplitViewController's delegate methods within a subclass of UISplitViewController. It's ugly, it breaks Cocoa conventions - I hate it. It's also the only thing that seems to work. This cannot be Apple's intended implementation, can it?

For those who want a more detailed explanation, the method below wasn't being called until after UIKit had presented its stack.

- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {

 if ([secondaryViewController isKindOfClass:[UINavigationController class]]
&& [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[GenericResourceViewController class]]
&& ([(GenericResourceViewController *)[(UINavigationController *)secondaryViewController topViewController] resourceLoaded] == NO)) {
return YES;

} else if ([secondaryViewController isKindOfClass:[GenericResourceViewController class]]) {
return YES;
}

return NO;
}

This methods asks the delegate how it wants to fold the detail (right) view controller stack into the master (left) view controller stack.

When UISplitViewController is created in a storyboard, much of the work is done for you including creating the segues that connect the splitViewController to the master and detail view controllers. The above code tells the split view controller to make the master visible when collapsed (in portrait) if the detail's data isn't initialized. After moving this and other delegate methods to the splitViewController itself, it's now called when the splitViewController is laying out its subviews for the first time.

Ideally, I would like to move the delegate methods out of the splitViewController for reusability reasons, but what should be responsible for them? I don't want to maintain multiple UISplitViewController subclasses, especially if they just contain delegate methods. I'll look at creating dedicated controllers to place these delegate methods. The problem lies in where these are initialized. I can't create them in the app delegate or Ill be right back to square one. I had previously tried including the delegate methods in the master view controller with the same results.

If you have suggestions, please let me know on twitter @wesleydyson or in the comments.

Apple's Magic Keyboard - First Impressions

Frequent Readers of this blog will know of my ongoing frustrations with the Apple Wireless Keyboard. The 1 and 2 keys on the first unit I began using in 2011 stopped working after about 2 years of daily use. Liquid may have spilled on it in that time, perhaps it was a manufacturing defect. Either way, I ordered a new keyboard.

The second Apple Wireless keyboard took 2 AA batteries instead of 3 and as far as I could tell, that's where the changes ended. I was happy use be using less batteries, so far so good.

Earlier this fall, the 1 and 2 keys on that second keyboard also failed. It could be because, in Objective-C, the ! and @ are commonly used symbols, but the same failure on the same model is more than a 1-off defect. Likely, a 3rd keyboard would eventually exhibit the same problem.

I decided not to buy a third Apple Wireless Keyboard and instead shop around for a different brand all together. I quickly learned that the alternatives either had the aesthetics of a first-grader or were filled with blue LEDs.

With the 2015 5K iMac, Apple introduced the Magic Keyboard. It has a thinner profile, low-travel keys, San Francisco key type, rechargeable battery, and includes no blue LEDs (it's a feature, not a bug). The rechargeable battery is what attracted me to it as I was plowing through over a dozen AA batteries each year.

I placed my order and I'm using the Magic Keyboard to write this post.

So far, I've been happy to have a keyboard with working 1 and 2 keys again. Pairing the keyboard with my iMac was as easy as plugging the keyboard into a Lightning cable. I now prefer the new low-travel keys over the old style and key strikes sound good to my ear.

Looks like I'll be sticking with the Apple Magic Keyboard.

Text Entry and the new Apple TV

The Siri remote on the new Apple TV is fantastic for scrolling through a UI and playing a new class of games thanks to the built-in gyroscope and touch pad but it's lousy for text entry.

But the new Apple TV hardware remote is no keyboard replacement. In fact, it's a step backwards from the last-generation Apple TV. With the previous Apple TV, you could use your iOS device's keyboard to enter text via the IOS Remote App. If a text field appeared, just open the Remote app and use the on-screen keyboard.

To enter text on this Apple TV, you have to manually enter each character with the hardware remote like a dog. Curiously, the new Apple TV doesn't support the Remote app at all and other than for the initial setup process, Apple TV has no use for your iPhone or iPad. Surely though, you could pair a Bluetooth keyboard? Nope.

For more about the frustrations in these early days of Apple TV 2015, take a look at Jason Snell's piece for Macworld.

What gives?

At 5 days after launch and more than a month of using the Dev kit, my best guess is a conscious decision by Apple to limit text entry on the new device. Remember that the new Apple TV is running a custom version of iOS 9.0. Devs were encouraged to port games and the process was relatively straight forward. Other apps like Speed Test and Plex have arrived on the App Store too. But what about Twitter, Pages, or Things?

Apple has made it nearly impossible to create or port apps that require more text entry than a basic search term or password. I mention Pages because it is technologically possible for the Apple TV's A8 SoC to run the iOS version of Pages. The market should decide if Text Editors on Apple TV is a good idea, not Apple.

Either Apple doesn't feel text editors have a place in the living room or decent text entry is an afterthought. I would believe the latter, that maybe it's coming in a future software update, if the Remote had never existed and we had not been able to pair a Bluetooth keyboard in the past. It's not a misstep, in tvOS it's by design. Things may change in tvOS 2 but I'm not holding my breath.

Screenshot++ 2.1 for iPhone and iPad Available Now

Screenshot++ has been updated with support for 3D Touch on new iPhones with Push and Pop for screenshots and new Quick Actions from the Home Screen.

Incorporating Peek and Pop into your workflow feels natural and easy to use. On iPhone 6s or iPhone 6s Plus, press lightly to see a preview of any screenshot.

Screenshot++ includes 3 new Home Screen Quick Actions - Clean Library, Open Dashboard, and Open Most Recent. Deep press on the Screenshot++ Home Screen icon to access these time-saving shortcuts.

This version also introduces a new app icon that's cleaner and more fun than before and sync that's now 50% faster for must users.

Screenshot++ 2.1 is a free update to existing Screenshot++ users, available now on the App Store!

Screenshot++ - Implementing Peek and Pop and Home Screen Quick Actions for iPhone 6s

Screenshot++DualiPhone6Promo.png

Screenshot++ 2.1 is about to enter beta testing and includes support for Peek and Pop and Home Screen Quick Actions for iPhone 6s and iPhone 6s Plus.

This is the first app I've updated to take advantage of these new features and I think they're awesome. Peeking is fast and fluid and a definite time saver for users.

Both of these new 6s features are relatively easy to implement if you've been using NSUserActivity and either table or collection views in your app. For a guide on implementing Peek and Pop, check out Apple's UIViewControllerPreviewing API sample code. For Home Screen Quick Actions, I used 3D-touch on Github to get started.

For Peeking into a UICollectionViewCell, set the sourceRect property on UIViewControllerPreviewing to that of the selected cell (I assume this is the same for UITableViewCell but I haven't tried Peek with a tableView yet.) Something like this:

UICollectionView *cv = self.collectionView;
UICollectionViewLayoutAttributes *attributes = [cv layoutAttributesForItemAtIndexPath:_openScreenshotCellIndexPath];

CGRect cellRect = attributes.frame;
[previewingContext setSourceRect:cellRect];
_assetViewController.preferredContentSize = CGSizeMake(asset.pixelWidth, asset.pixelHeight);

If you have any questions leave a comment or find me @wesleydyson on Twitter. Check out Screenshot++ and join the beta!