美文网首页
iOS知识点

iOS知识点

作者: YCLi | 来源:发表于2017-12-27 15:09 被阅读0次

1、引用计数是什么?

      引用计数实际上是对内存地址的持有者的一个计数。

2、引用计数的工作原理是什么?

      1)当我们创建(alloc)一个新的对象A时,它的引用计数从零变成1

      2)当有一个指针指向对象A时,也就是某对象想通过引用保留(retain)该对象A时,引用计数+1

      3)当某个指针或对象不指向该对象A时,也就是释放(release)该引用后,其引用计数-1

      4)当对象A的引用计数变为0时,说明该对象不再被任何指针引用(指向),这个时候将对象A销毁,所占内存将被回收,且所有指向该对象的引用都将变成无效,系统也会将其占用的内存标记为“可重用(reuse)”

3、strong、weak、copy、assign的区别

      strong表示指向并拥有该对象。其修饰的对象引用计数会增加1。该对象只要引用计数不为0则不会被销毁。当然强行将其设为nil可以销毁它。

      weak表示指向但不拥有该对象。其修饰的对象引用计数不会增加。无需手动设置,该对象会自行在内存中销毁。

      assign主要用于修饰基本数据类型,如NSInteger和CGFloat,这些数值主要存在于栈上。

      weak 一般用来修饰对象,assign一般用来修饰基本数据类型。原因是assign修饰的对象被释放后,指针的地址依然存在,造成野指针,在堆上容易造成崩溃。而栈上的内存系统会自动处理,不会造成野指针。

      copy与strong类似。不同之处是strong的复制是多个指针指向同一个地址,而copy的复制每次会在内存中拷贝一份对象,指针指向不同地址。copy一般用在修饰有可变对象类型的不可变对象上,如NSString, NSArray, NSDictionary。

      Objective-C 中,基本数据类型的默认关键字是atomic, readwrite, assign;普通属性的默认关键字是atomic, readwrite, strong。

4、ARC下 __strong、__weak、__autorleaseing的修饰用法

       __weak与weak基本相同。前者用于修饰变量(variable),后者用于修饰属性(property)。__weak主要用于防止block中的循环引用。

       __block也用于修饰变量。它是引用修饰,所以其修饰的值是动态变化的,即可以被重新赋值的。__block用于修饰某些block内部将要修改的外部变量。

       __weak和__block的使用场景几乎与block息息相关。而所谓block,就是Objective-C对于闭包的实现。闭包就是没有名字的函数,或者理解为指向函数的指针。

       __autoreleaseing表示将对象放入自动释放池中,等价于MRC下的[obj autorelease]方法,在自动释放池里清理对象的时候将对象的引用计数减一,如果对象计数为零则废弃并调用对象的dealloc方法。总结:__autoreleaseing最终效果是延长了对象的生命周期,将对象的释放(对自动释放池里的对象调用[obj release])时机改为runloop结束时。主要用于函数返回对象和引用参数的传递。

5、categoty和extension的区别,categoty为什么可以添加方法不能添加变量

     1)extension看起来很像一个匿名的category,但是extension和有名字的category几乎完全是两个东西。extension在编译期决议,它就是类的一部分,在编译期和头文件里的@interface以及实现文件里的@implement一起形成一个完整的类,它伴随类的产生而产生,亦随之一起消亡。extension一般用来隐藏类的私有信息,你必须有一个类的源码才能为一个类添加extension,所以你无法为系统的类比如NSString添加extension。

    但是category则完全不一样,它是在运行期决议的。就category和extension的区别来看,我们可以推导出一个明显的事实,extension可以添加实例变量,而category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。

    2)category是在运行期决定的,运行期,对象的内部布局已经确定,如果添加实例变量就会破坏类的内部布局(运行时可以为category添加实例变量)

6、main函数执行之前发生了什么

    1)动态库链接库

    2)ImageLoader加载可执行文件, 里边是被编译过的符号,代码等

    3)runtime与+load

      总结:整个事件由dyld主导,完成运行环境的初始化后,配合ImageLoader将二进制文件按格式加载到内存,动态链接依赖库,并由runtime负责加载成objc定义的结构,所有初始化工作结束后,dyld调用真正的main函数。

      值得说明的是,这个过程远比写出来的要复杂,这里只提到了runtime这个分支,还有像GCD、XPC等重头的系统库初始化分支没有提及(当然,有缓存机制在,它们也不会玩命初始化),总结起来就是main函数执行之前,系统做了茫茫多的加载和初始化工作,但都被很好的隐藏了,我们无需关心。

7、运行时机制是什么?runtime哪里用到了,怎么用的?

      1)运行时机制:Runtime又叫运行时,是一套底层的C语言API,其为iOS内部的核心之一,我们平时编写的OC代码,底层都是基于它来实现的。RunTime简称运行时。OC就是运行时机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数。对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。

     2)哪里用到了:

        (1)获取类里面的所有成员变量。

        (2)为类动态添加成员变量。(不确定能不能)

        (3)动态改变类的方法实现。

       (4)为类动态添加新的方法等。

    3)怎么用的:

        1). 使用时需要导入的头文件

        2). Runtime 运行时机制,它是一套C语言库。

        3). 实际上我们编写的所有OC代码,最终都是转成了runtime库的东西。

        比如:类转成了 Runtime 库里面的结构体等数据类型,

               方法转成了 Runtime 库里面的C语言函数,

               平时调方法都是转成了 objc_msgSend 函数(所以说OC有个消息发送机制)

               // OC是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。

               // [stu show];  在objc动态编译时,会被转意为:objc_msgSend(stu, @selector(show));

        4). 因此,可以说 Runtime 是OC的底层实现,是OC的幕后执行者。

8、runloop是什么?系统哪里用到了?你自己开启的线程,怎么保护不退出?

       从字面上讲就是运行循环,它内部就是do-while循环,在这个循环内部不断地处理各种任务。一个线程对应一个RunLoop,基本作用就是保持程序的持续运行,处理app中的各种事件。通过runloop,有事运行,没事就休息,可以节省cpu资源,提高程序性能。

       哪里用到:

       1)使用runloop保证子线程的长期存活(例:在iOS开发过程中,有时候我们不希望一些花费时间比较长的操作阻塞主线程,导致界面卡顿,那么我们就会创建一个子线程,然后把这些花费时间比较长的操作放在子线程中来处理。可是当子线程中的任务执行完毕后,子线程就会被销毁掉。)

       2)  定时器nstimer

       例:1.我们经常会在应用中看到tableView 的header 上是一个横向ScrollView,一般我们使用NSTimer,每隔几秒切换一张图片。可是当我们滑动tableView的时候,顶部的scollView并不会切换图片,这可怎么办呢?   2.界面上除了有tableView,还有显示倒计时的Label,当我们在滑动tableView时,倒计时就停止了,这又该怎么办呢?

       答:1、如果是在主线程中运行timer,想要timer在某界面有视图滚动时,依然能正常运转,那么将timer添加到RunLoop中时,就需要设置mode 为NSRunLoopCommonModes。

              2、如果是在子线程中运行timer,那么将timer添加到RunLoop中后,Mode设置为NSDefaultRunLoopMode或NSRunLoopCommonModes均可,但是需要保证RunLoop在运行,且其中有任务。

相关文章

网友评论

      本文标题:iOS知识点

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