我正试图在withReply
签名上使用我自己的类型编写XPC服务。类型/类具有Xcode的主应用程序和XPC服务的“目标成员资格”。但是我在调试输出中得到incompatible reply block signature
,即使withReply
签名中使用了相同的类,但Xcode目标有所不同,我将在下面解释。
注意:这是在Swift中使用this project来完成的。除此之外,他们使用NSData
而不是自定义类型。
出于这个问题的目的,我将使用以下作为例子
Tweet
- 此类符合NSSecureCoding
协议,以便可以在主应用和XPC服务之间传递TweetTransfer
,需要一种方法func take(_ count: Int, withReply: ((Tweet) -> Void))
然后是我导出符合TweetTransfer
的对象的所有常用XPC样板。 XPC服务似乎已启动,但随后在主应用程序之间进行转移失败并显示
XPCWorker[11069:402719] <NSXPCConnection: 0x61800010e220> connection from pid 11066 received an undecodable message
完整的消息在[1]之下,但“wire”和“local”之间的唯一区别是参数1是
_TtC17MainApp5Tweet
_TtC23XPCWorker5Tweet
Xcode目标不同的地方。这足以让它脱光吗?那么如何在应用程序和它的XPC服务之间共享代码?
[1]完整错误文字
<NSXPCConnection: 0x61800010e220> connection from pid 11066 received an undecodable message (incompatible reply block signature (wire: <NSMethodSignature: 0x618000074ec0>
number of arguments = 2
frame size = 224
is special struct return? NO
return value: -------- -------- -------- --------
type encoding (v) 'v'
flags {}
modifiers {}
frame {offset = 0, offset adjust = 0, size = 0, size adjust = 0}
memory {offset = 0, size = 0}
argument 0: -------- -------- -------- --------
type encoding (@) '@?'
flags {isObject, isBlock}
modifiers {}
frame {offset = 0, offset adjust = 0, size = 8, size adjust = 0}
memory {offset = 0, size = 8}
argument 1: -------- -------- -------- --------
type encoding (@) '@"_TtC17MainApp5Tweet"'
flags {isObject}
modifiers {}
frame {offset = 8, offset adjust = 0, size = 8, size adjust = 0}
memory {offset = 0, size = 8}
class '_TtC17MainApp5Tweet'
vs local: <NSMethodSignature: 0x610000074740>
number of arguments = 2
frame size = 224
is special struct return? NO
return value: -------- -------- -------- --------
type encoding (v) 'v'
flags {}
modifiers {}
frame {offset = 0, offset adjust = 0, size = 0, size adjust = 0}
memory {offset = 0, size = 0}
argument 0: -------- -------- -------- --------
type encoding (@) '@?'
flags {isObject, isBlock}
modifiers {}
frame {offset = 0, offset adjust = 0, size = 8, size adjust = 0}
memory {offset = 0, size = 8}
argument 1: -------- -------- -------- --------
type encoding (@) '@"_TtC23XPCWorker5Tweet"'
flags {isObject}
modifiers {}
frame {offset = 8, offset adjust = 0, size = 8, size adjust = 0}
memory {offset = 0, size = 8}
class '_TtC23XPCWorker5Tweet'
)
有关协议,remoteObjectProxy连接和Tweet对象的更多信息。这是用于XPC调用的协议:
@objc(TweetTransfer)
protocol TweetTransfer {
func take(_ count: Int, withReply: replyType)
}
typealias replyType = ((Tweet) -> Void)
为方便起见,我使用了类型别名。然后Tweet
对象非常简单,仅用于测试(虽然支持NSSecureCoding有点复杂):
final class Tweet: NSObject, NSSecureCoding {
var name: String
var text: String
static var supportsSecureCoding = true
init(name: String, text: String) {
self.name = name
self.text = text
}
init?(coder aDecoder: NSCoder) {
guard let name = aDecoder.decodeObject(forKey: "name") as? String else {
fatalError("Could not deserialise name!")
}
guard let text = aDecoder.decodeObject(forKey: "text") as? String else {
fatalError("Could not deseralise text!")
}
self.name = name
self.text = text
}
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
aCoder.encode(text, forKey: "text")
}
}
最后我们称之为remoteObjectProxy
guard let loader = workerConnection.remoteObjectProxyWithErrorHandler(handler) as? TweetTransfer else {
fatalError("Could not map worker to TweetTransfer protocol!")
}
var tweets = [Tweet]()
loader.take(1) { tweet in
tweets.append(tweet)
}
答案 0 :(得分:0)
完整的信息在下面,但“wire”和“local”之间的唯一区别是参数1是
- wire -
_TtC17MainApp5Tweet
- local -
_TtC23XPCWorker5Tweet
Xcode目标不同的地方。这足以让它脱光吗?那么如何在应用程序和它的XPC服务之间共享代码?
这确实足以将其抛弃。 Swift的命名空间使归档对象显示为不同的类。您可以通过使用;
声明Tweet对象来禁用名称间距@objc(Tweet) class Tweet: NSObject, NSSecureCoding { ... }
@objc(name)
中的名称通常表示为在objc vs Swift中显示不同名称的方式,但它也具有禁用Swift名称间距的效果。
来自Using Swift with Cocoa and Objective-C
当您在Swift类上使用@objc(name)属性时,该类在Objective-C中可用,没有任何命名空间。因此,在将可存档的Objective-C类迁移到Swift时,此属性也很有用。由于归档对象在归档中存储其类的名称,因此应使用@objc(name)属性指定与Objective-C类相同的名称,以便旧的归档可以由新的Swift类取消归档。
另一种方法是将自定义对象移动到Framework。然后该框架目标成为命名空间,XPC和App都将在框架中引用相同的命名空间/类。