SwiftUI TextField (MacOS) 的奇怪行为

Posted

技术标签:

【中文标题】SwiftUI TextField (MacOS) 的奇怪行为【英文标题】:Strange behavior of SwiftUI TextField (MacOS) 【发布时间】:2019-10-05 18:17:44 【问题描述】:

我在 MacOS 应用程序(XCode 11.0 稳定版,CoreData)上使用 SwiftUI 时遇到了 TextFields 的奇怪行为,这可能是由于我对 SwiftUI 数据流的一些误解。

实施

请考虑这个基本的主/详细视图设置:

型号:Account 容器:ContentView 主人:AccountListView 详情:AccountEditView
final class Account: NSManagedObject, Identifiable 
            @NSManaged var id: UUID
            @NSManaged var name: String
        

struct ContentView: View 
    var body: some View 
        NavigationView 
            AccountListView()
                .listStyle(SidebarListStyle())
        
        .navigationViewStyle(DoubleColumnNavigationViewStyle())
        .frame(minWidth: 300, idealWidth: nil, maxWidth: nil, minHeight: 300, idealHeight: nil, maxHeight: nil, alignment: .topLeading)
    


struct AccountListView: View 

    @FetchRequest(entity: Account.entity(), sortDescriptors: [])
    var accounts: FetchedResults<Account>

    var body: some View 
        VStack 
            List(accounts)  account in
                NavigationLink (destination: AccountEditView(account: account)) 
                    Text(account.name)
                
            
        
    


struct AccountEditView: View 

    @ObservedObject var account: Account

    var body: some View 
        VStack 
            TextField("Account Name", text: $account.name)
            Spacer()
        
    

问题

视图已正确填充。在列表视图中选择一个帐户会正确更新详细视图中的文本字段。

但是,一旦我编辑了文本字段值,事情就变得很奇怪:

新更新详细视图时,文本字段在输入第一个字符后失去焦点。列表视图中的帐户名称已正确更新(显示输入的单个字符) 当我再次输入文本时,我可以输入更多字符而不会失去焦点(同样,列表视图中的帐户名称已更新) 当我按下回车键时,TextField 的值恢复为旧值,而列表视图的值保持在更新后的值。 在不同的帐户条目之间来回切换时,详细视图会显示正确的值。因此模型对象已正确更新。

我的问题:

    为什么第一次输入单个字符时TextField失去焦点 为什么在提交更改时 TextField 会恢复其先前的值(而不是模型值)

抱歉问了这么长的问题...

【问题讨论】:

你有没有深入了解这个问题?看到同样的东西。 这里有同样的问题。你找到解决办法了吗? 也许这个问题需要更多的支持? 我并没有真正进一步调查它,据我所知,我没有找到解决方案。回过头来,我认为原因是我这边的方法有缺陷。我真的很惊讶其他人也遇到了这个问题...... 我也遇到了同样的问题,不过我会提交一个雷达,因为其他人似乎也有类似的问题,但没有解决方案 【参考方案1】:

coredata 属性是一种不同的选项。所以我们需要在 Model 类中定义 getter 和 setter 来转换它们的行为。

如果您的实体的代码生成不是手动/无,请在 contentview 中添加以下代码

extension Account 
    var wrappedName: String 
        get  name ?? "Unknown"
        set  name = newValue 
    

然后将所有account.name 替换为account.wrappedName

附注这是在 MacOS 10.5 上的 XCode 11.4 中测试和工作的

【讨论】:

以上是关于SwiftUI TextField (MacOS) 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - TextField 在 macOS 上的 List 中被禁用(不可编辑)

SwiftUI for MacOS 中的多行 TextField/TextEditor 表单

SwiftUI macOS 在 TextField 处于活动状态时使用箭头键滚动列表

如何在 MacOS 的 SwiftUI 中向 TextEditor 添加焦点环

SwiftUI macOS currencyFormatter 不更新绑定变量

如何在 SwiftUI macOS 中创建第一响应者