gpt4 book ai didi

swift - 防止 NSTableView 保存新行,直到用户填写值

转载 作者:行者123 更新时间:2023-11-30 10:51:47 25 4
gpt4 key购买 nike

我正在为我的应用程序创建一个首选项窗口,用户可以在其中使用 NSTableView 添加和删除预设.预设定义为:

struct Preset: Codable {
var name: String
var value: Int
}

这些预设应保留到 UserDefaults .我的目标是尽量少写代码,少写的应该是通用代码,所以我的项目使用了 NSUserDefaultsController , NSArrayController和 cocoa 绑定(bind)。 UserDefaults 使用的属性列表中可以看到数组、字符串和整数类型。为了存储这些设置,我决定使用这些而不是不透明的序列化数据类型。

此外,为了方便其余代码访问这些预设,我创建了一个带有属性 presets 的 Settings 单例对象。类型 [Preset]它实现了计算的 getter 和 setter 以从 UserDefaults 中检索它。

我已将 MCVE 上传到 GitHub .它记录 presets 的值每秒的属性(property)来展示我需要帮助的问题——除了这两个问题,我相信一切都很好。

第一个问题是我想在我的 NSTableView 中转到基于 View 的内容模式。 ,但是当我进行此更改并恢复另一个时,对 NSTableView 的条目所做的任何编辑未保存到 UserDefaults .它们在基于单元格的内容模式下运行良好,这是我在 MCVE 中使用的。由于我是 Cocoa/Swift 新手,我非常感谢有关在此项目中需要更改哪些内容以便迁移到基于 View 的内容模式的分步说明,同时保留编辑条目的功能 NSTableView .

编辑 : 看来我在这个问题上是一个人注意:见 this项目,以及 this cocoa 邮件列表中的线程。

然而,第二个问题是最严重的:当我按下 + 时按钮向我的 NSTableView 添加新行,最初“名称”和“值”列是空的,直到用户向其中添加一些文本/值。但是,绑定(bind)将一个新的空行(没有 namevalue 属性)保存到 UserDefaults。 .这可以通过注释掉 printPresets() 中的代码来看到。 .例如,在添加新行之前,这是 plist 的内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>presets</key>
<array>
<dict>
<key>name</key>
<string>First preset</string>
<key>value</key>
<integer>1</integer>
</dict>
<dict>
<key>name</key>
<string>Second preset</string>
<key>value</key>
<integer>2</integer>
</dict>
</array>
</dict>
</plist>

+后,这是 plist 的新内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>presets</key>
<array>
<dict>
<key>name</key>
<string>First preset</string>
<key>value</key>
<integer>1</integer>
</dict>
<dict>
<key>name</key>
<string>Second preset</string>
<key>value</key>
<integer>2</integer>
</dict>
<dict/>
</array>
</dict>
</plist>

注意额外的 <dict/>在第二个预设之后。

如果 getter 在设置处于此状态时运行,并且有一个空行,则 getter 会尝试从 plist 中读取该行,但由于缺少 name 而失败和 value特性。具体来说,我收到以下错误:
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error:
Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "name",
intValue: nil), Swift.DecodingError.Context(codingPath:
[_PlistKey(stringValue: "Index 2", intValue: 2)], debugDescription:
"No value associated with key CodingKeys(stringValue: \"name\",
intValue: nil) (\"name\").", underlyingError: nil))

我不知道如何解决这个问题。我已经尝试了一件事,但没有成功,并想到了另一件事,我可以就如何实现提出一些建议。如果提出其他我没有想到的替代方案,我也将不胜感激。
  • 我尝试设置 sharedUserDefaultsController.appliesImmediatelyfalse ,添加“保存”按钮并将其绑定(bind)到 sharedUserDefaultsControllersave:行动。当我这样做时,我的预设没有加载。另一方面,我可以使用 + 添加新行按钮,而不会立即使应用程序崩溃。只要我在按下“保存”按钮之前向该行添加名称和值,应用程序就不会崩溃。但是,如果我尝试在不填写名称或值字段或两者的情况下进行保存,应用程序仍然会崩溃。所以,不是一个好的解决方案。也许除非正确填写字段,否则我可以将“保存”按钮变灰?但是话又说回来,如果一切都一样,我想在这个窗口中使用“无保存”范例。
  • 我看到的另一种可能性是在创建新行时用一些默认数据填充“名称”和“值”字段,这在某种程度上是合理的。我找到了“Placeholder”属性,但它不适合:它只是对用户的建议,在用户实际填写某些内容之前,这些字段都是空白的,不会写入 plist。
  • 最佳答案

    我通过在 NSArrayController 的属性检查器中更改“对象 Controller ”下的“类名”解决了这个问题。给我的MyModuleName.Preset ,现在声明为一个类:

    class Preset: NSObject, Codable {
    let name: String
    let value: Int

    override init() {
    self.name = "A preset"
    self.setpoint = 1
    super.init()
    }

    init(name: String, value: Int) {
    self.name = name
    self.value = value
    super.init()
    }
    }

    通过在 init() 中提供默认值(没有参数的版本),当创建一个新行时,它会填充这些默认值,从而使问题消失。

    关于swift - 防止 NSTableView 保存新行,直到用户填写值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54385105/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com