互联网科技

Xcode创建终端命令

作者:金沙国际官网    发布时间:2020-04-27 18:31     浏览次数 :169

[返回]

图片 1

一.Swift语言简介

// Swift 命令行工具

典型的Mac用户交互都是基于鼠标在屏幕上操作图形元素来交互的.在这种交互方式之前,是用命令行和电脑交流的.命令行基于文本信息,键入程序名来运行,可选地带上参数.尽管图形界面很方便,但命令行程序依然在今天有很重要的作用.ImageMagick和ffmpeg在服务器中是很重要的命令行程序.实际上大多数网络服务都只运行命令行程序.这篇文章会教你写一个叫Panagram的命令行程序.他会根据你传入的参数,来判断是回文还是变位词.它可以以预定义的参数开始,或者交互模式下,提示用户输入所需的值。通常,命令行程序从shell启动,比macOS中的终端的bash shell.简单起见和方便学习,大多数时间我们都在Xcode启动命令行程序.最后才讲从终端启动命令行程序.

   1. Swift简洁但是不简单。

// REPL环境 就是每输入一句语句就立即执行和输出

Swift相对于传统的C, Perl, Ruby 或者 Java语言创建命令行程序是比较奇特的选择.但是选他肯定是有原因的:1.Swift可以作为解释型的脚本语言,也可以作为编译语言.作为脚本语言可以省去编译,易于维护.作为编译语言可以提高运行效率,或者打包出售给社会.2.不必切换语言.和多人说程序员每年都要学一门新语言.这是个好想法,但是如果你已经熟悉了Swift和它的标准库,你用Swift就是节约了时间.

   2. Swift并不是弱类型的语言。

// REPL环境只是表现的像是及时的解释执行,但是其实质还是啊每次输入代码后进行编译运行,所以不能在 REPL环境中做复杂的事情

这个教程会教你创建一个的编译项目.

   3. Swift并不是一种脚本语言。

//print("hello")

打开 Xcode 来到 File/New/Project. 找到macOS组, 选择Application/Command Line Tool,点击Next:图片 2在Product Name, 输入Panagram. 确保语言是Swift, 然后点击Next:图片 3

   4. Swift和Object-C各有轻重。

// Swift命令行工具的的一个常用的地方是直接脱离 Xcode 韩静进行编译和生成课执行的二进制文件。我们可以使用 swiftc 来进行编译

选择一个位置存储你的项目,然后点击Create.在Project Navigator area你会看到由末模板创建的main.swift文件

二.下载和安装Xcode

// 在 MyClass.swift 输入

图片 4

1. 安装Xcode有两个方法:一是在浏览器中登陆 Store进行下载并安装。这里是按照第二种方法进行安装的,个人觉得方便快捷。

class MyClass {

很多类C语言都有一个main函数作为程序入口.也就意味着程序启动一启动就执行这个函数的第一行代码.相反, Swift没有main函数,但是它有一个main文件.当你运行程序的时候,会执行第一行不是方法或者类声明的代码.所以保持main.swift文件整洁很重要.把类和结构放到他们自己的文件里.这样不仅合理,而且容易理解程序的执行路径.

  1. 安装辅助工具和文档:

let name = "XiaoMing"

大多数命令行程序都会打印一些信息给用户看.比如一个视屏格式转换器就会打印当前的进度或者错误信息.类unix比如macOS就定义两种不一样的输出流:1.标准输出流,通常定向到显示器,显示信息给用户.2.标准错误流,用来显示转台和错误信息.一般定向到显示器,也可以定向到一个文件.

(1).选择屏幕上方菜单中的Xcode—>Preferences,系统打开Xcode参数设置对话框;

func hello() {

注意:无论是从Xcode还是终端启动命令行程序,默认情况下stdout 和 stderr是一样的,而且输出的信息,都会写到控制台里.实际当中都会把stderr定向到文件中,便于之后查看.这样可以把用户不必知道的错误信息隐藏存储起来,之后可以再慢慢根据这些错误信息修复bug.

(2).单击Components选项,可以看到有simulators和documentation两个标签页,在各自的标签页下方看到能安装的各种辅助工具或者文档,如果各工具的右边显示☑️图标,则表示该工具已经安装了;如果显示下载按钮,则表明该工具还未安装,单击下载按钮就会安装该工具;

print("Hello (name)")

在Project navigator选中Panagram,然后按 Cmd + N创建新文件,选择Source/Swift File,按Next:图片 5

三.HelloWorld初体验:

}

把文件存储为ConsoleIO.swift,之后会封装input和output方法到一个小小的类,命名为ConsoleIO.添加下面的代码到ConsoleIO.swift的最后面:

1. Swift程序的入口:对于整个Swift应用只有一个源程序的情况,Swift源文件第一行可执行代码就是Swift程序的入口;对于整个应用由多个源程序组成的情况,文件名为main.swift的源程序中才可以放置可执行代码(也可以放置函数、类、结构体、枚举等定义)其他源程序中只能定义函数、类、枚举和结构体。此时,main.swift源程序中第一行可执行代码将作为Swift程序等入口。

}

class ConsoleIO {}

2.使用终端窗口编译、运行Swift程序:

// 在 main.swift 输入

解析来的任务就是让Panagram使用这两个输出流.在ConsoleIO.swift添加下面这个枚举类型到import行和ConsoleIO类实现之间:

(1)使用任意的文本编辑器,编写代码:

let object = MyClass()

enum OutputType { case error case standard}

import Foundation

object.hello()

这样就定义了输出信息时使用的输出流.接下来把下面这个方法到ConsoleIO 到类里(在这个类的花括号里):

print(“Hello World!”)

// 在终端 输入

func writeMessage(_ message: String, to: OutputType = .standard) { switch to { case .standard: print("") case .error: fputs("Error: \n", stderr) }}

(2)保存为hello.swift文件。

// swiftc MyClass.swift main.swift

这个方法有两个参数,第一个是要输出的信息,第二个是输出的目标地址,默认值是.standard..standard选项使用print,会写入到stdout. .error选项会使用c函数fputs写入信息到全局并且指向标准错误流的stderr再增加以下代码到ConsoleIO类里:

(3)打开Terminal终端,进入hello.swift文件所在的位置

// 就会生成一个 main 的可执行文件

func printUsage() { let executableName = (CommandLine.arguments[0] as NSString).lastPathComponent writeMessage writeMessage("(executableName) -a string1 string2") writeMessage writeMessage("(executableName) -p string") writeMessage writeMessage("(executableName) -h to show usage information") writeMessage("Type (executableName) without an option to enter interactive mode.")}

(4)编译:swiftc -o hello.out hello.swift——注意:是swiftc命令,输出文件名在前。

// 在终端输入 ./main

printUsage()方法会打印使用信息到控制台.每次运行程序,可执行文件的路径都在 argument[0]里,而 argument[0]可以通过全局枚举的CommandLine访问到.CommandLine是围绕argc和argv参数的Swift标准库中的封装的代码注意:实际当中,当用户使用错了参数,都会打印使用信息到控制台.创建另一个文件Panagram.swift .添加以下代码:

(5)运行:./hello.out。

// 终端就会输出

class Panagram { let consoleIO = ConsoleIO() func staticMode() { consoleIO.printUsage() }}

(6)此时在终端中就会打印出:Hello World

// Hello

定义了一个有一个方法的Panagram类.这个类会处理程序的主要逻辑.当前他只是简单地打印了使用信息.现在打开main文件,把print语句替换成:

// 另外,Swift命令行工具的使用案例是生成汇编级别的代码。有时候我们想确认经过优化后的汇编代码实际上做了些什么。 swiftc 提供了参数来生成 asm 级别的汇编代码

let panagram = Panagram()panagram.staticMode()

// 终端输入  swiftc -O hello.swift -o hello.asm, 生成 .asm 文件,借助 Hopper 反编译工具,就能了解编译器具体做了什么工作了

注意:如之前描述,这些代码会成为程序最开始执行的代码.编译运行项目,会显示如下信息在控制台:

// 终端输入 swift --help  还有  swiftc --help

usage:Panagram -a string1 string2orPanagram -p stringorPanagram -h to show usage informationType Panagram without an option to enter interactive mode.Program ended with exit code: 0

好了,到现在为止,你应该知道什么是命令行工具,从哪里开始执行,注意发送信息到stdout和stdout.如何有组织地安排代码到各个文件.下一节会处理参数,完成Panagram的static mode

运行命令行程序的时候,打在名字之后的东西都会成为参数传给程序,参数可以用空格分开.通常都使用两种参数:options 和 strings.Options的起始是一个破折号,之后跟着一个字符,或者两个破折号跟着一个单词.比如很多程序都有-h 或者 --help选项,前者是后者的简化.为了简单化,我们使用前者.打开Panagram.swift,添加下面代码到文件的最上面,在Panagram类的范围之外:

enum OptionType: String { case palindrome = "p" case anagram = "a" case help = "h" case unknown init(value: String) { switch value { case "a": self = .anagram case "p": self = .palindrome case "h": self = .help default: self = .unknown } }}

上面代码里用字符定义了一个枚举类型,可以把option参数直接传到init方法里.Panagram有三种options:-p检测回文,-a检测变位字,-h显示使用信息.除此之外的都为作为一个错误.接下来添加下面代码到Panagram类里:

func getOption(_ option: String) -> (option:OptionType, value: String) { return (OptionType(value: option), option)}

上面的方法接受一个option参数作为一个String,然后返回String和OptionType的一个元组.

注意:如果你不熟悉元组,看看我们的视频[PART 5: Tuples](https://videos.raywenderlich.com/courses/51-beginning-swift-3/lessons/5?_ga=2.76197205.1321793565.1518402701-549624587.1518402701)

在Panagram里,用下面代码替换staticMode()里面的内容:

//1let argCount = CommandLine.argc//2let argument = CommandLine.arguments[1]//3let (option, value) = getOption(argument.substring(from: argument.index(argument.startIndex, offsetBy: 1)))//4consoleIO.writeMessage("Argument count:  Option:  value: 

解释一下代码:1.取得参数的数量,因为执行路径总是存在(CommandLine.arguments[0]),所以数量总是大于等于1

  1. 从arguments数组获取真正的参数.3.解析参数,转换成OptionType类型.index(_:offsetBy:)忽略了第一个字符,因为我们总是这里总是破折号.4.输出解析结果到控制台.

在main文件里,替换panagram.staticMode()这一行:

if CommandLine.argc < 2 { //TODO: Handle interactive mode} else { panagram.staticMode()}