代码块对象:

通常称:代码块,是对C语言的扩展,,除了函数中的代码,其害包含变量绑定。代码块有时也被称为闭包(closure)。两种绑定类型:自动型和托管型。自动型使用的是栈中的内存,而托管绑定是通过堆创建的。

代码块和函数指针:

代码块特征:1.返回类型可以手动声明也可以由编译器推导。2.具有指定类型的参数列表。3.有用名称。

声明一个函数指针:void(*my_func)(void); 这是很基础的函数指针,它没有参数和返回结果,只要把 * 替换成 ^ 就可以把它转换成一个代码块的定义了。如:void (^my_block)(void);

在声明代码块变量和代码块实现的开头位置都要使用幂操作符。与函数中一样代码块都要放在{}中。

int (^square_block)(int number) = ^(int number) { return ( number * number);};

int result = square_block(5); printf(“Result = %d \n”,result);

这个特别的代码块获取了一个×××参数并返回了这个数字的平方,等号前面是代码块的定义,而等号后面是实现内容。

通用表达式:<returntype> (^blockname)(list of arguments) = ^(arguments){ body; };

typdef

typedf double (^MKSampleMultiply2BlockRef)(double c, double d);

这行代码定义了一个名为MKSampleMultiply2BlockRef的代码块变量,它包含两个双浮点型参数并返回一个双浮点型数值。

MKSampleMultiply2BlockRef multiply2 =^(double c, double d) {return c * d ; };

printf(“%f , %f “,multply2(4,5),multply2(5, 2));

本地变量

本地变量就是和代码块在同一范围内声明的变量。

typedef double (^MKSample) (void);

        double a = 10 , b = 20;//本地变量

        MKSample multiply = ^(){ return a * b;};

        NSLog(@"%f",multiply());//结果是200

        a = 20; b = 50;

        NSLog(@"%f",multiply());//结果仍然是200

参数变量

    代码块中的参数变量与函数中的参数变量具有相同的作用。

_block变量

    本地常量会被代码块作为常量获取到,如果想修改它们的值就必须将其声明为可修改的,例如: double c = 3;  MKSample multiply = ^(double a,double b){ return a * b;}; 此时编译器将报错。 应该将c声明为 _block double c =3;

_block类型的两个限制:没有长度可变的数组,没有包含可变长度数组的结构体。这两种变量不能声明为 _block 类型。

代码块内部的本地变量 

    这些变量与函数中的本地变量具有相同的作用。

Objective-C变量

    如果引用了一个OC对象,必须要保留它;如果通过引用访问了一个实例变量,要保留一次self(执行方法对象);通过数值访问了一个实例变量,变量需要保留。

因为代码块是对象,所以可以向他发送任何与内存管理有关的消息。在C语言级别中必须使用Block_copy()和Block_release()函数来适当管理内存。

并发性:

    如果只想让一些代码在后台运行,nsobject提供了方法,这些方法名字中都有performSelector:,最简单的就是:performSelectorInBackground:withObject:;他能在后台执行一个方法,它通过创建一个进程来运行方法。

这些方法不能有返回值,并且要么没有参数,要么只有一个参数对象。只能使用以下代码格式的一种:

-(void)myMethod;  -(void)myMethod:(id)myObject;

我们应该实现的代码如下:

-(void) myBackgroudMethod{

@autoreleasepool

{

NSLog(@“My Background Method.");

}

} 或者:

-(void) myBackgroudMethod: (id)myObject{

@autoreleasepool

{

NSLog(@“My Background Method.");

}

}

如果想要在后台执行你的方法,只需调用performSelectorInBackground:withObject:;如下:

[self performSelectorInBackground:@selector(myBackgroudMethod)withObject:nil];

调度队列:

 连续队列:dispatch_queue_t my_serial_queue;

my_serial_queue = dispatch_queue_create (“compares.MySerialQueue1”,NULL);

第一个参数是队列的名称,第二个是负责提供队列的特性,现在用不到所以是null。

如果要更改优先级,可以调用dispatch_get_global_queue方法。

三种优先级:DISPATCH_QUEUE_PRIORITY_HIGH  

DISPATCH_QUEUE_PRIORITY_LOW

DISPATCH_QUEUE_PRIORITY_DEFALUT.

使用dispatch_get_main_queue可以访问与应用程序主线程相关的连续队列。

调度队列是引用计数对象,可以用dispatch_retain()和dispatch_release()来修改计数器的值。

关于清理函数:让对象在弃用它的时候调用一个函数,就像类中的dealloc函数。

void function_name(void *context); 

void myFinalizer(viod *content){

NSLog(@“myFinalizerFunction.”);

NSMutableDictionary *theData = (__bridge_transfer NSMutableDictionary* )context;

[theData removeAllObjects];

}//该函数又叫终结器函数

__bridge_transfer关键字是把对象的内存管理由全局释放池变换成了我们的函数。

__bridge关键字是告诉ARC我们自己不管理上下文内容,交给系统来管理。

调度程序:

添加任务的最简单的方法是通过代码块,代码块必须是dispatch_block_t这样的类型,要定义为没有参数和返回值可行。 例如:typedef void (^dispatch_block_t)(void).

先添加异步代码块,这个函数有两个参数:队列和代码块。

dispatch_async(_serial_queue,^{ NSLog(@“Serial Task 1”) ; } );

如果要同步添加,使用dispatch_sync函数。函数原型:void function_name (void *argument)

等后续~~~~~~~~~


最近课程上的进度加快了很多,加之基础太弱,学起来很是吃力///