iOS之面试题笔记2

注:以下的内容是我自己面试遇到的或者是在网上找到的,然后自己总结了下,不恰当的地方请指正,万分感激!!

1.如果设计一个秒表的APP

为了防止手指在触摸屏幕的时候停止跳动,一般会用到哪个类?
一般会用到 NSRunLoop类?????

2.如果需要持久化对象,需要实现的协议是:

实现的协议是NSCoding的协议。// 归档和结归档。

NSCoding Delegate Method
- (void)encodeWithCoder:(NSCoder *)aCoder {
  // 进行编码操作
  [aCoder encodeObject:_instance forKey:@"_intance.key"];
}

- (void)initWithCoder:(NSCoder *)aDecoder {
  // 进行解码操作
  if (self = [super init]) {
    self.instance = [aDecoder decodeObjectForKey:@"_instance.key"];
  }
  return self;
}

3.UIApplication类帮助我们运行Maps,sms,浏览器或其他程序的时候用的方法是:- (BOOL)openURL:(NSURL*)url;

openURL:方法,/*'URL'就是统一资源定位符。*/
UIApplication类有个功能十分强大的openURL:方法
- (BOOL)openURL:(NSURL*)url;
openURL:方法的部分功能有
// 打电话:
UIApplication *app = [UIApplication sharedApplication];
[app openURL:[NSURL URLWithString:@"tel://10086"]];
//发短信 :
[app openURL:[NSURL URLWithString:@"sms://10086"]];
// 发邮件 :
[app openURL:[NSURL URLWithString:@"mailto://[email protected]"]];
// 打开一个网页资源:
[app openURL:[NSURL URLWithString:@"http://ios.cn"]];
打开其他app程序:openURL方法,可以打开其他APP。

4.在viewController中,init loadView viewWillAppear等的执行顺序。

执行的顺序为:
->init方法:执行关键数据初始化操作,注意这里不要做view相关操作
->loadView->viewDidLoad->viewWillAppear->viewWillLayoutSubviews->viewDidLayoutSubviews->viewDidAppear->viewWillDisappear->viewDidDisappear->viewWillUnload->viewDidUnload。

5.performSelector:withObject:方法的作用是什么?

简而言之就是程序在运行的时候去找方法,而不在编译的时候找方法。如果写了一个方法却不存在,直接调用执行这个方法,会在编译的时候报错,而如果使用performSelector进行调用的话,不会再编译的时候报错,而是在程序运行的时候进行报错而导致崩溃。

5.Socket和HTTP的区别 (TCP/IP)

http://blog.csdn.net/zeng622peng/article/details/5546384

a.HTTP:

HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。

b.Socket

c.区别

很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。

注:

TCP/IP的三从握手:
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。
建立起一个TCP连接需要经过“三次握手”:
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)

6.polymorphism(多态)

多态就是多个对象想要你同一个方法的时候有着不同的结果,这就是多态,这都要用到继承的。

7.为什么很多内置类如UITableViewController的delegate的属性都是用的assign而不是retain。

首先如果使用了retain的话,会造成循环引用。
如果控制器的有个对象a持有tableView的对象b,而恰好b的delegate又持有a,而如果delegate的属性是retain的话,那么在a想要释放的时候,a所持有的b是不会被释放,因而a也得不到释放,所以为了避免循环引用,要用assign。

8.在一个对象的方法里面:self.name = "object";和name = "obeject";有什么不同。

1.self.name:是会调用name的setName()方法。
2.name:会直接把object赋值给当前对象的name属性。

9.如何实现深拷贝

http://www.cocoachina.com/ios/20141113/10213.html
首先拷贝分为深拷贝和浅拷贝;
1.浅拷贝:只复制指向对象的指针,而不复制引用的对象本身,是通过复制对象的指针来访问指针。

char* str = (char*)malloc(100);
char* str2 = str;

2.深拷贝:复制的是对象本身。加入A修改了,而A_Copy是不会被修改的。
默认遵守了NSCopying和NSMutableCopying协议的可以有

NSString *string = @”dddd";
NSString *stringCopy = [string copy];
NSMutableString *stringDCopy = [string mutableCopy];
[stringMCopy appendString:@"!!"];

以上的代码得知,string和stringCopy的指向的地址是一致的,值也固然是一致的,但是如果更改了string的值,string的地址会改变,而stringCopy的地址和值均不改变。

但是如果没有遵守这两个协议的,也是可以构造。还是得遵守NSCopying协议和实现copyWithZone:方法。

#pragma  mark - 协议的遵守
@interface MyObj : NSObject{
    NSMutableString *_name;
    NSString * _imutableStr ;
    int _age;
}     
@property (nonatomic, retain) NSMutableString *name;
@property (nonatomic, retain) NSString *imutableStr;
@property (nonatomic) int age;

#pragma  mark - Copy的构造
- (id)copyWithZone:(NSZone *)zone{
    MyObj *copy = [[[self class] allocWithZone :zone] init];
    copy->name = [_name copy];
    copy->imutableStr = [_imutableStr copy];
    copy->age = age;
    return copy;
}

#pragma  mark - MutableCopy的构造
- (id)mutableCopyWithZone:(NSZone *)zone{
    MyObj *copy = NSCopyObject(self, 0, zone);
    copy->name = [_name mutableCopy];
    copy->age = age;
    return copy;
}

9.JSON和XML解析的原理

区别:
1.XML和JSON的可读性都基本相同,但是XML的可读性比较好。
2.可扩展性:两者都具有很好的扩展性,
3.编码难度:JSON的编码比较容易
4.解码难度:JSON的解码难度基本为0,XML需要考虑到子节点和父节点
5.数据体积:JSON相对XML而言体积小,传递速度更快
6.数据交互:JSON和JS的交互更加方便,更好的解析出来,更好的数据交互
7.数据描述:XML对数据描述性比较好
JSON解析原理
遍历字符串中的字符,最终根据格式规定的特殊字符,比如:
{} [] :等进行区分,
{}:是一个字典的开始
[]:是一个数组的开始
::字典的键 值 的区别
最终将JSON数据转化为字典,字典中的值可能是数组或者是字符串。
XML的解析原理
常用的解析方式是两种:DOM解析和SAX解析
DOM常用建立树形结构的方式访问XML文档,DOM解析把XML文档转化为包含其内容的树,并且可以对树进行遍历。使用DOM解析的时候,需要处理整个XML文档,所以对性能和内存的要求比较高;
SAX采用的是事件模型,SAX解析XML文档时可以触发一系列事件,当发现给定的tag值之后,可以激活一个回调方法,告诉该方法制定的tag已经找到,SAX对于内存的要求比较低。

10.什么是简便构造方法

- (instancetype)init
{
    self = [super init];
    if (self) {
        <#statements#>
    }
    return self;
}

初始化对象(分配空间并且初始化)
作用:
用作初始化对象的成员变量.
把 C 语言指针初始化为 NULL
把 OC 对象初始化为 nil
把基本数据类型初始化为0

11.什么是谓词

Predicate
谓词就相当于指定过滤器的条件。创建NSPredicate对象,这个对象可以准确的描述需要的条件,通过谓词筛选每个对象,就可以判断它们是否与条件相匹配
原理类似于在数据库中进行查询。

12.在项目中,什么时候使用GCD什么时候使用NSOperation

GCD一般做异步处理 。NSOperation一般是多个操作,可以方便的控制异步的执行数量,如下载任务。
两者的区别:
1.GCD:是APPLE为多核的并行运算提出的解决方案,他会自动利用更多的CPU内核,可以自动管理线层的生命。GCD是纯C语言的API,任务是用块来表示的,而块是个轻量级的数据结构。
2.NSOperation:他是oc的对象,operation是个重量级的oc对象,而且NSOperation和NSOperationQueue的好处如下:
a.取消某个操作
b.指定操作间的依赖关系
c.通过键值观测机制监控NSOperation对象的属性
d.指定操作的优先级
e.重用NSOperation对象。

13.什么是block,block实现原理。

1.块也就是我们所说的block,块与函数类似,只不过是直接定义在另一个函数里的,和定义在那个函数共享一个范围内的东西。block是用“^”表示的,后面跟着一对花括号,括号里面的是现实代码。例如:

^ {
  // block implementation is here
}

block其实就是一个值,自己有其相关的类型,也可以像int类型等把block赋值给变量。

void (^someBlock)() = ^ {
  // block implementation is here
};

这里的block类型的语法结构如下:

return_type (^block_name)(parameters)

2.block是可以分配在栈上或堆上的,也可以是全局的,分配在栈上的block是可以通过copy函数copy到堆上的(深拷贝),这样就具备了和oc对象一样的引用计数了。
3.block的实现原理
在oc引入块之前,要实现相同的功能的,就需要传入函数的指针或选择子的名称,提供给其他的方法进行调用。
而block在内存中的结构为isa、flags、reserved、invoke、discriptor。而isa也是指向Class对象的指针;在内存中最为重要的是invoke变量,这个函数指针指向block中的现实代码。而descriptor变量指向的是结构体的指针,其中申明了block对象的总体大小;这里还有两个辅助函数对应的指针,分别是copy和dispose,copy是要保留捕获的对象,而dispose是讲捕获的对象进行释放。
block是可以拿到所在函数范围内所有东西,所以在block里可以拿到被捕获的变量,但是默认是不能够对变量进行修改的,如需要进行修改是要加上__block修饰符的。

14.谈谈对响应链的理解

事件响应链:
包括了点击事件,画面刷新事件等,在试图栈内从上至下,或从下至上传播,可以说点事件的分发,传递及处理(具体的看Touch事件)
首先解释下响应者链的概念:
A.UIResponder类,是UIKit中一个用于处理事件响应的基类。窗口上所有事件触发都有该类响应(即事件处理入口),所有窗口上的View和控制器UIViewController都是其派生类。
B.调用UIResponder类提供的方法或熟悉,我们就可以捕捉到窗口上的所有响应事件,并且进行处理。
C.响应者链条是由多个响应者对象连接起来的链条,其中响应者对象是能处理事件的对象,所有的view和VC都是响应对象,利用响应者链条可以让多个控件处理同一个触摸事件。
事件传递机制:
如果当前的view不能处理当前事件,那么事件将会沿着响应者链
(Responder Chain)进行传递,直到遇到能处理该事件的响应者(Responder Object)。
接收事件的initial view如果不能处理该事件并且自己也不是顶层的View,则事件会往他的父类view进行传递
initial view的父视图获取事件如果还是不能处理,则会继续往上传递,循环这个过程。如果顶层的view还是不能处理这个事件的话,则事件会传递给她们的控制器VC。
如果VC也不能处理,则传递给UIWindow,此时UIWindow还是不能处理的话,就传递给UIApplication,如果UIApplication还是不能处理的话,这个事件就会被废弃掉。
注:事件的分发和以上的过程是相反的。事件分发主要是找到事件能够被处理的对象。

15.frame和bounds有什么区别

frame的位置和大小是以本个视图的父视图为基准的。
bounds的位置和大小是本个试图为基准的。

16.写一个标准的宏MIN,这个宏输入两个参数,并返回较小的一个

#define MIN(a,b) ((a)>(b)?(b):(a)) // 三元运算

17.说一说对NSRunLoop的理解。

Runloop 是什么?Runloop 还是比较顾名思义的一个东西,说白了就是一种循环,只不过它这种循环比较高级。一般的 while 循环会导致 CPU 进入忙等待状态,而 Runloop 则是一种“闲”等待。当没有事件时,Runloop 会进入休眠状态,有事件发生时, Runloop 会去找对应的 Handler 处理事件。Runloop 可以让线程在需要做事的时候忙起来,不需要的话就让线程休眠。
几乎每个讲 Runloop 的文章都会引用的图,大体说明了 Runloop 的工作模式:

iOS之面试题笔记2_第1张图片
工作模式

图中展现了 Runloop 在线程中的作用:从 input source 和 timer source 接受事件,然后在线程中处理事件。

Runloop 和线程是绑定在一起的。每个线程(包括主线程)都有一个对应的 Runloop 对象。我们并不能自己创建 Runloop 对象,但是可以获取到系统提供的 Runloop 对象。

主线程的 Runloop 会在应用启动的时候完成启动,其他线程的 Runloop 默认并不会启动,需要我们手动启动。

18.nil,Nil,NULL,NSNull的区别

1.nil和 C 语言的 NULL 相同,在 objc/objc.h 中定义。nil 表示 Objective-C 对象的值为空。在 C 语言中,指针的空值用 NULL 表示。在 Objective-C 中, nil 对象调用任何方法表示什么也不执行,也不会崩溃。
2.Nil:那么对于我们 Objective-C 开发来说,Nil 也就代表((void *)0)。但是它是用于代表空类的. 比如:Class myClass = Nil;
3.NULL : 在 C 语言中,NULL是无类型的,只是一个宏,它代表空. 这就是在 C/C++中的空指针。对于我们 Objective-C 开发来说, NULL 就表示((void*)0).
4. NSNull:NSNULL是继承于 NSObject 的类型。它是很特殊的类,它表示是空,什么也不存储,但是它却是对象,只是一个占位对象。使用场景就不一样了,比如说服务端接口中让我们在值为空时,传空。

NSDictionry *parameters = @{@"arg1" : @"value1",@"arg2" : arg2.isEmpty ? [NSNull null] : arg2};

 NULL、 nil、 Nil 这三者对于 Objective-C 中值是一样的,都是(void *)0,那么为什么要区分呢?又与 NSNull 之间有什么区别:
 NULL 是宏,是对于 C 语言指针而使用的,表示空指针;
 nil 是宏,是对于 Objective-C 中的对象而使用的,表示对象为空;
 Nil 是宏,是对于 Objective-C 中的类而使用的,表示类指向空;
 NSNull 是类类型,是用于表示空的占位对象,与 JS 或者服务端的null 类似的含意。

你可能感兴趣的:(iOS之面试题笔记2)