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)管理生命周期和捕获变量。
相关推荐
游戏开发爱好者821 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
黑码哥21 小时前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
2501_915106321 天前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview
2501_915106321 天前
使用 Sniffmaster TCP 抓包和 Wireshark 网络分析
网络协议·tcp/ip·ios·小程序·uni-app·wireshark·iphone
熊猫钓鱼>_>1 天前
移动端开发技术选型报告:三足鼎立时代的开发者指南(2026年2月)
android·人工智能·ios·app·鸿蒙·cpu·移动端
徐同保2 天前
通过ip访问nginx的服务时,被第一个server重定向了,通过设置default_server解决这个问题
ios·iphone
2501_915918412 天前
在 iOS 环境下查看 App 详细信息与文件目录
android·ios·小程序·https·uni-app·iphone·webview
2501_916007472 天前
没有 Mac 用户如何上架 App Store,IPA生成、证书与描述文件管理、跨平台上传
android·macos·ios·小程序·uni-app·iphone·webview
夏幻灵3 天前
HTTPS全面解析:原理、加密机制与证书体
ios·iphone
TheNextByte13 天前
如何在iPhone上恢复已删除的笔记的综合指南
笔记·ios·iphone