Swift 那些特有的语法结构

3,582 阅读8分钟

引言

刚开始接触到iOS 开发时,便是使用Swift语言进行开发,在大致看了一下Swift相关文档的目录结构后,感觉跟其他语言大差不差,便随意扫了一遍,但是在接触的时间变长后,渐渐发现,它的很多特殊的语法我都给忽略了,都是遇到时现查一番,本文便是对遇到的特殊语法的一个简要总结

关键字

weak

用于声明弱引用,主要用于解决实例循环强引用的问题。在类之间相互引用时,如果使用强引用(默认情况下),可能会导致循环引用,从而造成内存泄漏

本篇文章详细的介绍了weak的用法,同时还提到了另一个解决实例循环强引用问题的关键字unowned

lazy

用于声明延时加载存储属性,将属性的初始化推迟到第一次访问该属性的时候,而不是在对象初始化时立即执行

  • lazy声明的属性必须声明为变量(var),因为一旦初始化,它们的值可以在后续访问中改变
  • lazy属性在第一次访问后会保留其值,因此它只会初始化一次

本篇文章详细介绍了延时加载存储属性的概念

struct 结构体

struct 结构体class 类看起来挺相似的,无论长相还是写法,但是结构体还是与有着很多区别的:

  • 值类型
  • 不支持继承
  • 具有自动生成的成员初始化器
  • 属性默认不可变,要声明为var才可变

本篇文章对比介绍了struct 结构体class 类的区别

最大的区别:struct是值类型,而class是引用类型

private(set)

  • private用于限制整个成员(包括读取和设置)
  • private(set)用于限制属性的设置操作,但外部能读取

Swift提供了五个访问控制级别的修饰符:openpublicinternalfile privateprivate

访问级别修饰符都支持带上一个参数,该参数由一对圆括号和其中的set关键字组成

typealias:类型别名

typealiasSwift中的一个关键字,用于为现有的数据类型(包括结构体枚举协议函数类型等)定义一个别名。这个别名可以用来更方便地引用复杂的数据类型,提高代码的可读性和可维护性

try 和 try?

  • try:显示处理错误

    使用try表示希望捕获可能的错误并进行处理。如果发生错误,程序将抛出一个异常,可以使用do-catch块进行错误处理

  • try?:错误默认返回nil

    使用try?表示希望尽量避免处理错误,而是将结果作为可选值处理。如果代码执行成功,将返回结果值;如果发生错误,将返回nil

运算符

!:强制解析

!可选类型(?)的值强制解包,确定值不会为nil可使用,否则会导致运行崩溃

?:可选类型

可选类型Swift中用于处理可能包含空值(nil)的值的机制。可选类型有两种可能的值:

  • 有值:表示包含了一个具体的值
  • 无值(nil):表示没有值

??:空合并运算符

??的作用是在可选值nil时提供一个默认值,以防止使用可选值时出现nil引发的问题

区间运算符

  • a...b:闭区间运算符。表示一个从ab(包括ab)的闭区间范围
  • a...<b:半开区间运算符。表示一个从ab(包括a,但不包括b)的半开区间范围

属性观察器

  • willSet:在新的值被设置之前调用。可以在属性值即将发生变化时执行额外的代码
  • didSet:在新的值被设置之后调用。可以在属性值发生变化后执行额外的代码
// 在类型 {} 内使用
var property: Int {
    willSet {
        // 在属性值将要被设置前执行的代码
    }
    
    didSet { 
        // 在属性值被设置后执行的代码 
    }
}

数据类型

字典

字典这个数据类型在其他语言中也有,并不特殊,此处列出仅是其写法比较特殊,有些类似数组:

[KeyType: ValueType]

// 声明
var person = ["name": "Mary", "age": "18"]
// 添加
person["sex"] = "female"
// 访问
let personName = person["name"]
// 更新
person["name"] = "Alice"
// 删除
person["name"] = nil

枚举

枚举这个数据结构应该也是不陌生了,此处列出是因为在Swift中广泛的使用枚举关联值这个概念,在此便着重声明一下

枚举是一种在编程中用于定义命名常量集合的数据类型。枚举是一种有限的、离散的数据类型,它包含一组可能的值

// 带关联值的枚举:可以为枚举成员添加关联值,以便在枚举的不同成员之间传递数据
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

本篇文章详细的介绍了枚举相关的概念

元组

元组这个数据结构在其他的语言(如:Python)也是存在的,此处列出是为了说明一下在Swift元组的使用操作

元组可以包含不同类型的值,而且可以包含任意数量的值

// 写法一
(value1, value2)
// 写法二
(key1: value1, key2: value2)

key时通过key访问,没有时通过下标索引访问

let person1 = ("John", 30)
let name1 = person1.0 

let person2 = (name: "John", age: 30)
let name2 = person2.name

语法

\():字符串插值语法

\()用于将变量、常量、表达式或其他值嵌入到字符串字面量中,以创建一个新的字符串。这允许在字符串中包含变量或表达式的值,使字符串更加动态和可变

guard 语句

guard语句是Swift中用于执行条件检查并提前退出函数、方法或循环的结构之一。它通常与else子句一起使用,用于在条件不满足时执行特定的操作

guard condition else {

}

闭包

Swift中的闭包通常表示为用花括号{}包裹的一段代码块。这个代码块可以接受参数、返回值,以及在其中执行特定的操作

闭包是一种自包含的功能块,可以在代码中传递和引用,也可以在需要时执行

{ (parameters) -> ReturnType in
    // 闭包体,执行特定的操作
}

闭包作为参数传入函数,能使得函数更灵活、更通用。闭包在作为函数的参数传入时,可以将闭包的闭包体约等于是函数的函数体

尾随闭包:如果函数的最后一个参数是闭包类型,可以将闭包表达式写在函数调用的圆括号外部,作为函数调用的一部分

补充

  • 闭包的类型实际上是一种函数类型
  • 闭包表达式定义了函数的输入参数、返回值和执行体,以及其他相关的逻辑
  • 一个闭包的声明和初始化
    • var myClosure: (Int, Int) -> Int = { (a, b) in return a + b }

协议

Swift中的协议概念类似于其他编程语言中的接口(interface)概念。协议定义了一组方法属性其他功能的抽象规范,但不提供它们的具体实现。采纳(遵循)协议的结构体枚举需要提供协议要求的具体实现,就像其他编程语言中的类需要实现接口定义的方法一样

协议定义

协议通过protocol关键字来定义

protocol MyProtocol {
    // 协议要求的方法和属性定义在这里
}

类型采纳协议

结构体枚举可以采纳一个或多个协议,以表示它们提供了协议要求的功能。采纳协议使用class/struct/enum 类型名称: 协议名称的声明形式

struct MyStruct: MyProtocol {
    // 实现协议要求的具体功能
}

// 一个类型可以采纳多个协议,通过逗号分隔
struct MyStruct: Protocol1, Protocol2 {
    // 实现协议1和协议2的要求
}

协议扩展

协议扩展可以为协议要求提供默认方法和属性的实现,这使得采纳协议的类型可以选择性地使用这些默认实现,而无需在每个类型中重复实现相同的代码

// 定义一个协议
protocol MyProtocol {
    func doSomething()
}

// 为协议提供默认实现
extension MyProtocol {
    func doSomething() {
        // 函数体
    }
}

// 采纳协议的类型可以选择性地使用默认实现
struct MyStruct: MyProtocol {
    // 不需要重复实现 doSomething 方法
}

let myStruct = MyStruct()
myStruct.doSomething()

协议委托

协议常用于实现委托模式(Delegate Pattern)委托模式是一种设计模式,通过采纳协议来将对象的某些功能委托给其他对象,其中一个对象(委托对象)将自身设置为另一个对象(代理对象)的委托,代理对象可以执行委托对象定义的方法,从而实现解耦和可扩展性

// 定义一个协议,表示委托功能
protocol MyDelegate {
    func didPerformAction()
}

// 定义一个类,包含委托属性
class MyClass {
    var delegate: MyDelegate?

    func performAction() {
        // 执行某个操作,当操作完成后,通知委托对象
        delegate?.didPerformAction()
    }
}

// 实现委托协议的类
class MyDelegateClass: MyDelegate {
    func didPerformAction() {
        print("Action performed by delegate")
    }
}

let myClass = MyClass()
let myDelegateClass = MyDelegateClass()

// 设置委托对象
myClass.delegate = myDelegateClass

// 执行操作,并委托给委托对象处理
myClass.performAction() 

小结

语言是基础,你可能会由于各种原因接触到多种语言,但是打牢基础是无论做什么都需要遵循的准则。对于编程,我对打牢语言基础的感悟便是掌握牢固了才能看懂代码~