面试资料整理

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

静态语言:既一种在编译时,数据类型是固定的语言,大多静态类型定义语言强制这一点,它要求你在使用所有变量之前要声明它们的数据类型。在使用数据之前,我们必须首先定义数据类型,这些数据类型包括int、float、double等 将相当于使用它们之前,首先要为它们分配好内存空间。
优点:结构规范,便于调试,方便类型安全;
缺点:需要些更多的类型相关的代码,导致不便于阅读。不清晰明了。
动态语言:在运行期间检查数据的类型的语言,用这类语言编程,不会给变量指定类型,而是复制时得到数据类型。
优点:方便阅读,不需要写非常多的类型相关代码
缺点:不方便调试,明明不规范造成读不懂,不利于理解

项目中那些地方用到了动态语言的特性:
id类型:可以在运行时决定delegate的类型到底是哪个
isKindOfClass:someClass方法 :它是NSObject的方法,用意缺点某个NSObject对象是都是某个类的成员。
动态加载:比如我们平时用的@2x @3x图片或者PDF都是需求加载不同的图片

2.讲一下MVC和MVVM,MVP?

1.MVC最早出现在桌面程序中的,M是指业务数据,V指用户界面,C是控制器,在具体的业务场景中,C作为M和V之间的连接,负责获取输入的业务数据,然后将处理后的数据输出到界面做相应的展示。因为M和V之间是完全隔离的,所以在业务场景切换时,通常只需要替换相应的C,复用已有的M和V便可快速搭建新的业务场景,MVC因其复用性,提高了开发效率。

MVC的缺点

1.过渡的注重隔离:这个其实MV系列都有这个缺点,为了实现V层的完全隔离,V对外只暴露set方法,一般情况下没什么问题,但是当需要设置的属性很多时,大量重复的set方法写起来还是挺雷人的;
2.业务逻辑和业务展示强耦合:可以看到,有些业务逻辑(页面跳转、点赞、分享)是直接散落在V层的,这以为着我们在测试这些逻辑时,必须首先生成对应的V,然后才能进行测试。显然,这不是合理的,因为业务逻辑最终改变的是数据M,我们的关注点在M上,而不是展示M的V。

MVP

MVP将MVC中的Controller换成了Presenter,简单的说,MVP中将MVC中的View Controller当做View,MVP就解决了实际开发中Cocoa MVC的几个缺点,但是增加了代码量,单单增加Presenter就会多增加许多新的文件和类,增加了第三方库接入成本,第三方UI库大多是基于Cocoa MVC的,所以如果用继承方式接入的话,会带来额外的成本。
MVC的缺点在于并没有区分业务逻辑和业务展示,这对单元测试不是很友好,MVP针对以上缺点做了优化,它将业务逻辑和业务展示也做了一层隔离,对应的就编程了MVCP,M和V的功能不变,C现在只负责布局,而所有的逻辑全都转移到P层。
相对于MVC,其实只做了一件事,即分割业务展示和业务逻辑,展示和逻辑分开后,只要我们能保证V在收到P的数据更新通知后能正常刷新页面,,那么整个业务就没有问题,因为V收到的通知其实都是来自于P层数据获取或更新操作,所以我们只要保证P层的这些操作都是正常的就可以了,即我么只用测试P层的逻辑,不必关系V层的情况。

MVVM

鉴于MVP或者说是理想的Cocoa MVC已经是完美结构模式了,那么为什么还多一个MVVM?
因为不管MVC还是MVP都有一个问题,Controller和Presenter这个‘协调员’太关键了,代码稍微写多点,他们就编程了Massive Controller或者Massive Presenter。
如何给Controller和Presenter减负,答案就是让View和Model自己去沟通,让Controller和Presenter从协调员降级到介绍者。
一种可以很好地解决Massive View Controller问题的办法就是将 Controller 中的展示逻辑抽取出来,放置到一个专门的地方,而这个地方就是 viewModel 。MVVM衍生于MVC,是对 MVC 的一种演进,它促进了 UI 代码与业务逻辑的分离。

MVVM的基本概念

1.在MVVM中,View和View Controller正式联系在一起,我们把它们视为一个组件
2.view和view controller都不能直接引用model,而是引用视图模型。
3.viewmodel是一个方式用户输入验证逻辑,视图显示逻辑,发起网络请求和其他代码的地方。

MVVM的优势

1.低耦合:view独立于model变化和修改,一个viewmodel可以绑定到不同的view上
2.可重用性:可以把一些视图逻辑放在一个viewmodel里面,让很多view重用这段视图逻辑
3.独立开发:开发人员可以专注于业务逻辑和数据的开发viewmodel,设计人员可以专注于页面设计

MVVM的弊端

1.数据绑定使得bug很难被调试,你看到界面异常了,有可能是你view的代码有bug,也可能是model的代码有问题,数据绑定使得一个位置的bug被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
2.对于过大的项目,数据绑定和数据转化需要花费更多的内存成本

3.为什么代理要用weak?代理的delegate和dataSource有什么区别?block和代理的区别?

代理属性都用weak或是assign修饰;
weak:指明该对象不负责保护delegate这个对象,delegate这个对象的销毁由外部控制;
strong:该对象强引用delegate,外界不能销毁delegate对象,会导致循环引用。

delegate和DataSource区别

DataSource是在告诉使用者之前的view中都有什么东西,有什么属性,属性的值是多少,是只关于数据的东西。
delegate是告诉使用者之前view有什么方法可以供我调用,一个是数据,一个是操作。

block和代理的区别

首先两者作用是一样的,都是进行单一回调,不同的是,delegate是个对象,然后用过一个对象自己调用代理协议函数来完成整个流程。block是传递一个函数指针,利用函数指针执行来进行回调。还有在内存管理上需要注意,delegate不需要保存引用,block对引用数据有copy的处理。

属性的实质是什么?包括哪几个部分?属性默认的关键字都有哪些?@dynamic关键字和@synthesize关键字是用来做什么的?

属性的组成:@preperty = ivar +getter+setter;
实例变量+get方法+set方法。也就是说使用@property会自动生成setter和getter方法;我们经常使用assign、weak、strong、copy,nonatomic,atomic,readonly等关键字。
@synthesize和@dynamic区别, 在声明property属性后,有2种实现选择:
@synthesize:编译期间,让编译器自动生成getter、setter方法,当有自定义的存或取方法时,自定义会屏蔽自动生成该方法
@dynamic:高速编译器,不自动生成gettet、setter方法,避免编译期间产生警告然后由自己实现存取方法或存取方法在运行时动态绑定。

5.属性的默认关键字是什么?

对于基本数据类型默认关键字是:atomic,readwrite,assign
对于普通的oc对象:atomic,readwrite,strong

6.NSString为什么要用copy关键字,如果用strong会有什么问题?(注意:这里没有说用strong就一定不行。使用copy和strong是看情况而定的)

因为NSSting、NSDictionary、NSArray有对应的可变类型,他们经常会用到赋值操作,为保证字符串数值不会无意间被改动,应该在设置新属性值时拷贝一份。若使用strong,那么这个属性就可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性。

7.如何令自己所写的对象具有拷贝功能?

若想令自己所写的对象具有拷贝功能,则需要实现NSCoping协议,如果自定义的对象分为可变版本和不可变版本,那么就要同时实现NSCoping、NSMutableCoping协议。

8. 可变集合类 和 不可变集合类的 copy 和 mutablecopy有什么区别?如果是集合是内容复制的话,集合里面的元素也是内容复制么?

不可变集合的copy是浅拷贝,mutablecopy是深拷贝,重新拷贝了对象的指针地址。
可变集合的copy和mutable都是深拷贝,因为对象的指针地址都发生了改变

9. 为什么IBOutlet修饰的UIView也使用weak关键字?

当我们把控件拖到StroyBoard上时,相当于把这个控件加到了视图控制器的view上,view上有一个addsubview属性,这个属性是一个数组,里面所有的view都添加在这个数组中,view对加到它上面的对象是强引用,当我们使用outlet属性时,我们仅仅在view,controller中使用,没有必要拥有它,所以是weak。

10. nonatomic和atomic的区别?atomic是绝对的线程安全么?为什么?如果不是,那应该如何实现?

区别:nonatomic和atomic的区别在于系统自动生成的getter、setter方法不一样,如果你自己写getter、setter,那nonatomic、atomic、retain、assign、copy这些关键字只起提示作用,写不写都一样。
对于atomic属性,系统生成的getter、setter会保证get、set操作的完整性,不受其他线程影响。比如,线程A的getter方法运行到一半,线程B调用了setter;那么线程A的getter还是会得到一个完好无损的对象。而nonatomic就没有这个保证,所以nonatomic的速度比atomic快。

一般iOS程序中,所有属性都声明为nonatomic。这样做的原因是:
在iOS中使用同步锁的开销比较大,这会带来性能的问题。一般情况下并不要求属性必须是原子的,因为这并不能保证线程安全,若要实现线程安全的操作,还需采用更为深层的锁定机制才行。
然而atomic一定是线程安全的么?
不过atomic可并不能保证线程安全。如果线程A调了getter,于此同时线程B、线程C都调了setter,那最后线程Aget到的值,3种都有可能:可能是B,Cset之前原始的值,也可能是B set的值,也可能是C set的值。同时,最终这个属性的值,可能是B set的值,也可能是C set的值。
更准确的说应该是读写安全,但并不是线程安全的,因为别的线程还能进行读写之外的其他操作。线程安全需要开发者自己来保证。

11.UICollectionView自定义layout如何实现?

1.继承UICollectionViewLayout
2需要重写方法
- (CGSize)collectionViewContentSize;
返回collectionView内容区的宽度和高度,子类必须重载该方法,返回值代表了所有内容的宽度和高度,而不仅仅是可见范围,collectionView通过该信息配置它的滚动范围,默认返回CGSizeZero.
- (NSArray<__kindofUICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
返回UICollectionViewLayoutAttributes类型的数组,UICollectionViewLayoutAttributes对象包含cell或view的布局信息。子类必须重载该方法,并返回该区域内所有元素的布局信息,包括cell,追加视图和装饰视图。才创建layout attributes的时候,创建的是相应元素。
1 prepareLayout方法调用来为即将进行的layout作前期的计算

2 collectionViewContentSize方法基于初始计算,返回整体内容区域的size

3 layoutAttributesForElementsInRect:方法返回指定区域中cells和views的属性

layoutAttributesForElementsInRect:方法的实现需要遵循如下步骤:
1.遍历prepareLayout方法产生的数据以访问缓存的属性或者创建新的属性;
2.检查每个item的frame以确定是否与layoutAttributesForElementsInRect:方法中指定rectangle有重叠部分;
3.对每个重叠的item,添加一个对应的UICollectionViewLayoutAttributes对象到一个数组中;
4.返回布局属性的数组给collectionView.

12.用StoryBoard开发界面有什么弊端?如何避免?

1.后期难以维护,错误冲突不容易找
2.在团队开发中,极易造成冲突,而且复用性很差。
在相对界面简单,没有多次修改的需求上建议用storeboad或者xib编写,这样可以提升整体项目的速度,而对于复杂页面就用纯代码编写,可控性强,容易维护。

13. 进程和线程的区别?同步异步的区别?并行和并发的区别?
进程和线程的区别

1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程,线程是操作系统可识别的最小的执行和调度单位。
2.资源分配给进程,同一进程的所有线程共享该进程的所有资源,同一进程中的多个线程共享代码段,数据段,扩展段,但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。
3.处理机分给线程,即真正在处理机上运行的是线程。
4.线程在执行过程中,需要协作同步,不同进程的线程间要利用消息通信的办法实现同步。
进程和线程并不是一一对应的,一个程序执行在不同的数据集上就成为不同的进程,可以用进程控制块来唯一地标识每个进程。

同步异步的区别

同步:一个线程要等待上一个线程执行完毕之后才能执行当前的线程;
异步:同时去做两件或者多件事。不需要等待上一个线程有没有执行完毕。

并行和并发的区别

并行:指两个指两个或两个以上事件或活动在同一时刻发生。
并发:指两个或两个以上的事件或活动在同一时间间隔内发生。
区别:一个处理器同事处理多个任务和多个处理器或者是多核的处理器同事处理多个不同的任务。

14.线程间通信?

一个线程传数据给另一个线程,在一个线程中执行完特定任务后,转到另一个线程继续执行任务
#########线程间通信的常用的方法
NSThread可以将自己的当前线程对象注册到某个全局的对象中去,这样相互之间就可以获取对方的线程对象,然后就可以使用下面的方法进行线程间通信,由于主线程比较特殊,所以框架直接提供了再主线程执行的方法

15GCD的一些常用的函数?(group,barrier,信号量,线程同步)

1.The main queue(主线程串行队列):与主线程功能相同,提交至main queue的任务全在主线程中执行,main queue 可以通过dispatch_get_main_queue()来获取。
2.global queue(全局并发队列):全局并发队列由整个进程共享,有高、中、低、后台四个优先级别,global queue 可以通过调用dispatch_get_global_queue函数来获取,可以设置优先级
3.custom queue(自定义队列):可以为串行,也可以为并发。
custom queue可以通过dispatch_queue_create()来获取;
4.Group queue(队列组):将多线程进行分组,最大的好处是可获知所有线程的完成情况。
Group queue可以通过调用dispatch_group_create()来获取,通过dispatch_group_notify,可以直接监听组里所有线程完成情况。

16. 如何使用队列来避免资源抢夺?

讲需要访问同一块资源的任务添加到一个串行队列执行。队列内部可根据需求来决定是否需要异步或者同步。
如果不使用队列,可以添加线程锁:
1.@synchronized
2.采用NSLock
3.NSRecursiveLock,递归锁
4.NSConditionLock,条件锁 可以设置条件
5.NSDistributedLock,分布锁
6.使用信号量,限制访问统一资源的线程数目。

17.数据持久化的几个方案(fmdb用没用过)

1.plist文件:是将某些特定的类,通过XML文件的方式保存在目录中。
2.NSUserDefaults:
3.NSKeyedArchiver:归档在iOS中是另一种形式的序列化,只要遵循了NSCoding协议的对象都可以通过它实现序列化,
4.SQLite 3
5.CoreData
6.FMDB:是iOS平台的SQLite数据框架,它是以OC的方式封装了SQLite的C语言的API。

核心类

FMDB有三个主要的类:
1.FMDatabase :一个FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句
2.FMResultSet:使用FMDatabase执行查询后的结果集
3.FMDatabaseQueue:用于多线程中执行多个查询或更新,它是线程安全的

18.说一下AppDelegate的几个方法?从后台到前台调用了哪些方法?第一次启动调用了哪些方法?从前台到后台调用了哪些方法?

1.– (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions NS_AVAILABLE_IOS(3_0);
当程序启动时,调用此回调,launchOptions是启动参数,假如用户通过点击push通知启动的应用,这个参数里会存储一些push通知的消息。
2.– (void)applicationDidBecomeActive:(UIApplication *)application;
当应用程序全新启动,或者在后台转到前台,完全激活时,都会调用此方法,如果应用程序是以前运行在后台,这时可以选择刷新用户界面。
3.– (void)applicationWillResignActive:(UIApplication *)application;
当应用从活动状态主动到非活动状态的应用程序时会调用这个方法,这可以导致产生某些类型的临时中断。或者当用户退出应用程序,它开始过渡到的背景状态,使用此方法可以暂停正在进行的任务。
调用时机可能有以下几种:锁屏,按HOME键,下接状态栏,双击home等情况。
4.-(BOOL)application:(UIApplication )application handleOpenURL:(NSURL )url;
这个方法已经不再支持,可能会再以后某个版本中去掉,建议用下面的方法代替
5.– (BOOL)application:(UIApplication )application openURL:(NSURL )url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation NS_AVAILABLE_IOS(4_2);
当用户通过其他应用启动本应用时,会回调这个方法,url参数是其它应用调用openurl这个方法传过来的
6.– (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;
当应用可用内存不足时,会调用此方法,在这个方法中,应该尽量去清理可能释放的内存,如果实在不行,可能会被强行退出应用。
7.– (void)applicationWillTerminate:(UIApplication *)application;
当应用退出,并且进程即将解锁时会调到这个方法,一般很少主动调到,更多是内存不足时是被迫调到的,我们应该在这个方法里做一些数据存储操作。
8.registerForRemoteNotifications -(void)application:(UIApplication )application didRegisterForRemoteNotificationsWithDeviceToken:(NSData )deviceToken NS_AVAILABLE_IOS(3_0); -(void)application:(UIApplication )application didFailToRegisterForRemoteNotificationsWithError:(NSError )error NS_AVAILABLE_IOS(3_0);
客户端注册远程通知时,会掉上面两个方法。
如果成功,则回调didRegisterForRemoteNotificationsWithDeviceToken客户端把DeviceToken取出来发给服务端。
如果失败,则回调didFailToRegisterForRemoteNotificationsWithDeviceToken可以从error参数看一下失败原因。
9.– (void)applicationDidEnterBackground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);
当用户从前台状态转入后台时,调用此方法,使用此方法来释放资源共享,保存用户数据,无效计时器,并存储足够的应用程序状态信息的情况下被终止后,将应用程序恢复到目前的状态。如果应用程序支持后台运行,这种方法被调用,否则调用applicationWillTerminate,用户退出。
10.```– (void)applicationWillEnterForeground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);


#####19.NSCache优于NSDictionary的几点?
NSCache是一个容器类,类似于NSDictionary通过key-value形式存储和查询值,用于临时存储对象。
它与NSDictionary区别就是 NSCache中key不必实现copy,NSDictionary中的key必须实现copy
NSCache中存储的对象也不必实现NSCoding协议,因为毕竟是临时存储,类似于内存缓存,程序推书后就被释放。
NSCache胜过NSDictionary之处在于,当系统资源将要耗尽是,它可以自动删减缓存,如果采用普通的字典,那么就要自己编写挂钩,在系统发出低内存通知手工删减缓存。
NSCache并不会拷贝键,而是会保留它,此行为用NSDictionary也可以实现,然后需要编写相当复杂的代码,NSCache对象不拷贝键的原因在于:很多时候,键都是不支持拷贝操作的对象来充当的,因此,NSCache不会自动拷贝键,所以说,在键不支持拷贝的操作的情况下,该类用起来比字典更方便。另外,NSCache是线程安全的,而NSDictionary则绝对不具备此优势。

#####20.知不知道Designated Initializer?使用它的时候有什么需要注意的问题?
Designated Initializer:指定初始化器
注意:
1.确保类的Designated Initializer中,调用父类的Designated Initializer函数
2.父类的Designated Initializer函数的返回值存在变量self中,
3.第二部结束后,如果self的值为nil,不能继续初始化操作
4.确保子类复写了父类的Designated Initializer函数
5.确保类里的每个非Designated Initializer的出事化函数都会调用Designated Initializer

#####21实现description方法能取到什么效果?
实现description方法返回一个有意义的字符串,用以描述该实例
若想在调试时打印出更详尽的对象描述信息,则应该实现debugDescription方法

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

推荐阅读更多精彩内容