• iOS技术面试题


    OC:分类(优点。和延展的差别)block(原理,底层,作用。)代理循环引用(原因,解决)、内存

    分类 : 一般用于扩展一个类的方法,它可以不用创建一个新的类,可是不可以扩充成员变量,使用分类重写本类的方法后无法再调用原来的方法,使用分类还可以将一个类的定义写在不同的文件内,可以拆分业务逻辑,使一个分类的功能更专一

     

    延展(extension)延展相当于匿名的分类。一般写在实现文件中面(.m文件)。它能够扩充私有变量和方法。可是变量和方法仅仅能在本文件内有效(私有的),其它文件不能够调用。(而且一般不会有人通过延展扩充方法)。

     

    继承 使用继承扩充一个类。须要再创建一个子类,能够扩充成员变量和方法,能够重写父类的方法,并且能够通过super调用父类的方法。可是因为继承于父类.

     

    block

    1.保存代码。

    一段代码在合适的时间运行就调用block(1、请求成功时弹出一个提示框 2、异步运行完之后回调)。

    2block一般用来两个的类的数据逆传递(改动昵称,姓名。性别的时候) A-B  B往

    A传数据。

    3.block也能够将一个操作当做函数或方法的參数来传递

     

    代理的循环引用    

    Delegate使用weak来修饰?      循环引用 

     

    比如在tableviewController其中,tableView的Delegate使用weak来修饰,假设使用strong或者copy修饰,delegate作为tableview的一个成员变量,tableViewController会有一个强指针指向tableView,而tableview会有一个强指针指向delegate,这个时候delegate的引用计数就会加1,普通情况下tableview的代理都是指向自己的控制器,由于delegate使用strong修饰,所以delegate会有一个强指针指向tableViewController。tableViewController的引用计数也会加1,tableviewController和delegate创建时引用计数初始化都是1。此时它们的引用计数都是2,再ARC机制下,当控制器移除时,它们的引用计数会自己主动减1,然后各自的引用计数都是1,就再也不会释放了,这个时候就会照成内存泄露

     

    简单点说:

    (在tableViewController中delegate使用strong修饰时,delegate会有一个强指针指向controller,而controller会对内部的delegate做一次retain操作。就会有一个强指针指向delegate,当内存释放是。controller要释放就要等delegate先被释放,而delegate释放要等controller先释放,这个时候谁都无法释放,就造成了循环引用)

     

    内存

     

    在OC其中没有垃圾回收机制(GC),而是使用引用计数 来管理内存的释放,OC中有手动引用计数(_MRC)和自己主动引用计数(ARC)当oc中的对象使用alloc new 创建时引用计数就会加1,被retain、copy一次引用计数也会加1,当被release 或 autorelease时 引用计数减1,当引用计数下降为0时,该对象的内存就会被释放,对象被销毁

     

    在ARC中我们已经无需再手动管理内存的释放,ARC并非oc的特性。而是xcode编译器的特性,xcode会自己主动帮我们加上release 或autorelease等代码

     

    内存优化: 1、懒载入(1、使用时再载入 2、保证对象仅仅创建一次 )

                          2、复用 轮播 两个imageView复用 或者用collectionView做无线轮播

                          3、使用CF开头的东西一定要记得释放

                          4、切图:背景仅仅须要切一小条即可 1K 2K    启动图片通常是10K 20K         

                          5、profile ->  leaks   检查内存泄露 

                        

     

    UItableView循环利用(原因,流程)    数据持久化(详细用哪一种)     手势    UIView动画  

    在tableView中第一次显示cell时。会创建新的cell(cell会相应一个标识)而且仅仅显示当前tableView展现出来的数量,当cell从tableView中消失时。会被放入到tableView的缓存池其中,下一个cell出现时不会又一次创建新的cell ,而是先从缓存池中拿出相应标识的cell使用。可是缓存池的cell包括着上一次的图片,而我如今要显示的cell并没有图片,所以会出现利用有图片的cell。全部布局混乱

     

    而想要解决问题,1、都有label,都要显示文字:就是当cell出现时使用数据给其赋值(覆盖掉原有的数据)。将数据和cell绑定,这样能够覆盖缓存池中cell的数据,当然也能够在其显示曾经将其数据清空   2、要显示的cell没有图片。而缓存池中的cell有图片:在setTopic里推断要显示的cell是否有图片,假设有就把传给cell的topic模型里的图片数据赋值给图片控件,假设没有图片,将图片控件hidden

     

     

    数据持久化

    经常使用的数据持久化方式有:

             属性列表(plist文件)

            归档(存储自己定义的类的对象时;存储用户的数据(昵称。uid))

            偏好设置(NSUserDefault(存储一些简单的数据(用户的设置)))

            sqlite3、core data、FMDB(大量数据的时候)  

            createtable student IF NOT EXISTS (id integer, name text, age text)

     

                                    

    当有少量基础数据类型的数据和NSArray、NSDictionary须要储存而且无需加密时,就以使用plist文件

     

    储存少量的数据,并且须要加密,比方登录password、获取的accessToken时,或者须要储存对象。比方做收藏夹、近期訪问,都能够使用键值归档

     

    偏好设置的话就是储存一些用户设置信息。比方程序中设置其中的一些开关的Bool值等版本等等

     

    当须要储存大量的数据时,比方须要离线缓存一些数据。就须要使用数据库了,sqlit3是c语言的东西,使用起来不是特别方便,而FMDB是封装的sqlite3使用起来比較方便,所以一般开发其中都是使用FMDB

     

    UIView动画 是对Coreanimation的封装

    Core animation:

    组动画:运行一组动画

    属性动画:基础动画  关键帧动画

    转场动画:能够自己定义

     

    使用:

    1.创建动画对象   CAKeyFrameAnimation * anim = [alloc] init];

    2.设置属性  keyPath = @“layer 的属性”    而且支持KVC

    3.加入到layer上自己主动运行。

     

    注意:1、coreanimation动画并不会真正改变frame 仅仅是作用有layer

                 2、core animation动画运行完会自己主动回复到原来的位置。假设不想让其恢复。fullModel complateXXX 

     

     

    GCD  NSOperationQueue(底层、经常使用的函数,什么时候用)

    在开发过程其中使用的多线程方式一般有三种。NSThread,NSOperation/NSOperationQueue,GCD

     

    NSThread须要手动管理线程的生命周期,使用NSThread能够中途取消任务。也能够设置线程的优先级(0-1 越大优先级越高,默认都是0.5)在NSObject中苹果官方对其进行了封装

    能够直接调用

     

     

    -(void)performSelectorInBackGround:(SEL)aSelectorwithObject:(id)arg;

    在后台直接调用一个方法运行。本质就是自己主动建一个线程,然后在当中运行一个操作

     

    -(void)performSelector:(SEL)aSelectoronThread:(NSThread*)the withObject:(id)arg waitUntilDone:(BOOL)wait

    在指定线程上运行一个操作。须要用户创建一个线程对象

     

    -(void)performSelectorOnMainThread:(SEL)aSelectorwithObject:(id)arg waitUntilDone:(BOOL)wait;

    在主线程运行一个操作

     

    -(void)performSelector:(SEL)aSelectorwithObject:(id)arg afterDelay:(NSTimeInterval)time;

    另开一个线程延迟指定时间后再运行这个操作

     

     

    NSOperationQueue 是一个线程队列 能够创建一个NSOperation对象来放入队列中运行,通常是使用NSOperation的子类来创建一个任务,NSOperation有两个子类,一个是NSInvocationOperation 还有一个是NSBlockOperation,使用NSOperationQueue能够设置最大线程并发数量,而且能够使用[operation1addDependency:operation2】来_加入依赖,operation1须要等到operation2运行完成后再运行

     

    GCD

    GCD是一种基于C语言的一种多线程开发机制,

    在GCD其中有两种队列  串行队列:在当前线程运行,加入在其中的任务依照顺序依次运行

                                   并发队列:将加入进来的任务分配在可用的处理器上,同一时候运行。

     

    在GCD中也有两种运行方法。dispatch_async 异步运行

                                          dispatch_sync  同步运行

    能够通过dispatch_queue_t queue = dispatch_queue_creat(“你的队列名”,DISPATCH_QUEUE_SERIAL)

    来创建一个串行队列

     

     

    通过dispach_get_main_queue() 获得主队列 一般在主队列中运行更新UI的方法

     

     

    而获取并发队列的方法类似 dispatch_queue_creat)(“你的队列名”,DISPATCH_QUEUE_CONCURRENT)

    可是一般在开发中我们无需创建一个新的并发队列。我们能够通过

     

    dispatch_get_global_queue 来获取一个全局并行队列:  

     

     

    以下说一下GCD其中经常使用的方法

    dispatch_apply():反复运行某个任务,只是这种方法没有办法异步运行(只是能够用dispatch_async包装一下就OK了)

    dispatch_once() 这种方法仅仅会运行一次。从此以后在程序没有退出曾经就不会在运行,一般用来自己定义一个单例对象是使用

    dispatch_after()能够延迟一定时间运行一个任务,而且是异步的。

     

     

    尽管多线程可以提高程序的性能,可是有时候当多个线程抢夺同一个资源是就须要使用线程同步了 NSThread使用线程同步一般可以使用NSLock同步锁。还有NSCondition, 可是一般使用@synchronized(self){   }代码块,这样比較方便

     

    @synchronized(self){

            // 改动

    }

     

    {

    NSlock  l = [NSLockalloc]init];

     

    [l lock];

     

    // 改动操作

     

    [l unlock];

     

    }

     

     

    网络编程:AFN 和 ASI

    AFN和ASI都是网络请求数据的框架 可是它们两个有非常大的差别

    1.AFN直接操作的对象是AFHTTPClient 它是一个实现了NSCoping协议的NSObject子类,AFHTTPClient是一个封装了一系列操作方法的工具类,处理请求的操作类是一系列单独的。基于NSOperation封装的。AFURLConnectionOperation的子类

    ASI的直接操作对象是ASIHTTPRequest,是一个实现了NSCoping协议的NSOperation子类initialize和initwithURL:方法中初始化相关属性并配置一系列请求相关參数默认值,此外ASIHTTPRequest还提供了一系列方法用来配置请求对象

    2.AFN对JSON,XML。Plist,Image四种数据进行了处理。开发人员能够直接得到想要的数据类型

    ASI没有针对数据做不论什么处理。仅仅是预留了接口共开发人员使用

    3.AFN是基于NSURL框架。而且仅仅提供异步调用方法,回调时使用block

    ASI是基于CFNetwork框架,提供了同步异步两种方法,回调是能够使用代理。也能够使用block

    4,ASI的底层是CFNetwork,而AFN的底层NSURL也是基于CFNetwork开发的,所以ASI比AFN更加底层

    5,当项目网络逻辑不是特别复杂的时候能够使用AFN更加方便,当项目比較大。网络定制型要求高时。就能够考虑使用ASI

     

     

    SDWebImage的底层

    SDWebImage是使用NSOperation/NSOperationQueue进行异步载入图片,当它载入图片后会在程序沙盒下的缓存目录中创建一个目录。将下载的图片资源储存在目录其中,图片名就是图片的下载路径,当下次再次须要载入图片时,它会先在缓存目录中依据路径名进行查找假设找到就直接使用,假设没有再从网络上下载

     

     

    项目:

    自适应Cell(流程)  

    1、自己定义Cell

    2、最好对控件进行分层设计,这种设计方式能够添加代码的复用性。看起来也比較清晰,更改需求时,代码的变动也比較小

    3、计算每一个控件的frame。创建frame模型 。里面计算每一个控件的frame

    4、通过VC拿到frameModel   1、返回每一个cell的行高 2 把frame模型传给cell,给相应的控件frame赋值

     

    程序构架

     

    1、观察分析原型图

    2、设计架构:是tabBarVC包括 多个navigationVC还是其它的情况

    3、多控制器切换的话:假设4、5个VC,不须要考虑VC复用,假设20多个VC,考虑控制器的复用:1、3个tableView的循环利用 2、collectionView的cell中放tableView

     

    1、写框架前 要细致分析各个模块及控制器之间的跳转和依赖的关系,比方分析一下看看这几个控制之间有没有什么样的view是能够重用的。假设有的话。能够自己定义一个view。以备以后重用时简单

     

    自己定义控件(流程)

    自己定义控件常常使用,普通情况下。自己定义一个控件首先你要知道这个控件是干嘛用得。它需不须要显示图片,文字,需不须要点击。需不须要变动frame等,然后依据相应的需求留下相应的接口。比方点击一个自己定义控件,那这个控件须要通知控制它被点击了,简单情况下假设仅仅有一个button。仅仅须要通知一个控制器,就能够通过外部定义一个 add_Target方法连接内部的button的addTarget方法

     

    假设view处理的逻辑比較复杂须要使用代理协议来传递很多其它的信息,參数。假设一处点击须要通知多个控制器进行响应,就须要用到KVO。保证自己定义控件与其它控件或控制器之间尽量没有不论什么关系。调用时就是通过控件在.h中留下的方法(接口)进行操作的,减少耦合性。

     

    适配:

    适配原来使用的是autoResizeing。如今在storyboard和xib中通常是使用autolayout

     

    适配时使用的第三方有    masonry

    基于iOS SDK 的布局分类 UIView+AutoLayout

    高寿东:SDAutoLayout

     

     

    masonry的代码十分简洁。使用链式语法,使用起来也十分方便。以下说一下主要使用方法,比方布局一个view让它在显示居中。宽高都是100

    [viewmas_makeConstraints:^(MASConstraintMaker *make) {

           make.center.equalTo(self.view);

           make.size.mas_equalTo(CGSizeMake(100, 100));

    }];

     

    这样就完毕了一个居中view的布局。这里面可用的属性有top,bottom,left,right,width,height,leading,trailing,centerX,centerY,baseline事实上还能够直接使用center,edges内边距

     

    masonry一共同拥有3种布局方法

     

    mas_makeConstraints:创建一个新的约束,在autoLayout中对同一个对象设置多个反复约束会报错

     

    mas_updateConstraints:更新在block中出现的约束。不会出现反复的约束

     

    mas_remakeConstraints:清除之前的全部约束。仅保留block中的新的约束

     

    设置约束的方法也是三种

    mas_equalTo()等于

    mas_greaterThanOrEqualTo()

     大于等于mas_lessThanOrEqualTo() 小于等于

     

    UIView+AutoLayout的使用

    更接近autoLayout的底层,有三种设置方式,

    第一种以autoSetDimension开头的,约束size类(就是设置宽高)

     

    另外一种以autoPin开头。约束位置的(就是设置距离上下左右的距离)

     

    第三种以autoAlign开头,约束对齐(就是设置XY轴对齐的)

     

    语法简单一看就知道了

     

    百度地图。及友盟分享

     

    百度地图:

    百度地图的集成过程并不复杂,下面是集成时须要注意的几点

     

    1.在官网注冊应用。获取appkey.

    2.下载SDK并导入项目中。

    3.加入必要的框架。

    4.注冊appkey。

     

    遇到的问题:

    0.百度地图的静态库使用c++编写的,所以项目中至少有一个.mm文件,不然会报错。

     

    1.在appDelegate中启动百度地图引擎时,设置代理。在回调方法中提示错误參数230(假设正确的话是0)   解决的方法:这个时候你须要注意你的info.plist文件里的Bundle identifier 还有project里面的Bundle identifier 应该和你申请appkey 的时候填写的sdk 安全码不一致

     

     

    2.提示引擎启动失败,这个通常是由于你拉入忘记拉入mapapi.bundle了

    由于以后迅雷就不再更新.a 静态库了,所以在此使用的是BaiduMapAPI.framework,可是上述问题是两种类型都会遇到的问题

     

    收藏、近期

     

    收藏和近期主要就是封装一个业务类对数据进行添加和删除,保存数据时要重写数据的equalto方法(由于计算机是依据内存地址比較的,而有时候内存地址尽管不同,可是储存的数据确实一样的,所以一般依据数据的位置标识(比如id值)比較)

    假设是做近期,就须要将上一次的数据删除,加入新的数据进来,假设在收藏时须要记录控件的编辑和选中状态,就须要在数据模型中加入对应的属性,利用数据来控制控件的状态

    常出现的问题就是使用tableview时会出现循环利用的问题,这个问题就能够使用数据的值来避免,每次载入cell时,他的状态是受数据控制的,数据不会发生循环利用的问题。这个问题也就不会出现了

     

     

    FMDB

    使用FMDB的流程

    1创建一个库 

    2建一个表(表里面要定义你要储存的数据类型,就是字段())——》

    3然后就是插入数据,改动,删除,查询数据

    创表语句:create table  if  not exists t_student (id ingtger autoincrement primary key, name text, age integer)

     

    增删改查必须记住

     

     

    推送流程

    本地推送一般能够用来提示长时间未进入应用的用户,也能够用来做闹铃。

     

    (一个程序能够推送,首先你要配置推送证书)

    以下具体说一下远程推送的流程:

     

    1.当你的程序须要推送时,通过UIApplication中的registerUserNotification注冊远程推送,注冊后。你的程序会通过iOS系统向APNsserver请求,APNsserver接到请求后会将请求设备的device token(设备令牌)发送回你的应用,在UIApplication的代理方法中能够接收到device token,假设请求失败也会通过代理方法返回错误信息

     

    2.当应用程序拿到device token后。就能够将device token传给应用提供商server。server就知道了这台设备能够推送消息了。然后将device token储存在server内部,device token的生成算法仅仅有苹果公司才知道,所以为了防止苹果改动算法造成推送失败,最好每次启动程序时都请求一次device token。在device token发生改变时。告诉server新的device token

     

    (推送普通情况下是程序提供商向用户推送一些最新的消息或者资讯,只是比方QQ,微信等能够在离线的情况下进行消息的提醒,以下以qq推送离线消息为例。相比从server推送,qq离线消息的推送是由client编辑信息的)

     

    3.如今假设程序要推送消息了,就能够将消息和要发送的对象的账号发送给程序提供商server,server会通过你要推送的对象的账号信息找到相应绑定的device token,然后将推送消息内容和device token传给APNsserver

     

    4.APNsserver在接收到消息内容和device token后会查找已注冊的设备然后将相应的信息和device token推送到指定的设备上,设备通过device token中的app id找到要推送的app。然后信息会依照app的推送设置显示信息

     

    二维码

    做二维码的话,能够使用的第三发库有ZBar和ZXing 详细用法能够去网上查看文档

    可是如今iOS中的AVFoundation框架中也集成了二维码扫描。用起来也十分方便,而且扫描速度也更快,性能更好。还能够使用AVFoundation框架生成二维码

     

  • 相关阅读:
    awk中执行Linux命令的两种方式
    Hibernate-validator校验含javax.validation.constraints注解的对象其首次校验长耗时问题
    Linux系统查看端口常用命令
    简要记录搭建Nexus私服过程(发布和使用)
    简要记录搭建Nexus私服过程(配置)
    简要记录搭建Nexus私服过程(安装)
    [转载] jar包和war包的介绍和区别
    linux-exec
    linux-vim格式设置
    linux-array
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7270680.html
Copyright © 2020-2023  润新知