iOS开发中NSNotification的便利使用
Posted JackLee18
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS开发中NSNotification的便利使用相关的知识,希望对你有一定的参考价值。
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的便利使用的主要内容,如果未能解决你的问题,请参考以下文章