• 「MacOS」Swift 第一章:基础部分


    本来给swift单开了一个专栏,21年学的时候还是英文教程,现在22年都有中文教程啦,索性把之前的专栏都删了,新开一篇文章作为学习swift的个人笔记

    参考链接

    Swift官方中文教程页面

    1 基础部分

    下面是基础部分知识点概述

    数据类型:

    • Int
    • Double
    • Float
    • Bool:true 和 false
    • String

    集合类型

    • Array
    • Set
    • Dictionary
    • Tuple

    变量类型
    swift中的变量分为两类,变量与常量。变量在使用过程中可以对其进行修改;常量在使用过程中不会变化。两种类型的变量声明方式不同。

    可选类型

    • Optional

    1.1 变量与常量

    常量的值一旦设定就不能改变,而变量的值可以随意更改。常量和变量必须在使用前声明,用let 来声明常量,用 var 来声明变量。两者的声明方式如下:

    let a = 10  // 常量声明
    var b = 0	// 变量声明
    var x = 0.0, y = 0.0, z = 0.0	// 可以在一行中声明多个变量或常量,使用逗号隔开
    
    • 1
    • 2
    • 3

    1.2 变量与常量类型注解

    对变量或常量的数值类型进行注释说明。注解格式如下:

    var welcomeMessage: String // 为变量welcomeMessage注解,说明它是一个String类型变量
    welcomeMessage = "Hello"
    
    • 1
    • 2

    此外,还可以在一行中定义多个同样类型的变量,用逗号分割,并在最后一个变量名之后添加类型注解:

    var red, green, blue: Double
    
    • 1

    如果在声明变量或常量时赋予了一个初始值,那么swift会对其类型执行“类型推断”,推断出这个常量或者变量的类型。

    1.3 变量与常量命名规则

    常量和变量名可以包含几乎所有的字符,包括 Unicode 字符:

    let π = 3.14159
    let 你好 = "你好世界"
    let 🐶🐮 = "dogcow"
    
    • 1
    • 2
    • 3

    一旦常量和变量声明为确定的类型,就不能使用相同的名字再次进行声明,或者改变其存储的值的类型,也不能将常量与变量进行互转,但可以更改现有的变量值为其他同类型的值

    1.4 打印常量与变量

    可以通过print(_:separator:terminator:)方法来打印变量或常量,它输出一个或多个值。其中,separator 和 terminator 参数具有默认值,因此正常使用时可以忽略。此外,该函数以换行符输出作为输出结尾,如果不想以换行符作为输出结尾,可以传递一个空字符给terminator:print(someValue, terminator:""

    swift在输出中使用字符串插值,将变量插入字符串中输出:

    var friendlyWelcome = "Hello!"
    friendlyWelcome = "Bonjour!"
    print("The current value of friendlyWelcome is \(friendlyWelcome)")
    // 输出“The current value of friendlyWelcome is Bonjour!”
    
    • 1
    • 2
    • 3
    • 4

    1.5 代码注释

    • 单行注释://
    • 多行注释:/* + */
      多行注释可嵌套使用

    1.6 分号使用

    当想要在同一行内写多条独立的语句时,可以使用分号隔开,就像python:

    let cat = "🐱"; print(cat)
    // 输出“🐱”
    
    • 1
    • 2

    1.7 整数相关规则

    • 整数包括:带符号整数(正数、零、负数),无符号整数(正数、零)
    • Swift 提供8、16、32和64位的有符号和无符号整数类型
    • 可以访问不同整数类型的 min 和 max 属性来获取对应类型的最小值和最大值:
      let minValue = UInt8.min  // minValue 为 0,是 UInt8 类型
      let maxValue = UInt8.max  // maxValue 为 255,是 UInt8 类型
      
      • 1
      • 2
    • Int、Uint在不同平台上占有位数不同
    • 一般情况不建议使用Uint,统一使用 Int 可以提高代码的可复用性;使用Uint一般是在优化性能、内存占用等场景使用

    1.8 浮点数相关规则

    • Double表示64位浮点数,到小数点后15位
    • Float表示32位浮点数,到小数点后6位

    1.9 类型安全和类型推断

    swift是类型安全的语言,跟C++类似,但不同的地方在于,swift会在第一次接收数据时,执行数据类型判断,确定该变量的数据类型。当推断浮点数时,swift默认选择Double数据类型。

    1.10 数值型字面量

    整数字面量规则:

    • 一个十进制数,没有前缀
    • 一个二进制数,前缀是 0b
    • 一个八进制数,前缀是 0o
    • 一个十六进制数,前缀是 0x

    浮点数字面量规则:

    • 一个十进制,没有前缀
    • 一个十六进制,前缀是 0x

    具体举例有点复杂,看看就行

    1.11 数据类型转换

    如果数字超出了常量或者变量可存储的范围,编译的时候会报错。由于每种整数类型都可以存储不同范围的值,所以必须根据不同情况选择性使用数值型类型转换。

    整数转换可以将低位数据升位后与高位数据计算:

    let twoThousand: UInt16 = 2_000
    let one: UInt8 = 1
    let twoThousandAndOne = twoThousand + UInt16(one)
    
    • 1
    • 2
    • 3

    整数和浮点数的相互转换必须显式指定类型:

    let three = 3
    let pointOneFourOneFiveNine = 0.14159
    let pi = Double(three) + pointOneFourOneFiveNine
    // pi 等于 3.14159,所以被推测为 Double 类型
    
    • 1
    • 2
    • 3
    • 4

    1.12 类型别名

    类型别名就是给现有类型定义另一个名字,可以使用typealias关键字来定义类型别名。例如,当要给现有类型取一个更有意义的名称时,可以:

    typealias AudioSample = UInt16 // AudioSample与UInt16关键字等价
    var maxAmplitudeFound = AudioSample.min
    // maxAmplitudeFound 现在是 0
    
    • 1
    • 2
    • 3

    1.13 布尔值

    如果在需要使用布尔值的地方,使用了非不二之,机制会报错。例如:

    let i = 1
    if i {
        // 这个例子不会通过编译,会报错
    }
    
    let i = 1
    if i == 1 {
        // 这个例子会编译成功
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.14 元组

    元组可以包含所有类型和所有元素长度。

    • 元组的声明和解构如下:

      let http404Error = (404, "Not Found")
      // http404Error 的类型是 (Int, String),值是 (404, "Not Found")
      let (statusCode, statusMessage) = http404Error
      print("The status code is \(statusCode)")
      // 输出“The status code is 404”
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 支持python中下划线_的用法

      let (justTheStatusCode, _) = http404Error
      
      • 1
    • 可以通过下标来访问元组中的单个元素,下标从零开始

      print("The status code is \(http404Error.0)")
      // 输出“The status code is 404”
      print("The status message is \(http404Error.1)")
      // 输出“The status message is Not Found”
      
      • 1
      • 2
      • 3
      • 4
    • 可以在定义元组的时候给单个元素命名,然后通过名字来获取这些元素的值

      let http200Status = (statusCode: 200, description: "OK")
      print("The status code is \(http200Status.statusCode)")
      // 输出“The status code is 200”
      print("The status message is \(http200Status.description)")
      // 输出“The status message is OK”
      
      • 1
      • 2
      • 3
      • 4
      • 5

    1.15 可选类型

    可选类型的出现主要是为了解决传入值缺失的情形,可选类型表示两种情况:值存在或值缺失。例如,将字符串String "123"转换成 Int 整数类型,这是能够成功的,而我们却不能将"Hello"转换成Int 整数类型。那么当接收的字符串内容未知时,可选类型就派上用场了:

    let possibleNumber = "123"
    let convertedNumber = Int(possibleNumber)
    // convertedNumber 被推测为类型 "Int?", 或者类型 "optional Int"
    
    • 1
    • 2
    • 3

    可选类型的声明,在数据类型后面需要加上一个?,例如 Int 可选类型应该写作Int?,问号暗示包含的值是可选类型,说明该变量只能包含一个 Int 类型的值或者不包含任何类型值。

    nil

    swift中的 nil 是一个确定的值,用来表示值缺失。可以将 nil 赋值给变量或常量,表示没有值:

    var serverResponseCode: Int? = 404
    // serverResponseCode 包含一个可选的 Int 值 404
    serverResponseCode = nil
    // serverResponseCode 现在不包含值
    
    • 1
    • 2
    • 3
    • 4

    此外,nil 只能用于可选常量或变量。如果声明了一个可选常量或变量没有赋值,那么它们会被自动赋值nil:

    var surveyAnswer: String?
    // surveyAnswer 被自动设置为 nil
    
    • 1
    • 2

    if 语句和 nil 的判断、强制解析

    可以使用 if 来判断一个可选类型是否包含值,判断操作符为==!=,如果该可选变量或常量中包含值,那么它将不等于 nil:

    if convertedNumber != nil {
        print("convertedNumber contains some integer value.")
    }
    // 输出“convertedNumber contains some integer value.”
    
    • 1
    • 2
    • 3
    • 4

    当确定一个可选类型中包含值,那么可以通过!来获取改值:

    if convertedNumber != nil {
        print("convertedNumber has an integer value of \(convertedNumber!).")
    }
    // 输出“convertedNumber has an integer value of 123.”
    
    • 1
    • 2
    • 3
    • 4

    可选绑定

    可选绑定的作用是,判断一个变量或常量中是否包含值,如果包含则将该值赋值给一个临时常量或变量。可选绑定可以用于 if 和 wihle 语句中,也可以用于常量或变量。下面的例子中使用常量(let)举例:

    if let actualNumber = Int(possibleNumber) {
        print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
    } else {
        print("\'\(possibleNumber)\' has no value and could not be converted to an integer")
    }
    // 其中可选类型为possibleNumber,如果possibleNumber中包含值,则将它赋值给actualNumber,并进入第一个print;如果possibleNumber中没有值,则进入第二个print
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果在访问它包含的值后不需要引用原来的可选常量或是可选变量,可以对新的常量或是新的变量使用相同的名称:

    let myNumber = Int(possibleNumber)
    // 此处 myNumber 为一可选整型
    if let myNumber = myNumber {
    	// 此处 myNumber 为一不可选整型
    	print("My number is \(myNumber)")
    }
    // 输出 "My number is 123"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    对于上面的 if 部分,还可以有更简洁的写法:

    let myNumber = Int(possibleNumber)
    // 此处 myNumber 为一可选整型
    if let myNumber{
    	print("My number is \(myNumber)")
    }
    // 输出 "My number is 123"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以在一个 if 中使用多个可选绑定,用逗号隔开,如果多个可选绑定中有一个为 false,则整个 if 被判定为 false。下面两个 if 的表达是等价的:

    if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
        print("\(firstNumber) < \(secondNumber) < 100")
    }
    // 输出“4 < 42 < 100”
    if let firstNumber = Int("4") {
        if let secondNumber = Int("42") {
            if firstNumber < secondNumber && secondNumber < 100 {
                print("\(firstNumber) < \(secondNumber) < 100")
            }
        }
    }
    // 输出“4 < 42 < 100”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    隐式解析的可选类型

    当一个常量或变量为可选类型时,每次使用其中包含的值时都需要进行解析,而在有的情况,当一个常量或变量第一次被赋值时,就可以确定之后每次使用都是含值的。为了避免后续无必要的解析,swift提供了隐式解析方法。

    声明隐式解析只需要将可选类型后面的?修改为!即可:

    let possibleString: String? = "An optional string." // 声明一个可选类型
    let forcedString: String = possibleString! // 需要感叹号来获取值
    
    let assumedString: String! = "An implicitly unwrapped optional string." // 声明一个隐士解析可选类型
    let implicitString: String = assumedString  // 不需要感叹号即可获取值,因为上一句已经确定assumedString中含值
    let optionalString = assumedString // 当optionalString没有指明变量类型时,会自动被赋值为assumedString的变量类型,此时assumedString是一个可选类型
    // optionalString 的类型是 "String?",assumedString 也没有被强制解析。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果一个隐式解析可选类型中不包含值,但却被尝试取值,会触发运行错误。为了避免出现该错误,我们可以对隐式解析可选类型执行可选类型是否含值一样的判断、解析:

    if assumedString != nil {
        print(assumedString!)
    }
    // 输出“An implicitly unwrapped optional string.”
    if let definiteString = assumedString {
        print(definiteString)
    }
    // 输出“An implicitly unwrapped optional string.”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注意,如果一个变量之后可能变成 nil 的话就不要使用隐式解析可选类型,使用普通的可选类型即可。

    1.16 错误处理

    错误处理主要用于应对程序中可能会遇到的错误条件。错误处理需要程序在两个地方进行定义:

    // 在函数定义后面加上 throw 关键字
    func canThrowAnError() throws {
        // 这个函数有可能抛出错误
    }
    
    // 在函数调用处加上 do 和 try 关键字,使用 catch 关键字来应对错误发生时的应对操作
    do {
        try canThrowAnError()
        // 没有错误消息抛出
    } catch {
        // 有一个错误消息抛出
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    一个上面定义的实际例子:

    func makeASandwich() throws {
        // 函数功能
    }
    
    do {
        try makeASandwich() // 预判makeASandwich()中可能发生的错误
        eatASandwich()
    } catch SandwichError.outOfCleanDishes { // 当发生SandwichError.outOfCleanDishes错误时,应对处理为washDishes()
        washDishes()
    } catch SandwichError.missingIngredients(let ingredients) {
    	// 当发生SandwichError.missingIngredients错误时,应对处理为buyGroceries()
        buyGroceries(ingredients)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    其他细节会有专门的“错误处理”章节介绍。

    1.17 断言和先决条件

    断言和先决条件是对一个程序执行过程中执行状态的检查,如果执行状态满足,则继续往下执行程序,如果不满足则终止程序执行。

    断言能够帮助在开发阶段找到错误和不正确的假设,先决条件能够帮助在生产环境中探测到存在的问题。断言和先决条件并不是用来处理可以恢复的或者可预期的错误,可以强制检查数据和程序状态,使得程序可预测的中止。

    使用断言进行调试

    可以调用 Swift 标准库的assert(_:_:file:line:) 函数来写一个断言,向函数传入一个结果为布尔值的表达式以及一条信息,那么当表达式为 false 时,该条信息会被显示:

    let age = -3
    assert(age >= 0, "A person's age cannot be less than zero") // 显示信息的写法
    assert(age >= 0) // 不显示信息的写法
    // 因为 age < 0,所以断言会触发,当断言触发,程序后续内容不会被执行,程序终止;如果断言没被触发,则程序忽略断言部分,继续向后执行
    
    • 1
    • 2
    • 3
    • 4

    如果代码已经检查了条件,可以使用 assertionFailure(_:file:line:) 函数来表明断言失败(程序非正常执行):

    if age > 10 {
        print("You can ride the roller-coaster or the ferris wheel.")
    } else if age > 0 {
        print("You can ride the ferris wheel.")
    } else {
        assertionFailure("A person's age can't be less than zero.")
    } // 用于显示程序执行过程中的断言记录
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    强制执行先决条件

    当一个条件可能为假,但是继续执行代码要求条件必须为真的时候,可以使用先决条件实现。

    可以使用全局 precondition(_:_:file:line:) 函数来写一个先决条件,向函数传入一个结果为布尔值的表达式以及一条信息,那么当表达式为 false 时,该条信息会被显示:

    // 判断下标是否合法
    precondition(index > 0, "Index must be greater than zero.")
    
    • 1
    • 2

    可以调用preconditionFailure(_:file:line:)方法来表明出现了一个错误。例如,switch 进入了 default 分支,但是所有的有效值应该被任意一个其他分支(非 default 分支)处理。

  • 相关阅读:
    软件项目和安全项目案例(承接软件和安全项目合作)
    33. 搜索旋转排序数组
    PMP考试中常见的英文缩写
    接口测试工具那么多,新公司用的自己没接触过怎么办?
    基于Java+Swing+Mysql实现《黄金矿工》游戏
    什么是多态?java 中实现多态的机制是什么?
    北理工嵩天Python语言程序设计笔记(目录)
    Java常用工具类 : StringUtils、CollectionUtils、ArrayUtils、Lists、Maps等
    华为数通方向HCIP-DataCom H12-821题库(单选题:321-340)
    Jmeter连接Mysql数据库
  • 原文地址:https://blog.csdn.net/Liiipseoroinis/article/details/127940532