iOS之2016面试题三
1.OC内存管理机制
1).当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为 1.当你不再使用该对象时,你要负责向该对象发送一条release或autorelease消息.这样,该对象将在使用寿命结束时被销毁.
2).当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理.如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它.
3).如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等.
2.代理的作用,优点是啥?
代理的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。 另外一点,代理可以理解为java中的回调监听机制的一种类似
优点:1、避免子类化带来的过多的子类以及子类与父类的耦合
2、通过委托传递消息机制实现分层解耦
3.界面ID
界面传 ID 有两个方向:a,上级界面(当前界面)传给下级界面(待打开界面),这时直接在下级界面设置 ID 对应的属性即可,上级界面在打开下级界面之前,给下级界面 ID 属性赋值;b,下级界面传值给上级界面,这时用代理(这个就不说了),或者 block (带 ID 参数的 block)。方法是:下级界面定义一个 block,带 ID参数,上级界面打开下级界面之前,实现该 block;下级界面在触发了相应的事件后,调用该 block
4.记住上次浏览记录
进入应用后,停留在上次界面。这个相对简单,有几步:a,打开某个界面后,记录当前的界面(可以在 viewDidLoad 中记录);b, 在 AppDelegate 里面 (didFinishLoading。。 那个),查找 a 中的记录,如有,则把相应的 controller 赋值给 window 的 rootViewController (如果有 push,则要逐层建立 controller,然后逐个push 直至相应界面)
5.Json的格式
假定人名的key 为 name,年龄的 key 为 age:{"name":"张三”, "age":"20"}
JSON 是一个规范,有点像 NSDictionary,基于 key-value 的结构
6.readwrite,readonly,assign,retain,copy,nonatomic属性的作用
1).readwrite 是可读可写特性,需要生成getter和setter方法时
2).readonly 是只读特性,只生成getter方法,不会生成setter方法,不希望属性在类外改变
3).assign 是赋值特性,setter方法将方法传入参数赋值给实例变量,仅设置变量时
4).retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1
5).copy 表示赋值特性,setter方法将传入对象复制一份,需要完全一份新的变量时。(对于字符串和block基本上用copy,对于字符串,如果赋给属性的是一个Mutable的字符串,如果不用copy,那么在其他地方做了修改后,属性也会相应的改变——如果不希望这样的话,用copy;对于block,应用copy。copy会确保属性中的block是分配到堆上,后面调用的时候,不会报错;如果不用copy,并且block是分配在栈上的话,可能就crash了。【堆:应用级内存,在应用生命周期内,堆都是有效的;栈:方法级内存,方法调用完了,栈就释放了】)
6).nonatomic 非原子操作,决定编译器生成的setter、getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic。
7.类别的作用,类别和类扩展的区别
1).将类的实现分散到多个不同文件或多个不同框架中。
2).创建对私有方法的前向引用。
3).向对象添加非正式协议。
类别的局限性
有两方面局限性:
1).无法向类中添加新的实例变量,类别没有位置容纳实例变量。
2).名称冲突,即当类别中的方法与原始类方法名称冲突时,类别具有更高的优先级。类别方法将完全取代初始方法从而无法再使用初始方法。
无法添加实例变量的局限可以使用字典对象解决
区别:extensions可以添加属性,并且后者添加的方法是必须实现的
extensions可以认为是一个私有的(匿名)的Category。
8.Controller中几个方法调用次序
1).一般情况下调用init方法或者调用initWithNibName方法实例化UIViewController
-(id)initWithNibName:(NSString*)nibNameOrNilbundle:(NSBundle*)nibBundle OrNil
2).接着会调用loadView方法生成UIViewController.view
-(void)loadView
3).然后调用ViewDidLoad
-(void)viewDidLoad
4).如果 loadView 不能生成 UIViewController.view 系统将会反复调用 loadView 及 viewDidLoad 方法, 并且最终调用[super loadView] 方法返回 UIViewController.view
然后依次调用如下2个方法, 这2个方法也十分重要, 在UINavigationController 的POP操作后有时将要显示的 UIViewController 中的View并没有释放(也有可 能释放掉 ) , UIViewController 将不会调用上面的三个方法 (initWithNibName,loadView,viewDidLoad) 而会调用下面这 2 个方法
- (void)viewWillAppear:(BOOL)animated;
- (void)viewDidAppear:(BOOL)animated;
@class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含;
#import<>用来包含系统的头文件
#impor“”用来包含用户头文件,也可以用来导入库
11.POST和GET请求
发送GET请求
1)确定请求路径(一般由公司的后台开发人员以接口文档的方式提供),GET请求参数直接跟在URL后面
2)创建请求对象(默认包含了请求头和请求方法【GET】),此步骤可以省略
3)创建会话对象(NSURLSession)
4)根据会话对象创建请求任务(NSURLSessionDataTask)
5)执行Task
6)当得到服务器返回的响应后,解析数据(XML|JSON|HTTP)
发送POST请求
1)确定请求路径(一般由公司的后台开发人员以接口文档的方式提供)
2)创建 可变的 请求对象(因为需要修改),此步骤不可以省略
3)修改请求方法为POST
4)设置请求体,把参数转换为二进制数据并设置请求体
5)创建会话对象(NSURLSession)
6)根据会话对象创建请求任务(NSURLSessionDataTask)
7)执行Task
8)当得到服务器返回的响应后,解析数据(XML|JSON|HTTP)
区别:1).获取数据用 GET,上传数据用 POST。
2).但POST也是可以获取数据的。因为GET和POST都是向服务器发送请求。只是在浏览器上有区别GET直接发送URL,请求的参数都在URL上,就是明文的。
3).POST的参数,放在页面中,在地址栏是不显示的
4).GET的URL长度有限制,POST可以发送更多的数据
12.iOS各种控件默认高度
1.状态栏
状态栏一般高度为20像素,在打手机或者显示消息时会放大到40像素高,注意,两倍高度的状态栏在好像只能在纵向的模式下使用。
2.导航栏
在纵向模式下导航栏为44像素高,在横向模式下为32像素高
3.选项卡、工具栏
选项卡为48像素高,工具栏为44像素高。
4.键盘
此一般都为横向320*216像素,纵向为480*162像素
13.iOS中四种数据存储
- NSUserDefaults,用于存储配置信息
- SQLite,用于存储查询需求较多的数据
- CoreData,用于规划应用中的对象
- 使用基本对象类型定制的个性化缓存方案
14.中断GCD
- 在外面设置一个 BOOL 值,block 里面读这个值,为真就退出
2. NSOperation,NSOperation天生支持Cancel,调用其cancel方法即可
15.Const
1.修饰变量
2.修饰指针
3.常引用
多用于参数,防止参数被修改,引用是避免创建参数副本
5.常函数
就是类的成员函数,参数后面加个const,此函数不允许修改类的数据成员
16.block 的循环引用问题——属于内存管理的
一个对象中强引用了block ,在 block 中又使用了该对象,就会发射循环引用。
解决方法是将该对象使用 __weak或者__ block 修饰符修饰之后再在 block 中使用。