分类 block变量

来源:互联网 发布:yy刷粉丝软件 编辑:程序博客网 时间:2024/04/28 04:11

IOS学习第25天

分类

  • 分类的使用注意

1.在分类中不能写属性,只能写方法的声明和实现

2.可以用@property,但是即使使用了@property,也不会生成属性,只会生成setter和getter方法的声明

3.在分类中可以访问本类中的真私有属性,但是只能通过setter和getter方法访问

4.分类中的方法可以和本类的方法同名,当调用的时候,不管有没有引入分类,都会调用分类的方法,如果分类中有同名的方法,只会调用最后编译的那个分类中的方法

  • 分类的使用场景

1.团队开发:多人共同写一个类的时候

2.当一个类方法非常多,功能很复杂的时候,代码和方法写到一个类中,不易于后期的维护和修改

  • 非正式协议

    就是一个分类,市委系统类添加方法的分类

  • 延展的基本使用

1.延展是什么?(Extension)    一个特殊的分类:    1>是一个匿名的分类(就是一个分类没有名字)    2>在延展中可以有属性,但是只有方法的声明,而没有方法的实现(方法的实现在本类的.m文件中)2.如何写一个延展    @interface 本类名 ()//小括号中什么都不写,这就是延展    @end    "注意:延展没有实现,和本类共用一个实现3.延展的使用注意:    1>普通的分类(有名字):        不能写属性,可以写方法的声明 和实现        普通分类中可以使用@property,只会生成方法的声明    2>延展(没有名字)        可以属性,可以有方法的声明,延展的实现在本类中        延展中可以使用@property,会有属性,也会有方法的声明和实现1.延展的作用:"生成私有的@property和私有方法    @property 会生成属性,方法声明,方法实现    1>什么是私有的@property?就是生成的属性,方法声明和实现都不让外界访问    2>怎么办?        在.m中 可以写一个延展,然后把@property 写到延展里        这样生成的_属性名,getter和setter方法的声明都在.m文件中2.延展如何使用?    1>大部分的情况下 延展都会写在本类的.m文件中,而且是写到最上面    2>然后可以在延展中写属性和方法,这些属性和方法都是私有的成员"总之:    延展就是用来私有化成员的,只要你想写一个私有的成员(属性,方法)    写就到延展中"掌握":1.延展怎么写(写到本类的.m中) 2.延展里面写什么 (你要私有化成员)

block变量

  • block变量的声明

1.block是一个数据类型,它的变量可以存一段符合要求的代码

2.block变量的声明

返回值类型 (^变量名)(参数列表)void (^block1)()int (^block2)(int num1,int num2)
  • block变量赋值/初始化
1.写一个block代码块的格式    ^返回值类型(参数列表){        //代码    };2.写一个代码块 求2个整数的和    ^int(int num1,int num2){        //代码功能就是求和//        return num1+num2;        int num3 = num1 + num2;        return num3;    };    写一个代码块 求2个整数的最大值    ^int(int num1,int num2){        //代码块 求num1,和num2中的最大值        int max = num1 > num2 ? num1 : num2;        return max;    };3.保存上面的2个代码块   3.1>//第一种    int (^blockSum)(int num1,int num2);//定义了一个变量    blockSum =   ^int(int num1,int num2){        //代码功能就是求和        //        return num1+num2;        int num3 = num1 + num2;        return num3;    };    //第二种    int (^blockSum)(int num1,int num2) =  ^int(int num1,int num2){            //代码功能就是求和            //        return num1+num2;            int num3 = num1 + num2;            return num3;        };    3.2>//第一种        int (^blockMax)(int num1,int num2);//定义了一个变量        blockMax =  ^int(int num1,int num2){            //代码块 求num1,和num2中的最大值            int max = num1 > num2 ? num1 : num2;            return max;        };        //第二种        int (^blockMax)(int num1,int num2) = ^int(int num1,int num2){            //代码块 求num1,和num2中的最大值            int max = num1 > num2 ? num1 : num2;            return max;        };4.执行block变量中的代码    格式:        block变量名字(实参列表);        需要参数就传进去        如果有返回值 就接收
  • block的简写
]    注意:"声明block变量时的小括号不能省略    代码段:"打印两句"凤姐我爱你"    ^void{        NSLog(@"凤姐我爱你");        NSLog(@"凤姐我爱你");    };2.在写代码段时可以省略返回值类型,系统会自动判断返回值的类型    1>如果这个代码段没有返回值,系统 默认会是void    2>如果这个代码段有返回值 系统会根据返回值类型 来判断代码段返回值类型二."block变量的简写1..在声明block变量时,参数可以只写类型 而不写名称    注意:"代码段中类型和名称都不可以省略    int (^blockSum)(int,int);//这里小括号中的参数名字可以省略,但是类型不能省略    ^int(int num1,int num2){        int num3 = num1 + num2;//如果这时候省略了参数的名称 那么就发求和        return num3;    };"注意:我们写代码不简写,但是你必须能看懂别人的简写方式
  • 使用typedef简化block定义
1.typedef 的作用是?    为一个已经存在的数据类型,起一个数据类型2.使用typedef简化block的定义    1>typedef的基本使用    typedef long int Lint;    int nums1[4];//int[4] nums1;    int nums2[4];//int[4] nums2;    typedef int NUM[4];    NUM nums3;//等价于 int nums3[4];    2>typedef简化block的定义    void (^blockName)(int,int);    //void (^)(int,int) blockName;==>XXX a;    语法格式://    typedef void (^)(int,int) NewType;    typedef 返回值类型 (^新类型名字)(参数列表);    typedef void (^NewType)(int,int);    这个NewType就是新类型的名字    就可以通过NewType 来定义block变量    NewType block1,block2;
  • block访问外部变量
1.block代码段内部,可以定义和外部变量名字相同的变量2.block代码段的内部,    1>可以访问外部的全局变量和局部变量的值    2>可以修改外部全局变量的值 ,但是不能修改外部局部变量    如果非要修改外部的局部变量的值,那么必须给外部这个局部变量前加上__block修饰
  • block作为函数的参数
1.block作为函数的参数的写法    //第一种方式难看 恶心    void test(返回值类型 (^block变量名)(参数列表))    {    }    //第二种    typedef void (^NewType)(int num1,int num2);//给block类型 起了一个别名 NewType    void test(NewType block1)    {    }2.在函数内部如果执行block代码    typedef void (^NewType)(int num1,int num2);//给block类型 起了一个别名 NewType    void test(NewType block1)    {        //在函数内部 如果执行block1中的代码        block1(有参数写参数,没参数拉倒);//        //有返回值就接收    }3.调用这个函数的方法    1>定义一个block变量 给他赋值    NewType block2 = ^void(int num1,int num2){            int num3 = num1 + num2;            NSLog(@"num3 = %d",num3);            };    2>调用函数        test(block2);    3>终极版        test(^void(int num1,int num2){            int num3 = num1 + num2;            NSLog(@"num3 = %d",num3);        });//有一个小技巧,调用函数的时候 如果需要传递代码块,只需要敲回车键,自动添加代码块的格式"注意:定义block变量的时候,block内的代码不会执行    "block内的代码只有在调用block的时候才执行
4.例子:1>写一个函数模拟 下载数据 解析数据 并且调用视频播放器播放2>写一个函数模拟 下载音频 解析数据 并且调用音乐播放器播放#import <Foundation/Foundation.h>void downloadAV(){    //1.下载数据    NSLog(@"正在下载数据..");    //2.解析数据    NSLog(@"正在解析数据..");    //3.调用调用视频播放器播放    NSLog(@"正在用Qviod播放视频");}void downloadMP3(){    //1.下载数据    NSLog(@"正在下载数据..");    //2.解析数据    NSLog(@"正在解析数据..");    //3.调用音乐播放器播放MP3    NSLog(@"正在用QQ音乐 播放MP3");}void downloadHM(){    //1.下载数据    NSLog(@"正在下载数据..");    //2.解析数据    NSLog(@"正在解析数据..");    //3.调用音乐播放器播放MP3    NSLog(@"正在用黑马专用播放器 播放.HM");}void downloadEverything(void (^handlerBlock)()){    //1.下载数据    NSLog(@"正在下载数据..");    //2.解析数据    NSLog(@"正在解析数据..");    //3.怎么看这个文件,需要调用者告诉我    //需要调用者给我一段代码,我执行这段代码    //所以需要调用者传递给我一段代码    //所以函数需要一个block类型的参数    handlerBlock();//执行调用则传递进来的代码}int main(int argc, const char * argv[]) {    //函数内部 不知道怎么播放某个文件,需要调用者告诉他    //调用函数 下载东西,解析东西    //    downloadEverything(^{    //        //下载视频    //        NSLog(@"调用Qviod播放");    //    });    //    downloadEverything(^{    //        //下载音乐    //        NSLog(@"用YY播放");    //    });    return 0;}
0 0