以下是 Apple文档中将 Core Data 与 Cloudkit 结合使用的要求之一:
所有关系都必须是可选的。由于操作大小限制,关系更改可能无法自动保存。
尝试使用与 CloudKit 的可选关系会导致错误:
线程 1:致命错误:未解决的错误错误域 = NSCocoaErrorDomain 代码 = 134060“发生核心数据错误。” UserInfo={NSLocalizedFailureReason=CloudKit 集成要求所有关系都是可选的,以下不是:Some_Managed_Object: some_attribute}, ["NSLocalizedFailureReason": CloudKit 集成要求所有关系都是可选的,以下不是:Some_Managed_Object: some_attribute]
我想,这不是完全违背了利用关系的目的吗?
例如,假设我有两个实体:Account
和Transfer
。由于转账始终与源账户和目标账户相关联,Transfer
因此应与 具有两个非可选关系Account
。但由于上述要求,这些关系必须是可选的。
该文档给出了解释:“(这是因为)关系更改可能无法自动保存”。这似乎表明,在Cloudkit和Core Data之间的同步过程中,关系可能不完整,并且不完整的关系暴露给App代码。这对我来说似乎是一个严重的问题,因为:
在我上面的例子中,这两种关系本质上是非可选的。将它们更改为可选会使模式变得毫无意义。
即使在那些关系应该是可选的示例中,虽然不完整的关系在语法上是正确的,但它可能会导致意外的不一致问题。
所以我想知道这在真实的应用程序中应该如何工作?对我来说这似乎很破碎。我误解了什么吗?难道使用Cloudkit同步核心数据只适用于一小部分只使用可选关系的应用程序吗?(如果是这样,我想知道其他 Core Data 应用程序如何在设备之间同步数据。)
相关说明:像许多其他人一样,我努力搜索有关 Cloudkit 和 Core Data 使用的同步和冲突解决算法的详细信息。我能找到的仅有的一些信息是:
在最终一致的分布式系统中,您永远无法“知道”云中是否有现有数据或设备。您的应用程序将简单地“在某个时刻发现”该数据存在并且需要设计来处理该数据
是的,Core Data CloudKit 使用 CRDT 实现多对多关系!
NSPersistentCloudKitContainer 使用最后写入者获胜合并策略自动实现冲突解决。
虽然我大致了解这些信息的每一条,但它们并没有给出关于以下问题的直接结论:1)数据更改是否以原子方式在 Cloudkit 和 Core Data 之间同步?更重要的是 2) 同步期间是否会将不完整的数据暴露给应用程序代码?
我的猜测是 …
请参阅下面的示例代码:
struct TestView: View {
var body: some View {
ScrollViewReader { proxy in
List {
ForEach(1...30, id: \.self) { item in
Text("\(item)")
.id(item)
}
}
.onAppear {
proxy.scrollTo(8, anchor: .topLeading)
}
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink("test") {
TestView()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
两个观察结果:
如果我不放入TestView
in NavigationLink
(例如,直接放入ContentView
),代码可以正常工作。
以下差异可以解决该问题:
.onAppear {
- proxy.scrollTo(8, anchor: .topLeading)
+ DispatchQueue.main.async() {
+ proxy.scrollTo(8, anchor: .topLeading)
+ }
}
Run Code Online (Sandbox Code Playgroud)
有谁知道根本原因是什么?解决方法表明这是一个时间问题,这解释了我的观察结果 1,其中没有导航动画。那么,是否是因为当 …
假设一个 Python 应用程序依赖于一个模块,并且该模块在它的 setup.py 中的分类器元数据中仅声明了“Programming Language :: Python :: 3.5”,应用程序是否可以声明不同版本的 Python 解释器(例如,“Programming Language :: Python :: 3.7" 在它自己的 setup.py 中?
我在打包我自己的 Python3 应用程序时意识到了这个问题,我想支持所有最近的 Python3 版本。该应用程序依赖于 wcwidth 模块(https://pypi.org/project/wcwidth/)。Wcwidth 模块在其编程语言支持中仅列出“Python :: 3.4”和“Python :: 3.5”。所以我想知道如果我在使用 Python3.7 解释器时运行“pip install”会怎样?我虽然它会失败,但结果证明安装工作正常,因为 pip 下载了 wcwidth 源代码并在我的机器上编译它。
所以看起来pip在安装包时根本不检查分类器?
我已经使用了一段时间的 diffable 数据源,UITableView
我喜欢它。但是今天我意识到它设计中固有的一个问题。使用diffable数据源,需要在数据发生变化时生成并应用快照。如果数据量很大,或者更有可能数据量不是很大,但是生成每个数据点的时间很短,生成快照的累积时间会变得很明显,导致用户体验不佳。我不认为旧的 API 有这个问题,因为只为要在屏幕上显示的项目调用委托函数。
由于它是一项新技术(它是为 SwiftUI 引入的,对吗?),我无法相信它会有如此明显的局限性。但是从我在网上能找到的资料来看,我看不出它是如何解决这个问题的。在 WWDC 2019 session 220 视频中,演讲者提到它可以以透明的方式在后台线程上运行,但我认为这不一定能缓解所有场景中的问题。例如,在用户交互启动数据更改的场景中,通常以同步方式处理数据和更新 UI,因此在后台运行并没有真正的帮助。
我想我一定错过了什么,但我看不到它是什么。任何解释将不胜感激。
我试图找出在核心数据数据模型中实现具有关联值的枚举的推荐方法。假设我有一本图书实体,我想将我获取这本书的方式保存在数据库中,例如:
这将是一个 swift 枚举:
enum WhereItCameFrom {
case Bought(who: String, date: Date, where: String)
case Borrorwed(who: String, date: Date, dueDate: Date)
case GivenAsGift(who: String, date: Date, forWhat: String)
}
Run Code Online (Sandbox Code Playgroud)
我正在考虑使用继承在数据模型中实现它,如下所示:
引入一个父实体WhereItCameFrom
,并将上述案例定义为其子实体。
定义to-one
从Book
到 的关系WhereItCameFrom
。其删除规则为Cascade
。
定义to-one
从WhereItCameFrom
到 的关系Book
。其删除规则为Deny
。
看图:
我想知道这是否是正确的方法,并且我有一些具体问题。
1)实现具有关联值的枚举的典型方法是什么?
我认为我上面的模式很好。但以防万一,还有其他更好的方法吗?
2)没有属性的实体正常吗?
在上图中,WhereItCameFrom
没有任何属性。首先,我type
向它添加了一个属性来指示它是否是Bought
、Borrowed
、 或GivenAsGift
实体。但后来我意识到这个信息隐含在它的子实体类类型中,所以我删除了它。因此,父实体的唯一目的是保持关系。这种用法在核心数据中是典型的吗?
3)运行时修改关系时旧对象会自动删除吗?
book.whereItCameFrom
假设我在运行时修改关系值。它以前的值是一个Borrowed
对象。它的新值是一个GivenAsGift
对象。我是否需要 …
(在与下面的@AndreasOetjen 讨论后重写了这个问题。感谢他的评论。)
我在使用UITableView
diffable 数据源时遇到了问题。在我的应用程序中,当用户修改一个项目时,它可能会更改同一表视图中显示的另一个项目。问题是,在我创建并应用包含两个项目的新值的新快照后,间接更改的项目的 UI 没有更新。
起初我认为 diffable 数据源能够检测不同快照中项目的值变化。例如,它可能以这种方式工作:如果它发现两个快照包含相同的项目(即,两个快照中的项目具有相同的哈希值),则比较它们的值并在值更改时更新表视图中该项目的行。但是,后来我意识到它可能不会那样工作,因为 diffable 数据源没有定义任何 API 来获取和比较项目值(我最初的想法是它使用了description
计算属性和==
操作,但现在我认为这不是真的)。
所以我目前的理解是 diffable 数据源使用项目的散列来检测项目顺序变化(即插入新项目,旧项目仍然存在等),而不是项目值变化(即旧项目仍然存在但其值已更改)。如果这种理解是正确的,那么就引出了这个问题:如何使用diffable数据源来实现以下场景?
在旧UITableView
API 中,这可以通过调用reloadRows()
或来实现reloadData()
。但是如何使用 diffable 数据源来做到这一点?
更新:
在花时间做实验并解决问题后,我认为上述问题的理解是错误的。请看我下面的回答。我相信这解释了 diffable 数据源的工作原理。我希望它对其他有同样困惑的人有所帮助。我很高兴被证明是错误的。真的。因此,如果您有不同的想法,请留下您的答案。
下面是一个简单的示例,它不使用@Binding
,而是将@State
变量值直接传递给子视图(通过闭包)。
1 import SwiftUI\n \n 2 struct ContentView: View {\n 3 @State var counter = 0\n 4 var body: some View {\n 5 print("ContentView")\n 6 return VStack {\n 7 Button("Tap me!") { self.counter += 1 }\n 8 LabelView(number: counter)\n 9 }\n10 }\n11 }\n \n12 struct LabelView: View {\n13 let number: Int\n14 var body: some View {\n15 print("LabelView")\n16 return Group {\n17 Text("You've tapped \\(number) times")\n18 }\n19 }\n20 }\n
Run Code Online (Sandbox Code Playgroud)\n点击按钮会修改@State
变量,然后导致两者ContentView
并LabelView
得到更新。一个常见的解释是,因为顶层视图的 …
我在 macOS 12 (Monterey) 上使用 Xcode 13.1 附带的默认工具链。
$ sudo xcode-select -r
$ sudo xcode-select -p
/Applications/Xcode.app/Contents/Developer
Run Code Online (Sandbox Code Playgroud)
但我发现下面有两个SDK目录/Library/Developer/CommandLineTools/SDKs
:
$ pwd
/Library/Developer/CommandLineTools/SDKs
$ ls -1
MacOSX10.14.sdk
MacOSX10.15.sdk
Run Code Online (Sandbox Code Playgroud)
我想知道它们是如何安装的?
我过去曾多次升级 macOS(以及 Xcode)。升级期间是否安装了这些 SDK?/Applications/Xcode.app/Contents/Developer/Toolchains
但是既然xcode也升级了,那么它的目录下不应该包含最新的SDK吗?为什么需要在下面安装单独的副本/Library/Developer/CommandLineTools/SDKs
?
另外,SDK和工具链是同一个东西吗?我以为是,但现在我不确定。我用谷歌搜索了这个但没有发现任何有用的东西。我发现一个苹果文档解释了可以通过Preferences -> Components
在菜单中选择来查看 Xcode 中可用的工具链。使用这种方法时我什么也没看到,这似乎表明 MacOSX10.14.sdk 和 MacOSX10.15.sdk 在我的系统上不被视为(有效?)工具链?
或者 SDK 是否/Library/Developer/CommandLineTools/SDKs
仅用于 macOS 开发,而 Xcode 中的工具链包含更多适用于 iOS、iPad 等的工具链?但如果是这样,为什么下面没有MacOSX11.0.sdk和MacOSX12.0.sdk /Library/Developer/CommandLineTools/SDKs
?
我完全迷失了。感谢您的任何解释。
可以使用下面的代码一致地重现该问题。Xcode 13.3 + iOS 15.4(都是最新的)。
enum ListID: String, CaseIterable, Hashable, Identifiable {
case list1 = "List1"
case list2 = "List2"
var id: Self {
self
}
}
struct ContentView: View {
@State var listID: ListID = .list1
var body: some View {
VStack {
// 1) Picker
Picker(selection: $listID) {
ForEach(ListID.allCases) { id in
Text(id.rawValue)
}
} label: {
Text("Select a list")
}
.pickerStyle(.segmented)
// 2) List
switch listID {
case .list1:
createList(Array(1...2), id: .list1)
case .list2:
createList(Array(101...102), id: .list2) …
Run Code Online (Sandbox Code Playgroud) 在尝试 SwiftUI 4 中的新功能时NavigationStack
,我发现当状态更改时,返回的目标视图navigationDestination()
不会更新。请参阅下面的代码。
struct ContentView: View {
@State var data: [Int: String] = [
1: "One",
2: "Two",
3: "Three",
4: "Four"
]
var body: some View {
NavigationStack {
List {
ForEach(Array(data.keys).sorted(), id: \.self) { key in
NavigationLink("\(key)", value: key)
}
}
.navigationDestination(for: Int.self) { key in
if let value = data[key] {
VStack {
Text("This is \(value)").padding()
Button("Modify It") {
data[key] = "X"
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
重现问题的步骤:
运行代码并单击列表中的第一项。这将带您进入该项目的详细视图。
详细视图显示了该项目的价值。它还具有一个用于修改值的按钮。单击该按钮。您会发现详细视图中的值 …
在对应用程序的代码进行巨大更改后,我看到了此错误。我想知道是否有人知道这意味着什么以及是否可以忽略它。
列表访问单元格内容失败,返回空单元格。- SwiftUI/UICollectionViewListCoordinator.swift:296 - 请提交错误报告。
当我弹出一个包含List
from的视图时发生这种情况NavigationStack
。我List
在代码中使用了很多。我通过将每一项都一一更改来确定导致错误的确切原因,并查看错误消息是否消失List
。但是,我确实在我的代码中看不到任何可能导致此类错误的问题。另外,我无法用一个简单的示例重现该错误(尽管该错误可以在我的应用程序中一致地重现)。List
VStack
我在这里问是因为当错误出现时我的应用程序崩溃了。我后来以某种方式修复了崩溃问题,但上述错误消息仍然存在。所以我怀疑崩溃和上面的错误消息是两个不同的问题,但我不确定。搜索错误消息得到的结果很少。所以我想知道这是我个人的问题还是普遍的问题?谢谢。
更新:忘了提及,我怀疑导致问题的视图通常工作正常。当我从导航堆栈中弹出视图时,它只会在非常特定的情况下生成错误。在 @ahmed-maher 列出的三个可能的原因中,我认为第 1 项和第 2 项在我的情况下不太可能,因为否则错误消息应该首先显示。我不确定第 3 项,但我认为单元格的内容并不复杂(它只包含一些文本,由HStack
和组织VStack
)。
I have seen people using UserDefaults.setValue()
occasionally. Below is an example I find here and it works fine.
@propertyWrapper struct AppSetting<Value> {
let key: String
let defaultValue: Value
var container: UserDefaults = .standard
var wrappedValue: Value {
get { container.value(forKey: key) as? Value ?? defaultValue}
set { container.setValue(newValue, forKey: key) }
}
}
Run Code Online (Sandbox Code Playgroud)
从我在Apple的文档中可以找到的是其KVO功能setValue()
的API ,并且类继承自. 但是,尚不清楚该 API 在被调用时具体执行什么操作。从上面的例子,我可以猜到(似乎覆盖了这个方法)。但否则我会认为它设置了对象的属性,这是没有意义的。所以我想知道人们如何找到这种用法?它在任何地方都有记录吗?NSObject
UserDefaults
NSObject
UserDefaults
UserDefaults
UserDefaults
更新:我可能没有清楚地描述我的问题。我知道 KVO 是什么。我感到困惑的是 KVO 与 UserDefaults 的关系。根据我的理解,KVO 中的 key 和 UserDefaults 中的 …
我在XcodeMultiplatform
中创建应用程序时选择了模板(它是 Xcode 14.0 beta,以防万一)。我的目的是在 iOS 上运行该应用程序。我选择模板只是因为我认为看看它如何在.SwiftUI
Multiplatform
macOS
在 WWDC 2020 上,Apple推出了一种Info.plist
基于方法来实现应用程序的启动屏幕SwiftUI
。不幸的是,这种方法在Xcode 13中被破坏了。我的实验表明它在Xcode 14.0 beta中仍然不起作用,因此我通过使用文件来实现启动屏幕来解决该问题storyboard
。
但是,由于storyboard
基于UIKit
,这意味着它不适用于macOS
。这解释了为什么当我尝试在 上运行应用程序时Xcode报告以下错误macOS
:
iOS 故事板不支持设备类型“mac”
所以我想知道,鉴于基于的方法在XcodeInfo.plist
13 和 14中被破坏,如何在多平台应用程序中实现启动屏幕?是否可以跳过该文件?我检查了Xcode但没有找到方法。storyboard
macOS
另一个问题:在 上编写应用程序的常见方法是macOS
,如上所述编写多平台应用程序,还是编写两个单独的应用程序,一个用于iOS
,一个用于macOS
?谢谢。
ios ×11
swiftui ×6
core-data ×2
macos ×2
uikit ×2
cloudkit ×1
enums ×1
kvc ×1
list ×1
onappear ×1
pip ×1
python ×1
relationship ×1
scrollview ×1
setuptools ×1
swift ×1
swiftui-list ×1
swiftui-navigationsplitview ×1
swipe ×1
uitableview ×1
userdefaults ×1
xcode ×1