ios开发中nsnotification的便利使用(代码片段)

JackLee18 JackLee18     2023-03-23     334

关键词:

   NSNotification的使用有几个痛点:1)无法自动释放监听;2)重复添加监听没有提示;3)使用不够便利。最近在推动项目中使用swift,将原来的OC代码写了一个swift版本分享给大家。

实现原理

OC版本主要通过NSObject的分类,动态绑定一个数组,每次添加通知的监听,都会创建一个proxy对象,将这个proxy对象添加到刚才动态添加的数组中。这个proxy是真正的通知的监听者。并且响应处理通知的block,释放的时候会移除监听。能够实现proxy对象释放时,自动移除监听。一个对象被释放时,动态绑定的proxy的数组也会被释放,数组里面的proxy元素也会被释放。这样监听就被自动移除了。

OC版本代码如下:

/**
 监听通知事件。对通知扩展封装,避免循环引用。

 @param name 通知名称
 @param block 通知事件处理
 */
- (void)jk_observeNotificationForName:(NSString *)name
                           usingBlock:(void(^)(NSNotification *notification))block;

/// 监听一组通知事件
/// @param names 通知名称数组
/// @param block 通知事件处理
- (void)jk_observeNotificationForNames:(NSArray<NSString *> *)names
                            usingBlock:(void(^)(NSNotification *notification))block;

/// 发送通知
/// @param name 通知的名字
- (void)jk_postNotification:(NSString *)name;

/// 发送通知
/// @param name 通知的名字
/// @param object object
/// @param userInfo userInfo
- (void)jk_postNotification:(NSString *)name object:(nullable id)object userInfo:(nullable NSDictionary *)userInfo;
/**
 移除通知的监听

 @param name 通知名称
 */
- (void)removeNotification:(NSString *)name;

swift版本代码如下:

swift版本通过创建协议,并为协议添加默认实现,来达到OC版本分类的效果。

//
//  JKFastNotificationProtocol.swift
//  JKNoticationHelper_Swift
//
//  Created by JackLee on 2021/9/8.
//

import Foundation
//提供简便使用,不会自动移除通知的监听
public protocol JKFastNotificationProtocol 
    
    /// 添加通知的监听
    /// - Parameters:
    ///   - name: 通知的名字
    ///   - block: 处理通知的回调
    func jk_observeNotificaion(name:String, block:@escaping ((_ notification:Notification) -> Void)) ->Void
    
    /// 添加一组通知的监听
    /// - Parameters:
    ///   - names: 通知的名字组成的数组
    ///   - block: 处理通知的回调
    func jk_observeNotificaions(names:Array<String>,block:@escaping ((_ notification:Notification) -> Void)) ->Void
    
    /// 移除通知的监听
    /// - Parameter name: 通知的名字
    func jk_removeObserveNotification(for name:String) ->Void
    
    /// 发送通知
    /// - Parameter notificationName: 通知名字
    func jk_postNotification(notificationName:String) ->Void
    
    /// 发送通知
    /// - Parameters:
    ///   - notificationName: 通知名字
    ///   - object: 发送的对象
    ///   - userInfo: 用户信息
    func jk_postNotification(notificationName:String, object:Any?, userInfo:[AnyHashable : Any]?) ->Void
    
    
    var notificationProxyList: [JKFastNotificationProxy] get set


private struct JKFastNotificationProtocolAssociatedKey 
    static var identifier: String = "notificationProxyList_identifier"


public extension JKFastNotificationProtocol 
    
    var notificationProxyList: [JKFastNotificationProxy] 
        get objc_getAssociatedObject(self, &JKFastNotificationProtocolAssociatedKey.identifier) as? [JKFastNotificationProxy] ?? [] 
        set  objc_setAssociatedObject(self, &JKFastNotificationProtocolAssociatedKey.identifier, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 
    
    
     func jk_observeNotificaion(name:String, block:@escaping ((_ notification:Notification) -> Void)) ->Void 
        jk_observeNotificaions(names: [name], block: block)
    
    
     func jk_observeNotificaions(names:Array<String>,block:@escaping ((_ notification:Notification) -> Void)) ->Void 
        var tmpSelf = self
        
        let proxyArr:[JKFastNotificationProxy] = names.compactMap 
            let name:String = $0
            let observered:Bool = tmpSelf.notificationProxyList.contains  proxy in
                return proxy.notificationName == name
            
            if observered == false 
               return JKFastNotificationProxy(name: name, block: block)
             else 
                #if DEBUG
                assert(false, "duplicated add observer of the same name!")
                #endif
                return nil
            
        
        tmpSelf.notificationProxyList += proxyArr
    
    
     func jk_removeObserveNotification(for name:String) ->Void 
        var tmpSelf = self
        tmpSelf.notificationProxyList.removeAll  $0.notificationName == name
    
    
    func jk_postNotification(notificationName:String) ->Void 
        jk_postNotification(notificationName: notificationName, object: nil, userInfo: nil)
    
    
    func jk_postNotification(notificationName:String, object:Any?, userInfo:[AnyHashable : Any]?) ->Void 
        NotificationCenter.default.post(name: Notification.Name.init(notificationName), object: object, userInfo: userInfo)
    


swift版本使用示例:

import UIKit
import JKNoticationHelper_Swift
class ViewController: UIViewController,JKFastNotificationProtocol 
    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let button:UIButton = UIButton.init(frame: CGRect.init(x: 0, y: 0, width: 60, height: 60))
        button.backgroundColor = .red
        self.view.addSubview(button)
        button.center = self.view.center
        button.addTarget(self, action: #selector(buttonClicked), for:.touchUpInside)
        jk_observeNotificaion(name: "aaaaa")  notification in
            print("hahah")
        
        
    
    
    @objc func buttonClicked() ->Void 
       jk_postNotification(notificationName: "aaaaa")
    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    


通过pod集成如下:

OC:

pod 'JKNoticationHelper'

swift:

pod 'JKNoticationHelper_Swift'

源码下载地址:https://github.com/xindizhiyin2014/JKNoticationHelper.git

ios开发如何限制nsnotification的作用范围(代码片段)

  在实际的开发中NSNotification能够很好地解耦代码,跨层传输数据等。但是由于是全局生效的。因此有时候我们不想作用范围那么广,只想局限在某个范围内进行通知的发送与接收。最近弄了一个方案,分享给大家... 查看详情

ios通知(nsnotification)(代码片段)

一、通知1、基本概念NSNotification是iOS中一个调度消息通知的类,采用单例模式设计,在程序中实现传值、回调等地方应用很广。在iOS中,NSNotification&NSNotificaitonCenter是使用观察者模式来实现的用于跨层传递消息。2... 查看详情

尝试在 Swift 的多点连接测试应用程序中使用 NSNotification

】尝试在Swift的多点连接测试应用程序中使用NSNotification【英文标题】:TryingtouseNSNotificationinamultipeerconnectivitytestappinSwift【发布时间】:2014-09-0821:03:18【问题描述】:一直在关注本教程:http://www.appcoda.com/intro-multipeer-connectivity-fram... 查看详情

NSNotification 或 Delegate 在可见视图更改时注册

】NSNotification或Delegate在可见视图更改时注册【英文标题】:NSNotificationorDelegatetoregisterforwhenthevisibleviewchanges【发布时间】:2012-10-3118:36:58【问题描述】:我正在为ios开发一个objective-c项目,并且我有一个使用UITabBarController子类的... 查看详情

键入“NSNotification.Name?”没有成员“firInstanceIDTokenRefresh”

】键入“NSNotification.Name?”没有成员“firInstanceIDTokenRefresh”【英文标题】:Type\'NSNotification.Name?\'hasnomember\'firInstanceIDTokenRefresh\'【发布时间】:2017-06-1018:49:01【问题描述】:我在带有Swift的iOS应用中使用Firebase通知,我最近将Fire... 查看详情

SwiftUI / iOS |在没有 NSNotification 的情况下获取键盘大小

】SwiftUI/iOS|在没有NSNotification的情况下获取键盘大小【英文标题】:SwiftUI/iOS|GetkeyboardsizewithoutNSNotification【发布时间】:2019-07-2913:30:27【问题描述】:我想知道是否有可能在没有任何通知的情况下获取我的应用程序当前正在运行... 查看详情

如何在 Swift 中使用 NSNotification -> userInfo 发送对象数组

】如何在Swift中使用NSNotification->userInfo发送对象数组【英文标题】:howtosendarrayofobjectsusingNSNotification->userInfoinSwift【发布时间】:2015-09-0213:26:21【问题描述】:userInfo只发送anyObject类型的数据,所以我需要转换我的Meals数组到a... 查看详情

如何在 NSNotification 中传递 userInfo?

】如何在NSNotification中传递userInfo?【英文标题】:HowtopassuserInfoinNSNotification?【发布时间】:2010-10-0507:07:22【问题描述】:我正在尝试使用NSNotification发送一些数据但卡住了。这是我的代码://PostingNotificationNSDictionary*orientationData;... 查看详情

(七十二)自己定义通知nsnotification实现消息传递

    众所周知,iOS中一般在类之间传递消息使用较多的是delegate和block,另一种是基于通知进行的消息传递,我们经常是使用系统的通知。来实现一些功能。比如利用键盘尺寸改变的通知,我们能够依据键盘的位置... 查看详情

ios之深入解析通知nsnotification的底层原理(代码片段)

一、概念①NSNotificationNSNotification用于描述通知的类,一个NSNotification对象就包含了一条通知的信息,NSNotification对象是不可变的。所以当创建一个通知时通常包含如下属性: @interfaceNSNotification:NSObject<NSCopying,NSCodi... 查看详情

什么是 NSNotification?

】什么是NSNotification?【英文标题】:WhatisNSNotification?【发布时间】:2009-12-1411:25:21【问题描述】:谁能解释一下NSNotificationCenter的重要性?在哪里使用它们?NSNotificationCenter与AppDelegate有什么区别?【问题讨论】:【参考方案1】... 查看详情

ios8调用 - (void) onKeyboardShow:(NSNotification *)通知两次

】ios8调用-(void)onKeyboardShow:(NSNotification*)通知两次【英文标题】:ios8calls-(void)onKeyboardShow:(NSNotification*)notificationtwotimes【发布时间】:2014-09-1217:22:36【问题描述】:我们有一个带有UITextField和UITextView的屏幕。当我点击其中任何一个... 查看详情

官方core-ktx库能对富文本span开发带来哪些便利?(代码片段)

...的core-ktx库里面的扩展类、方法等等,看看能为项目开发带来哪些便利。已更新的文章列表如下:你需要了解的官方core-ktx库能对开发带来哪些便利1官方core-ktx库能对SparseArray系列、Pair开发带来哪些便利?接下来,... 查看详情

Xcode 从 NSNotification 检索 userInfo

】Xcode从NSNotification检索userInfo【英文标题】:XcoderetrieveuserInfofromNSNotification【发布时间】:2013-04-0919:27:22【问题描述】:我有一个带有userInfo的aNotification我想用另一种格式调用另一种方法。有没有办法从[aNotificationuserInfo]中检索... 查看详情

thymeleaftable便利数据跳转

  在开发中,作为初中级后台开发,便利数据这种工作是不可避免的,而在JSP中便利数据需要编辑大量的辅助js代码,甚至有些还需要在JS中拼接代码显示数据.  比如:.........for(vari=(pageNo-4);i<pageNo;i++){if(arroundProjects[i].mainPicUrl!=nul... 查看详情

nsnotification的使用&和代理的区别

...分3步1、增加观察者(说明对什么消息敏感)  [[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(getMsg:)name:@"myInfo"object:nil];2、完成回调(收到消息做什么)-(void)getMs 查看详情

NSNotification 与 UITextFieldDelegate

】NSNotification与UITextFieldDelegate【英文标题】:NSNotificationvsUITextFieldDelegate【发布时间】:2014-04-0813:13:42【问题描述】:我和我的同事更喜欢用不同的方法来解决一项小任务。我们想知道社区的意见。我们必须在编辑过程中处理UITe... 查看详情

在科尔多瓦插件中设置 NSNotification 观察者

】在科尔多瓦插件中设置NSNotification观察者【英文标题】:SettingNSNotificationsobserverinacordovaplugin【发布时间】:2014-02-0415:57:26【问题描述】:我有一个cordova插件,它依赖于连接到我的iOS设备的附件。通知正在刷卡的附件(磁性刷... 查看详情