题目!!!!

MVC的理解

=>MVC是一种设计模式,全程Model(模型)-View(视图)-Controller(控制器),将界面和业务逻辑分开

Model:包含数据和业务逻辑,View是视图,即用户看到的,用来显示数据,Controller用来充当二者的媒介。

类似的模式还有:MVVM


Delegate与Block的区别

二者都是回调的方式,delegate需要实现protocol

block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是加计数,使用完或者block置nil后才消除。delegate只是保存了一个对象指针,直接回调,没有额外消耗。


消息通知的种类

消息通知有两类:本地通知、推送通知,二者表现方式一样,可以通过横幅或弹出形式提醒用户。


Delegate, Notification,KVO优缺点

Delegate:语法严格,编译器可以进行语法检查并提醒错误,逻辑明确,容易跟踪流程,一个类可以有多个协议,每个协议可以不同的方法;可以获得反馈值,只能一对一

缺点:代码多

Notification:轻松实现一对多传值

缺点:编译器不明确通知是否会被处理,注册的通知对象要移除,通知发出后不能从观察者获得反馈信息

KVO:以上两种多用于Controller与其他对象的通信,KVO适用于任何对象对另一个对象的改变,是对象之间的同步。能够对非我们创造的对象进行监听。

缺点:只能监听属性,不能对方法有反应,属性必须用string来定义,因此编译器不会有提示。

综上:当处理属性级别的消息时,用KVO,其他用Delegate,如果处理的代码很简单,可以用通知。


手动触发KVO,以及KVO的底层原理

被观察者发出  addObserver:forKeyPath:options:context:。

观察者需要实现方法 observeValueForKeyPath:ofObject:change:context:

手动触发:[person willChangeValueForKey:@"name"];[person didChangeValueForKey:@"name"];

KVO的底层实现原理:是用Runtime来实现的,当类对象添加观察时,会动态地派生出一个新类继承自父类,新类重写setter方法,并且原来类对象的isa指针(每个实例对象有个isa的指针,他指向对象的类)会指向新类,当类对象改变值时,执行的是新类的setter方法,会有willChangeValueForKey、[super setValue:for:key]、didChangeValueForKey从而observeValueForKey:ofObject:change:context:被调用通知被观察对象的值有更改。


Objective-C的Copy在那些场景下使用

NSString,NSArray,NSDictionary属性会用copy,都对应有可变类型,防止赋值给它的是可变的数据,如果可变的数据发生了变化,那么该property也会发生变化。

block在MRC时需要使用copy,在ARC与Strong效果一样。

可变的不能用Copy,比如NSMutableArray,因为copy就是复制一个不可变对象,如果增删改会因为找不到方法而崩溃。


Runtime的消息传递

消息传递:相较于C语言而言,C语言使用的是“静态绑定”,函数的调用在编译期就能知道运行期所需要调用的函数了,编译完成之后就按照顺序执行(面向过程就是这么任性)。而OC使用的是“动态绑定”特性,也就是说编译器在编译期的时候无法决定运行期调用哪个函数,也就是说在编译阶段,OC可以调用任何函数,即使该函数未实现,但只要声明过就不会报错,对象在接收到消息之后,究竟该调用哪个方法完全由运行期决定,甚至可以在程序运行时改变。

id returnValue = [someObject messageName:paramater];

编译器会将方法转换成objc_msgSend函数

id returnValue = objc_msgSend(someObject, @selector(messageName:), paramater);

消息传递的过程:当给一个对象发送消息的时候,消息传递函数首先根据对象的isa指针找到类的结构,然后在其分发表中寻找对应的selector,如果找到的话就调用对应的实现;如果找不到则会根据super class指针去其父类寻找,如果父类还找不到,会接着去父类的父类中寻找,直到NSObject类为止。为了加速消息传递的过程,运行时系统会缓存用到过的selector,每个类都有一个单独的cache,它可以缓存继承或自己定义的方法。在根据selector名字搜索分发表之前,消息路由会首先检查someObject的类的cache是否已经缓存对应的selector,如果有的话就直接调用对应的实现。


Runtime消息转发

当向某个对象发送一条消息时,若该对象的方法列表以及它相应继承链上的方法列表都无法找到以该消息selector作为key的方法实现时,则会触发消息转发机制。转发有三次机会:

1、动态解析:+ (BOOL)resolveInstanceMethod:(SEL)sel;如果在这个函数中动态添加方法(class_addMethod),则运行这个方法并且添加到缓存中以便下次调用,如果没有则进入第二步

2、消息接受对象更改:- (id)forwardingTargetForSelector:(SEL)aSelector;该方法可以返回一个能处理该选择子的其他对象,运行时系统会根据返回的对象进行查找,若找到则跳转到相应方法的实现,则消息转发结束。如果返回为nil,则进入第三步

3、完整的改变:- (void)forwardInvocation:(NSInvocation *)anInvocation;该方法可以改变消息调用对象,运行时系统根据所改变的调用对象,向调用目标方法列表中查询对应方法的实现并实现跳转,这种方式和第二步的操作非常相似。当然你也可以修改方法的selector,亦或者向所调用方法中追加一个参数等来跳转到相关方法的实现。如果依旧无法处理,则进入第四步

4、无法处理:- (void)doesNotRecognizeSelector:(SEL)aSelector;


load与initialize的区别

Load:load方法在这个文件被程序装载时调用。只要是在Compile Sources中出现的文件总是会被装载,这与这个类是否被用到无关,因此load方法总是在main函数之前调用。这个方法会自动调用父类的load,不需要手动实现,比较常用的是Method Swizzle放在load里实现。

InitializeI:这个方法在第一次给某个类发送消息时调用(比如实例化一个对象),并且只会调用一次。initialize方法实际上是一种惰性调用,也就是说如果一个类一直没被用到,那它的initialize方法也不会被调用,initialize方法主要用来对一些不方便在编译期初始化的对象进行赋值。比如NSMutableArray这种类型的实例化依赖于runtime的消息发送,所以显然无法在编译器初始化。

load和initialize方法都会在实例化对象之前调用,以main函数为分水岭,前者在main函数之前调用,后者在之后调用。这两个方法会被自动调用,不能手动调用它们。load方法通常用来进行Method Swizzle,initialize方法一般用于初始化全局变量或静态变量。


isMemberOfClass和isKindOfClass的区别

-(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例

-(BOOL) isMemberOfClass: classObj 判断是否是这个类的实例


数据持久化方案有哪些?

plist文件(属性列表):plist文件是将某些特定的类(NSArray;NSMutableArray;NSDictionary;NSData;NSString;NSNumber;NSDate;)通过XML文件的方式保存在目录中。存储时使用writeToFile: atomically:方法。 其中atomically表示是否需要先写入一个辅助文件,再把辅助文件拷贝到目标文件地址。这是更安全的写入文件方法,一般都写YES。读取时使用arrayWithContentsOfFile:方法。

preference(偏好设置):NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

偏好设置是专门用来保存应用程序的配置信息的,一般不要在偏好设置中保存其他数据。

如果没有调用synchronize方法,系统会根据I/O情况不定时刻地保存到文件中。所以如果需要立即写入文件的就必须调用synchronize方法。

偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件。

NSKeyedArchiver(归档):遵循NSCoding协议的对象都可以通过它实现序列化

[NSKeyedArchiver archiveRootObject:person toFile:file];//归档

Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];//解档

SQLite 3:SQLite3的使用还是比较麻烦的,因为都是些c语言的函数,理解起来有些困难。不过在一般开发过程中,使用的都是第三方开源库 FMDB,封装了这些基本的c语言方法,使得我们在使用时更加容易理解,提高开发效率。

integer : 整数

real : 实数(浮点数)

text : 文本字符串

blob : 二进制数据,比如文件,图片之类的

CoreData:SQLite的封装,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句


ViewController生命周期,详细介绍一下loadView

视图加载

通过Storyboard加载:这是苹果推荐的方式,也是未来的趋势。通过这种方式创建UIViewController对象的话,首先生成UIStoryboard类型的对象,然后调用这个对象的instantiateViewControllerWithIdentifier:方法

通过Nib文件加载:Nib文件其实就是xib文件,Storyboard相当于是聚合了多个nib文件,并且添加了对不同的UIViewController之间的segue和relationship的管理。但总的实现原理非常类似,通过这种方式加载视图,需要调用UIViewController类的initWithNibName:bundle:方法

通过loadview方法加载:这就是通过代码加载。这需要我们在loadView方法中,通过编程创建自己的视图层次,并且把把根视图赋值给UIViewController的view属性。

loadView:在UIViewController对象的view属性被访问到且为空的时候调用。因此这个方法在视图控制器的生命周期内可能会被多次调用。在创建view的过程中,首先会根据nibName去找对应的Nib文件然后加载。如果nibName为空,或找不到对应的Nib文件,则会创建一个空视图(这种情况一般是纯代码,也就是为什么说代码构建View的时候,要重写loadView方法)。注意在重写loadView方法的时候,不要调用父类的方法

-[ViewController initWithCoder:]或-[ViewController initWithNibName:Bundle]:首先从归档文件中加载UIViewController对象。即使是纯代码,也会把nil作为参数传给后者。

-[UIView awakeFromNib]:作为第一个方法的助手,方便处理一些额外的设置。

-[ViewController loadView]:创建或加载一个view并把它赋值给UIViewController的view属性

-[ViewController viewDidLoad]:此时整个视图层次(view hierarchy)已经被放到内存中,可以移除一些视图,修改约束,加载数据等

-[ViewController viewWillAppear:]:视图加载完成,并即将显示在屏幕上,还没有设置动画,可以改变当前屏幕方向或状态栏的风格等。

-[ViewController viewWillLayoutSubviews]:即将开始子视图位置布局

-[ViewController viewDidLayoutSubviews]:用于通知视图的位置布局已经完成

-[ViewController viewDidAppear:]:视图已经展示在屏幕上,可以对视图做一些关于展示效果方面的修改。

-[ViewController viewWillDisappear:]:视图即将消失

-[ViewController viewDidDisappear:]:视图已经消失


Runloop

程序启动时,Runloop随着主线程的启动而启动,每个线程都有一个runloop,但是只有主线程的会自动启动。对于辅助线程,我们仍然需要判断是否需要启动Run Loop。比如我们使用一个线程去处理一个预先定义的长时间的任务,我们应当避免启动Run Loop。下面是官方Document提供的使用Run Loop的几个场景:

需要使用Port-Based Input Source或者Custom Input Source和其他线程通讯时

需要在线程中使用Timer

需要在线程中使用上文中提到的selector相关方法

需要让线程执行周期性的工作

Runloop的本质是一直运行着的循环,线程中的循环,用来接收循环中的事件并且安排线程工作,并且在没有工作的时候,让线程进入休眠状态。

接收事件:

1、Input source用来投递异步消息,通常消息来自另外的线程或者程序。在接收到消息并调用程序指定方法时,线程中对应的NSRunLoop对象会通过执行runUntilDate:方法来退出。Input source有两个不同的种类:Port-Based Sources和Custom Input Sources

2、Timer source用来投递timer事件(Schedule或者Repeat)中的同步消息。在处理消息时,并不会退出Run Loop。Timer在选择使用一次后,在执行完成时,会从Run Loop中移除。选择循环时,会一直保存在当前Run Loop中,直到调用invalidated方法。

3、Run Loop还有一个观察者Observer的概念,可以往Run Loop中加入自己的观察者以便监控Run Loop的运行过程,Run Loop Observer则在Run Loop本身进入某个状态时得到通知:Run Loop 进入的时候,Run Loop 处理一个Timer的时候,Run Loop 处理一个Input Source的时候,Run Loop 进入睡眠的时候,Run Loop 被唤醒的时候,在唤醒它的事件被处理之前,Run Loop 停止的时候

Runloop Mode,更改mode只能重新开启runloop,在设置Run Loop Mode后,你的Run Loop会自动过滤和其他Mode相关的事件源,而只监视和当前设置Mode相关的源(通知相关的观察者)。大多数时候,Run Loop都是运行在系统定义的默认模式上。

1) NSDefaultRunLoopMode: 大多数工作中默认的运行方式。

2) NSConnectionReplyMode: 使用这个Mode去监听NSConnection对象的状态,我们很少需要自己使用这个Mode。

3) NSModalPanelRunLoopMode: 使用这个Mode在Model Panel情况下去区分事件(OS X开发中会遇到)。

4) UITrackingRunLoopMode: 使用这个Mode去跟踪来自用户交互的事件(比如UITableView上下滑动)。

5) GSEventReceiveRunLoopMode: 用来接受系统事件,内部的Run Loop Mode。

6) NSRunLoopCommonModes:这是一个伪模式,其为一组run loop mode的集合。如果将Input source加入此模式,意味着关联Input source到Common Modes中包含的所有模式下。在iOS系统中NSRunLoopCommonMode包含NSDefaultRunLoopMode、NSTaskDeathCheckMode、UITrackingRunLoopMode.可使用CFRunLoopAddCommonMode方法向Common Modes中添加自定义mode。

Run Loop运行时只能以一种固定的Mode运行,只会监控这个Mode下添加的Timer source和Input source。如果这个Mode下没有添加事件源,Run Loop会立刻返回。

Run Loop不能在运行在NSRunLoopCommonModes,因为NSRunLoopCommonModes是个Mode集合,而不是一个具体的Mode。我们可以在添加事件源的时候使用NSRunLoopCommonModes,只要Run Loop运行在NSRunLoopCommonModes中任何一个Mode,这个事件源都可以被触发。


Objective-C中对象等同性怎么做?

obj1 == obj2这个是直接比较两个对象的指针是否相等,而不是对象本身,若想要检测对象的”对象的等同性“,请提供”isEqual:“与hash方法,NSObject类对这两个方法的默认实现是:当且仅当“指针值”(pointer value)完全相等时,这两个对象才相等,自定义对象时,则必须复写这些方法,如果isEqual:方法判定两个对象相等,那么其hash也必须返回同一个值。但是,如果两个对象的hash方法返回同一个值,那么“isEqual:”方法未必会认为两者相等。也就是相同的对象必须具有相同的hash码,但是两个hash码相同的对象却未必相同。


Autoreleasepool的使用场景,Autoreleasepool什么时候释放?

在没有手加Autorelease Pool的情况下,Autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop迭代中都加入了自动释放池Push和Pop

ARC下,我们使用@autoreleasepool{}来使用一个AutoreleasePool,编译器转化成

void *context = objc_autoreleasePoolPush();

// {}中的代码

objc_autoreleasePoolPop(context);


Objective-C字典中Key、Value有什么特别的要求

1、key不可以重复,value可以重复

2、key和value不能为空,如果要加入空值,用NSNull

3、value必须是对象


怎么判断Cell是否在屏幕中?

tableView有两个属性

@property(nonatomic,readonly)NSArray<__kindofUITableViewCell*> *visibleCells;

@property(nonatomic,readonly,nullable)NSArray *indexPathsForVisibleRows;


Strong和weak的底层了解吗?

MRC与ARC下blcok的区别

聊一下block的strong weak dance-参考

读过那些开源代码?请介绍其中一个

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

推荐阅读更多精彩内容

  • 1.内存管理 2.单例的理解 3.post和get的区别 4.md5和base64是什么,有什么区别 5.简单谈谈...
    coder_Wg阅读 1,285评论 1 6
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,125评论 29 470
  • 1、基础篇 1、1 属性和成员变量的区别 ? 1、11 涉及到的问题是类的分类中是否可以添加属性。 肯定是可以添...
    奋斗的蝼蚁阅读 367评论 0 9
  • Objective-C是一门动态的语言 ① 什么是动态语言? 动态语言,是指程序在运行时可以改变其结构:新的函数可...
    小李龍彪阅读 361评论 0 0
  • 一、笔试常用基础问题 1.#import 和 #include 的区别 @class? @class一般用于头文件...
    郑莫轩阅读 1,329评论 0 11