我在我的 Mac Catalyst 应用程序中创建了一个 LSPCatalyst 类来替换 MacOS LanguageServerProcessHost。为了完成这项工作,我将process
属性替换为processProxy
使用 FoundationApp 协议访问 MacOS 包中的流程实例的属性,如下所述。
按照@Adam 的建议,我创建了一个 MacOS 包来代理流程实例。您遵循与他指出的从 Catalyst 应用程序访问 AppKit 相同的想法,但您只需要 Foundation 即可访问 Process。我调用了捆绑包 FoundationGlue 并将所有内容放在我的 Xcode 项目中的 FoundationGlue 文件夹中。捆绑包需要一个 Info.plist,将主体类标识为“FoundationGlue.MacApp”,MacApp.swift 看起来像:
import Foundation
class MacApp: NSObject, FoundationApp {
var process: Process!
var terminationObserver: NSObjectProtocol!
func initProcess(_ launchPath: String!, _ arguments: [String]?, _ environment: [String : String]?) {
process = Process()
process.launchPath = launchPath
process.arguments = arguments
process.environment = environment
}
func setTerminationCompletion(_ completion: (()->Void)!) {
let terminationCompletion = {
NotificationCenter.default.removeObserver(self.terminationObserver!)
completion?()
}
terminationObserver =
NotificationCenter.default.addObserver(
forName: Process.didTerminateNotification,
object: process,
queue: nil) { notification -> Void in
terminationCompletion()
}
}
func setupProcessPipes(_ stdin: Pipe!, _ stdout: Pipe!, _ stderr: Pipe!) {
process.standardInput = stdin
process.standardOutput = stdout
process.standardError = stderr
}
func launchProcess() {
process.launch()
print("Launched process \(process.processIdentifier)")
}
func terminateProcess() {
process.terminate()
}
func isRunningProcess() -> Bool {
return process.isRunning
}
}
我称为 FoundationApp.h 的相应标头如下所示:
#import <Foundation/Foundation.h>
@protocol FoundationApp <NSObject>
typedef void (^terminationCompletion) ();
- (void)initProcess: (NSString *) launchPath :(NSArray<NSString *> *) arguments :(NSDictionary<NSString *, NSString *> *) environment;
- (void)setTerminationCompletion: (terminationCompletion) completion;
- (void)setupProcessPipes: (NSPipe *) stdin :(NSPipe *) stdout :(NSPipe *) stderr;
- (void)launchProcess;
- (void)terminateProcess;
- (bool)isRunningProcess;
@end
FoundationAppGlue-Bridging-Header.h 仅包含:
#import "FoundationApp.h"
为 MacOS 构建包后,将其作为框架添加到 Mac Catalyst 项目中。我在该项目中创建了一个 Catalyst.swift 以访问 FoundationGlue 捆绑功能:
import Foundation
@available(macCatalyst 13, *)
struct Catalyst {
/// Catalyst.foundation gives access to the Foundation functionality identified in FoundationApp.h and implemented in FoundationGlue/MacApp.swift
static var foundation: FoundationApp! {
let url = Bundle.main.builtInPlugInsURL?.appendingPathComponent("FoundationGlue.bundle")
let bundle = Bundle(path: url!.path)!
bundle.load()
let cls = bundle.principalClass as! NSObject.Type
return cls.init() as? FoundationApp
}
}
然后,您可以从您的应用程序中使用它,例如:
let foundationApp = Catalyst.foundation!
foundationApp.initProcess("/bin/sh", ["-c", "echo 1\nsleep 1\necho 2\nsleep 1\necho 3\nsleep 1\necho 4\nsleep 1\nexit\n"], nil)
foundationApp.setTerminationCompletion({print("terminated")})
foundationApp.launchProcess()