一、函数与闭包核心特性
1. 柯里化 (Currying)
重点说明:
- 核心定义:将接收多个参数的函数,拆解为一系列单参数函数,每个函数返回下一个函数,实现分步传参、参数固化与函数复用,是Swift函数式编程的核心特性之一。
- 注意:Swift 3+ 移除了原生柯里化语法糖,需通过函数嵌套手动实现。
代码示例:
swift
// 传统多参数函数
func addTwoNum(_ a: Int, _ b: Int) -> Int {
a + b
}
// 柯里化实现:分步接收参数
func curryingAdd(_ a: Int) -> (Int) -> Int {
return { b in a + b }
}
// 使用:固化参数生成新函数
let add10 = curryingAdd(10)
let result1 = add10(5) // 15
let result2 = add10(20) // 30
// 多参数柯里化扩展
func curryingThreeParams(_ a: Int) -> (Int) -> (Int) -> Int {
return { b in
return { c in a + b + c }
}
}
let finalResult = curryingThreeParams(5)(3)(2) // 10
2. @autoclosure 自动闭包
重点说明:
- 核心定义:将传入的表达式自动封装为无参闭包,实现延迟执行,仅当闭包被调用时才执行表达式,避免不必要的性能开销。
- 核心场景:空合运算符
??底层基于@autoclosure实现,适用于条件判断中的默认值处理。 - 注意:仅支持无参闭包,禁止滥用导致可读性下降。
代码示例:
swift
// 传统闭包:需手动写闭包语法
func logIfFalse(_ condition: Bool, errorMsg: () -> String) {
if !condition { print(errorMsg()) }
}
logIfFalse(1 > 2, errorMsg: { "条件错误" })
// @autoclosure 自动封装表达式
func autoLogIfFalse(_ condition: Bool, errorMsg: @autoclosure () -> String) {
if !condition { print(errorMsg()) }
}
// 调用时直接写表达式,自动封装为闭包
autoLogIfFalse(1 > 2, errorMsg: "条件错误")
// 自定义??运算符(底层基于@autoclosure)
func customNilCoalescing<T>(optional: T?, defaultValue: @autoclosure () -> T) -> T {
switch optional {
case .some(let value): return value
case .none: return defaultValue()
}
}
let optionalStr: String? = nil
let finalStr = customNilCoalescing(optional: optionalStr, defaultValue: "默认值")
3. @escaping 逃逸闭包
重点说明:
- 核心定义:闭包作为函数参数,在函数返回后才会被执行,称为逃逸闭包,必须用
@escaping标记。 - 核心场景:异步网络请求、GCD延时操作、函数内属性存储闭包。
- 注意:逃逸闭包内必须显式引用
self,需警惕循环引用风险;非逃逸闭包默认无循环引用风险。
代码示例:
swift
import Foundation
// 非逃逸闭包:函数执行结束前完成执行
func syncTask(closure: () -> Void) {
print("任务开始")
closure()
print("任务结束")
}
// 逃逸闭包:函数返回后才执行,必须标记@escaping
var globalClosure: (() -> Void)?
func asyncTask(closure: @escaping () -> Void) {
print("异步任务开始")
// 1. 存储到全局变量,函数返回后执行
globalClosure = closure
// 2. 异步延时执行
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
closure()
}
print("异步函数执行结束")
}
// 调用
asyncTask {
print("逃逸闭包执行")
}
4. 函数基础增强特性
重点说明:
- 方法嵌套:函数内部可定义子函数,封装内部逻辑,实现作用域隔离。
- 可变参数:用
...标记,接收0个或多个同类型参数,函数内自动转为数组使用。 - 默认参数:给参数设置默认值,调用时可省略该参数,提升灵活性。
- inout参数:输入输出参数,可在函数内修改外部变量的值。
代码示例:
swift
// 1. 方法嵌套
func calculateTotalPrice(price: Double, count: Int) -> Double {
// 嵌套函数:仅外层函数可访问
func calculateDiscount(_ total: Double) -> Double {
if total > 1000 { return total * 0.8 }
else if total > 500 { return total * 0.9 }
return total
}
let total = price * Double(count)
return calculateDiscount(total)
}
let finalPrice = calculateTotalPrice(price: 200, count: 6) // 960
// 2. 可变参数
func sumNumbers(_ numbers: Int...) -> Int {
numbers.reduce(0, +)
}
let sum = sumNumbers(1,2,3,4,5) // 15
// 3. 默认参数
func userInfo(name: String, age: Int = 18, city: String = "未知") {
print("姓名:\(name),年龄:\(age),城市:\(city)")
}
userInfo(name: "张三") // 自动使用默认值
// 4. inout参数
func swapValue<T>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}
var num1 = 10, num2 = 20
swapValue(&num1, &num2) // num1=20, num2=10
二、协议与面向协议编程
1. protocol 方法的 mutating 声明
重点说明:
- 核心定义:Swift的protocol可被class、struct、enum实现,struct和enum是值类型,默认无法在实例方法中修改自身属性,必须用
mutating修饰方法。 - 最佳实践:协议方法若会修改实例自身,必须声明
mutating,保证struct/enum的实现兼容性;class实现时可忽略该关键字。
代码示例:
swift
// 正确协议定义:声明mutating
protocol Countable {
mutating func addCount()
mutating func resetCount()
}
// struct实现:必须保留mutating
struct Counter: Countable {
private(set) var count: Int = 0
mutating func addCount() { count += 1 }
mutating func resetCount() { count = 0 }
}
// class实现:可忽略mutating
class ClassCounter: Countable {
private(set) var count: Int = 0
func addCount() { count += 1 }
func resetCount() { count = 0 }
}
// 使用
var structCounter = Counter()
structCounter.addCount()
print(structCounter.count) // 1
2. Sequence 与 IteratorProtocol
重点说明:
- 核心定义:Swift中
for...in循环的底层基于Sequence协议,实现Sequence必须先实现IteratorProtocol协议,定义元素的遍历规则。 - 核心关系:
IteratorProtocol负责生成元素,通过next()方法返回下一个元素,nil表示遍历结束;Sequence负责创建迭代器,提供遍历能力。
代码示例:
swift
// 1. 实现迭代器协议:反向遍历迭代器
struct ReverseIterator<T>: IteratorProtocol {
typealias Element = T
private var elements: [T]
private var currentIndex: Int
init(elements: [T]) {
self.elements = elements
self.currentIndex = elements.count - 1
}
mutating func next() -> T? {
guard currentIndex >= 0 else { return nil }
let element = elements[currentIndex]
currentIndex -= 1
return element
}
}
// 2. 实现Sequence协议:提供遍历能力
struct ReverseSequence<T>: Sequence {
private var elements: [T]
init(elements: [T]) {
self.elements = elements
}
func makeIterator() -> ReverseIterator<T> {
ReverseIterator(elements: elements)
}
}
// 使用:支持for...in循环
let numbers = [1,2,3,4,5]
let reverseSequence = ReverseSequence(elements: numbers)
for num in reverseSequence {
print(num) // 输出:5 4 3 2 1
}
3. associatedtype 关联类型
重点说明:
- 核心定义:协议中的占位类型,协议实现时才指定具体类型,实现协议的泛型能力,是面向协议编程的核心特性。
- 核心场景:协议中需要使用多个关联的泛型类型,保证类型安全,避免
Any类型滥用。
代码示例:
swift
// 带关联类型的协议
protocol Stackable {
// 定义关联类型,实现时指定具体类型
associatedtype Element
mutating func push(_ element: Element)
mutating func pop() -> Element?
var topElement: Element? { get }
}
// 泛型实现:自动推断关联类型
struct GenericStack<T>: Stackable {
private var elements: [T] = []
mutating func push(_ element: T) {
elements.append(element)
}
mutating func pop() -> T? {
elements.popLast()
}
var topElement: T? {
elements.last
}
}
// 使用
var stringStack = GenericStack<String>()
stringStack.push("Swift")
stringStack.push("iOS")
print(stringStack.topElement ?? "空") // iOS
4. Protocol Extension 协议扩展
重点说明:
- 核心定义:给协议添加扩展,提供方法、计算属性的默认实现,是Swift实现可选协议、功能横向复用、面向协议编程的核心。
- 核心价值:无需继承即可给多个类型添加统一功能;实现协议可选方法,无需
@objc限制,支持struct/enum。
代码示例:
swift
// 协议定义
protocol Runnable {
func run()
func stop()
}
// 协议扩展:提供默认实现
extension Runnable {
func run() { print("默认的跑步行为") }
func stop() { print("默认的停止行为") }
// 扩展新增方法,所有遵循者自动获得
func warmUp() { print("热身准备") }
}
// 遵循协议,无需实现任何方法,自动获得默认实现
struct Person: Runnable {}
// 重写默认实现
class Car: Runnable {
func run() { print("汽车启动行驶") }
func stop() { print("汽车刹车停止") }
}
// 使用
let person = Person()
person.warmUp() // 热身准备
person.run() // 默认的跑步行为
let car = Car()
car.run() // 汽车启动行驶
car.warmUp() // 热身准备
// 实现可选协议:替代@objc可选方案
protocol OptionalProtocol {
func necessaryMethod() // 必须实现
func optionalMethod() // 可选,扩展提供默认实现
}
extension OptionalProtocol {
func optionalMethod() {}
}
// 只需实现必须方法,可选方法自动获得默认实现
struct ProtocolImplementer: OptionalProtocol {
func necessaryMethod() {
print("必须实现的方法")
}
}
三、可选类型与安全编程
1. 可选链 Optional Chaining
重点说明:
- 核心定义:通过
?在可选值上链式调用属性、方法、下标,可选值为nil时,整个链式调用直接返回nil,不会崩溃,替代多层强制解包。 - 注意:可选链的返回值始终是可选类型,即使调用的属性/方法返回非可选类型。
代码示例:
swift
// 定义嵌套模型
class Address {
var city: String?
var detail: String?
}
class User {
var name: String
var address: Address?
init(name: String) {
self.name = name
}
}
// 可选链使用
var user: User? = User(name: "张三")
// 1. 链式访问属性
let city = user?.address?.city
// 类型:String?,任意一层为nil直接返回nil
print(city ?? "地址为空") // 地址为空
// 2. 安全赋值:可选值不为nil时才执行
user?.address = Address()
user?.address?.city = "成都"
let newCity = user?.address?.city
print(newCity ?? "地址为空") // 成都
// 3. 多层解包
if let detail = user?.address?.detail {
print("详细地址:\(detail)")
}
2. 多重 Optional
重点说明:
- 核心定义:Optional类型本身可作为另一个Optional的包装值,形成嵌套可选类型(如
String??),本质是Optional枚举的嵌套。 - 核心坑点:直接判空
!= nil只能判断外层是否为nil;字面量nil赋值给多重可选是外层为nil,把nil的可选值赋值给多重可选是外层.some、内层.none。
代码示例:
swift
// 多重可选的核心区别
var aNil: String? = nil // 单层nil
var anotherNil: String?? = aNil // 外层.some,内层.none
var literalNil: String?? = nil // 外层直接.none
// 判空区别
if anotherNil != nil {
print("anotherNil 外层不为nil") // 会执行
}
if literalNil != nil {
print("literalNil 外层不为nil") // 不会执行
}
// 正确解包方式
// 1. 多层if let
if let outer = anotherNil, let inner = outer {
print("解包成功:\(inner)")
} else {
print("内层为nil")
}
// 2. 空合运算符直接解包
let finalValue = anotherNil ?? "默认值"
print(finalValue) // 默认值
// 3. switch模式匹配
switch anotherNil {
case .some(.some(let value)):
print("有值:\(value)")
case .some(.none):
print("外层有值,内层nil")
case .none:
print("外层直接nil")
}
3. Optional Map 与 flatMap
重点说明:
map:对可选值的非nil值进行转换,nil则直接返回nil,闭包返回非可选类型。flatMap:用于转换后仍是可选值的场景,自动解包一层,避免生成多重可选。
代码示例:
swift
// Optional Map
let optionalNum: Int? = 5
let mapResult = optionalNum.map { num in
"数字:\(num)"
}
// 类型:String?,optionalNum为nil时直接返回nil
print(mapResult ?? "空") // 数字:5
// flatMap:避免多重可选
let strNum: String? = "123"
// map转换后生成Int??双重可选
let mapDoubleOptional = strNum.map { Int($0) }
// flatMap自动解包一层,返回Int?
let flatMapResult = strNum.flatMap { Int($0) }
print(flatMapResult ?? "转换失败") // 123
4. ?? 空合运算符
重点说明:
- 核心定义:可选值非nil则解包返回,nil则返回后面的默认值,底层基于
@autoclosure实现,默认值延迟执行。 - 核心价值:替代三目运算符,简化可选值的默认值处理,支持链式使用。
代码示例:
swift
// 基础使用
let optionalStr: String? = "Swift"
let result = optionalStr ?? "默认值"
// 类型:String,非可选
print(result) // Swift
// 链式使用
let level1: String?? = nil
let level2: String?? = "第二层值"
let finalResult = level1 ?? level2 ?? "最终默认值"
print(finalResult) // 第二层值
// 延迟执行特性:默认值仅在nil时执行
func getDefaultValue() -> String {
print("执行了默认值方法")
return "默认值"
}
let hasValue: String? = "有值"
let test1 = hasValue ?? getDefaultValue()
// 不会执行getDefaultValue,无打印
四、语法糖与基础类型增强
1. Tuple 多元组
重点说明:
- 核心定义:将多个不同类型的值组合成一个复合值,无需提前定义结构体/类,是轻量级数据组合方案。
- 核心场景:多返回值、变量交换、多值绑定、函数参数简化。
代码示例:
swift
// 1. 基础定义
// 命名元素多元组
let userInfo = (name: "张三", age: 20, city: "成都")
print(userInfo.name) // 张三
print(userInfo.age) // 20
// 2. 变量交换:无需临时变量
var a = 10, b = 20
(a, b) = (b, a)
print(a, b) // 20 10
// 3. 函数多返回值
func calculateStats(_ numbers: [Int]) -> (sum: Int, average: Double, max: Int)? {
guard !numbers.isEmpty else { return nil }
let sum = numbers.reduce(0, +)
let average = Double(sum) / Double(numbers.count)
return (sum, average, numbers.max()!)
}
if let stats = calculateStats([1,2,3,4,5]) {
print("总和:\(stats.sum),平均值:\(stats.average)")
}
2. 自定义操作符
重点说明:
- 核心定义:Swift支持自定义中缀、前缀、后缀操作符,扩展运算符功能,需先声明操作符,再实现对应的函数。
- 注意:避免滥用导致代码可读性下降,自定义操作符需符合语义。
代码示例:
swift
import Foundation
// 1. 自定义正则匹配中缀操作符 =~
infix operator =~: ComparisonPrecedence
func =~ (input: String, pattern: String) -> Bool {
guard let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) else {
return false
}
let range = NSRange(input.startIndex..., in: input)
return regex.firstMatch(in: input, range: range) != nil
}
// 使用:邮箱校验
let mailPattern = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$"
let isMail = "test@example.com" =~ mailPattern
print(isMail) // true
// 2. 自定义前缀平方操作符 **
prefix operator **
prefix func ** (num: Int) -> Int {
num * num
}
let square = **5 // 25
3. 下标 subscript
重点说明:
- 核心定义:给类、结构体、枚举定义下标,通过下标语法快速访问集合元素,支持多参数、重载、只读/读写。
- 核心场景:自定义集合类型、安全数组访问、快捷模型属性访问。
代码示例:
swift
// 安全数组:避免下标越界崩溃
struct SafeArray<T> {
private var elements: [T]
init(elements: [T]) {
self.elements = elements
}
// 基础下标:越界返回nil,不崩溃
subscript(index: Int) -> T? {
get {
guard index >= 0, index < elements.count else { return nil }
return elements[index]
}
set {
guard let newValue = newValue, index >= 0, index < elements.count else { return }
elements[index] = newValue
}
}
// 重载下标:范围访问
subscript(range: ClosedRange<Int>) -> [T] {
let start = max(range.lowerBound, 0)
let end = min(range.upperBound, elements.count - 1)
guard start <= end else { return [] }
return Array(elements[start...end])
}
}
// 使用
let array = SafeArray(elements: [1,2,3,4,5])
print(array[2] ?? "越界") // 3
print(array[10] ?? "越界") // 越界,无崩溃
print(array[1...3]) // [2,3,4]
4. 区间运算符与模式匹配
重点说明:
- 区间运算符:
...闭区间(包含首尾)、..<半开区间(包含首不包含尾),支持单侧区间,用于遍历、切片、范围判断。 - 模式匹配:Swift强大的语法特性,支持元组、可选值、枚举、范围、类型匹配,核心基于
switch,也可用于if case/for case。
代码示例:
swift
// 区间运算符
let numbers = [1,2,3,4,5,6,7,8,9,10]
let slice1 = numbers[2...5] // [3,4,5,6]
let slice2 = numbers[2..<5] // [3,4,5]
let slice3 = numbers[5...] // [6,7,8,9,10]
// 模式匹配:switch范围判断
let score = 85
switch score {
case 0..<60: print("不及格")
case 60..<80: print("及格")
case 80...100: print("优秀")
default: print("无效分数")
}
// 可选值模式匹配
let optionalNum: Int? = 5
if case let num? = optionalNum, num > 0 {
print("正数:\(num)")
}
// for case 遍历匹配
let numArray: [Int?] = [1, nil, 3, nil, 5]
for case let num? in numArray {
print(num) // 输出:1 3 5
}
五、类与结构体初始化规则
1. Designated、Convenience、Required 初始化
重点说明:
- 指定初始化(Designated):类的主初始化方法,必须初始化所有未赋值的存储属性,调用父类的指定初始化方法。
- 便利初始化(Convenience):辅助初始化方法,必须调用同类的指定初始化方法,提供便捷的初始化入口。
- 必须初始化(Required):强制子类必须重写的初始化方法,子类重写时必须加
required,无需override。 - 核心规则:便利初始化必须横向调用,指定初始化必须纵向调用父类方法。
代码示例:
swift
// 父类
class Person {
var name: String
var age: Int
// 指定初始化
init(name: String, age: Int) {
self.name = name
self.age = age
super.init()
}
// 便利初始化
convenience init(name: String) {
self.init(name: name, age: 18)
}
// 必须初始化
required init() {
self.name = "未知"
self.age = 0
super.init()
}
}
// 子类
class Student: Person {
var studentID: String
// 子类指定初始化
init(name: String, age: Int, studentID: String) {
// 先初始化子类属性,再调用父类初始化
self.studentID = studentID
super.init(name: name, age: age)
}
// 重写必须初始化
required init() {
self.studentID = "000000"
super.init()
}
}
2. 可失败初始化(init?)
重点说明:
- 核心定义:初始化方法可返回nil,用
init?()声明,在初始化过程中进行参数校验,校验失败返回nil,中断初始化。 - 注意:Swift 5+ 支持在属性初始化完成前提前返回nil。
代码示例:
swift
class User {
let name: String
let age: Int
init?(name: String, age: Int) {
// 参数校验,失败返回nil
guard !name.isEmpty else { return nil }
guard age >= 0, age <= 150 else { return nil }
// 校验通过,初始化属性
self.name = name
self.age = age
}
}
// 使用
let validUser = User(name: "张三", age: 20) // 非nil
let invalidUser = User(name: "", age: 20) // nil
六、类型系统与核心关键字
1. static 与 class
重点说明:
static:可用于class、struct、enum、protocol,定义的方法/属性不能被子类重写,静态绑定。class:仅用于class类型,定义的方法/计算属性可被子类重写,动态绑定;不能用于存储属性。
代码示例:
swift
class Animal {
// static存储属性:不可重写
static let species = "动物"
// class计算属性:可重写
class var typeName: String { "Animal" }
// static方法:不可重写
static func breathe() { print("动物需要呼吸") }
// class方法:可重写
class func makeSound() { print("动物发出声音") }
}
class Cat: Animal {
// 重写class计算属性
override class var typeName: String { "Cat" }
// 重写class方法
override class func makeSound() { print("猫发出喵喵声") }
}
// 调用
print(Animal.typeName) // Animal
print(Cat.typeName) // Cat
Cat.makeSound() // 猫发出喵喵声
2. 属性观察 willSet / didSet
重点说明:
- 核心定义:监听存储属性的值变化,
willSet在值变化前触发,didSet在值变化后触发,初始化时不会触发,仅赋值时触发。 - 核心场景:数据绑定、值校验、UI更新、状态同步。
代码示例:
swift
class User {
var name: String {
willSet(newName) {
print("即将把名字从\(name)改为\(newName)")
}
didSet(oldName) {
print("已经把名字从\(oldName)改为\(name)")
if name.isEmpty { name = oldName } // 空值恢复
}
}
var age: Int {
didSet {
// 年龄自动修正
if age < 0 { age = 0 }
else if age > 150 { age = 150 }
}
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
// 使用
let user = User(name: "张三", age: 20)
user.name = "李四" // 触发属性观察
user.age = 200 // 自动修正为150
3. lazy 懒加载修饰符
重点说明:
- 核心定义:延迟存储属性的初始化,只有在属性第一次被访问时,才会执行初始化代码,仅执行一次。
- 核心特性:只能用于
var变量,初始化时可访问self,线程不安全。 - 核心场景:耗时初始化、依赖其他属性的初始化、不常用的属性,提升初始化性能。
代码示例:
swift
class DataManager {
// 普通属性:初始化时立即创建
let createTime = Date()
// lazy属性:第一次访问时才初始化
lazy var fileManager: FileManager = {
print("执行fileManager初始化")
return FileManager.default
}()
// lazy属性:依赖其他属性
lazy var documentPath: String = {
print("执行documentPath初始化")
return fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!.path
}()
init() {
print("DataManager初始化完成")
}
}
// 使用
let manager = DataManager()
// 输出:DataManager初始化完成,lazy属性未初始化
_ = manager.fileManager
// 输出:执行fileManager初始化
4. 元类型、.self 与 AnyClass
重点说明:
- 元类型:类型的类型,用
Type表示,如String.Type,代表类型本身。 AnyClass:AnyObject.Type的别名,代表任意类的元类型。.self:类型.self获取元类型,实例.self返回实例本身。- 核心场景:动态创建实例、工厂模式、runtime动态操作。
代码示例:
swift
// 获取元类型
let stringType: String.Type = String.self
print(stringType) // String
// AnyClass与动态创建实例
class Person {
required init() {}
func sayHello() { print("Hello") }
}
class Student: Person {
override func sayHello() { print("Student Hello") }
}
let personClass: AnyClass = Person.self
let studentClass: AnyClass = Student.self
func createInstance(_ classType: AnyClass) -> Person? {
guard let type = classType as? Person.Type else { return nil }
return type.init()
}
let student = createInstance(studentClass)
student?.sayHello() // Student Hello
七、进阶特性
1. Reflection 与 Mirror
重点说明:
- 核心定义:Swift的反射机制,通过
Mirror在运行时获取、遍历实例的所有属性信息,是Swift少有的运行时自省能力。 - 核心特性:只读反射,支持struct、class、enum、tuple,无法修改属性值。
- 核心场景:模型转字典、JSON序列化、对象属性打印。
代码示例:
swift
// 模型定义
struct User {
let name: String
let age: Int
let isVip: Bool
}
// 模型转字典通用方法
func modelToDictionary(_ model: Any) -> [String: Any] {
let mirror = Mirror(reflecting: model)
var dict: [String: Any] = [:]
for (propertyName, propertyValue) in mirror.children {
guard let propertyName = propertyName else { continue }
dict[propertyName] = propertyValue
}
return dict
}
// 使用
let user = User(name: "张三", age: 20, isVip: true)
let userDict = modelToDictionary(user)
print(userDict) // ["name": "张三", "age": 20, "isVip": true]
2. 正则表达式
重点说明:
- Swift语言层面未内置正则表达式,基于
Foundation的NSRegularExpression实现,可通过封装简化调用。 - 注意:Swift字符串的range需基于
utf16转换,避免中文/表情符号的range错误。
代码示例:
swift
import Foundation
// 正则工具类
struct RegexHelper {
private let regex: NSRegularExpression
init(pattern: String, options: NSRegularExpression.Options = .caseInsensitive) throws {
self.regex = try NSRegularExpression(pattern: pattern, options: options)
}
// 匹配是否成功
func isMatch(_ input: String) -> Bool {
let range = NSRange(input.startIndex..., in: input)
return regex.firstMatch(in: input, range: range) != nil
}
// 提取匹配结果
func matches(_ input: String) -> [String] {
let range = NSRange(input.startIndex..., in: input)
let matches = regex.matches(in: input, range: range)
return matches.compactMap {
guard let range = Range($0.range, in: input) else { return nil }
return String(input[range])
}
}
}
// 常用正则枚举
enum RegexPattern: String {
case email = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$"
case phone = "^1[3-9]\\d{9}$"
}
// 便捷扩展
extension String {
func isMatch(pattern: RegexPattern) -> Bool {
guard let helper = try? RegexHelper(pattern: pattern.rawValue) else {
return false
}
return helper.isMatch(self)
}
}
// 使用
let isEmail = "test@example.com".isMatch(pattern: .email) // true
let isPhone = "13800138000".isMatch(pattern: .phone) // true
3. 命名空间
重点说明:
- Swift无原生命名空间关键字,通过无case枚举+静态成员模拟命名空间,解决类名冲突,实现代码模块化,替代OC的前缀方案。
代码示例:
swift
// 模拟命名空间
enum MyApp {
// 网络模块
enum Network {
static let baseURL = "https://api.myapp.com"
static func request(url: String) {
print("发起请求:\(url)")
}
}
// UI模块
enum UI {
static let mainColor = "#FF0000"
static func showToast(message: String) {
print("显示Toast:\(message)")
}
}
}
// 使用
print(MyApp.Network.baseURL)
MyApp.UI.showToast(message: "操作成功")
// 解决类名冲突
enum ModuleA {
class User { var name = "ModuleA User" }
}
enum ModuleB {
class User { var name = "ModuleB User" }
}
let userA = ModuleA.User()
let userB = ModuleB.User()
八、OC混编与工程化特性
1. 条件编译
重点说明:
- 根据编译环境、平台、配置等条件选择性编译代码,是编译时执行,不符合条件的代码不会被编译到二进制中。
- 常用条件:平台(os(iOS)/os(macOS))、模式(DEBUG/RELEASE)、Swift版本、自定义标记。
代码示例:
swift
// 调试/发布模式区分
#if DEBUG
let serverURL = "https://test-api.example.com"
#else
let serverURL = "https://api.example.com"
#endif
// 平台适配
#if os(iOS)
import UIKit
let screenWidth = UIScreen.main.bounds.width
#elseif os(macOS)
import AppKit
let screenWidth = NSScreen.main?.frame.width ?? 0
#endif
// Swift版本适配
#if swift(>=5.5)
print("支持async/await新特性")
#else
print("使用低版本兼容方案")
#endif
2. 编译标记 MARK / TODO / FIXME
重点说明:
- 代码标记注释,Xcode会在导航栏中显示,用于代码分块、标记待办事项、待修复问题,提升代码可维护性。
- 核心类型:
// MARK::代码分块,加-生成分隔线// TODO::待办事项// FIXME::待修复的bug
代码示例:
swift
import UIKit
class ViewController: UIViewController {
// MARK: - 生命周期
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
// MARK: - UI设置
private func setupUI() {
view.backgroundColor = .white
// TODO: 添加导航栏按钮
// FIXME: 适配iPhone SE布局
}
// MARK: - 事件处理
@objc private func buttonClick() {
// TODO: 实现按钮点击逻辑
}
}
3. @objc、dynamic 与 Selector
重点说明:
@objc:将Swift的类、方法、属性暴露给OC runtime,支持OC代码调用、runtime特性(KVO、target-action)。dynamic:强制方法/属性使用OC runtime动态派发,支持方法交换、动态修改。Selector:OC的方法选择器,Swift中用#selector()创建,用于动态方法调用、target-action。
代码示例:
swift
import UIKit
@objc class SwiftPerson: NSObject {
@objc var name: String
@objc var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
super.init()
}
@objc func sayHello() {
print("Hello,我是\(name)")
}
// dynamic标记:动态派发
@objc dynamic func dynamicMethod() {
print("原始动态方法")
}
}
// Selector动态调用
let person = SwiftPerson(name: "张三", age: 20)
let selector = #selector(SwiftPerson.sayHello)
person.perform(selector) // 输出:Hello,我是张三
// target-action使用
let button = UIButton()
button.addTarget(person, action: #selector(SwiftPerson.sayHello), for: .touchUpInside)