基础

1、父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。

深拷贝同浅拷贝的区别:浅拷贝是指指针拷贝,对一个对象进行浅拷贝,相当于对指向对象的指针进行复制,产生一个新的指向这个对象的指针,那么就是有两个指针指向同一个对象,这个对象销毁后两个指针都应该置空。深拷贝是对一个对象进行拷贝,相当于对对象进行复制,产生一个新的对象,那么就有两个指针分别指向两个对象。当一个对象改变或者被销毁后拷贝出来的新的对象不受影响。
• 实现深拷贝需要实现NSCoying协议,实现- (id)copyWithZone:(NSZone *)zone 方法。当对一个property属性含有copy修饰符的时候,在进行赋值操作的时候实际上就是调用这个方法。
• 父类实现深拷贝之后,子类只要重写copyWithZone方法,在方法内部调用父类的copyWithZone方法,之后实现自己的属性的处理
• 父类没有实现深拷贝,子类除了需要对自己的属性进行处理,还要对父类的属性进行处理。

2、KVO,NSNotification,delegate及block的区别

  • KVO就是cocoa框架实现的观察者模式,一般同KVC搭配使用,通过KVO可以检测到一个值的变化,比如view的高度变化。是一对多的关系,一个值变化会通知所有观察者。
  • NSNotification是通知,也是一对多的场景。在某些情况下,KVO和NSNotification是一样的都是状态变化后告知对方。NSNotification的特点,就是需要被观察者主动发出通知,然后观察者注册监听后再来进行响应,比KVO多了发送通知的一步,但是其优点就是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,使用也灵活
  • delegate是代理,就是我不想做的事情交给别人做。比如狗需要吃饭,就是通过delegate通知主人,主人就会给它做饭,盛饭,倒水,这些狗不需要关心,只需要调用delegate就可以了,又其它类完成所需要的操作。所有delegate是一对一关系
  • block就是delegate的另一种形式,是函数式编程的一种形式。使用场景跟delegate一样,相比delegate更加灵活,而且代理的实现更直观
  • KVO的使用场景是数据,需求是数据变化,比如股票价格变化,我们一般使用KVO(观察者模式)。delegate一般使用场景是行为,需求是需要别人帮我做一件事情,比如买卖股票,我们一般使用delegate
  • Notification一般是进行全局通知,比如好消息一出,通知大家去买。delegate是强关联,就是委托和代理双方相互知道,你委托别人买股票你就需要知道经纪人,经纪人也不要知道自己的顾客。Notification是弱关联,好消息发出,你不需要知道是谁发的也可以做出相应反应,同理发消息的人也不需要知道接受的人也可以正常发消息

3、将一个函数在主线程执行的4种方法
• GCD方法,通过向主线程队列发送一个block块,使block里的方法可以在主线程中执行。

dispatch_async(dispatch_get_main_queue(),^{
    需要执行的方法
});
  • NSOperation方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; // 主队列
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    需要执行的方法
}];
[mainQueue addOperation:operation];
  • NSThread
[self performSelector:@selector(method) onThread [NSThread mainThread] withObject:nil waitUntilDone:YES modes:nil];
[self performSelectorOnMainThread:@selector(method) withObject:nil waitUntilDone:YES];
[[NSThread mainThread] performSelector:@selector(method) withObject:nil];
  • RunLoop方法
[[NSRunLoop mainRunLoop] performSelector:@selector(method) withObject:nil];

4、如何让计时器调用一个类方法
• 计时器只能调用实例方法,但是可以在这个实例方法里面调用静态方法。

• 使用计时器需要注意,计时器一定要加入RunLoop中,并且选好model才能运行。scheduledTimerWithTimeInterval方法创建一个计时器并加入到RunLoop中所以可以直接使用。

• 如果计时器的repeats选择YES说明这个计时器会重复执行,一定要在合适的时机调用计时器的invalid。不能在dealloc中调用,因为一旦设置为repeats 为yes,计时器会强持有self,导致dealloc永远不会被调用,这个类就永远无法被释放。比如可以在viewDidDisappear中调用,这样当类需要被回收的时候就可以正常进入dealloc中了。

[NSTimer scheduledTimerWithTimeInterval:1 target:self
selector:@selector(timerMethod) userInfo:nil repeats:YES];
-(void)timerMethod
{
    调用类方法
    [[self class] staticMethod];
}
-(void)invalid
{
    [timer invalid];
    timer =nil;
}

5、如何重写类方法

1、在子类中实现一个同基类名字一样的静态方法
2、在调用的时候不要使用类名调用,而是使用[self
class]的方式调用。原理,用类名调用是早绑定,在编译期绑定,用[self class]是晚绑定,在运行时决定调用哪个方法

6、iOS 核心框架
• CoreAnimation
• CoreGraphics
• CoreLocation
• AVFoundation
• Foundation

7、iOS本地数据存储都有几种方式?

①.NSkeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码.
②.NSUserDefaults:用来保存应用程序设置和属性,用户保存的数据.用户再次打开程序或者开机后这些数据仍然存在.NSUserDefaults可以存储的数据类型包括:NSData,NSString,NSNumber,NSDate,NSArray.NSDictionary,其他类型的数据需要先行转换.
③.Write写入方式:永久保存在磁盘中.具体:a.获得文件保存的路径.b.生成该路径下的文件,c,往文件中写入数据.d.从文件中读出数据.
④.SQLite:采用SQLite数据库来存储数据,SQLite作为一种轻量级数据库.具体:a.添加SQLite相关的库以及头文件,b.使用数据库存数数据:打开数据库,编写数据库语句,执行,关闭数据库.另:写入数据库,字符串可以采用char方式,而从数据库中取出char类型,当char类型有表示中文字符时,会出现乱码,这是因为数据库默认使用ascII编码方式,所以想要正确从数据库中取出中文,需要使用NSString来接受从数据库取出的字符串.
⑤.CoreData:原理是对SQLite的封装,开发者不需要接触sql语句,就可以对数据库进行操作.

8、什么是安全释放?
先释放再置空.

9、什么是序列化和反序列化,可以用来做什么?如何在OC中实现复杂对象的存储.

序列化和反序列化:归档和反归档,进行本地化,进行数据存储.
CoreData:数据托管.有四种存储方式:xml,sqlite,二进制,内存.
遵循NSCoding协议之后,进行归档即可实现复杂对象的存储.

10、事件循环,是线程里面的一个组件.主线程的RunLoop是自动开启的.分为:计时源(timer source),事件源(输入源):input source.防止CPU中断(保证程序执行的线程不会被系统终止).

Runloop提供了一种异步执行代码的机制,并不能并行执行任务,是事件接收和分发机制的一个实现.每一个线程都有其对应的RunLoop,但是默认非主线程的RunLoop是没有运行的,需要为RunLoop添加至少一个事件源,然后run它.
一般情况下我们是没有必要去启动线程的RunLoop的,除非你在一个单独的线程中需要长时间的检测某个事件.
RunLoop,正如其名所示,是线程进入和被线程用来响应事件以及调用事件处理函数的地方.
input source传递异步事件,通常是来自其他线程和不同程序的消息。
timer source传递同步事件.
当有事件发生时,RunLoop会根据具体的事件类型通知应用程序作出响应.
当没有事件发生时,RunLoop会进入休眠状态,从而到达省电的目的.
当事件再次发生时,RunLoop会被重新唤醒,处理事件.
一般在开发中很少会主动创建RunLoop,而通常会把事件添加到RunLoop中.

11、ViewController的didReceiveMemoryWarning是在什么时候被调用的?

1.当应用程序的内存使用接近系统的最大内存使用时,应用会向系统发送内存警告,这时候系统会调用方法向所有ViewController发送内存警告.
2.打开系统相机.
3.加载高清图片.
默认操作:把里面没有用的对象进行释放.

12、事件响应者链

如果当前view是控制器的view,那么就传递给控制器
如果控制器不存在,则将其传递给它的父控件
在视图层次结构的最顶层视图也不能处理接收到的事件或消息,则将事件或消息传递给UIWindow对象进行处理
如果UIWindow对象也不处理,则将事件或消息传递给UIApplication对象
如果UIApplication也不能处理该事件或消息,则将其丢弃
补充:如何判断上一个响应者
如果当前这个view是控制器的view,那么控制器就是上一个响应者
如果当前这个view不是控制器的view,那么父控件就是上一个响应者

13、触摸事件的传递

触摸事件的传递是从父控件传递到子控件
如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件
不能接受触摸事件的四种情况
不接收用户交互,即:userInteractionEnabled = NO
隐藏,即:hidden = YES
透明,即:alpha <= 0.01
未启用,即:enabled = NO
提示:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的
如何找到最合适处理事件的控件:
首先,判断自己能否接收触摸事件
§ 可以通过重写hitTest:withEvent:方法验证
其次,判断触摸点是否在自己身上
§ 对应方法pointInside:withEvent:
从后往前(先遍历最后添加的子控件)遍历子控件,重复前面的两个步骤
如果没有符合条件的子控件,那么就自己处理

14、UIScrollView的contentSize能否在viewDidLoad中设置?

  • 因为UIScrollView的内容尺寸是根据其内部的内容来决定的,所以是可以在viewDidLoad中设置的
    补充:(这仅仅是一种特殊情况)
  • 前提,控制器B是控制器A的一个子控制器,且控制器B的内容只在控制器A的view的部分区域中显示
    假设控制器B的view中有一个UIScrollView这样一个子控件
  • 如果此时在控制器B的viewDidLoad中设置UIScrollView的contentSize的话会导致不准确的问题
  • 因为任何控制器的view在viewDidLoad的时候的尺寸都是不准确的,如果有子控件的尺寸依赖父控件的尺寸,在这个方法中设置会导致子控件的frame不准确,所以这时应该在下面的方法中设置子控件的尺寸

15、描述下SDWebImage里面给UIImageView加载图片的逻辑

SDWebImage 中为UIImageView 提供了一个分类UIImageView+WebCache.h, 这个分类中有一个最常用的接口sd_setImageWithURL:placeholderImage:,会在真实图片出现前会先显示占位图片,当真实图片被加载出来后在替换占位图片
• 加载图片的过程大致如下:
○ 首先会在SDWebImageCache 中寻找图片是否有对应的缓存, 它会以url
作为数据的索引先在内存中寻找是否有对应的缓存
○ 如果缓存未找到就会利用通过MD5处理过的key来继续在磁盘中查询对应的数据, 如果找到了, 就会把磁盘中的数据加载到内存中,并将图片显示出来
○ 如果在内存和磁盘缓存中都没有找到,就会向远程服务器发送请求,开始下载图片
○ 下载后的图片会加入缓存中,并写入磁盘中
○ 整个获取图片的过程都是在子线程中执行,获取到图片后回到主线程将图片显示出来

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。• 深拷贝同浅拷贝的区别:浅拷...
    JonesCxy阅读 948评论 1 7
  • • 深拷贝同浅拷贝的区别:浅拷贝是指针拷贝,对一个对象进行浅拷贝,相当于对指向对象的指针进行复制,产生一个新的指向...
    WSGNSLog阅读 1,168评论 0 1
  • 1. 父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 1.1 深拷贝同浅拷贝...
    iYeso阅读 1,840评论 0 13
  • 1.OC的类可以多重继承吗?可以实现多个接口吗?要想实现类似多重继承如何实现?答:OC不可以实现多重继承。可以实现...
    欧辰_OSR阅读 1,906评论 0 29
  • 1.1 谈一谈GCD和NSOperation的区别? 首先二者都是多线程相关的概念,当然在使用中也是根据不同情境进...
    John_LS阅读 1,271评论 0 12