You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift含Block方法的objc_method_description.types编码格式问询

Swift生成的Objective-C扩展方法类型编码解析问题

问题核心

Swift编译器为包含Block的异步方法生成的Objective-C方法编码,使用了官方ObjC类型编码文档未记载的语法,涉及的特殊字符包括*"、<、>*。

例如以下Swift方法:

func DebugLog2(message: String) async -> String

对应的方法编码为:

v32@0:8@"NSString"16@?<v@?@"NSString">24

NSMethodSignature兼容性问题

NSMethodSignature类无法兼容这类扩展编码,执行以下代码:

[NSMethodSignature signatureWithObjCTypes:"\"NSString\"16@?<v@?@\"NSString\">24"];

会触发报错:

'+[NSMethodSignature signatureWithObjCTypes:]: unsupported type encoding spec '"' in '"NSString"16@?<v@?@"NSString">24''

Swift代码库线索

查阅Swift代码库时,发现存在“extended method type encodings(扩展方法类型编码)”相关的测试代码,但未找到该编码的具体生成逻辑。

示例代码与输出

Swift示例代码

decodeProto()

@objc
class TestClass : NSObject {
    @objc
    func DebugLog(message: String) -> String {
        print(message)
        return message
    }

    @objc
    func DebugLog2(message: String) async -> String {
        do {
            try await Task.sleep(nanoseconds: 1_000_000_000)
        } catch {}
        print(message);
        return message;
    }
}

func decodeProto() {
    var methodCount : UInt32 = 1
    let methodList = class_copyMethodList(TestClass.self, UnsafeMutablePointer(&methodCount))!
    for i in 0..<Int(methodCount) {
        let method = methodList[i];
        let desc = method_getDescription(method);
        let name = desc.pointee.name!
        let types = String(validatingUTF8: desc.pointee.types!)!
        print("Selector: \(name) Description: \(types)")
    }
}

运行输出

Selector: DebugLog2WithMessage:completionHandler: Description: v32@0:8@"NSString"16@?<v@?@"NSString">24
Selector: DebugLogWithMessage: Description: @24@0:8@16
Selector: init Description: @16@0:8

需求背景

需要通过解析方法编码计算栈帧的最大尺寸,该需求源于拦截objc_msgSend调用,在调用实际objc_msgSend前添加Objective-C异常处理,逻辑如下:

intercept_objc_msgSend (...) {
    @try {
        objc_msgSend (...);
    } @catch (NSException *ex) {
        handleException (ex);
    }
}

由于无法用C创建通用拦截方法,故采用汇编实现。通用拦截代码需为原始参数(栈帧)分配空间并复制,因此需解析方法编码以确定每个参数的大小。只需获取最大尺寸而非精确值,累加所有参数所需空间即可,无需减去寄存器传递参数的尺寸。


内容的提问来源于stack exchange,提问作者Rolf Bjarne Kvinge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:56:00