iOS ---- YY(欢聚时代)面试基础整理


很惊讶,我成功收到了欢聚时代的面试邀请。接着就开始了我的准备。俗话说临阵磨枪,不快也光嘛。好了,开始我的面试过程---->


1.先来个自我介绍--->介绍完后你是用什么语言开发的,OC?Swift?还是C++? (swift和OC 混编)
2.那你说下OC是一门怎样的动态语言 (巴拉巴拉哔哔一通)
3.那你刚才说他底层是消息机制,那么什么是消息机制?(回答有说到objc_msgSend)
4.那你说下如果对一个空对象发送消息,是如何流转的?(巴拉巴拉... )
5.那什么叫运行时机制 (...)
6.说下strong,weak,assign。(哔里巴拉...说weak时,提到了block)
7.block的存储域问题(栈区比如if、for的大括号,临时性的,用完就会释放;堆区通过copy...又一顿哔哔)
8.为什么要放到堆区 (保持引用,避免用到时,在内存中找不到...)
9.说下MVC (又一顿哔哔...)
10.那你数据请求在哪里做 (C,然后又说也可以放到M里做<感觉自己萌萌哒,已经被虐傻了,极度不自信>;提到了MVVM)
11.那你怎么看MVVM(我的理解是不论是MVVM,MVCS,MVP都是从MVC中演化来的;MVVM中的MV和MVC的MVC作用相同,VM是用来做数据相关的操作的,比如网络请求...哔哩吧啦又哔哔了一顿。这时感觉这位面试官大牛已经露出失望的神色了~~)
12.一个页面,只有一个tableview的这种简单页面,要同时保证数据的正确获取,和UI界面的正确刷新(面试官说yy直播里面,主播开播,关播,cell都会增加减少。这时,用户点击这个cell<实际已经不存在了的>,这时就会造成crash)怎样解决?
13.你刚经常提到selector,它是具体是什么?

1.为什么说Objective-C是一门动态语言

1.Objective-C是一门运行时语言。在编译阶段不确定所有的东西,在运行时,根据运行环境确定对象的类型,对象对应类的方法实现等。
2.它的动态主要体现在3个方面,动态类型、动态绑定、动态加载
3.动态类型如id(弱类型);
  动态绑定(将方法调用的时机推迟到运行时,在编译阶段,方法的调用不和代码绑定。只有消息发送出来之后,才会确定调用的代码);
  动态加载(如动态资源加载,@2x、@3x)

2.什么是消息机制

在Objective-C中,方法调用是一个消息发送的过程(在java,C++等静态语言中是函数调用)。
OC对象发送一个消息的过程如下:
1.向对象发送消息
2.在缓存中查找是否有匹配方法。如果有则响应,否则继续
3.在对象的类对象的方法列表中(method list)查找是否有匹配方法,如果有则响应,否则继续
4.在对象的父类的缓存中查找是否有匹配方法。如果有则响应,否则继续
5.在对象的父类的方法列表中(method list)查找是否有匹配方法。如果有则响应,否则继续
6.进入动态解析 -(BOOL)resolveInstanceMethod:(SEL)sel;- (BOOL)resolveClassMethod:(SEL)sel;查看是否有动态添加方法实现。如果有则响应,否则继续
7.进入消息重定向 -(id)forwardingTargetForSelector:(SEL)sel;如果有指定消息接收对象则响应,否则(指:返回nil或者self)继续
8.进入方法签名- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector返回方法签名并进入下一步,否则调用doesNotRecongnizeSelector:方法并抛出异常。
9.进入消息转发 - (void)forwardInvocation:(NSInvocation *)aInvocation;如果有指定消息转发对象则响应,否则调用doesNotRecongnizeSelector:方法并抛出异常。

3.说下copy、strong、weak、assign

copy会重新开辟新的内存空间来保存一份相同的数据。被赋值对象(copy修饰的对象)和原对象值的修改互不影响。
strong和weak指针都指向原对象值的地址。原对象值修改,也随之修改。区别是前者会对原对象的引用计数+1,防止原对象被释放;后者不会,当原对象引用计数为0时被释放时,weak的值也为nil了。
weak和assign都是弱引用一个对象,不会对该对象的引用计数+1。但是当被引用对象的引用计数为0时,assign修饰的对象会发生野指针错误,原因是assign虽然不会对引用对象的引用计数+1,但是当引用对象值改变时,也不会销毁指向引用对象的指针。
 而weak修饰的对象会随引用对象值改变而销毁指向引用对象的指针。
retain与strong相同 , weak,assign修饰的属性验证

4.block的使用及它的存储域问题

简单理解 block 是一个可以带有变量的匿名函数,实际上block也是一个OC对象。
block可能会存储在堆区(_NSConcreteMallocBlock)、全局数据区(_NSConcreteGlobalBlock)、栈区(_NSConcreteStackBlock)<栈上的block仅在MRC环境下存在>。
在ARC环境下,block声明既可以用copy也可以用strong。使用copy是在MRC时代遗留的习惯问题。因为在ARC时,编译器会自动将block从栈区拷贝到堆区。避免在使用时,已被释放。
weak属性经常配合block使用,避免循环引用问题。<注:weak修饰符在iOS 5引入,只能在ARC环境下使用>
__block修饰基本数据类型。可以使其在block内部进行修改其值。原因从下图源码中可以看出,正常定义一个变量 a 时, block的实现中 是与外部变量 a 的定义结构相同;当使用__block修饰时,a会变为一个指针,使用指针引用外部变量 a 的地址。

最后附一篇介绍block及__block的文章

5.MVC设计模式

MVC是一种架构模式,M表示MOdel,V表示视图View,C表示控制器Controller:
Model负责存储、定义、操作数据;
View用来展示书给用户,和用户进行操作交互;
Controller是Model和View的协调者,Controller把Model中的数据拿过来给View用。
Controller可以直接与Model和View进行通信,而View不能和Controller直接通信。
View与Controller通信需要利用代理协议的方式,当有数据更新时,MOdel也要与Controller进行通信,这个时候就要用Notification和KVO,这个方式就像一个广播一样,MOdel发信号,
Controller设置监听接受信号,当有数据更新时就发信号给Controller,Model和View不能直接进行通信,这样会违背MVC设计模式。

6.在定义 property 的时候,atomic 和 nonatomic 有何区别?

atomic 和 nonatomic 的区别在于,系统自动生成的getter/setter 方法不一样。如果你自己写 
getter/setter,那 atomic/nonatomic/retain/assign/copy 这些关键字只起提示作用,
写不写都一样。
对于atomic的属性,系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。
比如,线程 A 的 getter 方法运行到一半,线程 B 调用了 setter:那么线程 A 的 getter 还是能
得到一个完好无损的对象。
而nonatomic就没有这个保证了。所以,nonatomic的速度要比atomic快。
不过atomic可并不能保证线程安全。如果线程 A 调了 getter,与此同时线程 B 、线程 C 都调了 
setter——那最后线程 A get 到的值,3种都有可能:可能是 B、C set 之前原始的值,也可能是 B set 
的值,也可能是 C set 的值。同时,最终这个属性的值,可能是 B set 的值,也有可能是 C set 的
值。

转自链接:https://www.jianshu.com/p/7288eacbb1a2

简单验证如下:
- (void)gcdGroup
{
    /// init property name
    self.name = @"origin";
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("com.bonlion.queue", DISPATCH_QUEUE_CONCURRENT);
    
    /// thread A
    dispatch_group_async(group, queue, ^{
        self.name = @"A";
        NSLog(@"thread A->%@", [NSThread currentThread]);
    });
    /// thread B
    dispatch_group_async(group, queue, ^{
        self.name = @"B";
        NSLog(@"thread B->%@", [NSThread currentThread]);
    });
    /// thread C
    dispatch_group_async(group, queue, ^{
        NSLog(@"name value is ->%@", self.name);
        NSLog(@"thread C->%@", [NSThread currentThread]);
    });
    dispatch_group_notify(group, queue, ^{
        NSLog(@"notify thread is used");
    });
}

7.用@property声明的 NSString / NSArray / NSDictionary 经常使用 copy 关键字,为什么?如果改用strong关键字,可能造成什么问题?

答:用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有
对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋
值操作(就是把可变的赋值给不可变的),为确保对象中的字符串值不会无意间变动,应该在设置新属性值
时拷贝一份。

1. 因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 
无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本。
2. 如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改
了,那么会影响该属性。

总结:使用copy的目的是,防止把可变类型的对象赋值给不可变类型的对象时,可变类型对象的值发送变化
会无意间篡改不可变类型对象原来的值。

转自链接:https://www.jianshu.com/p/5595ae4262ed

8.系统对象的 copy 与 mutableCopy 方法

不管是集合类对象(NSArray、NSDictionary、NSSet ... 之类的对象),还是非集合类对象
(NSString, NSNumber ... 之类的对象),接收到copy和mutableCopy消息时,都遵循以下
准则:
1. copy 返回的是不可变对象(immutableObject);如果用copy返回值调用mutable对象的
方法就会crash。
2. mutableCopy 返回的是可变对象(mutableObject)。
【总结一句话】:
只有对不可变对象进行copy操作是指针复制(浅复制),其它情况都是内容复制(深复制)!

链接:https://www.jianshu.com/p/5595ae4262ed

9.KVC底层实现

当一个对象调用setValue:forKey: or valueForKey:方法时,方法内部会做以下操作:
1). 检查是否存在相应的 key 的setter or getter方法,如果存在,就调用setter or getter方法。
2). 如果setter or getter 方法不存在,就会查找与 key 相同名称并且带下划线的成员变量,
     如果有,则直接给成员变量属性赋值 or 取值。
3). 如果没有找到_key,就会查找相同名称的属性key,如果有就直接赋值 or 取值。
4). 如果还没有找到,则调用 setValue:forUndefinedKey: 和valueForUndefinedKey: 方法。
以上两个方法的默认实现都是抛出异常,我们可以根据需要进行重写。

10.KVO的原理

[附一份KVO简单实现——有详细注释](https://link.jianshu.com?t=https%3A%2F%2Fgithub.com%2F304164084%2Fcustom_KVO_IMP)
[KVO深层次的讲解](https://www.jianshu.com/p/742b4b248da9)
[facebook的自释放KVO](https://link.jianshu.com?t=https%3A%2F%2Fgithub.com%2Ffacebook%2FKVOController)
基本概念:
KVO又称键(key)值(value)监听(observing)。
KVO的底层实现依赖于强大的runtime库。
KVO通过addObserver:forKeyPath:options:context:添加观察者对象(observer),观察目标对象
的某个属性(key)的新值或者旧值(options)的改变,关键字(context)可以作为区分使用 的方式实现值改变的回调机制。
使用场景:
1.一般使用于对scrollView的偏移量(contentOffset)值改变的监听。
2.商城购物车中改变商品数量,更新总价
底层原理:
在注册观察者之后,编译器会通过runtime的API动态创建注册一个中间类(派生类),继承自原本类(父类),然后将父类的 isa 指针指向这个子类(中间类)。同时,为子类动态添加了设置(setter)方法。
随后在 setter 方法中实现成对出现的 willChangeValueForKey: 与 didChangeValueForKey: 方法及父类的 setter 方法。然后再在didChangeValueForKey:方法中实现监听者的 observeValueForKeyPath: 方法,实现监听属性改变的过程。

大致过程如下:

- (void)viewDidLoad {
    [super viewDidLoad];

    Person *p = [[Person alloc] init];
    // 表明观察策略--> 观察新值 与 旧值的改变
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    // 注册观察者,监听者为当前控制器,监听对象为 p。
    [p addObserver:self forKeyPath:@"age" options:options context:@"as you like"];

}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"\nkeyPath->%@\nchange->%@\ncontext->%@", keyPath, change, context);
}

断点之后,发现使用runtime获取到的p对象所属的类为 NSKVONotifying_Person
中间类的setter方法实现大致如下
可以通过runtime得知,中间类的类名及其对应的方法列表的方法名。中间类只有setter方法,同时还有一个 class 方法,说明它重写了NSObject类的class方法。为什么这么做呢?因为它内部的实现大致这样- (Class)class{return object_getClass(class_getSuperclass(self));}
就可以做到过程欺骗。因为你使用[p class]方法得到的类还是Person类,除非使用runtime API 才能获得到真实类。

11.iOS是如何管理内存的

首先我们要知道,对于创建的普通对象,由于我们现在的项目都是ARC的,不需要我们过多干涉,而且记住内存管理的黄金法则就可以应付
而对于Block的内存管理来讲,很容易造成循环引用,因此在用到Block的地方一定要小心内存管理问题,最好在基类controller里重写dealloc,加一句打印日志,来查看类有没有得到释放,如果无打印信息,则说明这个类一只被引用而没有被释放,很有可能在用到block的地方发生循环引用了,对于block中需要引用外部cotroller的属性或者成员变量的时候,一定要使用弱引用。
如果不是block的问题再去查看是不是定时器或者代理引发的

#**Objective-C内存管理机制 **
Objective-C中的对象都是基于引用计数来管理生命周期的。简单来说就是,我们在需要持有一个对象时,调用retain让它的引用计数+1。不需要这个对象的时候,调用release让它的引用计数-1。当一个对象引用计数为0的时候,这个对象就会被自动销毁。
MRC
我们在手动管理引用计数的时候,要明确地控制对象的生命周期,显式的调用每一个retain和release。我们必须清楚的了解每个接口对引用计数的处理(如把一个对象放到数组里引用计数会被+1,用alloc创建的对象的引用计数一开始就是1,用哪些接口创建的对象是已经被调用过autorelease的等等)。在处理引用计数时稍有疏忽,就可能导致程序崩溃或内存泄漏。
ARC
ARC是编译器通过对代码的静态分析,确定对象的生命周期,并在合适的位置自动加上retain和release的机制。把内存管理交给编译器以后,我们不需要再调用任何的retain和release了。ARC减少了MRC带来的思考负担,减少了内存问题出现的可能性,也大幅减少了代码量。

重点来了11.谈谈 ffmpeg ?

首先介绍以下..具体资料加我QQ972491872: 可以免费送大家


 FFmpeg 简介
FFmpeg 是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用 LGPL 或
GPL 许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方 案。它包含了非常先进的音频/视频编解码库 libavcodec,为了保证高可移植性和编解 码质量,libavcodec 里很多 codec 都是从头开发的。
ffmpeg 项目由以下几部分组成:
1.ffmpeg 视频文件转换命令行工具,也支持经过实时电视卡抓取和编码成视频文
件.
2.ffserver 基于 HTTP、RTSP 用于实时广播的多媒体服务器.也支持时间平移 3.ffplay 用 SDL 和 FFmpeg 库开发的一个简单的媒体播放器
4.libavcodec 一个包含了所有 FFmpeg 音视频编解码器的库.为了保证最优性能和
高可复用性,大多数编解码器从头开发的. 5.libavformat 一个包含了所有的普通音视格式的解析器和产生器的库
2.1.2 FFmpeg 安装 1.将所有源代码压缩在一个文件夹中,例如/绝对路径/ffmpeg。 2.在终端输入以下指令:
Cd /绝对路径/ffmpeg
./configure (此时,会出现问题。然后重新输入./configure –disable-yasm-) Make
至此,ffmpeg 安装编译通过,可以进行对音视频的操作。
ffplay 的编译需要依赖于 SDL 库,所以要想编译成功 ffplay,必须先安装 SDL 库, 安装方法:下载最新版本的 SDL 相应版本的 SDL 源码,编译,即可生成 SDL 库。

总结:平时没事调休,可以多去面面试试,一来发现以下自己的不足二来看看市场的新技术方向把控好心态就行了,学无止境.更上一层楼**。

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

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,027评论 8 265
  • 设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型的...
    卑微的戏子阅读 594评论 0 1
  • 历史是迷茫的,古代的事、人你都知道哪些。你知道无赖的皇帝——朱温吗?最傻的皇帝——普惠帝吗?如果你不知道这些...
    wawda阅读 296评论 0 2
  • 父母宠爱孩子是天经地义的事情,但是有些父母对孩子的宠爱过度了,变成了溺爱。这种溺爱对孩子来说只一种伤害,看看现在很...
    刘树华阅读 385评论 1 0
  • 昨天咱们办公网上通报了教育局对两位做微商的老师的处理决定,写检查,约谈,学习师德师风。 这对整个教育系统来说,震...
    凤翔千仞兮阅读 300评论 0 1