• 关于block以及__bridge的一些笔记


    问题概要

    • _block是否是一个OC对象?
    • __bridge相关。
    _block是否是一个OC对象?
    • 结论

      • 一般来说,block可以看做一个OC对象,但是在编译器底层,block又可以被细分为block对象,独立于OC对象的存在。
    • 分析

      • 根据苹果官方文档,明确的指明block是一个OC对象。有兴趣的在文档里面搜索Working with Blocks
      • 根据文档Clang 4.0 documentation里面描述的,这里引入一个概念——可保留对象指针(retainable object pointer),这是苹果官方文档Working with Blocks这章里面没有出现过的字眼,这里面是这样描述的:可保留对象指针分为三类: block块指针,OC对象指针,由__attribute__((NSObject))标志的指针。
      • block一般可以认为是一个OC对象,但是在编译器底层有细分为block对象,独立于OC对象的存在,但是无论怎么描述,可保留对象(一般认为的OC对象)指针都可以受ARC管理。
    __bridge相关。(参考文档Clang 4.0 documentation)
    • __bridge

      • 在文档中关于__bridge的描述是这样的,可以实现非可保留对象指针以及可保留对象指针之间的转换,转换的两个对象必须一个是可保留对象,另外一个是非可保留对象,不做对象所有权转移,为了方便理解,可保留对象可以认为是一般情况下的OC对象(包括block等),非可保留对象可以认为是Core Foundation里面的对象等。
    • __bridge_retain

      • 文档中对__bridge_retained的描述是这样的,__bridge_retained把可保留对象指针类型转换为非可保留对象指针类型(不可以倒过来),转换前后对象所有权转移(从被转换者转移到转换者)。
      (void)bridgeRetain{
        CFStringRef fontName = (__bridge CFStringRef)@"PingFangSC-Thin";
        CGFloat fontSize = 13;
        CTFontRef fontRef = CTFontCreateWithName(fontName, fontSize, NULL);
        {
            id obj = [[NSObject alloc] init];
            fontRef = (__bridge CTFontRef)obj;
        }
        CFRelease(fontRef);
      }
      • 使用__bridge的情况

       
      • 一个已经释放掉的对象重复释放,本质上是坏内存访问,无论调这个类的什么方法都会出现坏内存crash,并不特指释放方法,obj的对象所有权没有转移,还是由自身去管理内存,ARC下,可保留对象的内存管理在自动调用release来释放内存。
      • 使用bridge_retain之后可以运行通过,对象所有权转移到fontRef,所以必须要调用CFRelease函数来管理内存,不然会发生内存泄露。

    • __bridge_transform

      • __bridge_transform:把非可保留对象指针类型转换为可保留对象指针类型,对象所有权转移,ARC下,自动调用realeas操作。
      //示例函数
      (void)bridgeTransform{
        CFStringRef fontName = (__bridge CFStringRef)@"PingFangSC-Thin";
        CGFloat fontSize = 13;
        CTFontRef fontRef = CTFontCreateWithName(fontName, fontSize, NULL);
        UIFont font = (__bridge_transfer UIFont)fontRef;
      }
      • 使用__bridge会出现内存泄露,fontRef的对象所有权没有转移,内存还是要手动释放。


        ​

      • 使用__bridge_transform的情况,对象所有权转移,内存转移到font来管理,ARC下,可保留对象会自动调用release操作。
        
       
    • 目前的项目中的使用很多关于__bridge的用法

      • 有以下用法的,感觉先将UIImage转CGImage,在转id再赋给contents,感觉中间的操作是可以去掉的,但是去掉中间的操作发现contents展示是空的。
      
      
      //这样
      animationView.contents = (__bridge id)MQZ_LOAD_QZONE_IMAGE_NO_CACHE("mqz_live_bg.jpg").CGImage;
       
      • 在《ios核心动画高级技巧》这本书中是这样描述的,造成这个现象是由Mac OS的历史原因造成的。它之所以被定义为id类型,是因为在Mac OS系统上,这个属性对CGImage和NSImage类型的值都起作用。如果你试图在iOS平台上将UIImage的值赋给它,只能得到一个空白的图层。

    参看资料
  • 相关阅读:
    将字符串格式化为csv数据
    以RTMP的方式播放录制好的视频
    as3signals的使用介绍
    rootkit hook之[四] IDT Hook
    .net调试WEB程序时页面无法显示的原因分析及解决办法
    rootkit hook之[六] sysenter Hook
    CUDA初探:GPU的并行计算
    rootkit hook 之[五] IRP Hook全家福
    rootkit之[七]IAT Hook HybridHook之终极打造
    CUDA初探:CUDA的初始化
  • 原文地址:https://www.cnblogs.com/superYou/p/6115518.html
Copyright © 2020-2023  润新知