ios 面试题整理

来源:互联网 发布:数据分析 尼尔森 编辑:程序博客网 时间:2024/06/11 05:14

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

#include

        #include  <>    :用于对系统文件的引用,编译器会在系统文件目录下去查找该文件。
 
        #include "xx.h":用于对用户自定义的文件的引用,编译器首先会去用户目录下查找,然后去安装目录,最后去系统目录查找。
 
       注:使用include要注意重复引用的问题:
 
       class A,class B都引用了class C,class D若引用class A与class B,就会报重复引用的错误。
 
#import
      功能与include基本相同,不过它避免了重复引用的问题。所以在OC中我们基本用的都是import。
 
@class
      @class就是告诉编译器有这个类存在,但是类是如何实现的不用告诉编译器.若.m文件用到了这个类,还是要在.m文件汇总import这个类的。
      既然这样,为什么不直接在头文件中import呢,举个例子:
      class A引用了class B,class B引用了class C.... , class A,B,C...的头文件又import了很多文件,那么 import了A的话,编译器就需要编译大量的文件,编译时间就会增加。 
 
      难道头文件中都是用@class吗?当然不是,有时也是需要#import的,那么什么时候该用什么呢?
     (1) 一般如果有继承关系的用#import,如B是A的子类那么在B中声明A时用#import;

     (2) 另外就是如果有循环依赖关系,如:A->B,B->A这样相互依赖时,如果在两个文件的头文件中用#import分别声明对方,那么就会出现头文件循环利用的错误,
     这时在头文件中    用@class声明就不会出错;
 
    (3) 还有就是自定义代理的时候,如果在头文件中想声明代理的话如@interface SecondViewController:UIViewController时应用#import不然的话会出错误,
     注意XXXXDelegate是自定义的。

2、谈谈Object-C的内存管理方式及过程?

     从一段内存被申请之后,就存在一个变量用于保存这段内存被使用的次数,我们暂时把它称为计数器,当计数器变为0的时候,

那么就是释放这段内存的时候,比如说,当在程序A里面一段内存被成功申请完成之后,那么这个计数器就从0变成了1

(我们把这个过程叫做alloc)然后程序B也需要使用这个内存,那么计数器就从1变成了2(我们把这个过程叫做retain)

紧接着程序A不再需要这段内存了,那么程序A就把这个计数器减1(我们把这个过程叫做release)程序B也不再需要这段

内存的时候,那么也把计数器减1(这个过程还是release)当系统(也就是Foundation)发现这个计数器变成了0,那么就会

调用内存回收程序把这段内存回收(我们把这个过程叫做dealloc)


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

               objective-c – 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个

       对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法

@interface Controller : NSObject { NSString *something; }

+ (void)thisIsAStaticMethod;

– (void)thisIsAnInstanceMethod;

@end

@interface Controller (private) -

(void)thisIsAPrivateMethod;

@end

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

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


4Object-C有多继承吗?没有的话用什么代替?cocoa 中所有的类都是NSObject 的子类?

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

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


5、内存管理 autoreleaseretaincopyassignset方法和含义?

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的)

6、浅拷贝和深拷贝区别是什么

 简单的来说就是,在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存,采用深拷贝的情况下,释放内存的时候就不会出现在浅拷贝时重复释放同一内存的错误.


7Cobj-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

8Objective-C中类别和类扩展的区别。

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

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

9、我们说的Objective-C是动态运行时语言是什么意思?

 多态。 主要是将数据类型的确定由编译时,推迟到了运行时。

这个问题其实浅涉及到两个概念,运行时和多态。

简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。

多态:不同对象以自己的方式响应相同的消息的能力叫做多态。意思就是假设生物类(life)都用有一个相同的方法-eat;

那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法。

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

因此也可以说,运行时机制是多态的基础?

10Objective-C堆和栈的区别?

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

申请大小:

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

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

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

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

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

11static 关键字的作用: 

(1)设置变量的存储域,函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
(2)限制变量的作用域,在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)限制函数的作用域,在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
(4)在类中的static成员变量意味着它为该类的所有实例所共享,也就是说当某个类的实例修改了该静态成员变量,其修改值为该类的其它所有实例所见;
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量

 

12obj-c的优缺点 

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

  3)不支持多重继承

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

 

13readwritereadonlyassignretaincopynonatomic属性的作用 

 1 . 可读性: readonly、readwrite
    @property(readwrite,....) valueType value;
     这个属性是变量的默认属性,就是如果你 (readwrite and readonly 都没有使用,那么你的变量就是 readwrite属性 ) ,通过加入 readwrite 属性你的变量就会有 get 和 set 方法。

     property(readonly,...) valueType value;
     这个属性变量就是表明变量只有可读方法,也就是说,你只能使用它的 get 方法。

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

3 . retain , setter 方法对参数进行 release 旧值再 retain 新值,所有实现都是这个顺序

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

5 .nonatomic ,非原子性访问,不加同步,多线程并发访问会提高性能。

     注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级 。 所以不加nonatomic 对与多线程是安全的 。

6 . retain vs. Copy
      copy   :建立一个索引计数为 1 的对象,然后释放旧对象
     retain :释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为 1


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

1.参数的不同
      使用delegate参数更加直观,使用notification参数不那么直观,所以能使用delegate的地方,尽量使用delegate
2.传递的长度
     有时候你的页面会一次跳好几个页面,那么你想把这个页面的数据传回到底层是很麻烦的事情,因为你要把delegate指针从底层界面一直传上来。
3.传递多个数据
    当你在同一个对象传递给多个对象,用delegate就不可行了。

3.什么是Notifi cation?

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

4.什么时候用delegate,什么时候用Notification?

  答:delegate针对one-to-one关系,并且reciever可以返回值给sender,notification可以针对one-to-one/many/none,reciever无法返回值给sender.所以,delegate用于sender希望接受到reciever的某个功能反馈值,notification用于通知多个object某个事件。

15、类别的作用

 1.对系统的类或自己定义的类的扩充(只是指,不能声明属性 Instance variable)  base64
    但是不能保证所有的方法都能被调用。尤其是在指定一个与系统的方法相同的方法时一定要注意。
     文件名: NSString+additions.h
     NSString+additions.m
      @interface NSString (Base64)

2. 可以声明私有方法。
    ZYViewController.m
   @interfaceZYViewController (additions)
  //{

    //    BOOL isOK;

  //}
 - (void)ok;
  @property
  @end

3.分散类体现出类别不仅可以扩充系统的方法,而且可以扩充自己定义的类。
  由第3个作用可知:不管是否使用的分散类在任何的.h文件中,我只考虑类别中的方法包裹在
  @interface className ..@end,那么我只明确将来类别中的方法就属于className这个类。
  这个是我在运用之间的总结,如果和官方的定义不同,请以官方的为准。3. 可以声明分散类的方法 (NSIndexPath)

16、关键字volatile有什么含意?

 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
  1). 并行设备的硬件寄存器(如:状态寄存器)
  2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
  3). 多线程应用中被几个任务共享的变量
  回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。
  假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
  1). 一个参数既可以是const还可以是volatile吗?解释为什么。
  2). 一个指针可以是volatile 吗?解释为什么。
  3). 下面的函数有什么错误:
  int square(volatile int *ptr)
  {
  return *ptr * *ptr;
  }
  下面是答案:
  1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
  2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
  3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
  int square(volatile int *ptr)
  {
  int a,b;
  a = *ptr;
  b = *ptr;
  return a * b;
  }
  由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
  long square(volatile int *ptr)
  {
  int a;
  a = *ptr;
  return a * a;
  }


17、关于多态性理解

 多态性是指用一个名字定义不同的函数,这函数执行不同但又类似的操作,从而实现“一个接口,多种方法”。

    多态性的实现与静态联编、动态联编有关。静态联编支持的多态性称为编译时的多态性,也称静态多态性,它是通过函数重载和运算符重载实现的。动态联编支持的多态性称为运行时的多态性,也称动态多态性,它是通过继承和虚函数实现的。

2.函数重载

    函数重载的意义在于他能用同一个名字访问一组相关的函数。

    在类中普通成员函数和构造函数都可以重载,特别是构造函数的重载(他提供了多种初使化方式)给用户更大的灵活性。在基类和派生类的函数重载有两种情况:一种是参数有所差别的重载。另一种是参数没有差别的重载,只是他们属于不同的类。

    可以用以下两种方法来区分这两种函数:用对象名加以区分;使用“类名::”加以区分。

3.运算符重载称动态多态性,他是通过继承和虚函数实现的。

    运算符重载通过创建运算符函数operator@()来实现。运算符函数定义了重载的运算符将要进行的操作,这种操作通常作用在一个类上。这样,在编译时遇到名为operator@的运算符函数(@表示所要重载的运算符),就检查传递给函数的参数的类型。

    重载运算符与预定义运算符的使用方法完全相同,它不能改变原有运算符的参数个数(单目或双目),也不能改变原有的优先级的结合性。用户不能定义新的运算符,只能从C++已有的运算符中选择一个恰当的运算符重载。

 

18frame bounds区别bound的大小改变,frame改变吗?

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

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

rame就容易理解一些:frame的(frame.origin.x,frame.origin.y)就是相对于父坐标系的偏移量。

bounds稍微有点费解,稍不留神,想的多了,就会绕进去。每个view都有一个本地坐标系统。这个坐标系统作用比较重要,比如触摸的回调函数中的UITouch里面的>坐标值都是参照这个本地坐标系统的坐标。当然bounds这个属性也是参照这个本地坐标系统来的。

其实本地坐标系统的关键就是要知道的它的原点(0,0)在什么位置(这个位置又是相对于上层的view的本地坐标系统而言的,最上层view就是 window它的本地坐标系统原点就是屏幕的左上角了)。

通过修改view的bounds属性可以修改本地坐标系统的原点位置。

所以,bounds的有这么一个特点:

它是参考自己坐标系,它可以修改自己坐标系的原点位置,进而影响到“子view”的显示位置。


19 idnilNilNULLIMPSEL代表什么?

 Objective-C中有一些很有趣的数据类型经常会被错误地理解。他们中的大多数都可以在/usr/include/objc/objc.h或者这个目录中的其他头文件中找到。下面是从objc.h中摘录的一段,定义了一些数据类型:


Objective-C中有一些很有趣的数据类型经常会被错误地理解。他们中的大多数都可以在/usr/include/objc/objc.h或者这个目录中的其他头文件中找到。下面是从objc.h中摘录的一段,定义了一些数据类型:

 // objc.h

    typedef struct objc_class *Class;
     typedef struct objc_object {
      Class isa;
    } *id;
     
    typedef struct objc_selector  *SEL;
    typedef id      (*IMP)(id, SEL, …);
    typedef signed char   BOOL;
     
    #define YES             (BOOL)1
    #define NO              (BOOL)0
     
    #ifndef Nil
    #define Nil 0  
    #endif
     
    #ifndef nil
    #define nil 0  
    #endif

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对象,这个对象的指针指向空(没有东西就是空)。

 
Nil

首字母大写的Nil和nil有一点不一样,Nil定义一个指向空的类(是Class,而不是对象)。

SEL

这个很有趣。SEL是“selector”的一个类型,表示一个方法的名字。比如以下方法:

-[Foo count] 和 -[Bar count] 使用同一个selector,它们的selector叫做count。

在上面的头文件里我们看到,SEL是指向 struct objc_selector的指针,但是objc_selector是什么呢?那么实际上,你使用GNU Objective-C的运行时间库和NeXT Objective-C的运行运行时间库(Mac OS X使用NeXT的运行时间库)时,它们的定义是不一样的。实际上Mac OSX仅仅将SEL映射为C字符串。比如,我们定义一个Foo的类,这个类带有一个- (int) blah方法,那么以下代码:

    NSLog (@"SEL=%s", @selector(blah));

    会输出为 SEL=blah。
    说白了SEL就是返回方法名。

IMP

从上面的头文件中我们可以看到,IMP定义为 id (*IMP) (id, SEL, …)。这样说来, IMP是一个指向函数的指针,这个被指向的函数包括id(“self”指针),调用的SEL(方法名),再加上一些其他参数。
说白了IMP就是实现方法。

 
Method
在objc/objc-class.h中定义了叫做Method的类型,是这样定义的:
    typedef struct objc_method *Method;
    struct objc_method {
      SEL method_name;
      char *method_types;
      IMP method_imp;
    };

20  输入结果:

      union u

{

     double a;

     int b;

     };

 

     union u2

     {

     char a[13];

     int b;

     };

 

     union u3

     {

     char a[13];

     char b;

     };

 

   cout<<sizeof(u)<<endl;

   cout<<sizeof(u2)<<endl;

   cout<<sizeof(u3)<<endl;

 

 

21socket连接和http连接的区别

 HTTP协议:简单对象访问协议,对应于应用层 ,HTTP协议是基于TCP连接的
tcp协议: 对应于传输层
ip协议: 对应于网络层
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
http连接:http连接就是所谓的短连接,即客户端向服务器端发送一次请求,服务器端响应后连接即会断掉;
socket连接:socket连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉;但是由于各种环境因素可能会是连接断开,比如说:服务器端或客户端主机down了,网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。所以当一个socket连接中没有数据的传输,那么为了维持连接需要发送心跳消息~~具体心跳消息格式是开发者自己定义的

22、创建线程的几种方式,线程同步方式。

 (1)//通过NSObject的方法创建线程
    //(这个方法会自动开辟一个后台线程,参数1:在这个后台线程中执行的方法,参数2:用于传递参数)
    [self performSelectorInBackground:@selector(banZhuanPlus) withObject:nil];


(2)//通过NSThread创建线程(参数1:方法的执行者;参数2:在线程中执行的方法;参数3:用于传递参数)
//第一步:创建线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(banZhuanPlus) object:nil];
//第二步:执行
[thread start];

[thread release];


(3)  NSOperation就是一个操作单元,用来执行方法,是一个抽象类,必须子类化或者使用系统创建好的子类(NSInvocationOperation or NSBlockOperation)
      NSOperation是最小的操作单元;只能够执行一次;

      NSInvocationOperation第一步:创建
         NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(banZhuanPlus) object:nil];
     第二步:(不设置的话不添加到队列)在主线程中执行
       [invocation start];

     NSBlockOperation第一步:创建
    NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
   [self banZhuanPlus];
    }];
   第二步:执行(在主线程中执行)
   [block start];//如果添加到队列就不要start了

这个队列会自动帮咱们创建一个辅助的线程
这个队列里面只能够添加NSOperation以及子类的对象;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:2];//设置最大并行数;
[queue addOperation:block];//只要把操作队列添加到队列中就会执行;
[queue addOperation:invocation];


  (4)  GCD,全称Grand Central Dispath,是苹果开发的一种支持并行操作的机制。它的主要部件是一个FIFO队列和一个线程池,前者用来添加任务,后者用来执行任务。
        GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行(但不保证一定先执行结束)。
        通过与线程池的配合,dispatch queue分为下面两种:
         Serial Dispatch Queue -- 线程池只提供一个线程用来执行任务,所以后一个任务必须等到前一个任务执行结束才能开始。
         Concurrent Dispatch Queue -- 线程池提供多个线程来执行任务,所以可以按序启动多个任务并发执行。


23Singleton(单例模式)实现(objectc

 

24、请写一个C函数,若处理器是Big_endian的,则返回0

     若是Little_endian的,则返回1

 

25、请用c语言实现 void* memcpy(void* desc, const void*src,int size)(注意内存重叠问题)   

0 0
原创粉丝点击