如何在 XPC 服务中提供 Swift 类?
Posted
技术标签:
【中文标题】如何在 XPC 服务中提供 Swift 类?【英文标题】:How do you make a Swift class available in an XPC service? 【发布时间】:2019-06-13 17:29:22 【问题描述】:我正在尝试将 Apple 的 XPC“小写”示例代码从 Objective-C 重建为 Swift。我了解 XPC 会,但我对 Swift 和 Objective-C 互操作性还比较陌生。
当我使用他们的确切示例代码时,它将 String
从应用程序传递到目标并返回,它可以工作。但是当我尝试用我自己的自定义类 Person
替换它时,我得到了错误:
NSXPCConnection: ...匿名侦听器上的连接或 来自 pid 4133 的服务监听器:
在解码接收到的选择器 upperCasePerson:withReply: 时捕获异常,丢弃传入的 消息。
异常:解码参数 0 时出现异常(#2 of 调用):
异常:decodeObjectForKey:类 “CombineCycle.Person”未加载或不存在。
(演示应用名称为“CombineCycle”)
Person
是一个继承自NSObject
并符合NSSecureCoding
的Swift 类。它有一个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
的实例,因此该类被包含在内。问题似乎是NSXPCDecoder
(私有类)无法反序列化它......
__exceptionPreprocess + 250
objc_exception_throw + 48
_decodeObject + 1413
-[NSXPCDecoder _decodeObjectOfClasses:atObject:] + 63
_NSXPCSerializationDecodeInvocationObjectOnlyArgumentArray + 463
【问题讨论】:
我还没有使用 NSXPCConnection,但我猜你必须用@objc
标记所有类/属性。
你检查过这个matthewminer.com/2018/08/25/… 吗?
我确实引用了该资源,并且与 Apple 示例代码一样,它使用 String 作为传输。这很好用,但是如果我用Person
(这是我的 Swift 类)替换 String,那么我会遇到异常。如果我将@objc
添加到Person
类,它似乎没有帮助。我需要更改任何构建设置吗?上面的参考实际上需要进行一些更改才能使 Swift 正常工作。也许我忽略了桥接头的其他内容......
【参考方案1】:
问题似乎与 NSCoder 如何通过依赖类的名称进行归档和取消归档有关。当Person
对象在应用程序端编码时,使用的名称是<ModuleName.ClassName>
。
当试图在服务中反序列化时,ModuleName 自然是错误的。在 Person 上使用 @objc(Person)
来设置 Objective-C 名称似乎是有效的。
【讨论】:
感谢您提供这方面的好信息。但即使在使用@objc(Person) 之后,我仍然会收到相同的错误:'异常:decodeObjectForKey:类“Person”未加载或不存在'。 Person 源代码包含在两个目标中。与您的情况一样,如果我使用 String 而不是 Person,一切正常。有什么想法吗? 很难保留您可能遇到的问题,但我会尝试在您的 XPC 目标中实例化一个Person
对象,以确保 XPC 目标确实具有适当的包括的课程。请务必从 Swift 文件和 ObjC 文件进行测试。这应该有助于缩小问题的范围。还值得检查以确保您允许通过 NSSecureCoding
方法解码 Person
类。
如果有人需要更多信息来说明如何在这里使用@objc,这篇文章让我明白了 - developer.apple.com/forums/thread/7296以上是关于如何在 XPC 服务中提供 Swift 类?的主要内容,如果未能解决你的问题,请参考以下文章
NSSecureCoding 实现类必须在共享框架中才能与 XPC 一起使用吗?
如何在macOS上使用MTLSharedTextureHandle或MTLSharedEventHandle与C XPC接口?