This sample code builds a weather app that displays a simple five-day weather forecast using a horizontally paging collection view. Each collection view cell contains a label showing the day the forecast applies to, an icon representing the forecast, and a label describing it. In this example, the Today extension provides a more compact, glanceable view of the app’s data.
This sample project consists of three targets:
The main app — WeatherApp
A Today extension containing the widget — WeatherTodayExtension
An embedded framework for shared code — WeatherFramework
Place Shared Code in an Embedded Framework
If both the main app and the Today extension require access to the same classes, those classes must be extracted into an embedded framework. In this sample project, the model code is located in WeatherFramework.
Any classes or other entities in WeatherFramework must be made explicitly public so they’re available from the other targets. The initializer of the WeatherForecast struct—which is private in the implicit implementation—must also be reimplemented and made public.
If both the main app and the Today extension use images or other assets, as in this sample, include them in an asset catalog contained within the embedded framework. Load image assets from the embedded framework by using the init(named:in:compatibleWith:) method of UIImage.
The main app processes the URL in the application(_:open:options:) delegate method, where it parses the parameters before scrolling the collection view in the ForecastViewController to the correct cell.
Weather forecast data in this sample is generated randomly and stored on disk in a property list (.plist) file. To allow both targets to access the same area of the file system, you add the App Group entitlement to each target that requires access. Once the entitlement is added and an App Group has been created, you can use the containerURL(forSecurityApplicationGroupIdentifier:) method of FileManager to get the URL to the shared directory.
Tapping the refresh button on the navigation bar of the main app generates a new random weather forecast and writes it to the shared app group’s container. To ensure that the Today extension always shows the latest data, use the widgetPerformUpdate(completionHandler:) method of the NCWidgetProviding protocol to update your data.