• OC语言的Block与Protocol(协议)


    Block

    ● Block封装了一段代码,可以在任何时候执⾏行
    ● Block可以作为函数参数或者函数的返回值,⽽而其本⾝身又可以带输⼊入参数或返回值。

    ● 苹果官⽅方建议尽量多⽤用block。在多线程、异步任 务、集合遍历、集合排序、动画转场⽤用的很多

    定义BLOCK变量

    Int (^SumBlock)(int,int);//有参数,返回值类型为int

    Void (^MyBlock)();//无参数,返回值类型为空

    Blocks的定义:
    int (^MySum)(int, int) = ^(int a, int b) { 

    return a+b;

     };

    定义了⼀一个叫MySum的blocks对象,它带有两个int参数,返回int。等式右边就 是blocks的具体实现

    Block可以访问局部变量,但是不能修改。 int sum = 10;
    int (^MyBlock)(int) = ^(int num) {

    sum++;//编译报错

    return num * sum;

     };
    

    如果要修改就要加关键字:__block __block int sum = 10;

     
    Blocks和函数指针对⽐比 ● 定义函数指针

    int (*myFn)(); ● 定义Blocks

    int (^MyBlocks)(int,int); ● 调⽤用函数指针

    (*myFn)(10, 20);
    

    ● 调⽤用Blocks MyBlocks(10, 20);

    Blocks的赋值
    ● 在声明的同时定义变量,然后赋值

    int (^MySum)(int,int) = ^(int a,int b) {
       return a + b;
    

    };

    ● 也可先⽤用typedef先声明类型,再定义变量进⾏行赋值 typedef int (^MySum)(int,int);
    MySum sum = ^(int a,int b) {

       return a + b;
    };

      1 //
      2 //  main.m
      3 //  04-block
      4 //
      5 //  Created by apple on 13-8-11.
      6 //  Copyright (c) 2013年 itcast. All rights reserved.
      7 //
      8 
      9 #import <Foundation/Foundation.h>
     10 
     11 /*
     12  block要掌握的东西
     13  1> 如何定义block变量
     14  int (^sumBlock)(int, int);
     15  void (^myBlock)();
     16  
     17  2> 如何利用block封装代码
     18  ^(int a, int b) {
     19     return a - b;
     20  };
     21  
     22  ^() {
     23     NSLog(@"----------");
     24  };
     25  
     26  ^ {
     27     NSLog(@"----------");
     28  };
     29  
     30  3> block访问外面变量
     31  * block内部可以访问外面的变量
     32  * 默认情况下,block内部不能修改外面的局部变量
     33  * 给局部变量加上__block关键字,这个局部变量就可以在block内部修改
     34  
     35  4> 利用typedef定义block类型
     36  typedef int (^MyBlock)(int, int);
     37  // 以后就可以利用MyBlock这种类型来定义block变量
     38  MyBlock block;
     39  MyBlock b1, b2;
     40  
     41  b1 = ^(int a, int b) {
     42     return a - b;
     43  };
     44  
     45  MyBlock b3 = ^(int a, int b) {
     46     return a - b;
     47  };
     48  */
     49 
     50 typedef int (*SumP)(int, int);
     51 
     52 
     53 typedef int (^MyBlock)(int, int);
     54 
     55 int sum(int a, int b)
     56 {
     57     return a + b;
     58 }
     59 
     60 int main()
     61 {
     62     // int (*p)(int, int) = sum;
     63     // int (*p2)(int, int) = sum;
     64     // SumP p = sum;
     65     // SumP p2 = sum;
     66     
     67     
     68     /*
     69     int (^sumBlock)(int, int);
     70     
     71     sumBlock = ^(int a, int b) {
     72         return a + b;
     73     };
     74     
     75     int (^minusBlock)(int, int) = ^(int a, int b) {
     76         return a - b;
     77     };*/
     78     
     79     MyBlock sumBlock;
     80     sumBlock = ^(int a, int b) {
     81         return a + b;
     82     };
     83     
     84     MyBlock minusBlock = ^(int a, int b) {
     85         return a - b;
     86     };
     87     
     88     
     89     MyBlock multiplyBlock = ^(int a, int b) {
     90         return a * b;
     91     };
     92     
     93     
     94     NSLog(@"%d - %d - %d", multiplyBlock(2, 4),  sumBlock(10 , 9), minusBlock(10, 8));
     95      
     96     return 0;
     97 }
     98 
     99 void test3()
    100 {
    101     int a = 10;
    102     __block int b = 20;
    103     
    104     void (^block)();
    105     
    106     block = ^{
    107         // block内部可以访问外面的变量
    108         //NSLog(@"a = %d", a);
    109         
    110         // 默认情况下,block内部不能修改外面的局部变量
    111         // a = 20;
    112         
    113         // 给局部变量加上__block关键字,这个局部变量就可以在block内部修改
    114         b = 25;
    115     };
    116     
    117     
    118     block();
    119 }
    120 
    121 // 有返回值、有形参的block
    122 void test2()
    123 {
    124     /*
    125      // 指针函数的指针
    126      int (*p)(int, int) = sum;
    127      int d = p(10, 12);
    128      NSLog(@"%d", d);
    129      */
    130     
    131     
    132     int (^sumblock)(int, int) = ^(int a, int b){
    133         return a + b;
    134     };
    135     
    136     int c = sumblock(10, 11);
    137     
    138     
    139     // 用一个block输出n条横线
    140     
    141     
    142     void (^lineBlock)(int) =  ^(int n)
    143     {
    144         for (int i = 0; i<n; i++) {
    145             NSLog(@"----------------");
    146         }
    147     };
    148     lineBlock(5);
    149 
    150 }
    151 
    152 // 没有返回值、没有形参的block
    153 void test()
    154 {
    155     // block用来保存一段代码
    156     // block的标志:^
    157     /*
    158      block跟函数很像:
    159      1.可以保存代码
    160      2.有返回值
    161      3.有形参
    162      4.调用方式一样
    163      */
    164     
    165     // 定义block变量
    166     /*
    167     void (^myblock)() = ^(){
    168         NSLog(@"----------------");
    169         NSLog(@"----------------");
    170     };*/
    171     
    172     // 如果block没有形参,可以省略后面的()
    173     void (^myblock)() = ^{
    174         NSLog(@"----------------");
    175         NSLog(@"----------------");
    176     };
    177     
    178     // 利用block变量调用block内部的代码
    179     myblock();
    180     
    181     myblock();
    182 }

    Protocol(协议)

    1、 简单使用
    1. 基本用途
    ➢ 可以用来声明一大堆方法(不能声明成员变量),不能写实现
    ➢ 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明
    ➢ 只要父类遵守了某个协议,就相当于子类也遵守了

    ➢Protocol声明的方法可以让任何类去实现,protocol就是协议。

    ➢OC不能继承多个类(单继承)但是能够遵守多个协议。继承(:),遵守协议(< >)

    ➢基协议:<NSObject>是基协议,是最根本最基本的协议,其中声明了很多最基本的方法。

    ➢协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一份协议中的方法声明。

     

    2. 格式
    ➢ 协议的编写

    @protocol 协议名称

    // 方法声明列表

    @end

    ➢ 某个类遵守协议

    @interface 类名 : 父类 <协议名称>

    @end

     

    3. 关键字

    协议中有2个关键字可以控制方法是否要实现(默认是@required在大多数情况下,用途在于程序员之间的交流

    ➢ @required:这个方法必须要实现(若不实现,编译器会发出警告)
    ➢ @optional:这个方法不一定要实现

     

    4. 协议遵守协议
    ➢ 一个协议可以遵守其他多个协议,多个协议之间用逗号 , 隔开
    ➢ 一个协议遵守了其他协议,就相当于拥有了其他协议中的方法声明

    @protocol 协议名称 <协议1, 协议2>

    @end

     

    5. 基协议
    ➢ NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它
    ➢ 其实还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议
    ➢ NSObject协议中声明很多最基本的方法,比如descriptionretainrelease
    ➢ 建议每个新的协议都要遵守NSObject协议

     

    6. 定义变量时指定协议

    // NSObject类型的对象,并且要遵守NSCopying协议

    NSObject<NSCopying> *obj;

    // 任何OC对象,并且要遵守NSCoding协议

    id<NSCoding> obj2;

     

    2、 代理设计模式
    1. 设计原理
    ➢ 有些麻烦的事情不想自己亲自做,就可以找个人帮忙做,即交给代理对象去做

     

    2. 设计原则
    ➢ 首先得拥有某个代理对象属性
    ➢ 其次要很清楚代理有哪些方法
    ➢ 最后要保证能解耦

     

    3. 实现方案
    ➢ 定义一个protocol,在其中声明一些和代理沟通的方法
    ➢ 拥有一个代理属性id<protocol> delegate
    ➢ 让代理遵守protocol
     
      1 //
      2 //  main.m
      3 //  05-protoco
      4 //
      5 //  Created by apple on 13-8-11.
      6 //  Copyright (c) 2013年 itcast. All rights reserved.
      7 //
      8 
      9 
     10 /*
     11  1.协议的定义
     12  @protocol 协议名称 <NSObject>
     13   // 方法声明列表....
     14  @end
     15  
     16  
     17  2.如何遵守协议
     18  1> 类遵守协议
     19  @interface 类名 : 父类名 <协议名称1, 协议名称2>
     20  
     21  @end
     22  
     23  2> 协议遵守协议
     24  @protocol 协议名称 <其他协议名称1, 其他协议名称2>
     25  
     26  @end
     27  
     28  3.协议中方法声明的关键字
     29  1> @required (默认)
     30    要求实现,如果没有实现,会发出警告
     31  
     32  2> @optional
     33    不要求实现,怎样不会有警告
     34  
     35  4.定义一个变量的时候,限制这个变量保存的对象遵守某个协议
     36  类名<协议名称> *变量名;
     37  id<协议名称> 变量名;
     38  NSObject<MyProtocol> *obj;
     39  id<MyProtocol> obj2;
     40  
     41  如果没有遵守对应的协议,编译器会警告
     42  
     43  5.@property中声明的属性也可用做一个遵守协议的限制
     44  @property (nonatomic, strong) 类名<协议名称> *属性名;
     45  @property (nonatomic, strong) id<协议名称> 属性名;
     46 
     47  @property (nonatomic, strong) Dog<MyProtocol> *dog;
     48  @property (nonatomic, strong) id<MyProtocol> dog2;
     49  
     50  6.协议可用定义在单独.h文件中,也可用定义在某个类中
     51  1> 如果这个协议只用在某个类中,应该把协议定义在该类中
     52  
     53  2> 如果这个协议用在很多类中,就应该定义在单独文件中
     54  
     55  7.分类可用定义在单独.h和.m文件中,也可用定义在原来类中
     56  1> 一般情况下,都是定义在单独文件
     57  2> 定义在原来类中的分类,只要求能看懂语法
     58  */
     59 
     60 #import <Foundation/Foundation.h>
     61 #import "MyProtocol.h"
     62 #import "MyProtocol3.h"
     63 #import "Person.h"
     64 #import "Dog.h"
     65 #import "Hashiqi.h"
     66 
     67 int main()
     68 {
     69     Person *p = [[Person alloc] init];
     70     p.obj = [[Hashiqi alloc] init];
     71     
     72     return 0;
     73 }
     74 
     75 void test()
     76 {
     77     //NSObject *obj = [[NSObject alloc] init];
     78     
     79     
     80     //NSObject *obj2 = @"4324324";
     81     
     82     
     83     // 要求obj3保存的对象必须是遵守是MyProtocol这个协议
     84     
     85     //NSObject<MyProtocol> *obj3 = [[NSObject alloc] init];
     86     
     87     NSObject<MyProtocol> *obj3 = [[Person alloc] init];
     88     
     89     obj3 = nil;
     90     
     91     
     92     id<MyProtocol> obj4 = [[Person alloc] init];
     93     
     94     obj4 = nil;
     95     
     96     // 要求obj5,保存的对象必须遵守MyProtocol3、并且继承了Person
     97     Person<MyProtocol3> *obj5 = [[Person alloc] init];
     98     
     99     obj5 = nil;
    100 }

    代理设计模式

     1 //
     2 //  main.m
     3 //  07-协议的应用-代理模式
     4 //
     5 //  Created by apple on 13-6-30.
     6 //  Copyright (c) 2013年 apple. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 #import "Person.h"
    11 #import "Agent.h"
    12 #import "NextAgent.h"
    13 
    14 int main(int argc, const char * argv[])
    15 {
    16 
    17     @autoreleasepool {
    18         Person *p = [[[Person alloc] init] autorelease];
    19         
    20         NextAgent *a = [[[NextAgent alloc] init] autorelease];
    21         
    22         p.delegate = a;
    23         
    24         [p buyTicket];
    25     }
    26     return 0;
    27 }
    28 
    29 void test()
    30 {
    31     //
    32     Person *p = [[Person alloc] init];
    33     // 代理
    34     Agent *a = [[Agent alloc] init];
    35     
    36     // 设置人的代理
    37     p.delegate = a;
    38     
    39     // 人打算看电影
    40     [p buyTicket];
    41     
    42     [a release];
    43     [p release];
    44 }
  • 相关阅读:
    vscode task 与 linux shell编程小记
    Python并行计算专题
    分类任务评价指标(Accuracy / Precision / Recall / F1 / ROC / AUC)
    JAVA笔记 10.04
    MySQL5.7忘记密码 Linux
    MYSQL 获取最近多少天时间列表
    Volatile 关键字的原理和实现
    安装正常APP时被小米提醒是诈骗APP不允许安装的问题
    【瞎口胡】网络流基础
    题解 Luogu P4774 [NOI2018]屠龙勇士
  • 原文地址:https://www.cnblogs.com/zhangxiaomeng1991/p/4160908.html
Copyright © 2020-2023  润新知