ACCESSiOS知识原理篇二

lldb(gdb)常用之调节命令?

  • po:打印对象,会调用对象description方法。是print-object的简写
  • expr:可以当调节时动态执行指定表达式,并将结果打印出来,很有因此之吩咐
  • print:也是打印命令,需要指定项目
  • bt:打印调用堆栈,是thread
    backtrace的简写,加all可打印所有thread的仓库
  • br l:是breakpoint list的简写

BAD_ACCESS在啊情形下出现?

  • 看一个僵尸对象,访问僵尸对象的成员变量或者朝那作消息
  • 死循环

哪些调试BAD_ACCESS错误

  • 装全局断点快速定位问题代码所在行
  • 翻开僵尸对象调试功能
![]()



![]()

简述下Objective-C中调用方法的进程(runtime)

  • Objective-C是动态语言,每个方法在运转时会见为动态转为消息发送,即:objc_msgSend(receiver,
    selector),整个过程介绍如下:

    • objc在向一个目标发送信息时,runtime库会根据目标的isa指针找到该目标实际所属的类
    • 然后以此类中的章程列表以及那父类方法列表中觅办法运行
    • 倘,在极其顶层的父类(一般为便NSObject)中仍然找不顶对应的方式时,程序于运转时见面挂掉并丢掉来老unrecognized
      selector sent to XXX
    • 而是于就之前,objc的运作时会见为出三次救程序崩溃的空子,这三不善挽救程序奔溃的征见问题《什么时候会报unrecognized
      selector的死》中的认证
  • 补给说明:Runtime 铸就了Objective-C
    是动态语言的风味,使得C语言具备了面向对象的表征,在程序运行期创建,检查,修改类、对象及其相应的法门,这些操作都可以使用runtime中之相应措施实现。

好家伙是method swizzling(俗称黑魔法)

  • 简单说就是进展方式交换
  • 每当Objective-C中调用一个措施,其实是于一个目标发送信息,查找消息之绝无仅有因是selector的名字。利用Objective-C的动态特性,可以实现在运作时偷换selector对应之章程实现,达到让方挂钩的目的
  • 每个接近都发出一个措施列表,存放着智的名跟法实现之映照关系,selector的实质实际上就算是措施名,IMP有点类似函数指针,指向具体的Method实现,通过selector就可找到相应之IMP
![]()
  • 换成方法的几乎种植实现方式
    • 利用 method_exchangeImplementations 交换两单艺术的兑现
    • 利用 class_replaceMethod 替换方法的贯彻
    • 利用 method_setImplementation 来一直装有方法的IMP
    ![]()

objc中为一个nil对象发送信息将会晤发出啊?

  • 当Objective-C中往nil发送信息是一点一滴可行之——只是以运行时不见面来外作用

    • 若一个艺术返回值是一个靶,那么发送给nil的音讯将返回回0(nil)
    • 而措施返回值为指针类型,其指针大小为小于或者当sizeof(void*)
    • float,double,long double 或者long
      long的整型标量,发送给nil的消息将赶回回0
    • 如果艺术返回值为结构体,发送给nil的音信将回回0。结构体中逐一字段的值将还是0
    • 假设艺术的回到值未是上述涉的几乎种植状况,那么发送给nil的消息的返值将是匪定义的
  • 现实原因剖析

    • objc是动态语言,每个方法以运行时会给动态转为消息发送,即:objc_msgSend(receiver,
      selector)
    • 为好清楚是情,还是贴一个objc的源代码

    struct objc_class
    {
      // isa指针指向Meta Class,因为Objc的类的本身也是一个Object,
      // 为了处理这个关系,runtime就创造了Meta Class,
      // 当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object
      Class isa OBJC_ISA_AVAILABILITY;
      #if !__OBJC2__
      Class super_class OBJC2_UNAVAILABLE; // 父类
      const char *name OBJC2_UNAVAILABLE; // 类名
      long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
      long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
      long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
      struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
      struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
      // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,
      // 这时会在method Lists中遍历,
      // 如果cache了,常用的方法调用时就能够提高调用的效率。
      // 这个方法缓存只存在一份,不是每个类的实例对象都有一个方法缓存
      // 子类会在自己的方法缓存中缓存父类的方法,父类在自己的方法缓存中也会缓存自己的方法,而不是说子类就不缓存父类方法了
      struct objc_cache *cache OBJC2_UNAVAILABLE;
      struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
      #endif
      } OBJC2_UNAVAILABLE;
    
    • objc在通往一个对象发送信息不时,runtime库会根据目标的isa指针找到该对象实际所属之近乎,然后于此类中的办法列表以及那个父类方法列表中搜索办法运行,然后重新发送信息之时,objc_msgSend方法无会见回值,所谓的归内容都是现实性调用时实行的。
    • 比方向一个nil对象发送信息,首先在寻觅目标的isa指针时就是0地址返回了,所以无见面出现任何不当

objc中为一个目标发送信息[obj foo]和objc_msgSend()函数之间有啊关系?

  • [obj foo];在objc动态编译时,会受转意为:objc_msgSend(obj,
    @selector(foo));

哎呀时候会报unrecognized selector的雅?

  • 当调用该对象上有方法,而拖欠目标上没实现这艺术的时节,
    可以经“消息转发”进行缓解,如果要要命就会见报unrecognized
    selector异常

  • objc是动态语言,每个方法以运行时会给动态转为消息发送,即:objc_msgSend(receiver,
    selector),整个经过介绍如下:

    • objc于为一个目标发送信息不时,runtime库会根据目标的isa指针找到该对象实际所属之好像
    • 下一场在此类中之主意列表以及那父类方法列表中寻觅办法运行
    • 如若,在尽顶层的父类中仍然找不顶对应的措施时,程序于运转时见面挂掉并丢掉来大unrecognized
      selector sent to XXX
      。但是以就前面,objc的运转时见面于闹三次救程序崩溃的空子
  • 三次抢救程序崩溃的时机

    • Method resolution
      • objc运行时会调用+resolveInstanceMethod:或者 +resolveClassMethod:,让你出机遇提供一个函数实现。
      • 要您补充加了函数并返回
        YES,那运行时系统就是见面重新启动同等不行信息发送的长河
      • 一经 resolve 方法返回 NO ,运行时便会见变到下一致步,消息转发
    • Fast forwarding
      • 如果目标靶实现了-forwardingTargetForSelector:,Runtime
        这时便见面调用这个主意,给你拿此信息转发给其他对象的会
      • 假定这艺术返回的不是nil和self,整个消息发送的经过就是会见被重启,当然发送的对象见面成为你回去的死目标。
      • 不然,就见面连续Normal Fowarding。
      • 此叫Fast,只是以区别下一样步之中转机制。因为就同一步不会见创任何新的目标,但Normal
        forwarding转发会创建一个NSInvocation对象,相对Normal
        forwarding转发更快点,所以这边叫Fast forwarding
    • Normal forwarding
      • 即时同一步是Runtime最后一破吃您挽救的机遇。
      • 先是她见面发送-methodSignatureForSelector:消息得到函数的参数与归值类型。
      • 假定-methodSignatureForSelector:返回nil,Runtime则会起-doesNotRecognizeSelector:消息,程序这时也即吊掉了。
      • 比方回去了一个函数签名,Runtime就见面创造一个NSInvocation对象并发送-forwardInvocation:消息给目标对象

HTTP协议中POST方法及GET方法来那些区别?

  • GET用于向服务器请求数据,POST用于提交数据
  • GET请求,请求参数拼接形式暴露在地址栏,而POST请求参数则在请求体里面,因此GET请求不称用来证明密码等操作
  • GET请求的URL有长限制,POST请求不会见有长限制

下block时什么状况会出引用循环,如何解决?

每当block内怎么修改block外部变量?

运用系统的某些block api(如UIView的block版本写动画时),是否也考虑循环引用问题?

  • 系统的某些block
    api中,UIView的block版本写动画时不需要考虑,但也有一些api 需要考虑
  • 以下这些使用方法不会引循环引用的题目

[UIView animateWithDuration:duration animations:^
{ [self.superview layoutIfNeeded]; }];

[[NSOperationQueue mainQueue] addOperationWithBlock:^
{ self.someProperty = xyz; }];

[[NSNotificationCenter defaultCenter] addObserverForName:@"someNotification"
            object:nil
             queue:[NSOperationQueue mainQueue]
        usingBlock:^(NSNotification * notification)
        { self.someProperty = xyz; }];
  • 不过一旦艺术中之局部参数是 成员变量,那么得引致循环引用,如 GCD
    、NSNotificationCenter调用就要小心一点,比如 GCD 内部如果引用了
    self,而且 GCD 的参数是 成员变量,则要考虑到循环引用,举例如下:

    • GCD
      • 分析:self–>_operationsQueue–>block–>self形成闭环,就招了循环引用

    __weak __typeof__(self) weakSelf = self;
    dispatch_group_async(_operationsGroup, _operationsQueue, ^
    {
        [weakSelf doSomething];
        [weakSelf doSomethingElse];
    } );
    
    • NSNotificationCenter
      • 分析:self–>_observer–>block–>self形成闭环,就导致了巡回引用

      __weak __typeof__(self) weakSelf = self;
      _observer = [[NSNotificationCenter defaultCenter]
      addObserverForName:@"testKey"
      object:nil
      queue:nil
      usingBlock:^(NSNotification *note){
          [weakSelf dismissModalViewControllerAnimated:YES];
      }];
    

OC中普遍的大循环引用总结

相关文章