Create Today Extension (Widget) with SwiftUI
Published by @SoNiceInfo at 7/5/2020
I'll show you how to create a Today Extension (widget) using the SwiftUI.
If you want to know about the new widgets from iOS 14 announced at WWDC20, please see Create Widget Extension.
Add Today Extension
Go to File → New → Target... then dialog appears, select Today Extension
and press Select.
Enter the appropriate Product Name and Finish.
Press Activate when asked when activating "PRODUCT_NAME" scheme.TodayViewController.swift
, MainInterface.storyboard
and info.plist
will be added in the new directory.
You are now ready to create a Today Extension.
By default, the Today Extension shows "Hello World".
Delete Hello World on MainInterface.storyboard
The contents of the MainInterface.storyboard looks like this
This time we'll be developing with SwiftUI instead of Storyboard, so we'll remove the Hello World label.
At this point, make the background to the none at the right pane. Or please select your color.
Prepare SwiftUI View
File → New → File... (⌘N) to select SwiftUI View.
Here, the file name is WidgetView.
//
// WidgetView.swift
//
import SwiftUI
struct WidgetView: View {
var body: some View {
HStack {
Image(systemName: "globe")
Text("Hello, SwiftUI!")
}
.font(.title)
}
}
struct WidgetView_Previews: PreviewProvider {
static var previews: some View {
WidgetView()
}
}
Call WidgetView in TodayViewController
In viewDidLoad
, use UIHostingController
to call WidgetView
.
Don't forget to import SwiftUI
.
After that, let it automatically determine the display area and make the background clear.
//
// TodayViewController.swift
//
import UIKit
import NotificationCenter
import SwiftUI
class TodayViewController: UIViewController, NCWidgetProviding {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let vc = UIHostingController(rootView: WidgetView())
self.addChild(vc)
self.view.addSubview(vc.view)
vc.didMove(toParent: self)
vc.view.translatesAutoresizingMaskIntoConstraints = false
vc.view.heightAnchor.constraint(equalTo: self.view.heightAnchor).isActive = true
vc.view.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
vc.view.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
vc.view.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
vc.view.backgroundColor = UIColor.clear
}
func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResult.Failed
// If there's no update required, use NCUpdateResult.NoData
// If there's an update, use NCUpdateResult.NewData
completionHandler(NCUpdateResult.newData)
}
}
Completion
I published the code at GitHub.d1v1b/WidgetSample: Today Extension Sample with SwiftUI
iOS 14 Support
New "Widgets" have been announced for iOS 14 that can be placed on the home screen.
You can continue to use the Today Extension in iOS 14 using the methods here.
If you want to know about the new widgets from iOS 14 announced at WWDC20, please see Create Widget Extension.