Eric
Eric

Reputation: 793

SwiftUI: How to update textfield with live changes

In my content view i have function that detects whenever a user copies a website address

ContentView

@State private var detectedurl = ""

   .................
   .onAppear {
            urlclipboardwatcher()
          }

       func urlclipboardwatcher() {
                let pasteboard = NSPasteboard.general
                
                var changeCount = NSPasteboard.general.changeCount             
                Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true) { _ in
                    
                    if let copiedString = pasteboard.string(forType: .string)  {
                            ...............
                            if copiedString.starts(with: "https://") {
                                detectedurl = copiedString
                                
                            }    
                    }
                }
                
            }

I want to pass this value to the textfield in my NewBookmark View. How do i update the textfield with any changes that happen with the pasteboard?

struct NewBookmark: View {


@Binding var detectedurl: String
@ObservedObject private var vm: AddNewBookmarkViewModel



init(vm: AddNewBookmarkViewModel, detectedurl: Binding<String>) {
    self.vm = vm
    self._detectedurl = detectedurl

}

 TextField("Enter a URL", text: $vm.url)
   // i want the detected url to automatically populate this textfield 



Button("Save") {
    vm.save()
}.disabled(vm.url.isEmpty)

AddBookMarkViewModel

class AddNewBookmarkViewModel: ObservableObject {
    
    @Published var url: String = ""
     .............

    func save() {
        
        do {
        let myBM = MyBookmark(context: context)
        myBM.url = url
        try myBM.save()
        } catch {
            print(error)
        }

    }
    
}

Upvotes: 1

Views: 110

Answers (1)

Truelies42
Truelies42

Reputation: 143

Tbh, I am not really sure how the code which you posted works. But I did something similar in the past. Maybe it helps. What I basically did is, one viewModel with two views. Both views hold on to the viewModel PasteboardViewModel. PasteboardViewModel is a StateObject which is passed on two the second view via. environmentObject. And url variable in the viewModel is bound to the PasteboardView. So every time this Publisher changes the TextField does it too.

struct ContentView: View {
    @StateObject var viewModel: PasteboardViewModel = .init()
    
    var body: some View {
        VStack {
            .....
            
            PasteboardView()
                .environmentObject(viewModel)
        }
        .onAppear {
            viewModel.watchPasteboard()
        }
        .padding()
    }
}
struct PasteboardView: View {
    @EnvironmentObject var viewModel: PasteboardViewModel
    
    var body: some View {
        TextField(text: $viewModel.url) {
            Text("Test")
        }
    }
}
class PasteboardViewModel: ObservableObject {
    @Published var url: String = ""
    
    func watchPasteboard() {
        let pasteboard = UIPasteboard.general
        var changeCount = UIPasteboard.general.changeCount
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
            if let copiedString = pasteboard.string {
                if pasteboard.changeCount != changeCount {
                    self.url = copiedString
                    changeCount = pasteboard.changeCount
                }
            }
        }
    }
}

Upvotes: 3

Related Questions