iOS面试题,希望给面试的同学一点帮助。

                                  iOS基础面试题

1.用objective-c写一个插入法排序

 

2.写一个NSString类的实现

+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;

+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding{

       NSString *obj;

       obj = [self allocWithZone: NSDefaultMallocZone()];

       obj = [obj initWIthCString: nullTerminatedCString encoding: encoding];

       return AUTORELEASE(obj);

}

3.写一个委托的interface

#import <Foundation/Foundation.h>

@protocol MyDelegate;//声明

@interface MyClass : NSObject

{

    id <MyDelegate> delegate;

}

@end

@protocol MyDelegate//委托方法

- (void)didJobs:(NSArray *)args;

@end

4.obj-c有私有方法么?私有变量呢

在Objective-C有私有方法,有静态方法和实例方法。也有私有变量。

@interface MyClass (Private)

- (void)testPrivate;

@end

objective-c - 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法

@interface Controller : NSObject { NSString *something; }

+ (void)thisIsAStaticMethod;

- (void)thisIsAnInstanceMethod;

@end

@interface Controller (private) -

(void)thisIsAPrivateMethod;

@end

@private可以用来修饰私有变量

在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的

 

5.#import跟#include的区别?

预编译指令Objective-C:#import   C,C++:#include   #import由gcc编译器支持

在 Objective-C 中,#import 被当成 #include 指令的改良版本来使用。除此之外,#import 确定一个文件只能被导入一次,这使你在递归包含中不会出现问题。

使用哪一个还是由你来决定。一般来说,在导入 Objective-C 头文件的时候使用 #import,包含 C 头文件时使用 #include。比如:

#import <foundation /Foundation.h>

#include <asl .h>

#include <mach /mach.h>

#import比起#include的好处就是不会引起交叉编译

扩展:@class是用来做类引用的

@class就是告诉编译器有这么一个类,至于类的定义是啥不知道

@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import

举个例子说明:

在ClassA.h中

#import ClassB.h 相当于#include整个.h头文件。如果有很多.m文件#import ClassA.h,那么编译的时候这些文件也会#import ClassB.h增加了没必要的#import,浪费编译时间。在大型软件中,减少.h文件中的include是非常重要的。

如果只是@class ClassB 那就没有include ClassB.h。仅需要在需要用到ClassB的ClassA.m文件中 #import ClassB.h

@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import
而#import比起#include的好处就是不会引起重复包含

6.请写出你对MVC模式的理解

答:MVC是一种设计模式,考虑三种对象:模型对象、视图对象和控制器对象。模型对象负责应用程序的数据和定义操作数据的逻辑;视图对象知道如何显示应用程序的模型数据;控制器对象是M与V之间的协调者。实现了功能模块和显示模块的分离,同时它还提高了应用系统的可维护性、可扩展性、可移植性和组件的可复用性。

7.什么是键-值,键路径是什么

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

键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。第一个键的性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。键路径使您可以以独立于模型实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性。

许多编程技术都基于间接机制,不是OC特性,而是Cocoa提供的一种特性,KVC是一种间接更改对象状态的方式,其实现方法是使用字符串描述要更改的对象状态部分。

除了通过键设置值外,键值编码还支持指定键路径,像文件系统路径一样,可以遵循一系列关系来指定该路径。

For example, the key path address.streetwould get the value of the address property from the receiving object, and then determine the street property relative to the address object.

8.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.

9.什么是目标-动作机制

目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参 见"插座变量"部分)
的形式保有其动作消息的目标。动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现 的方法。程序需要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制

10.请列举你熟悉cocoa touch框架(至少三个)

答:Core Animation 通过 Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。 Core Audio Core Audio 是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。 Core Data 提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。

11.请写出obj-c的内存管理代码

12.自动释放池是什么,如何工作

当您向一个对象发送一个autorelease 消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当 程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。

1.  ojc-c 是 通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
2. NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不用你管的.
3. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一.

 

13.obj-c的优缺点

objc优点: 1) Cateogies 2) Posing 3) 动态识别 4) 指标计算 5)弹性讯息传递
  6) 不是一个过度复杂的 C 衍生语言 7) Objective-C 与 C++ 可混合编程
缺点:  1) 不支援命名空间 2)  不支持运算符重载 3) 不支持多重继承  4) 使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。

14.readwrite,readonly,assign,retain,copy,nonatomic属性的作用

@property是一个属性访问声明,扩号内支持以下几个属性:
1,getter=getterName,setter=setterName,设置setter与getter的方法名
2,readwrite,readonly,设置可供访问级别
2,assign,setter方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题
3,retain,setter方法对参数进行release旧值再retain新值,所有实现都是这个顺序(CC上有相关资料)
4,copy,setter方法进行Copy操作,与retain处理流程一样,先旧值release,再Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。
5,nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级。

15.在一个对象的方法里面:
self.name = “object”; 和 name =”object”; 有什么不同吗? 

16.ViewController 的 loadView, viewDidLoad, viewDidUnload 分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?
18.ViewController 的 didReceiveMemoryWarning

2. 以下为Windows NT下的32位C++程序,请计算sizeof的值

void Func ( char str[100] )  
{  
  sizeof( str ) = ?  
}  
void *p = malloc( 100 ); 
sizeof ( p ) = ?

这题 很常见了,Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等 操作,可以被修改。Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof ( p ) 都为4。


3.还 是考指针,不过我对cocoa的代码还是不太熟悉

大概是这样的

- (void)*getNSString(const NSString * inputString)

{

     inputString = @"This is a main test\n";

     return ;

}

-main(void)

{

NSString *a=@"Main";

 NSString *aString = [NSString stringWithString:@"%@",getNSString(a)];

 NSLog(@"%@\n", aString);

}

最后问输出的字符串:NULL,output在 函数返回后,内存已经被释放。

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

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL  
我在这想看到几件事 情:  
?; #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)  
?; 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
  
?; 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。  
?; 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要

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


#define MIN(A,B) ((A) <= (B) ? (A) : (B))  
这
个

测试是为下面的目的而设的:  
?; 
标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为

标准C的一部分,宏是方便产生嵌入代码的唯一方
法,
对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。  
?;

 
三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比 if-then-else

更优化的代码,了解这个用法是很重要的。
 

?; 懂得在宏中小心地把参数用括号括起来  
?;

我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?  
  
 least = MIN(*p++, b); 

结果是:
((*p++) <= (b) ? (*p++) : (*p++))
这个表达式会产生副作用,指针p会作三次++自增操作。

5.写一个委托的 interface

@protocol MyDelegate;

@interface MyClass: NSObject

{

    id <MyDelegate> delegate;

}

// 委托方法

@protocol MyDelegate

- (void)didJobs:(NSArray *)args;

@end

6. 写一个NSString类的实现

+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;

+ (id) stringWithCString: (const char*)nullTerminatedCString 
            encoding: (NSStringEncoding)encoding
{
  NSString  *obj;

  obj = [self allocWithZone: NSDefaultMallocZone()];
  obj = [obj initWithCString: nullTerminatedCString encoding: encoding];
  return AUTORELEASE(obj);
}

7.obj-c有多重继承么?不是的话有什么替代方法?


cocoa 中所有的类都是NSObject 的子类 

多继承在这里是用protocol 委托代理 来实现的 
你不用去考虑繁琐的多继承 ,虚基类的概念.
ood的多态特性  在 obj-c 中通过委托来实现. 

8.obj- c有私有方法么?私有变量呢

 objective-c - 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法

@interface Controller : NSObject { NSString *something; }

+ (void)thisIsAStaticMethod;

- (void)thisIsAnInstanceMethod;

@end

@interface Controller (private) -

(void)thisIsAPrivateMethod;

@end

@private可以用来修饰私有变 量

在Objective‐C中,所有实例变量默认都是私 有的,所有实例方法默认都 是公有的

9.关键字const有什么含 意?修饰类呢?static的作 用,用于类呢?还有extern c的作用

const 意味着"只读",下面的声明都是什么意思?  
const int a;  
int const a;  
const int *a;  
int * const a;  
int const * a const; 

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指 针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改 的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

结论:

?; 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果
你曾花很多 时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清
理的。)  
?; 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。  
?; 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。  
 

(1)欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初
始化,因为以后就没有机会再去改变它了; 
(2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指
定为 const; 
(3)在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值; 
(4)对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量; 
(5)对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左值”。

关键字volatile有什么含意?并给出三个不同的例子。

一个定义为 volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到
这个变量时必须 每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:  

?; 并行设备的硬件寄存器(如:状态寄存器)  
?; 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)  
?; 多线程应用中被几个任务共享的变量 

?; 一个参数既可以是const还可以是volatile吗?解释为什么。  
?; 一个指针可以是volatile 吗?解释为什么。  

下 面是答案:  
?; 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。  
?; 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。  

static 关键字的作用:

(1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值; 
(2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问; 
(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明
它的模块内; 
(4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝; 
(5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。 

extern "C" 的作用

(1)被 extern "C"限定的函数或变量是 extern 类型的;

       extern 是 C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,
其声明的函数和变量可以在本模块或 其它模块中使用。

(2)被 extern "C"修饰的变量和函数是按照 C 语言方式编译和连接的; 

extern "C"的惯用法 

(1)在 C++中引用 C 语言中的函数和变量,在包含 C 语言头文件(假设为 cExample.h)时,需进
行下列处理: 
extern "C"  
{  
#include "cExample.h"  
}  
而在 C 语言的头文件中,对其外部函数只能指定为 extern 类型,C 语言中不支持 extern "C"声明,
在.c 文件中包含了 extern "C"时会出现编译语法错误。

(2)在 C 中引用 C++语言中的函数和变量时,C++的头文件需添加 extern "C",但是在 C 语言中不
能直接引用声明了 extern "C"的该头文件,应该仅将 C 文件中将 C++中定义的 extern "C"函数声明为
extern 类型。

10.为什么标准头文件都有类似以下的结构?  
   #ifndef __INCvxWorksh  
   #define __INCvxWorksh  
   #ifdef __cplusplus  
   extern "C" {  
   #endif  
   /*...*/  
   #ifdef __cplusplus  
   }  
   #endif  
   #endif /* __INCvxWorksh */ 

显然,头文件中的编译宏 “#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用
是防止该头文件被重复引用。

11.#import 跟#include的区别,@class呢?

 @class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文 件中还是需要使用#import

而#import比 起#include的好处就是不会引起交叉编译

12.MVC 模式的理解

MVC设计模式考虑三种对 象:模型对象、视图对象、和控制器对象。模型对象代表 特别的知识和专业技能,它们负责保有应用程序的数据和定义操作数据的逻辑。视图对象知道如何显示应用程序的模型数据,而且可能允许用户对其进行编辑。控制 器对象是应用程序的视图对象和模型对象之间的协调者。

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

进程和线程都是由操作系统所体会的程序运行的基本 单元,系统利用该基本单元实现系统对应用的并发性。

程和线程的主要差别在于它们是不同的操作系统资源 管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变 量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一 些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

14.列举几种进程的同步机制,并比较其优缺点。

答案:  原子操作 信号量机制    自旋锁    管程,会合,分布式系统 
进程之间通信的途径

答案:共享存储系统消息传递系统管道:以文件系统为基础 
进 程死锁的原因

答案:资源竞争及进程推 进顺序非法 
死锁的4个必要条 件

答案:互斥、请求保持、不可剥夺、 环路 
死锁的处理

答案:鸵鸟策略、预防策略、避免策略、检测与解除死锁

15.堆和栈 的区别

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

申请大 小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统 预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示 overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地 址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

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

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

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

16.什么是键-值,键路径是什么

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

键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性 质序列。第一个键的
性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。键路径使您可以以独立于模型
实现的方式指定相关 对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相
关对象的特定属性。

For example, the key path address.streetwould get the value of the address property from the receiving

object, and then determine the street property relative to the address object.

19.cocoa touch框架

iPhone OS 应用程序的基础 Cocoa Touch 框架重用了许多 Mac 系统的成熟模式,但是它更多地专注于触摸的接口和优化。UIKit 为您提供了在 iPhone OS 上实现图形,事件驱动程序的基本工具,其建立在和 Mac OS X 中一样的 Foundation 框架上,包括文件处理,网络,字符串操作等。

Cocoa Touch 具有和 iPhone 用户接口一致的特殊设计。有了 UIKit,您可以使用 iPhone OS 上的独特的图形接口控件,按钮,以及全屏视图的功能,您还可以使用加速仪和多点触摸手势来控制您的应用。

各色俱全的框架 除了 UIKit 外,Cocoa Touch 包含了创建世界一流 iPhone 应用程序需要的所有框架,从三维图形,到专业音效,甚至提供设备访问 API 以控制摄像头,或通过 GPS 获知当前位置。Cocoa Touch 既包含只需要几行代码就可以完成全部任务的强大的 Objective-C 框架,也在需要时提供基础的 C 语言 API 来直接访问系统。这些框架包括:

Core Animation

通过 Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。

Core Audio

Core Audio 是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。

Core Data

提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用 或大或小的数据模型。

功能列表:框架分类

下面是 Cocoa Touch 中一小部分可用的框架:

音频和 视频Core AudioOpenALMedia LibraryAV Foundation数据管理Core DataSQLite

图 形和动画Core AnimationOpenGL ESQuartz 2D网络/li>BonjourWebKitBSD Sockets

用 户应用Address BookCore LocationMap KitStore Kit

21.自动释放池是什么,如何工作 

 当您向一个对象发送一个autorelease消息时,Cocoa就会将该对 象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置 时,自动释放池就会被释放,池中的所有对象也就被释放。

1.  ojc-c 是通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
2. NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不用你管的.
3. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数 减一.

22.类工厂方法是什么

 类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中, 返回被创建的对象,并
进行自动释放处理。这些方法的形式是+ (type)className...(其中 className不包括任何前缀)。

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

类工厂方法的 另一个目的是使类(比如NSWorkspace)提供单件实例。虽 然init...方法可以确认一
个类在每次程序运行过程只存在一个实例,但它需要首先分配一个“生的”实例,然后还必须释放该实例。
工厂 方法则可以避免为可能没有用的对象盲目分配内存。

23.单件实例是什么

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

24.动态绑定—在运行时确定要调用的方法

动 态绑定将调用方法的确定也推迟到运行时。在编译时,方法的调用并不和代码绑定 在一起,只有在消实发送出来之后,才确定被调用的代码。通过动态类型和动态绑定技术,您的代码每次执行都可以得到不同的结果。运行时因子负责确定消息的接 收者和被调用的方法。 运行时的消息分发机制为动态绑定提供支持。当您向一个动态类型确定了的对象发送消息时,运行环境系统会通过接收者的isa指针定位对象的类,并以此为起点 确定被调用的方法,方法和消息是动态绑定的。而且,您不必在Objective-C 代码中做任何工作,就可以自动获取动态绑定的好处。您在每次发送消息时,


特别是当消息的接收者是动态类型已经确定的对象时,动态绑定就会例行而 透明地发生。

25.obj-c的优缺 点

objc优点:
  1) Cateogies 
  2) Posing 
  3) 动态识别
  4) 指标计算 
  5)弹性讯息传递
  6) 不是一个过度复杂的 C 衍生语言
  7) Objective-C 与 C++ 可混合编程
缺点: 
  1) 不支援命名空間 
  2)  不支持运算符重载 3) 不支持多重继承  4) 使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。

26.sprintf,strcpy,memcpy使用上有什 么要注意的地方

strcpy是一个字符串拷贝的函数,它的函数原型为strcpy(char *dst, const char *src);

将 src开始的一段字符串拷贝到dst开始的内存中去,结束的标志符号为 '\0',由于拷贝的长度不是由我们自己控制的,所以这个字符串拷贝很容易出错。具备字符串拷贝功能的函数有memcpy,这是一个内存拷贝函数,它的函 数原型为memcpy(char *dst, const char* src, unsigned int len);

将长度为len的一段内存,从src拷贝到dst中去,这个函数的长度可控。但 是会有内存叠加的问题。

sprintf是格式化函数。将 一段数据通过特定的格式,格式化到一个字符串缓 冲区中去。sprintf格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲区的大小,造成溢出。

27. 用变量a给出下面的定义  

a) 一个整型数(An integer)  
b)一 个指向整型数的指针( A pointer to an integer)  
c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r  
d)一个有10个整型数的数组( An array of 10 integers)  
e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers)  
f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)  
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument
 and returns an integer)  
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions t
hat take an integer argument and return an integer )  
 
答 案是:  
a) int a; // An integer  
b) int *a; // A pointer to an integer  
c) int **a; // A pointer to a pointer to an integer  
d) int a[10]; // An array of 10 integers  
e) int *a[10]; // An array of 10 pointers to integers  
f) int (*a)[10]; // A pointer to an array of 10 integers  
g) int (*a)(int); // A pointer to a function a that  takes an integer argument and returns an integer  
h) int (*a[10])(int); // An array of 10 pointers to functions  that take an integer argument and return an integer

Iphone基础面试题

1.写一个NSString类的实现

+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;

 

+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding{

       NSString *obj;

       obj = [self allocWithZone: NSDefaultMallocZone()];

       obj = [obj initWIthCString: nullTerminatedCString encoding: encoding];

       return AUTORELEASE(obj);

}

2.写一个委托的interface

答: 

@protocol MyDelegate;

@interface MyClass: NSObject

{

       id <MyDelegate> delegate;

}

// 委托方法

@protocol MyDelegate

- (void)didJobs:(NSArray *)args;

@end

3.请写出你对MVC模式的理解

答:MVC模式考虑三种对象:模型对象、视图对象和控制器对象。模型对象负责应用程序的数据和定义操作数据的逻辑;视图对象知道如何显示应用程序的模型数据;控制器对象是M与V之间的协调者。

4.什么是键-值,键路径是什么

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

键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。第一个键的性质是由先前的性质决定的,接下来每个键的值也是相对于其前面的性质。键路径使您可以以独立于模型实现的方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意深度的路径,使其指向相关对象的特定属性。

5.请列举你熟悉cocoa touch框架(至少三个)

答:

Core Animation

通过 Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。

Core Audio

Core Audio 是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。

Core Data

提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。

功能列表:框架分类

下面是 Cocoa Touch 中一小部分可用的框架:

  • 音频和视频 Core Audio   OpenAL  Media Library   AV Foundation
  • 数据管理  Core Data  SQLite
  • 图形和动画  Core Animation   OpenGL ES   Quartz 2D
  • 网络>  Bonjour  WebKit   BSD Sockets
  • 用户应用  Address Book  Core Location  Map Kit  Store Kit

6.自动释放池是什么,如何工作

当您向一个对象发送一个autorelease 消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当 程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。

1.  ojc-c 是 通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
2. NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不用你管的.
3. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一.

 

7.readwrite,readonly,assign,retain,copy,nonatomic属性的作用

@property是一个属性访问声明,扩号内支持以下几个属性:
1,getter=getterName,setter=setterName,设置setter与getter的方法名
2,readwrite,readonly,设置可供访问级别
2,assign,setter方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题
3,retain,setter方法对参数进行release旧值再retain新值,所有实现都是这个顺序(CC上有相关资料)
4,copy,setter方法进行Copy操作,与retain处理流程一样,先旧值release,再Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。
5,nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级。

8.ViewController 的 loadView, viewDidLoad, viewDidUnload 分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?

viewDidLoad在view 从nib文件初始化时调用,loadView在controller的view为nil时调用。此方法在编程实现view时调用,view 控制器默认会注册memory warning notification,当view controller的任何view 没有用的时候,viewDidUnload会被调用,在这里实现将retain 的view release,如果是retain的IBOutlet view 属性则不要在这里release,IBOutlet会负责release 。 

9.类工厂方法是什么

 类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中, 返回被创建的对象,并
进行自动释放处理。这些方法的形式是+ (type)className...(其中 className不包括任何前缀)。

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

类工厂方法的 另一个目的是使类(比如NSWorkspace)提供单件实例。虽 然init...方法可以确认一
个类在每次程序运行过程只存在一个实例,但它需要首先分配一个“生的”实例,然后还必须释放该实例。
工厂 方法则可以避免为可能没有用的对象盲目分配内存。

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

答:会引起循环引用。

这里delegate我们只是想得到实现了它delegate方法的对象,然后拿到这个对象的指针就可以了,

我们不期望去改变它或者做别的什么操作,所以我们只要用assign拿到它的指针就可以了。

而 用retain的话,计数器加1。我们有可能在别的地方期望释放掉delegate这个对象,然后通过一些

判断比如说它是否已经被释放,做一些操作。但是 实际上它retainCount还是1,没有被释放掉,要在

UITableViewController的dealloc里面才被释放掉(这里我只是举个 例子,一般retain的对象都是

在dealloc里被释放)。这里就会造成一些问题出现。

而如果你确定不会有冲突的问题出现的话,或者你也希望用到delegate的这个对象,直到你不用它为

止,那么用retain也未尝不可,只是需要最后release一次。

 

 

 

1.浅复制和深复制的区别?//浅拷贝和深拷贝


答案:


浅层复制(copy):只复制指向对象的指针,而不复制引用对象本身。//通过对象的指针来访问这个对象


深层复制(mutableCopy):复制引用对象本身
意思就是有个A对象,复制一份后得到A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象本身资源
还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了
两份独立对象本身。//当修改A时,A copy不变。

打个比喻:1、浅拷贝就是:你挂了,你妈妈喊你回家吃饭时找不到人了,她很伤心。2、深拷贝就是:你克隆了一个你自己:你挂了、你兄弟还在,你妈妈喊你回家吃饭时能找到人。所以、孩子,安全起见、深拷贝吧,记得内存管理就是了。


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


答案:category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。// category:类、种类


并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。//类别跟类的优先级


类别主要有3个作用:


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


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


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


继承可以增加,修改或者删除方法,并且可以增加属性。
//非正式协议:是使用类别category来实现,非正式协议是NSObject的一个类别,这样任何类的对象都可以作为委托对象来使用,它可以列出对象能够执行的所有方法,这样用来实现委托, 我们可以使用选择器来判断该非正式协议中是否有这个方法。
正式协议:是一个命名的方法列表,与非正式协议相比不同的是,它要求显示的采用协议,采用协议的方法是在类的@interface声明中列出协议的名称,此时,实现协议的类应该遵守协议,承诺实现协议中的所有方法。

3 类别和类扩展的区别。


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


4. oc中的协议和java中的接口概念有何不同?


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


5.什么是KVO 和 KVC?


答案:kvc:键 - 值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制。//KVC运用了一个isa-swizzling技术。isa-swizzling就是类型混合指针机制。

KVC主要通过isa-swizzling,来实现其内部查找定位的。isa指针,就是is a kind of的意思,指向维护分发表的对象的类。该分发表实际上包含了指向实现类中的方法的指针,和其它数据。

 

kvo(Key-Value Observing):键值观察机制,他提供了观察某一属性变化的方法,极大的简化了代码。
用过的一个地方是对于按钮点击变化状态的的监控。
比如我自定义的一个button。   //当属性改变时KVO回提供自动的消息通知。每次属性改变了就会发送消息通知。这是因为当这个方案已经被明确定义,获得框架级支持,可以方便的采用,开法人员不需要设计自己的观察这模型,可以直接在工程里使用。KOV的架构可以支持多个观察者观察同一个属性,以及相关值。



[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil]; 



 
#pragma mark KVO


 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context


{ 
    if ([keyPath isEqualToString:@"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查找的逻辑理解,就说的过去了。


6.代理的作用?


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

7.oc中可修改和不可以修改类型。


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

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


答案:多态。 主要是将数据类型的确定由编译时,推迟到了运行时。
这个问题其实浅涉及到两个概念,运行时和多态。
运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
多态:不同对象以自己的方式响应相同的消息的能力叫做多态。
//都用有一个相同的方法,不同的对象以自己的方式响应了相同的消息.
因此也可以说,运行时机制是多态的基础


9.通知和协议的不同之处?


答案:协议有控制链(has-a)的关系,通知没有。//通知:它可以一对多,一条消息可以发送给多个消息接受者,但是不会处理消息
控制链:单一拥有和可控制的对应关系。


10.关于多态性


答案:多态,子类指针可以赋值给父类。
对象不仅仅可以已本身的类型存在,也可以作为其父类类型存在。 多态性是允许将父对象设置成为和一个或多个它的子对象相等的技术, 多态性使得能够利用同一类(基类)类型的指针来引用不同类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作.


11.说说响应链


答案: 事件响应链。包括点击事件,画面刷新事件等。在视图栈内从上至下,或者从下之上传播。


12. frame和bounds有什么不同?


答案:frame指的是:该view在父view坐标系统中的位置和大小。(参照点是父亲的坐标系统)//frame:框架、结构


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


14. NSOperation队列


操作和操作队列,基本可以看成java中的线程和线程池的概念。用于处理ios多线程开发的问题。
网上部分资料提到一点是,虽然是queue,但是却并不是带有队列的概念,放入的操作并非是按照严格的先进现出。
这边又有个疑点是,对于队列来说,先进先出的概念是Afunc添加进队列,Bfunc紧跟着也进入队列,Afunc先执行这个是必然的,
但是Bfunc是等Afunc完全操作完以后,B才开始启动并且执行,因此队列的概念离乱上有点违背了多线程处理这个概念。
但是转念一想其实可以参考银行的取票和叫号系统。
因此对于A比B先排队取票但是B率先执行完操作,我们亦然可以感性认为这还是一个队列。
但是后来看到一票关于这操作队列话题的文章,其中有一句提到
“因为两个操作提交的时间间隔很近,线程池中的线程,谁先启动是不定的。”
瞬间觉得这个queue名字有点忽悠人了,还不如pool~
综合一点,我们知道他可以比较大的用处在于可以帮组多线程编程就好了。


15.是否在一个视图控制器中嵌入两个tableview控制器?


答案:一个视图控制只提供了一个View视图,理论上一个tableViewController也不能放吧,
只能说可以嵌入一个tableview视图。而是宏观的表示视图控制者,那我们倒是可以把其看成一个视图控制者,它可以控制多个视图控制器,比如TabbarController

16. 一个tableView是否可以关联两个不同的数据源?你会怎么处理?
答案:首先从代码来看,数据源如何关联上的,其实是在数据源关联的代理方法里实现的。
 



-(UITableViewCell*)cellForRowAtIndexPath:(NSIndexPath*)indexPath


{


if(indexPath.section == 0)


{


}


if(indexPath.section == 1)


{


}


}


17. 什么是id类型


答案:id类型的变量可以存放任何数据类型的对象。在内部处理上,这种类型被定义为指向对象的指针,实际上是一个指向这种对象的实例变量的指针。
例如:id number
将number声明为id类型的变量。可声明的方法使其具有id类型的返回值,如下:


-(id)newObject;(int)type;
这个程序声明了一个名为newObject的实例方法,它具有名为type的单个整型参数并有id类型的返回值。应该注意的是,对返回值和参数类型声明来说,id是默认的类型。
id类型是objetive-c中非常中药店额数据类型,它是多态和动态绑定的基础。

 

18.写一个NSString类的实现


+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;

+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding

{


  NSString *obj;

 
 obj = [self allocWithZone:NSDefaultMallocZone()];


   obj = [obj initWIthCString:nullTerminatedCString encoding: 
encoding];


   return AUTORELEASE(obj);


}

19.写一个委托的interface


答: 

 
@protocol MyDelegate;


@interface MyClass: NSObject 


{

 
 id <MyDelegate> delegate; 


} 


 

// 委托方法 


@protocol MyDelegate


- (void)didJobs:(NSArray *)args; 


@end

20.请写出你对MVC模式的理解 


答:MVC模式考虑三种对象:模型对象、视图对象和控制器对象。
模型对象负责应用程序的数据和定义操作数据的逻辑;
视图对象知道如何显示应用程序的模型数据;
控制器对象是M与V之间的协调者。

21.什么是键-值,键路径是什么 


答:模型的性质是通过一个简单的键(通常是个字符串)来指定的。
视图和控制器通过键来查找相应的属性值。在一个给定的实体中,
同一个属性的所有值具有相同的数据类型。键-值编码技术用于进行
这样的查找—它是一种间接访问对象属性的机制。 
键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接
在一起的对象性质序列。第一个键的性质是由先前的性质决定的,接下来
每个键的值也是相对于其前面的性质。键路径使您可以以独立于模型实现的
方式指定相关对象的性质。通过键路径,您可以指定对象图中的一个任意
深度的路径,使其指向相关对象的特定属性。

22.请列举你熟悉cocoa touch框架(至少三个)


答:
Core Animation 


通过 Core Animation,您就可以通过一个基于组合独立图层的简单的编程
模型来创建丰富的用户体验。


Core Audio 
Core Audio 是播放,处理和录制音频的专业技术,能够轻松为您的应用
程序添加强大的音频功能。


Core Data 
提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理
任何应用或大或小的数据模型。 


功能列表:框架分类 


下面是 Cocoa Touch 中一小部分可用的框架: 


音频和视频: 


Core Audio 


OpenAL 


Media Library 


AV Foundation 


数据管理:


Core Data 


SQLite 


图形和动画:


Core Animation


OpenGL ES


Quartz 2D 


网络: 


Bonjour 


WebKit 


BSD

Sockets 


用户应用: 


Address Book 


Core Location 


Map Kit 


Store Kit


23.自动释放池是什么,如何工作


答案:当您向一个对象发送一个autorelease 消息时,Cocoa就会将该对象
的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此
自动释放池定义的作用域内的其它对象可以向它发送消息。当 程序
执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对
象也就被释放。 
ojc-c 是 通过一种"referring counting"(引用计数)的方式来管理内
存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰
到有copy,retain的时候引用计数都会加一, 每当碰到release和
autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 
就会被系统销毁. 
2. NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西
一般不用你管的. 
3. autorelease和release没什么区别,只是引用计数减一的时机不
同而已,autorelease会在对象的使用真正结束的时候才做引用计数
减1.


24.readwrite,readonly,assign,retain,copy,nonatomic
属性的作用

答案:
@property是一个属性访问声明,扩号内支持以下几个属性: 
1,getter=getterName,setter=setterName,设置setter与getter的方法名 


2,readwrite,readonly,设置可供访问级别 


3,assign,setter方法直接赋值,不进行任何retain操作,为了解决原类
型与环循引用问题 


4,retain,setter方法对参数进行release旧值再retain新值,所有实现
都是这个顺序(CC上有相关资料) 


5,copy,setter方法进行Copy操作,与retain处理流程一样,先旧值
release,再Copy出新的对象,retainCount为1。这是为了减少对上下文
的依赖而引入的机制。 


6,nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。
注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁
被加到所属对象实例级。

25.ViewController 的 loadView, viewDidLoad, viewDidUnload 
分别是在什么时候调用的?在自定义ViewController的时候这几个
函数里面应该做什么工作?

答案:
viewDidLoad在view 从nib文件初始化时调用,loadView在controller的view为nil时调用。
此方法在编程实现view时调用,view 控制器默认会注册memory warning notification,


当view controller的任何view 没有用的时候,viewDidUnload会被调用,在这里实现将
retain 的view release,如果是retain的IBOutlet view 属性则不要在这里release,
IBOutlet会负责release 。

 
 


26.类工厂方法是什么
 

答案:类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中,返回
被创建的对象,并
进行自动释放处理。这些方法的形式是+ (type)className...
(其中 className不包括任何前缀)。
工厂方法可能不 仅仅为了方便使用。它们不但可以将分配和初始化合在一起,还可以 为
初始化过程提供对
象的分配信息。
类工厂方法的 另一个目的是使类(比如NSWorkspace)提供单件实例。虽 然init...方法
可以确认一
个类在每次程序运行过程只存在一个实例,但它需要首先分配一个“生的”实
例,然后还必须释放该实例。
工厂 方法则可以避免为可能没有用的对象盲目分配内存。
 


 


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


答:会引起循环引用。
这里delegate我们只是想得到实现了它delegate方法的对象,然后拿到这个对象的指针就
可以了,
我们不期望去改变它或者做别的什么操作,所以我们只要用assign拿到它的指针就可以了。
而 用retain的话,计数器加1。我们有可能在别的地方期望释放掉delegate这个对象,
然后通过一些判断比如说它是否已经被释放,做一些操作。但是 实际上它retainCount还
是1,没有被释放掉,要在UITableViewController的dealloc里面才被释放掉(这里我只是
举个 例子,一般retain的对象都是在dealloc里被释放)。这里就会造成一些问题出现。
而如果你确定不会有冲突的问题出现的话,或者你也希望用到delegate的这个对象,直到
你不用它为止,那么用retain也未尝不可,只是需要最后release一次。

 

 

28.

1.main() 

 {  

   int a[5]={1,2,3,4,5};  

   int *ptr=(int *)(&a+1);   

   printf("%d,%d",*(a+1),*(ptr-1)); 

} 

答:2,5 

     *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5 

  &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int) 

  int *ptr=(int *)(&a+1); 

  则ptr实际是&(a[5]),也就是a+5 

原因如下: 

  &a是数组指针,其类型为 int (*)[5]; 

  而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同。 

  a是长度为5的int数组指针,所以要加 5*sizeof(int) 

  所以ptr实际是a[5] 

  但是prt与(&a+1)类型是不一样的(这点很重要) 

  所以prt-1只会减去sizeof(int*) 

  a,&a的地址是一样的,但意思不一样 

    a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址, 

    a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]. 

  

29.以下为Windows NT下的32位C++程序,请计算sizeof的值 

void Func ( char str[100] )  

{  

  sizeof( str ) = ?  

}  

void *p = malloc( 100 ); 

sizeof ( p ) = ? 

答:这题很常见了,Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof ( p ) 都为4。 

  

30.还是考指针,不过我对cocoa的代码还是不太熟悉 

大概是这样的 

- (void)*getNSString(const NSString * inputString) 

     inputString = @"This is a main test\n"; 

     return ; 

-main(void) 

  

NSString *a=@"Main"; 

  

 NSString *aString = [NSString stringWithString:@"%@",getNSString(a)]; 

  

 NSLog(@"%@\n", aString); 

答:最后问输出的字符串:NULL,output在函数返回后,内存已经被释放。 

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

答:#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL  

我在这想看到几件事情:  

 #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)  

懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。 

意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。  

如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。  

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

答:#define MIN(A,B) ((A) <= (B) ? (A) : (B))  

这个测试是为下面的目的而设的:  

标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方 

法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。  

三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比 if-then-else 更优化的代码,了解这个用法是很重要的。 懂得在宏中小心地把参数用括号括起来  我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?  least = MIN(*p++, b);  

结果是: 

((*p++) <= (b) ? (*p++) : (*p++)) 

这个表达式会产生副作用,指针p会作三次++自增操作。 

  

33.写一个委托的interface 

  答:

@protocol MyDelegate; 

  

@interface MyClass: NSObject 

    id <MyDelegate> delegate; 

  

// 委托方法 

@protocol MyDelegate 

- (void)didJobs:(NSArray *)args; 

@end 

34.写一个NSString类的实现 

答:

+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding; 

+ (id) stringWithCString: (const char*)nullTerminatedCString  

            encoding: (NSStringEncoding)encoding 

  NSString  *obj; 

  obj = [self allocWithZone: NSDefaultMallocZone()]; 

  obj = [obj initWithCString: nullTerminatedCString encoding: encoding]; 

  return AUTORELEASE(obj); 

35.obj-c有多重继承么?不是的话有什么替代方法? 

答:

cocoa 中所有的类都是NSObject 的子类

多继承在这里是用protocol 委托代理来实现的  

你不用去考虑繁琐的多继承 ,虚基类的概念. 

ood的多态特性在 obj-c 中通过委托来实现.  

36.obj-c有私有方法么?私有变量呢 

答:

objective-c - 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法 

@interface Controller : NSObject { NSString *something; } 

+ (void)thisIsAStaticMethod; 

- (void)thisIsAnInstanceMethod; 

@end 

@interface Controller (private) - 

(void)thisIsAPrivateMethod; 

@end 

@private可以用来修饰私有变量 

在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的 

 

37.关键字const有什么含意?修饰类呢?static的作用,用于类呢?还有extern c的作用

const意味着"只读",下面的声明都是什么意思?  

const int a;  

int const a;  

const int *a;  

int * const a;  

int const * a const;  

  答:

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。 

结论: 

关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果 你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清 理的。) 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。   

(1)欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初 

始化,因为以后就没有机会再去改变它了; 

(2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指 

定为 const; 

(3)在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值; 

(4)对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量; 

(5)对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左值”。 

38.关键字volatile有什么含意?并给出三个不同的例子。 

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到 

这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:   

并行设备的硬件寄存器(如:状态寄存器)  一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)  多线程应用中被几个任务共享的变量  

 一个参数既可以是const还可以是volatile吗?解释为什么。  

一个指针可以是volatile 吗?解释为什么。  

下面是答案:  

是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。  

是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。   

39.static 关键字的作用: 

(1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次, 

因此其值在下次调用时仍维持上次的值; 

(2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问; 

(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明 

它的模块内; 

(4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝; 

(5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。  

40.extern "C" 的作用 

(1)被 extern "C"限定的函数或变量是 extern 类型的; 

       extern 是 C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器, 

其声明的函数和变量可以在本模块或其它模块中使用。 

(2)被 extern "C"修饰的变量和函数是按照 C 语言方式编译和连接的;  

41.extern "C"的惯用法  

(1)在 C++中引用 C 语言中的函数和变量,在包含 C 语言头文件(假设为 cExample.h)时,需进行下列处理: 

extern "C"  

{  

#include "cExample.h"  

}  

而在 C 语言的头文件中,对其外部函数只能指定为 extern 类型,C 语言中不支持 extern "C"声明, 在.c 文件中包含了 extern "C"时会出现编译语法错误。 

(2)在 C 中引用 C++语言中的函数和变量时,C++的头文件需添加 extern "C",但是在 C 语言中不 能直接引用声明了 extern "C"的该头文件,应该仅将 C 文件中将 C++中定义的 extern "C"函数声明为 extern 类型。 

42.为什么标准头文件都有类似以下的结构?  

   #ifndef __INCvxWorksh  

   #define __INCvxWorksh  

   #ifdef __cplusplus  

   extern "C" {  

   #endif  

   /*...*/  

   #ifdef __cplusplus  

   }  

   #endif  

   #endif /* __INCvxWorksh */  

显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用 

是防止该头文件被重复引用。 

43.#import跟#include的区别,@class呢? 

 @class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import 

而#import比起#include的好处就是不会引起交叉编译 

44.MVC模式的理解 

MVC设计模式考虑三种对象:模型对象、视图对象、和控制器对象。模型对象代表特别的知识和专业技能,它们负责保有应用程序的数据和定义操作数据的逻辑。视图对象知道如何显示应用程序的模型数据,而且可能允许用户对其进行编辑。控制器对象是应用程序的视图对象和模型对象之间的协调者。 

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

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。 

程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。 

 

46.列举几种进程的同步机制,并比较其优缺点。 

答案:  原子操作 信号量机制    自旋锁    管程,会合,分布式系统 

进程之间通信的途径 

答案:共享存储系统消息传递系统管道:以文件系统为基础 

进程死锁的原因 

答案:资源竞争及进程推进顺序非法 

死锁的4个必要条件 

答案:互斥、请求保持、不可剥夺、环路 

死锁的处理 

答案:鸵鸟策略、预防策略、避免策略、检测与解除死锁 

47.堆和栈的区别 

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

申请大小: 

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

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

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

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

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

48.什么是键-值,键路径是什么 

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

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

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

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

关对象的特定属性。 

For example, the key path address.streetwould get the value of the address property from the receiving 

object, and then determine the street property relative to the address object. 

49.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.

50.目标-动作机制 

  答案:

目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参见"插座变量"部分) 

的形式保有其动作消息的目标。 

动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现的方法。 

程序需要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制。

51.cocoa touch框架 

答案:

iPhone OS 应用程序的基础 Cocoa Touch 框架重用了许多 Mac 系统的成熟模式,但是它更多地专注于触摸的接口和优化。UIKit 为您提供了在 iPhone OS 上实现图形,事件驱动程序的基本工具,其建立在和 Mac OS X 中一样的 Foundation 框架上,包括文件处理,网络,字符串操作等。 

Cocoa Touch 具有和 iPhone 用户接口一致的特殊设计。有了 UIKit,您可以使用 iPhone OS 上的独特的图形接口控件,按钮,以及全屏视图的功能,您还可以使用加速仪和多点触摸手势来控制您的应用。 

各色俱全的框架 除了 UIKit 外,Cocoa Touch 包含了创建世界一流 iPhone 应用程序需要的所有框架,从三维图形,到专业音效,甚至提供设备访问 API 以控制摄像头,或通过 GPS 获知当前位置。Cocoa Touch 既包含只需要几行代码就可以完成全部任务的强大的 Objective-C 框架,也在需要时提供基础的 C 语言 API 来直接访问系统。这些框架包括: 

Core Animation 

通过 Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。 

Core Audio 

Core Audio 是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。 

Core Data 

提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。 

功能列表:框架分类 

下面是 Cocoa Touch 中一小部分可用的框架: 

音频和视频 


Core Audio 


OpenAL 


Media Library 


AV Foundation 


数据管理 


Core Data 


SQLite 

图形和动画

 
Core Animation 


OpenGL ES 


Quartz 2D 


网络


Bonjour 


WebKit 


BSD

Sockets 

用户应用 

Address Book 


Core Location 


Map Kit 


Store Kit 

52.objc的内存管理 

答案:  如果您通过分配和初始化(比如[[MyClass alloc] init])的方式来创建对象,您就拥 有这个对象,需要负责该对象的释放。这个规则在使用NSObject的便利方法new 时也同样适用。 如果您拷贝一个对象,您也拥有拷贝得到的对象,需要负责该对象的释放。 如果您保持一个对象,您就部分拥有这个对象,需要在不再使用时释放该对象。 反过来,如果您从其它对象那里接收到一个对象,则您不拥有该对象,也不应该释放它(这个规则有少数 的例外,在参考文档中有显式的说明)。 

53.自动释放池是什么,如何工作 

 答案:

当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。 

1.  ojc-c 是通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁. 

2. NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不用你管的. 

3. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一.  

54.单件实例是什么 

答案:

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

55.动态绑定 

答案:

在运行时确定要调用的方法 。动态绑定将调用方法的确定也推迟到运行时。在编译时,方法的调用并不和代码绑定在一起,只有在消实发送出来之后,才确定被调用的代码。通过动态类型和动态绑定技术,您的代码每次执行都可以得到不同的结果。运行时因子负责确定消息的接收者和被调用的方法。运行时的消息分发机制为动态绑定提供支持。当您向一个动态类型确定了的对象发送消息时,运行环境系统会通过接收者的isa指针定位对象的类,并以此为起点确定被调用的方法,方法和消息是动态绑定的。而且,您不必在Objective-C 代码中做任何工作,就可以自动获取动态绑定的好处。您在每次发送消息时,特别是当消息的接收者是动态类型已经确定的对象时,动态绑定就会例行而透明地发生。 

56.obj-c的优缺点 

答案:

objc优点: 

  1) Cateogies 

  2) Posing 

  3) 动态识别 

  4) 指标计算 

  5)弹性讯息传递 

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

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

缺点: 

  1) 不支援命名空间 

  2)  不支持运算符重载 

  3) 不支持多重继承 

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

57.sprintf,strcpy,memcpy使用上有什么要注意的地方

答案: 

strcpy是一个字符串拷贝的函数,它的函数原型为strcpy(char *dst, const char *src); 

将src开始的一段字符串拷贝到dst开始的内存中去,结束的标志符号为'\0',由于拷贝的长度不是由我们自己控制的,所以这个字符串拷贝很容易出错。具备字符串拷贝功能的函数有memcpy,这是一个内存拷贝函数,它的函数原型为memcpy(char *dst, const char* src, unsigned int len); 

将长度为len的一段内存,从src拷贝到dst中去,这个函数的长度可控。但是会有内存叠加的问题。 

sprintf是格式化函数。将一段数据通过特定的格式,格式化到一个字符串缓冲区中去。sprintf格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲区的大小,造成溢出。

58. 用变量a给出下面的定义   

a) 一个整型数(An integer)   

b)一个指向整型数的指针( A pointer to an integer)   

c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r   

d)一个有10个整型数的数组( An array of 10 integers)   

e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers)   

f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)   

g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument 

 and returns an integer)   

h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions t 

hat take an integer argument and return an integer )  

答案是:   

a) int a; // An integer   

b) int *a; // A pointer to an integer   

c) int **a; // A pointer to a pointer to an integer   

d) int a[10]; // An array of 10 integers   

e) int *a[10]; // An array of 10 pointers to integers   

f) int (*a)[10]; // A pointer to an array of 10 integers   

g) int (*a)(int); // A pointer to a function a that  takes an integer argument and returns an integer   

h) int (*a[10])(int); // An array of 10 pointers to functions  that take an integer argument and return an integer 

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

答案:

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。?进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

60. 定义属性时,什么情况使用copy,assign,和retain?

答案:assign用于简单数据类型,如NSInteger,double,bool。retain和copy用于对象。copy用于当a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy 的方式,a和b各自有自己的内存,就可以解决这个问题。retain 会使计数器加1,也可以解决assign的问题。另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。?加了atomic,setter函数会变成下面这样:

if (property != newValue)

{

  [property release];

  property = [newValue retain];

61. 对象是在什么时候被release的?

答案:

引用计数为0时。

autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。对于每一个Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object(就是autorelease的对象)会被release。那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 都会是一个新的Runloop。

62. IPhone OS有没有垃圾回收?

没有。iPhone开发的时候没有垃圾回收机制

63. ViewController 的 loadView, viewDidLoad, viewDidUnload 分别是在什么时候调用的?

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

答案:由init、loadView、viewDidLoad、viewDidUnload、dealloc的关系说起。

init方法:在init方法中实例化必要的对象(遵从LazyLoad思想)。init方法中初始化ViewController本身

loadView方法:当view需要被展示而它却是nil时,viewController会调用该方法。不要直接调用该方法。如果手工维护views,必须重载重写该方法;如果使用IB维护views,必须不能重载重写该方法。loadView和IB构建view,你在控制器中实现了loadView方法,那么你可能会在应用运行的某个时候被内存管理控制调用。 如果设备内存不足的时候, view 控制器会收到didReceiveMemoryWarning的消息。 默认的实现是检查当前控制器的view是否在使用。 如果它的view不在当前正在使用的view hierarchy里面,且你的控制器实现了loadView方法,那么这个view将被release, loadView方法将被再次调用来创建一个新的view。

viewDidLoad方法:viewDidLoad 此方法只有当view从nib文件初始化的时候才被调用。重载重写该方法以进一步定制view,在iPhone OS 3.0及之后的版本中,还应该重载重写viewDidUnload来释放对view的任何索引;viewDidLoad后调用数据Model。

viewDidUnload方法:当系统内存吃紧的时候会调用该方法(注:viewController没有被dealloc)。内存吃紧时,在iPhone OS 3.0之前didReceiveMemoryWarning是释放无用内存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式。在该方法中将所有IBOutlet(无论是property还是实例变量)置为nil(系统release view时已经将其release掉了)在该方法中释放其他与view有关的对象、其他在运行时创建(但非系统必须)的对象、在viewDidLoad中被创建的对象、缓存数据等 release对象后,将对象置为nil(IBOutlet只需要将其置为nil,系统release view时已经将其release掉了)

一般认为viewDidUnload是viewDidLoad的镜像,因为当view被重新请求时,viewDidLoad还会重新被执行viewDidUnload中被release的对象必须是很容易被重新创建的对象(比如在viewDidLoad或其他方法中创建的对象),不要release用户数据或其他很难被重新创建的对象

dealloc方法:viewDidUnload和dealloc方法没有关联,dealloc还是继续做它该做的事情。

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

2、在一个对象的方法里面:

self.name = “object”;

name =”object”

有什么不同吗?

3、这段代码有什么问题吗:

@implementation Person

- (void)setAge:(int)newAge {

self.age = newAge;

}

@end

4、什么是retain count?

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

Person *person = [[Person alloc] init];

[person retain];

[person release];

[person release];

6、为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?

7、定义属性时,什么情况使用copy,assign,和retain

8、autorelease的对象是在什么时候被release的?

9、这段代码有什么问题,如何修改

10、for (int i = 0; i < someLargeNumber; i++) {

NSString *string = @”Abc”;

string = [string lowercaseString];

string = [string stringByAppendingString:@"xyz"];

NSLog(@“%@”, string);

}

11、autorelease和垃圾回收机制(gc)有什么关系?

12、IPhone OS有没有垃圾回收(gc)?

13、什么是Notification?

答:观察者模式,controller向defaultNotificationCenter添加自己的notification,其他类注册这个notification就可以收到通知,这些类可以在收到通知时做自己的操作(多观察者默认随机顺序发通知给观察者们,而且每个观察者都要等当前的某个观察者的操作做完才能轮到他来操作,可以用NotificationQueue的方式安排观察者的反应顺序,也可以在添加观察者中设定反映时间,取消观察需要在viewDidUnload 跟dealloc中都要注销)

14、什么时候用delegate,什么时候用Notification?

答:

15、什么是KVC和KVO?

答:KVC(Key-Value-Coding)内部的实现:一个对象在调用setValue的时候,(1)首先根据方法名找到运行方法的时候所需要的环境参数。(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现。KVO(Key-Value-Observing):当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名。

1.objective-c中是所有对象间的交互是如何实现的?(深圳皆凯科技有限公司笔试题)

2.如何将产品进行多语言发布?

3.objective-c中是如何实现线程同步的?

4.编写函数_memmove说明如下:实现C语言库函数memmove的功能:将一块缓冲区中的数据移动到另一块缓冲区中。可能有重复。 

5.什么叫数据结构?(面试顺风快递iphone开发) 

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

7.Sizeofstrlen的区别和联系?

8.什么是抽象类?抽象类有什么作用?能实例化吗?

9.线程中有哪些函数?写出来

10.有没有写过自定义的控件

11.调用一个类的静态方法需不需要release

12.do-while  while-do的区别?

13.写出几个死循环?

14.考察对@interface@property的理解?

15. Iphone开发中控制类有什么作用?

16. Objective-C写冒泡法. 

Object-C有多继承吗?没有的话用什么代替?

cocoa 中所有的类都是NSObject 的子类
多继承在这里是用protocol 委托代理 来实现的
你不用去考虑繁琐的多继承 ,虚基类的概念.
ood的多态特性 在 obj-c 中通过委托来实现.


Object-C有私有方法吗?私有变量呢?

objective-c – 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法
@interface Controller : NSObject { NSString *something; }
+ (void)thisIsAStaticMethod;
– (void)thisIsAnInstanceMethod;
@end
@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end

@private可以用来修饰私有变量
在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的

关键字const什么含义

const意味着”只读”,下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

结论:
•; 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果
你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清
理的。)
•; 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
•; 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初
始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指
定为 const;
(3)在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左值”。

关键字volatile有什么含义?并给出三个不同例子?

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到
这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
• 并行设备的硬件寄存器(如:状态寄存器)
• 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
• 多线程应用中被几个任务共享的变量

• 一个参数既可以是const还可以是volatile吗?解释为什么。
• 一个指针可以是volatile 吗?解释为什么。

下面是答案:
• 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
• 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

static作用?

函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值;
(2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明
它的模块内;
(4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。

#import和#include的区别,@class代表什么?

@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import
而#import比起#include的好处就是不会引起重复包含

线程和进程的区别?

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

堆和栈的区别?

管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
申请大小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

Object-C的内存管理?

1.当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.当你不再使用该对象时,你要负责向该对象发送一条release或autorelease消息.这样,该对象将在使用寿命结束时被销毁.
2.当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理.如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它.
3.如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等.

为什么很多内置的类,如TableViewController的delegate的属性是assign不是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方式的,那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时,也要注意这点。

定义属性时,什么情况使用copy、assign、retain?

assign用于简单数据类型,如NSInteger,double,bool,
retain和copy用于对象,
copy用于当a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy 的方式,a和b各自有自己的内存,就可以解决这个问题。
retain 会使计数器加一,也可以解决assign的问题。
另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。
加了atomic,setter函数会变成下面这样:
if (property != newValue) {
[property release];
property = [newValue retain];
}

对象是什么时候被release的?

引用计数为0时。
autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。对于每一个Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object(就是autorelease的对象)会被release。那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 都会是一个新的Runloop

iOS有没有垃圾回收?

Objective-C 2.0也是有垃圾回收机制的,但是只能在Mac OS X Leopard 10.5 以上的版本使用。

tableView的重用机制?

 查看UITableView头文件,会找到NSMutableArray*  visiableCells,和NSMutableDictnery* reusableTableCells两个结构。visiableCells内保存当前显示的cells,reusableTableCells保存可重用的cells。

  TableView显示之初,reusableTableCells为空,那么tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。开始的cell都是通过[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]来创建,而且cellForRowAtIndexPath只是调用最大显示cell数的次数。

  比如:有100条数据,iPhone一屏最多显示10个cell。程序最开始显示TableView的情况是:

  1. 用[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]创建10次cell,并给cell指定同样的重用标识(当然,可以为不同显示类型的cell指定不同的标识)。并且10个cell全部都加入到visiableCells数组,reusableTableCells为空。

  2. 向下拖动tableView,当cell1完全移出屏幕,并且cell11(它也是alloc出来的,原因同上)完全显示出来的时候。cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。

3. 接着向下拖动tableView,因为reusableTableCells中已经有值,所以,当需要显示新的cell,cellForRowAtIndexPath再次被调用的时候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出visiableCells,cell2加入到reusableTableCells。之后再需要显示的Cell就可以正常重用了。


ViewController 的loadView、viewDidLoad、viewDidUnload分别是什么时候调用的,在自定义ViewCointroller时在这几个函数中应该做什么工作?

由init、loadView、viewDidLoad、viewDidUnload、dealloc的关系说起
init方法
在init方法中实例化必要的对象(遵从LazyLoad思想)
init方法中初始化ViewController本身

loadView方法
当view需要被展示而它却是nil时,viewController会调用该方法。不要直接调用该方法。
如果手工维护views,必须重载重写该方法
如果使用IB维护views,必须不能重载重写该方法

loadView和IB构建view
你在控制器中实现了loadView方法,那么你可能会在应用运行的某个时候被内存管理控制调用。 如果设备内存不足的时候, view 控制器会收到didReceiveMemoryWarning的消息。 默认的实现是检查当前控制器的view是否在使用。 如果它的view不在当前正在使用的view hierarchy里面,且你的控制器实现了loadView方法,那么这个view将被release, loadView方法将被再次调用来创建一个新的view。

viewDidLoad方法
viewDidLoad 此方法只有当view从nib文件初始化的时候才被调用。
重载重写该方法以进一步定制view
在iPhone OS 3.0及之后的版本中,还应该重载重写viewDidUnload来释放对view的任何索引
viewDidLoad后调用数据Model

viewDidUnload方法
当系统内存吃紧的时候会调用该方法(注:viewController没有被dealloc)
内存吃紧时,在iPhone OS 3.0之前didReceiveMemoryWarning是释放无用内存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式
在该方法中将所有IBOutlet(无论是property还是实例变量)置为nil(系统release view时已经将其release掉了)

在该方法中释放其他与view有关的对象、其他在运行时创建(但非系统必须)的对象、在viewDidLoad中被创建的对象、缓存数据等 release对象后,将对象置为nil(IBOutlet只需要将其置为nil,系统release view时已经将其release掉了)

一般认为viewDidUnload是viewDidLoad的镜像,因为当view被重新请求时,viewDidLoad还会重新被执行

viewDidUnload中被release的对象必须是很容易被重新创建的对象(比如在viewDidLoad或其他方法中创建的对象),不要release用户数据或其他很难被重新创建的对象

dealloc方法
viewDidUnload和dealloc方法没有关联,dealloc还是继续做它该做的事情


ViewController的didReceiveMemoryWarning是在什么时候调用的?默认的操作是什么?

当程序接到内存警告时View Controller将会收到这个消息:didReceiveMemoryWarning

从iOS3.0开始,不需要重载这个函数,把释放内存的代码放到viewDidUnload中去。

这个函数的默认实现是:检查controller是否可以安全地释放它的view(这里加粗的view指的是controller的view属性),比如view本身没有superview并且可以被很容易地重建(从nib或者loadView函数)。

如果view可以被释放,那么这个函数释放view并调用viewDidUnload。

你可以重载这个函数来释放controller中使用的其他内存。但要记得调用这个函数的super实现来允许父类(一般是UIVIewController)释放view。

如果你的ViewController保存着view的子view的引用,那么,在早期的iOS版本中,你应该在这个函数中来释放这些引用。而在iOS3.0或更高版本中,你应该在viewDidUnload中释放这些引用。

 

列举Cocoa中常见的集中多线程的实现,并谈谈多线程安全的几种解决办法,一般什么地方会用到多线程?

NSOperation NSThread
@sychonized

怎么理解MVC,在Cocoa中MVC是怎么实现的?

MVC设计模式考虑三种对象:模型对象、视图对象、和控制器对象。模型对象代表特别的知识和专业技能,它们负责保有应用程序的数据和定义操作数据的逻辑。视图对象知道如何显示应用程序的模型数据,而且可能允许用户对其进行编辑。控制器对象是应用程序的视图对象和模型对象之间的协调者。
ViewCotroller
Xib

delegate和notification区别,分别在什么情况下使用?

KVC(Key-Value-Coding)
KVO(Key-Value-Observing)
理解KVC与KVO(键-值-编码与键-值-监看)

当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过几种不同的方式解析这个调用。首先查找对象是否带有 someKey 这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到,程序会继续试图调用 -(id) valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。

(Key-Value Coding查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以及_getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。)

设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。


self.跟self什么区别?


id、nil代表什么?

id

 

id和void *并非完全一样。在上面的代码中,id是指向struct objc_object的一个指针,这个意思基本上是说,id是一个指向任何一个继承了Object(或者NSObject)类的对象。需要注意的是id是一个指针,所以你在使用id的时候不需要加星号。比如id foo=nil定义了一个nil指针,这个指针指向NSObject的一个任意子类。而id *foo=nil则定义了一个指针,这个指针指向另一个指针,被指向的这个指针指向NSObject的一个子类。

 

nil

 

nil和C语言的NULL相同,在objc/objc.h中定义。nil表示一个Objctive-C对象,这个对象的指针指向空(没有东西就是空)。

内存管理 Autorelease、retain、copy、assign的set方法和含义?

1,你初始化(alloc/init)的对象,你需要释放(release)它。例如:

  NSMutableArray aArray = [[NSArray alloc] init];

  后,需要

  [aArray release];

  2,你retain或copy的,你需要释放它。例如:

  [aArray retain]

  后,需要

  [aArray release];

  3,被传递(assign)的对象,你需要斟酌的retain和release。例如:

  obj2 = [[obj1 someMethod] autorelease];

  对象2接收对象1的一个自动释放的值,或传递一个基本数据类型(NSInteger,NSString)时: 你或希望将对象2进行retain,以防止它在被使用之前就被自动释放掉。但是在retain后,一定要在适当的时候进行释放。

 

  关于索引计数(Reference Counting)的问题

  retain值 = 索引计数(Reference Counting)

  NSArray对象会retain(retain值加一)任何数组中的对象。当NSArray被卸载(dealloc)的时候,所有数组中的对象会被执行一次释放(retain值减一)。不仅仅是NSArray,任何收集类(Collection Classes)都执行类似操作。例如NSDictionary,甚至UINavigationController。

  Alloc/init建立的对象,索引计数为1。无需将其再次retain。

  [NSArray array]和[NSDate date]等“方法”建立一个索引计数为1的对象,但是也是一个自动释放对象。所以是本地临时对象,那么无所谓了。如果是打算在全Class中使用的变量(iVar),则必须retain它。

  缺省的类方法返回值都被执行了“自动释放”方法。(*如上中的NSArray)

  在类中的卸载方法“dealloc”中,release所有未被平衡的NS对象。(*所有未被autorelease,而retain值为1的)

类别的作用?

有时我们需要在一个已经定义好的类中增加一些方法,而不想去重写该类。比如,当工程已经很大,代码量比较多,或者类中已经包住很多方法,已经有其他代码调用了该类创建对象并使用该类的方法时,可以使用类别对该类扩充新的方法。

  注意:类别只能扩充方法,而不能扩充成员变量。

委托(举例)

委托代理(degegate),顾名思义,把某个对象要做的事情委托给别的对象去做。那么别的对象就是这个对象的代理,代替它来打理要做的事。反映到程序中,首先要明确一个对象的委托方是哪个对象,委托所做的内容是什么。
委托机制是一种设计模式,在很多语言中都用到的,这只是个通用的思想,网上会有很多关于这方面的介绍。
那么在苹果开发过程中,用到委托的程序实现思想如下,我主要拿如何在视图之间传输信息做个例子。
譬如:在两个页面(UIIview视图对象)实现传值,用委托(delegate)可以很好做到!
方法:
类A
@interface A:UIView
        id transparendValueDelegate;
       @property(nomatic, retain) id transparendValueDelegate;
@end

@implemtion A
@synthesize transparendValueDelegate
-(void)Function
{ 
      NSString* value = @"hello";
      //让代理对象执行transparendValue动作
      [transparendValueDelegate transparendValue: value];
}
@end

类B
@interface B:UIView
      NSString* value;
@end

@implemtion B
-(void)transparendValue:(NSString*)fromValue
{
      value = fromValue;
      NSLog(@"the value is %@ ",value); 
}
@end

//下面的设置A代理委托对象为B
//在定义A和B类对象处:

A* a = [[A alloc] init];
B* b = [[B alloc] init];
a. transparendValueDelegate = b;//设置对象a代理为对象b

这样在视图A和B之间可以通过委托来传值!

下面这个例子委托有两类:
1、一个视图类对象的代理对象为父视图,子视图用代理实现让父视图显示别的子视图
2、同一父视图下的一个子视图为另一个子视图的代理对象,让另一个子视图改变自身背景色为给定的颜色
===============================================
规范格式如下:
@protocol TransparendValueDelegate;

@interface A:UIView
id< TransparendValueDelegate > m_dTransparendValueDelegate;
@property(nomatic, retain) id m_dTransparendValueDelegate;
@end
//代理协议的声明
@protocol TransparendValueDelegat<NSObject>
{
      -(void)transparendValue:(NSString*)fromValue;
}

retainCount?

【转】iPhone 面试题解答

2011-10-11 21:34

转载自 492437598

最终编辑 492437598

1.main() {

   int a[5]={1,2,3,4,5};

   int *ptr=(int *)(&a+1); 

   printf("%d,%d",*(a+1),*(ptr-1));

}

答:2,5

     *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5
  &a+1不是首地址+1,系统会认为加一个a数组的偏 移,是偏移了一个数组的大小(本例是5个int)
  int *ptr=(int *)(&a+1);
  则ptr实际 是&(a[5]),也就是a+5
原因如下:

  &a是数组指针,其类型为 int (*)[5];
  而 指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同。
  a是长度为5的int数组指针,所以要加 5*sizeof(int)
  所以ptr实际是a[5]
  但是prt与(&a+1)类型是不一样的(这点很重要)
   所以prt-1只会减去sizeof(int*)

  a,&a的地址是一样的,但意思不一样
    a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,
    a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].

 

 

2. 以下为Windows NT下的32位C++程序,请计算sizeof的值

void Func ( char str[100] ) 

  sizeof( str ) = ? 

void *p = malloc( 100 );
sizeof ( p ) = ?

 

这题 很常见了,Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等 操作,可以被修改。Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof ( p ) 都为4。


 

 

 

 

3.还是考指针,不过我对cocoa的代码还是不太熟悉

大概是这样的

- (void)*getNSString(const NSString * inputString)

{

      is a main test\n";

     return ;

}

-main(void)

{

 

NSString ";

 

 NSString *aString = [NSString stringWithString:@"%@",getNSString(a)];

 

 NSLog(@"%@\n", aString);

}

 

最后问输出的字符串:NULL,output在 函数返回后,内存已经被释放。

 

 

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

 

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 
我在这想看到几件事 情: 
?; #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等) 
?; 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
 
?; 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。 
?; 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。

 

 

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

 


#define MIN(A,B) ((A) <= (B) ? (A) : (B)) 

个测试是为下面的目的而设的: 
?;
标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方
法,
对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。 
?;
三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比 if-then-else 更优化的代码,了解这个用法是很重要的。
 

?; 懂得在宏中小心地把参数用括号括起来 
?; 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事? 
 
least = MIN(*p++, b);

 

 

结果是:
((*p++) <= (b) ? (*p++) : (*p++))
这个表达式会产生副作用,指针p会作三次++自增操作。
6. 写一个NSString类的实现

+ (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding;

+ (id) stringWithCString: (const char*)nullTerminatedCString
            encoding: (NSStringEncoding)encoding
{
  NSString  *obj;

  obj = [self allocWithZone: NSDefaultMallocZone()];
  obj = [obj initWithCString: nullTerminatedCString encoding: encoding];
  return AUTORELEASE(obj);
}

7.obj-c有多重继承么?不是的话有什么替代方法?


cocoa 中所有的类都是NSObject 的子类

多继承在这里是用protocol 委托代理 来实现的
你不用去考虑繁琐的多继承 ,虚基类的概念.
ood的多态特性  在 obj-c 中通过委托来实现.

9.关键字const有什么含意?修饰类呢?static的作 用,用于类呢?还有extern c的作用

 

const 意味着"只读",下面的声明都是什么意思? 
const int a; 
int const a; 
const int *a; 
int * const a; 
int const * a const;

 

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指 针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改 的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

 

结论:

?; 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果
你曾花很多 时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清
理的。) 
?; 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。  
?; 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。 
 

(1)欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初
始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指
定为 const;
(3)在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左值”。

关键字volatile有什么含意?并给出三个不同的例子。

 

一个定义为 volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到
这个变量时必须 每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 

?; 并行设备的硬件寄存器(如:状态寄存器) 
?; 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 
?; 多线程应用中被几个任务共享的变量

 

?; 一个参数既可以是const还可以是volatile吗?解释为什么。 
?; 一个指针可以是volatile 吗?解释为什么。 

下 面是答案: 
?; 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。 
?; 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。 

 

 

static 关键字的作用:

 

(1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值;
(2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明
它的模块内;
(4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。

extern "C" 的作用

 

(1)被 extern "C"限定的函数或变量是 extern 类型的;

       extern 是 C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,
其声明的函数和变量可以在本模块或 其它模块中使用。

(2)被 extern "C"修饰的变量和函数是按照 C 语言方式编译和连接的;

 

extern "C"的惯用法

(1)在 C++中引用 C 语言中的函数和变量,在包含 C 语言头文件(假设为 cExample.h)时,需进
行下列处理:
extern "C" 

#include "cExample.h" 

而在 C 语言的头文件中,对其外部函数只能指定为 extern 类型,C 语言中不支持 extern "C"声明,
在.c 文件中包含了 extern "C"时会出现编译语法错误。

(2)在 C 中引用 C++语言中的函数和变量时,C++的头文件需添加 extern "C",但是在 C 语言中不
能直接引用声明了 extern "C"的该头文件,应该仅将 C 文件中将 C++中定义的 extern "C"函数声明为
extern 类型。

10.为什么标准头文件都有类似以下的结构? 
   #ifndef __INCvxWorksh 
   #define __INCvxWorksh 
   #ifdef __cplusplus 
   extern "C" { 
   #endif 
   /*...*/ 
   #ifdef __cplusplus 
   } 
   #endif 
   #endif /* __INCvxWorksh */

显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用
是防止该头文件被重复引用。

 

11.#import跟#include的区别,@class呢?

 

 @class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文 件中还是需要使用#import

而#import比起#include的好处就是不会引起交叉编译

12.MVC模式的理解

MVC设计模式考虑三种对象:模型对象、视图对象、和控制器对象。模型对象代表 特别的知识和专业技能,它们负责保有应用程序的数据和定义操作数据的逻辑。视图对象知道如何显示应用程序的模型数据,而且可能允许用户对其进行编辑。控制 器对象是应用程序的视图对象和模型对象之间的协调者。

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



进程和线程都是由操作系统所体会的程序运行的基本 单元,系统利用该基本单元实现系统对应用的并发性。

程和线程的主要差别在于它们是不同的操作系统资源 管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变 量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一 些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

 

14.列举几种进程的同步机制,并比较其优缺点。

答案:  原子操作 信号量机制    自旋锁    管程,会合,分布式系统
进程之间通信的途径

答案:共享存储系统消息传递系统管道:以文件系统为基础
进 程死锁的原因

答案:资源竞争及进程推进顺序非法
死锁的4个必要条 件

答案:互斥、请求保持、不可剥夺、环路
死锁的处理

答案:鸵鸟策略、预防策略、避免策略、检测与解除死锁



15.堆和栈的区别



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

申请大小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统 预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示 overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地 址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

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

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

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

19.cocoa touch框架



iPhone OS 应用程序的基础 Cocoa Touch 框架重用了许多 Mac 系统的成熟模式,但是它更多地专注于触摸的接口和优化。UIKit 为您提供了在 iPhone OS 上实现图形,事件驱动程序的基本工具,其建立在和 Mac OS X 中一样的 Foundation 框架上,包括文件处理,网络,字符串操作等。

 

Cocoa Touch 具有和 iPhone 用户接口一致的特殊设计。有了 UIKit,您可以使用 iPhone OS 上的独特的图形接口控件,按钮,以及全屏视图的功能,您还可以使用加速仪和多点触摸手势来控制您的应用。

 

各色俱全的框架 除了 UIKit 外,Cocoa Touch 包含了创建世界一流 iPhone 应用程序需要的所有框架,从三维图形,到专业音效,甚至提供设备访问 API 以控制摄像头,或通过 GPS 获知当前位置。Cocoa Touch 既包含只需要几行代码就可以完成全部任务的强大的 Objective-C 框架,也在需要时提供基础的 C 语言 API 来直接访问系统。这些框架包括:

Core Animation

通过 Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。

Core Audio

Core Audio 是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。

Core Data

提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用 或大或小的数据模型。

功能列表:框架分类

下面是 Cocoa Touch 中一小部分可用的框架:

音频和视频

  • Core Audio
  • OpenAL
  • Media Library
  • AV Foundation
  • 数据管理
  • Core Data
  • SQLite

图形和动画

  • Core Animation
  • OpenGL ES
  • Quartz 2D
  • 网络/li>
  • Bonjour
  • WebKit
  • BSD Sockets

用户应用

  • Address Book
  • Core Location
  • Map Kit
  • Store Kit

20.objc的内存管理

 

 

?  如果您通过分配和初始化(比如[[MyClass alloc] init])的方式来创建对象,您就拥
有这个对象,需要负责该对象的释放。这个规则在使用NSObject的便利方法new 时也同样适用。
?  如果您拷贝一个对象,您也拥有拷贝得到的对象,需要负责该对象的释放。
?  如果您保持一个对象,您就部分拥有这个对象,需要在不再使用时释放该对象。
反过来,
?  如果您从其它对象那里接收到一个对象,则您不拥有该对象,也不应该释放它(这个规则有少数
的例外,在参考文档中有显式的说明)。

21.自动释放池是什么,如何工作

 当您向一个对象发送一个autorelease消息时,Cocoa就会将该对 象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置 时,自动释放池就会被释放,池中的所有对象也就被释放。

1.  ojc-c 是通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
2. NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不用你管的.
3. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数 减一.

22.类工厂方法是什么

 类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中, 返回被创建的对象,并
进行自动释放处理。这些方法的形式是+ (type)className...(其中 className不包括任何前缀)。

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

类工厂方法的另一个目的是使类(比如NSWorkspace)提供单件实例。虽 然init...方法可以确认一
个类在每次程序运行过程只存在一个实例,但它需要首先分配一个“生的”实例,然后还必须释放该实例。
工厂 方法则可以避免为可能没有用的对象盲目分配内存。

 

23.单件实例是什么

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



24.动态绑定

—在运行时确定要调用的方法

 

动态绑定将调用方法的确定也推迟到运行时。在编译时,方法的调用并不和代码绑定 在一起,只有在消实发送出来之后,才确定被调用的代码。通过动态类型和动态绑定技术,您的代码每次执行都可以得到不同的结果。运行时因子负责确定消息的接 收者和被调用的方法。 运行时的消息分发机制为动态绑定提供支持。当您向一个动态类型确定了的对象发送消息时,运行环境系统会通过接收者的isa指针定位对象的类,并以此为起点 确定被调用的方法,方法和消息是动态绑定的。而且,您不必在Objective-C 代码中做任何工作,就可以自动获取动态绑定的好处。您在每次发送消息时,


特别是当消息的接收者是动态类型已经确定的对象时,动态绑定就会例行而 透明地发生。

25.obj-c的优缺点

objc优点:
  1) Cateogies
  2) Posing
  3) 动态识别
  4) 指标计算
  5)弹性讯息传递
  6) 不是一个过度复杂的 C 衍生语言
  7) Objective-C 与 C++ 可混合编程
缺点:
  1) 不支援命名空間
  2)  不支持运算符重载

  3) 不支持多重继承

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

 

26.sprintf,strcpy,memcpy使用上有什 么要注意的地方

 

 

strcpy是一个字符串拷贝的函数,它的函数原型为strcpy(char *dst, const char *src);

将src开始的一段字符串拷贝到dst开始的内存中去,结束的标志符号为 '\0',由于拷贝的长度不是由我们自己控制的,所以这个字符串拷贝很容易出错。具备字符串拷贝功能的函数有memcpy,这是一个内存拷贝函数,它的函 数原型为memcpy(char *dst, const char* src, unsigned int len);

将长度为len的一段内存,从src拷贝到dst中去,这个函数的长度可控。但 是会有内存叠加的问题。

sprintf是格式化函数。将一段数据通过特定的格式,格式化到一个字符串缓 冲区中去。sprintf格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲区的大小,造成溢出。

27. 用变量a给出下面的定义  

a) 一个整型数(An integer) 
b)一 个指向整型数的指针( A pointer to an integer) 
c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r 
d)一个有10个整型数的数组( An array of 10 integers) 
e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers) 
f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers) 
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument
 and returns an integer) 
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions t
hat take an integer argument and return an integer ) 
 
答 案是: 
a) int a; // An integer 
b) int *a; // A pointer to an integer 
c) int **a; // A pointer to a pointer to an integer 
d) int a[10]; // An array of 10 integers 
e) int *a[10]; // An array of 10 pointers to integers 
f) int (*a)[10]; // A pointer to an array of 10 integers 
g) int (*a)(int); // A pointer to a function a that  takes an integer argument and returns an integer 
h) int (*a[10])(int); // An array of 10 pointers to functions  that take an integer argument and return an integer

28.readwrite,readonly,assign,retain,copy,nonatomic 属性的作用

@property是 一个属性访问声明,扩号内支持以下几个属性:
1,getter=getterName,setter=setterName,设置setter与 getter的方法名
2,readwrite,readonly,设置可供访问级别
2,assign,setter方法直接赋值,不进行 任何retain操作,为了解决原类型与环循引用问题
3,retain,setter方法对参数进行release旧值再retain新值,所有 实现都是这个顺序(CC上有相关资料)
4,copy,setter方法进行Copy操作,与retain处理流程一样,先旧值release,再 Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。
5,nonatomic,非原子性访问,不加同步, 多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级(我是这么理解的...)。


@synthesize xxx;  来实现实际代码



*********************************

 

1Objective-C内部的实现

2CALayer和View的关系

3 http协议,tcp/ip

4 UITableView的那些元素是可以自定义的?

5 c语言的,定义变量,比如int,在什么情况下,其最大值是不同的

6 比较32位平台和64位平台不同

7 iphone app为什么会被打回来,如何避免??

8 为啥离开团队?

 

1.针对第一个问题,可以看看下面的教程

Object c研究的比较深入的教程

http://www.cnblogs.com/yaski/

 第6章写的尤其好

 

 KVO/KVC 实现机理分析

http://archive.cnblogs.com/a/1886332/

 

2.CALayer和View的关系

  一个UIView包含CALayer树,CALayer是一个数据模型,包含了一些用于显示的对象,但本身不用于显示。

CALayer相当于photoshop的一个层,很多动画可以通过设置CALayer来实现。据说有人用CALayer显示图片来播放视频。

Core animation应该是用CAlayer来实现各种动画。

这里有篇博文,介绍的还可以http://www.cnblogs.com/uyoug321/archive/2011/01/22.html


IOS面试题详解(一)

这套题目来自cocoachina的yoyokko版主大大招人时候的题目,论坛各路大神都觉得偏难。自己看了一下,发现很多是自己知道,但又说不上来的感觉。所以觉得有必要梳理完善一下,题很多,反正写到哪算哪吧!另外,因为我不是C/C++ 或写 mac “发家” 所以还是有解答不上来的,但是关于IOS方面,一定尽量解答,如果回答得有不尽入人意的地方,欢迎高手纠正。 下面先看看题目:

1.Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?

2.#import 跟#include 又什么区别 #import<> 跟 #import""又什么区别?

3.类变量的@protected ,@private,@public,@package声明各有什么含义?

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

5.MVC是什么?有什么特性?为什么在iPhone上被广泛运用?

6.对于语句NSString* testObject = [[NSData alloc] init];testObject 在编译时和运行时分别时什么类型的对象?

7.什么是安全释放?

8.为什么有些4.0独有的objective-c 函数在3.1上运行时会报错.而4.0独有的类在3.1上分配内存时不会报错?分配的结果是什么?

9.为什么4.0独有的c函数在3.1的机器上运行不会报错(在没有调用的情况下?)而4.0独有的类名在3.1的机器上一运行就报错?

10.异常exception 怎么捕获?不同的CPU结构上开销怎样?C中又什么类似的方法?

11.property中属性retain,copy,assgin的含义分别是什么?有什么区别?将其转换成get/set方法怎么做?有什么注意事项?

12.委托是什么?委托的property声明用什么属性?为什么?

13.浅拷贝和深拷贝区别是什么?...

14.Cocoa中与虚基类的概念么?怎么简洁的实现?

15.自动释放池跟GC有什么区别?iPhone上有GC么?[pool release] 和[pool drain]有什么区别?

16.

for(int index = 0; index < 20; index ++){

    NSString *tempStr = @”tempStr”;

    NSLog(tempStr);

    NSNumber *tempNumber = [NSNumber numberWithInt:2];

    NSLog(tempNumber);

}

这段代码有什么问题.?会不会造成内存泄露(多线程)?在内存紧张的设备上做大循环时自动释放池是写在循环内好还是循环外好?为什么?

17.内存管理的几条原则时什么?按照默认法则.那些关键字生成的对象需要手动释放?在和property结合的时候怎样有效的避免内存泄露?

18.在一个对象释放前.如果他被加到了notificationCenter 中.不在notificationcenter中remove这个对象可能会出现什么问题?

19.怎样实现一个 singleton的类.给出思路。

20.什么是序列化或者Acrchiving,可以用来做什么,怎样与copy结合,原理是什么?.

21.线程是什么? 有哪些注意事项.?

22.在iphone上有两件事情要做,请问是在一个线程里按顺序做效率高还是两个线程里做效率高?为什么?

23.runloop是什么?在主线程中的某个函数里调用了异步函数,怎么样block当前线程,且还能响应当前线程的timer事件,touch事件等.

24.ios平台怎么做数据的持久化?coredata和sqlite有无必然联系?coredata是一个关系型数据库吗?

25.阐述一个nil对象从interface bulider产生,到载入程序运行空间,最后被释放时所经历的生命周期.

26.notification是同步还是异步? kvo是同步还是异步?notification是全进程空间的通知吗?kvo呢?

27.kvc是什么?kvo是什么?有什么特性?

28.响应者链是什么?

29.unix上进程怎么通信?

30.timer的间隔周期准吗?为什么?怎样实现一个精准的timer?

31.UIscrollVew用到了什么设计模式?还能再foundation库中找到类似的吗?

32如果要开发一个类似eclipse的软件,支持插件结构。且开放给第三方开发。你会怎样去设计它?(大概思路)

 

iOS开发工程师笔试题(请在30分钟内做完)

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

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365ul)

1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少 秒而不是计算出实际的值,是更清晰而没有代价的。
3) 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4) 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。

2. Objective-C有多重继承么?不是的话有什么替代方法?
Dfad
cocoa 中所有的类都是NSObject 的子类
多继承在这里是用protocol 委托代理 来实现的
你不用去考虑繁琐的多继承 ,虚基类的概念.
ood的多态特性 在 obj-c 中通过委托来实现.
3. Objective-C有私有方法么?私有变量呢?
objective-c – 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法
@interface Controller : NSObject { NSString *something; }
+ (void)thisIsAStaticMethod;
– (void)thisIsAnInstanceMethod;
@end
@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end

@private可以用来修饰私有变量
在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的

4. 关键字const有什么含意?
Asdfds
const意味着”只读”,下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

结论:
•; 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果
你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清
理的。)
•; 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
•; 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

(1)欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初
始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指
定为 const;
(3)在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左值”。

5. 关键字volatile有什么含意?并给出三个不同的例子:
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到
这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
• 并行设备的硬件寄存器(如:状态寄存器)
• 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
• 多线程应用中被几个任务共享的变量

• 一个参数既可以是const还可以是volatile吗?解释为什么。
• 一个指针可以是volatile 吗?解释为什么。

下面是答案:
• 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
• 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

6. 简单阐述static 关键字的作用:
(1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值;
(2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明
它的模块内;
(4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。

8. 线程与进程的区别和联系?
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

9. 简单阐述堆和栈的区别:
asdfad
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
申请大小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

10. 简单阐述一下Objective-C内存管理:
1.当你使用new,alloc和copy方法创建一个对象时,该对象的保留计数器值为1.当你不再使用该对象时,你要负责向该对象发送一条release或autorelease消息.这样,该对象将在使用寿命结束时被销毁.
2.当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理.如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它.
3.如果你保留了某个对象,你需要(最终)释放或自动释放该对象.必须保持retain方法和release方法的使用次数相等.

11. 为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?
会引起循环引用。

12. 定义属性时,什么情况使用copy,assign,和retain?
assign用于简单数据类型,如NSInteger,double,bool,
retain和copy用于对象,
copy用于当a指向一个对象,b也想指向同样的对象的时候,如果用assign,a如果释放,再调用b会crash,如果用copy 的方式,a和b各自有自己的内存,就可以解决这个问题。
retain 会使计数器加一,也可以解决assign的问题。
另外:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。
加了atomic,setter函数会变成下面这样:
if (property != newValue) {
[property release];
property = [newValue retain];
}

13. 对象是在什么时候被release的?
引用计数为0时。
autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。对于每一个Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object(就是autorelease的对象)会被release。那什么是一个Runloop呢? 一个UI事件,Timer call, delegate call, 都会是一个新的Runloop。

14. IPhone OS有没有垃圾回收?
Objective-C 2.0也是有垃圾回收机制的,但是只能在Mac OS X Leopard 10.5 以上的版本使用。

15. ViewController 的 loadView, viewDidLoad, viewDidUnload 分别是在什么时候调用的?在自定义ViewController的时候这几个函数里面应该做什么工作?

由init、loadView、viewDidLoad、viewDidUnload、dealloc的关系说起
init方法
在init方法中实例化必要的对象(遵从LazyLoad思想)
init方法中初始化ViewController本身

loadView方法
当view需要被展示而它却是nil时,viewController会调用该方法。不要直接调用该方法。
如果手工维护views,必须重载重写该方法
如果使用IB维护views,必须不能重载重写该方法

loadView和IB构建view
你在控制器中实现了loadView方法,那么你可能会在应用运行的某个时候被内存管理控制调用。 如果设备内存不足的时候, view 控制器会收到didReceiveMemoryWarning的消息。 默认的实现是检查当前控制器的view是否在使用。 如果它的view不在当前正在使用的view hierarchy里面,且你的控制器实现了loadView方法,那么这个view将被release, loadView方法将被再次调用来创建一个新的view。

viewDidLoad方法
viewDidLoad 此方法只有当view从nib文件初始化的时候才被调用。
重载重写该方法以进一步定制view
在iPhone OS 3.0及之后的版本中,还应该重载重写viewDidUnload来释放对view的任何索引
viewDidLoad后调用数据Model

viewDidUnload方法
当系统内存吃紧的时候会调用该方法(注:viewController没有被dealloc)
内存吃紧时,在iPhone OS 3.0之前didReceiveMemoryWarning是释放无用内存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式
在该方法中将所有IBOutlet(无论是property还是实例变量)置为nil(系统release view时已经将其release掉了)

在该方法中释放其他与view有关的对象、其他在运行时创建(但非系统必须)的对象、在viewDidLoad中被创建的对象、缓存数据等 release对象后,将对象置为nil(IBOutlet只需要将其置为nil,系统release view时已经将其release掉了)

一般认为viewDidUnload是viewDidLoad的镜像,因为当view被重新请求时,viewDidLoad还会重新被执行

viewDidUnload中被release的对象必须是很容易被重新创建的对象(比如在viewDidLoad或其他方法中创建的对象),不要release用户数据或其他很难被重新创建的对象

dealloc方法
viewDidUnload和dealloc方法没有关联,dealloc还是继续做它该做的事情

16. ViewController 的 didReceiveMemoryWarning 是在什么时候被调用的?默认的操作是什么?

17. 列举Cocoa中常用的几种多线程实现,并谈谈多线程安全问题的几种解决方案,什么地方会用到多线程
NSOperation NSThread
@sychonized

18. 你是怎么理解MVC的,在Cocoa中MVC是怎么实现的?
Adsfasd
MVC设计模式考虑三种对象:模型对象、视图对象、和控制器对象。模型对象代表特别的知识和专业技能,它们负责保有应用程序的数据和定义操作数据的逻辑。视图对象知道如何显示应用程序的模型数据,而且可能允许用户对其进行编辑。控制器对象是应用程序的视图对象和模型对象之间的协调者。
ViewCotroller
Xib

19. KVC,KVO
Ewe
KVC(Key-Value-Coding)
KVO(Key-Value-Observing)
理解KVC与KVO(键-值-编码与键-值-监看)

http://www.cocoachina.com/macdev/cocoa/2009/0611/221.html

k-v-o 扫盲

http://www.cnblogs.com/scorpiozj/archive/2011/03/14/1983643.html

当通过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方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。

ios开发工程师常见面试题汇总

1.Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?

2.#import 跟#include 又什么区别,@class呢; #import<> 跟 #import”"又什么区别?

3.属性readwritereadonlyassignretaincopynonatomic 各是什么作用,在那种情况下用?

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

5.MVC是什么?有什么特性?为什么在iPhone上被广泛运用?

6.对于语句NSString* testObject = [[NSData alloc] init];testObject 在编译时和运行时分别时什么类型的对象?

7.什么是安全释放?

8.为什么有些4.0独有的objective-c 函数在3.1上运行时会报错.而4.0独有的类在3.1上分配内存时不会报错?分配的结果是什么?

9.为什么4.0独有的c函数在3.1的机器上运行不会报错(在没有调用的情况下?)而4.0独有的类名在3.1的机器上一运行就报错?

10.常见的object-c的数据类型有那些, 和 c 的 基本数据类型有什么区别?如:nsinteger 和int

11.property中属性retain,copy,assgin的含义分别是什么?有什么区别?将其转换成get/set方法怎么做?有什么注意事项?

12.委托是什么?委托的property声明用什么属性?为什么?

13.浅拷贝和深拷贝区别是什么?…

14.NSString 和 NSMutableString 有什么区别?

15.自动释放池跟GC有什么区别?iPhone上有GC么?[pool release] 和[pool drain]有什么区别?

16.

for(int index = 0; index < 20; index ++){

    NSString *tempStr = @”tempStr”;

    NSLog(tempStr);

    NSNumber *tempNumber = [NSNumber numberWithInt:2];

    NSLog(tempNumber);

}

这段代码有什么问题.?会不会造成内存泄露(多线程)?在内存紧张的设备上做大循环时自动释放池是写在循环内好还是循环外好?为什么?

17.内存管理的几条原则时什么?按照默认法则.那些关键字生成的对象需要手动释放?在和property结合的时候怎样有效的避免内存泄露?

18.在一个对象释放前.如果他被加到了notificationCenter 中.不在notificationcenter中remove这个对象可能会出现什么问题?

19.怎样实现一个 singleton的类.给出思路。

20.什么是序列化或者Acrchiving,可以用来做什么,怎样与copy结合,原理是什么?.

21.线程是什么? 有哪些注意事项.?

22.在iphone上有两件事情要做,请问是在一个线程里按顺序做效率高还是两个线程里做效率高?为什么?

23.runloop是什么?在主线程中的某个函数里调用了异步函数,怎么样block当前线程,且还能响应当前线程的timer事件,touch事件等.

24.ios平台怎么做数据的持久化?coredata和sqlite有无必然联系?coredata是一个关系型数据库吗?

25.阐述一个nil对象从interface bulider产生,到载入程序运行空间,最后被释放时所经历的生命周期.

26.notification是同步还是异步? kvo是同步还是异步?notification是全进程空间的通知吗?kvo呢?

27.kvc是什么?kvo是什么?有什么特性?

28.响应者链是什么?

29.unix上进程怎么通信?

30.timer的间隔周期准吗?为什么?怎样实现一个精准的timer?

31.UIscrollVew用到了什么设计模式?还能再foundation库中找到类似的吗?

32.如果要开发一个类似eclipse的软件,支持插件结构。且开放给第三方开发。你会怎样去设计它?(大概思路)

33.线程和进程的区别和联系?

34.C和obj-c 如何混用?

35.以下每行代码执行后,person对象的retain count分别是多少
Person *person = [[Person alloc] init];   // count 1
[person retain];   // count 2
[person release];   //count 1
[person release];   //retain count = 1;

36.ViewController 的 loadView, viewDidLoad, viewDidUnload 分别是在什么时候调用的?

37.ViewController 的 didReceiveMemoryWarning 是在什么时候被调用的?

38.ios5新特性有那些?

39.谈谈你对ARC 的认识和理解?

下面从第一题开始解答:

题目:1.Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?

关于多继承:

首先 object-c不能够多继承,类似下面代码的这种方式是绝对通不过编译的.当然,你也可以把NSString前面的":"去掉再试试,呵呵!

那么有没有别的方式来替代呢?有,一种我们称之为伪继承,另一种我们可以通过ios中无处不在的@protocol委托方式来实现.

1.伪继承

     尽管再objtive-C中不提供多继承,但它提供了另外一种解决方案,使对象可以响应在其它类中实现的消息(别的语言中,一般叫方法,两者无差别). 这种解决方案叫做消息转发,它可以使一个类响应另外一个类中实现的消息。

     在一般情况下,发送一个无法识别的消息会产生一个运行时的错误,导致应用程序崩溃,但是注意,在崩溃之前,iphone运行时对象为每个对象提供了第二次机会来处理消息。捕捉到一条消息后可以把它重定向到可以响应该消息的对象。

     这个功能完全通过消息转发来实现,发送消息给一个无法处理该选择器的对象时,这个选择器就会被转发给 forwardInvocation 方法.接收这条消息的对象,用一个NSInvocation的实例保存原始的选择器和被请求的参数.所以,我们可以覆盖 forwardInvocation 方法,并把消息转发给另外一个对象.

1.1 实现消息转发功能

   在给程序添加消息转发功能以前,必须覆盖两个方法,即methodSignatureForSelector: 和 forwardInvocation:。methodSignatureForSelector:的作用在于为另一个类实现的消息创建一个有效的方法签名。forwardInvocation:将选择器转发给一个真正实现了该消息的对象.

例子:

1.

1 - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector

2 {

3     NSMethodSignature* signature = [super methodSignatureForSelector:selector];

4    

5     if (!signature)

6         signature = [self.carInfo methodSignatureForSelector:selector];

7    

8     return signature;

9 }

2.

1 - (void)forwardInvocation:(NSInvocation *)invocation

2 {

3     SEL selector = [invocation selector];

4    

5     if ([self.carInfo respondsToSelector:selector])

6     {

7         [invocation invokeWithTarget:self.carInfo];

8     }

9 }


 3.调用

1 Car *myCar = [Car car]; //Car为一个类

2 [(NSString *)myCar UTF8String]  //这里调用NSString中的UTF8String方,注意Car中并未实现该方法

复制代码

解释: 这里借iphone开发秘籍的例子来说明, self.carInfo是一个只读的NSString对象,存在于Car类中.例子中Car实例是无法正确的为另外一个对象(NSString)实现的选择器创建一个有效的签名。运行时当检查到当前没有有效的签名,即进入该对象(这里是myCar)的methodSignatureForSelector:方法中,此时,将在这个方法中对每个伪继承进行迭代并尝试构建一个有效的方法签名的机会.例如代码中,当myCar调用UTF8String时,由于无法从当前对象中获得消息,转入第二次机会捕捉消息,首先进入methodSignatureForSelector:方法,采用迭代的方式为当前被调用的方法创建一个有效的签名,得到签名后,转入forwardInvocation:方法对其调用的方法(UTF8String)进行实现.  forwardInvocation:中,首先获得调用的方法(UTF8String),判断self.carInfo(一个nsstring对象)能否响应该方法,如果可以,将调用UTF8String对象的目标转换为self.carInfo对象. 这样 ,我们就实现了多继承,呵呵!!

注:如果您仍有疑问,可访问苹果的官方文档查询消息转发相关内容:

地址 http://www.apple.com.cn/developer/mac/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/chapter_6_section_1.html#//

    apple_ref/doc/uid/TP40008048-CH105-SW1

2.委托

在IOS中委托通过一种@protocol的方式实现,所以又称为协议.协议是多个类共享的一个方法列表,在协议中所列出的方法没有响应的实现,由其它人来实现.这叫好比我想买个手机,所以我有个buyIphone 方法,但是我不知道谁那买手机,所以把这个需求发布出去(比如公布在网站上),如果有卖手机的商人(也就是说他能实现buyIphone这个方法)看到,他就会接受我的委托,(在商人自己的类中实现<XXXdelegate>),那么我的委托对象就指向了这个商人..当我要买手机的时候,直接找他就行了.

例如:

@protocol MyDelegate

-(void)buyIphone:(NSString *)iphoneType money:(NSString *)money;

@end

@interface My : NSObject

{

    id<MyDelegate> deleage;

}

@property(assign,nonatomic)id<MyDelegate> delegate;

@end

代码中声明了一个协议 名叫Mydelegate,在其中有一个buyIphone方法,即一个委托项。当我要购买手机的时候只需要通过delegate 调用 BuyIphone方法即可.

如下:

-(void)willbuy

{

    [delegate buyIphone:@"iphone 4s" money:@"4888"];

 

}

我不必关心谁现实了这一委托,只要实现了这个委托的类,并且buyIphone是声明的委托中必须实现的方法,那么就一定能够得到结果.

例如:商人类实现了这一委托(用<Mydelegate>表示实现)

#import <Foundation/Foundation.h>

#import "My.h"

@interface Business : NSObject<MyDelegate>

@end

然后在 @implementation Business 中调用 buyIphone方法

#import "Business.h"

 

@implementation Business

 

-(void)buyIphone:(NSString *)iphoneType money:(NSString *)money

{

    NSLog(@"手机有货,这个价钱卖你了,发货中!!");

}

@end

就ok啦。这样是不是也模拟了多继承呢?通过委托,其实你也就摆脱了去考虑多继承方面的事情,从而关注当前类。

转载于:https://www.cnblogs.com/iteching/p/4068770.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值