Building the widget
Apple’s Programming Guide for Extensions is quite good at providing a quick intro into how building extensions work. However, it falls somewhat short at explaining the details and especially some of the issues one might encounter. So in this post I will cover what I did to get the Widget we’re using to work and some of the pitfalls I found on the way.
Running the widget
Running the widget turned out to be quite the pain. XCode creates a separate target for your Widget but unfortunately it doesn’t provide good instructions on how to use it. First of all, running the widget target won’t unlock your phone like a regular app does, instead you have to have the device unlocked and to be safe have it on the home screen. While it’s gotten more stable with recent XCode betas there are still some issues and from time to time the widget simply won’t launch.
Once you launch the app, you’re presented with a dialogue asking you what app to run. At first this feels very odd but there is actually only one choice for a widget and that is the today app (If it’s not found at the top simply search for it).
A neat trick that works in the current beta of XCode at least is to edit the widget scheme and selecting Other… under executable then simply closing the dialogue. This will set the executable to Today-View, avoiding you the extra step each build.
Another interesting issue you can encounter is the error “No application exists at /Today-View”. This is also solved by editing the scheme making sure that “Debug Extensions and XPC services” is checked, as described on StackOverflow.
Sharing data between the extension and its app
This part is described quite well in Apple’s documentation however it’s lacking a clear step-by-step instruction. What you need to do is set up an App Group in the Member Center. This is a completely new feature which will force you to recreate all your provisioning profiles, since it involves changing properties in your App ID, so beware of that.
Once you’ve done that (The process is quite straightforward and the Member center guides you through it) you need to enable groups in your app. To do this, go to your app’s target and select the Capabilities tab. From here enable App Groups and check the group you created and XCode should do the rest for you. Don’t forget to do this in both your app’s target as well as the widget’s.
When all that is done you can set up a shared
NSUserDefaults like so:
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.mygroupId"];
It’s important that the ID you enter as
suiteName is the same as the one you specified in Member Center. You can then treat the
NSUserDefaults just like you normally do, with the only difference that you create a new
NSUserDefaults object each time instead of fetching it using
[NSUserDefaults standardUserDefaults]. This confused me a lot at first, as I was looking for some method to get the singleton
NSUserDefaults and recreating it each time made no sense. However this seems to be standard practice and it’s apparently the way it’s supposed to work.
Launching your application
To launch the containing application you use the URIs defined by your app. However, instead of calling
openURL: you have to use a method in
NSExtensionContext. This is somewhat poorly documented but the object is available as a property through the category
NSExtensionAdditions which is imported by default in your extension.
The following code opens a remote in our widget for example:
URSharedRemote *remote = [self.remotes objectAtIndex:indexPath.row]; [self.extensionContext openURL:[NSURL URLWithString: [[NSString stringWithFormat:@"ur://intent/remote:%@", remote.ID] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] completionHandler:nil];
All in all, extensions are still a bit tricky and not that well documented. This part of Stack Overflow is not as well-stocked with questions and answers as one might be used to and even more notable is the absence of experts so far. Getting answers to a question is still hard. All of this, combined with a lot of XCode and iOS 8 bugs (Like Springboard crashes every 4 or 5 launches) means that working with extensions can be a quite frustrating experience. However it can also be an interesting one since it’s quite uncommon these days that there is something new to discover which no one else has tried before when it comes to iOS. I hope this blog can help some developers out there who are working with widgets and if you have any questions feel free to drop a comment and I’ll try to answer as best I can.