在iOS应用程序中,我想使用具有以下功能的文件使用Process:
public func system(_ body: String) throws {
if #available(macOS 10.0, *) {
let process = Process()
...
} else {
fatalError()
}
}
然后,即使我应用了可用性条件而且我没有唤起这个功能,我也得到了一个错误的错误:使用未解析的标识符'Process'。
我在Playground尝试了类似的代码,我得到了同样的错误。
我知道我们不能通过这个问题以常规方式使用iOS应用程序中的进程:How to execute terminal commands in Swift 4?,我有一个解决方案,我使用平台将这些代码与文件分开。但如果可以的话,我想使用这个单一文件。
请给我你理想的另一种解决方案。
if #available()
对OS版本进行运行时检查。
if #available(macOS 10.0, *)
如果代码在macOS 10.0或更高版本上运行,或在iOS / tvOS / watchOS上运行至少是最低部署目标的OS,则评估为true
。
您想要的是条件编译,具体取决于平台:
#if os(macOS)
let process = Process()
#else
// ...
#endif
即使你已经解决了这个问题,只是为了让你知道,我想告诉你实际上,Process()
(或Swift 3.0或更新的CommandLine()
)可用于iOS,但你需要使用custom Objective-C header file来创建对象Process()
/ CommandLine()
,或者更确切地说是NSTask()
,以及它需要的一切。
然后,为了将此代码与Swift一起使用,您需要创建一个Bridging-Header,您需要导入NSTask.h
文件才能将其暴露给Swift并能够在Swift代码中使用它。
完成后,使用NSTask()
而不是Process()
:
let process = NSTask() /* or NSTask.init() */
或者只要在运行任务时在代码中使用以下函数:
func task(launchPath: String, arguments: String...) -> NSString {
let task = NSTask.init()
task?.setLaunchPath(launchPath)
task?.arguments = arguments
// Create a Pipe and make the task
// put all the output there
let pipe = Pipe()
task?.standardOutput = pipe
// Launch the task
task?.launch()
task?.waitUntilExit()
// Get the data
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
return output!
}
如你所见,在这种情况下,NSTask()
将相当于Process()
。
并称之为:
task(launchPath: "/usr/bin/echo", arguments: "Hello World")
这也将返回值,因此您甚至可以通过执行以下操作来显示它:
print(task(launchPath: "/usr/bin/echo", arguments: "Hello, World!"))
哪个会打印:
~> Hello, World!
为了使其工作而不是抛出NSInternalInconsistencyException
,您需要将launchPath设置为可执行文件的完整路径,而不是仅包含它的目录。
您还需要设置用逗号分隔的所有命令参数。
在iPad Mini 2(iOS 12.1~> Jailbroken)和iPhone Xr(iOS 12.2~>不越狱)上进行了测试。
注意:即使这适用于非越狱和越狱设备,你的应用程序将在AppStore上被拒绝,因为@ClausJørgensen说:
You're using private APIs, so it'll be rejected on the App Store. Also, Xcode 11 has some new functionality that will trigger a build failure when using certain private APIs.
如果您的应用是针对越狱的iOS设备,并将上传到第三方商店,如Cydia,Zebra,Thunderbolt或Sileo,那么这将正常工作。
希望这对你有所帮助。