你如何使 Swift class 在 XPC 服务中可用?
How do you make a Swift class available in an XPC service?
我正在尝试将 Apple 的 XPC "lowerCase" 示例代码从 Objective-C 重建为 Swift。我知道 XPC 会,但我对 Swift 和 Objective-C 互操作性还比较陌生。
当我使用他们的确切示例代码时,它将 String
从应用程序传递到目标并返回,它起作用了。但是当我尝试用我自己的自定义 class、Person
替换它时,我收到错误:
NSXPCConnection: ... connection on anonymousListener or
serviceListener from pid 4133:
Exception caught during decoding of received selector upperCasePerson:withReply:, dropping incoming
message.
Exception: Exception while decoding argument 0 (#2 of
invocation):
Exception: decodeObjectForKey: class
"CombineCycle.Person" not loaded or does not exist.
(演示应用程序名称是 'CombineCycle')
Person
是一个Swiftclass,继承自NSObject
,符合NSSecureCoding
。 name:String
有一个 属性。它附带的 .swift
源文件包含在 XPC 目标的构建中。
异常似乎不言自明,但我不确定我需要更改哪些构建设置,或者我需要生成哪些文件来解决潜在问题。
这只是一个演示应用程序。主应用程序创建为 Swift 应用程序,不包含 Objective-C 文件。 XPC 目标是使用 Xcode 的新目标功能创建的,该功能在 Xcode 11 中生成一个 Objective-C 骨架。我用 Swift 实现替换了所有这些文件。
// Person.swift (Included in both targets)
@objc public class Person : NSObject, NSSecureCoding {
var name:String?
init(_ name:String) {
self.name = name
}
public static var supportsSecureCoding: Bool {
return true
}
public required init?(coder: NSCoder) {
self.name = coder.decodeObject(forKey: "name") as? String
}
public func encode(with coder: NSCoder) {
coder.encode(self.name, forKey: "name")
}
}
更新
XPC 服务能够很好地实例化 Person
的实例,因此包含了 class。问题似乎是 NSXPCDecoder
(私有 class)无法反序列化它...
__exceptionPreprocess + 250
objc_exception_throw + 48
_decodeObject + 1413
-[NSXPCDecoder _decodeObjectOfClasses:atObject:] + 63
_NSXPCSerializationDecodeInvocationObjectOnlyArgumentArray + 463
这些问题似乎与 NSCoder 如何根据类的名称进行归档和取消归档有关。当 Person
对象在应用程序端编码时,使用的名称是 <ModuleName.ClassName>
。
当试图在服务中反序列化时,ModuleName 自然是错误的。在 Person 上使用 @objc(Person)
来设置 Objective-C 名称似乎有效。
我正在尝试将 Apple 的 XPC "lowerCase" 示例代码从 Objective-C 重建为 Swift。我知道 XPC 会,但我对 Swift 和 Objective-C 互操作性还比较陌生。
当我使用他们的确切示例代码时,它将 String
从应用程序传递到目标并返回,它起作用了。但是当我尝试用我自己的自定义 class、Person
替换它时,我收到错误:
NSXPCConnection: ... connection on anonymousListener or serviceListener from pid 4133:
Exception caught during decoding of received selector upperCasePerson:withReply:, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: decodeObjectForKey: class "CombineCycle.Person" not loaded or does not exist.
(演示应用程序名称是 'CombineCycle')
Person
是一个Swiftclass,继承自NSObject
,符合NSSecureCoding
。 name:String
有一个 属性。它附带的 .swift
源文件包含在 XPC 目标的构建中。
异常似乎不言自明,但我不确定我需要更改哪些构建设置,或者我需要生成哪些文件来解决潜在问题。
这只是一个演示应用程序。主应用程序创建为 Swift 应用程序,不包含 Objective-C 文件。 XPC 目标是使用 Xcode 的新目标功能创建的,该功能在 Xcode 11 中生成一个 Objective-C 骨架。我用 Swift 实现替换了所有这些文件。
// Person.swift (Included in both targets)
@objc public class Person : NSObject, NSSecureCoding {
var name:String?
init(_ name:String) {
self.name = name
}
public static var supportsSecureCoding: Bool {
return true
}
public required init?(coder: NSCoder) {
self.name = coder.decodeObject(forKey: "name") as? String
}
public func encode(with coder: NSCoder) {
coder.encode(self.name, forKey: "name")
}
}
更新
XPC 服务能够很好地实例化 Person
的实例,因此包含了 class。问题似乎是 NSXPCDecoder
(私有 class)无法反序列化它...
__exceptionPreprocess + 250
objc_exception_throw + 48
_decodeObject + 1413
-[NSXPCDecoder _decodeObjectOfClasses:atObject:] + 63
_NSXPCSerializationDecodeInvocationObjectOnlyArgumentArray + 463
这些问题似乎与 NSCoder 如何根据类的名称进行归档和取消归档有关。当 Person
对象在应用程序端编码时,使用的名称是 <ModuleName.ClassName>
。
当试图在服务中反序列化时,ModuleName 自然是错误的。在 Person 上使用 @objc(Person)
来设置 Objective-C 名称似乎有效。