The goal is to build a widget that can fetch quotes from TronaldDump and display it on the home screen. It'll also automatically update every 10 mins.
For this, you'll need the latest Xcode 12 Beta.
Start up a new project with iOS and then add a new target with WidgetExtension. You can delete the boilerplate code for now.
Add a Swift file named Quotes.swift. This will contain the structure and functions to get the quote.
//Structure of the quotestruct Quotes: Codable {var value: String?}class QuoteController {let url = URL(string: "https://tronalddump.io/random/quote")!static let shared = QuoteController()//Get a random quote from tronalddumpfunc getQuote(completion : @escaping(Quote)->Void) {let session = URLSession.sharedlet task = session.dataTask(with: url) { (data, response, error) inguard let data = data else { return }let quote = try! JSONDecoder().decode(Quote.self, from: data)completion(quote)}task.resume()}}
This file will handle all the quote-related stuff. The next step is to head to the QuoteWidget.swift file.
The smallest element of a widget is the structure of the item inside the widget i.e. the quote
struct QuoteEntry: TimelineEntry {var date: Datevar quote: Quote}
The next part is the view of the Widget. It'll show the quote from the QuoteEntry structure.
struct WidgetEntryView: View {var entry: QuoteEntryvar body: some View {VStack(alignment: .leading, spacing: 5) {Text(entry.quote.value ?? "").italic().font(.caption)Text("- Donald Trump").foregroundColor(.secondary).font(.footnote)}.padding()}}
The third part is the Content/Timeline Provider, which decides what and when to show.
struct Provider: TimelineProvider {// Our controller classvar loader = QuoteController()// the snapshot view shown in the widget library. It'll be constantfunc snapshot(with context: Context,completion: @escaping (QuoteEntry) -> ()) {let entry = QuoteEntry(date: Date(), quote: Quote(value: "President of the US of A"))completion(entry)}// The timeline for the widgetfunc timeline(with context: Context,completion: @escaping (Timeline<QuoteEntry>) -> ()) {//time pointslet components = DateComponents(minute: 10)let futureDate = Calendar.current.date(byAdding: components, to: Date())!//load a quoteloader.getQuote { (quote) inlet entry = QuoteEntry(date: Date(), quote: quote)//reload this after 10 minslet timeline = Timeline(entries: [entry], policy: .after(futureDate))completion(timeline)}}}
And finally, the actual widget
@mainstruct QuoteWidget: Widget {var body: some WidgetConfiguration {StaticConfiguration(kind: "QuoteWidget",provider: Provider(),placeholder: Text("Cool Stuff by Dolan Trum"),content: { entry inWidgetEntryView(entry: entry)}).configurationDisplayName("Quote Widget").description("Shows the dumbest stuff said by Donald Trump")}}
Note that this uses the new @main start point in SwiftUI, which determines the starting point of the application.
With this, you will have a small widget showing dum dum quotes from Donald Trump. It's very fascinating to work with new stuff, really ✨.
Find the complete source code here. For more in-depth stuff, I recommend John Sundell's WWDCbySundell.