我有一个文本字段,用户可以在其中手动输入位置字符串.这与我所观察到的物体AppState绑定,我重新标记为(app),它有一个称为@Published vardestination.这工作得很好,我可以像这样在文本字段中绑定手动输入的文本:

TextField("Destination", text: $app.destination)

我已经开始try 实现一个Collection 夹系统,用户可以保存和更改多达4个目的地,以便快速输入,无需重新输入(一次只能在文本字段中输入1个).

当用户按下他们的最爱之一时,最爱就会出现在文本字段中,他们可以通过输入新的最爱并保存它来更改它,或者按下新的最爱来替换文本字段中的最爱.用户还必须可以 Select 根本不输入最喜欢的内容,并且还可以随机输入一个.

到目前为止,我的这个部分运行得相当好,并且对它的功能感到满意.

我这里的问题是,我不知道如何将文本字段中的内容绑定到我的ObservedObject app.destination.经过一些故障处理后,我发现只有手动输入的文本才会存储在app.destination中.文本字段中出现最喜欢的内容不会绑定.

我try 过.onChange().onTapGesture().focused()的变体来运行if/else块,该块将简单地将文本字段中的文本分配给app.destination,但它仍然有缺陷,并且您无法保存新的最爱.

我正在绕圈子试图弄清楚这个问题,并非常感谢一些帮助.

我有一个最低可复制的示例供您复制和粘贴.谢谢你

主视图

struct ContentView: View {
    @StateObject private var favoritesViewModel = FavoritesViewModel()
    @ObservedObject var app = AppState()
    @State private var newLocation = ""
    @State private var selectedLocationIndex = 0
    @State private var userSelectedFavourite: String = ""
    @State private var favouritePressed: Bool = false
    @FocusState private var isFocused: Bool
    
    var body: some View {
        VStack {
            HStack {
                //.........THIS IS THE ISSUE TEXTFIELD
                TextField("Destination", text: (favouritePressed && !isFocused) ? $favoritesViewModel.favoriteLocations[selectedLocationIndex] : $newLocation)
                //.....................................
                .focused($isFocused)
                .contentShape(.rect)
                .textInputAutocapitalization(.characters)
                .disableAutocorrection(true)
                .padding()
                .frame(width: 280, height: 60)
                .overlay(
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(Color.gray, lineWidth: 2)
                )
                
                Button("Save") {
                    saveLocation(locationIndex: selectedLocationIndex)
                }
            }
            
            Picker("Favorite Locations", selection: $selectedLocationIndex) {
                ForEach(favoritesViewModel.favoriteLocations.indices, id: \.self) { index in
                    Text(favoritesViewModel.favoriteLocations[index])
                        .tag(index)
                }
            }
            .onChange(of: selectedLocationIndex) {
                favouritePressed = true
                isFocused = false
                        }
            .pickerStyle(.palette)

            Spacer()
        }
        
        .navigationTitle("Favorite Locations")
    }
    
    
    func saveLocation(locationIndex: Int) {
        print("Saving...")
        if !newLocation.isEmpty {
            favoritesViewModel.addFavoriteLocation(newLocation, locationIndex: locationIndex)
            newLocation = ""
        }
    }
}

这个只存储最喜欢的:

class FavoritesViewModel: ObservableObject {
    // Key for UserDefaults
    let favoritesKey = "favoriteLocations"

    // UserDefaults instance
    var defaults: UserDefaults {
        UserDefaults.standard
    }

    // Published property to manage favorite locations
    @Published var favoriteLocations: [String] = []

    // Initialize with default values
    init() {
        self.favoriteLocations = loadFavorites()
    }

    // Load favorite locations from UserDefaults
    func loadFavorites() -> [String] {
        return defaults.stringArray(forKey: favoritesKey) ?? []
    }

    // Save favorite locations to UserDefaults
    func saveFavorites() {
        defaults.set(favoriteLocations, forKey: favoritesKey)
    }

    // Add a new favorite location
    func addFavoriteLocation(_ location: String, locationIndex: Int) {
        // Check if location is already in favorites and limit to 4 locations
        if !favoriteLocations.contains(location) {
            if favoriteLocations.count < 4 {
                favoriteLocations.insert(location, at: locationIndex)
            } else {
                favoriteLocations.remove(at: locationIndex)
                favoriteLocations.insert(location, at: locationIndex)
            }
            saveFavorites() // Save after adding or updating favorites
        }
    }
}

仅观察类:

class AppState: ObservableObject {
    
    // THIS IS THE VARIABLE IM TRYING TO SAVE TEXT TO
    @Published var destination: String = ""
    
}

推荐答案

您仍然应该使用$app.destination作为文本字段的绑定.记住,single source of truth.

当用户在 Select 器中 Select 某个内容时,只需将app.destination设置为所选位置即可.

您只需要这些州:

@StateObject private var favoritesViewModel = FavoritesViewModel()
@StateObject private var app = AppState()
@State private var selectedLocationIndex: Int?
@FocusState private var isFocused: Bool

我认为selectedLocationIndex是可选的更有意义,以代表不 Select 任何东西的状态.

代码的其余部分很简单.请注意app.destination如何设置在.onChange(of: selectedLocationIndex)中.

var body: some View {
    VStack {
        HStack {
            TextField("Destination", text: $app.destination)
                .focused($isFocused)
                .contentShape(.rect)
                .textInputAutocapitalization(.characters)
                .disableAutocorrection(true)
                .padding()
                .frame(width: 280, height: 60)
                .overlay(
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(Color.gray, lineWidth: 2)
                )
            
            Button("Save") {
                saveLocation(locationIndex: selectedLocationIndex ?? 0)
            }
        }
        
        Picker("Favorite Locations", selection: $selectedLocationIndex) {
            ForEach(favoritesViewModel.favoriteLocations.indices, id: \.self) { index in
                Text(favoritesViewModel.favoriteLocations[index]).tag(Optional.some(index))
            }
        }
        .onChange(of: selectedLocationIndex) { _, newValue in
            if let newValue {
                isFocused = false
                app.destination = favoritesViewModel.favoriteLocations[newValue]
            }
        }
        .pickerStyle(.palette)

        Spacer()
    }
}


func saveLocation(locationIndex: Int) {
    print("Saving...")
    favoritesViewModel.addFavoriteLocation(app.destination, locationIndex: locationIndex)
    app.destination = ""
}

Ios相关问答推荐

如何以最可靠的方式删除文本视图中的额外页边距?

与iPadOS中带有扣件的模式相似的组件是什么?

如何访问iOS模拟器中的zoom 设置?(在搜索中列出,但不可见)

ios PWA从外部链接返回后降低了innerheight

为什么EKEventStore().questFullAccessToEvents()可以与模拟器一起使用,而不能与真实设备一起使用?

withTaskGroup不适用于CLGeocoder

当 Swift 枚举具有 any existential 作为其关联值之一时,我如何使它符合 `Equatable`?

无法从 Xcode 获取模拟器列表.请打开 Xcode 并try 直接从那里运行项目以解决剩余问题

使用 JSONDecoder 解码的对象的打印输出有问题

SwiftUI 中的描边图像边框

在视图控制器中实例化视图控制器是否可能/智能?

Text() 正在添加额外的前导尾随填充 SwiftUI

类型任何视图不能符合具有泛型的协议上的视图

SensorKit - 获取数据不调用结果委托函数

如何告诉 SwiftUI 视图绑定到嵌套的 ObservableObjects

如何在 Swift 中使用包含多个值的查询参数构建一个 URL?

Xcode 11 向后兼容性:UIWindowScene 仅在 iOS 13 或更高版本中可用

在滚动视图中使用动态大小的控制器调整容器视图的大小

如何动态计算 UILabel 高度?

SRCROOT 和 PROJECT_DIR 有什么区别?