I have ContentView.swift
struct ContentView: View {
@State var seconds: String = "60"
var body: some View {
TextField("60", text: $seconds)
}
func getSeconds() -> String {
return $seconds.wrappedValue;
}
}
And AppDelegate.swift
class AppDelegate: NSObject, NSApplicationDelegate {
var contentView = ContentView()
...
func launchTimer() {
print(contentView.getSeconds())
let timer = DispatchTimeInterval.seconds(Int(contentView.getSeconds()) ?? 0)
DispatchQueue.main.asyncAfter(deadline: .now() timer) {
self.launchTimer()
}
}
...
@objc func showPreferenceWindow(_ sender: Any?) {
if(window != nil) {
window.close()
}
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.isReleasedWhenClosed = false
window.contentView = NSHostingView(rootView: contentView)
window.center()
window.makeKeyAndOrderFront(nil)
NSApplication.shared.activate(ignoringOtherApps: true)
}
}
contentView.getSeconds()
always returns 60, even if I modify the value of the TexField
in my content view (by manually typing in the text field).
How does one get the wrapped value/real value of a state variable from the app delegate?
CodePudding user response:
add a variable to appDelegate
var seconds : Int?
then do this in your contentView :
.onChange(of: seconds) { seconds in
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {return}
appDelegate.seconds = seconds
}
CodePudding user response:
Ended up instantiating the ContentView
with the AppDelegate
as a param. I added a seconds
attribute to the AppDelegate
to be modified by the ContentView
.
AppDelegate.swift
import SwiftUI
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var contentView: ContentView?
var seconds = 60
func applicationDidFinishLaunching(_ aNotification: Notification) {
self.contentView = ContentView(self)
launchTimer()
}
func launchTimer() {
let timer = DispatchTimeInterval.seconds(seconds)
print(timer)
DispatchQueue.main.asyncAfter(deadline: .now() timer) {
self.launchTimer()
}
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var seconds: String = "60"
var appDelegate: AppDelegate
init(_ appDelegate: AppDelegate) {
self.appDelegate = appDelegate
}
var body: some View {
TextField("60", text: $seconds, onCommit: {
self.appDelegate.seconds = Int($seconds.wrappedValue) ?? 0
})
}
}
This code hurts my brain and surely there is a better way of doing this