Day08-Object-C Block与协议

1. 延展: Extension

1). 是1个特殊的分类, 所以延展也是类的一部分
2). 特殊之处:
    a. 延展这个特殊的分类没有名字
    b. 只有声明没有实现, 和本类共享1个实现
2. 延展的语法
    语法:
    @interface 本类名()
    @end
    没有实现, 和本类共享1个实现
3.为类添加延展的步骤
    只有1个.h文件, 文件名称:本类名_取得文件名.h
    这个文件中只有延展的声明
    @interface Person()
    @end
4.延展的基本使用
    1). 延展的本质是1个分类, 作为本类的一部分, 只不过是1个特殊的分类, 没有名字
    2). 延展只有声明, 没有单独的实现, 和本类共享一个实现
 5. 延展和分类的区别
    1). 分类有名字, 延展没有名字, 是1个匿名的分类
    2). 每1个分类都有单独的声明和实现, 而延展只有声明, 没有单独的实现和本类共享1个实现
    3). 分类中只能新增方法, 而延展中任意的成员都可以写
    4) 分类中可以写@property 但是只会生成getter setter的声明
    延展中写@property会自动生成私有属性, 也会生成getter setter的声明和实现
6 延展的应用场景
    1). 要为类写1个私有的@property
        生成getter setter方法只能在类的内部访问, 不能再外部访问, 其实, 我们可以想: @property生成私有属性, 生成getter setter 的实现, 不要声明
    2). 延展100%的情况下不会独占1个文件, 都是将延展直接写在本类的实现文件中, 这个时候, 写在延展中的成员, 就相当于是这个类的私有成员, 只能在本类的实现中访问, 外部不能访问
    3). 什么时候使用延展?
        当我们想要为类定义私有成员的时候, 就可以使用延展, 将延展定义在这个类的实现文件中
        如果想要为类写1个真私有属性, 虽然我们可以定义在@implementation之中, 但是不要这么写, 这样很不规范. 写1个延展, 将这个私有属性定义在延展中
        如果要为类写1个私有方法,建议将声明写在延展中, 实现写在本类的实现中, 提高代码的阅读性
        如果要为类写1个私有的@property, 就直接写在延展中就可以了
    4). 延展天生就是来私有化类的成员的, 如果类的成员只希望在类的内部访问, 那么就将其定义在延展中
        如果类的成员允许被外界访问, 定义在本类的@interface中

3. block

1. OC在c的基础之上新增了一些数据类型
    BOOL
    Boolean
    class
    nil
    SEL
    id
    block
2. block是1个数据类型
    int double float char...
    既然是1个数据类型, 那么就可以声明这个数据类型的变量, 所以我们完全可以声明1个block类型的变量
    不同类型的变量可以存储不同类型的数据
    那么block类型的变量中可以存储什么样的数据呢?
    1). block是1个数据类型, 所以我们可以声明1个block类型的变量
    2). block类型的变量中专门存储1段代码, 这段代码可以有参数, 可以有返回值
3. block变量的声明
    1). 虽然block变量中是用来存储1段代码的,但是1个block变量中并不是任意的1段代码都可以存进去的
    而是有限定的
    也就是说, 在声明block变量的时候, 必须要指定这个block变量存储的代码段是否有参数, 是否有返回值
    一旦指定以后, 这个block变量中就只能存储这样的代码了
    声明了1个block变量, 返回值是void参数是1个int类型的
    这个时候, 这个block变量就只能存储无返回值并且有1个int参数的代码段
    2). 声明block变量的语法格式:
    返回值类型 (^block变量的名称) (参数列表);
        void (^myblock1)();表示声明了1个block类型的变量叫做myblock1这个变量中只能存储没有返回值没有参数的代码段
        int(^myblock2)();
        int(^myblock3)(int num1, int num2);
    3). 最重要的
    声明block变量的时候要指定这个block变量可以存储的代码段的返回值和参数描述
    一旦指定, 这个block变量中就只能存储这样的代码段了, 其他格式代码段无法存储
4. 初始化block变量
    1). 原理: 写1个符合block要求的代码段, 存储到block变量中就可以了
    2). 代码段的书写格式:
    ^返回值类型(参数列表){
            代码段;
    }
3) 写1个无参数无返回值的代码段
^void(){
    NSLog(@"dd");
}
这个时候, 我们就可以将这段代码使用赋值符号存储到, 无返回值无参数要求的block变量中
void (^myblock1)();
myblock1 = ^void(){
    ......
}
当然也可以在声明block变量的同时使用符合要求的代码段初始化
void (^myblock1)() = ^void(){
    ...
}
4).有返回值的代码段
    ^int(){
        int num1 = 10+20;
        return num1;
    };
    我们就可以将这段代码赋值给符合要求的block变量
    int(^myblock2)()=^int(){
        int num1 = 10+20;
        return num1;
    };
5). 既有参数既有返回值的代码段
^int(int num1, int num2){
    int num3=num1+num2;
    return num3;
};
所以 我们可以将这个代码赋值给符合要求的block变量
int(^myblock3)(int num1, int num2)=^int(int num1, int num2){
    int num3 = num1+num2;
    return num3;
};
6). 注意.
    赋值给block变量的代码段必须要符合block变量的要求, 否则就会报错
5, 如何执行存储在block变量中的代码段
    语法格式: block变量名();
    有参数就传参数, 有返回值就接
6. 关于block的简写
    1). 如果我们写的代码段没有返回值, 那么代码段的void可以省略.
    void(^myblock1)()=^(){
        ....
    };
    注意,代码段的返回值是void可以省略, 声明block变量的返回值无论是什么都不可以省略
    2). 如果我们写的代码段没有参数, 那么代码段的小括弧可以省略
    int(^myblock)()=^int{
        int num1 = 10+20;
        return num1;
    };
    再次强调, 是代码段可以省略
    所以, 当1个代码段即没有参数, 也没有返回值的适合, 就只写^
    void (^myblock)()=^{
        ...
    };
    3) 声明block变量的时候, 如果有指定参数
    可以只写参数的类型而不写参数的名称;
    int(^myblock)(int,int)=^int(int num1, int num2){
        int num3 = num1+num2;
        return num3;
    };
    注意:这个地方我们说的是声明block变量的时候, 再写代码段的时候类型和名称都要写.
    4).无论代码段是否有返回值, 在写代码的时候, 可以不写返回值类型, 省略
    如果在写代码段的时候, 省略了返回值,
    这个时候系统会自动的确定返回值的类型
    如果代码段中没有返回任何数据
    那么它会认为这个代码段是没有返回值的
    如果代码中有返回值, 返回的数据是什么类型
    它就会认为这个代码段是什么类型的
    建议:仍然按照我们最标准的写法来写block变量和block代码段. 因为这样可以提高代码的阅读性
7. 简化block变量的复杂定义.
    1). 问题:定义block变量的时候, 要写好大1串, 类型
    2). typedef的使用场景:将1个长类型定义为1个短类型
    3). 我们也可以使用typedef将长的block类型, 定义为1个短类型
    typedef 返回值类型(^新类型)(参数列表);
    typedef void (^NewType)();代表重新定义了1个类型叫做NewType是1个block类型, 无参数无返回值的block类型
8. 关于block块访问外部变量的问题.
    1). 在block代码块的内部可以取定义在外部的变量的值, 定义在外部的局部变量和全局变量
    2). 在block代码块的内部可以修改全局变量的值, 但是不能修改定义在外部的全局变量的值
    3). 如果你希望我们定义的局部变量可以允许在block代码的内部去修改, 那么就为这个局部变量加1个_block的修饰符.

    1. block是1个数据类型
    2. block变量是存储1段代码的
    3. block变量的shen
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值