Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.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
输入字符时,SwiftUI中的TextField会失去焦点_Swift_Swift4.2_Swiftui - Fatal编程技术网

输入字符时,SwiftUI中的TextField会失去焦点

输入字符时,SwiftUI中的TextField会失去焦点,swift,swift4.2,swiftui,Swift,Swift4.2,Swiftui,当我在文本字段(在ExerciseSetView中)中输入字符时,我有一个问题,我必须重新单击文本框使其成为文本框,以便输入另一个字符。如果我从Textfield中删除绑定,我可以流畅地输入文本 我认为这与我的presenter类和更新集函数重新创建集合实例有关,因为我必须将数组中的某些值替换为两级 // // ContentView.swift // test // // import SwiftUI import Combine import CoreData class Worko

当我在文本字段(在ExerciseSetView中)中输入字符时,我有一个问题,我必须重新单击文本框使其成为文本框,以便输入另一个字符。如果我从Textfield中删除绑定,我可以流畅地输入文本

我认为这与我的presenter类和更新集函数重新创建集合实例有关,因为我必须将数组中的某些值替换为两级

//
//  ContentView.swift
//  test
//
//

import SwiftUI
import Combine
import CoreData

class WorkoutExerciseSetVM: Hashable, ObservableObject {
    @Published public var id: Int
    @Published public var reps: String
    @Published public var weight: String

    init(id: Int, reps: String, weight: String) {
        self.id = id
        self.reps = reps
        self.weight = weight
    }

    static func ==(lhs: WorkoutExerciseSetVM, rhs: WorkoutExerciseSetVM) -> Bool {
        return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
    }

    func hash(into hasher: inout Hasher) { return hasher.combine(ObjectIdentifier(self)) }
}

class WorkoutExerciseVM: Hashable, ObservableObject {
    @Published public var id: UUID
    @Published public var name: String
    @Published public var sets: [WorkoutExerciseSetVM]

    init(id: UUID, name: String, sets: [WorkoutExerciseSetVM]) {
        self.id = id
        self.name = name
        self.sets = sets
    }

    static func ==(lhs: WorkoutExerciseVM, rhs: WorkoutExerciseVM) -> Bool {
        return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
    }

    func hash(into hasher: inout Hasher) { return hasher.combine(ObjectIdentifier(self)) }
}

class WorkoutVM: Hashable, ObservableObject {
    @Published public var id = UUID()
    @Published public var name: String
    @Published public var exercises: [WorkoutExerciseVM]
    @Published public var started: Date? = Date()
    @Published public var completed: Date? = Date()

    init(id: UUID, name: String, exercises: [WorkoutExerciseVM], started: Date?, completed: Date?) {
        self.id = id
        self.name = name
        self.exercises = exercises
        self.started = started
        self.completed = completed
    }

    static func ==(lhs: WorkoutVM, rhs: WorkoutVM) -> Bool {
        return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
    }

    func hash(into hasher: inout Hasher) { return hasher.combine(ObjectIdentifier(self)) }
}

class WorkoutPresenter: ObservableObject {
    @Published public var id: UUID
    @Published public var exercises: [WorkoutExerciseVM]
    @Published public var name: String
    @Published public var started: Date?
    @Published public var completed: Date?

    init(routine: WorkoutVM) {

        self.id = UUID()
        self.name = routine.name
        self.started = Date()
        self.completed = nil
        self.exercises = routine.exercises.map{ exercise in
            return WorkoutExerciseVM(
                id: UUID(),
                name: exercise.name,
                sets: [
                    WorkoutExerciseSetVM(id: 1, reps: "0", weight: "0")
                ]
            )
        }
    }

    func removeExercise(id: UUID) {
        let exerciseId = id.uuidString;
        self.exercises = self.exercises.filter{$0.id.uuidString != exerciseId}
    }

    func addSet(id: UUID) {
        let exerciseId = id.uuidString;

        self.exercises = self.exercises.map {
            if ($0.id.uuidString == exerciseId) {
                if ($0.sets.count == 0) {
                    $0.sets.append(WorkoutExerciseSetVM(id: 1, reps: "0", weight: "0"))
                }

                if let lastSet = $0.sets.last {
                    $0.sets.append(WorkoutExerciseSetVM(id: lastSet.id + 1, reps: lastSet.reps, weight: lastSet.weight))
                }
            }

            return $0
        }
    }

    func updateSet(id: UUID, set: WorkoutExerciseSetVM) {
        let exerciseId = id.uuidString

        self.exercises = self.exercises.map{
            if $0.id.uuidString == exerciseId {
                $0.sets = $0.sets.map{(oldExerciseSet) -> WorkoutExerciseSetVM in
                    if oldExerciseSet.id == set.id {
                        return set
                    }

                    return oldExerciseSet
                }

                return $0
            }

            return $0;
        }
    }

    func removeSet(id: UUID) {
        let exerciseId = id.uuidString;

        self.exercises = self.exercises.map{(exercise) -> WorkoutExerciseVM in
            if exercise.id.uuidString == exerciseId {
                let newExercise = exercise

                if newExercise.sets.count > 1 {
                    newExercise.sets.removeLast()
                }

                return newExercise
            }

            return exercise;
        }
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            WorkoutView(presenter: WorkoutPresenter(routine: WorkoutVM(id: UUID(), name: "Test", exercises: [WorkoutExerciseVM(id: UUID(), name: "Exercise", sets: [WorkoutExerciseSetVM(id: 1, reps: "0", weight: "0")])], started: nil, completed: nil)))
        }

    }
}

struct WorkoutView: View {
    @ObservedObject var presenter: WorkoutPresenter
    var body: some View {
        return GeometryReader { geo in
            ZStack {
                VStack {
                    ScrollView {
                        ForEach(self.presenter.exercises, id: \.self) { exercise in
                            ExerciseView(presenter: self.presenter, exercise: exercise)
                        }
                    }
                }
            }
        }
    }
}

struct ExerciseView: View {
    @ObservedObject var presenter: WorkoutPresenter
    var exercise: WorkoutExerciseVM
    var body: some View {
        VStack {
            VStack(alignment: .leading) {
                VStack {
                    VStack {
                        ForEach(exercise.sets, id: \.self) { exerciseSet in
                            ExerciseSetView(
                                set: exerciseSet,
                                onUpdate: { newExerciseSet in
                                    self.presenter.updateSet(id: self.exercise.id, set: newExerciseSet)
                                }
                            )
                        }
                    }
                }
            }
            HStack {
                Button(action: {
                    self.presenter.addSet(id: self.exercise.id)
                }) {
                    HStack {
                        Image(systemName: "plus")
                        Text("Add Set")
                    }

                }
                Button(action: {
                    self.presenter.removeSet(id: self.exercise.id)
                }) {
                    HStack {
                        Image(systemName: "minus")
                        Text("Remove Set")
                    }

                }
            }

        }

    }
}

struct ExerciseSetView: View {
    var set: WorkoutExerciseSetVM
    var onUpdate: (_ set: WorkoutExerciseSetVM) -> Void
    var body: some View {
        let repBinding = Binding(
            get: {
                String(self.set.reps)
            },
            set: {
                if ($0 as String?) != nil {
                    self.onUpdate(WorkoutExerciseSetVM(id: self.set.id, reps: $0 , weight: self.set.weight))
                }
            }
        )

        let weightBinding = Binding(
            get: {
                String(self.set.weight)
            },
            set: {
                if ($0 as String?) != nil {
                    self.onUpdate(WorkoutExerciseSetVM(id: self.set.id, reps: self.set.reps, weight: $0 ))
                }
            }
        )

        return HStack {
            Spacer()
// textfield that isn't working
            TextField("", text: repBinding)
            Spacer()
// textfield that isn't working
            TextField("", text: weightBinding)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

您的代码有一些基本错误。在使用此代码投入生产之前,请研究
可观察对象
已发布的
值。否则,以后将很难处理此代码

我已经更新了你的观点,这似乎有效。您没有使用应使用的
observateObject
。只需传递
observeObjects
s,让它们为您执行绑定,而不是设置自定义绑定

struct ExerciseView: View {

    @ObservedObject var presenter: WorkoutPresenter
    @ObservedObject var exercise: WorkoutExerciseVM

    var body: some View {
        VStack {
            VStack(alignment: .leading) {
                ForEach(exercise.sets, id: \.self) { exerciseSet in
                    ExerciseSetView(set: exerciseSet)
                }
            }
            HStack {
                Button(action: {
                    self.presenter.addSet(id: self.exercise.id)
                }) {
                    HStack {
                        Image(systemName: "plus")
                        Text("Add Set")
                    }
                }
                Button(action: {
                    self.presenter.removeSet(id: self.exercise.id)
                }) {
                    HStack {
                        Image(systemName: "minus")
                        Text("Remove Set")
                    }
                }
            }
        }
    }
}

struct ExerciseSetView: View {

    @ObservedObject var set: WorkoutExerciseSetVM

    var body: some View {
        HStack {
            Spacer()
            TextField("", text: $set.reps)
            Spacer()
            TextField("", text: $set.weight)
        }
    }
}

让我知道这是否对您有效。

由于缺少许多依赖项,代码不可测试,您能提供更集中的演示吗?@Asperi我已经用一个工作示例更新了代码示例。这非常有效,非常感谢您,所以我将接受答案,我将进一步了解ObserveObject,你有什么有用的资源吗?@mintuz很好,它很有效!不幸的是,我没有任何具体的资料来源,但我找到了这一条,它简要而准确地总结了这一点: