iOS核心面试题

2016-10-31  本文已影响59人  Wen_Wei_Yen

一、语言

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

ARC--自动引用计数 可以用来管理对象的使用以及了解对象的使用情况,当对象引用计数不为0时,对象不会被释放,当对象引用计数为0时 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:非原子性访问, 不加同步, 多线程并发访问会提高性能.

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

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

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

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

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

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。这样的好处能有效的防止野指针。

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

在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

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

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

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

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

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

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

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

二、设计模式

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

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

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

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

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

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

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

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

三、UI

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

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

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

当一个视图控制器被创建,并在屏幕上显示的时候。 代码的执行顺序

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

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

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

asd

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

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

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

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

 // 获得section包含的cell个数
  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 
  //创建UITableViewCell
  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

四、网络

GET是从服务器获取数据, POST修改数据

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

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

开辟线程可以用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上提升效率。

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创建派发队列.

线程锁 NSLog

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

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<NSObject>
   // 设置解析器的类型
    // 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<NSObject>      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)
    }
  }

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

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

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

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

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

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

k

五、数据操作

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

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

使用归档来实现

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

六、项目

七、

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

上一篇 下一篇

猜你喜欢

热点阅读