We recently launched Yelp’s new Today Widget, so now you can search Yelp with a single tap from anywhere on your iPhone or iPad (iOS 8+).

Today Widgets live in Notification Center, which can be accessed anywhere on the device by swiping on the top of the screen. You can search directly for a category near your current location, or open up the app directly to search input.

App Extensions

Today Widgets are a type of app extension (which include action, share, and photo editing extensions, custom keyboards, and document pickers). An app extension is a separate binary from the containing app, running in a separate process, and requiring a new target in Xcode. App extensions are packaged as a part of a containing app, and launched by a host app. In the case of something like a share extension, the share extension is launched in the context of a ‘host app’ and linked to its ‘containing app’. The containing app is the app downloaded from the app store, and the ‘host app’ is a third party app. For a Today Widget, its host app is the Notification Center.

Today Widgets

Today Widgets use standard UIKit classes, meaning you can subclass UIViewController and UIView. The design for the Yelp widget is static so using a storyboard could have worked, but we’ve found it hard to use storyboards and handle lots of merge conflicts. Instead, the Yelp widget views are constructed programmatically and use Auto Layout. Auto Layout was chosen because it makes supporting multiple screen sizes easy (more on this later in the Localization section).

To display widgets, the system takes snapshots of the widget’s view, and displays the previous one until a new one is available. To update the view for a snapshot, a widget’s main view controller can conform to the NCWidgetProviding protocol. The protocol’s widgetPerformUpdateWithCompletionHandler method is opportunistically called by the system when the widget is about to be shown and in the background. The widget can update its content in this method, then call the completion handler and tell the system whether there was a view update from new data. Today widgets have several limitations. It can’t access sharedApplication, perform long-running background tasks, and has an unpredictable life cycle since it can be killed at anytime.

The widget has three ways to communicate:

  • The widget can tell its NSExtensionContext to open an URL in the containing app
  • With app groups enabled, the widget and containing app can both read from and write to shared app group resources. This is done by instantiating a shared NSUserDefaults for the app group, that is separate from the standard NSUserDefaults in the main app.
  • It can make requests through NSURLSession. NSURLSession does networking in a separate process from the containing app or the today widget. If the extension’s process is killed before the request responds, the request response is sent to the containing app.

To launch the containing Yelp app, we used NSExtensionContext openURL:. Yelp has several public deep links for searching, opening a business, and viewing check-ins, and we used the same links to open up the app from the widget.

Analytics

The widget can send analytics if you use NSURLSession, and frameworks like Google Analytics also work well with the widget. When we use deep links to open the app, we add some tracking parameters from the widget. These parameters are passed to our main app and allows us to track how an app session originated.

Localization

The widget is available in all the countries and languages of the Yelp app. We updated our localization scripts to work for this new target, and Auto Layout allowed us to ensure that text wraps correctly for all the different languages we support. Localization in the widget works like the main app, using the NSLocalized set of macros. The widget should have its own set of Localizable.strings separate from the main app, since it builds into a different target.

Next Steps

You can add a Today Widget by adding a new target in your project. The default template will create a storyboard for you, but if you prefer to create your views in code you can also define the starting view controller by specifying the NSExtensionPrincipalClass in the widget’s Info.plist. If you’re interested in storyboards, we also have a blog post on our Apple Watch app here, which does use storyboards. We’re just getting started with our widget, so stay tuned for more!

Intern at Yelp and build products that matter

Our interns get a hands-on experience of building products that reach millions of consumers. Think you could make the cut? Apply here!

View Job

Back to blog