跨境派

跨境派

跨境派,专注跨境行业新闻资讯、跨境电商知识分享!

当前位置:首页 > 工具系统 > 选词工具 > 想学 Swift?Swift 从入门到进阶,这一篇就够了!!!

想学 Swift?Swift 从入门到进阶,这一篇就够了!!!

时间:2024-05-04 15:01:20 来源:网络cs 作者:康由 栏目:选词工具 阅读:

标签: 入门 

一、Swift 是什么

Swift 是一门现代、高效且多范式的编程语言,专门用于开发 iOS、macOS、watchOS 和 tvOS 应用程序。它的诞生是为了解决 Objective-C 在某些方面的限制,并提供更直观、安全和强大的编码方式。

Swift 具有以下特点:

易读易写:注重可读性,代码更接近自然语言,使开发者能够更快速地理解和编写代码。安全性:引入了类型推断、空值处理和内存管理等特性,减少了程序崩溃和内存泄漏的可能性。高性能:设计时考虑了性能,与 C 和 Objective-C 相比,它通常更快速,有助于构建响应迅速的应用程序。现代特性:提供了诸如闭包、元组、泛型和模式匹配等现代编程特性,帮助开发者更优雅地解决问题。多范式:Swift 支持面向对象编程、函数式编程和协议导向编程等多种编程范式,使得代码更灵活且易于扩展。开源:Swift 是开源的,这意味着开发者可以参与到语言的演进和改进中,共同构建一个更好的编程生态。丰富的生态系统:Swift 拥有庞大的社区和丰富的第三方库,使开发者能够快速构建复杂的应用程序。

综合来看,Swift 是一个注重开发效率、代码质量和性能的现代编程语言,适合于构建各种规模的 iOS 和 macOS 应用。无论是初学者还是有经验的开发者,都能从 Swift 中获得丰富的开发体验。

接下来分为三部分来介绍 Swift,基础语法 / 高级语言特性 / 多范式。

二、Swift 基础语法

变量和常量

使用 var 关键字来声明变量,使用 let 关键字来声明常量。变量是可以修改的,而常量则是不可修改的。例:

var message = "Hello, world!"message = "Welcome to Swift!" // 可以修改变量的值let name = "Swift"name = "Objective-C" // 常量的值不可修改,会报编译错误

常量的性能更好,并且带来确定性,通常不知道用哪种的时候,就先定义为 let 即可。

数据类型

常用的数据类型包括:

Int: 整数类型,例如:let age: Int = 18Double 和 Float: 浮点数类型,例如:let price: Double = 3.99Bool: 布尔类型,例如:let isFinished: Bool = trueString: 字符串类型,例如:let message: String = "Hello, world!"

数组和字典

数组是一个有序的集合,字典是一个无序的集合。例:

var fruits = ["apple", "banana", "orange"] // 数组fruits.append("pear") // 添加一个元素到数组print(fruits) // 输出:["apple", "banana", "orange", "pear"]var scores = ["Tom": 90, "Jerry": 80, "Lucy": 85] // 字典scores["Mary"] = 95 // 添加一个键值对到字典print(scores) // 输出:["Tom": 90, "Jerry": 80, "Lucy": 85, "Mary": 95]

控制流

常用的控制流语句包括:if/elsefor-inwhileswitch。例:

let score = 80if score >= 90 {    print("优秀")} else if score >= 80 {    print("良好")} else if score >= 70 {    print("中等")} else {    print("不及格")}for fruit in fruits {    print(fruit)}var i = 0while i < 10 {    print(i)    i += 1}switch score {case 90...100:    print("优秀")case 80..<90:    print("良好")case 70..<80:    print("中等")default:    print("不及格")}

延迟加载

只有在首次访问属性时,才会执行初始化操作。可以通过 lazy 关键字来实现。例:

class FileManager {    lazy var fileCount: Int = {        // 执行一些复杂的初始化操作        return 100    }()}

属性观察器

允许你在属性值即将发生变化或已经发生变化时,执行特定的代码。它可以帮助你在属性状态变化时进行逻辑处理。
使用 willSet 观察器可以在属性值即将被赋新值前执行代码,而使用 didSet 观察器可以在属性值已经被赋新值后执行代码。例:

class Student {    var score: Double = 0 {        willSet {            print("值即将被更新为 \(newValue)")        }        didSet {            print("值已经被更新为 \(score)")        }    }}

可选类型

可选类型是 Swift 中一个重要的概念,它允许我们在变量中存储值或者一个特殊的值 nil,表示没有值。可选类型在处理可能为空的值时非常有用,可以帮助我们避免潜在的运行时错误。

1. 声明可选类型:
在 Swift 中,你可以使用 ? 来将一个类型声明为可选类型。例如:

var optionalInt: Int?

这里的 optionalInt 是一个可选的整数类型,它可以存储整数值,也可以存储 nil

2. 使用可选类型:
使用可选类型时,需要考虑到可能存在值为空的情况。可以使用可选绑定来判断可选类型是否包含值,并安全地进行访问。例:

if let value = optionalInt {    print("值是 \(value)")} else {    print("值是 nil")}

3. 强制解包:
当你确定一个可选类型一定有值时,可以使用强制解包(force unwrapping)来访问其值。但要小心,如果可选类型实际上是 nil,则强制解包会导致运行时错误,例:

let intValue: Int? = 42let unwrappedValue = intValue! // 强制解包print("解包后的值是 \(unwrappedValue)")

4. 隐式解包可选类型:
有些情况下,你可能在声明变量时就确定它一定会有值,但仍将其声明为可选类型。这时可以使用隐式解包可选类型,它在使用时会自动解包。例:

var implicitlyUnwrapped: String! = "Hello"print("解包后的值是 \(implicitlyUnwrapped)")

5. 可选链
当模型嵌套时,我们不必进行多层的判空操作,可选字段后加 ? 即可,例:

struct Car {    var brand: String}struct Person {    var car: Car?}// 创建一个有汽车的人let car = Car(brand: "Toyota")let person = Person(car: car)// 使用可选链获取汽车品牌if let carBrand = person.car?.brand {    print("这个人拥有一辆 \(carBrand) 汽车。")} else {    print("这个人没有汽车。")}

6.nil 合并运算符:
当我们希望为可选值提供一个兜底的默认值时可以使用 ?? 运算符,以防可选类型为 nil,例:

let optionalName: String?let greeting = "Hello \(optionalName ?? "World")"

通过以上这些方式,你可以在 Swift 中安全地处理可能为空的值,避免潜在的崩溃。

模式匹配

允许你根据不同的模式,对值进行匹配和提取。这可以用于条件语句、循环、元组、集合等多种情况,使你的代码可读性更强。

1. 基本的模式匹配:
使用 switch 语句时,可以在不同的 case 中对值进行模式匹配。例:

let number = 5switch number {case 0:    print("It's zero")case 1...5:    print("It's between 1 and 5")default:    print("It's something else")}

在条件语句中,可以使用 if case 来进行模式匹配,例:

let age = 25if case 18...35 = age, age >= 21 {    print("Young adult")}

for-in 循环可以遍历区间、集合和序列。通过 case 子句可以指定元素的类型和条件,例:

let numbers: [Any] = [1, 2, "three", 4, "five"]for case let number as Int in numbers {    print("Number: \(number)")}

2. 元组的模式匹配:
你可以使用元组来进行更复杂的模式匹配,同时匹配多个值。例如:

let point = (2, 3)switch point {case (0, 0):    print("Origin")case (_, 0):    print("On x-axis")case (0, _):    print("On y-axis")default:    print("Somewhere in space")}

3. 可选类型的模式匹配:
模式匹配也可以用于可选类型。使用 if case let 来同时匹配并提取可选类型中的值:

let optionalName: String? = "Alice"if case let name? = optionalName {    print("Hello, \(name)")} else {    print("Hello, Guest")}

错误处理

错误处理是在 Swift 中处理潜在错误情况的一种方式。与其他语言的异常机制不同,Swift 使用错误(Error)类型来表示错误,提供了一种更具有类型安全性和可读性的错误处理方式。

1. 定义和抛出错误:
你可以定义一个符合 Error 协议的类型来表示错误,然后使用 throw 关键字抛出错误。例:

enum FileError: Error {    case notFound    case permissions}func openFile(at path: String) throws {    if path.isEmpty {        throw FileError.notFound    }    // 打开文件的逻辑}

2. 错误处理:
在调用可能会抛出错误的函数时,使用 do-catch 块来捕获和处理错误。例:

do {    try openFile(at: "myfile.txt")    print("File opened successfully")} catch FileError.notFound {    print("File not found")} catch FileError.permissions {    print("Permission denied")} catch {    print("An error occurred: \(error)")}

3. 使用 try? 和 try!: try? 用于将抛出错误的表达式转换为可选类型,如果出错则返回 niltry! 则表示你确定不会出错,但如果出错会导致运行时错误。例:

if let file = try? openFile(at: "myfile.txt") {    print("File opened: \(file)")}let file = try! openFile(at: "myfile.txt")print("File opened: \(file)")

闭包

闭包是 Swift 中的一种功能强大的特性,它允许你将一段代码作为值传递和存储,以便在需要时执行。闭包可以作为参数传递给函数,也可以作为函数的返回值。在函数式编程中,闭包被广泛用于实现函数的参数化和灵活的逻辑组合。

1. 闭包表达式:
闭包表达式是一种更简洁的定义闭包的方式,通常使用在函数调用中。一个闭包表达式包括参数、箭头(->)和闭包体。例如:

let add: (Int, Int) -> Int = { (a, b) in    return a + b}let result = add(3, 5) // 结果为 8

2. 尾随闭包:
当闭包是函数的最后一个参数时,可以使用尾随闭包语法。这使得函数调用更具可读性。示例:

func performOperation(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) {    let result = operation(a, b)    print("Result: \(result)")}performOperation(4, 2) { $0 * $1 } // 输出:Result: 8

3. 高阶函数:
Swift 提供了许多高阶函数,如 mapfilterreduce,它们接受闭包作为参数,用于对集合进行变换、过滤和合并操作。示例:

let numbers = [1, 2, 3, 4, 5]let doubled = numbers.map { $0 * 2 } // 结果为 [2, 4, 6, 8, 10]let even = numbers.filter { $0 % 2 == 0 } // 结果为 [2, 4]let sum = numbers.reduce(0, +) // 结果为 15

4. 捕获值:
闭包可以捕获其上下文中的值,即使在上下文不再存在时也可以访问。

func makeIncrementer(incrementAmount: Int) -> () -> Int {    var total = 0    let incrementer: () -> Int = {        total += incrementAmount        return total    }    return incrementer}let incrementByTwo = makeIncrementer(incrementAmount: 2)print(incrementByTwo()) // 输出 2print(incrementByTwo()) // 输出 4

以上就是关于基础语法的部分,介绍了可选类型、模式匹配、错误处理、闭包等,虽然是基础,但可以看到 Swift 代码的简洁,接下来将介绍更多高级语言特性。

三、Swift 高级语言特性

泛型

泛型允许我们将函数或类中的具体类型交给外部来决定,这样能实现更通用的能力,接下来用几个例子来详细说明。

// 泛型函数示例func swap<T>(_ a: inout T, _ b: inout T) {    let temp = a    a = b    b = temp}var num1 = 5, num2 = 10swap(&num1, &num2)var str1 = "Hello", str2 = "World"swap(&str1, &str2)

这个示例展示了一个名为 swap 的泛型函数。泛型参数 T 允许我们在函数中使用不同类型的数据,而不需要为每种类型写不同的函数。无论是整数、字符串还是其他类型,这个函数都可以交换传入的两个值的位置。这样,您可以避免编写重复的代码,同时提高了代码的可重用性。

// 泛型类型示例struct Stack<Element> {    private var items: [Element] = []    mutating func push(_ item: Element) {        items.append(item)    }    mutating func pop() -> Element? {        return items.popLast()    }}var intStack = Stack<Int>()intStack.push(1)intStack.push(2)var stringStack = Stack<String>()stringStack.push("Swift")stringStack.push("is")stringStack.push("fun!")

这个示例定义了一个泛型结构体 Stack<Element>,其中的 Element 是一个占位符,可以是任何类型。通过这个泛型类型,您可以创建适用于不同数据类型的栈(堆栈)结构。这种通用的数据结构可以在许多情况下使用,使代码更灵活和通用。

// 泛型约束示例func findIndex<T: Equatable>(of valueToFind: T, in array: [T]) -> Int? {    for (index, value) in array.enumerated() {        if value == valueToFind {            return index        }    }    return nil}let numbers = [4, 8, 15, 16, 23, 42]if let index = findIndex(of: 15, in: numbers) {    print("Index of 15: \(index)")} else {    print("Value not found")}

在这个示例中,findIndex 函数接受一个遵循 Equatable 协议的泛型类型 T。这个泛型约束要求传入的类型必须支持相等比较。函数在数组中查找特定值的索引,如果找到则返回索引,否则返回 nil。通过泛型约束,我们可以编写更具通用性的函数,同时确保传入的参数满足特定的条件。

Result Builders

Result Builders 是 Swift 5.4 引入的一个强大特性,它允许您通过自定义 DSL(领域特定语言)来构建更具表现力的数据结构,例如视图层次结构。通过 Result Builders,您可以在代码中创建一种声明式的结构,以更直观的方式表示复杂的数据组合。

@resultBuilderenum MyBuilder {    static func buildBlock(_ components: String...) -> String {        components.joined(separator: " ")    }}@MyBuilderfunc createMessage() -> String {    "Hello,"    "this is"    "a custom"    "result builder!"}let message = createMessage()print(message)// Output: "Hello, this is a custom result builder!"

在这个简单的例子中,我们定义了一个名为 MyBuilder 的 Result Builder。通过 @MyBuilder 声明,我们可以在 createMessage 函数中以 DSL 的形式构建内容。

而这个能力的实现依赖于编译器,编译器识别到 @resultBuilder 会将对应的内容做转换,对于这个例子,编译生成的代码类似于:

enum MyBuilder {    static func buildBlock(_ components: String...) -> String {        components.joined(separator: " ")    }}func createMessage() -> String {    let v1 = "Hello,"    let v2 = "this is"    let v3 = "a custom"    let v4 = "result builder!"    return MyBuilder.buildBlock(v1, v2, v3, v4)}

虽然例子中只使用了一个 buildBlock 方法,实际上 @resultBuilder 还支持 buildOptionalbuildExpressionbuildLimitedAvailabilitybuildArraybuildEither 以应对不同的场景,在这里不做展开。
由于是编译器的能力,所以低版本 iOS 也能用,比如 SwiftUI 最低支持 iOS 13,但实际上 SwiftUI 在 iOS 13 功能有很多缺失,真要应用至少要更高版本,所以商用遥遥无期,但是基于这个能力,也能定制一些 DSL 去减少模版代码,甚至去实现类似 SwiftUI 的声明式 UI。

async/await

async/await 是 Swift 5.5 引入的一种异步编程模型,它旨在简化异步操作的编写和管理,使异步代码更具可读性和可维护性。它允许你以一种类似于同步代码的方式来编写异步任务,而无需显式地编写回调闭包或处理复杂的回调链,先看一个例子:

func fetchUserDetails(userID: Int) async -> UserDetails {    let user = await fetchUser(userID: userID)    let posts = await fetchPosts(userID: userID)    return UserDetails(user: user, posts: posts)}let userDetails = await fetchUserDetails(userID: 123)print(userDetails)

在这个示例中,fetchUserDetails 函数是一个异步函数,它使用 await 关键字来等待两个异步操作:fetchUserfetchPosts。这些异步操作会在后台进行,fetchUserDetails 函数会暂停执行,直到所有异步操作完成。

async 函数可以返回一个遵循 AsyncSequenceAsyncThrowingSequence 协议的对象,也可以返回任何遵循 Task 协议的对象。使用 async 关键字声明的函数可以包含 await 表达式,这些表达式用于等待异步操作的完成。

async 函数中,可以使用 await 关键字来等待一个异步操作的完成。await 表达式会暂停当前函数的执行,直到异步操作完成,然后返回异步操作的结果。

优势和好处:

可读性和可维护性提升: 使用 async/await 可以让异步代码看起来更像是同步代码,减少了回调嵌套和复杂的异步逻辑,从而提高了代码的可读性和可维护性。错误处理更简洁: 使用 async/await 可以更自然地处理异步操作的错误,使用 try/catch 语句来捕获和处理可能的异常。更直观的代码流程: 使用 async/await 可以使代码流程更加直观,有助于开发人员理解和推断异步操作的顺序和关系。

Actor

在 Swift 5.5 中引入的 Actor 模型允许你封装状态,并确保只有一个线程可以访问该状态,从而提高并发代码的安全性和可维护性。

在传统的多线程编程中,多个线程可以同时访问和修改共享数据,导致了数据竞争和错误。而 Actor 模型将状态封装在特定的 Actor 对象内部,限制了对该对象状态的访问,只允许一个线程同时访问该对象,从而避免了竞争条件。

以下是一个使用 Actor 模型的简单示例:

actor BankAccount {    private var balance: Double = 0    func deposit(amount: Double) {        balance += amount    }    func withdraw(amount: Double) {        balance -= amount    }    func getBalance() -> Double {        return balance    }}let account = BankAccount()Task {    await account.deposit(amount: 100)    await account.withdraw(amount: 50)    let balance = await account.getBalance()    print("Account balance: \(balance)")}

在这个示例中,BankAccount 类是一个 Actor,它封装了账户的余额。使用 await 关键字,我们确保了在同一时间只有一个任务可以访问和修改账户的余额,从而避免了竞争条件。

优势和好处:

线程安全: 因为同一时间只有一个线程可以访问 Actor 内部的数据,可以防止一些常见的并发问题,如数据竞争和死锁。简化并发编程: 使用 Actor 模型,你无需显式地编写锁或互斥体来保护共享数据,从而减少了并发编程的复杂性。更高的性能: 由于只有一个线程可以访问 Actor 内部的状态,不需要频繁地进行锁竞争,可以提高并发代码的性能。

四、Swift 多范式

面向对象编程

面向对象编程(Object-Oriented Programming,简称 OOP)是一种软件开发的编程范式,它将数据和操作数据的方法组合成对象,从而实现了代码的模块化、可维护性和可重用性。在 Swift 中,面向对象编程是一个重要的编程思想,通过类、结构体和枚举来实现。

1. 类(Class):
类是一种引用类型,它可以封装属性和方法,以创建一个具有特定功能和行为的对象。类支持继承,可以从另一个类派生出新的类,并在派生类中添加、修改或重写属性和方法。示例:

class Person {    var name: String    var age: Int    init(name: String, age: Int) {        self.name = name        self.age = age    }    func sayHello() {        print("Hello, my name is \(name)")    }}let person = Person(name: "Alice", age: 30)person.sayHello()

2. 结构体(Struct):
结构体是一种值类型,它也可以封装属性和方法,但与类不同,结构体在传递时总是进行值复制。结构体适合用于简单的数据封装,如坐标、颜色等。示例:

struct Point {    var x: Int    var y: Int}var origin = Point(x: 0, y: 0)var otherPoint = originotherPoint.x = 10print("Origin: \(origin.x), \(origin.y)") // 输出 "Origin: 0, 0"

3. 枚举(Enum):
枚举是一种自定义的数据类型,它包含一组相关的值。枚举可以带有关联值,用于表示更复杂的数据。枚举在 Swift 中可以拥有方法,使其更加灵活。示例:

enum Direction {    case north    case south    case east    case west    func description() -> String {        switch self {        case .north:            return "North"        case .south:            return "South"        case .east:            return "East"        case .west:            return "West"        }    }}let direction = Direction.northprint("Direction: \(direction.description())") // 输出 "Direction: North"

函数式编程

函数式编程也是一种编程范式,它将计算过程视为函数应用的组合,强调数据不可变性和无副作用,并使用高阶函数来进行抽象和组合操作。

核心概念

函数是一等公民:函数可以作为参数传递给其他函数,也可以作为返回值。高阶函数:高阶函数是能够接受一个或多个函数作为参数,这使得函数可以被抽象、组合和复用。纯函数:纯函数是指函数的输出仅由输入决定,没有副作用。相同的输入总是产生相同的输出。

系统提供的高阶函数

map:映射是指将一个函数应用于集合中的每个元素,创建一个新的集合:

let numbers = [1, 2, 3, 4, 5]let squared = numbers.map { $0 * $0 } // [1, 4, 9, 16, 25]

filter:过滤操作基于给定的条件从集合中选择特定的元素:

let even = numbers.filter { $0 % 2 == 0 } // [2, 4]

reduce:折叠操作将一个初始值和一个函数作用于集合中的元素,将它们合并为一个值:

let sum = numbers.reduce(0, +) // 15

也可以链式调用,例如:

let numbers = [1, 2, 3, 4, 5]let sum = numbers    .map { $0 * $0 } // [1, 4, 9, 16, 25]    .filter { $0 % 2 == 0 } // [4, 16]    .reduce(0, +) // 20

除了上面三种外,还有很多高阶函数,例如 flatMapcompactMapsortedforEachzipprefix(while:)first(where:)allSatisfy 等,不一一展开。

可以看到这些高阶函数抽离出了一套处理数据的模式,但是具体的规则则由我们传入的函数决定,相比遍历去处理可以省去大量的代码,而且易于理解,其它一些关于函数式编程的实践在 Swift 中由于不太常见就不过多赘述。

面向协议编程

协议允许您定义一组方法和属性的契约,以便不同类型(类、结构体和枚举)可以遵循这些契约并提供相应的实现。这为代码重用和模块化提供了强大的工具,同时也促进了更好的代码组织和扩展性。

1. 协议与继承的结合:
协议与继承结合,可以在保留类层次结构的同时,实现多态性和共享行为,例:

protocol Sound {    func makeSound()}class Animal {    func eat() {        print("Animal is eating")    }}class Dog: Animal, Sound {    func makeSound() {        print("Dog barks")    }}class Cat: Animal, Sound {    func makeSound() {        print("Cat meows")    }}let dog: Sound = Dog()let cat: Sound = Cat()dog.makeSound() // Dog barkscat.makeSound() // Cat meows

在这个示例中,Sound 协议定义了一个 makeSound() 方法,Animal 类具有 eat() 方法。DogCat 类既继承自 Animal,又遵循了 Sound 协议,使它们能够实现多态性,分别发出不同的声音。

2. 协议与扩展的结合:

通过为遵循协议的类型添加扩展,可以为这些类型提供协议所需的实现,同时保持类型的原始定义不变,例:

protocol Colorful {    var color: String { get }}extension Dog: Colorful {    var color: String {        return "Brown"    }}extension Cat: Colorful {    var color: String {        return "Gray"    }}let colorfulDog = Dog()let colorfulCat = Cat()print(colorfulDog.color) // Brownprint(colorfulCat.color) // Gray

在这个示例中,Colorful 协议要求类型具有 color 属性。通过为 DogCat 类添加扩展,我们为它们提供了符合协议的实现,同时不改变原始类型的定义。

3. 协议与泛型的结合:

协议与泛型结合,可以创建适用于多种类型的通用行为规范。

protocol Stack {    associatedtype Element    mutating func push(_ item: Element)    mutating func pop() -> Element?}struct IntStack: Stack {    private var items: [Int] = []    mutating func push(_ item: Int) {        items.append(item)    }    mutating func pop() -> Int? {        return items.popLast()    }}var stack = IntStack()stack.push(1)stack.push(2)print(stack.pop()) // Output: Optional(2)

在这个示例中,Stack 协议使用了泛型,通过关联类型 Element 来定义栈的通用操作。IntStack 结构体遵循了 Stack 协议,实现了针对整数类型的栈操作。这使得我们可以为不同类型创建通用的栈实现。

结合协议、继承、扩展和泛型,我们创造了更高层次的代码抽象、重用和模块化,使我们能够更灵活地构建适用于不同情景的通用组件。

多范式的结合

考虑一个场景:你正在开发一个社交媒体应用,需要处理用户的帖子和评论。我们可以使用协议定义通用的功能,然后通过面向对象和函数式编程来实现和扩展这些功能。

协议定义(面向协议编程):

protocol Postable {    var author: String { get }    var content: String { get }    var timestamp: Date { get }    func display()}struct Post: Postable {    let author: String    let content: String    let timestamp: Date    func display() {        print("Post by \(author) at \(timestamp):\n\(content)")    }}struct Comment: Postable {    let author: String    let content: String    let timestamp: Date    func display() {        print("Comment by \(author) at \(timestamp):\n\(content)")    }}

面向对象编程:

class User {    let username: String    var posts: [Postable] = []    init(username: String) {        self.username = username    }    func createPost(content: String) {        let post = Post(author: username, content: content, timestamp: Date())        posts.append(post)    }    func displayPosts() {        for post in posts {            post.display()        }    }}let user = User(username: "John")user.createPost(content: "Hello, world!")user.createPost(content: "Swift is awesome!")user.displayPosts()

函数式编程:

extension Array where Element == Postable {    func sortByTimestamp() -> [Postable] {        return self.sorted { $0.timestamp < $1.timestamp }    }}let comments = [    Comment(author: "Alice", content: "Great post!", timestamp: Date().addingTimeInterval(-3600)),    Comment(author: "Bob", content: "Nice work!", timestamp: Date().addingTimeInterval(-1800))](user.posts + comments)    .sortByTimestamp()    .forEach { $0.display() }

在这个示例中,我们首先定义了一个 Postable 协议,然后分别用 PostComment 结构体实现了这个协议。通过面向对象编程,我们创建了一个 User 类来管理用户和帖子,并展示了用户创建帖子和展示帖子的方式。然后,通过函数式编程,我们扩展了数组的功能,实现了按时间戳排序的功能。

虽然这是一个简单的例子,但更多的是想展示不同的编程方式在不同的场景下能发挥不同的优势和可能性,最终则是提高代码的可读性、开发效率以及我们开发过程中的乐趣。

结语

最后想随便聊聊我自己的想法,我相信时至今日没人会质疑 Swift 相比 OC 的先进,无论是安全性、开发效率、可读性都是更好的选择,感觉没必要再强调,主要制约我们的是迁移/混编以及学习的成本。

这其中确实也会涉及到很多混编的问题,抛开工程上的问题不谈,开发中主要面临的混编问题大多是 OC 调用 Swift 的问题,因为 Swift 包含大量新增的语言特性,例如在 Swift 中最基本的 struct、enum,在 OC 中就完全看不到,因为并不存在可以平替的东西。

反过来 Swift 基本可以调用 OC 的所有能力(除了宏,主要是编译过程关于宏这里有差异,但是宏虽然用的多,但代码量并不大,也可以用其它方式实现),所以虽然很多基础能力是从中台辐射到业务,但其实 Swift 的迁移更适合从业务包围中台,因为业务是 Swift 依然可以使用中台 OC 的代码,可以更平滑的迁移,但是反过来就有很多限制。

总的来说,无论是从语言本身的优劣还是从官方的态度来看,Swift 就是苹果生态的主要开发语言,我们迟早会转到 Swift 开发,那不如就从现在开始学习吧!借用冰球明星韦恩格雷茨基的一句名言:要向着冰球运动的方向滑,而不是它现在的位置…

本文链接:https://www.kjpai.cn/news/2024-05-04/164781.html,文章来源:网络cs,作者:康由,版权归作者所有,如需转载请注明来源和作者,否则将追究法律责任!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。

文章评论