美文网首页
iOS开发基础随笔

iOS开发基础随笔

作者: 放羊的王小二 | 来源:发表于2020-03-12 17:51 被阅读0次

    1.内存可分为代码区、数据区、堆区和栈区

    ·代码区用于存放二进制代码。

    ·常量区用于存放常量,静态变量和全局变量。

    ·堆区一般用来存放OC对象,比如通过alloc或new创建出来的对象,需要由程序员去创建和释放。

    ·栈区一般是在方法内申请的,用于存放局部变量及方法的参数,方法结束时由系统释放。


    2.iOS多线程有哪几种?

    ·pthread 运用C语言 可跨平台使用,线程的生命周期由程序员管理,但使用难度较大实际开发中几乎不用。

    ·NSThread 在使用上更加面向对象 可直接操作线程对象,线程的生命周期由程序员管理,实际开发中较少使用。

    ·GCD 为替代NSThread等线程技术,能充分利用设备的多核,自动管理线程的生命周期,实际开发中使用频率较高。

    ·NSOperation 基于GCD再次封装,相对GCD多了一些实用功能,易用性更高,自动管理线程的生命周期,在实际开发中使用频率较高。

    GCD 和 NSOperation 的区别是什么?

    ·GCD是纯C语言的API,NSOperation则是基于GCD封装的OC版本。

    ·GCD只支持FIFO(先入先出)的队列,NSOperation则可以很方便的调整执行顺序,设置并发数量。

    ·NSOperationQueue可以在各Operation间设置依赖关系,而GCD则较为麻烦。

    ·NSOperationQueue支持KVO键值观察模式,可以检测Operation是否正在执行(isExecuted),是否结束(isFinisn),是否取消(isCancel)

    ·GCD 的执行速度比 NSOpreation快。

    ~多线程的并行和并发区别:

        ·并行:充分利用计算机的多核,在多个线程上同步进行。

        ·并发:在一条线程上多个任期间快速交替进行。

    适用场景

    如果只是为了加快方法的执行速度或是一些简单的使用场景,对队列中任务依赖关系无要求者可选用轻量级的GCD更为合适。

    若是对一组任务之间的依赖关系,或是优先级有特殊要求,或者是需要暂停,恢复,取消任务的则选择 NSOperation 更为合适一些。


    3.RunLoop

    RunLoop 是线程管理的一种机制 ,简单来说就是一个处理程序运行过程中出现的各种事件的循环(触摸事件,UI刷新事件,定时器事件等)从而保持程序的持续运行。RunLoop 会在程序没有事件需要处理的时候,使线程进入休眠状态,节省CUP资源,提高性能。

    ·RunLoop和线程

    每个线程都有一个与之对应的RunLoop对象

    主线程的RunLoop对象系统在程序的Main函数中已经帮我们创建好了,子线程的RunLoop对象由程序员主动管理。

    4.RunTime

    运行时机制,使得OC的函数在编译期间并不决定调用哪个函数,而是在运行期间才会根据函数的名称找到具体的函数来调用。

    OC中的方法调用在运行时都转成了objc_msgSend函数调用,给receiver (方法调用者)发送了一条消息(函数的方法名)。

    如:[obj show]

    在调用时编译器转为消息发送:objc_msgSend(obj, show);

    根据obj的指针获取obj的class

    遍历class的 method list 找到 show 方法

    如果当前class中没有找到 show 方法,则去class的 super class 中遍历 method list

    找到show方法后就去调用它的实现。

    ·如果messageSend找不到相应的对象

        如果对象为空,则消息失效

        如果对象不为空,则程序抛出异常。

    但 此种方法每次收到消息后都需要遍历 class 的 method list 效率较低,所以 objc_cache 在找到要调用的方法后 会将 method_name 作为Key     method_imp 作为Value缓存起来,当再次接收到 method_Name的消息的时候 会先从缓存中查找,避免多次遍历 method List。

    RunTime 在开发中的实际运用

    ·交换方法的实现。(交换系统某些方法的实现,添加校验)

    ·KVO的实现也是也是依赖于RunTime机制,当观察obj对象时,KVO机制会动态的为obj对象的当前类创建一个子类,并重写子类obj属性的setter方法,setter方法会在调用原setter方法之前和之后通知所有观察属性值的更改情况。

    ·访问和修改类的私有属性。通过RunTime遍历类的属性列表,通过 object_getIvar访问私有属性。通过object_setIvar修改私有属性的值。

    ·字典转模型。

    ·关联对象,为分类添加属性。


    5.Http中 get 和 post 的区别?

    ·post 用来发送数据,get用来接收数据。

    ·参数放置的位置不通,post放置在 body 中  get 放置在url中。

    ·get传输的数据量大小有限制,而理论上来说 post 对参数的大小是没有限制的。


    6.数据的持久化方案有哪些?

    ·plist文件 将某些特定的类通过XML的格式保存在目录中(数组,字典,字符串等)。

    ·NSUserDefaults  本地存储一般用来保存App的偏好设置。

    ·NSKeyedArchiver 归档  需遵循 NSCoding 协议

    ·数据库 FMDB 相对于苹果自带的Core Data 来说更灵活 更轻量级,使用上更加面向对象易用性高。


    7.iOS的沙盒机制

    ·iOS 每个程序都有自己的沙盒,与其它应用的沙盒隔离,应用程序智能访问自己的沙盒,保证数据安全。

    ·沙盒目录:


    8.iOS的网络通信方式

    ·ios 网络通信的方法有两大类:使用socket方式进行通信 和 使用asynsocket类库进行通信,建议使用的时候用asynsocket更好些 因为是别人已经封装好的类库,比较稳定 Socket通信的方法更灵活 因为控制都是自己在做的事情。


    9.在网络请求中如何提高性能?

    ·减少请求宽带,使用高效的数据交换格式 比如 json。

    ·压缩数据

    ·通过缓存响应来避免冗余的网络请求都会加速应用并改进用户体验


    10.在网络请求中如何保证安全性?

    ·base64 字节编码。

    ·3DES 数据加密

    ·使用https 请求


    11.#define和const定义的变量,有什么区别?

    ·#define 是宏定义 编译时不会进行数据类型的校验 运行时 不会为它分配内存。

    ·#define 定义表达式时需要注意『边缘效应』

            比如 #define  obj  2+2      int temp = obj / 2    看起来结果应该是 2  但是在编译期间 obj会被替换为 2+2    整个表达式为 2+2/2 结果却等于1  因为在定义表达式时 

    要注意这样定义     #define obj (2+2)。

    ·const 定义的常量在编译是会进行类型校验,运行是会给它分配内存。


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

    ·Block block被copy 并retain  block引用的对象,需要用weak去修饰block引用的对象。

    ·delegate  用weak去修饰delegate 否则也可能会出现循环引用。

    ·Timer  在delloc 去执行Timer invalidate 方法,由于Timer未停止所以controller 不会被释放 因此不会执行delloc方法 导致Timer没有停止,导致循环引用 。应该在controller的viewDidDisappear 调用 invalidate 方法释放Timer。


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

    ·并不是,当block 本身并不被 self 持有同时不产生循环引用的时候就不需要。比如 UIView 的动画代码。在这里 UIView的动画对象持有block ,block 持有self  而 self 并不持有block 动画结束时,UIView 会释放掉block,block会释放掉 self 所以不会产生循环引用。


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

    ·queue  对于queue中所执行的代码不一定都在主线程中执行,如果queue是在主线程中创建的那么就会在主线程中执行,如果是在子线程中创建的就会在子线程中执行。

    ·main queue 中的代码一定会在主线程中执行。


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

    ·成员变量的三种权限   @private(私有的)        

                                            @protected(受保护的) 

                                            @public(公共的)

        .h文件中的成员变量默认是 protected 权限,外部不可以直接访问。(知道变量名的情况下可直接用KVC访问或修改变量,或是直接用RunTime机制遍历类属性列表获取访问修改变量)


    16. MD5和Base64的区别是什么,各自场景是什么?

    ·MD5一般用于密码的加密、文件校验,是不可逆的。

    ·Base64 是一种数据编码格式,可逆 。


    17.哪些类不适合使用单例模式,单例模式有什么优缺点?

    ·同一类型的对象在不同场景下会发生变化的时候不适用于单例。

    ·优点:只创建一次,节约了系统资源。

    ·缺点:单例模式中没有抽象层接口很难扩展,违背了单一原则。


    18.代理delegate 通知Notification Block 三者的使用区别

    ·delegate 和 block 一般用于一对一的交互通信。

    ·delegate 需要定于协议方法,代理对象需要遵循代理,实现协议方法才能通信。

    ·block 使用上比较简洁,但不适用于通信事件较多的场景。

    ·notification 多用于一对多或是跨模块通信的场景,代码可读性较差。


    19,简单介绍KVC和KVO

    ·KVC 键值编码  间接访问或修改对象的属性。(访问或修改类的私有属性)

        底层实现:当一个对象调用 setValue 方法时:

    ~查找是否存在相应key 的set方法,如果存在 则直接调用

    ~如果不存在 则查找与Key相同名称且带下划线的成员变量 如果有 则直接赋值

    ~如果没有找到_key 则会查找相同名称的属性Key 如果有就直接赋值

    ~如果还是没有则会调用 valueForUndefinedKey:和setValue:forUndefinedKey:方法

    ·KVO 键值观察 观察某一属性的方法。 (音乐播放器拖拽进度)

        底层实现:

        ~给 A 类添加KVO时,runTime


    20.简单介绍下苹果的推送机制

    ·安装了应用的设备需要向苹果的远程推送服务器注册,注册成功后会获取一个deviceToken。

    ·拿到deviceToken后将这个deviceToken上传到我们的服务器上。

    ·需要推送消息时,我们的服务器会将推送的消息和需要推送设备的deviceToken发送到苹果的远程推送服务器上。

    ·苹果的远程推送服务器将需要推送的消息发送到指定的deviceToken 设备上。


    21.深拷贝和浅拷贝

    ·深拷贝是将obj复制了一份存在了新的地址下。

    ·浅拷贝是将obj的指针复制了一份,而指针指向的还是原来的obj。

    对于不可变对象来说 如NSString     copy 为浅拷贝,返回不可变对象    mutableCopy 为深拷贝,返回可变对象。

    对于可变对象来说   如 NSMutableString   copy 和  mutableCopy 都为深拷贝,返回的都为可变对象。

    copy: 对于可变对象为深拷贝,对于不可变对象为浅拷贝

    mutableCopy:始终是深拷贝


    22.类别的作用? 继承和类别有什么区别?

    ·类别可以为类添加新的方法,智能添加不能修改或删除。如果类别中的方法名和原类中的方法名冲突,则会执行类别中的方法。

    类别的3个作用:将类的实现分散到多个不用的文件或框架中

                                  创建对私有方法的向前引用

                                   向对象添加非正式协议

    继承和类别的区别:继承可以增加、修改或是删除方法,还可以增加属性。


    23.进程与线程的区别和联系?

    ·进程是系统进行资源分配和调度的一个独立单位,线程是进程的一个实体。

    ·进程有自己的独立的地址控件,有自己的堆栈和局部变量,线程则没有。

    ·一个程序至少有一个进程一个进程至少有一个线程。

    ·进程和线程都是程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。

    ·进程和线程的主要差别在于他们是不同的操作系统资源管理方式。


    24.定义一个NSString类型的属性时为什么用copy  而不用strong ?

    ·定义为copy时,操作属性时等同于copy了一份对象,这个指针会指向新生成的copy对象,当使用copy时,无论是拷贝自NSStrong 或是 NSMutableString 其结果都是不可变的NSString。如果使用strong 则当指针指向的对象改变时,属性值也会发生相应的改变,导致错误。


    25.UIView与CALayer的关系

    ·UIView及负责事件的响应以及内容的展示,UIView是 CALayer的容器

    ·CALayer内容的创建。


    26.UI卡顿掉帧优化

    ·把以下操作放在子线程中进行

            对象创建,调整及销毁

            预排版(布局计算,文本计算,缓存高度等)

            预渲染(文本异步绘制,图片解码等)


    27,nil、NIL、NSNULL 有什么区别?

    ·nil 和 NIL  都代表的是内存中的一块空地址。

    ·NSNULL  代表一个指向nil的空对象。


    28,id 和 instanceType 有什么区别?

    ·相同点:  都是指向对象的万能指针。

    ·不同点:id类型在编译的时候不能确定对象的真实类型,instanceType 可以。

                     id可以用来定义变量、参数类型,返回值类型 而 instanceType 只能用作返回值类型。


    29.js和oc互相调用的几种方式

    ·js调用oc的三种方法

    ~根据网页重定向截取字符串,通过URLscheme判断。

    ~替换方法 context[@"copyText"]

    ~注入对象 遵守协议JSExport,设置context

    ·oc调用js代码 2种

    ~通过 WebView 调用 webView stringByEvaluatingJavaScriptFromString: 调用

    ~通过 JSContext 调用 [context evaluateScript:]


    30.为什么block要用copy修饰?

    ·block 在没用使用外部变量是 是存储在内存中的常量区的,在使用外部变量时 会被存储到栈区 当block copy 后是存储在堆区的,如果是在栈区 block 随时有可能被释放,一但被释放就会造成野指针程序崩溃,所以要用copy关键字。


    31.iOS的签名机制是什么样的?

    ·签名机制

        ~先讲应用内容通过摘要算法,得到摘要

        ~再用私钥对摘要进行加密,得到密文

        ~将源文本、密文和私钥对应的公钥一起发布

    ·验证流程

        ~查看公钥是否是私钥方的

        ~用公钥对密文进行解密得到摘要

        ~将APP通过同样的算法得到摘要进行对比,如果相等 则一切正常。


    32.常用的项目架构  MVC MVP MVVM 

    ·MVC (model 、View 、Controller)model 负责处理数据,View负责展示视图,controller处理逻辑,model与View之间不能相互通信。

    优点:降低了各模块之间的耦合行,提高了view的复用行,代码逻辑更清晰。

    缺点:随着业务逻辑的复杂,controller中的逻辑代码较多,维护较难。

    ·MVP (Model,View,Presenter) Model 负责处理数据,View 可以是View或是ViewController,Presenter负责从Model层获取数据传递给View。

    优点:视图和模型分离,更高效的使用模型。

    缺点:Presenter 除了负责业务逻辑外 也要负责Model-View之间的通信 会导致Presenter层比较臃肿。

    ·MVVM(Model、Controller / View,ViewModel) View和ViewController都不能直接引用Model,而是引用视图模型 ViewModel,ViewModel 用来防止用户输入验证逻辑,视图显示,网络请求等逻辑。

    优点:View可以独立于Model的变化和修改,一个ViewModel 可以绑定到不用的View上降低了耦合行,提高了复用性。

    缺点:过于简单的项目不适应,大型的项目视图状态较多时,构建和维护成本较大。


    33.性能优化

    ·TableView

        ~tableViewCell 的重用

        ~创建时就布局好,避免频繁更新UI

        ~体检计算并缓存cell的高度

        ~尽可能减少cell中控件的数量

        ~不要使用clearColor 会导致渲染时间变长

        ~如果可以局部更新就避免全部更新

        ~加载网络数据,下载图片尽量异步加载,并缓存

    ·如何提高TableView的流畅度

        ~对于不必要响应事件的视图可以考虑用CALayer代替

        ~不要频繁的修改UIView的frame等属性

        ~图片的大小最好和imageView的大小保持一致

        ~尽量将耗时的操作放到子线程中执行

        ~减少视图的数量和层次

    ·iOS界面保持流畅的技巧

        ~预排版 提前计算

        ~预渲染,提前绘制

        ~异步绘制

        ~全局并发

        ~异步加载图片等

    34.如何实现一个自定义对象的深拷贝

    ·自定义类遵循copy协议

    ·实现 copyWithZone方法

    ·在copyWithZone方法中 使用 allocWithZone 创建一个新的对象

    ·将自定义类中的属性深拷贝赋值给新创建的对象

    ·在使用的时候直接调用对象的copy方法即可

    35.GCD

    ·GCD中的2个核心概念   任务  和 队列

    ·任务

        ~任务的执行方式有2中 同步执行和异步执行  

            同步添加任务到指定的队列中,在添加的任务执行结束之前会一直等待,只能在当前线程中执行,不具备开启新线程的能力

            异步添加任务到执行的队列中,不需要等待,可以继续执行任务且可以在新线程中执行,具备开启新线程的能力

    ·队列

       ~GCD中的队列有2中  串行  和  并发

          串行:所有任务一个接一个的执行,每次只有一个任务被执行。(开启一个线程,逐个任务执行)

          并发:可以让多个任务同时执行(可以开启多个线程同时执行任务)

    相关文章

      网友评论

          本文标题:iOS开发基础随笔

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