在XPC协议中使用自定义类 [英] Using custom class in XPC protocol
问题描述
我正在尝试使用自己在withReply
签名上的类型来编写XPC服务.类型/类具有Xcode的主应用程序和XPC服务的目标成员身份".但是,即使在withReply
签名中使用了相同的类,我也在调试输出中得到了incompatible reply block signature
,但是Xcode目标有所不同,如下所述.
I’m attempting to write an XPC service using my own type on the withReply
signature. The type/class has Xcode’s "target membership" of both the main app and the XPC service. However I am getting incompatible reply block signature
in the debug output even though the same class is being used in the withReply
signature however the Xcode target differs as I will explain below.
注意:这是使用此项目在Swift中完成的让我开始.除了那里,他们使用NSData
而不是自定义类型.
Note: This is being done in Swift using this project to get me started. Except there they use NSData
instead of a custom type.
出于这个问题的目的,我将使用以下示例
For the purposes of this question I’ll use the following as an example
- 自定义类-
Tweet
-此类符合NSSecureCoding
协议,因此可以在主应用程序和XPC服务之间传递 - XPC协议-
TweetTransfer
,其中一种方法要求func take(_ count: Int, withReply: ((Tweet) -> Void))
- Custom class -
Tweet
- This class conforms to theNSSecureCoding
protocol so that it can be passed between the main app and the XPC service - XPC Protocol -
TweetTransfer
with one method requiredfunc take(_ count: Int, withReply: ((Tweet) -> Void))
,然后是所有常见的XPC样板,在其中导出符合TweetTransfer
的对象. XPC服务似乎已启动,但随后它与主应用之间的传输失败,并显示
and then all the usual XPC boilerplate where I export an object conforming to TweetTransfer
. The XPC service appears to launch but then transfer between it and the main app fails with
XPCWorker[11069:402719] <NSXPCConnection: 0x61800010e220> connection from pid 11066 received an undecodable message
完整消息在下面[1],但是"wire"和"local"之间的唯一区别是第一个参数是
The full message is below[1] but the only difference between the "wire" and "local" is that argument one is
- 电线-
_TtC17MainApp5Tweet
- 本地-
_TtC23XPCWorker5Tweet
- wire -
_TtC17MainApp5Tweet
- local -
_TtC23XPCWorker5Tweet
Xcode目标不同的地方.这足以把它扔掉吗?然后如何在应用程序和它的XPC服务之间共享代码?
Where the Xcode target is different. Is that enough to throw it off? How then do I share code between an app and it's XPC service?
[1]完整的错误文本
[1] Full error text
<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调用所使用的协议:
Update
Some more info regarding the protocol, remoteObjectProxy connection and Tweet object. This is the protocol used for the XPC calls:
@objc(TweetTransfer)
protocol TweetTransfer {
func take(_ count: Int, withReply: replyType)
}
typealias replyType = ((Tweet) -> Void)
为了方便起见,我使用类型别名.然后Tweet
对象非常简单,仅用于测试(尽管通过支持NSSecureCoding有点复杂):
I'm using a type alias for convenience. And then the Tweet
object is very simple and just for testing (although somewhat complicated by supporting 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的点
and finally the point at which we call the 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)
}
推荐答案
下面是完整的消息,但是"wire"和"local"之间的唯一区别是参数一个是
The full message is below but the only difference between the "wire" and "local" is that argument one is
- 电线-
_TtC17MainApp5Tweet
- 本地-
_TtC23XPCWorker5Tweet
- wire -
_TtC17MainApp5Tweet
- local -
_TtC23XPCWorker5Tweet
Xcode目标不同的地方.这足以把它扔掉吗?然后如何在应用程序和它的XPC服务之间共享代码?
Where the Xcode target is different. Is that enough to throw it off? How then do I share code between an app and it's XPC service?
这确实足以把它扔掉. Swift的命名空间使已归档的对象显示为不同的类.您可以通过以下方式声明您的Tweet对象来禁用名称间隔:
That is indeed enough to throw it off. Swift's namespacing makes the archived object appear as a different class. You can disable name spacing by declaring your Tweet object with;
@objc(Tweet) class Tweet: NSObject, NSSecureCoding { ... }
@objc(name)
中的名称通常被用作在objc和Swift中呈现不同名称的一种方式,但是它也具有禁用Swift的名称间距的作用.
The name in @objc(name)
is often presented as a way to present a different name in objc vs Swift, but it also has the effect of disabling Swift's name spacing.