我很遗憾地承认我对块没有任何线索。
我正在编写一个GUI卸载程序应用程序,它使用特权助手工具删除我所有产品的文件和目录。
因为帮助器是单个文件,所以我通过创建一个TEXT段然后将Info.plist复制到其中来将Info.plist嵌入到可执行文件中。
到目前为止,我可以成功使用SMJobBless()
在/Library/PrivilegedHelperTools
及其/Library/LaunchDaemons
中的launchd属性列表中安装该帮助工具。
Apple建议使用XPC来确保GUI应用程序和工具具有二进制兼容版本。 EvenBetterAuthorizationSample使用块来调用辅助工具。我需要使用getVersion函数将NSMutableString
传回verifyVersionCompatibility
。
- (uint32_t)getVersion: (NSMutableString**) helperVersionPtr
// Called when the user clicks the Get Version button.
// This is the simplest form of
// NSXPCConnection request because it doesn't require any authorization.
{
assert( helperVersionPtr != NULL );
assert( *helperVersionPtr != NULL );
[self connectAndExecuteCommandBlock:^(NSError * connectError) {
if (connectError != nil) {
[self logError:connectError];
*helperVersionPtr = NULL;
DBG_MSG(( "%s connectAndExecuteCommandBlock failed connectError: %s\n", __func__, [[connectError description] UTF8String] ));
} else {
[[self.helperToolConnection remoteObjectProxyWithErrorHandler:^(NSError * proxyError) {
[self logError:proxyError];
}] getVersionWithReply:^(NSString *version) {
[self logWithFormat:@"version = %@\n", version];
[*helperVersionPtr setString: version]; // Pass the version back
}];
}
}];
return 0;
}
块在这里执行:
- (void)connectAndExecuteCommandBlock:(void(^)(NSError *))commandBlock
// Connects to the helper tool and then executes
// the supplied command block on the
// main thread, passing it an error indicating
// if the connection was successful.
{
assert([NSThread isMainThread]);
// Ensure that there's a helper tool connection in place.
[self connectToHelperTool];
// Run the command block.
// Note that we never error in this case because, if there is
// an error connecting to the helper tool, it will be delivered
// to the error handler
// passed to -remoteObjectProxyWithErrorHandler:.
// However, I maintain the possibility
// of an error here to allow for future expansion.
commandBlock(nil);
}
帮助工具的getVersionWithReply:
- (void)getVersionWithReply:(void(^)(NSString * version))reply
// Part of the HelperToolProtocol.
// Returns the version number of the tool. Note that never
// requires authorization.
{
// We specifically don't check for authorization here.
// Everyone is always allowed to get
// the version of the helper tool.
reply([[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]);
}
答案 0 :(得分:1)
我认为你问的是-getVersion:
如何同步获取通过XPC回复功能获得的字符串值并将其返回给调用者。
问题是所有XPC消息/处理程序都是在异步和随机线程上执行的。
如果你真的必须进行同步通话,你可以使用信号量来阻止,直到收到回复:
- (NSString*)synchronousExample
{
NSConditionLock* barrierLock = [[NSConditionLock alloc] initWithCondition:NO];
id<YourXPCServiceMessaging> proxy = self.serviceProxy; // get the proxy object of the XPC connection
// Send the XPC message that requests a response
__block NSString* replyString = nil;
[proxy someMessageWithStringReply:^(NSString* string){
// The XPC service has responded with the value; squirrel it away and let the original thread know it's done
replyString = string;
[barrierLock lock];
[barrierLock unlockWithCondition:YES];
}];
// Wait for the reply block to execute
[barrierLock lockWhenCondition:YES];
[barrierLock unlock];
return replyString;
}
如果您可以重新组织代码,一种更简单的方法是发出异步请求,然后在收到回复后继续:
- (void)startVerifyCheck
{
id<YourXPCServiceMessaging> proxy = self.serviceProxy; // get the proxy object of the XPC connection
[proxy someMessageWithStringReply:^(NSString* string){
// The XPC service has responded with the value
if ([string isEqualToString:@"the expected value"])
{
// Verify successful: continue with the next step
dispatch_async(dispatch_get_main_queue(), ^{
[self verifyComplete];
});
}
}];
// Reply block will continue once the reply is received
}
- (void)verifyComplete
{
// do the next step here...
}