OC-代理、通知、block使用与使用差别

本文介绍了iOS开发中的几个核心概念:protocol(协议)、NSNotification(通知)和block(代码块)。详细解释了它们的定义、使用方法及注意事项,并对比了代理、通知和block在实际应用中的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、在IOS开发中,有一个非常常见的定义,就像property一样,它就是protocol

下面我就protocol做一个初层次的概述;

1、首先,讲讲protocol的定义;作为一个OC里面的一个专门用来定义协议的关键字,通常格式为:@protocol  协议名称 <NSObject>  .....     @end; 

2、如何遵守协议;它包括了:

1)类的遵守协议;比较常见的格式为:

@interface 类名 :父类 <协议1,协议2>    ..........   @end    

2)协议遵守协议;比较常见的格式为:

@protocol 协议名称 <其他协议>.................  @end

3、协议的方法实现中声明关键字

1)@required  这后面的方法表示一定要实现的。如果没有写明,默认一定要实现

2)@optional 这后面的方法表示不一定要实现的,可以选择性实现

4、在定义一个变量的时候,可以用协议来限制变量,使这变量遵循某一协议。例如,NSObject <协议名称> *变量名


5、@property 中声明的属性也可以用一个需要遵守协议的限制。例如,@property (nonatomic,stong)类名 *属性名


6、protocol定义的协议以作为一个独立的协议单独使用,也有可以在一个类中使用。但是要注意,当多个类都要用时,只能单独放在一边。而只有一个类用才可以写在这个类一起。


7、有一个关键字的使用与protocol有相似一处,它就是分类。分类也可以单独使用,也可以放在类一起,但是也同时也要注意,多个要用时,也只能单独放一个文件。

综上述,protocol在我们IOS中很常见,经常使用,创建一些合理的协议,对整个程序的架构有很大帮助。所以需要更深入的去学习protocol的相关用法,最后使自己成为一个优秀的IT人!

二、通知

1、通知中心(NSNotificationCenter)实际是在程序内部提供了一种广播机制。把接收到的消息,根据内部的消息转发表,将消息转发给需要的对象。这句话其实已经很明显的告诉我们要如何使用通知了。第一步:在需要的地方注册要观察的通知,第二步:在某地方发送通知。(这里注意:发送的通知可能是我们自定义的,也可能是系统的)。

2、通知的使用:
发通知:

- (void)postNotification:(NSNotification *)notification;

- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;

- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary*)aUserInfo;

一般来说,发送通知主要是上面的三个方法;aName,通知的名称,一般取一个与这通知的作用类似的名称,并且给一个宏定义,以防接收通知时写错名称。

anObject,传递的一个对象(当然也包括对象中的各个属性)。aUserInfo,这主要是传递值的字典(注意非对象存字典的时候,需要转化为对象才能存),通知传值一般情况下都用它来传。

接收通知:

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject;

- (id <NSObject>)addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullableNSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block;

使用以上方法接收通知的时候,第一个方法的接收参数等操作在aSelector中处理。在处理过程,selector 的方法实现中 eg:- (void)receive:(NSNotification *)notification ,NSNotification有object和userInfo两个属性处理其传过来的对象和值。第二个主要是要在其block中处理其传过来的对象和值,当然我们一般把queue 定义在主线程里面。其实是用过程中建议使用这个方法。

3、使用注意事项

在接收通知的时候,我们一般是在主线程操作的,有时候,有特殊需求要在次线程中处理的,但是要注意,操作UI的时候要回到主线程。

在接收完通知的地方都需要把监听在dealloc移除、移除、移除(重要的事情说三遍):

- (void)removeObserver:(id)observer;

- (void)removeObserver:(id)observer name:(nullable NSNotificationName)aName object:(nullable id)anObject;


三、block

1、一个类似C语言函数的待执行的代码块。

  •  int outA = 8;  
  •     int (^myPtr)(int) = ^(int a){ return outA + a;};  
  •     //block里面可以读取同一类型的outA的值  
  •     int result = myPtr(3);  // result is 11  
  •     NSLog(@"result=%d", result);  

    2、使用过程中我们可以把它当成一个参数。

    1. -(void)objcMethod:(int(^)(int))square;  //square参数的类型是int(^)(int)  


    3、使用注意

    A、block在读取内存变量的时候,如果是一个非对象量时,它只是复制其值,而不会改变其原值,eg

    1. {  
    2.     int outA = 8;  
    3.     int (^myPtr)(int) = ^(int a){ return outA + a;}; //block里面可以读取同一类型的outA的值  
    4.       
    5.     outA = 5;  //在调用myPtr之前改变outA的值  
    6.     int result = myPtr(3);  // result的值仍然是11,并不是8  
    7.     NSLog(@"result=%d", result);  
    8. }  

     

    B、在读取一个对象变量的时候,它是读取其内存地址,因此在block里面做变量的赋值或者改变值的时候,会改变其原来的值,eg 

    1. {  
    2.     NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];  
    3.     int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);  
    4.     NSLog(@"test array :%@", mutableArray); // 输出的值是@{@"one", @"two"
    5. }

    C、如果我们要在block中改变一个非对象量的时候,我们可以用__block 来修饰这个量。实际上这样一修饰,它就成为了Block Variable类型,eg 

    1. {  
    2.     __block int num = 5;  
    3.       
    4.     int (^myPtr)(int) = ^(int a){return num++;};  
    5.     int (^myPtr2)(int) = ^(int a){return num++;};  
    6.     int result = myPtr(0);   //result的值为5,num的值为6  
    7.     result = myPtr2(0);      //result的值为6,num的值为7  
    8.     NSLog(@"result=%d", result);    
    9.   
    10. }  


    D、注意使用block里面的循环问题。一般我们如果发现了循环,我们可以对其中的self 用weakSelf来代替,eg

    __weak __typeof(&*self)weakSelf = self 


    四、代理、通知、block使用差别

    1、代理和block的使用都大同小异的,但是实际使用过程我们还是有一定的区别:

    代理,使用的时候比较繁琐,必须有三大步骤写完整,但是我们在提供给第三方使用的时候,代理更加具有可读性和可使用性(比如我们写一个供别人使用的框架或者什么的时候,代理就是一个很好的选择)

    block,使用方便,还可以当参数传,但是如果大量的用会增加代码的可读性

    代理是一对一的,设置 delegate 属性,在需要的时候,通过 delegate 调用 selector 方法!

    通知是一对多的,只要发生事件,会以广播的形式,通知所有的监听者

    通知中心/发布通知的对象不需要知道谁是监听者,发布对象和监听者之间的耦合度很低

    监听者需要知道通知的名称字符串,如果发布者还传递 userInfo 字典,监听者同时需要知道字典的键名  --(技巧:在 OC 的框架中,如果定义通知,通常通知的名字包含"Notification"字样,同时 key 会和 通知定义在一起!)

    通知监听方法不能有返回值!

    代理可以有返回值!

    通知,一般说来能不用就不用,他的性能比较低。在我们不同的控制器之间的传值(逆传)可以选择用它。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值