iOS应用程序或Playground中的进程是否始终未解析?

问题描述 投票:1回答:1

在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?,我有一个解决方案,我使用平台将这些代码与文件分开。但如果可以的话,我想使用这个单一文件。

请给我你理想的另一种解决方案。

ios swift swift4 platform
1个回答
1
投票

if #available()对OS版本进行运行时检查。

if #available(macOS 10.0, *)

如果代码在macOS 10.0或更高版本上运行,或在iOS / tvOS / watchOS上运行至少是最低部署目标的OS,则评估为true

您想要的是条件编译,具体取决于平台:

#if os(macOS)
let process = Process()
#else
// ...
#endif

0
投票

即使你已经解决了这个问题,只是为了让你知道,我想告诉你实际上,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,那么这将正常工作。

希望这对你有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.