如何在Swift中访问程序参数?

44

C语言及其衍生语言在入口函数中有argcargv(以及envp)参数,但Swift没有一个合适的入口函数:顶层代码只是代码,它没有参数。

那么,在Swift程序中如何访问等效于argcargv的内容?

6个回答

55

Process 刚被重命名为 CommandLine(自 Swift 3.0 8月4日快照版起)。

let arguments = CommandLine.arguments

(由于某种原因,这在更改日志中没有提到)


2
这是现在使用Xcode 8 Beta 6的正确答案。我在这里注意到的许多变化中,这是其中之一: http://www.brightdigit.com/blog/16/08/17/updating-for-xcode-8-beta-6/ - leogdion

39

Process.arguments 是你的好帮手!

幸运的是,这非常容易,而且已经内置:无需导入任何东西,也不需要用C、Objective或其他方式动手。

考虑下面这个示例,我们将其称为 args.swift:

Swift 2 版本:

var c = 0;
for arg in Process.arguments {
    println("argument \(c) is: \(arg)")
    c++
}

Swift 3 版本:

var c = 0;
for arg in CommandLine.arguments {
    print("argument \(c) is: \(arg)")
    c += 1
}

我们可以像这样编译并运行它:

$ swift -o args args.swift && ./args fee fi fo fum
argument 0 is: ./args
argument 1 is: fee
argument 2 is: fi
argument 3 is: fo
argument 4 is: fum

请注意,第一个参数是程序名称,这一点符合您的预期。

很明显,每个参数都是字符串。

我非常希望随着Swift不断发展,Process 能够变得更加有用,但目前它似乎只提供了参数。如果您正在尝试编写纯Swift程序,这已经足够了。


1
你也可以使用 swift -i 像运行 Python 或 Ruby 脚本一样运行 Swift 代码;结合 Process.arguments,Swift 成为了一种有前途的脚本语言。参考链接 - Joe
3
Process 有没有相关文档? - alaroldai
以上评论同意 - 我在哪里可以找到有关进程的信息? - David H
1
Process终于在这里有了文档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Reference/Swift_Process_Enumeration/ - cabbey
打字错误?应该是 swift -o args ... 而不是 swiftc -o args... - Jan ATAC

13

一旦您的应用程序启动,我将使用进程信息:

let args = NSProcessInfo.processInfo().arguments
print(args)

没有任何不安全的地方,非常方便。

请注意你需要import Foundation(或者Cocoa/UIKit)。


看起来你必须手动输入 import Foundation 才能使它工作,否则会出现 error: use of unresolved identifier 'NSProcessInfo' 的错误。 - Brad Dwyer
如果您不想要任何ObjectiveC代码,只需导入Darwin即可。 - David H
@DavidH 我不明白你的意思。 - Daij-Djan
@Daij-Djan 抱歉错过了你的问题 - "import Darwin" 应该只导入 C 库,因此不会导入 ObjectiveC 库。然后,就可以像其他答案中提到的那样使用 "Process"。 - David H
NSProcessInfo是ObjC语言中Foundation框架的一部分。 - Daij-Djan

11

对于 Swift 3,您可以使用以下代码:

let argc = CommandLine.argc
let argv = UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc))

这相当于 Objective-C 主函数中使用的 argcargv 参数:

int main(int argc, char *argv[])

对于旧版本的Swift,您可以使用Process.argcProcess.unsafeArgvC_ARGCC_ARGV

您可以将这些变量传递给iOS应用程序中的UIApplicationMain函数:

Swift 3:

let argc = CommandLine.argc
let argv = UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc))
UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.self))

之前的 Swift 版本:

UIApplicationMain(Process.argc, Process.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
或者:
UIApplicationMain(C_ARGC, C_ARGC, nil, NSStringFromClass(AppDelegate.self))

Objective-C:

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

更简单地说,CommandLine.arguments - zneak
@zneak,当然,这是最简单的方法,但你不能将它传递给UIApplicationMain函数,你必须使用提到的UnsafeMutableRawPointer - Darrarski
我明白了。我只做macOS开发。在我们这边,仅仅拥有一个应用程序代理就会导致编译器创建一个调用NSApplicationMain的主函数。我以为在iOS上也会发生类似的事情。 - zneak

1

一个优雅的替代CommandLine.argumentsSwift Argument ParserArgumentParser将为您解析命令行参数,将参数映射到struct中。它提供了所有您期望从命令行应用程序中获得的功能,包括类型安全解析参数、自动帮助功能、短选项和长选项等。

只需使用“Swift Package Manager”将ArgumentParser包添加到您的命令行项目中(例如,在Xcode的“文件”»“添加包”命令中)。


0
     import Foundation


     println(C_ARGC) //CInt    
     println(C_ARGV) // CString

如上所示的代码中,你可以使用C_ARGC来获取参数的个数。使用C_ARGV来获取这些参数。

4
这并没有回答问题。如果您想对作者进行评论或要求澄清,请在他们发布的帖子下留言。 - Getz
添加了额外的解释。 - Waruna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接