• IOS开发学习笔记015-block和protocol


    一、block

     block 代码段

       标识是 ^

       block 和函数很像

            1、可以保存代码

            2、有返回值

            3、有形参

     格式

            返回值 (block名)(形参列表) = ^(形参列表) {代码段};

       使用方法:block名(形参);

      

    block 总结:

        1、定义     

            // 没有返回值 ,没有形参可以省略后面的小括号

            void (^myblock)() = ^

            {

                NSLog(@"****************");

            };

            myblock(); // 使用

         

            // 带参数和返回值的block

            int (^SumBlock)(int,int) = ^(int a,int b)

            {

                return a + b;

            };

        2、block访问外部变量

            block可以访问外部变量

            默认情况下,block 不能修改外部的局部变量

            给局部变量加上__block 关键字就可以在block内部修改

            int a = 10;

            __block int b = 20;

            void (^block) = ^

            {

                b = 40; // 现在修改没有问题

            }

        3、利用typdef定义block类型

            // 使用typdef简化代码

            typedef int (^MyBlock) (int, int);

            // 使用也很简单

            MyBlock block1 = ^(int a, int b)

            {

                return a * b;

            };

     代码示例:

     1 //
     2 //  main.m
     3 //  05_block
     4 //
     5 //  Created by Christian on 15/4/19.
     6 //  Copyright (c) 2015年 Christian. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 
    11 // 使用typdef简化代码
    12 typedef int (^MyBlock) (int, int);
    13 
    14 void test()
    15 {
    16     NSLog(@"****************");
    17 }
    18 
    19 int Sum(int a,int b)
    20 {
    21     return a + b;
    22 }
    23 
    24 int main()
    25 { 
    26     // 没有返回值 ,没有形参可以省略后面的小括号
    27     void (^myblock)() = ^
    28     {
    29          NSLog(@"****************");
    30          NSLog(@"****************");
    31     };
    32     myblock(); // 使用
    33     
    34     // 带参数和返回值的block
    35     int (^SumBlock)(int,int) = ^(int a,int b)
    36     {
    37         return a + b;
    38     };
    39     
    40     NSLog(@"%d",SumBlock(2,4));
    41     
    42     // 使用typdef简化代码
    43     MyBlock block1 = ^(int a, int b)
    44     {
    45         return a * b;
    46     };
    47     NSLog(@"%d",block1(5,4));
    48     
    49     
    50     // 函数指针
    51     int (*p)(int,int) = Sum; // block 和函数指针类似
    52     NSLog(@"sum is %d",p(5,7));
    53     
    54       return 0;
    55 }

     二、 protocol

      1、 定义

      @protocol MyProtocol

     1 #import <Foundation/Foundation.h>
     2 
     3 // 定义了一个名字叫@MyProtocol的协议
     4 @protocol MyProtocol
     5 
     6 @required // 要求实现方法,不实现会出现警告,默认是@required
     7 - (void)test;
     8 @optional // 可选,可实现也可不实现,没有警告
     9 - (void)test2;
    10 
    11 
    12 @end

       2、 遵守协议使用   <>   

    1 #import <Foundation/Foundation.h>
    2 #import "MyProtocol.h"
    3 
    4 // 只要一个类遵守了某个协议,就能使用这个协议里声明的方法。
    5 // <> 用来遵守协议
    6 @interface Person : NSObject <MyProtocol>
    7 
    8 @end

      3、类可以遵守多个协议 

    1 #import <Foundation/Foundation.h>
    2 
    3 @protocol MyProtocol2 
    4 
    5 @required
    6 - (void)haha2;
    7 @optional
    8 - (void)haha3;
    9 @end
    1 @interface Person : NSObject <MyProtocol, MyProtocol2> // 遵守多个协议
    2 
    3 @end

      4、基协议

      1、NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它

      2、其实还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议

      3、NSObject协议中声明很多最基本的方法,比如description、retain、release等

      4、建议每个新的协议都要遵守NSObject协议

    1 #import <Foundation/Foundation.h>
    2 
    3 @protocol MyProtocol2 <NSObject>  // 遵守基协议
    4 
    5 @required
    6 - (void)haha2;
    7 @optional
    8 - (void)haha3;
    9 @end

        生成指向特定的协议

    1     // 定义一个只能指向遵守协议MyPtotocol的指针
    2     NSObject<MyProtocol> *obj = [[Person alloc] init]; // Person遵守了MyProtocol,所以可以赋值。
    3     
    4     // id 不需要写指针
    5     id<MyProtocol> obj2 = [[Person alloc] init];
    6     

     协议也可以在.h头文件中只声明,在.m文件中包含头文件

      和@class Dog;原理一样。

      声明

      @protocol MyProtocol;

      @protocol MyProtocol, MyProtocol2;

    协议总结

      1、定义

        @protocol MyProtocol <NSObject>

          方法列表

        @end

      2、类遵守协议

        @interface Dog : NSObject <协议名1,协议名2>

          .....

        @end

      3、协议遵守协议

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

          方法列表

        @end

      4、协议中声明方法的关键字

        @required  // 要求实现,不实现会出现警告 ,默认就是这个

        @optional // 可选,可实现也可不实现,没有警告

      5、定义变量时,限制这个变量保存的对象遵守某个协议

        类名<协议名> *变量名;

        id <协议名> 变量名;

        如果没有遵守对应的协议,编译器会有警告

      6、声明一个成员变量时可以直接用协议做一个限制

        @property (nonatomic, strong) Dog<协议名> *dog;

        @property (nonatomic, strong) Person<协议名1, 协议名2> *person;

      7、当一个协议比较小,并且只运用到单独的一个类,那么可以将协议定义到某个.h文件(某个类)中。

         如果协议用到很多类中,就定义到单独的.h文件中。

      8、分类@Category定义在单独的文件中,也可以定义在原来的类中。

     三、代理模式的例子

      1、新建Person类

    //
    //  Person.h
    //  08_代理模式
    //
    //  Created by Christian on 15/4/19.
    //  Copyright (c) 2015年 Christian. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import "TicketDelegate.h"
    
    @interface Person : NSObject
    // 代理,使用id,可以指向任意对象,降低耦合性
    // 使用协议对象,可以彻底取消去代理的关系,只要遵守协议的代理都可以
    @property (nonatomic, strong) id<TicketDelegate> delegate;
    
    // 买票
    - (void)buyTicket;
    
    
    @end
    //
    //  Person.m
    //  08_代理模式
    //
    //  Created by Christian on 15/4/19.
    //  Copyright (c) 2015年 Christian. All rights reserved.
    //
    
    #import "Person.h"
    
    @implementation Person 
    
    
    - (void)buyTicket
    {
        // 找代理买票
        NSLog(@"找代理买票");
        NSLog(@"票价是:%f,票余数是:%d",[_delegate ticketPrice],[_delegate ticketNum]);
    }
    @end

       2、新建一个代理类Agent

    //
    //  Agent.h
    //  08_代理模式
    //
    //  Created by Christian on 15/4/19.
    //  Copyright (c) 2015年 Christian. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import "TicketDelegate.h"
    
    // 遵守协议,只需实现相关的方法即可
    @interface Agent : NSObject <TicketDelegate>
    
    
    @end
     1 //
     2 //  Agent.m
     3 //  08_代理模式
     4 //
     5 //  Created by Christian on 15/4/19.
     6 //  Copyright (c) 2015年 Christian. All rights reserved.
     7 //
     8 
     9 #import "Agent.h"
    10 
    11 @implementation Agent
    12 
    13 - (int)ticketNum
    14 {
    15     return 12;
    16 }
    17 
    18 - (double)ticketPrice
    19 {
    20     return 49.9;
    21 }
    22 
    23 @end

       3、新建一个协议 protocol

     1 //
     2 //  TicketDelegate.h
     3 //  08_代理模式
     4 //
     5 //  Created by Christian on 15/4/19.
     6 //  Copyright (c) 2015年 Christian. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 
    11 // TicketDelegate 协议,作为Person和代理的中间人
    12 @protocol TicketDelegate <NSObject>
    13 
    14 @required
    15 - (double)ticketPrice;
    16 - (int)ticketNum;
    17 
    18 
    19 @end

       4、主函数如下

     1 //
     2 //  main.m
     3 //  08_代理模式
     4 //
     5 //  Created by Christian on 15/4/19.
     6 //  Copyright (c) 2015年 Christian. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 #import "Person.h"
    11 #import "Agent.h"
    12 
    13 
    14 int main()
    15 {
    16     @autoreleasepool
    17     {
    18         Person *p = [[[Person alloc] init] autorelease];
    19         // 任何遵守TicketDelegate协议的代理都可以使用
    20         Agent *a = [[[Agent alloc] init] autorelease];
    21         p.delegate = a; // 找代理
    22         
    23         [p buyTicket]; // 只需买票,不用关心细节
    24         
    25     }
    26    
    27     
    28     return 0;
    29 }

    输出结果是

      2015-04-19 15:57:14.889 08_代理模式[2406:156789] 找代理买票

      2015-04-19 15:57:23.171 08_代理模式[2406:156789] 票价是:49.900000,票余数是:12

    2015-04-19 今日如此,明日依旧。

  • 相关阅读:
    mybatis <=或这个>=提示错误Tag name expecte问题解决
    Navicat 设置自增长初始值
    mysql 时间与字符串相互转换
    jquery 动态控制显隐
    mysql 查询常见时间段数据
    jquery 取得select选中的值
    java8 运算语法集
    springboot 单元测试
    idea 自动生成并跳转单元测试
    限制页面被pc端访问
  • 原文地址:https://www.cnblogs.com/songliquan/p/4438988.html
Copyright © 2020-2023  润新知