OC加强Day03 - block与协议

来源:互联网 发布:怎么破解红蜘蛛软件 编辑:程序博客网 时间:2024/05/16 06:38

        • 非正式协议 实际上还是分类
        • 延展 Extension
            • 一句话解释 是1个特殊的分类所以延展与分类一样是类的一部分
        • block 是一个数据类型
          • 数据类型的作用
          • block类型的变量的声明
          • 声明block变量的语法
          • block变量的初始化
          • 执行存储在block变量中的代码
          • 关于block的简写
          • 简化block定义
          • block 访问外部变量
        • block作为函数的参数
        • block与函数
          • block作为函数的返回值
      • 协议
        • 协议的基本使用

非正式协议–> 实际上还是分类.

  1. 分类: 我们刚才学习分类,都是为自己的类写分类.
: 思考: 能不能为系统自带的类写分类呢?
可以的.
为系统自带的类写分类.就叫做非正式协议.
  1. 什么时候你才要去为系统自带的类写1个分类?

系统的那个类,写的挺好.但是如果能够再多加1个方法就完美了.这个时候,就可以使用分类还给它加1个方法就好了.

延展: Extension

一句话解释: 是1个特殊的分类.所以,延展与分类一样是类的一部分.
  1. 特殊的地方

    1. 延展是1个匿名的分类,没有名字.
    2. 延展只有声明没有实现.和本类共享1个实现
  2. 延展的声明.@interface 本类名 () @end

  1. 延展没有单独的实现.和本类共享1个实现
  2. 将方法声明写在延展中 将方法的实现写在本类的实现中.
  1. 如何添加1个延展.
    延展虽然是匿名的没有名字,但是还是有文件名
延展只有1个.h文件. 没有.m文件. 因为延展没有单独的实现.和本类共享1个实现.
  1. 延展的使用注意.
  1. 分类中只能新增方法.可以写@property但是只会生成getter setter的声明.
  2. 延展中可以写属性.
  3. 也可以写@property. 会自动的生成私有属性,getter setter的声明. getteer setter的实现.方法声明肯定也是可以的.
  1. 延展的作用: 肯定不是来把1个类分为多个模块的.因为实现和本类共享1个实现.

也肯定不是来扩展1个类的.因为实现和本类共享1个实现.你新增1个方法 方法的实现还要写在本类的实现中.

  • 1). 思考

    1. 要为1个类写1个私有的@property.
    2. 什么时候私有的@property?
    3. 生成的getter setter方法要是私有的.
  • 延展.

        //100%的情况下,延展不会独占1个头文件.        //延展都是写在类的.m文件中.写在implementation上面        @imterface HMStudent ()        {            ing _age;        }        @property NSString* name;        - (void) study;        @end        //下面是.m的实现        @implementation        - (void)study        {            NSLog(@"我叫%@,今年%d岁",self.name,self->_age);        }        @end        //写在延展中的成员,都是这个类的私有成员,只能在这个类的内部访问.无法在外部访问.
  • 延展天生就是来:私有化类的成员的.

如果类中有成员需要被私有化.

    属性需要被私有化:     a. 在本类的@interface中@private    b. 在本类的@implementation中.    c. 写在延展中.

==必须将其写在延展中.==

    方法需要被私有化:    只写实现不写声明.    建议: 私有方法仍然要写声明和实现,只不过声明写在延展中.
  • @property需要被私有化

    • @property写在延展中.
  • 如何使用.

    如果类中有私有成员, 将这些私有成员全部的写在延展中.私有属性,私有方法的声明.私有@property.写在延展中的成员,只能在类的内部访问.不能在外部访问

block 是一个数据类型

数据类型的作用
可以声明这个这个数据类型的变量,来存储数据.int num;double num;
block类型的变量的声明
  • block也是1个数据类型.

    • 所以我们也可以声明1个block类型的变量.
    • 往这个变量中存储数据.
  • block类型的变量是专门用来存储 1段代码的.

    • 这段代码可以有参数也可以返回值.
  • 存储的代码是有限定的
    • 声明变量的时候,必须指定这个变量的参数和返回值
声明block变量的语法
返回值类型 (^block变量名称)(参数列表);void (^MyBlock)();//代表声明了一个block类型的变量`^`//变量名叫做`Myblock` .//这个变量中只能存储没有返回值`(void)`//也没有参数的代码`()`

==语法怪异之处在于,变量名在中间==

int (^myBlock)(int num1,int num2);           //代表声明了1个block类型的变量,变量名加做myBlock.           //这个变量中只能存储返回值为int类型的,并且有两个整型的参数的1段代码.  
block变量的初始化

1. 初始化Block变量的原理:谢一段符合block变量要求的代码,把这段代码储存到这个block变量中

2. 书写一个block代码段的语法格式

^返回值类型(参数列表){    代码;}

3. 无参数无返回值的代码段

        ^void(){            NSLog(@"我爱你");            NSLog(@"打瞌睡的小男孩");        };        //这个时候,就可以将这段代码 通过赋值符号. 赋值给无参数,无返回值的block变量.         void (^myBlock1)();         myBlock1 =  ^void(){            NSLog(@"我爱你");            NSLog(@"打瞌睡的小男孩");         };         //代表的意义:myBlock1变量中存储了这段代码

4. 有返回值无参数的代码段.
==可以声明的同时赋值==

int (^Myblock2)() =  ^int(){    int num1 = 10;    int num2 = 20;    int num3 = num1 + num2;    return  num3;//如果代码段标识了有返回值,代码段结束之前必须要使用return返回一个数据}

5. 有返回值有参数的代码段

^int(int num1,int num2){    int num3 = num1 + num2;    return num3;}
  1. 特别强调:只能存储和这个block变量要求相同的代码段.否则就会报语法错误
执行存储在block变量中的代码

block();有参数穿参数,有返回值就;

关于block的简写
  1. 如果一个代码段没有参数,那么这个代码段的小括弧可以省略.==这个不建议省略==!!!

    声明block变量的小括弧是不可以少的

  2. 代码段的时候,可以省略返回值类型,系统也是这么用的,可以省略.

    系统根据返回的数据,自动判断返回值类型.没有返回就是void

  3. 声明block变量的时候,如果要求存储的代码段有参数,这个时候,参数可以只写类型不写名称
    int (^myBlock)(int,int);
    但是代码段必须要同时些参数的类型和名称

  4. ==我们在写block的时候,还是按照最标准的方式写比较好== 标准的总没错,没人会笑你写的标准.

简化block定义
  1. 隐隐感到不爽的地方:声明一个block变量代码太长了
  2. 想想办法将长的block定义变得短一些
  3. typedef也可以将一个长的block类型,定义为1个短类型
    为一个已经存在的数据类型,太长的时候,取一个别名.比如 typedef unsigned long NSUInteger
  4. 语法格式typedef 返回值类型 (^新类型名称)(参数列表);
    1. 举例 typedef void (^NewType)();.
    2. 这时一个无参数无返回值的block类型
    3. 如果我们要定义一个无参数无返回值的block变量,直接实用NewType就可以定义了.
    4. 举例NewType b1;
block 访问外部变量
  1. 在block代码块的内部可以定义一个和外部的变量名称相同的变量
  2. 内部可以取出外部的全局变量和局部变量的值
    1. 并且还可以修改全局变量的值,但是不能修改局部变量的值.
    2. 如果就是要修改,给外面的局部变量加一个修饰符__block,比如__block int num = 10;

block作为函数的参数

  1. block是一个数据类型,那么block就必须可以作为方法/函数的参数
  2. 如何为函数写一个block类型的参数.
  1. 只需要在函数的小括弧中声明一个block类型的变量就可以.

    void test (void (^block)());//代表,这个函数有一个无参数无返回值的block参数.
  2. 如果你觉得晕.那么可以用typedef将block类型定义的短一点

    typedef void (^NewType)();void test(NewType b1)
  1. 如何调用带block参数的函数.
  1. 如果调用的函数的参数是一个block类型的.
    那么就要求传递一个和形参的block**类型相同的block变量**.test(myBlock);
  2. 直接传递符合要求的代码段
    objc
    test( ^{
    代码段;
    });
    slmn bvc”wrap_width”: 80, //换行宽度(单位:字符)
  3. 小技巧,打开Xcode提示的情况下,选中函数中的参数提示,按下回车,自动生成代码段的格式
  1. 能实现什么效果?
  1. 函数的惨速回能将调用者的数据传递到函数的内部去使用
  2. block作为参数:可以调用者的一段代码传递到函数的内部去执行
  1. 什么时候需要将block作为参数?

1个函数代表1个相对独立的功能.
函数在完成这个功能的时候,发旋需要执行一段代码才可以据需完成
而这段代码函数内部不确定是什么样的代码
只有调用者确定
那么这个时候,就可以将block作为函数的参数
让调用者在调用这个函数的时候 把这段代码传递进来
放在这里执行

block与函数

  • 相同点
    • 都可以封装一段代码
  • 不同点
    • block是一个数据类型,可以声明变量.
    • 函数就是一个函数
      • block可以作为函数的参数
      • 函数不能直接作为函数的参数
block作为函数的返回值

99%都不会作为函数或者方法的返回值,但是是可以的.

//这样写编译器都蒙圈了.void (^)() test(){    //如果非要作为返回值,就不要这样写,用typedef定义一下.    void (^b1)() = ^{        NSLog(@"hhhhaaa");    };    return b1;}

协议

协议的基本使用

协议: protocol
1. 协议: 专门用来写方法的声明的,协议中不能写属性.

遵守了协议的类,这个类就拥有了这份协议中的所有的方法的声明,而不用自己去定义.

  1. 声明一个协议
@protocol 协议名称 <NSObject>方法阿德声明@end
  1. 协议中不能写属性.
  2. 可以写方法的声明
    也可以写(开发中不会写)@property,但是协议中的@property只会生成get set的声明,没有实现.
  1. 类遵守协议.
  1. 如果一个类想要拥有某个协议中的所有的方法的声明,就只要遵守这个协议就可以了.

    //遵守协议的格式@interface 类名 : 父类名 <协议名称>// : 冒号 是继承  <>尖括号是遵守协议@end
  2. 类遵守协议的效果:就是拥有协议的声明 ,不会自动实现.如果没有实现协议中的方法,编译的时候会给一个警告,执行的时候如果调用了没实现的方法,就会报错.如果父类遵守协议,相当于子类也继承了.

  1. 继承是单继承.协议是可以多遵守的
    “`objc
    @interface 类名 : 父类名 <协议名1,协议名2,……>
    @end
0 0
原创粉丝点击