Swift基础知识(三)

Swift 与 Objective-C 中的自省(Introspection)对比


1. 核心概念

  • 自省(Introspection):在运行时检查对象的类型或是否符合特定协议的能力。
  • Objective-C :基于 NSObject 的类体系,主要用于检查类继承关系。
  • Swift :支持所有类型(类、结构体、枚举),不依赖 NSObject,且涵盖协议检查。

2. 类型检查语法与行为

特性 Objective-C Swift
检查类继承关系 isKindOfClass:(判断类或子类) isMemberOfClass:(仅判断自身类) is 操作符(判断类型或子类型)
支持类型 NSObject 子类 所有类型(类、结构体、枚举)
协议一致性检查 conformsToProtocol: is(检查协议类型) as?(转换并检查协议)
值类型支持 不支持(仅类) 支持(结构体、枚举)
泛型支持 支持(结合泛型类型检查)

3. 具体用法与示例

Objective-C
objc 复制代码
// 类继承检查
BOOL isView = [obj isKindOfClass:[UIView class]];       // YES(obj 是 UIView 或其子类实例)
BOOL isExactView = [obj isMemberOfClass:[UIView class]]; // NO(obj 必须是 UIView 实例)

// 协议检查
BOOL conforms = [obj conformsToProtocol:@protocol(NSCopying)];
Swift
swift 复制代码
// 类型检查
let obj: Any = "Hello"
if obj is String { // true
    print("是 String 类型")
}

// 协议检查
protocol Drawable { func draw() }
struct Circle: Drawable { func draw() { } }

let shape: Any = Circle()
if shape is Drawable { // true
    print("符合 Drawable 协议")
}

// 值类型检查
let value: Any = 100
if value is Int { // true
    print("是 Int 类型")
}

// 类型转换 + 检查
if let drawableShape = shape as? Drawable {
    drawableShape.draw()
}

4. 核心区别总结

维度 Objective-C Swift
类型体系依赖 必须继承自 NSObject 不依赖任何基类,支持所有类型
检查范围 仅类(包括子类) 类、结构体、枚举、协议
协议检查 需显式调用 conformsToProtocol: 直接通过 isas? 检查
语法简洁性 方法调用(冗长) 操作符(简洁直观)
泛型支持 支持泛型类型检查

5. 高级特性(Swift 独有)

  • 模式匹配 :结合 switch 语句进行类型和协议匹配。

    swift 复制代码
    func checkType(_ value: Any) {
        switch value {
        case is String: print("字符串类型")
        case let num as Int where num > 0: print("正整数")
        case is Drawable: print("可绘制对象")
        default: break
        }
    }
  • 元类型检查 :通过 .Type 获取类型元信息。

    swift 复制代码
    let type: Int.Type = Int.self
    let instance = type.init(10) // 创建 Int 实例

6. 使用建议

  • Objective-C :在维护旧项目或与 Cocoa 框架交互时使用,注意仅适用于 NSObject 子类。
  • Swift :在新项目中优先使用 isas?,充分利用其对值类型和协议的支持,提升代码灵活性和安全性。

三、Swift 闭包(Closures)与 Objective-C Block 的对比

1. 内存分配与结构

特性 Swift 闭包 Objective-C Block
底层数据结构 闭包是 捕获上下文的函数,本质是结构体 Block 是 封装函数指针的结构体对象
内存位置 默认栈分配,逃逸闭包自动提升到堆 默认栈分配,需显式 copy 到堆
结构体布局 闭包结构体包含函数指针和捕获的上下文数据 Block 结构体包含 isa 指针、函数指针、捕获变量等
生命周期管理 通过 引用计数(ARC) 管理堆内存 手动 copy/release 或 ARC 管理堆内存

2. 变量捕获机制

特性 Swift 闭包 Objective-C Block
值类型捕获 捕获值类型的副本(深拷贝) 默认捕获值类型变量的 原始值 (需 __block 修饰允许修改)
引用类型捕获 捕获引用类型的强引用(需通过捕获列表弱化) 捕获对象的强引用(需 __weak 弱化)
可变性支持 通过 varinout 参数捕获可变变量 __block 修饰符实现变量可变性

3. 函数执行与上下文

特性 Swift 闭包 Objective-C Block
函数指针 闭包的函数指针直接指向编译生成的函数代码 Block 的函数指针通过 invoke 成员指向代码
上下文管理 闭包通过结构体存储捕获的变量(值或引用) Block 通过结构体的 descriptor 管理捕获变量引用计数
逃逸性处理 编译器自动检测逃逸闭包,并生成堆分配逻辑 需手动调用 copy 将 Block 从栈复制到堆

4. 底层实现细节

Swift 闭包
  1. 结构体表示

    swift 复制代码
    // 伪代码表示闭包结构体
    struct Closure<T> {
        var function: (T) -> Void  // 函数指针
        var capturedValues: [Any]  // 捕获的上下文数据
    }
  2. 内存管理

    • 非逃逸闭包:栈分配,函数返回后销毁。
    • 逃逸闭包:自动复制到堆,由 ARC 管理生命周期。
  3. 捕获列表优化

    • 显式声明 [weak self][unowned self],避免隐式强引用。
    • 编译器生成代码时,捕获列表直接修改闭包结构体的成员引用类型。
Objective-C Block
  1. 结构体表示

    objc 复制代码
    // 伪代码表示 Block 结构体
    struct Block_layout {
        void *isa;                  // 指向 Block 类型(栈/堆/全局)
        int flags;                  // 状态标记(是否被拷贝等)
        int reserved;               // 保留字段
        void (*invoke)(void *, ...); // 函数指针
        struct Block_descriptor *descriptor; // 描述符(引用计数、捕获变量等)
        // 捕获的变量数据...
    };
  2. 内存管理

    • 栈 Block:默认创建在栈上,函数返回后失效。
    • 堆 Block :通过 copy 操作复制到堆,由引用计数管理。
  3. 变量捕获

    • __block 修饰的变量会被包装为 Block_byref 结构体,允许跨 Block 修改。
    • 对象类型变量通过 retain/release 管理引用计数(ARC 下自动处理)。

5. 性能对比

维度 Swift 闭包 Objective-C Block
内存开销 更小(结构体直接存储捕获数据) 较大(包含 isaflags 等元数据)
执行速度 更快(直接函数指针调用) 稍慢(需通过 invoke 间接调用)
捕获变量修改 灵活(值类型副本独立修改) __block 包装,性能开销较大

6. 总结

  • Swift 闭包

    • 更轻量:基于结构体和值语义,减少内存开销。
    • 更安全:编译时检查捕获列表,避免循环引用。
    • 更高效:栈分配优化 + 直接函数调用。
  • Objective-C Block

    • 更底层:直接操作结构体和引用计数,灵活性高。
    • 兼容性:与 Cocoa 框架深度集成,适合传统代码维护。
    • 显式控制 :需手动管理 copy__block 修饰符。

底层核心差异

  • Swift 闭包是 值类型结构体,通过编译优化实现高效捕获和内存管理。
  • Objective-C Block 是 对象 ,依赖运行时元数据(isadescriptor)管理生命周期和捕获变量。
相关推荐
微:xsooop5 小时前
iOS 上架4.3a 审核4.3a 被拒4.3a 【灾难来袭】
flutter·unity·ios·uniapp
Haha_bj7 小时前
iOS深入理解事件传递及响应
前端·ios·app
在下历飞雨9 小时前
Kuikly基础之动画实战:让孤寡青蛙“活”过来
前端·ios·harmonyos
D***t13111 小时前
Swift在iOS中的多任务处理
开发语言·ios·swift
2501_9159184113 小时前
iOS 手机抓包软件怎么选?HTTPS 调试、TCP 数据流分析与多工具组合的完整实践
android·ios·智能手机·小程序·https·uni-app·iphone
游戏开发爱好者813 小时前
iOS 应用上架的工程实践复盘,从构建交付到审核通过的全流程拆解
android·ios·小程序·https·uni-app·iphone·webview
编程大师哥13 小时前
Xcode26新特性与iOS26适配指南
ios
00后程序员张13 小时前
iOS App 如何上架,从准备到发布的完整流程方法论
android·macos·ios·小程序·uni-app·cocoa·iphone
他们都不看好你,偏偏你最不争气13 小时前
【iOS】TableView的优化
macos·ios·objective-c·cocoa