Home > Enterprise >  SwiftUI: How to update textfield with live changes
SwiftUI: How to update textfield with live changes

Time:10-27

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)
        }

    }
    
}

CodePudding user response:

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
                }
            }
        }
    }
}
  • Related