黑马程序员——OC之Category、Block

来源:互联网 发布:知乎大家都用真名吗 编辑:程序博客网 时间:2024/06/04 19:18

------  Java培训、Android培训、iOS培训、.Net培训期待与您交流! ------

http://www.itheima.com

  • Category:可以被翻译为类别、分类、类目等,其作用是:将一个类中的不同方法分到多个不同的文件中存储, 便于对类进行模块化设计、团队合作开发;可以在不修改原来类的基础上, 为这个类扩充一些方法。
  • 分类的命名规则:类名+扩展方法,例如:"Person+study"
  • 分类的声明格式:

@interface 待扩展的类名 (分类的名称)

//待扩展的方法

@end

  • 分类的实现格式:

@implementation 待扩展的类名 (分类的名称)

//扩展的方法

@end

  • 调用分类中的方法和调用普通类中的方法一样:[对象名 扩展的方法名];
  • 分类的使用注意事项:

1.分类的声明中不能声明实例变量,也不能使用 @property。

2.分类的方法中,可以访问类中的实例变量,例如:

@interface Person : NSObject

{

    int _age; 

}

@end

@implementation Person (base)

-(void)information{

//访问类中的实例变量

  NSLog(@"age  = %d",_age);

}

@end

3.在分类中存在和类同名的方法时,优先访问分类的方法。

4.当在多个分类中有同名的方法时,执行最后编译的那个类别的同名方法。

  • 非正式协议:所谓的非正式协议就是给NSObject或者其子类Foundation框架中的类增加的分类。例如,下面的非正式协议的使用:

给NSObject增加一个分类:

@interface NSObject (run)

-(void)eat;

@end

@implementation NSObject (run)

-(void)eat{

   NSLog(@"吃东西");

}

@end

所有继承NSObject的子类都能调用run方法或者重写run方法。

  • 延展:延展是一个特殊的分类,可叫做匿名的类别或者类扩展,延展可为一个类增加额外的原来没有的变量、方法。
  • 特点:可以在延展中定义实例变量,该实例变量默认是私有类型,作用范围只能在自身类;延展所声明的方法必须依托对应类的实现部分来实现,其没有独立的实现部分;定义在.m文件中的类扩展方法为私有的,在.h文件中声明的类扩展方法为公有方法,延展是在.m文件中声明私有方法的非常好的方式。
  • Block:是一种类型,用^操作符来声明一个Block变量,Block变量用来存放代码块
  • 四种形式:

1.无参无返回值
定义格式:void (^变量名)()=^(){代码块;};   优化后的格式:void (^block变量名)()=^{代码块;};
使用格式:变量名();
2.有参无返回值
定义格式:void (^变量名)(参数类型及个数) = ^(形参列表){代码块;};
使用格式:变量名(对应类型、个数实参);例如:

void (^plus)(int ,int )=^(int a,int b){

            NSLog(@"a + b = %d",a+b);

        };

plus(30,10);

3.有参数有返回值

定义格式:返回值类型 (^变量名)(参数类型及个数) = ^(形参列表){代码块;};
使用格式:变量名(对应类型、个数实参);例如:

int (^plus)(int a,int b ) = ^(int x,int y){

            return x+y;

        };

int sum = plus(10,20);

4.无参有返回值
定义格式:返回值类型 (^变量名)() = ^(){代码块;};
使用格式:变量名();例如:

 int (^plus)( ) = ^(){

            int x=5;

            int y=6;

            return x+y;

        };

        int sum = plus();

  • block的typedef
1.格式:typedef 返回值类型(^block变量名)(参数类型列表);例如:

  typedef int (^new)(int ,int );

        new a ;

这样我们就定义了一个类型new,用new定义了block变量a。然后我们可以给变量a赋值,如:

a = ^(int a,int b){

         return a+b;};

  • block访问外部变量:在block内部可以访问block外部的变量,并且可以修改block外部的全局变量(经测试全局变量的地址和block内部使用的全局变量的地址是同一个地址),但是不可以修改block外部的局部变量(当定义block的时候,block把外部的局部变量以const的方式复制一份到block的所在的内存中);若非要在block内部修改变量的值,则block外部的局部变量定义时要加上__block,如__block int = 10,这时修改的是block所在空间的a的值,存放在栈区的a的值是不变的,不过如果我们用__block修饰变量a,之后我们再使用变量a时,使用的是block所在空间的a值;另外block内部也可以定义和block外部的同名的变量,该变量存放在栈区,此时局部变量会暂时屏蔽外部变量的作用域。
  • block作为函数的返回值
步骤:
1.使用typedef 定义一个新的类型:

typedef int(^newType)(int ,int );

2.用新定义的类型作为函数的返回值:

newType add(){

    return ^(int a,int b){

        return  a+b;

    };

}

3.定义block变量接收函数返回的结果:

newType n = test();

4.执行block代码块:

n();

  • block作为方法的参数

//定义新类型

typedef void(^BlockType)();

//声明方法,block类型的参数

@interface Person : NSObject

-(void)test:(BlockType) block;

@end

//实现方法

@implementation Person

-(void)test:(BlockType) block{

    if (block !=nil) {  

//执行代码块

      block();       

    }

}

@end

//调用方法,block代码块作为参数传递

[p test:^{NSLog(@"hello word!");}];


0 0