protocol -协议基础-01

  • 是什么?
    通俗的讲,协议是一系列方法的列表,
    注意: 只声明方法不实现它,实现的部分由遵守协议的那边完成。
  • 怎么使用?
    • 定义一个协议: @protocol 协议名 ... 方法声明...@end
      #import 
      @protocol PeopleProtocol 
      -(void)eat; //吃
      -(void)drink; //喝
      -(void)sleep; //睡
      @end
      
    • 让一个类去遵守这个协议. People类遵守PeopleProtocol协议
      • .h文明中,声明协议#import XX.h"
      • 遵守这个协议<协议名称>
      #import 
      #import "PeopleProtocol.h"
      @interface People : NSObject 
      @end
      
    • 在类的实现里,去实现协议里定义的方法.
      @implementation People
      - (void)drink {  NSLog(@"喝起来"); }
      - (void)eat {  NSLog(@"吃起来");   }
      - (void)sleep {
        [self eat];
        [self drink];
        NSLog(@"吃了喝,喝了睡,真爽!");
       }
      
    • 使用
      - (void)viewDidLoad {
        [super viewDidLoad];
        People *pe = [[People alloc]init];
        [pe sleep]; -- 协议的方法
        }
      

特点:

  • 一个类遵守了什么协议,就要实现这个协议规定的方法。
    • @required修饰的方法是必须实现得。(默认得)
    • @optional修饰的方法是可实现,也可不实现得。
  • 一个协议可以同时遵守多个协议。(多个协议直接用,隔开),也叫做扩展现有协议
     @protocol StaffProtocol  
     @end
    
    • "实现协议的类" 需要实现所有协议的@required修饰的方法
    • 协议继承的区别,
      • 继承只能继承一个,
      • 继承是单继承,协议可以是多协议.
      • 协议与协议之间叫遵守. 类与类之间叫继承
  • 一个类可以遵守多个协议。(多个协议直接用,隔开)
    • 遵循单个协议 @interface XX ()
    • 遵循多个协议 @interface XX ()<协议名1,协议名2>
  • 同一个协议可以被多个类遵守。
    如: StaffBoss类都遵循了PeopleProtocol协议。
    #import "PeopleProtocol.h"
    @interface Staff : NSObject 
    
    #import "PeopleProtocol.h"
    @interface Boss : NSObject 
    
  • 基协议
    基类与其同名.且基类也遵守这个协议.
    所有的自定义协议都必须直接或间接遵守这个基协议。
  • 协议的提前声名
    • 是什么?
      @protocol 协议名; 注意: 有;符号。
      可放在协议里,也可放在类里
      如: @protocol PeoPleTest;
    • 特点 ?
      仅仅是告诉这个类,有这个协议,但是协议里的内容不知道(方法有哪些,并不知道).
      注意:"实现协议的类里面", 去实现协议里的方法,
      必须在"类里面", 添加 #import 协议名.h
    • 有什么用?
      • 类似于,在类里面的@class
      • 定义在使用/遵循的下面,则需要提前声明。
        StaffProtocol协议遵循PeopleProtocol协议,
        但是PeopleProtocol还没有定义,所以就需先提前声明
        @protocol PeopleProtocol; //提前声明 - 定义在使用者这下面,则需要提前声明
        -- 协议'StaffProtocol'遵循了'NSObject'协议和'PeopleProtocol'协议
        @protocol StaffProtocol  //使用/遵循 PeopleProtocol协议
        @end
        @protocol PeopleProtocol  //定义'PeopleProtocol'协议
        @end
        
  • 协议的内部定义
    • 是什么?
      类的内部,写协议。如:BossProtocol协议,直接写在Boss类里
      @protocol BossProtocol
      - (void)collectMoney;// 筹钱
      @end
      @interface Boss : NSObject 
      @end
      
    • 什么情况下,使用内部协议?
      此协议只是给某一个类/协议使用,则可以使用内部协议
  • 限制对象类型
    • 思路

      • 假设: 老板想送奖品"MacBookPro"给优秀员工'八戒' ,有多种途径! (1. 快递奖品给"八戒"2.通过在一起的员工,转送给他....)
      • 因存在多个对象,可以完成给"八戒"送"奖品"这事。
        所以不能将对象的类型固定死。所以用id 类型
        @property (nonatomic,weak) id delegate;
      • 虽然老板有很多途径,可以将"奖品",送到"八戒"那。但是很多并不表示所有, 如: 随便叫个阿猫阿狗,肯定是无法送到!
      • 所以肯定是将"奖品"交给能送到的人手里,叫他去送!
        • 那怎样才能确保"他"是能送到的人呢?
          • 遵循了协议的对象,就是能送到的人
            @property (nonatomic,weak) id delegate;
      • 所以说协议还有个功能,限制对象的类型
    • 示例代码
      委托方: 就是委托别人干事的一方,指定协议的一方。

      #import "CourierProtocol.h" -- 引入协议文件 (带有方法)
      @protocol CourierProtocol; -- 声明协议(没有方法)
      @interface Boss : NSObject -- 注意没有'遵循协议'
      -- 任何对象,只要遵循了`CourierProtocol`协议的对象,都可以。
      @property (nonatomic,weak) id  delegate;
      -(void)talkCourier; -- 喊人
      @end
      
      #import "CourierProtocol.h"
      @implementation Boss
      -(void)talkCourier{
      -- 叫代理方去完成
      -- 注意: 是[self.delegate ...], 不是[self ....]
      if([self. delegate respondsToSelector: @selector(sendStuff:)]){
         [self.delegate sendStuff:@"奖品:MacBookPro" senderName:@"八戒" recipientName:@"你的Boss"];
        }
      }
      @end
      

      注意:

      • @protocol ...;声明是没有方法得.后面用到方法还需要#import "XX.h"
      • 上面示例中,在.h文件中有些引入协议#import "XX.h",就不需要@protocol ...;声明。
      • 如果在 "类的内部定义了协议",那么就不用写引入协议#import "XX.h"
      • 委托方在调用代理协议的方法时,要判断代理方是否实现了此方法(respondsToSelector:)
        否则报错 NSInvalidArgumentException

      代理方: 接受委托的一方;具体做事的,实现协议的一方。

      #import "CourierProtocol.h"
      @interface Courier()
      @end
      @implementation Courier
      - (void)sendStuff:(NSString *)stuffName senderName:(NSString *)senderName recipientName:(NSString *)name{
      NSLog(@"'%@'收到了,来自'%@'寄来的'%@'",senderName,name,stuffName);
      }
      @end
      

      协议: 代理方做事的守则,也就是代理方需要实现方法的申明。

      #import 
      @protocol CourierProtocol 
      - (void)sendStuff:(NSString *)stuffName senderName:(NSString *)senderName recipientName:(NSString *)name; //送东西
      @end
      

      使用

      - (void)viewDidLoad {
        [super viewDidLoad];
        Boss *boss =[[Boss alloc]init];
        -- Courier * courier = [[Courier alloc]init];  -- 快递员
        -- boss.delegate = courier;
        Staff * staff = [[Staff alloc]init]; -- 员工
        boss.delegate = staff;
        [boss talkCourier];
      }
      
    • 有什么用?
      1.降低耦合.
      2.提高扩展性.


注意:

  • 协议没有父类,并且不能定义成员变量,且没有属性。
  • 协议里的方法,都是声名,没有实现。
  • 协议是无类的(classless),任何类都可以遵守某项协议
  • 子类拥有父类协议的所有方法
    因为子类拥有父类的所有行为和方法。
    如果一个类遵守某项协议,那么它的子类也遵守该协议!
  • 协议的命名规范 : 名称+delegate, 如: UIScrollViewDelegate

也可以看看

  • delegate - 代理基础01
  • delegate - 代理基础02
  • delegate - 代理基础03
  • 没有协议的代理-简单实现
  • 代理设计模型-自定义
  • delegate - ScrollView01

来自于哪里?

  • iOS-MJ-UI基础-大神班/临散知识点/protocol -协议基础-01

你可能感兴趣的:(protocol -协议基础-01)