Xcode 8扩展执行NSTask

标签 xcode xcode8 nstask clang-format xcode-extension

我的目标是创建一个执行 clang-format 的扩展。我的代码看起来像这样:

- (void)performCommandWithInvocation:(XCSourceEditorCommandInvocation *)invocation completionHandler:(void (^)(NSError * _Nullable nilOrError))completionHandler
{
    NSError *error = nil;

    NSURL *executableURL = [[self class] executableURL];

    if (!executableURL)
    {
          NSString *errorDescription = [NSString stringWithFormat:@"Failed to find clang-format. Ensure it is installed at any of these locations\n%@", [[self class] clangFormatUrls]];
              completionHandler([NSError errorWithDomain:SourceEditorCommandErrorDomain
              code:1
              userInfo:@{NSLocalizedDescriptionKey: errorDescription}]);
          return;
    }

    NSMutableArray *args = [NSMutableArray array];
    [args addObject:@"-style=LLVM"];
    [args addObject:@"someFile.m"];
    NSPipe *outputPipe = [NSPipe pipe];
    NSPipe *errorPipe = [NSPipe pipe];

    NSTask *task = [[NSTask alloc] init];
    task.launchPath = executableURL.path;
    task.arguments = args;

    task.standardOutput = outputPipe;
    task.standardError = errorPipe;

    @try
    {
          [task launch];
    }
    @catch (NSException *exception)
    {
          completionHandler([NSError errorWithDomain:SourceEditorCommandErrorDomain
              code:2
              userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Failed to run clang-format: %@", exception.reason]}]);
          return;
    }

    [task waitUntilExit];

    NSString *output = [[NSString alloc] initWithData:[[outputPipe fileHandleForReading] readDataToEndOfFile]
          encoding:NSUTF8StringEncoding];
    NSString *errorOutput = [[NSString alloc] initWithData:[[errorPipe fileHandleForReading] readDataToEndOfFile]
          encoding:NSUTF8StringEncoding];
    [[outputPipe fileHandleForReading] closeFile];
    [[errorPipe fileHandleForReading] closeFile];

    int status = [task terminationStatus];
    if (status == 0)
    {
          NSLog(@"Success: %@", output);
    }
    else
    {
          error = [NSError errorWithDomain:SourceEditorCommandErrorDomain
              code:3
              userInfo:@{NSLocalizedDescriptionKey: errorOutput}];
    }

    completionHandler(error);
}

我需要try-catch块的原因是因为当我尝试运行此代码时会引发异常。异常原因是:

Error: launch path not accessible



我的 clang-format 的路径是/usr/local/bin/clang-format。我发现的是,它不喜欢我尝试访问/usr/local/bin中的应用程序,但是/bin可以(例如,如果我尝试执行/bin/ls,就没有问题)。

我尝试的另一个解决方案是通过设置启动路径和参数来运行/bin/bash,如下所示:
task.launchPath = [[[NSProcessInfo processInfo] environment] objectForKey:@"SHELL"];
task.arguments = @[@"-l", @"-c", @"/usr/local/bin/clang-format -style=LLVM someFile.m"];

这样可以成功启动任务,但是失败,并显示以下错误:

/bin/bash: /etc/profile: Operation not permitted /bin/bash: /usr/local/bin/clang-format: Operation not permitted



第一条错误消息是由于尝试在bash中调用-l参数而导致的,该参数尝试以用户身份登录。

知道如何启用对其他文件夹的访问吗?我需要启用某种沙箱环境设置吗?

最佳答案

我猜是因为沙箱,这是不可能的。
您可以捆绑 clang-format 的可执行文件,然后从那里使用它。

关于Xcode 8扩展执行NSTask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39413889/

相关文章:

ios - 如何在不为每种语言创建 xib 的情况下本地化 xib View 中的文本?

ios - 我不知道我的代码有什么问题(带有 MWFeedParser 的 rss 阅读器)

ios - 为 iOS 的所有 View 保持相同的按钮高度

objective-c - 启动后写入 NSTasks 标准输入

cocoa - NSTask 只执行一次

objective-c - 进程间通信使用NSPipe,NSTask

ios - 您的应用包含非公开 API 使用 - 提交应用

Objective-C Clang-Format 方法大括号中断

objective-c - 语音识别不工作 mac OS X

iphone - 由于 Alamofire 的符号链接(symbolic link)错误,xcodebuild 无法创建存档