美文网首页
Swift 起步

Swift 起步

作者: 枫林风雨 | 来源:发表于2018-12-20 12:23 被阅读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>
    
    • Xcode的Playground正是基于REPL来实时解释运行实现的。

    在交互解释器中甚至可以直接引用系统模块,比如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 run

    你也可以先用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)!")
    }
    
    • 这个sayHello(name:)方法接收一个字符串作为参数并拼接"Hello, "后打印。

    第二步:打开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`
    
    • 如需要学习Swift包管理器,包括怎么构建模块、引入依赖和索引到系统自带的库,请参考Swift Package Manager

    使用 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
    
    • p指令也能计算swift表达式:
      (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、构建系统、调试器,如果需要更深一步的学习,这里有一些建议供参考:

    相关文章

      网友评论

          本文标题:Swift 起步

          本文链接:https://www.haomeiwen.com/subject/kncykqtx.html