美文网首页
iOS开发 - 监听(NSNotificationCenter)

iOS开发 - 监听(NSNotificationCenter)

作者: 俺不是大佬儿 | 来源:发表于2021-09-29 16:54 被阅读0次
    场景:订单提交成功后pop返回上级页面,并弹出下一步功能操作的提示弹窗,多次反复提交订单发现提示弹窗会重复弹出多次,说明通知被监听到了多次。
    原因分析:详情页面提交订单成功注册发送通知给列表控制器并pop返回,列表控制器监听到通知后弹窗,这时被监听的通知并没有被移除,再重复操作,由于第一次的被监听通知没有移除,所以后续的操作会一直累加重复监听。

    通知的使用步骤:创建通知、发送通知、移除通知

    监听通知有两种方法:
    1. - (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject

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

    建议在viewDidLoad方法中创建和监听通知,因为此方法只走一次可防止重复创建

    一、- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject方法

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        #1.注册通知监听
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(publishFindGoodsSuccessNotAc:) name:@"PublishPreciseProcurementSuccessNotification"object:nil];
    }
    #2.监听通知执行方法
    - (void)publishFindGoodsSuccessNotAc:(NSNotification *)not{
         NSLog(@"弹窗");
    }
    
    #3.发送通知(通知发送时可传参)
    [[NSNotificationCenter defaultCenter]  postNotificationName:@"PublishPreciseProcurementSuccessNotification" object:@1];
    
    #4.移除通知
    //移除通知一般在dealloc中实现,因为应用支持手势返回,滑回一半又返回等操作,在页面真正销毁的时候移除最合适
    //移除有两种方法,一个是移除当前页面所有的通知,一种移除指定的通知,如下:
    - (void)dealloc{
         // 移除当前控制器所有通知
        [[NSNotificationCenter defaultCenter] removeObserver:self];
        //移除名为@"PublishPreciseProcurementSuccessNotification"的那个通知
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"PublishPreciseProcurementSuccessNotification"object:nil];
    }
    
    

    实际中发现dealloc方法有时会不走,一般有以下三种原因可以参考排查

    1. ViewController 中有Block,Block里面存在强引用;
    2. ViewController 中有关的代理 ,delegate的属性应该用assign/weak修饰;
    3. ViewController 中存在NSTimer ,计时器没有及时销毁;

    二、- (id <NSObject>)addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block方法

    该方法有个block,要操作的步骤可以直接写在block里面 使用较第一种方法方便

    
    ///声明通知观察者
    @property (weak,   nonatomic) id preciseObserve;
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
    
        #1.注册通知监听
        //Name: 通知的名称
        //object:谁发出的通知
        //queue: 队列,决定 block 在哪个线程中执行, nil 在发布通知的线程中执行
        //usingBlock: 只要监听到通知,就会执行这个 block
    
        #该方法有个block,要操作的步骤可以直接写在block里面 使用较第一种方法方便
    
        self.preciseObserve = [[NSNotificationCenter defaultCenter]  addObserverForName:@"PublishPreciseProcurementSuccessNotification"object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
            @strongify(self);
            [self publishFindGoodsSuccessNotAc:note];
        }];
    }
    
        #2.发送通知(与第一种方法相同)
    
        #3.移除通知
    - (void)dealloc {
        //移除观察者 preciseObserve
        [[NSNotificationCenter defaultCenter] removeObserver:self.preciseObserve];
    }
    
    通过比较移除的方法,可以知道,为什么第二种创建通知方法时要有一个id类型的观察者接收值,不要用第一种的注销方法,这也是我出现重复弹框bug的原因,我创建的时候没用一个观察者接收,直接写:
     //用第二种创建监听方法,错误的移除示例
     [[NSNotificationCenter defaultCenter] addObserverForName:@"PublishPreciseProcurementSuccessNotification" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
            NSLog(@"收到通知");
            @strongify(self);
            [self publishFindGoodsSuccessNotAc:note];
     }];
    

    导致通知未移除而重复创建,执行方法一次比一次多,而移除的时候用

    - (void)dealloc{
        //移除名为PublishPreciseProcurementSuccessNotification的通知
        [[NSNotificationCenter defaultCenter] removeObserver:self.preciseObserve name:@"PublishPreciseProcurementSuccessNotification" object:nil];
    }
    
    需要注意销毁应该是哪里监听哪里销毁,不要在发送通知的控制器里执行销毁!!

    欢迎大佬儿来指正纠错,共同学习!!

    相关文章

      网友评论

          本文标题:iOS开发 - 监听(NSNotificationCenter)

          本文链接:https://www.haomeiwen.com/subject/lhejnltx.html