OC 语言

来源:互联网 发布:java分布式集群框架 编辑:程序博客网 时间:2024/05/18 02:47

OC 语言

共94题

 

1、#import 跟#include、@class有什么区别?#import<> 跟 #import”"又什么区别?【难度系数★】

1)#import和#include都能完整地包含某个文件的内容,#import能防止同一个文件被包含多次,防止交叉编译

2)@class仅仅是声明一个类名,并不会包含类的完整声明;@class还能解决循环依赖的问题

3)#import<> 用来包含系统自带的文件,#import “”用来包含自定义的文件

 

2、属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况用?【难度系数★★】

1)readwrite:是可读可写特性;同时生成get方法和set方法的声明和实现

2)readonly:是只读特性;只生成get方法的声明和实现

3)assign:是赋值特性;set方法的实现是直接赋值,用于基本数据类型

4)retain:表示持有特性;set方法的实现是release旧值,retain新值,用于OC对象类型

5)copy:表示赋值特性;set方法的实现是release旧值,copy新值,用于NSString、block等类型

6)nonatomic:非原子性,set方法的实现不加锁(比atomic性能高)决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic

 

3、对于语句NSString*obj = [[NSData alloc]init];,编译时和运行时obj分别是什么类型?【难度系数★】

编译时是NSString类型

运行时是NSData类型

 

4、面向对象的三大特征【难度系数★】

封装、继承、多态
1)封装:把具体的对象封装成抽象的类,隐藏内部实现,对象的属性和实现细节,仅对外公开接口,提高代码的安全性,实现模块化调用。为元素搞公有私有访问就是为了隐藏实现细节,只露一个干净的接口,让业务逻辑不被实现细节所污染,即所谓的封装
好处:1.使用者只关注接口而不必关注实现,在使用第三方框架的时候。2.代码的维护性好

2)继承:描述类与类的关系,一个类是另外一个类的子类,子类可以复用父类的方法和属性
子类继承父类就会拥有父类所有的属性和方法
如果对于方法不满意可以重写父类的方法
缺点:1.使程序变得复杂2.破坏了封装性3.降低了可维护性和可扩展性

3)多态:引用的多种形态,Polymorphism,父类指针指向子类对象,子类可以重写父类的方法。Animal子类有cat,dog,虽然都有Eat方法,但是父类不能用子类的方法,子类的方法可能各有不同。不同对象以自己的方式响应相同的消息的能力叫做多态

 

5、常见的object-c的数据类型有那些, 和C的基本数据类型有什么区别【难度系数★】

1)常用OC类型:NSString、NSArray、NSDictionary、NSData、NSNumber等创建后便是对象,而C语言的基本数据类型int,只是一定字节的内存空间,用于存放数值;

2) NSInteger是基本数据类型,并不是NSNumber的子类,当然也不是NSObject的子类。NSInteger是基本数据类型Int或者Long的别名(NSInteger的定义typedeflong NSInteger),它的区别在于,NSInteger会根据系统是32位还是64位来决定是本身是int还是Long

3)OC对象需要手动管理内存,C的基本数据类型不需要管理

 

6、id 声明的变量有什么特性?【难度系数★】

id声明的变量能指向任何OC对象

具有运行时的特点,在程序运行时才确定对象的类型

不可使用点语法

 

7、原子(atomic)跟非原子(non-atomic)属性有什么区别? 【难度系数★★】

1)atomic提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误

2)non-atomic:在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了nonatomic ,那么访问器只是简单地返回这个值。

 

8、Objective-C如何对内存管理的,说说你的看法和解决方法?【难度系数★★】

Objective-C的内存管理主要有三种方式ARC(自动引用计数)、MRC(手动内存计数)、autorelease(自动释放池)。

 

1)每个对象都有一个引用计数器,每个新对象的计数器是1,当对象的计数器减为0时,就会被销毁

2)通过retain可以让对象的计数器+1、release可以让对象的计数器-1

3)如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等.

4)@property如果用了copy或者retian,就需要对不再使用的属性做一次release操作

5)还可以通过autoreleasepool管理内存

6)如果用ARC,编译器会自动生成管理内存的代码

 

9、Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 【难度系数★★】

Object-c的类不可以多重继承;可以实现多个接口,通过实现多个接口可以完成C++的多重继承;Category是类别,一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系。

 

10、类别的作用?继承和类别在实现中有何区别? 【难度系数★★】

category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改,并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。

类别主要有3个作用:

1).将类的实现分散到多个不同文件或多个不同框架中。

2).创建对私有方法的前向引用。

3).向对象添加非正式协议。

继承可以增加,修改或者删除方法,并且可以增加属性

 

11、类别和类扩展的区别。【难度系数★】

category和extensions的不同在于 后者可以添加属性。另外后者添加的方法是必须要实现的。

extensions可以认为是一个私有的Category。

 

12、什么是block【难度系数★★】

block是对象,它封装了一段代码,这段代码可以在任何时候执行。Block 是一种具有匿名功能的内嵌函数块。Block 一般是用来表示、简化一小段的程式码,它特别适合用来建立一些同步执行的程式片段、封装一些小型的工作或是用来做为某一个工作完成时的回传呼叫(callback) 。格式如下:^(传入参数列) {行为主体};

13、使用typed声明block【难度系数★★】

typedefvoid(^didFinishBlock) (NSObject *ob);

这就声明了一个didFinishBlock类型的block,

然后便可用

@property(nonatomic,copy) didFinishBlock finishBlock;

声明一个blokc对象,注意对象属性设置为copy,接到block 参数时,便会自动复制一份。

__block是一种特殊类型,

使用该关键字声明的局部变量,可以被block所改变,并且其在原函数中的值会被改变

 

14、使用block时什么情况会发生引用循环如何解决【难度系数★★】

一个对象中强引用了block,在block中又使用了该对象,就会发射循环引用。
解决方法是将该对象使用weak或者block修饰符修饰之后再在block中使用。

idweak weakSelf = self;
或者 weak __typeof(&*self)weakSelf = self该方法可以设置宏

id__block weakSelf = self

 

15、__block和__weak的区别【难度系数★★】

1)__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。

2)__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。

3)__block对象可以在block中被重新赋值,__weak不可以。

 

16、nil,NSNULL,NULL区别【难度系数★】

nil是指向obj-c中对象的空指针,是一个对象,在o-c中ni对象调用方法不会引起crash。

Nil是指向obj-c中的类的空指针,表示的是一个空类。

NULL是指向任何类型的空指针(如c/c++中的空指针),在objective-c中是一个数值。

NSNULL用于集合操作,在集合对象中,表示一个空值的集合对象。

 

17、KVCand KVO【难度系数★】

KVC(key-value-coding)键值编码,是一种间接操作对象属性的一种机制,可以给属性设置值。通过setValue:forKey:和valueForKey,实现对属性的存取和访问。

KVO(key-value-observing)键值观察,是一种使用观察者模式来观察属性的变化以便通知注册的观察者。通过注册observing对象addObserver:forKeyPath:options:context:和观察者类必须重写方法 observeValueForKeyPath:ofObject:change:context:。常应用MVC模型中,数据库(dataModal)发生变化时,引起view改变

 

18、什么是键-,键路径是什么【难度系数★】

模型的性质是通过一个简单的键(通常是个字符串)来指定的。视图和控制器通过键来查找相应的属性值。在一个给定的实体中,同一个属性的所有值具有相同的数据类型。键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制。

键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。第一个键的

性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。键路径使您可以以独立于模型

实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相

关对象的特定属性。

 

19、类工厂方法是什么【难度系数★★】

类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中,返回被创建的对象,并

进行自动释放处理。这些方法的形式是+ (type)className...(其中 className不包括任何前缀)。

工厂方法可能不仅仅为了方便使用。它们不但可以将分配和初始化合在一起,还可以为初始化过程提供对

象的分配信息。

类工厂方法的另一个目的是使类(比如NSWorkspace)提供单件实例。虽然init...方法可以确认一

个类在每次程序运行过程只存在一个实例,但它需要首先分配一个“生的”实例,然后还必须释放该实例。

工厂方法则可以避免为可能没有用的对象盲目分配内存。

 

20、单件实例是什么【难度系数★】

Foundation和 Application Kit 框架中的一些类只允许创建单件对象,即这些类在当前进程中的唯一实例。举例来说,NSFileManager 和NSWorkspace 类在使用时都是基于进程进行单件对象的实例化。当向这些类请求实例的时候,它们会向您传递单一实例的一个引用,如果该实例还不存在,则首先进行实例的分配和初始化。单件对象充当控制中心的角色,负责指引或协调类的各种服务。如果类在概念上只有一个实例(比如

NSWorkspace),就应该产生一个单件实例,而不是多个实例;如果将来某一天可能有多个实例,您可

以使用单件实例机制,而不是工厂方法或函数。

 

21obj-c的优缺点【难度系数★】

objc优点:

  1)Cateogies

  2)Posing

  3)动态识别

  4)指标计算

  5)弹性讯息传递

  6)不是一个过度复杂的 C 衍生语言

  7)Objective-C 与 C++ 可混合编程

缺点:

  1)不支援命名空间

  2)不支持运算符重载

  3)不支持多重继承

  4)使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。

 

22、 怎样防止指针的越界使用问题? 【难度系数★】

必须让指针指向一个有效的内存地址,

防止数组越界

防止向一块内存中拷贝过多的内容

防止使用空指针

防止改变const修改的指针

防止改变指向静态存储区的内容

防止两次释放一个指针

防止使用野指针.

 

23、代理的作用? 【难度系数★】

1)代理的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。

2)另外一点,代理可以理解为java中的回调监听机制的一种类似

 

24、简述NotificationCenter、KVC、KVO、Delegate?并说明它们之间的区别?【难度系数★★★】

1)KVC:是一种间接访问对象属性的机制,而不是直接通过设置器和访问器或者点语法来访问对象属性

2)KVO:当对象的某一个属性发生变化的时候,我们得到一个相应的通知。[teacher addObserver:teacher  forKeyPath:@"name"options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld   context:nil];

3)NSNotification:的对象很简单,就是poster要提供给observer的信息包裹

4)区别:

 1.效率肯定是delegate比nsnotification高。

 2.delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要关注返回值, 也就是delegate方法的结果。比如-windowShouldClose:,需要关心返回的是yes还是no。所以delegate方法往往包含should这个很传神的词。也就是好比你做我的delegate,我会问你我想关闭窗口你愿意吗?你需要给我一个答案,我根据你的答案来决定如何做下一步。相反的,notification最大的特色就是不关心接受者的态度, 我只管把通告放出来,你接受不接受就是你的事情,同时我也不关心结果。

和delegate一样,KVO和NSNotification的作用也是类与类之间的通信,与delegate不同的是1)这两个都是负责发出通知,剩下的事情就不管了,所以没有返回值;2)delegate只是一对一,而这两个可以一对多。这两者也有各自的特点。

5)KVO的使用:

被观察者发出  addObserver:forKeyPath:options:context:  方法来添加观察者。

然后只要被观察者的keyPath值变化(注意:单纯改变其值不会调用此方法,只有通过getters和setters来改变值才会触发KVO),就会在观察者里调用方法observeValueForKeyPath:ofObject:change:context:

因此观察者需要实现方法 observeValueForKeyPath:ofObject:change:context: 来对KVO发出的通知做出响应。

这些代码都只需在观察者里进行实现,被观察者不用添加任何代码,所以谁要监听谁注册,然后对响应进行处理即可,使得观察者与被观察者完全解耦,运用很灵活很 简便;但是KVO只能检测类中的属性,并且属性名都是通过NSString来查找,编译器不会帮你检错和补全,纯手敲所以比较容易出错。

 

6)NSNotification的使用

这里的通知不是由被观察者发出,而是由NSNotificationCenter来统一发出,而不同通知通过唯一的通知标识名notificationName来区分,标识名由发送通知的类来起。

首先被观察者自己在必要的方法A里,通过方法postNotificationName:object:来发出通知notificationName这样发送通知者这边的工作就完成了,每次A被调用,就会发送一次通知notificationName。

然后谁要监听A的变化,就通过[NSNotificationCenter defaultCenter]的方法addObserver:selector:name:object:为观察者注册监听name为notificationName的通知然后每次发出name为notificationName的通知时,注册监听后的观察者就会调用其自己定义的方法notificationSelector来进行响应。

NSNotification的特点呢,就是需要被观察者先主动发出通知,然后观察者注册监听后再来进行响应,比KVO多了发送通知的一步,但是其优点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,使用也更灵活。

 

25、OC中可修改和不可以修改类型。【难度系数★】

1)可修改不可修改的集合类。这个我个人简单理解就是可动态添加修改和不可动态添加修改一样。

2)比如NSArray和NSMutableArray。前者在初始化后的内存控件就是固定不可变的,后者可以添加等,可以动态申请新的内存空间。

 

26、对于单例的理解【难度系数★】

在objective-c中要实现一个单例类,至少需要做以下四个步骤:

1).为单例对象实现一个静态实例,并初始化,然后设置成nil,

2).实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,

3).重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,

4).适当实现allocWitheZone,copyWithZone,release和autorelease。

 

27、什么时候使用NSMutableArray,什么时候使用NSArray? 【难度系数★】

当数组在程序运行时,需要不断变化的,使用NSMutableArray,当数组在初始化后,便不再改变的,使用NSArray。需要指出的是,使用NSArray只表明的是该数组在运行时不发生改变,即不能往NSAarry的数组里新增和删除元素,但不表明其数组內的元素的内容不能发生改变。NSArray是线程安全的,NSMutableArray不是线程安全的,多线程使用到NSMutableArray需要注意

 

 

 

30、用@property声明的NSString(或NSArrayNSDictionary)经常使用copy关键字为什么如果改用strong关键字可能造成什么问题【难度系数★★★】

1)因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.

2)如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.

copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。
3)当属性类型为 NSString 时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。4)所以,这时就要拷贝一份“不可变”(immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。

 

31、objc中的类方法和实例方法有什么本质区别和联系【难度系数★】

1)类方法:

类方法是属于类对象的

类方法只能通过类对象调用

类方法中的self是类对象

类方法可以调用其他的类方法

类方法中不能访问成员变量

2)实例方法:

实例方法是属于实例对象的

实例方法只能通过实例对象调用

实例方法中的self是实例对象

实例方法中可以访问成员变量

实例方法中直接调用实例方法

实例方法中也可以调用类方法(通过类名)

 

32、Objective-C堆和栈的区别?【难度系数★★★】

1)管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

2)申请大小:

栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

3)碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出

4)分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

5)分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

 

33、队列和栈有什么区别:【难度系数★★】

队列和栈是两种不同的数据容器。从”数据结构”的角度看,它们都是线性结构,即数据元素之间的关系相同。

队列是一种先进先出的数据结构,它在两端进行操作,一端进行入队列操作,一端进行出列队操作。

栈是一种先进后出的数据结构,它只能在栈顶进行操作,入栈和出栈都在栈顶操作

 

34、什么是深拷贝,浅拷贝【难度系数★★】

1)深拷贝又叫对象拷贝,系统为对象放在一个新的内存空间中,是真正意义上的复制

2)浅拷贝又叫指针拷贝,不过是给原有对象增加了一次引用计数,这时候相当于retain

3)对于系统的非容器类对象,我们可以认为,如果是对一不可变的对象复制,copy是浅拷贝,mutableCopy是深拷贝,如果是对一可变对象复制,copy和mutableCopy都是深拷贝,但是copy返回的对象是不可变的

4)对于系统的容器类NSArray,NSDictionary来说,对整个容器做copy活mutableCopy操作,不会影响容器中的元素,容器中元素都是浅拷贝,及指针拷贝

 

35、协议的基本概念和协议中方法默认为什么类型

答:OC 中的协议是一个方法列表,且多少有点相关。它的特点是可以被任何类使用(实现),但它并不是类(这里我们需要注意),自身不会实现这样方法, 而由又其他人来实现。协议经常用来实现委托对象(委托设计模式)。 如果一个类采用了一个协议,那么它必须实现协议中必须需要实现的方法,在 协议中的方法默认是必须实现(@required),添加关键字@optional,表明一旦采用该协议,这些“可选”的方法是可以选择不实现的。

 

36、@public、@protected、@private它们的含义与作用

(1) @public:

 答:对象的实例变量的作用域在任意地方都可以被访问

(2) @protected:

 答:对象的实例变量作用域在本类和子类都可以被访问

(3) @private:

 答:实例变量的作用域只能在本类(自身)中访问

(4)通过指针运算符(->)能够访问到 private 方法吗?OC 语言中还提供 了哪些方式能直接和间接的访问对象的实例变量?

答:不可以,可以通过合成存取器访问实例变量,也可自己定义 setter 和getter 方法访问实例变量,KVC(key value coding)——键值编码,间接的方式访问实例变量。

 

37、简述类目优点和缺点,如果覆盖本类或者父类的方法,会出现什么问题?

答:(1)优点:不需要通过增加子类而增加现有类的行为(方法),且类目中 的方法与原始类方法基本没有区别;通过类目可以将庞大一个类的方法进行划 分,从而便于代码的日后的维护、更新以及提高代码的阅读性。

(2)缺点:无法向类目添加实例变量,如果需要添加实例变量,只能通过 定义子类的方式;类目中的方法与原始类以及父类方法相比具有更高级别的优先 级,如果覆盖父类的方法,可能导致 super 消息的断裂。因此,最好不要覆盖原始类中的方法。

 

38、在 objective c中是否支持垃圾回收机制?

答:OC是支持垃圾回收机制的(Garbagecollection简称GC),但是apple的移动终端中,是不支持 GC 的,Mac 桌面系统开发中是支持的。

 

39、什么是 ARC技术?与 GC 是否相同?

答:ARC 是Automatic Reference Counting 的简称,我们称之为自动引用计数, 是在IOS 5之后推出的新技术,它与GC的机制是不同的。我们在编写代码时, 不需要向对象发送 release 或者 autorelease 方法,也不可以调用 delloc 方法, 编译器会在合适的位置自动给用户生成 release 消息(autorelease),ARC 的特 点是自动引用技术简化了内存管理的难度。

 

40、什么是 retain count


答:每一个对象都默认有一个retainCount 的属性,数值的多少表示现在有几 个实例正在引用它。当它为 0 时,系统会自动调用 dealloc方法,将内存回收。

 

41、以下代码有问题吗?如果有,会出现什么问题

- (void)setName:(NSString *)name {

self.name = name; }

答:引起重复调用(自己调用自己)。

 

42、定义属性时,什么时候用 assign、retain、copy 以及 它们的之间的区别

答:(1)assign:普通赋值,一般常用于基本数据类型,常见委托设计模式, 以此来防止循环引用。(我们称之为弱引用,weak)

(2)retain:保留计数,获得到了对象的所有权。引用计数在原有基础上 加1。

(3)copy:一般认为,是在内存中重新开辟了一个新的内存空间,用来

存储新的对象,和原来的对象是两个不同的地址,引用计数分别 1。但是当 copy 对象为不可变对象时,那么 copy 的作用相当于retain。因为,这样可以节约内 存空间。

 

43、解释以下关键字,static、self、super 用实例说明

答:static: 静态全局变量,持久性作用、存储区域在静态区域,它的生命周期 和应用进行绑定。程序结束时,由系统自动回收。

self:当前消息的接收者。 super:向父类发送消息。

 

44、解释 self = [super init]方法

答:容错处理,当父类初始化失败,会返回一个 nil,表示初始化失败。由于继承的关系,子类是需要拥有父类的实例和行为的,因此,我们必须先初始化父 类,然后再初始化子类。

 

45、当我们释放对象时,为什么需要调用[super dealloc] 方法?

答:(1)因为,子类是继承自父类,那么子类中有一些实例变量(对象),是继承子父类的,因此,我们需要调用父类方法,将父类所拥有的实例进行释放。

(2)先将子类所拥有的实例进行释放,然后再释放父类的。

 

46、在某个方法中 self.name = _name、name = _name 他 们有区别吗,为什么?

答:是有区别的,前者是存在内存管理的,它会对_name 对象进行保留或者拷 贝操作,而后者是普通赋值。

 

47、在 objective c中如何实现 KVO

答:(1)注册观察者(这里我们需要注意,观察者和被观察者不会被保留也不 会被释放)

-(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath

options:(NSKeyValueObservingOptions)options

context:(void*)context;

(2)接收变更通知
- (void)observeValueForKeyPath:(NSString *)keyPath

ofObject:(id)objectchange:(NSDictionary *)change context:(void *)context;

(3)移除对象的观察者身份
- (void)removeObserver:(NSObject *)observer

forKeyPath:(NSString*)keyPath;

 

48、当我们将一个对象加入自动释放池时,该对象何时被销毁

答:我们在application kit 应用程序中,自动释放池中的临时对象被销毁的时 间时,一个事件循环结束后。注意自动释放池没有被释放,而是被排空了,向池 发送了 drain 消息。

 

49、当我们调用一个静态方法时,需要对对象进行 release 吗?

答:不需要,静态方法(类方法)创建一个对象时,对象已被放入自动释放池。在池被释放时,很有可能被销毁。

 

50、循环引用是什么,如何解决这样的问题

答:对象 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 两端产生不必要的循环引用。

 

51、我们说的OC是动态运行时语言是什么意思?

答:多态。主要是将数据类型的确定由编译时,推迟到了运行时。这个问题其实浅涉及到两个概念,运行时和多态。简单来说, 运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。多态:不同对象以自己的方式响应 相同的消息的能力叫做多态。意思就是假设生物类(life)都用有一个相同的方法-eat;那人类属于生物,猪也属于生物,都 继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法。也就是不同的对象以自己的方式响应了相同的消 息(响应了eat这个选择器)。因此也可以说,运行时机制是多态的基础。

 

4、readwrite,readonly,assign,retain,copy,nonatomic、strong、weak属性的作用?并区别 strong(强引用)、 weak(弱引用)?什么情况使用copy,assign,和retain?

答:readwrite 是可读可写特性;需要生成getter方法和setter方法时
readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变
assign是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
copy 表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时。nonatomic 非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic
assign用于简单数据类型,如NSInteger,double,bool。
retain 和copy用户对象,copy用于当 a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy的方式,a和b各自有自己的内存,就可以解决这个问题。retain 会使计数器加1,也可以解 决assign的问题。另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。 在多线程环境 下,原子操作是必要的,否则有可能引起错误的结果。

 

53、ObjC中,与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?

答:与retain配对使用的方法是release,因为retain使retainCount计数加1,release使retainCount计数减1;与 retain语义相反的是release。与alloc配对使用的是release,因为:alloc是使retainCount计数加1,,使retainCount计数减1。与alloc语义相反

的是dealloc,因为:alloc是创建一个对象,,dealloc是销毁一个对象。

 

54、重写一个NSStrng类型的,retain方式声明name属性的setter和getter方法

答:{ NSString * _name; } @propertyNSString *name;----加上这些是为了避免错误

setter方法:
-(void)setName:(NSString*)name
{
{[_namerelease];
_name=[name retain];
}
}


 

55、分别描述类别(categories)和延展(extensions)是什么?以及两者的区别?继承和类别在实现中有何区别?为什么Category只能为对象添加方法,却不能添加成员变量?

类别:在没有原类.m文件的基础上,给该类添加方法; 延展:一种特殊形式的类别,主要在一个类的.m文件里声明和实现延展的作用,就是给某类添加私有方法或是私有变量。 两个的区别:延展可以添加属性并且它添加的方法是必须要实现的。延展可以认为是一个私有的类目。继承和类别在实现中的区别:类别可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修 改。并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。

Category只能为对象添加方法,却不能添加成员变量的原因:如果可以添加成员变量,添加的成员变量没有办法初始 化----这是语言规则


 

56、c和obj-c如何混用?

1)obj-c的编译器处理后缀为m的文件时,可以识别obj-c和c的代码,处理mm文件可以识别obj-c,c,c++代码,但cpp文件必须只

能用c/c++代码,而且cpp文件include的头文件中,也不能出现obj- c的代码,因为cpp只是cpp。
2) 在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是问题
3)在cpp中混用obj- c其实就是使用obj-c编写的模块是我们想要的。如果模块以类实现,那么要按照cpp class的标准写类的定 义,头文件中不能出现obj-c的东西,包括#import cocoa的。 实现文件中,即类的实现代码中可以使用obj-c的东西,可以import,只是后缀是mm。如果模块以函数实现,那么头文件要按c的格 式声明函数,实现文件中,c++函数内部可以用obj-c,但后缀还是mm或m。总结:只要cpp文件和cpp include的文件中不包含 obj-c的东西就可以用了,cpp混用obj-c的关键是使用接口,而不能直接使用实现代码,实际上cpp混用的是obj-c编译后的o文 件,这个东西其实是无差别的,所以可以用。obj-c的编译器支持cpp。


 

57、如何将产品进行多语言发布?


程序国际化;
比如:本地化应用程序名称
(1、选中工程,Info—Localizations点击“+”添加要国际化的语言。 (2、在InfoPlist.strings右边会多出一个三角形,点击展开可看到InfoPlish.strings(english)和

InfoPlish.strings(chinese)两个版本的文件; (3、在InfoPlish.strings(english)文件中加入:

CFBundleDisplayName="Program"; 其中“Program”为英文应用程序名称,同理在InfoPlish.strings(chinese)文件中加入: CFBundleDisplayName ="应用程序"; 其中“应用程序”为中文名称,注意:CFBundleDisplayName加不加双引号都行;

(4、编辑Info.plist,添加一个新的属性Application has localizeddisplay name, 设置其类型为boolean,并将其value设置为YES即可。

 

58、什么是沙箱模型?哪些操作是属于私有api范畴?

答:某个iphone工程进行文件操作有此工程对应的指定的位置,不能逾越。 iphone常见私有api的应用(比如直接发送短信,访问沙箱之外的磁盘文件).

 

59、什么是沙盒?沙盒包含哪些文件,描述每个文件的使用场景。如何获取这些文件的路径?如何获取应用程序包中文件的路径?

答:沙盒是某个iphone工程进行文件操作有此工程对应的指定的位置,不能逾越。 包括:四个文件夹:documents,tmp,Library。 手动保存的文件在documents文件里。Nsuserdefaults保存的文件在tmp文件夹里。

Documents 目录:您应该将所有de应用程序数据文件写入到这个目录下。这个目录用于存储用户数据或其它应该定期备 份的信息。AppName.app 目录:这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以 您在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。Library 目录:这个目录下有两个子目 录:Caches 和 PreferencesPreferences 目录包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是 应该使用NSUserDefaults类来取得和设置应用程序的偏好.Caches 目录用于存放应用程序专用的支持文件,保存应用程 序再次启动过程中需要的信息。tmp 目录:这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。

获取这些目录路径的方法:
1,获取家目录路径的函数:
NSString *homeDir = NSHomeDirectory();
2,获取Documents目录路径的方法:
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *docDir = [paths objectAtIndex:0];
3,获取Caches目录路径的方法:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES);
NSString *cachesDir = [paths objectAtIndex:0];
4,获取tmp目录路径的方法:
NSString *tmpDir =NSTemporaryDirectory();
5,获取应用程序程序包中资源文件路径的方法:
例如获取程序包中一个图片资源(apple.png)路径的方法:
NSString *imagePath =[[NSBundle mainBundle] pathForResource:@”apple” ofType:@”png”]; UIImage*appleImage = [[UIImage alloc] initWithContentsOfFile:imagePath]; 代码中的mainBundle类方法用于返回一个代表应用程序包的对象。


英文题目,一定过一遍,有的公司为了考察应聘者的英语水平,故意出英文笔试题

 

60、Difference between shallow copy and deep copy?
浅复制和深复制的区别?


答案:浅层复制:只复制指向对象的指针,而不复制引用对象本身。
深层复制:复制引用对象本身。
意思就是说我有个A对象,复制一份后得到A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象本身资源
还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了
两份独立对象本身。
用网上一哥们通俗的话将就是:
浅复制好比你和你的影子,你完蛋,你的影子也完蛋
深复制好比你和你的克隆人,你完蛋,你的克隆人还活着。

 

61、What is advantage of categories? What is difference betweenimplementing a category and inheritance?
类别的作用?继承和类别在实现中有何区别?

答案:category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。
并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
类别主要有3个作用:
(1)将类的实现分散到多个不同文件或多个不同框架中。
(2)创建对私有方法的前向引用。
(3)向对象添加非正式协议。
 继承可以增加,修改或者删除方法,并且可以增加属性。

 

62、Difference between categories and extensions?
类别和类扩展的区别。

答案:category和extensions的不同在于后者可以添加属性。另外后者添加的方法是必须要实现的。
extensions可以认为是一个私有的Category。

 

63、Difference between protocol in objective c and interfaces in java?
obc中的协议和java中的接口概念有何不同?


答案:OC中的代理有2层含义,官方定义为 formal和informal protocol。前者和Java接口一样。
informal protocol中的方法属于设计模式考虑范畴,不是必须实现的,但是如果有实现,就会改变类的属性。
其实关于正式协议,类别和非正式协议我很早前学习的时候大致看过,也写在了学习教程里
“非正式协议概念其实就是类别的另一种表达方式“这里有一些你可能希望实现的方法,你可以使用他们更好的完成工作”。
这个意思是,这些是可选的。比如我门要一个更好的方法,我们就会申明一个这样的类别去实现。然后你在后期可以直接使用这些更好的方法。
这么看,总觉得类别这玩意儿有点像协议的可选协议。"
现在来看,其实protocal已经开始对两者都统一和规范起来操作,因为资料中说“非正式协议使用interface修饰“,
现在我们看到协议中两个修饰词:“必须实现(@requied)”和“可选实现(@optional)”。

 

64、What are KVO and KVC?


答案:kvc:键 - 值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制。
很多情况下可以简化程序代码。apple文档其实给了一个很好的例子。
kvo:键值观察机制,他提供了观察某一属性变化的方法,极大的简化了代码。
具体用看到嗯哼用到过的一个地方是对于按钮点击变化状态的的监控。
比如我自定义的一个button
[cpp] 
[selfaddObserver:self forKeyPath:@"highlighted" options:0context:nil]; 
 
 
#pragma mark KVO 
 
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)objectchange:(NSDictionary *)change context:(void*)context 
{ 
    if ([keyPathisEqualToString:@"highlighted"] ) { 
       [self setNeedsDisplay]; 
    } 
} 

对于系统是根据keypath去取的到相应的值发生改变,理论上来说是和kvc机制的道理是一样的。
对于kvc机制如何通过key寻找到value:
“当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过几种不同的方式解析这个调用。首先查找对象是否带有 someKey 这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到,程序会继续试图调用 -(id)valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。
 
(cocoachina.com注:Key-Value Coding查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以及_getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。)
 
设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。这样做有很多好处,下面的两个例子说明了这样做的好处。“
来至cocoa,这个说法应该挺有道理。
因为我们知道button却是存在一个highlighted实例变量.因此为何上面我们只是add一个相关的keypath就行了,
可以按照kvc查找的逻辑理解,就说的过去了。

 

65、What is purpose of delegates?
代理的作用?

答案:代理的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。
另外一点,代理可以理解为java中的回调监听机制的一种类似。

 

66、What are mutable and immutable types in Objective C?
obc中可修改和不可以修改类型。


答案:可修改不可修改的集合类。这个我个人简单理解就是可动态添加修改和不可动态添加修改一样。
比如NSArray和NSMutableArray。前者在初始化后的内存控件就是固定不可变的,后者可以添加等,可以动态申请新的内存空间。

 

67、When we call objective c is runtime language what does it mean?
我们说的oc是动态运行时语言是什么意思?


答案:多态。 主要是将数据类型的确定由编译时,推迟到了运行时。
这个问题其实浅涉及到两个概念,运行时和多态。
简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
多态:不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类(life)都用有一个相同的方法-eat;
那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法。
也就是不同的对象以自己的方式响应了相同的消息(响应了eat这个选择器)。
因此也可以说,运行时机制是多态的基础?

 

68、what is difference between NSNotification and protocol?
通知和协议的不同之处?


答案:协议有控制链(has-a)的关系,通知没有。
首先我一开始也不太明白,什么叫控制链(专业术语了~)。但是简单分析下通知和代理的行为模式,我们大致可以有自己的理解
简单来说,通知的话,它可以一对多,一条消息可以发送给多个消息接受者。
代理按我们的理解,到不是直接说不能一对多,比如我们知道的明星经济代理人,很多时候一个经济人负责好几个明星的事务。
只是对于不同明星间,代理的事物对象都是不一样的,一一对应,不可能说明天要处理A明星要一个发布会,代理人发出处理发布会的消息后,别称B的
发布会了。但是通知就不一样,他只关心发出通知,而不关心多少接收到感兴趣要处理。
因此控制链(has-a从英语单词大致可以看出,单一拥有和可控制的对应关系。

 

69、Polymorphism?
关于多态性


答案:多态,子类指针可以赋值给父类。
这个题目其实可以出到一切面向对象语言中,
因此关于多态,继承和封装基本最好都有个自我意识的理解,也并非一定要把书上资料上写的能背出来。
最重要的是转化成自我理解。

 

70、Singleton?
对于单例的理解


答案:11,12题目其实出的有点泛泛的感觉了,可能说是编程语言需要或是必备的基础。
基本能用熟悉的语言写出一个单例,以及可以运用到的场景或是你编程中碰到过运用的此种模式的框架类等。
进一步点,考虑下如何在多线程访问单例时的安全性。

 

71、frame和bounds有什么不同?【难度系数★】

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

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

 

72、什么是延迟加载?【难度系数★】

懒汉模式,只在用到的时候才去初始化。也可以理解成延时加载。

最好也最简单的一个列子就是tableView中图片的加载显示了。

一个延时载,避免内存过高,一个异步加载,避免线程堵塞

 

73、iOS的系统架构【难度系数★★】

iOS的系统架构分为( 核心操作系统层 theCore OS layer )、( 核心服务层theCore Serviceslayer )、( 媒体层 theMedia layer )和( Cocoa 界面服务层 the Cocoa Touch layer )四个层次

 

74、xib,storyboard,手动书写代码【难度系数★★★】

1)xib(interface buider),方便对界面进行编辑。可以在窗口上面直接添加各种视图,优点:直接看到界面的效果,操作简单。缺点:不方便对视图进行动态控制,不灵活。

手动编写代码,继承(主要是UIView,UIViewController),优点:可以对视图进行定制,灵活控制方便。缺点:不能马上看到效果,复杂。

2)storyboard(故事板在ios6加入)。优点:可以看到界面效果,能同时进行多个界面的交互,高效快速。缺点:不能进行进行界面的定制,却笑灵活性。

3)xib和storyboard主要用于界面中的元素位置固定和清楚里面有哪些元素。但是如果需要动态变化界面还是手动编写代码比较好。一般还是各种方式混合使用。

loadView,viewDidLoad,ViewDidUnload,viewWillAppear,viewDidAppear,viewwilldDisappear,viewDidDisappear

当view的nib文件为nil时,手动创建界面时调用loadView,当view的nib文件存在时,会在viewDidLoad中实现。但是当你的程序运行期间内存不足时,视图控制器收到didReceiveMemoryWarning时,系统会检查当前的视图控制器的view是否还在使用,如果不在,这个view会被release,再次调用loadView来创建一个新的View。viewDidLoad ,不论是从xib中加载视图,还是从loadview生成视图,都会被调用。但是如果改view在栈中下一次显示是不会被调用。ViewWillAppear,ViewDidAppear会在view每次即将可见和完全显示时都会调用。我们会在ViewWillAppear里面进行一些view显示的准备工作,ViewDidDi sappear 和ViewWillDisAppear时会在view每次消失时都会调用。当系统收到didReceiveMemoryWarning通知时显示内存不足时,会调用ViewDidUnload来清理View中的数据和release后置为nil

 

75、tableview的优化【难度系数★★★】

优化:

1)正确的复用cell。

2) 减少在返回每个cell里面的处理逻辑和处理时间。尽量将数据进行缓存和复用。

3)尽量减少处理加载和计算的时间,不阻塞UI线程。

4)尽量使用绘制每个cell。

5)设置每个cell的opaque属性。

6)尽量返回每行固定的height。

7)在每个cell减少图形效果。

8)分段加载数据。

 

76、CAlayer介绍【难度系数★★】

一个UIView包含CALayer树,CALayer是一个数据模型。包含了一些用来显示的对象,在UIView的子类中都可以找到层这个组件,层是位于固定的画布上的一个子片,可以被覆盖。层是彼此堆叠在一起的最终产生一个界面。除此之层可以包含多个层,通过层可以操作位于此层上面的其他内容,例如旋转,动画,翻页等。

 

77、UIScrollView的contentSize、contentOffSet和contentInset属性的区别【难度系数★★】

contentSize表示UIScrollView滚动区域的大小。UIScrollView的frame属性在设置好了以后不会随内容的变化而变化。

contentOffSet表示是UIScrollView当前显示区域顶点相对于frame顶点的偏移量,一般用来设置UIScrollView显示的位置。

contentInset表示是scrollview的contentView的顶点相对于scrollview的位置,假设你的contentInset = (0 ,100),那么你的contentView就是从scrollview的(0 ,100)开始显示。一般都是(0,0)表示从scrollView的开始显示

 

78、UIView与CLayer有什么区别?【难度系数★★】

1).UIView 是 iOS 系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由 CoreAnimation 来实现的。它真正的绘图部分,是由一个 CALayer 类来管理。 UIView 本身更像是一个 CALayer 的管理器,访问它的跟绘图和跟坐标有关的属性。

2).UIView 有个重要属性 layer,可以返回它的主 CALayer 实例。

3).UIView 的 CALayer 类似 UIView 的子 View 树形结构,也可以向它的 layer 上添加子layer ,来完成某些特殊的表示。即 CALayer 层是可以嵌套的。

4).UIView 的 layer 树形在系统内部,被维护着三份 copy 。分别是逻辑树,这里是代码可以操纵的;动画树,是一个中间层,系统就在这一层上更改属性,进行各种渲染操作;显示树,其内容就是当前正被显示在屏幕上得内容。

5).动画的运作:对UIView 的 subLayer (非主 Layer )属性进行更改,系统将自动进行动画生成,动画持续时间的缺省值似乎是 0.5 秒。

6).坐标系统:CALayer 的坐标系统比 UIView 多了一个anchorPoint 属性,使用CGPoint 结构表示,值域是 0~1 ,是个比例值。这个点是各种图形变换的坐标原点,同时会更改 layer 的 position 的位置,它的缺省值是 {0.5,0.5} ,即在 layer 的中央

7).渲染:当更新层,改变不能立即显示在屏幕上。当所有的层都准备好时,可以调用setNeedsDisplay 方法来重绘显示。

8).变换:要在一个层中添加一个 3D 或仿射变换,可以分别设置层的 transform 或affineTransform 属性。

9).变形: QuartzCore 的渲染能力,使二维图像可以被自由操纵,就好像是三维的。图像可以在一个三维坐标系中以任意角度被旋转,缩放和倾斜。 CATransform3D 的一套方法提供了一些魔术般的变换效果

 

79、iPhone OS主要提供了几种播放音频的方法?【难度系数★】

SystemSound Services

AVAudioPlayer 类

Audio Queue Services

OpenAL

 

80、tableView 的重用机制?【难度系数★★★】

UITableView 通过重用单元格来达到节省内存的目的: 通过为每个单元格指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,以及当单元格滚出屏幕时,允许恢复单元格以便重用.对于不同种类的单元格使用不同的ID,对于简单的表格,一个标识符就够了.

 

81、loadView干嘛用的?【难度系数★】

1)loadView在View为nil时调用,早于ViewDidLoad,通常用于代码实现控件,收到内存警告时会再次调用。loadView默认做的事情是:如果此VIewcontroller存在一个对应的nib文件,那么就加载这个nib。否则,就创建一个UIView对象。如果你用Interface BVuilder来创建界面,那么不应该重载这个方法。

如果你想自己创建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,那么就是浪费了一些资源而已

 

82、如何高性能的给 UIImageView 加个圆角? (不准说 layer.cornerRadius!)【难度系数★★★】

一般情况下给 UIImageView 或者说 UIKit 的控件添加圆角都是改变 clipsToBounds 和 layer.cornerRadius, 这样大约两行代码就可以解决这个问题.但是, 这样使用这样的方法会强制
Core Animation 提前渲染屏幕的离屏绘制, 而离屏绘制就会为性能带来负面影响.

我们也可以使用另一种比较复杂的方式来为图片添加圆角,这里就用到了贝塞尔曲线.

UIImageView * imageView= [[UIImageViewalloc] initWithFrame:CGRectMake(0, 0, 100, 100)];  

imageView.center = CGPointMake(200,300);  

UIImage *anotherImage = [UIImageimageNamed:@"image"];  UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO,1.0);  

[[UIBezierPathbezierPathWithRoundedRect:imageView.bounds                        cornerRadius:50]addClip];

[anotherImage drawInRect:imageView.bounds];

imageView.image =UIGraphicsGetImageFromCurrentImageContext();  UIGraphicsEndImageContext();  

[self.view addSubview:imageView];

在这里使用了贝塞尔曲线"切割"个这个图片, 给 UIImageView 添加了的圆角.

 

83、使用drawRect有什么影响?(这个可深可浅,你至少得用过。。)【难度系数★★★】

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

2)这个方法的主要作用是根据传入的 rect来绘制图像 参见文档. 这个方法的默认实现没有做任何事情, 我们可以在这个方法中使用 Core Graphics 和 UIKit 来绘制视图的内容.

3)这个方法的调用机制也是非常特别.当你调用 setNeedsDisplay 方法时, UIKit 将会把当前图层标记为 dirty, 但还是会显示原来的内容, 直到下一次的视图渲染周期, 才会为标记为 dirty 的图层重新建立 Core Graphics 上下文, 然后将内存中的数据恢复出来, 再使用 CGContextRef 进行绘制.

 

84、IBOutlet连出来的视图属性为什么可以被设置成weak?【难度系数★】

因为既然有外链那么视图在xib或者storyboard中肯定存在,视图已经对它有一个强引用了。

不过这个回答漏了个重要知识,使用storyboard(xib不行)创建的vc,会有一个叫_topLevelObjectsToKeepAliveFromStoryboard的私有数组强引用所有top level的对象,所以这时即便outlet声明成weak也没关系

 

85、什么叫回调,什么叫回调函数用block怎么实现回掉调【难度系数★★】

比如你调用一个方法下载图片,下载完后要返回调用的地方刷新UI,这个返回的过程就叫回调,代理,block,通知都可以实现回调,目前最简便的回调方式是block,block要首先用typedef声明一个block类型,然后调用图片下载的时候把block回调代码传入方法,然后图片下载完后block自动回调,需要注意防止循环引用,造成内存泄漏

防止循环引用的方法是:当block中调用self时需要先用一个中间变量赋值为self,声明这个中间变量为__weak,然后block回调里使用这个中间变量

 

86、如何在scrollView中加100个tableView(假设横向加多个tableVIew)【难度系数★★★】

(1)自定义一个UIScrollView的子类FSReuseScrollView

(2)根据scrollView中tableView的宽度,contentOffset来判断当前屏幕显示的一个tableView(tableVIew宽度跟屏幕宽度相同时),或多个tableView,放到FSReuseScrollView的属性visiableTableViews数组中,滑动时将移出屏幕的tableView放到canReuseTableViews中,然后将要显示到屏幕的tableVIew从canReuseTableViews中取出来,显示到界面上,修改里边显示的数据。

(3)我这种需求一般使用系统的collectionView横向滚动来实现,系统实现的重用

(4)我也很喜欢写第三方开源代码,比如自定义的tabbar,navBar都在github上有

 

87、viewController的loadView,viewDidLoad,viewDidUnload,didReceiveMemoryWarning分别是什么时候调用的【难度系数★★★】

在自定义viewController的时候这几个函数里面应该做什么工作

(1)loadView在加载self.view时会调用,viewDidLoad当界面显示的时候会调用,viewDidUnload在self.view = nil的时候会调用

(2)在viewDidLoad中写用纯代码方式创建的各个view,以及self.view创建出来后要执行的操作

(3) viewDidUnload里执行view 的release操作,如果是代码创建的要在这里release,IBOutlet创建的不需要release,会自动release。

(4)当应用程序接收到系统的内容警告时,就有可能调用控制器的didRece…Warning方法

 

 

88、描述一下UITableView的重用机制【难度系数★★★】

(1)tableView重用机制是苹果为了实现大量数据显示而采用的一种节省内存的机制

(2)为什么要重用呢?假设一个tableVIew有几百个cell,如果所有cell都要占用内存的话消耗是很大的,很容易出现memoryWarning,甚至crash

(3)重用机制的原理:cell创建的时候会标示一个identifier,tableVIew显示后只会创建一个屏幕大小的cell个数放到visiableCells中,当你上滑屏幕的时候,上边的cell会依次进入可重用队列reusableTableCells,下方要显示的cell从可重用队列reusableTableCells中根据identifier取出重用的cell,修改它显示的数据,来实现可显示大量数据的目的。

 

89、tabbar和toolbar分别是什么?两者之间有何共同点和不同点。【难度系数★】

tabbar是显示不同页面用的控件,toolbar一般用于不跳转页面,是在一个页面显示不同内容或者是做不同操作

 

89、drawRect和layoutSubviews的区别【难度系数★★★】

1)当调用setNeedsDisplay时会自动调用drawRect方法,这样就可以拿到currentContext就可以画画了,而setNeedsLayout会自动调用layoutSubViews,就可以处理子视图的一些数据。

layoutSubViews方便数据计算,drawRect方便视图重绘

2)layoutSubviews在以下情况下会被调用:

addSubview,

frame发生改变,

滚动一个scrollView

旋转screen

改变子view的frame,

直接调用setLayoutSubviews

直接调用setNeedsLayout

3)drawRect会在以下情况被调用:

在viewDidLoad走完后会调用,

调用sizeToFit后会被调用,

设置contentMode为UIViewContentModeRedraw,那么每次frame修改会自动调用drawRect:

直接调用setNeedsDisplay

 

91、frame,bounds,center,alpha,opaque,hidden【难度系数★★】

这些都是view的一些基本属性。

frame是描述该view在其父视图中的一块区域。其坐标系是在其父视图中的坐标。我们在进行view的初始化时会经常使用到frame。

bounds也是描述该view的大小,是其在自身的坐标系中的位置大小。center是描述其在父视图的中心位置坐标。我们在进行view的位置改变而不改变view的大小的时,会使用center。

alpha是用来描述改view的透明度从0到1,0表示的是透明,1表示不透明。alpha支持动画(animation),alpha = 0 与 hidden =YES 效果一样都是看不到view,但是后者相比开销大。在alpha等于0时view接受touch事件,但是hidden则不接受。并且hidden和apaque不支持动画。alpha并不影响镶嵌在其内部view行为,而hidden会影响。当把view设置为透明背景时,一般把opaque设置为NO,可以减少开销,优化内存.opaque影响图形绘制系统。设置为YES,会优化view的绘制

 

92、宽度固定的情况下,如何计算UILabel要显式的内容所需要的高度【难度系数★★】

文本内容调用boundingRectWithSize方法,传入参数size,width固定,高度填写MAXFLOAT,传入font属性,返回一个size,size中的高度即为适应后的高度。

 

93、controllerA调用controllerB后,如何在B中对A进行一些代码操作,请用Block和delegate分别实现。【难度系数★★★】

Delegate:

(1)定义B的代理协议,及代理方法接口。CallBackDelegate,doSomething

(2)在A的viewDidLoad中写B.delegate = self;

(3)A中实现B的代理协议中的方法doSomething

(4)在B中调用让delegate调用它的代理方法执行一些代码操作。

 

Block:

(1)用typedef定义一个block

(2)在A中调用B的过程中将block回调要执行的代码写成代码块传入B中,在B中需要调用A代码块的地方写block回调。

 

94、tableview的代理和数据源所必须实现的方法。【难度系数★】

    代理方法:返回tableview每行高度、监听tableview每行的选中

    数据源方法:返回tableview数据的组数和行数、每行显示什么数据

 

0 0