Swift 起步

2018-12-20  本文已影响21人  枫林风雨

原文来自Swift官方网站

查看版本
$ swift --version
Apple Swift version 2.2-dev (LLVM ..., Clang ..., Swift ...)

REPL

如果想运行没有参数的Swift指令,你可以使用REPL(Read-eval-print-loop 交互式解释器),swift的交互解释器可以直接读取、计算、打印你输入的swift代码。

$ swift
Welcome to Apple Swift version 2.2. Type :help for assistance.
  1>

在交互解释器中甚至可以直接引用系统模块,比如Darwin(Darwin 是MacOS的底层核心):

1> import Darwin
2> arc4random_uniform(10)
$R0: UInt32 = 4

打包指令

Swift的包管理器提供了一整套符合开发者习惯的系统用来构建包、可执行文件、和使用不同的package分享代码。当本地的swift开发包安装完成,你就可以直接调用包管理工具了:swift package, swift run, swift build and swift test

$ swift package --help
OVERVIEW: Perform operations on Swift packages
...
1.创建一个包

第一步:创建一个文件夹,命名为Hello:

$ mkdir Hello
$ cd Hello

第二步:每个包都要有一个manifest文件叫做Package.swift放在根目录,即此时的Hello文件夹。也可以命令生成一个最低配置的包:
swift package init
init命令默认生成如下的包目录结构:

├── Package.swift
├── README.md
├── Sources
│   └── Hello
│       └── Hello.swift
└── Tests
    ├── HelloTests
    │   └── HelloTests.swift
    └── LinuxMain.swift
2.构建一个包

然后可以使用swift build命令来构建一个包,指令会下载、分解、编译配置文件manifest中引入的依赖文件:

swift build
Compile Swift Module 'Hello' (1 sources)

测试运行包:swift test

Compile Swift Module 'HelloTests' (1 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/HelloPackageTests.xctest/Contents/MacOS/HelloPackageTests
Test Suite 'All tests' started at 2016-08-29 08:00:31.453
Test Suite 'HelloPackageTests.xctest' started at 2016-08-29 08:00:31.454
Test Suite 'HelloTests' started at 2016-08-29 08:00:31.454
Test Case '-[HelloTests.HelloTests testExample]' started.
Test Case '-[HelloTests.HelloTests testExample]' passed (0.001 seconds).
Test Suite 'HelloTests' passed at 2016-08-29 08:00:31.455.
     Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'HelloPackageTests.xctest' passed at 2016-08-29 08:00:31.455.
     Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'All tests' passed at 2016-08-29 08:00:31.455.
     Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.002) seconds

3.构建可执行文件

一个构建目标target如果包含了main.swift那这个target就会被当做一个可执行文件,包管理器会编译这个main文件到一个二进制可执行文件中。

下面做一个栗子,这个包会生成一个叫Hello的可执行文件,执行完成输出“Hello, world!”。

第一步:创建并进入目录

$ mkdir Hello
$ cd Hello

第二步:初始化包,指定为可执行文件类型

swift package init --type executable

第三步:使用swift run指令构建并执行上面初始化后的可执行文件

swift run Hello

你也可以先用swift build命令先编译这个包,再在 .build 目录下运行二进制文件:

$ swift build
Compile Swift Module 'Hello' (1 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/Hello

>$ .build/x86_64-apple-macosx10.10/debug/Hello
Hello, world!

👇下面我们在一个新的源文件来定义一个方法 sayHello(name:),并让可执行文件来执行我们定义的这个方法。

构建接收外部参数的包

第一步:在Sources/Hello目录创建一个新文件Greeter.swift,输入如下代码:

func sayHello(name: String) {
    print("Hello, \(name)!")
}

第二步:打开main.swift文件,替换里面的代码为:

if CommandLine.arguments.count != 2 {
    print("Usage: hello NAME")
} else {
    let name = CommandLine.arguments[1]
    sayHello(name: name)
}

比起之前用硬编码的方式,main.swift现在从命令行读取参数,并传入sayHello(name:)方法中处理后再输出。

第三步:再次运行swift run,生成新版本的Hello执行文件:

$ swift run Hello `whoami`

使用 LLDB 调试器

可以使用LLDB调试器一步一步运行swift程序,设置断点,检查和修改程序状态。

举个栗子,以下代码定义了一个factorial(n:)方法,调用后打印执行结果:

func factorial(n: Int) -> Int {
    if n <= 1 { return n }
    return n * factorial(n: n - 1)
}

let number = 4
print("\(number)! is equal to \(factorial(n: number))")

创建一个Factorial.swift文件,将上面的代码copy到文件,然后运行swiftc命令,把这个文件的文件名作为参数,跟一个-g选项来生成调试信息。执行后会在当前目录生成一个名为Factorial的可执行文件。

$ swiftc -g Factorial.swift
$ ls
Factorial.dSYM
Factorial.swift
Factorial(Unix可执行文件)

使用swiftc命令(类似javac和gcc的编译工具)编译swift文件同时可以输出编译信息。然后,我们不适用run指令直接执行程序,而是换成LLDB来运行,使用LLDB调试器需要把程序作为参数输入lldb指令后面:

$ lldb Factorial
(lldb) target create "Factorial"
Current executable set to 'Factorial' (x86_64).
(lldb) ...等待输入调试指令...

然后会出现一个交互式控制台让我们来运行lldb命令。

使用b指令(breakpoint set)在factorial(n:)方法的第二行设置断点,然后每次执行到这一行代码时都会获取到程序间歇。

(lldb) b 2
Breakpoint 1: where = Factorial`Factorial.factorial (Swift.Int) -> Swift.Int + 12 at Factorial.swift:2, address = 0x0000000100000e7c

使用r指令(run)运行程序,输入r并回车以后程序会运行起来并停止在factorial(n:)方法的调用栈:

(lldb) r
Process 40246 resuming
Process 40246 stopped
* thread #1: tid = 0x14dfdf, 0x0000000100000e7c Factorial`Factorial.factorial (n=4) -> Swift.Int + 12 at Factorial.swift:2, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000e7c Factorial`Factorial.factorial (n=4) -> Swift.Int + 12 at Factorial.swift:2
   1    func factorial(n: Int) -> Int {
-> 2        if n <= 1 { return n }
   3        return n * factorial(n: n - 1)
   4    }
   5
   6    let number = 4
   7    print("\(number)! is equal to \(factorial(n: number))")

使用p指令(print)来查看参数 n 的值:

(lldb) p n
(Int) $R0 = 4
  (lldb) p n * n
  (Int) $R1 = 16

使用bt指令(backtrace)来查看通向factorial(n:)的框架:

(lldb) bt
* thread #1: tid = 0x14e393, 0x0000000100000e7c Factorial`Factorial.factorial (n=4) -> Swift.Int + 12 at Factorial.swift:2, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x0000000100000e7c Factorial`Factorial.factorial (n=4) -> Swift.Int + 12 at Factorial.swift:2
    frame #1: 0x0000000100000daf Factorial`main + 287 at Factorial.swift:7
    frame #2: 0x00007fff890be5ad libdyld.dylib`start + 1
    frame #3: 0x00007fff890be5ad libdyld.dylib`start + 1

使用c指令(continue)来继续程序,直到遇到下一个断点:

(lldb) c
Process 40246 resuming
Process 40246 stopped
* thread #1: tid = 0x14e393, 0x0000000100000e7c Factorial`Factorial.factorial (n=3) -> Swift.Int + 12 at Factorial.swift:2, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000e7c Factorial`Factorial.factorial (n=3) -> Swift.Int + 12 at Factorial.swift:2
   1    func factorial(n: Int) -> Int {
-> 2        if n <= 1 { return n }
   3        return n * factorial(n: n - 1)
   4    }
   5
   6    let number = 4
   7    print("\(number)! is equal to \(factorial(n: number))")

再次使用p指令来查看参数 n 的值:

(lldb) p n
(Int) $R2 = 3

使用br di指令(breakpoint disable)关闭所有断点,然后用c指令继续程序:

(lldb) br di
All breakpoints disabled. (1 breakpoints)
(lldb) c
Process 40246 resuming
4! is equal to 24
Process 40246 exited with status = 0 (0x00000000)

#结语

现在已经介绍完了Swift的REPL、构建系统、调试器,如果需要更深一步的学习,这里有一些建议供参考:

上一篇下一篇

猜你喜欢

热点阅读