Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/104.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在SwiftUI中检测文本字段的实时更改?_Ios_Textfield_Swiftui - Fatal编程技术网

Ios 如何在SwiftUI中检测文本字段的实时更改?

Ios 如何在SwiftUI中检测文本字段的实时更改?,ios,textfield,swiftui,Ios,Textfield,Swiftui,我有一个简单的文本字段,它绑定到状态“location”,如下所示 TextField("Search Location", text: $location) 每次此字段更改时,我都要调用一个函数,如下所示: TextField("Search Location", text: $location) { self.autocomplete(location) } 然而,这不起作用。我知道有回调,onEditingChanged-但是这似乎只有在聚焦字段时才会触发 如何在每次更新字段时调

我有一个简单的文本字段,它绑定到状态“location”,如下所示

TextField("Search Location", text: $location)
每次此字段更改时,我都要调用一个函数,如下所示:

TextField("Search Location", text: $location) {
   self.autocomplete(location)
}
然而,这不起作用。我知道有回调,onEditingChanged-但是这似乎只有在聚焦字段时才会触发


如何在每次更新字段时调用此函数?

您可以使用自定义闭包创建绑定,如下所示:

TextField("Search Location", text: $location) {
   self.autocomplete(location)
}
struct ContentView:View{
@状态变量位置:String=“”
var body:一些观点{
let binding=binding(获取:{
自我定位
},集:{
self.location=$0
//在这里你想干什么就干什么
})
返回VStack{
文本(“当前位置:\(位置)”)
TextField(“搜索位置”,文本:绑定)
}
}
}

如果需要使用
视图模型,另一种解决方案可以是:

import SwiftUI
import Combine

class ViewModel: ObservableObject {
    @Published var location = "" {
        didSet {
            print("set")
            //do whatever you want
        }
    }
}

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()

    var body: some View {
        TextField("Search Location", text: $viewModel.location)
    }
}

我发现最有用的是TextField有一个名为onEditingChanged的属性,该属性在编辑开始和编辑完成时调用

               TextField("Enter song title", text: self.$userData.songs[self.songIndex].name, onEditingChanged: { (changed) in
               if changed {
                   print("text edit has begun")
               } else {
                   print("committed the change")
                   saveSongs(self.userData.songs)
               }

           }).textFieldStyle(RoundedBorderTextFieldStyle())
               .font(.largeTitle)
迅捷2.0 在iOS 14、macOS 11或任何其他包含SwiftUI 2.0的操作系统中,有一个名为
.onChange
的新修饰符,用于检测给定
状态的任何更改:

struct ContentView: View {
    @State var location: String = ""

    var body: some View {
        TextField("Your Location", text: $location)
            .onChange(of: location) {
                print($0) // You can do anything due to the change here.
                // self.autocomplete($0) // like this
            }
    }
}
迅捷1.0 对于较旧的iOS和其他SwiftUI 1.0平台,您可以使用onReceive

.onReceive(location.publisher) { 
    print($0)
}
import Combine
import SwiftUI

struct ContentView: View {
    @State var location: String = ""

    var body: some View {
        TextField("Search Location", text: $location)
            .onReceive(Just(location)) { location in
                // print(location)
            }
    }
}
请注意它返回的是更改,而不是整个值。如果您需要与
onChange
相同的行为,可以使用组合并遵循@pawello2222提供的答案。

SwiftUI 1和2 在接收时使用
onReceive

.onReceive(location.publisher) { 
    print($0)
}
import Combine
import SwiftUI

struct ContentView: View {
    @State var location: String = ""

    var body: some View {
        TextField("Search Location", text: $location)
            .onReceive(Just(location)) { location in
                // print(location)
            }
    }
}

虽然其他答案可能有用,但这一个对我有用,因为我需要倾听文本的变化并对其作出反应

第一步创建一个扩展函数

extension Binding {
    func onChange(_ handler: @escaping (Value) -> Void) -> Binding<Value> {
        Binding(
            get: { self.wrappedValue },
            set: { newValue in
                self.wrappedValue = newValue
                handler(newValue)
            }
        )
    }
}

来源:

Hi@superpuccio,如果要使用ViewModel,可以将代码放在didSet{…}中。无需:可取消/接收;;-)这是一个比公认的IMO更清晰的答案。如果您的body var中有多个绑定,它可能会很快变得混乱。它是否需要是一个可观察对象?@Zorayr是的,否则您将无法获得已发布属性的更新。@FrankCheng在视图重新绘制时不会重新创建可观察对象(即再次请求视图主体时)。当视图位于另一个视图主体内且该视图被重绘时,将重新创建视图主体(即再次请求其主体,在该主体中有包含观察对象的子视图,因此将使用其所有属性(包括观察对象)完全重新创建视图)。如果是这种情况,您应该从外部将观察到的对象注入视图中,或者,如果您可以使用iOS 14,请尝试新的StateObject,它正好用于此。Hi kontiki!只是关于您有趣的答案的一个问题(我从未想过以这种方式使用
绑定
):我想知道为什么如果我在
位置
变量上附加一个didSet,那么didSet根本不会被调用。类似于
@State-var-location:String=”“{didSet{//do Something}
我不明白为什么函数没有被调用。谢谢。location上的didSet从不触发,因为您通过绑定更改的是location.wrappedValue,而不是location。是的,这完全有道理。我弄糊涂了。像往常一样:谢谢:)从SwiftUI中的textFieldDidChange()进行调整的伟大解决方案谢谢!我得到一个函数,它声明了一个不透明的返回类型,但是在它的主体中没有返回语句,从中可以推断出一个基础类型。文本更改时,不会调用onEditingChanged,而是在编辑开始或停止时调用onEditingChanged。单击文本字段内部时调用一次,然后单击“完成”时调用下一次。它确实是这样工作的。如果您正在寻找每次击键时调用的内容,那么这不是它。但这是一个很好的解决方案,具体问题是文本何时更改,而不是编辑何时开始/停止。这个问题的答案不正确。哦,你是对的。有用,但不是他们要求的。这实际上是一个非常好,干净和聪明的方式做这件事!这真的有效吗?您不需要将(位置)存储在某个位置以订阅并接收其值吗?@Xaxxus它工作得非常好。“我鼓励你自己尝试一下。”pawello2222我最终需要为我的用例做一些不同的事情。我有一个文本字段,下面有一个错误标签。错误标签只需要显示是否存在错误。触发错误标签的验证需要在击键(300毫秒)时运行。所以我最后做的是为我的文本字段创建一个可观察的对象视图模型。使用text和errorText published属性和I.onRecieve(viewModel.text.debounce(300,runloop.main))的$text变量触发我的验证,并使用.debounce进行验证,效果非常好。