首页 > 解决方案 > 如何在 XPC 服务中提供 Swift 类?

问题描述

我正在尝试将 Apple 的 XPC“小写”示例代码从 Objective-C 重建为 Swift。我了解 XPC 会,但我对 Swift 和 Objective-C 互操作性还比较陌生。

当我使用他们的确切示例代码时,它将 aString从应用程序传递到目标并返回,它可以工作。但是当我尝试用我自己的自定义类替换它时Person,我得到了错误:

NSXPCConnection: ... 来自 pid 4133 的匿名侦听器或服务侦听器上的连接:

在解码接收到的选择器 upperCasePerson:withReply: 时捕获异常,丢弃传入消息。

异常:解码参数 0 时出现异常(调用#2):

例外:decodeObjectForKey:类“CombineCycle.Person”未加载或不存在。

(演示应用程序名称为“CombineCycle”)

Person是一个 Swift 类,它继承自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就好了,所以该类被包含在内。问题似乎是NSXPCDecoder(私有类)无法反序列化它......

    __exceptionPreprocess + 250
    objc_exception_throw + 48
    _decodeObject + 1413
    -[NSXPCDecoder _decodeObjectOfClasses:atObject:] + 63
    _NSXPCSerializationDecodeInvocationObjectOnlyArgumentArray + 463

标签: objective-cswiftmacosxpcnsxpcconnection

解决方案


这些问题似乎与 NSCoder 如何通过依赖类的名称进行归档和取消归档有关。当Person对象在应用程序端编码时,使用的名称是<ModuleName.ClassName>.

当试图在服务中反序列化时,ModuleName 自然是错误的。在 Person 上使用@objc(Person)来设置 Objective-C 名称似乎是有效的。


推荐阅读