面试准备——iOS基础知识

作者: tmachc | 来源:发表于2018-02-13 18:20 被阅读61次

    iOS基础知识

    iOS的内存管理

    分为ARC、MRC两种,通过引用计数来控制对象,引用计数为0的时候,释放对象。
    new、alloc、copy =1,retain +1,release -1。autorelease pool 是自动释放池,池子里的对象会等到池子释放时候一并释放,只释放计数为0的。

    什么情况下会出现内存的循环引用?

    循环引用是只相互强引用导致无法释放内存,造成内存泄露。

    1. Timer:timer一般为某个类的成员变量,创建timer的时候需要addTarget,这样timer就强引用了类,timer处于validate状态时,引用计数为1无法释放,若不手动释放,会出现循环引用;p.s.释放要在dealloc之前释放。
    2. block:block一般为某个类的成员变量,创建block的时候会对内部对象强引用,造成循环引用;解决方法为,将block内部的对象weak了再使用。如__weak __typeof(&*self)weakself = self;
    3. delegate:delegate一般为某个类的成员变量,要用weak来修饰,否则容易出现循环引用。

    block中的weak self,是任何时候都需要加的么?

    在block中用到self时要加。

    GCD的queue,main queue中执行的代码,一定是在main thread么?

    queue不一定,main queue一定是main thread。

    NSOperationQueue有哪些使用方式

    • 添加operation
    • 顺序执行operation(依赖、优先级)
    • 设置并发数
    • 取消所有operation([queue cancel]
    • 阻塞当前线程,等待queue的所有操作执行完毕 ( [queue waitUntilAllOperationsAreFinished])
    • 暂停继续queue

    NSThread中的Runloop的作用,如何使用?

    1. 使程序一直运行并接收用户的输入
    2. 决定程序在何时处理哪些事件
    3. 节省CPU时间(当程序启动后,什么都没有执行的话,就不用让CPU来消耗资源来执行,直接进入睡眠状态)
      每个线程(NSThread)对象中内部都有一个run loop(NSRunLoop)对象用来循环处理输入事件,处理的事件包括两类,一是来自Input sources的异步事件,一是来自Timer sources的同步事件;

    [1]run Loop在处理输入事件时会产生通知,可以通过Core Foundation向线程中添加run-loop observers来监听特定事件,以在监听的事件发生时做附加的处理工作。 主线程的Run Loop会在App运行时自动运行,子线程中需要手动运行。

    Run Loop就是一个处理事件源的循环,你可以控制这个Run Loop运行多久,如果当前没有事件发生,Run Loop会让这个线程进入睡眠状态(避免再浪费CPU时间),如果有事件发生,Run Loop就处理这个事件。

    如果子线程进入一个循环需要不断处理一些事件,那么设置一个Run Loop是最好的处理方式,如果需要Timer,那么Run Loop就是必须的。

    开发中遇到的需要使用Run Loop的情况有:

    • 需要使用Port或者自定义Input Source与其他线程进行通讯。
    • 子线程中使用了定时器
    • 使用任何performSelector*****到子线程中运行方法
    • 使用子线程去执行周期性任务
    • NSURLConnection在子线程中发起异步请求

    NSThread和runloop

    .h文件中的变量,外部可以直接访问么?(注意是变量,不是property)

    不可以。访问变量需要有getter,直接访问会崩溃。

    讲述一下runtime的概念,message send如果寻找不到相应的对象,会如何进行后续处理 ?

    • 类:
    struct objc_class {
        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;  // 方法定义的链表
        struct objc_cache *cache                OBJC2_UNAVAILABLE;  // 方法缓存
        struct objc_protocol_list *protocols    OBJC2_UNAVAILABLE;  // 协议链表
    #endif
    } OBJC2_UNAVAILABLE;
    
    • 消息机制:
      [receiver message]会转化为objc_msgSend(receiver, selector)

    • 方法调用过程:
      先去缓存中找,没有去方法列表里找,再没有去父类的方法列表里找,如果找到则调用,实在找不到,动态方法解析,最后消息转发。

    • 动态方法解析:
      resolveInstanceMethod:resolveClassMethod:两种。

    void dynamicMethodIMP(id self, SEL _cmd) {
        // implementation ....
    }
    @implementation MyClass
    + (BOOL)resolveInstanceMethod:(SEL)aSEL
    {
        if (aSEL == @selector(resolveThisMethodDynamically)) {
              class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
              return YES;
        }
        return [super resolveInstanceMethod:aSEL];
    }
    @end
    
    • 消息转发:
      • 确定消息要发到哪里
      • 将所有的参数一起发过去
    - (void)forwardInvocation:(NSInvocation *)anInvocation
    {
        if ([someOtherObject respondsToSelector:[anInvocation selector]])
            [anInvocation invokeWithTarget:someOtherObject];
        else
            [super forwardInvocation:anInvocation];
    }
    

    [2]


    1. 参考自:https://www.jianshu.com/p/ac9a37567be3

    2. 参考自:https://blog.tmachc.win/ios-runtime/

    相关文章

      网友评论

        本文标题:面试准备——iOS基础知识

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