欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

【IOS学习】面试iOS工程师的相关问题

程序员文章站 2022-05-14 09:53:38
1. oc中,与alloc语义相反的方法是dealloc还是release?与retain语义相反的方法是dealloc还是release?为什么?需要与alloc配对使用的方法是dealloc还是...

1. oc中,与alloc语义相反的方法是dealloc还是release?与retain语义相反的方法是dealloc还是release?为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?

以下是针对mrc(手动内存释放)模式:

与alloc语义相反的方法是dealloc,与retain语义相反的方法是release。

alloc是为对象在内存中开辟空间,而dealloc则是对象销毁时释放空间。

retain方法是对象开辟空间以后使对象的引用计数器加1,而release是对象的引用计数器减1。

需要与alloc配对的方法是release,因为对象创建以后,对象的引用计数器自动加1,

而调用release方法后,对象的引用计数器归0,会自动调用dealloc方法释放空间。

2. 在一个对象的方法里面:self.name = @"object";和 _name = @"object"有什么不同吗?

self.name = @"object"; 是通过点语法修改属性name的值。

本质上使用的是name属性的setter方法进行的赋值操作,实际上执行的代码是

[self setname:@"object"];

例如:

@property(nonatomic, strong) nsstring *name;

//根据@property关键词,系统自动生成setter方法。

(void)setname:(nsstring )name{

//根据strong关键词

[name retain]; //内存计数+1

[_name release]; //把之前指针指向的内容内存计数-1

_name = name; //指向新内容

}

_name = @“object”; 只是单纯的把‘_name’指针指向‘@"object"’字符串对象所在的地址,

没有调用方法。

3. 这段代码有什么问题吗?

-(void)setage:(int)newage{

self.age = newage;

}

在age属性的setter方法中,不能通过点语法给该属性赋值。

会造成setter方法的循环调用。因为self.age = newage;

本质上是在调用 [self setage:newage]; 方法。

解决循环调用的方法是方法体修改为 _age = newage;

另外 变量名称不能使用new开头!

4. 以下每行代码执行后,person对象的retain count分别是多少?

person person = [[person alloc] init];

[person retain];

[person release];

[person release];

person person = [[person alloc] init]; =1

[person retain]; +1 = 2

[person release]; -1 = 1

[person release]; -1 = 0

内存计数技术规律

alloc,new,copy 内存计数 = 1

retain +1

release -1

uiview addsubview +1

nsmutablearray addobject +1

5. 这段代码有什么问题,如何修改?

for(int i = 0; i < somelargenumber; i++){

nsstring string = @“abc”;

string = [string lowercasestring];

string = [string stringbyappendingstring:@“xyz”];

nslog(@“%@“, string);

}

代码本身不会报错。

但是猜测出题者的意思是要循环添加为 abcxyzxyzxyz.....这样的形式。

如果是想在abc后面拼接多个xyz字符串的话,

则需要把"nsstring string = @“abc”;" 这行代码放在循环语句外面。

*6. 简要叙述面向对象的特点,特别是多态。

封装

封装是对象和类概念的主要特性。它是隐藏内部实现,提供外部接口,可以看作是“包装”。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,

对不可信的进行信息隐藏。

封装的目的是增强安全性和简化,使用者不必了解具体的实现细节,而只是要通过外部接口,

以特定的访问权限来使用类的成员。

好处:可以隐藏内部实现细节。通过大量功能类封装,加快后期开发速度。

继承

面向对象编程 (oop) 语言的一个主要功能就是“继承”。

继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下

对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。

继承的过程,就是从一般到特殊的过程。在考虑使用继承时,有一点需要注意,

那就是两个类之间的关系应该是“属于”关系。

例如,employee(雇员)是一个人,manager(领导)也是一个人,因此这两个类都可以继承person类。

但是 leg(腿) 类却不能继承 person 类,因为腿并不是一个人。

多态

多态性(polymorphism)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,

赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。

简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

不同对象以自己的方式响应相同的消息的能力叫做多态。

意思就是假设生物类(life)都用有一个相同的 方法-eat;那人类属于生物,猪也属于生物,

都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法。

也就是不同的对象以 自己的方式响应了相同的消息(响应了eat这个选择器)。

实现多态,有二种方式,覆盖,重载。

? 覆盖(override),是指子类重新定义父类的虚函数的做法。

? 重载(overload),是指允许存在多个同名函数,而这些函数的参数表不同

(或许参数个数不同,或许参数类型不同,或许两者都不同)。

这里注意:oc没有重载,因为oc只认函数名,不认参数类型。oc不允许存在多个同名函数。

总结:封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);

它们的目的都是为了——代码重用。

而多态则是为了实现另一个目的——接口重用!

多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

在类层次中,子类只继承一个父类的数据结构和方法,则称为单重继承。

在类层次中,子类继承了多个父类的数据结构和方法,则称为多重继承。

*7. objective-c 所有对象间的交互是如何实现的?

在对象间交互中每个对象承担的角色不同,但总的来说无非就是”数据的发送者”或”数据的接收者”两种角色。消息的正向传递比较简单,直接拿到接受者的指针即可。消息的反响传递可以通过委托模式,观察者模式(本质是单例模式),block语法,appdelegagte来实现。其中委托模式,block语法都是1对1的消息传递。 观察者模式是1对多。appdelegate比较特殊,这是一个生命周期与进程一致的对象。 8. 什么叫数据结构?

数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合。通常,精心选择的数据结构可以带来更高的运行或者存储效率。 9. oc的类可以多继承吗?可以实现多个接口吗?category是什么?分类中能定义成员变量或属性吗?为什么?重写一个类的方式是继承好还是类别好?为什么?

object-c的类不可以多重继承;可以实现多个接口(协议),通过实现多个接口可以完成c++的多重继承;category是类别,推荐使用类别,用category去重写类的方法,仅对本引入category的类有效,不会影响到其他类与原有类的关系。 10. #import和#include有什么区别?@class呢?#import<>和#import”“有什么区别?*

import是objective-c导入头文件的关键字,#include是c/c++导入头文件的关键字,使用#import头文件会自动只导入一次,不会重复导入,相当于#include和#pragma once;@class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含;#import<>用来包含系统的头文件,#import””用来包含用户头文件。例如:/ 如果这里不写@class,则报错。 原因是找不到myvc的定义。因为代码执行顺序是由上至下的。当声明协议myvcdelegate时, myvc还没有声明。使用 @class 名称随便写,不管是否存在。 可以自己用代码尝试随意写个@class 例如:@class hello; 就算项目中根本没有hello类,这里也不会报错。 因为只有当项目运行起来,才会真的去检查hello类是否声明了。/@class myvc;@protocol myvcdelegate- (void)myvc:(myvc *)myvc click:(id)sender;

@end

@interface myvc : basevc

@end

ps:ios7之后的新特性,可以使用@import 关键词来代理#import引入系统类库。

使用@import引入系统类库,不需要到build phases中先添加添加系统库到项目中。

11.属性readwrite, readonly, assign, retain, copy, nonatomic各是什么作用?在哪种情况下用?

1.readwrite 是可读可写特性;需要生成getter方法和setter方法时

(补充:默认属性,将生成不带额外参数的getter和setter方法(setter方法只有一个参数))

2.readonly 是只读特性,只会生成getter方法,不会生成setter方法;不希望属性在类外改变

3.assign 是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;

4.retain(mrc)/strong(arc) 表示持有特性,setter方法将传入参数先保留,

再赋值,传入参数的retaincount会+1;

5.copy 表示拷贝特性,setter方法将传入对象复制一份;需要完全一份新的变量时。

6.nonatomic 非原子操作,决定编译器生成的setter和getter方法是否是原子操作。

atomic表示多线程安全,需要对方法加锁,保证同一时间只有一个线程访问属性,

因为有等待过程,所以影响执行效率

一般使用nonatomic。不加锁。效率会更高。但是线程不安全。

12. 写一个setter方法用于完成@property(nonatomic, strong)nsstring name, 写一个setter方法用于完成@property(nonatomic, copy)nsstring name

(void)setname:(nsstring*)str //retain

{

[str retain];

[_name release];

_name = str;

}

(void)setname:(nsstring )str //copy

{

id t = [str copy];

[_name release];

_name = t;

}

*13. 对于语句nsstring obj = [[nsdata alloc] init]; obj在编译时和运行时分别是什么类型的对象?

编译时是nsstring的类型;运行时是nsdata类型的对象。 14. 常见的oc的数据类型有哪些? 和c的基本数据类型有什么区别? 如:nsinteger和int*

object-c的数据类型有nsstring,nsnumber,nsarray,nsmutablearray,nsdata等等。

c语言的基本数据类型int,只是一定字节的内存空间,用于存放数值;

nsinteger类型的定义是

if lp64 || (target_os_embedded && !target_os_iphone)

|| target_os_win32 || ns_build_32_like_64

typedef long nsinteger;

typedef unsigned long nsuinteger;

else

typedef int nsinteger;

typedef unsigned int nsuinteger;

endif

可以看到,在64位操作系统上,nsinteger是 c语言的long类型。

在32位操作系统上,则是int类型。

15. id声明的对象有什么特性?

id 声明的对象具有运行时的特性,即可以指向任意类型的objcetive-c的对象;

可以作为返回值,也可以声明对象。

例如

(id)initwithname:(nsstring *)name;

id obj = [nsobject new];

现在我们使用苹果推荐使用的“instancetype”类型代替id类型作为返回值

(instancetype)initwithname:(nsstring )name;

instancetype和id的区别在于, id可以声明对象 也可以作为返回值,

instancetype只能作为返回值。

*16. oc如何对内存管理的,说说你的看法和解决方法。

objective-c的内存管理主要有三种方式arc(自动内存计数)、手动内存计数、内存池。

自动内存计数arc:由xcode自动在app编译阶段,在代码中添加内存管理代码。

手动内存计数mrc:遵循内存谁申请,谁添加。谁释放的原则。

内存释放池release pool:把需要释放的内存统一放在一个池子中,当池子被抽干后(drain)

池子中所有的内存空间也被自动释放掉。 内存池的释放操作分为自动和手动。

自动释放受runloop机制影响。

17. 你对@interface中的成员变量和@property声明的属性的理解。

@interface aa: nsobject{

nsstring _name; //成员变量

}

@property nsstring sex; //属性

如上所示:

属性拥有setter和getter方法 外加_sex成员变量。

_name只是成员变量, 没有setter和getter方法。

18. do while 和while do的区别?

while do是先判断while中的表达式的真假,再执行循环。

do while先进行循环一次,再判断while中的表达式的真假。

19. 用预处理指令#define声明一个常数,用以表明一年中有多少秒(忽略闰年问题)。

define seconds_per_year (60 60 24 * 365)

20. 浅拷贝和深拷贝的区别?

浅拷贝:只复制指向对象的指针,而不复制引用对象本身。

深拷贝:复制引用和对象本身。

意思就是说我有个a对象,复制一份后得到a_copy对象后,

对于浅复制来说,a和a_copy指向的是同一个内存资源,复制的只不过是是一个指针,

对象本身资源还是只有一份。

那如果我们对a_copy执行了修改操作,那么发现a引用的对象同样被修改,

这其实违背了我们复制拷贝的一个思想。

深复制就好理解了,内存中存在了两份独立对象本身。

用网上一哥们通俗的话将就是:

浅拷贝好比你和你的影子,你完蛋,你的影子也完蛋

深拷贝好比你和你的克隆人,你完蛋,你的克隆人还活着。

21. 类别的作用?继承和类别在实现中有何区别?

category可以向类中添加新的方法,或者重写已有方法。

正常情况下不可以添加属性。但是实际应用中可以通过runtime机制添加属性。

类别主要有3个作用:

将类的实现分散到多个不同文件或多个不同框架中。降低耦合性。

重写主类方法

向类中添加协议,属性,方法。

继承主要作用:

重写父类方法

在父类基础上增加属性,方法,协议

区别:继承使用时,需要使用子类。 category使用时只需要引入头文件。

22. 我们说的oc是动态运行时语言是什么意思?

编译时等价于编码时, 编码时就是程序员写的代码的样子. 程序员为一个类编写代码,

便可以为一个类添加 “成员变量(实例变量)” . 程序员也可以在一个类中写一些函数, 被称作“方法”.

运行前编译, 编译器会把程序员写的代码编译成可执行文件, 里面便有之前写的类的信息,

包括实例变量和方法, 这些信息并不能组成一个实际的数据类型.

程序运行后, 会将这些信息拼凑成一个结构体, 这个结构体便是一个数据类型.

同时, 在运行期间, 数据类型可以改变, 表现为:

可以动态增添方法

可以动态增添实例变量

等等..做一些运行时数据类型修改.

一旦做了运行时修改, 就会使得这个结构体与程序员当初编写的类不一样.

23. 为什么很多内置类如uitableview的delegate属性都是assign而不是retain ?

如果是retain会引起循环引用。

所有的引用计数系统,都存在循环引用的问题。例如下面的引用关系:

对象a创建并引用了对象b,对象b创建并引用了对象c,对象c创建并引用了对象b.

这时候b和c的引用计数分别是2和1。当a不再使用b,调用release释放对b的所有权,因为c还引用了b。

所以b的引用计数为1,b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。

从此,b和c永远留在内存中。

这种情况,必须打断循环引用,通过其他规则来维护引用关系。

比如,我们常见的delegate往往是assign方式的属性而不是retain方式的属性,

赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。

如果一个uitableviewcontroller对象a通过retain获取了uitableview对象b的所有权,

这个uitableview对象b的delegate又是a,如果这个delegate是retain方式的,

那基本上就没有机会释放这两个对象了。

24. 什么时候用delegate,什么时候用notification?

delegate(委托模式):

1对1的反向消息通知功能。

notification(通知模式):

只想要把消息发送出去,告知某些状态的变化。但是并不关心谁想要知道这个。

25. 什么是kvc和kvo?

kvc(key-value-coding):键 - 值编码是一种通过字符串间接访问对象的方式。

而不是通过调用setter方法或通过实例变量访问的机制。很多情况下可以简化程序代码。

例如:

@interface meiling:nsobject

@property nsstring name;

@property uilabel label;

@end

对于name的赋值 可以使用 meiling.name = @"笑玲"; 这是点语法。调用的是setname方法。

kvc的写法是 [meiling setvalue:@"梦玲" forkey:@"name"]; 通过name字符串赋值。

当然也可以跨层赋值,例如为label的text属性赋值

点语法: meiling.label.text = @"笑玲";

kvc: [meiling setvalue:@"梦玲" forkeypath:@"label.text"];

kvo:键值观察机制,他提供了观察某一属性变化的方法,极大的简化了代码。

kvo 只能被 kvc触发, 包括使用setvalue:forkey:方法 和 点语法。

通过下方方法为属性添加kvo观察

(void)addobserver:(nsobject )observer

forkeypath:(nsstring )keypath

options:(nskeyvalueobservingoptions)options

context:(nullable void *)context;

当被观察的属性发生变化时,会自动触发下方方法

(void)observevalueforkeypath:(nsstring )keypath

ofobject:(id)object

change:(nsdictionary )change

context:(void )context

*26. 设计模式是什么?你知道哪些设计模式,并简要叙述。

单例模式:通过static关键词,声明全局变量。在整个进程运行期间只会被赋值一次。

观察者模式:kvo是典型的通知模式,观察某个属性的状态,状态发生变化时通知观察者。

委托模式:代理+协议的组合。实现1对1的反相传值操作。

工厂模式:通过一个类方法,批量的根据已有模板生产对象。

mvc模式:model view control, 把模型 视图 控制器 层进行解耦合编写。

mvvm模式:model view viewmodel 把 模型 视图 业务逻辑 层进行解耦合编写。

27. 描述一下ios sdk中如何实现mvc的开发模式。

mvc即 model-view-control

model称为模型层,主要负责数据结构,业务逻辑相关的操作

view 称为视图层,主要负责视图的展示

control 称为控制层,主要负责把view和model层结合起来的操作。例如点击视图上的某个按钮

要执行model层中的某个业务逻辑。 或者把model中的数据展现在视图上。

28. viewcontroller的didreceivememorywarning是在什么时候调用的?默认的操作是什么?

当系统内存不足时,首先uiviewcontroller的didreceivememorywarining方法会被调用。

默认操作如果当前控制器不是window的根视图控制器,会自动将self.view释放。

29. delegate和block的区别?

delegate:

需要定义协议方法并且实现协议方法,会使代码结构变复杂

效率没有block高

block:

代码结构更加紧凑,不需要额外定义方法。

需要注意防止循环引用,使用__weak 关键词修饰

当需要在块中修改外部变量时,需要对外部变量使用__block 关键词修饰

30. frame和bounds有什么不同?

frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父亲的坐标系统)

bounds指的是:该view在本身坐标系统中 的位置和大小。(参照点是本身坐标系统)

31.viewcontroller生命周期

按照执行顺序排列

initwithcoder:通过nib文件初始化时触发

awakefromnib:nib文件被加载的时候,会发送一个awakefromnib的消息到nib文件中的每个对象

loadview:开始加载视图控制器自带的view

viewdidload:视图控制器的view被加载完成

viewwillappear:视图控制器的view将要显示在window上

updateviewconstraints:视图控制器的view开始更新autolayout约束

viewwilllayoutsubviews:视图控制器的view将要更新内容视图的位置

viewdidlayoutsubviews:视图控制器的view已经更新视图的位置

viewdidappear:视图控制器的view已经展现到window上

viewwilldisappear:视图控制器的view将要从window上消失

viewdiddisappear:视图控制器的view已经从window上消失

32. 如何将产品进行多语言发布,开发?

国际化操作

在xcode中,project里,找到localization,点击+号,添加想要支持的语言

通过新建strings文件,把文件进行国际化处理。 通过键值对的形式,同一个key在不同的国际化

文件中,对应不同的值。

通过 nslocalizedstringfromtable 等方法,通过key来自动根据ios设备的当前语言,

显示不同的字符串。

33. oc中是如何实现线程同步的?

@synchronized: 添加同步锁

nslock:加锁

nscondition:加条件锁

dispatch_async(dispatch_get_main_queue(), ^{}); :异步主线程

nsoperationqueue:添加线程依赖

nsoperationqueue:设置最大并发数为1

34. udp和tcp的区别是什么?

1.基于连接与无连接;

2.对系统资源的要求(tcp较多,udp少);

3.udp程序结构较简单;

4.流模式与数据报模式 ;

5.tcp保证数据正确性,udp可能丢包,tcp保证数据顺序,udp不保证

35. tcp/ip建立连接的过程?

在tcp/ip 协议中,tcp协议提供可靠的连接服务,采用三次握手建立连接;

第一次握手:建立连接时,客户端发送连接请求到服务器,并进入syn_send状态,等待服务器确认;

第二次握手:服务器收到客户端连接请求,向客户端发送允许连接应答,

此时服务器进入syn_recv状态;

第三次握手:客户端收到服务器的允许连接应答,向服务器发送确认,客户端和服务器进入通信状态,

完成三次握手。

(所谓的三次握手,就是要有三次连接信息的发送、接收过程。

tcp连的建立需要进行三次连接信息的发送、接收。)

36. 编程中,保存数据有哪几种方式?

数据:sqlite。 操作方式分为原生的sqlite3,fmdb,coredata

归档:archive。 自定义类型需要注意遵循nscoding协议

plist:就是数组或字典,写入文件后的表现形式。

nsuserdefault:本质上就是plist。

写文件

上传到服务器

37. 介绍版本控制中git与svn。

1、git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。

主要区别于svn工具的功能是 分支功能比svn强大。 (常用)

2、svn是subversion的简称,是一个开放源代码的版本控制系统,它采用了分支管理系统,

它的设计目标就是取代cvs。

38. oc中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码,方法又是什么?

创建线程的方法

[nsthread detachnewthreadselector:nil totarget:nil withobject:nil]

[self performselectorinbackground:nil withobject:nil];

[[nsthread alloc] initwithtarget:nil selector:nil object:nil];

dispatch_async(dispatch_get_global_queue(0, 0), ^{});

[[nsoperationqueue new] addoperation:nil];

主线程中执行代码的方法

[self performselectoronmainthread:nil withobject:nil waituntildone:yes]

dispatch_async(dispatch_get_main_queue(), ^{});

[[nsoperationqueue mainqueue] addoperation:nil];

延迟执行代码

sleep(2) 睡两秒钟

nstimer启动定时器

39. ios中有哪些多线程方案?

常用的有三种: nsthread nsoperationqueue gcd。

1、nsthread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,

你需要自己管理thread的生命周期,线程之间的同步。线程共享同一应用程序的部分内存空间,

它们拥有对数据相同的访问权限。你得协调多个线程对同一数据的访问,

一般做法是在访问之前加锁,这会导致一定的性能开销。

2、nsoperationqueue 以面向对象的方式封装了用户需要执行的操作,

我们只要聚焦于我们需要做的事情,而不必太操心线程的管理,同步等事情,

因为nsoperation已经为我们封装了这些事情。

nsoperation 是一个抽象基类,我们必须使用它的子类。

3、 gcd: ios4 才开始支持,它提供了一些新的特性,以及运行库来支持多核并行编程,

它的关注点更高:如何在多个cpu上提升效率。

总结:

nsthread是早期的多线程解决方案,实际上是把c语言的pthread线程管理代码封装成oc代码。

gcd是取代nsthread的多线程技术,c语法+block。功能强大。

nsoperationqueue是把gcd封装为oc语法,额外比gcd增加了几项新功能。

最大线程并发数

取消队列中的任务

暂停队列中的任务

可以调整队列中的任务执行顺序,通过优先级

线程依赖

nsoperationqueue支持kvo。 这就意味着你可以观察任务的状态属性。

但是nsoperationqueue的执行效率没有gcd高,所以一半情况下,我们使用gcd来完成多线程操作。

40. 线程与进程的区别和联系?

1.什么是进程

进程是指在系统中正在运行的一个应用程序

每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内

2.什么是线程

1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程)

线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行。

mrc:手动内存释放。遵循谁申请谁释放的原则,需要手动的处理内存计数的增加和修改。从12年开始,逐步被arc(自动内存释放)模式取代。

点语法: “self.属性 = obj” 调用属性的setter方法。”self.属性” 调用属性的getter方法区别在于是否有等号。

41.provider是指某个iphone软件的push服务器,这篇文章我将使用.net作为provider。

apns 是apple push notification service(apple push服务器)的缩写,是苹果的服务器。

上图可以分为三个阶段。

第一阶段:.net应用程序把要发送的消息、目的iphone的标识打包,发给apns。

第二阶段:apns在自身的已注册push服务的iphone列表中,查找有相应标识的iphone,并把消息发到iphone。

第三阶段:iphone把发来的消息传递给相应的应用程序,并且按照设定弹出push通知。

http://blog.csdn.net/zhuqilin0/article/details/6527113 //消息推送机制

看内存泄露时候:在搜索中搜索run 找到run static analyzer .

42.asidownloadcache 设置下载缓存

它对get请求的响应数据进行缓存(被缓存的数据必需是成功的200请求):

[asihttprequest setdefaultcache:[asidownloadcache sharedcache]];

当设置缓存策略后,所有的请求都被自动的缓存起来。

另外,如果仅仅希望某次请求使用缓存操作,也可以这样使用:

asihttprequest request = [asihttprequest requestwithurl:url];

[request setdownloadcache:[asidownloadcache sharedcache]];

缓存存储方式

你可以设置缓存的数据需要保存多长时间,asihttprequest提供了两种策略:

a,asicacheforsessiondurationcachestoragepolicy,默认策略,基于session的缓存数据存储。当下次运行或[asihttprequest clearsession]时,缓存将失效。

b,asicachepermanentlycachestoragepolicy,把缓存数据永久保存在本地,

如:

asihttprequest request = [ asihttprequest requestwithurl:url ];

[ request setcachestoragepolicy:asicachepermanentlycachestoragepolicy ];

43.http协议详解

http是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。目前在www中使用的是http/1.0的第六版,http/1.1的规范化工作正在进行之中。

http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于tcp的连接方式,http1.1版本中给出一种持续连接的机制,绝大多数的web开发,都是构建在http协议之上的web应用。

http协议的主要特点可概括如下:

1.支持客户/服务器模式。

2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有get、head、post。每种方法规定了客户与服务器联系的类型不同。由于http协议简单,使得http服务器的程序规模小,因而通信速度很快。

3.灵活:http允许传输任意类型的数据对象。正在传输的类型由content-type加以标记。

4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

5.无状态:http协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

44.url

http url (url是一种特殊类型的uri是他的子类,包含了用于查找某个资源的足够的信息)的格式如下:

http://host[":"port][abs_path]

http表示要通过http协议来定位网络资源;host表示合法的internet主机域名或者ip地址;port指定一个端口号,为空则使用缺省端口80;abs_path指定请求资源的uri;如果url中没有给出abs_path,那么当它作为请求uri时,必须以“/”的形式给出,通常这个工作自动帮我们完成。

45.tcp/udp区别联系

tcp---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个tcp连接,之后才能传输数据。tcp提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

udp---用户数据报协议,是一个简单的面向数据报的运输层协议。udp不提供可靠性,它只是把应用程序传给ip层的数据报发送出去,但是并不能保证它们能到达目的地。由于udp在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快

tcp(transmission control protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个tcp连接必须要经过三次“对话”才能建立起来,我们来看看这三次对话的简单过程:1.主机a向主机b发出连接请求数据包;2.主机b向主机a发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包;3.主机a再发出一个数据包确认主机b的要求同步:“我现在就发,你接着吧!”,这是第三次对话。三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机a才向主机b正式发送数据。

udp(user data protocol,用户数据报协议)是与tcp相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去! udp适用于一次只传送少量数据、对可靠性要求不高的应用环境。

tcp协议和udp协议的差别

是否连接面向连接面向非连接

传输可靠性可靠不可靠

应用场合传输大量数据少量数据

速度慢快

46.socket连接和http连接的区别

简单说,你浏览的网页(网址以http://开头)都是http协议传输到你的浏览器的, 而http是基于socket之上的。socket是一套完成tcp,udp协议的接口。

http协议:简单对象访问协议,对应于应用层 ,http协议是基于tcp连接的

tcp协议: 对应于传输层

ip协议: 对应于网络层

tcp/ip是传输层协议,主要解决数据如何在网络中传输;而http是应用层协议,主要解决如何包装数据。

socket是对tcp/ip协议的封装,socket本身并不是协议,而是一个调用接口(api),通过socket,我们才能使用tcp/ip协议。

http连接:http连接就是所谓的短连接,即客户端向服务器端发送一次请求,服务器端响应后连接即会断掉;

socket连接:socket连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉;但是由于各种环境因素可能会是连接断开,比如说:服务器端或客户端主机down了,网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。所以当一个socket连接中没有数据的传输,那么为了维持连接需要发送心跳消息~~具体心跳消息格式是开发者自己定义的

我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于unix,而unix/linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写io、打开、关闭),这些函数我们在后面进行介绍。我们在传输数据时,可以只使用(传输层)tcp/ip协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如http、ftp、telnet等,也可以自己定义应用层协议。web使用http协议作应用层协议,以封装http文本信息,然后使用tcp/ip做传输层协议将它发到网络上。

1)socket是一个针对tcp和udp编程的接口,你可以借助它建立tcp连接等等。而tcp和udp协议属于传输层 。

而http是个应用层的协议,它实际上也建立在tcp协议之上。

(http是轿车,提供了封装或者显示数据的具体形式;socket是发动机,提供了网络通信的能力。)

2)socket是对tcp/ip协议的封装,socket本身并不是协议,而是一个调用接口(api),通过socket,我们才能使用tcp/ip协议。socket的出现只是使得程序员更方便地使用tcp/ip协议栈而已,是对tcp/ip协议的抽象,从而形成了我们知道的一些最基本的函数接口。

47.什么是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连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客户端交互,最终确定断开)

48.利用socket建立网络连接的步骤

建立socket连接至少需要一对套接字,其中一个运行于客户端,称为clientsocket ,另一个运行于服务器端,称为serversocket 。

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

1。服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

2。客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

3。连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

1.什么是arc?(arc是为了解决什么问题诞生的?)

首先解释arc: automatic reference counting自动引用计数。

arc几个要点:

在对象被创建时 retain count +1,在对象被release时 retain count -1.当retain count 为0 时,销毁对象。

程序中加入autoreleasepool的对象会由系统自动加上autorelease方法,如果该对象引用计数为0,则销毁。

那么arc是为了解决什么问题诞生的呢?这个得追溯到mrc手动内存管理时代说起。

mrc下内存管理的缺点:

1.当我们要释放一个堆内存时,首先要确定指向这个堆空间的指针都被release了。(避免提前释放)

2.释放指针指向的堆空间,首先要确定哪些指针指向同一个堆,这些指针只能释放一次。(mrc下即谁创建,谁释放,避免重复释放)

3.模块化操作时,对象可能被多个模块创建和使用,不能确定最后由谁去释放。

4.多线程操作时,不确定哪个线程最后使用完毕

【IOS学习】面试iOS工程师的相关问题

2.请解释以下keywords的区别: assign vs weak, __block vs __weak

assign适用于基本数据类型,weak是适用于nsobject对象,并且是一个弱引用。

assign其实也可以用来修饰对象,那么我们为什么不用它呢?因为被assign修饰的对象在释放之后,指针的地址还是存在的,也就是说指针并没有被置为nil。如果在后续的内存分配中,刚好分到了这块地址,程序就会崩溃掉。

而weak修饰的对象在释放之后,指针地址会被置为nil。所以现在一般弱引用就是用weak。

首先__block是用来修饰一个变量,这个变量就可以在block中被修改(参考block实现原理)

__block:使用__block修饰的变量在block代码快中会被retain(arc下,mrc下不会retain)

__weak:使用__weak修饰的变量不会在block代码块中被retain

同时,在arc下,要避免block出现循环引用 __weak typedof(self)weakself = self;【IOS学习】面试iOS工程师的相关问题

3.__block在arc和非arc下含义一样吗?

是不一样的。

在mrc中__block variable在block中使用是不會retain的

但是arc中__block則是會retain的。

取而代之的是用__weak或是__unsafe_unretained來更精確的描述weak reference的目的

其中前者只能在ios5之後可以使用,但是比較好 (該物件release之後,此pointer會自動設成nil)

而後者是arc的環境下為了相容4.x的解決方案。

所以上面的範例中

__block myclass* temp = …; // mrc環境下使用

__weak myclass* temp = …; // arc但只支援ios5.0以上的版本

__unsafe_retained myclass* temp = …; //arc且可以相容4.x以後的版本

【IOS学习】面试iOS工程师的相关问题

4.使用nonatomic一定是线程安全的吗?()

不是的。

atomic原子操作,系统会为setter方法加锁。 具体使用 @synchronized(self){//code }

nonatomic不会为setter方法加锁。

atomic:线程安全,需要消耗大量系统资源来为属性加锁

nonatomic:非线程安全,适合内存较小的移动设备

【IOS学习】面试iOS工程师的相关问题

5.描述一个你遇到过的retain cycle例子。

block中的循环引用:一个viewcontroller

@property (nonatomic,strong)httprequesthandler * handler;

@property (nonatomic,strong)nsdata *data;

_handler = [httprequesthandler sharedmanager];

[ downloaddata:^(id responsedata){

_data = responsedata;

}];

self 拥有_handler, _handler 拥有block, block拥有self(因为使用了self的_data属性,block会copy 一份self)

解决方法:

__weak typedof(self)weakself = self

[ downloaddata:^(id responsedata){

weakself.data = responsedata;

}];

【IOS学习】面试iOS工程师的相关问题

6.+(void)load; +(void)initialize;有什么用处?

在objective-c中,runtime会自动调用每个类的两个方法。+load会在类初始加载时调用,+initialize会在第一次调用类的类方法或实例方法之前被调用。这两个方法是可选的,且只有在实现了它们时才会被调用。

共同点:两个方法都只会被调用一次。

【IOS学习】面试iOS工程师的相关问题

7.为什么其他语言里叫函数调用, objective c里则是给对象发消息(或者谈下对runtime的理解)

先来看看怎么理解发送消息的含义:

曾经觉得objc特别方便上手,面对着 cocoa 中大量 api,只知道简单的查文档和调用。还记得初学 objective-c 时把[receiver message]当成简单的方法调用,而无视了“发送消息”这句话的深刻含义。于是[receiver message]会被编译器转化为:

objc_msgsend(receiver, selector)

如果消息含有参数,则为:

objc_msgsend(receiver, selector, arg1, arg2, ...)

如果消息的接收者能够找到对应的selector,那么就相当于直接执行了接收者这个对象的特定方法;否则,消息要么被转发,或是临时向接收者动态添加这个selector对应的实现内容,要么就干脆玩完崩溃掉。

现在可以看出[receiver message]真的不是一个简简单单的方法调用。因为这只是在编译阶段确定了要向接收者发送message这条消息,而receive将要如何响应这条消息,那就要看运行时发生的情况来决定了。

objective-c 的 runtime 铸就了它动态语言的特性,这些深层次的知识虽然平时写代码用的少一些,但是却是每个 objc 程序员需要了解的。

objc runtime使得c具有了面向对象能力,在程序运行时创建,检查,修改类、对象和它们的方法。可以使用runtime的一系列方法实现。

顺便附上oc中一个类的数据结构 /usr/include/objc/runtime.h

struct objc_class {

class isa objc_isa_availability; //isa指针指向meta class,因为objc的类的本身也是一个object,为了处理这个关系,r untime就创造了meta class,当给类发送[nsobject alloc]这样消息时,实际上是把这个消息发给了class object

#if !__objc2__

class super_class objc2_unavailable; // 父类

const char *name objc2_unavailable; // 类名

long version objc2_unavailable; // 类的版本信息,默认为0

long info objc2_unavailable; // 类信息,供运行期使用的一些位标识

long instance_size objc2_unavailable; // 该类的实例变量大小

struct objc_ivar_list *ivars objc2_unavailable; // 该类的成员变量链表

struct objc_method_list **methodlists objc2_unavailable; // 方法定义的链表

struct objc_cache *cache objc2_unavailable; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。

struct objc_protocol_list *protocols objc2_unavailable; // 协议链表

#endif

} objc2_unavailable;

oc中一个类的对象实例的数据结构(/usr/include/objc/objc.h):

typedef struct objc_class *class;

/// represents an instance of a class.

struct objc_object {

class isa objc_isa_availability;

};

/// a pointer to an instance of a class.

typedef struct objc_object *id;

向object发送消息时,runtime库会根据object的isa指针找到这个实例object所属于的类,然后在类的方法列表以及父类方法列表寻找对应的方法运行。id是一个objc_object结构类型的指针,这个类型的对象能够转换成任何一种对象。

然后再来看看消息发送的函数:objc_msgsend函数

在引言中已经对objc_msgsend进行了一点介绍,看起来像是objc_msgsend返回了数据,其实objc_msgsend从不返回数据而是你的方法被调用后返回了数据。下面详细叙述下消息发送步骤:

检测这个 selector 是不是要忽略的。比如 mac os x 开发,有了垃圾回收就不理会 retain,release 这些函数了。

检测这个 target 是不是 nil 对象。objc 的特性是允许对一个 nil 对象执行任何一个方法不会 crash,因为会被忽略掉。

如果上面两个都过了,那就开始查找这个类的 imp,先从 cache 里面找,完了找得到就跳到对应的函数去执行。

如果 cache 找不到就找一下方法分发表。

如果分发表找不到就到超类的分发表去找,一直找,直到找到nsobject类为止。

如果还找不到就要开始进入动态方法解析了,后面会提到。

后面还有:

动态方法解析resolvethismethoddynamically

消息转发forwardingtargetforselector

【IOS学习】面试iOS工程师的相关问题

8.什么是method swizzling?

method swizzling 原理(方法搅拌?)

在objective-c中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。利用objective-c的动态特性,可以实现在运行时偷换selector对应的方法实现,达到给方法挂钩的目的。

每个类都有一个方法列表,存放着selector的名字和方法实现的映射关系。imp有点类似函数指针,指向具体的method实现。

【IOS学习】面试iOS工程师的相关问题

我们可以利用 method_exchangeimplementations 来交换2个方法中的imp,

我们可以利用 class_replacemethod 来修改类,

我们可以利用 method_setimplementation 来直接设置某个方法的imp,

……

归根结底,都是偷换了selector的imp,如下图所示:

【IOS学习】面试iOS工程师的相关问题
【IOS学习】面试iOS工程师的相关问题

9.uiview和calayer是啥关系?

1.uiview是ios系统中界面元素的基础,所有的界面元素都继承自它。它本身完全是由coreanimation来实现的 (mac下似乎不是这样)。它真正的绘图部分,是由一个叫calayer(core animation layer)的类来管理。 uiview本身,更像是一个calayer的管理器,访问它的跟绘图和跟坐标有关的属性,例如frame,bounds等 等,实际上内部都是在访问它所包含的calayer的相关属性。

2.uiview有个layer属性,可以返回它的主calayer实例,uiview有一个layerclass方法,返回主layer所使用的 类,uiview的子类,可以通过重载这个方法,来让uiview使用不同的calayer来显示,例如通过

- (class) layerclass {

return ([caeagllayer class]);

}

=使某个uiview的子类使用gl来进行绘制。

3.uiview的calayer类似uiview的子view树形结构,也可以向它的layer上添加子layer,来完成某些特殊的表 示。例如下面的代码

graycover = [[calayer alloc] init];

graycover.backgroundcolor = [[[uicolor blackcolor] colorwithalphacomponent:0.2] cgcolor];

[self.layer addsublayer: graycover];

会在目标view上敷上一层黑色的透明薄膜。

4.uiview的layer树形在系统内部,被系统维护着三份copy(这段理解有点吃不准)。

逻辑树,就是代码里可以操纵的,例如更改layer的属性等等就在这一份。

动画树,这是一个中间层,系统正在这一层上更改属性,进行各种渲染操作。

显示树,这棵树的内容是当前正被显示在屏幕上的内容。

这三棵树的逻辑结构都是一样的,区别只有各自的属性。

【IOS学习】面试iOS工程师的相关问题

10. 如何高性能的给uiimageview加个圆角?(不准说layer.cornerradius!)

我觉得应该是使用quartz2d直接绘制图片,得把这个看看。

步骤:

a、创建目标大小(cropwidth,cropheight)的画布。

b、使用uiimage的drawinrect方法进行绘制的时候,指定rect为(-x,-y,width,height)。

c、从画布中得到裁剪后的图像。

- (uiimage*)cropimagewithrect:(cgrect)croprect

{

cgrect drawrect = cgrectmake(-croprect.origin.x , -croprect.origin.y, self.size.width * self.scale, self.size.height * self.scale);

uigraphicsbeginimagecontext(croprect.size);

cgcontextref context = uigraphicsgetcurrentcontext();

cgcontextclearrect(context, cgrectmake(0, 0, croprect.size.width, croprect.size.height));

[self drawinrect:drawrect];

uiimage *image = uigraphicsgetimagefromcurrentimagecontext();

uigraphicsendimagecontext();

return image;

}

@end

【IOS学习】面试iOS工程师的相关问题

11. 使用drawrect有什么影响?(这个可深可浅,你至少得用过。。)

drawrect方法依赖core graphics框架来进行自定义的绘制,但这种方法主要的缺点就是它处理touch事件的方式:每次按钮被点击后,都会用setneddsdisplay进行强制重绘;而且不止一次,每次单点事件触发两次执行。这样的话从性能的角度来说,对cpu和内存来说都是欠佳的。特别是如果在我们的界面上有多个这样的uibutton实例。

【IOS学习】面试iOS工程师的相关问题

12. asihttprequest或者sdwebimage里面给uiimageview加载图片的逻辑是什么样的?

【IOS学习】面试iOS工程师的相关问题

13. 麻烦你设计个简单的图片内存缓存器(移除策略是一定要说的)

图片的内存缓存,可以考虑将图片数据保存到一个数据模型中。所以在程序运行时这个模型都存在内存中。

移除策略:释放数据模型对象。

【IOS学习】面试iOS工程师的相关问题

14. 讲讲你用instrument优化动画性能的经历吧(别问我什么是instrument)

【IOS学习】面试iOS工程师的相关问题

15. loadview是干嘛用的?

当你访问一个viewcontroller的view属性时,如果此时view的值是nil,那么,viewcontroller就会自动调用loadview这个方法。这个方法就会加载或者创建一个view对象,赋值给view属性。

loadview默认做的事情是:如果此viewcontroller存在一个对应的nib文件,那么就加载这个nib。否则,就创建一个uiview对象。

如果你用interface builder来创建界面,那么不应该重载这个方法。

如果你想自己创建view对象,那么可以重载这个方法。此时你需要自己给view属性赋值。你自定义的方法不应该调用super。如果你需要对view做一些其他的定制操作,在viewdidload里面去做。

=========================================

根据上面的文档可以知道,有两种情况:

1、如果你用了nib文件,重载这个方法就没有太大意义。因为loadview的作用就是加载nib。如果你重载了这个方法不调用super,那么nib文件就不会被加载。如果调用了super,那么view已经加载完了,你需要做的其他事情在viewdidload里面做更合适。

2、如果你没有用nib,这个方法默认就是创建一个空的view对象。如果你想自己控制view对象的创建,例如创建一个特殊尺寸的view,那么可以重载这个方法,自己创建一个uiview对象,然后指定 self.view = myview; 但这种情况也没有必要调用super,因为反正你也不需要在super方法里面创建的view对象。如果调用了super,那么就是浪费了一些资源而已

【IOS学习】面试iOS工程师的相关问题

16. viewwilllayoutsubview你总是知道的。

横竖屏切换的时候,系统会响应一些函数,其中 viewwilllayoutsubviews 和 viewdidlayoutsubviews。

//

- (void)viewwilllayoutsubviews

{

[self _shouldrotatetoorientation:(uideviceorientation)[uiapplication sharedapplication].statusbarorientation];

}

-(void)_shouldrotatetoorientation:(uideviceorientation)orientation {

if (orientation == uideviceorientationportrait ||orientation ==

uideviceorientationportraitupsidedown) {

// 竖屏

}

else {

// 横屏

}

}

通过上述一个函数就知道横竖屏切换的接口了。

注意:viewwilllayoutsubviews只能用在viewcontroller里面,在view里面没有响应。

【IOS学习】面试iOS工程师的相关问题

17. gcd里面有哪几种queue?你自己建立过串行queue吗?背后的线程模型是什么样的?

1.主队列 dispatch_main_queue(); 串行 ,更新ui

2.全局队列 dispatch_global_queue(); 并行,四个优先级:background,low,default,high

3.自定义队列 dispatch_queue_t queue ; 可以自定义是并行:dispatch_queue_concurrent或者串行dispatch_queue_serial

【IOS学习】面试iOS工程师的相关问题

18. 用过coredata或者sqlite吗?读写是分线程的吗?遇到过死锁没?咋解决的?

【IOS学习】面试iOS工程师的相关问题

19. http的post和get啥区别?(区别挺多的,麻烦多说点)

1.get请求的数据会附在url之后(就是把数据放置在http协议头中),以?分割url和传输数据,参数之间以&相连,如:login.action?name=hyddd&password=idontknow&verify=%e4%bd%a0%e5%a5%bd。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用base64,得出如:%e4%bd%a0%e5%a5%bd,其中%xx中的xx为该符号以16进制表示的ascii。

post把提交的数据则放置在是http包的包体中。

2.”get方式提交的数据最多只能是1024字节,理论上post没有限制,可传较大量的数据,iis4中最大为80kb,iis5中为100kb”??!

以上这句是我从其他文章转过来的,其实这样说是错误的,不准确的:

(1).首先是”get方式提交的数据最多只能是1024字节”,因为get是通过url提交数据,那么get可提交的数据量就跟url的长度有直接关系了。而实际上,url不存在参数上限的问题,http协议规范没有对url长度进行限制。这个限制是特定的浏览器及服务器对它的限制。ie对url长度的限制是2083字节(2k+35)。对于其他浏览器,如netscape、firefox等,理论上没有长度限制,其限制取决于操作系统的支持。

注意这是限制是整个url长度,而不仅仅是你的参数值数据长度。[见参考资料5]

(2).理论上讲,post是没有大小限制的,http协议规范也没有进行大小限制,说“post数据量存在80k/100k的大小限制”是不准确的,post数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。

3.在asp中,服务端获取get请求参数用request.querystring,获取post请求参数用request.form。在jsp中,用request.getparameter(\”xxxx\”)来获取,虽然中也有request.getquerystring()方法,但使用起来比较麻烦,比如:传一个test.jsp?name=hyddd&password=hyddd,用request.getquerystring()得到的是:name=hyddd&password=hyddd。在php中,可以用get和_post分别获取get和post中的数据,而request则可以获取get和post两种请求中的数据。值得注意的是,jsp中使用request和php中使用_request都会有隐患,这个下次再写个文章总结。

4.post的安全性要比get的安全性高。注意:这里所说的安全性和上面get提到的“安全”不是同个概念。上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的security的含义,比如:通过get提交数据,用户名和密码将明文出现在url上,因为(1)登录页面有可能被浏览器缓存,(2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用get提交数据还可能会造成cross-site request forgery攻击。

总结一下,get是向服务器发索取数据的一种请求,而post是向服务器提交数据的一种请求,在form(表单)中,method默认为”get”,实质上,get和post只是发送机制不同,并不是一个取一个发!【IOS学习】面试iOS工程师的相关问题

20. 我知道你大学毕业过后就没接触过算法数据结构了,但是请你一定告诉我什么是binary search tree? search的时间复杂度是多少?

binary search tree:二叉搜索树。

主要由四个方法:(用c语言实现或者python)

1.search:时间复杂度为o(h),h为树的高度

2.traversal:时间复杂度为o(n),n为树的总结点数。

3.insert:时间复杂度为o(h),h为树的高度。

4.delete:最坏情况下,时间复杂度为o(h)+指针的移动开销。

可以看到,二叉搜索树的dictionary operation的时间复杂度与树的高度h相关。所以需要尽可能的降低树的高度,由此引出平衡二叉树balanced binary tree。它要求左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。这样就可以将搜索树的高度尽量减小。常用算法有红黑树、avl、treap、伸展树等。