Increasing App Usage with Suggestions Based on User Activities
At a glance
| Item | Summary |
|---|---|
| Purpose | Demonstrate searchable activity donation, keyboard content suggestions, and directions-request handling. |
| Architecture | A storyboard tab app with separate controller-led examples; AppDelegate routes system entry events to the relevant tab. |
| Data style | Framework values such as MKMapItem, NSUserActivity, and MKDirectionsRequest are passed directly; no app model/service layer is introduced. |
Project structure
ProactiveToolbox/
├── AppDelegate.swift
├── SearchViewController.swift
├── LocationViewController.swift
├── KeyboardSuggestionsViewController.swift
└── DirectionsRequestViewController.swift
Each controller is a self-contained demonstration. Shared concepts are system contracts, not shared domain objects.
Overall architecture
flowchart LR
System["Search / App Switcher / URL"] --> AppDelegate
AppDelegate --> Tabs["UITabBarController"]
Tabs --> Search["SearchViewController"]
Search --> Location["LocationViewController"]
Location --> Activity["search-eligible NSUserActivity"]
Tabs --> Keyboard["KeyboardSuggestionsViewController"]
AppDelegate --> Directions["DirectionsRequestViewController"]
Directions --> MapKit["MKDirectionsRequest validation"]
Reference code
ProactiveToolbox/AppDelegate.swift:25 — the application boundary decodes a continued activity and routes it to the search flow.
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
// ...
}Ownership and state
classDiagram
AppDelegate *-- UIWindow
SearchViewController *-- CLLocationManager
SearchViewController *-- Array : map items
LocationViewController o-- MKMapItem : selected item
LocationViewController *-- NSUserActivity : UIResponder property
DirectionsRequestViewController *-- Bool : validation flags
KeyboardSuggestionsViewController *-- UITextField : outlets
Ownership evidence
ProactiveToolbox/LocationViewController.swift:47 — the visible location screen creates and assigns the donated activity it represents.
func updateUserActivity() {
// ...
}Each tab controller owns its framework objects and transient UI state. UIKit owns the controller hierarchy and manages a view controller’s userActivity while visible. The app delegate owns only top-level routing, not the feature state.
Class and protocol design
| Type | Responsibility | Framework contracts |
|---|---|---|
SearchViewController |
Location request, local search, results table, and segue preparation | UITableViewDataSource, CLLocationManagerDelegate |
LocationViewController |
Display a place, donate/restore activity metadata | NSUserActivityDelegate |
KeyboardSuggestionsViewController |
Annotate fields with semantic content types | UITextFieldDelegate |
DirectionsRequestViewController |
Validate and display a directions destination | UIKit controller with MapKit/CLGeocoder calls |
AppDelegate |
Route continued activity and directions URL entry | UIApplicationDelegate |
There are no app-defined protocols; framework delegates are the extension seams.
Access control
| Boundary | Effect and rationale |
|---|---|
fileprivate cell and status-image names |
Restricts UI implementation constants to their controller source files. |
Explicit internal validateAndDisplayDirectionsRequest |
Same effective access as the default; permits AppDelegate to invoke the tab controller. |
Most outlets and state are implicit internal |
Storyboard-era sample code favors target-wide visibility over strict encapsulation. |
No public app API |
All controllers belong to one executable module. |
ProactiveToolbox/SearchViewController.swift:28 and ProactiveToolbox/DirectionsRequestViewController.swift:25 show file-scoped constants; the cross-controller method is at ProactiveToolbox/DirectionsRequestViewController.swift:37.
Logic ownership and placement
| Logic | Owner |
|---|---|
| System-event decoding and tab selection | AppDelegate |
| Map search and result navigation | SearchViewController |
| Activity eligibility, payload, and searchable attributes | LocationViewController |
| Semantic text content types | KeyboardSuggestionsViewController |
| Directions validation/geocoding | DirectionsRequestViewController |
Design patterns
| Pattern | Evidence | Purpose |
|---|---|---|
| Controller-led MVC | ProactiveToolbox/SearchViewController.swift:17 |
Keeps each demonstration screen self-contained around framework values. |
| Activity donation | ProactiveToolbox/LocationViewController.swift:47 |
Makes a visible location eligible for system suggestions and search. |
| Application routing | ProactiveToolbox/AppDelegate.swift:46 |
Maps external URL/activity entry to a tab and controller. |
| Framework delegate | ProactiveToolbox/KeyboardSuggestionsViewController.swift:16 |
Integrates text-field and lifecycle behavior without polling. |
Naming conventions
- Controller names describe the system feature being demonstrated:
KeyboardSuggestions,DirectionsRequest, andLocation. - Restoration fields use
...ToRestore, separating pending input from currentitemstate. - Methods use direct action names:
updateUserActivity,restoreMapItem, andvalidateAndDisplayDirectionsRequest.
Architecture takeaways
- Route external application events at the app boundary, then hand feature values to a screen owner.
- Donate activity from the controller whose visible state it represents.
- Keep unrelated proactive features in isolated screens when they share no domain model.
- This older sample is intentionally controller-centric and only lightly encapsulated.
Source map
| Source | Role |
|---|---|
ProactiveToolbox/AppDelegate.swift:21 |
System-event router |
ProactiveToolbox/SearchViewController.swift:17 |
Search flow owner |
ProactiveToolbox/LocationViewController.swift:16 |
Activity donation owner |
ProactiveToolbox/KeyboardSuggestionsViewController.swift:16 |
Semantic text fields |
ProactiveToolbox/DirectionsRequestViewController.swift:17 |
Directions validation |