iOS核心面试题

一、语言

  • 1 . 请简述你对协议的理解

比如说a想做一件事却因为一些原因不能做,于是让b遵循a的一些约定,这样b就可以帮助a做事了。协议中包括了遵循方b需要实现的一些方法,以及b能够做的事情。

  • 2 . 如何理解ARC自动引用计数机制

ARC--自动引用计数 可以用来管理对象的使用以及了解对象的使用情况,当对象引用计数不为0时,对象不会被释放,当对象引用计数为0时 dealloc函数被调用 对象将会被释放。

  • 3 . 如何理解retain/copy/assign/release/autorelease/dealloc关键字

retain让对象引用计数加1,release让对象引用计数减1,当对象引用计数为0的时候会调用dealloc将对象进行释放。copy是你不想让a和b共享一块内存时候,让a和b有各自的内存。在使用基本数据类型的时候需要使用assgin,assgin是直接赋值,会引起对象引用计数加1.
(1)assign:普通赋值, 一般用于基本数据类型,防止循环引用。
(2)retain:保留计数, 获得用户的所有权
(3)copy:用来赋值的对象, 一般字符串使用copy, Foundation中的不可变对象使用copy效果相当于retain,只是引用计数+1.
(4)nonatomic:非原子性访问, 不加同步, 多线程并发访问会提高性能.

  • 4 . 请简述self.name = xxx 和 _name = xxx 的区别

(1) self.name 有getter 和 setter方法
(2) self.name 可以被kvo 监听到 (set 方法 和kvc方法)
(3) self.name 考虑了内存管理 是一个对象指针

self.name实际上是调用了set方法给变量赋值,_name是直接给变量赋值。

  • 5 . 请简述类别和继承有什么联系和区别

类别是对父类进行扩展(运行时的动态),继承是将父类中的属性、方法等保留下来,根据自己的实际情况进行实现。

继承可以增加,修改,方法,还可以增加属性

category可以很方便给现有类添加方法,但是不能添加成员变量,匿名类除外,比如可以给 NSString 增加方法,给UINavigationBar 增加方法,比 SDWebImage 给 UIImageView 增加了 setImageWithURL:方法

  • 6 . 请简述你对strong和weak关键字的理解 以及_unsafe_unretained与weak的区别

strong相当于retain 让对象引用计数加1,防止对象在异常情况下被提前释放,导致崩溃(crash)。weak 弱引用防止产生循环应用无法释放对象和产生野指针。

strong叫做强引用,在ARC中使用strong告诉编译器帮组我们自动插入retain,weak是普通赋值相当于手动管理内存的assign。
_unsafe_unretained与weak功能一致,区别在于当指向的对象销毁后,weak会将变量重置为nil,防止调用野指针,产生EXC_BAD_ACCESS这类的错误。
strong:
@property (nonatomic, strong) NSString *string1;
@property (nonatomic, strong) NSString *string2;
self.string1 = @"String 1";
self.string2 = self.string1;
self.string1 = nil;
NSLog(@"String 2 = %@", self.string2);
结果是:String 2 = String 1由于string2是strong定义的属性,所以引用计数+1,使得它们所指向的值都是@"String 1"
weak:
@property (nonatomic, strong) NSString *string1;
@property (nonatomic, weak) NSString *string2;
self.string1 = @"String 1";
self.string2 = self.string1;
self.string1 = nil;
NSLog(@"String 2 = %@", self.string2);
结果是:String 2 = null
分析一下,由于self.string1与self.string2指向同一地址,且string2没有retain内存地址,而self.string1=nil释放了内存,所以string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。

  • 7 . 请简述weak和assgin有什么区别

weak用于对象,assgin既可以用于对象也可以修饰常量类型
weak弱引用

  • 8 . 如何实现ARC和MRC的混合编程

在targets的build phases选项下Compile Sources下选择要使用ARC编译的文件:  在targets的build phases选项下Compile Sources下选择要不使用ARC编译的文件, 就会出报错。方法如下,双击它 输入 -fno-objc-arc 即可。
在ARC(自动管理内存)工程中引入MRC文件的时候,需要在target-build phrase中进行标记,标记符号为:-fno-objc-arc
在MRC(手动管理内存)工程中引入ARC文件的时候,需要将该文件标记为:-fobjc-arc

  • 9 . Objective-C中是否支持多继承

不支持多继承 因为消息机制名字查找发生在运行时而非编译时,很难解决多个基类可能导致的二义性问题 。可以 通过协议 实现与多继承相似的功能。

  • 10 . Objective-C中变量默认是私有的吗,方法默认是私有的吗

oc中没有私有公有之分
(1)使用private修饰的全局变量是私有的变量
(2)Objective-C在语法上是没有设计私有的方法,不过可以通过延展在实现文件里定义方法作为私有的方法。但不是真正意义上的私有方法,也是可以调用的,只是外部不可见而已。

  • 11 . #include与#import的区别,#import"".h 和@class+类名的区别

(1)#include与#import的区别: #include与#import其效果相同,只是后者不会引起交叉编译,确保头文件只会被导入一次
(2)#import"".h 和@class+类名的区别: import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你。使用#import编译效率高,防止相互包含的编译错误。

  • 12 . 请简述页面传值都有哪些实现方式

Block、委托协议、通知、单例

  • 13 . 请简述深拷贝和浅拷贝的区别

浅复制: 只复制对象本身,不对里面的属性复制
深复制: 不仅复制对象本身,对象持有的属性对象也做复制

深拷贝会重新在堆上开辟一块内存空间 是一个全新的对象 指针地址和原来不一样 浅拷贝不会重新开辟一块内存空间 指针和原来是一样的。

深拷贝和浅拷贝的本质是: 地址相同,就是浅拷贝,地址不同就是深拷贝。
浅拷贝是拷贝操作后,并没有进行真正的复制,而是另一个指针也指向了同一个地址。深拷贝操作后,是真正的复制了一份,另一个指针指向了拷贝后的地址。

二、设计模式

  • 14 . 系统中哪些对象是单例

iOS系统的单例类:
UIApplication(应用程序实例)
NSNotificationCenter(消息中心)
NSFileManager(文件管理):
NSUserDefaults(应用程序设置)
NSURLSession

NSURLCache(请求缓存)
NSHTTPCookieStorage(应用程序cookies池)

  • 15 . 请简述你对MVC架构模式的理解

MVC : Model - View - Controller 模型负责数据任务 试图负责呈现 以及和用于进行交互 控制器用来控制试图
model 模型:主要负责存储和操作数据
view 视图:主要负责展⽰示数据和⽤用户交互
controller 主要负责将model和view联系起来:
从网络获取数据->赋值给数据模型->将model的数据传递给view展⽰示(响应view的delegate和datasource⽅方法)->刷新view

  • 16 . iOS中那些技术符合观察模式

Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。每次指定的被观察的对象的属性被修改后,KVO自动通知相应的观察者。

  应用场景:一般为model层对,controller和view进行的通知方式,不关心谁去接收,只负责发布信息。
  优势:解耦合
  敏捷原则:接口隔离原则,开放-封闭原则
  实例:Notification通知中心,注册通知中心,任何位置可以发送消息,注册观察者的对象可以接收。
  kvo,键值对改变通知的观察者。
  • 17 . 请简述你对工厂方法的理解

使用类方法将基础控件涉及到的常用属性做一归纳总结,方便统一设置和修改

通过一个类来创建一些子类的方法叫工厂方法

  • 18 . 什么是代理模式, 实现代理需要注意什么

代理模式:帮助别人完成别人委托你完成的事情。你需要注意遵守别人给你定的约定,和你是否拥有完成这件事的能力。

三、UI

  • 19 . 请简述StoryBoard和Xib的联系和区别

StoryBoard可以在上面实现整个项目界面的搭建,可以清楚得看到各个试图控制器之间的关系,XIB实现自定义要素和良好部件重用性复杂的UI。

  • 20 . 请简述UITableView对Cell的重用机制

应用场景: 假如说屏幕上能显示 5 个单元格,那么tableView只会创建 6 个单元格,也就是 n + 1 ,当滑倒第7个单元格的时候就会复用第一个单元格对象,因为tableView中有单元池的一个概念,tableView调用协议方法获取单元格的时候,先从复用池里查找是否有可复用的单元格,如果用的话就复用,如果没有的话就创建一个单元格对象

  • 21 . 请简述UIScrollView实现无限加载多张图片

写一个NSTimer 每隔0.5秒 执行以下回调方法timerAction 如果图片数量有限 进行一个if判断 当超过图片总数时候,显示第一张,重新开始从第一张显示。

  • 22 . 请简述视图控制器的生命周期
当一个视图控制器被创建,并在屏幕上显示的时候。 代码的执行顺序

1、 alloc 创建对象,分配空间
2、init (initWithNibName) 初始化对象,初始化数据
3、loadView 从nib载入视图 ,通常这一步不需要去干涉。除非你没有使用xib文件创建视图
4、viewDidLoad 载入完成,可以进行自定义数据以及动态创建其他控件
5、viewWillAppear 视图将出现在屏幕之前,马上这个视图就会被展现在屏幕上了
6、viewDidAppear 视图已在屏幕上渲染完成

当一个视图被移除屏幕并且销毁的时候的执行顺序,这个顺序差不多和上面的相反

1、viewWillDisappear 视图将被从屏幕上移除之前执行
2、viewDidDisappear 视图已经被从屏幕上移除,用户看不到这个视图了
3、dealloc 视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行释放

  • 23 . UITableView有哪些优化方法

asd

  • 24 . 请简述iOS中的事件传递机制

举例:如果view是控制器的view,就传递给控制器;如不是,则将其传递给它的父视图 在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理 如果window对象也不处理,则其将事件或消息传递给UIApplication对象 如果UIApplication也不能处理该事件或消息,则将其丢弃

注意:为什么用队列管理事件,而不用栈?
队列先进先出,能保证先产生的事件先处理。栈先进后出。

UIEvent
iOS封装成UIEvent->前景App(RunLoop事件)->UIApplication->UIWindow(keyWindow)->ViewController->View.........在进行事件传递的时候会经历hitTest: Event

从View层反过来就是响应者链

  • 25 . UITableView有哪些必须要实现的数据源方法
 // 获得section包含的cell个数
  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 
  //创建UITableViewCell
  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

四、网络

  • 26 . 请简述Http协议中Get请求和POST请求的区别
GET是从服务器获取数据, POST修改数据

安全性的问题: GET请求的参数全部暴露在接口中,一般叫做明文请求或者傻瓜式请求, POST请求的参数一般是以字典的方式进行拼接,相对于GET比较安全
对文件大小的要求: GET不允许向服务器上传文件(图片,pdf,音视频)
如果从服务器获取数据或者查询数据使用GET请求,如果上传数据到服务器或者修改服务器上数据使用POST

  • 27 . 请简述你对异步请求数据的理解

更好的用户体验: 减少卡顿 假死的现象。因为异步请求数据不会一直等待某个任务完成才执行另外一个任务,可以同时进行的
同步、异步
串行、并行
进程、线程

  • 28 . iOS中都有哪些技术可以实现开辟线程,它们的联系和区别是什么

开辟线程可以用GCD、NSOperation、NSThread
多线程在iOS中用的比较多,比如说每个ASI请求,SDWebImage请求,数据请求等待网络数据处理,多线程/异步就是主要是为了界面流畅,防止界面假死。

每一个ASI请求就是一个NSOperation
每一个NSUrlConnnection也是一个线程
NSthread是创建线程的一个通用的类。比如线程创建,取消,开始等。
NSOperation就是一个简单的以任务为导向的多线程模型。目的是为了不懂操作系统,不懂线程的人使用的
GCD类似于NSOperation,是一个blocks版本的线程模型

...

1.NSThread
2.NSOperationQueue
3.GCD

区别:
Thread是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程之间的同步。线程共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。你得协调多个线程对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在iOS中我们可以使用多种形式的thread:

Cocoa threads:使用NSThread或直接从NSObject的类方法performSelectorInBackground:withObject:来创建一个线程。如果你选择thread来实现多线程,那么NSThread就是官方推荐优先选用的方式。

Cocoa operations是基于Obective-C实现的,类NSOperation以面向对象的方式封装了用户需要执行的操作,我们只要聚焦于我们需要做的事情,而不必太操心线程的管理,同步等事情,因为NSOperation已经为我们封装了这些事情。NSOperation是一个抽象基类,我们必须使用它的子类。iOS提供了两种默认实现:NSInvocationOperation和NSBlockOperation。

Grand Central Dispatch (GCD): iOS4才开始支持,它提供了一些新的特性,以及运行库来支持多核并行编程,它的关注点更高:如何在多个cpu上提升效率。

  • 29 . NSThread中线程之间是如何实现通信的
  • 30 . GCD中有哪些创建线程方式

CD 中 Queue 的种类还要看我们怎么进行分类, 如果根据同一时间内处理的操作数分类的话, GCD 中的 Queue 分为两类

  1. Serial Dispatch Queue2. Concurrent Dispatch Queue
    一类是串行派发队列, 它只使用一个线程, 会等待当前执行的操作结束后才会执行下一个操作, 它按照追加的顺序进行处理. 另一类是并行派发队列, 它同时使用多个线程, 如果当前的线程数足够, 那么就不会等待正在执行的操作, 使用多个线程同时执行多个处理.
    另外的一种分类方式如下:
  2. Main Dispatch Queue2. Global Dispatch Queue3. Custom Dispatch Queue
    主线程只有一个, 它是一个串行的进程. 所有追加到 Main DispatchQueue 中的处理都会在 RunLoop 在执行. Global Dispatch Queue 是所有应用程序都能使用的并行派发队列, 它有 4 个执行优先级 High,Default, Low, Background. 当然我们也可以使用 dispatch_queue_create创建派发队列.
  • 31 . iOS中有哪些技术可以保证线程安全

线程锁 NSLog

  • 32 . ASIHttpRequest的父类是什么, 被废了

ASIHTTPRequest是一款极其强劲的HTTP访问开源项目。让简单的API完成复杂的功能,如:异步请求,队列请求,GZIP压缩,缓存,断点续传,进度跟踪,上传文件,HTTP认证。
它是NSOperationQueues的扩展,小而强大。
但也与它的父类略有区别。
如,仅添加到队列中其实并不能执行请求,只有调用[queue go]才会执行;
一个正在运行中的队列,并不需要重复调用[queue go ]。
默认情况下,队列中的一个请求如果失败,它会取消所有未完成的请求。
可以设置[queue setShouldCancel];

  • 33 . 请简述AFNetWork的实现原理

AFNetworking是实际项目中最常用的一个网络请求库,目前在github下载量排名第一,对应的版本最新的为3.0, 2.0以前封装自系统的NSURLConnection, 3.0之后(iOS9之后出来的), 封装自系统的NSURLSession,主要使用异步数据请求,还可以检测网络状态,缓存图片。

涉及到的常用的请求方式有GET和POST

创建一个get请求无参数
  func dataRequestWithGet1() {
   // http://d.yixincao.com/interface/getdata.php?act=list&type=nuanwen&page=1 GET请求的参数一般是以&拼接的
   // 创建请求管理类
    let manager = AFHTTPSessionManager()
    // 参数1: 请求的借口
    // 参数2: 需要的参数
    // 参数3: 请求成功的回调
    // 参数4: 请求失败的回调
    >
   // 设置contentType, 默认情况下表示的是application/json,如果为text/html格式的话需要手动设置
    manager.responseSerializer.acceptableContentTypes = NSSet(object: "text/html") as! Set
   // 设置解析器的类型
    // AFNetworking在默认情况下对数据做了解析,返回的是json格式
    manager.responseSerializer = AFHTTPResponseSerializer()  // 将数据转为二进制流
              manager.GET("http://d.yixincao.com/interface/getdata.php?act=list&type=nuanwen&page=1", parameters: nil, success: { (dataTask:NSURLSessionDataTask?, responseObject:AnyObject?) -> Void in
        >
       // dataTask表示数据任务
        // responseObject表示请求到的数据(二进制流或者json格式), ,如果是json格式的话,返回的类型可能为数组、字典或者NSData
        print(responseObject!)
       }) { (dataTask, error) -> Void in
            print("请求失败\(error)")
    }
   }
创建一个get请求携带参数
  func dataRequestWithGet2() {
    >
   // http://iappfree.candou.com:8080/free/applications/limited

   let manager = AFHTTPSessionManager()

   // 参数
    let dic = ["currency": "rmb","page": "1"]
   manager.GET("http://iappfree.candou.com:8080/free/applications/limited", parameters: dic, success: { (dataTask, responseObject) -> Void in       
        print(responseObject)
        }) { (dataTask, error) -> Void in
            print(error)
    }
  }
POST请求
   func dataRequestWithPost() {  
    let manager = AFHTTPSessionManager()     
    // 解析器的设置和contentType的设置和get请求一样
    // 出现请求失败: 原因是Request failed: unacceptable content-type: text/html
    manager.responseSerializer.acceptableContentTypes = NSSet(object: "text/html") as! Set      manager.POST("http://d.yixincao.com/interface/getdata.php?act=list&type=nuanwen&page=1", parameters: nil, success: { (dataTask, responseObject) -> Void in       
            print(responseObject)
        }) { (dataTask, error) -> Void in
            print(error)
    }
  }
  • 34 . 你如何理解block,block有什么用途

在oc中叫代码块,是一个函数指针,本质是一个对象,可以回调可以进行反向传值,在swift中叫闭包,

⚠️ block在ARC和MRC的表现是不同的

  • 35 . 请简述TCP和UDP的区别

TCP传输可靠有保证,它有三次握手机制,这一机制保证校验了数据,保证了他的可靠性。而UDP就没有了,所以不可靠。不过UDP的速度是TCP比不了的,而且UDP的反应速度更快,QQ就是用UDP协议传输的,HTTP是用TCP协议传输的。

  • 36 . 请问怎么样能够保证定位更省电

desiredAccuracy,这个属性用来控制定位精度,精度越高耗电量越高,所以应该看实际情况设置这个属性的值。

  • 37 . 请简述SDWebImage的实现原理

SDWebImage是用来加载网络图片的第三方库,实现了异步请求数据,并且实现了图片的缓存

实现原理 :
在内存和沙盒目录下各缓存一份文件,内存中的文件到一定程度会自动清除,沙盒目录下的文件需要由用户手动清除,首先检测内存-检测沙盒目录-网络请求(就是省流量)

  • 38 . 请简述XML和Json数据各有哪些优势

k

  • 39 . 请简述线程和进程有什么联系别区别

五、数据操作

  • 40 . 请简述NSUserDefaults的使用场景和使用注意事项

对于NSUerdefaults来说 一般可以用来保存用户的偏好设置 比如登陆账号 密码这些。 除此之外 我们还可以用它来保存图片, 字符串 , 数字 和对象。它被保存到项目中的Plists文件里面里。保存图片 一般用它里面的两个方法 图片保存可以用PNG或者JPG对应的方法 先转换成NSData 再用NSUerdefaults保存 保存的时候为了让它马上存下来要用synchronize 。它还可以用来在程序间进行反向传值。

  • 41 . iOS中数据库使用什么技术实现的
  • 42 . 请简述什么是主键、什么是外建

主键是用来唯一确定一条记录的唯一标记,如身份证号码。外键是用来关联其他表,可以通过这个外键唯一确定另外一张表上面的字段。如:A表中有个字段是B表中的主键,那么这个字段就是A的外键。

  • 43 . iOS中如何实现数据模型的存储

使用归档来实现

  • 44 . 请简述iOS的沙盒机制

OS中的沙盒机制(SandBox)是一种安全体系,防止iOS程序之间互相访问,它规定了应用程序只能在为该应用创建的文件夹内读取文件,不可以访问其他地方的内容。所有的非代码文件都保存在这个地方,比如图片、声音、属性列表和文本文件等。
1.每个应用程序都在自己的沙盒内
2.不能随意跨越自己的沙盒去访问别的应用程序沙盒的内容
3.应用程序向外请求或接收数据都需要经过权限认证

六、项目

  • 45 . 如何实现真机调试
  • 46 . 如何查找项目中的内存泄漏
  • 47 . 项目中的支付环节如何实现的
  • 48 . 如何实现项目上线到AppStore
  • 49 . 请简述你在项目中遇到过哪些问题,如何解决的
  • 50 . 如何实现流媒体格式的视频边播放,边缓存

七、

  • 增加题
    • 1 . 请简述你理解的内存管理
    • 2 . 请简述你理解的面相对象思想
    • 3 . 如何设计一个缓存类
    • 4 . 谈谈你对蓝牙技术的了解
    • 5 . iOS8.0 都有哪些新特性
    • 6 . 什么是懒加载?
    • 7 . 在ARC下发生内存泄漏怎么处理
    • 8 . GCD (异步的Block )中 self. 的处理
    • 9 . APNS 推送的实现过程
    • 10 . 添加 NSNotificationCenter 监听,其后面的 object 的意义是什么
    • 11 . 谈iOS的常用加密方式,以及各方式的优劣
    • 12 . 论Socket 和 http 协议的区别
    • 13 . iOS中数据的持久话存储方式有哪些
    • 14 . 什么是 KVC/KVO 及它们之间有什么关系
    • 15 . iOS中 frame 和 bounds 的区别

(1) Frame: frame的view是在父视图的view坐标系中的位置和大小(参照的是父视图的坐标系),但是当view做了transform(形变)的时候,他的值就不准确了
(2) Bounds: bounds的view是在本身坐标系的位置和大小 (参照点是本身的坐标系统)

  • 16 . 服务器连接三次握手
  • 17 . GCD有哪三种队列和用法
  • 18 . CALayer和UIVIew和绘图API的关系
  • 19 . 介绍动画矩阵变换算法

你可能感兴趣的:(iOS核心面试题)