无法取消存档手表发送的文件
Can't unarchive a file sent by watch
我有一个 class 包含在 Apple Watch 上生成的数据。我使用下面的方法来归档class,将数据存储在一个文件中,然后将文件发送到iPhone。
func send(file counter: CounterModel) {
let session = WCSession.default
let fm = FileManager.default
let documentsDirectory = fm.urls(for: .documentDirectory, in: .userDomainMask).first!
let transferStore = documentsDirectory.appendingPathComponent("transferfile").appendingPathExtension("cnt")
do {
let counterData = try NSKeyedArchiver.archivedData(
withRootObject: counter,
requiringSecureCoding: false
)
try counterData.write(to: transferStore)
if session.activationState == .activated {
session.transferFile(transferStore, metadata: nil)
}
} catch {
print("Oops")
}
}
将文件发送到 iPhone 工作正常,正在调用委托方法并接收文件。但是,我无法取消存档数据并收到错误消息“无法读取数据,因为它的格式不正确。”代表很简单:
func session(_ session: WCSession, didReceive file: WCSessionFile) {
do {
let contents = try Data(contentsOf: file.fileURL)
if let newValue = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(contents) as? CounterModel {
listOfCounters.append(newValue)
} else {
print("The content could not be decoded.")
}
} catch {
print("Failed to retrieve the file with error \(error.localizedDescription).")
}
}
显然,我做错了什么。 iPhone 上的数据取消存档有效,所以这不是问题所在。也许发送的文件有另一种格式,但我无法获得任何相关信息。
我将问题作为 DTS 的票证打开并得到以下答案:
The culprit is that your Model class has a different (full) class name in different targets. A Swift class has a module name, which by default is tied to the target name. When your Model class is compiled for your WatchKit extension, its full name is “TagetName_watchkit_extension.Model”; when it is compiled for your iOS app, it becomes “TargetName.Model”.
When your WatchKit extension archives an object Model, it uses “Target_watchkit_extension.Model” as the class name, which is not recognized by your iOS app, and triggers the failure.
You can use @objc
to give your Model class a full name, which prevents the compiler from adding the module name, like below:
@objc(Model)
class Model: NSObject, NSCoding, ObservableObject {
我实施了这个建议并且奏效了。但是,在我的 MacBook 上,我从预览中收到一条错误消息,指出我需要更改带有“@objc dynamic”前缀的模型的某些方法。然而,这可能会发生,因为 Apple 的 DTS 没有收到此错误。
对该问题的回复是:
“@objc dynamic” is required for KVO (key-value observation) support. Since a “@Published" variable relies on KVO as well, adding that does sound reasonable for me.
这解决了我的问题,我很高兴。
我有一个 class 包含在 Apple Watch 上生成的数据。我使用下面的方法来归档class,将数据存储在一个文件中,然后将文件发送到iPhone。
func send(file counter: CounterModel) {
let session = WCSession.default
let fm = FileManager.default
let documentsDirectory = fm.urls(for: .documentDirectory, in: .userDomainMask).first!
let transferStore = documentsDirectory.appendingPathComponent("transferfile").appendingPathExtension("cnt")
do {
let counterData = try NSKeyedArchiver.archivedData(
withRootObject: counter,
requiringSecureCoding: false
)
try counterData.write(to: transferStore)
if session.activationState == .activated {
session.transferFile(transferStore, metadata: nil)
}
} catch {
print("Oops")
}
}
将文件发送到 iPhone 工作正常,正在调用委托方法并接收文件。但是,我无法取消存档数据并收到错误消息“无法读取数据,因为它的格式不正确。”代表很简单:
func session(_ session: WCSession, didReceive file: WCSessionFile) {
do {
let contents = try Data(contentsOf: file.fileURL)
if let newValue = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(contents) as? CounterModel {
listOfCounters.append(newValue)
} else {
print("The content could not be decoded.")
}
} catch {
print("Failed to retrieve the file with error \(error.localizedDescription).")
}
}
显然,我做错了什么。 iPhone 上的数据取消存档有效,所以这不是问题所在。也许发送的文件有另一种格式,但我无法获得任何相关信息。
我将问题作为 DTS 的票证打开并得到以下答案:
The culprit is that your Model class has a different (full) class name in different targets. A Swift class has a module name, which by default is tied to the target name. When your Model class is compiled for your WatchKit extension, its full name is “TagetName_watchkit_extension.Model”; when it is compiled for your iOS app, it becomes “TargetName.Model”.
When your WatchKit extension archives an object Model, it uses “Target_watchkit_extension.Model” as the class name, which is not recognized by your iOS app, and triggers the failure.
You can use
@objc
to give your Model class a full name, which prevents the compiler from adding the module name, like below:@objc(Model) class Model: NSObject, NSCoding, ObservableObject {
我实施了这个建议并且奏效了。但是,在我的 MacBook 上,我从预览中收到一条错误消息,指出我需要更改带有“@objc dynamic”前缀的模型的某些方法。然而,这可能会发生,因为 Apple 的 DTS 没有收到此错误。
对该问题的回复是:
“@objc dynamic” is required for KVO (key-value observation) support. Since a “@Published" variable relies on KVO as well, adding that does sound reasonable for me.
这解决了我的问题,我很高兴。