iOS知识原理篇二

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,整个音信发送的历程就会被重启,当然发送的目标会变成你回到的十分目的。
      • 要不,就会延续诺玛l Fowarding。
      • 此处叫法斯特(Fast),只是为着不同下一步的转账机制。因为这一步不会创建任何新的靶子,但诺玛(Norma)l
        forwarding转载会创立一个NSInvocation对象,相对诺玛l
        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中广大的轮回引用总括

相关文章