美文网首页
OC中int(unsigned long)与id之间的关系

OC中int(unsigned long)与id之间的关系

作者: 传说中的汽水枪 | 来源:发表于2019-06-08 07:39 被阅读0次

    在CFRuntime源码中有如下的代码(删减了很多):
    typedef unsigned long uintptr_t;

    CF_EXPORT uintptr_t __CFDoExternRefOperation(uintptr_t op, id obj) {
        uintptr_t count;
        switch (op) {
        case 300:   // increment
        case 350:   // increment, no event
        CFBasicHashAddValue(table, disguised, disguised);
            if (__CFOASafe && op != 350) __CFRecordAllocationEvent(__kCFObjectRetainedEvent, obj, 0, 0, NULL);
            return (uintptr_t)obj;
        case 450:   // decrement, no event
            count = (uintptr_t)CFBasicHashRemoveValue(table, disguised);
            return 0 == count;
        case 500:
            count = (uintptr_t)CFBasicHashGetCountOfKey(table, disguised);
            return count;
        }
        return 0;
    }
    

    一个函数,居然即返回了unsigned long,又返回了bool,且返回了对象。一下子就扩展了我的知识面,因此我写了如下的测试代码:

    typedef NS_ENUM(NSInteger, RXTMIntToIdType) {
        RXTMIntToIdType_Int,
        RXTMIntToIdType_Bool,
        RXTMIntToIdType_Object,
    };
    
    @implementation RXTMIntToIdObject
    - (void)test {
        uintptr_t r1 = [self valueWithType:RXTMIntToIdType_Int];
        uintptr_t r2 = [self valueWithType:RXTMIntToIdType_Bool];
        uintptr_t r3 = [self valueWithType:RXTMIntToIdType_Object];
        // 代码1: 需要把此文件修改为不支持ARC的,才能进行转换
        NSObject *o3 = (id)r3;
        NSLog(@"%ld, %ld, %ld, %@", r1, r2, r3, o3);
    }
    - (uintptr_t)valueWithType:(RXTMIntToIdType)type {
        switch (type) {
            case RXTMIntToIdType_Int:
                return 0;
            case RXTMIntToIdType_Bool:
            {
                NSInteger random = arc4random() % 2;
                return random == 0;
            }
            case RXTMIntToIdType_Object:
            default:
            {
                NSString *str = @"Hello I'm a string";
                id value = str;
                // 代码2: 如果这里是int的话,会导致int溢出,会得不到正确的内存地址
                return (uintptr_t)value;
            }
        }
    }
    @end
    

    代码1: 需要把此文件修改为不支持ARC的,才能进行转换
    代码2: 如果这里是int的话,会导致int溢出,会得不到正确的内存地址

    一些知识的总结:

    1. OC对象和id 最后都是通过指针来表示的,而指针地址就是数字
    2. 64位机器,int不够用了,所以需要unsigned long

    相关文章

      网友评论

          本文标题:OC中int(unsigned long)与id之间的关系

          本文链接:https://www.haomeiwen.com/subject/lhvbxctx.html