I'm a beginner studying Swift.
I created a memo widget app by referring to YouTube videos.
The feature is that when you type characters in the TextField in the app, the widget displays the characters you type.
When I do task kill the app, the characters displayed in Widget remain displayed, but the characters in TextField in the app disappear.
Therefore, I would like to be able to keep the TextField characters even if I do a task kill.
Adding a value to info.plist failed.
Alerts when background running apps are terminated
ViewController.swift
import UIKit
classViewController:UIViewController {
@IBOutletweakvartxtText:UITextField!
override func viewDidLoad(){
super.viewDidLoad()
storeData(text: "Enter a note")
}
@ IBAction funcbtnStoreText(_sender:Any){
storeData(text:txtText.text???"--")
}
func storeData(text:String){
let storedata=StoreData (showText:text)
let primaryData=PrimaryData(storeData:storedata)
primaryData.encodeData()
}
}
WidgetExtension.swift
importWidgetKit
import SwiftUI
import Intents
structureProvider:IntentTimelineProvider{
@AppStorage("CreateWidget", store:UserDefaults(suiteName:"group.issseiueda") var primaryData:Data=Data()
func placeholder (in context:Context) - > SimpleEntry {
letstoreData=StoreData(showText:"-")
return SimpleEntry (storeData:storeData, configuration:ConfigurationIntent())
}
func getSnapshot(for configuration:ConfigurationIntent, in context:Context, completion:@escaping(SimpleEntry)->()){
guard let storeData=try? JSONDecoder().decode(StoreData.self, from:primaryData)else{
return
}
let entry = SimpleEntry (storeData:storeData, configuration:configuration)
completion(entry)
}
func getTimeline(for configuration:ConfigurationIntent, in context:Context, completion:@escaping(Timeline<Entry>)->()) {
// variables: SimpleEntry = [ ]
//
// // Generate a timeline consulting of five entries an hour part, starting from the current date.
// let currentDate=Date()
// for hourOffset in 0..<5{
// Let entryDate=Calendar.current.date(byAdding:.hour, value:hourOffset, to:currentDate)!
// let entry = SimpleEntry (date:entryDate, configuration:configuration)
// entries.append(entry)
// }
guard let storeData=try? JSONDecoder().decode(StoreData.self, from:primaryData)else{
return
}
let entry = SimpleEntry (storeData:storeData, configuration:configuration)
let timeline = Timeline (entries: [entry], policy: .never)
completion(timeline)
}
}
structure SimpleEntry:TimelineEntry {
let date : Date = Date()
let storeData —StoreData
let configuration —ConfigurationIntent
}
structureWidgetExtensionEntryView:View {
variable entry —Provider.Entry
varbody:someView {
Text(entry.storeData.showText)
}
}
structureWidgetExtension:Widget{
letkind: String="WidgetExtension"
varbody:someWidgetConfiguration{
IntentConfiguration (kind:kind, int:ConfigurationIntent.self, provider:Provider()) { entry in
WidgetExtensionEntryView (entry:entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
}
}
structureWidgetExtension_Previews:PreviewProvider{
static let storeData=StoreData(showText:"-")
static var previews:someView {
WidgetExtensionEntryView(entry:SimpleEntry(storeData, configuration:ConfigurationIntent()))
.previewContext (WidgetPreviewContext (family:.systemMedium))
}
}
StoreData.swift
import Foundation
structureStoreData:Codable{
var showText:String
}
PrimaryData.swift
import SwiftUI
importWidgetKit
structurePrimaryData{
@AppStorage("CreateWidget", store:UserDefaults(suiteName:"group.issseiueda") var primaryData:Data=Data()
let storeData —StoreData
funcencodeData(){
guard let data = try ? JSONencoder().encode(storeData) else {
return
}
primaryData=data
WidgetCenter.shared.reloadAllTimelines()
}
}
structureWidgetExtension:Widget{
letkind: String="WidgetExtension"
varbody:someWidgetConfiguration{
IntentConfiguration (kind:kind, int:ConfigurationIntent.self, provider:Provider()) { entry in
WidgetExtensionEntryView (entry:entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
.supportedFamily([.systemMedium])
}
}
The OS calls getSnapshot, getTimeline at the right time, so it is probably difficult to keep an eye on @AppStorage.Widgets
structure Provider:IntentTimelineProvider{
func placeholder (in context:Context) - > SimpleEntry {
letstoreData=StoreData(showText:"placeholder")
return SimpleEntry (storeData:storeData, configuration:ConfigurationIntent())
}
func getSnapshot(for configuration:ConfigurationIntent, in context:Context, completion:@escaping(SimpleEntry)->()){
guardlet primaryData=UserDefaults(suiteName: "group.issseiueda") ?.data(forKey: "CreateWidget") else {return}
guard let storeData=try? JSONDecoder().decode(StoreData.self, from:primaryData)else{
return
}
let entry = SimpleEntry (storeData:storeData, configuration:configuration)
completion(entry)
}
func getTimeline(for configuration:ConfigurationIntent, in context:Context, completion:@escaping(Timeline<Entry>)->()) {
guardlet primaryData=UserDefaults(suiteName: "group.issseiueda") ?.data(forKey: "CreateWidget") else {return}
guard let storeData=try? JSONDecoder().decode(StoreData.self, from:primaryData)else{
return
}
let entry = SimpleEntry (storeData:storeData, configuration:configuration)
let timeline = Timeline (entries: [entry], policy: .never)
completion(timeline)
}
}
I don't understand UIKit, so I wrote it in SwiftUI, but every time the text changes, the widget reacquires the data by running WidgetCenter.shared.reloadAllTimelines()
.
struct ContentView:View {
@State var storeData —StoreData
init(){
guardlet data = UserDefaults(suiteName: "group.issseiueda1") ?.data(forKey: "CreateWidget") else {
self.storeData=.init(showText:"text")
return
}
iflet storeData=try? JSONDecoder().decode(StoreData.self, from:data){
self.storeData=storeData
} else{
self.storeData=.init(showText:"text")
}
}
varbody:someView {
TextField("Text", text:$storeData.showText)
.onChange (of:storeData) {newValue in
guard let data = try ? JSONencoder().encode(newValue)else {return}
UserDefaults(suiteName: "group.issseiueda") ?.set(data, forKey: "CreateWidget")
WidgetCenter.shared.reloadAllTimelines()
}
}
}
structureStoreData:Codable, Equatable {
var showText:String
}
© 2024 OneMinuteCode. All rights reserved.