如何使XPC服务中的Swift类可用?

时间:2019-06-13 17:29:22

标签: objective-c swift macos xpc nsxpcconnection

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

当我使用他们的确切示例代码时,该示例代码将String从应用程序传递到目标,然后又传递回目标,它将起作用。但是,当我尝试用自己的自定义类Person替换它时,出现了错误:

  

NSXPCConnection:...匿名监听器上的连接或   来自pid 4133的serviceListener:

     

在解码接收到的选择器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

1 个答案:

答案 0 :(得分:2)

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

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