iOS 使用消息轉發機制實現多代理功能

在iOS開發中,我們有時候會用到多代理功能,比如我們列表的埋點事件,需要我們在列表的某個特定的時機進行埋點上報,我們當然可以用最常見的做法,就是設置代理實現代理方法,然后在對應的代理方法里面進行上報,但是這樣做有個問題,就是會做大量重復的工作,我們想要到達的效果是,我們只需要實現業務邏輯,而埋點操作,只需需要我們配置一下數據,就會自動進行,這樣就為我們減少了大量的重復性工作。
下面介紹一下我們實現列表的自定化埋點的思路
我們自定義一個列表類,繼承于系統類,然后該類有一個代理中心,
該代理中心類負責消息轉發,他引用了真正的原始代理,和一個代理對象,該代理對象也實現了列表的代理方法,里面的實現只進行埋點操作。 我們重寫自定義列表類的setDelegate方法,在里面創建代理對象,并將列表的代理設置為代理中心,在代理中心中將消息轉發給代理對象和原始代理, 通過這樣的方式,實現了自動化埋點
代碼
代理中心

//
//  LBDelegateCenter.m
//  TEXT
//
//  Created by mac on 2025/3/2.
//  Copyright ? 2025 劉博. All rights reserved.
//#import "LBDelegateCenter.h"@implementation LBDelegateCenter- (instancetype)initWithTarget:(id)target proxy:(id)proxy
{if (self = [super init]) {_target = target ? target : [NSNull null];_proxy = proxy ? proxy : [NSNull null];}return self;
}- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{NSMethodSignature *targetSign = [_target methodSignatureForSelector:sel];if (targetSign) {return targetSign;}NSMethodSignature *proxySign = [_proxy methodSignatureForSelector:sel];if (proxySign) {return proxySign;}return [super methodSignatureForSelector:sel];
}- (void)forwardInvocation:(NSInvocation *)anInvocation
{//AUKLogInfo(@"New proxy = %@, selector=%@", [self.proxy class], NSStringFromSelector([anInvocation selector]));BOOL hit = NO;if ([_target respondsToSelector:[anInvocation selector]]) {hit = YES;[anInvocation invokeWithTarget:_target];}if ([_proxy respondsToSelector:[anInvocation selector]]) {//AUKLogInfo(@"New proxy handle");hit = YES;[anInvocation invokeWithTarget:_proxy];}if (!hit && [super respondsToSelector:[anInvocation selector]]) {[super forwardInvocation:anInvocation];}
}- (BOOL)respondsToSelector:(SEL)aSelector
{if ([_target respondsToSelector:aSelector]) {return YES;}if ([_proxy respondsToSelector:aSelector]) {return YES;}return [super respondsToSelector:aSelector];
}- (BOOL)conformsToProtocol:(Protocol *)aProtocol
{if ([_target conformsToProtocol:aProtocol]) {return YES;}if ([_proxy conformsToProtocol:aProtocol]) {return YES;}return [super conformsToProtocol:aProtocol];
}- (BOOL)isKindOfClass:(Class)aClass
{if ([_target isKindOfClass:aClass]) {return YES;}if ([_proxy isKindOfClass:aClass]) {return YES;}return [super isKindOfClass:aClass];
}- (BOOL)isMemberOfClass:(Class)aClass
{if ([_target isMemberOfClass:aClass]) {return YES;}if ([_proxy isMemberOfClass:aClass]) {return YES;}return [super isMemberOfClass:aClass];
}@end

代理對象

//
//  LBScrollViewDelegate.m
//  TEXT
//
//  Created by mac on 2025/3/2.
//  Copyright ? 2025 劉博. All rights reserved.
//#import "LBScrollViewDelegate.h"
#import <UIKit/UIKit.h>
#import "UITableViewCell+Event.h"
#import "UICollectionViewCell+Event.h"@implementation LBScrollViewDelegate// 自動輪播的開始,但是需要重點關注是否可能存在觸發scrollViewDidScroll
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{//執行滾動
}- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{//開始拖動,執行曝光埋點
}//
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{//開始減速, 停止滾動
}//
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{//停止減速
}//
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{if (!decelerate) {//停止滾動}
}//
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{//
}// 10.3.86 切換使用新方法代替點擊捕獲
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];[cell setMonitorSelected:YES];
}- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];[cell setMonitorSelected:YES];
}// 結束顯示周期是準確的,但開始顯示可能只顯示一次,可能顯示并不完全,所以暫只開了開始。
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{if ([self needCheckCellIn:tableView isStart:YES]) {}
}- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{if ([self needCheckCellIn:collectionView isStart:YES]) {}
}- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath
{if ([self needCheckCellIn:tableView isStart:NO]) {}
}- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{if ([self needCheckCellIn:collectionView isStart:NO]) {}
}- (BOOL)needCheckCellIn:(UIView *)view isStart:(BOOL)start
{return YES;
}@end

自定義列表類

//
//  LBCollectionView.m
//  TEXT
//
//  Created by mac on 2025/3/2.
//  Copyright ? 2025 劉博. All rights reserved.
//#import "LBEventCollectionView.h"
#import "LBScrollViewDelegate.h"
#import "LBDelegateCenter.h"@implementation LBEventCollectionView- (void)didMoveToWindow
{[super didMoveToWindow];//執行cell 曝光埋點
}- (void)reloadData
{[super reloadData];[self checkNeedReportLog_auk];}- (void)checkNeedReportLog_auk
{if (!self.window || !self.superview) {return;}// 上報當前visiblecell及其子view的所有埋點,放到下一個runloop,等到cell渲染完成[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(performCommitScroll) object:nil];[self performSelector:@selector(performCommitScroll) withObject:nil afterDelay:0.5];}- (void)performCommitScroll
{//執行曝光埋點
}- (LBScrollViewDelegate *)collectionDelegate_auk
{if (!_collectionDelegate_auk) {_collectionDelegate_auk = [[LBScrollViewDelegate alloc] init];}return _collectionDelegate_auk;
}- (void)setDelegate:(id<UICollectionViewDelegate>)delegate
{if (delegate == nil) {
//        self.delegateProxy_auk = nil;[super setDelegate:nil];return;}self.delegateProxy_auk = [[LBDelegateCenter alloc] initWithTarget:self.collectionDelegate_auk proxy:delegate];self.delegateProxy_auk.scrollView = self;[super setDelegate:(id)self.delegateProxy_auk];
}- (NSMutableDictionary *)visibleCellInfos_auk
{if (!_visibleCellInfos_auk) {_visibleCellInfos_auk = [[NSMutableDictionary alloc] init];}return _visibleCellInfos_auk;
}- (NSMutableDictionary *)lastVisibleInfos_auk
{if (!_lastVisibleInfos_auk) {_lastVisibleInfos_auk = [[NSMutableDictionary alloc] init];}return _lastVisibleInfos_auk;
}- (NSHashTable *)validViews_auk
{if (!_validViews_auk) {_validViews_auk = [NSHashTable hashTableWithOptions:NSHashTableWeakMemory];}return _validViews_auk;
}- (void)dealloc
{
//    self.delegate = nil;_delegateProxy_auk = nil;_collectionDelegate_auk = nil;
}- (BOOL)supportAspectExposure
{return NO;
}@end

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72267.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72267.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72267.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

XGBoost和LightGBM機器學習算法對比及實戰

文章目錄 1. XGBoost 原理核心思想關鍵技術點2. LightGBM 原理核心思想關鍵技術點3. XGBoost vs LightGBM 對比4. 適用場景選擇5. 總結1. 數據準備2. XGBoost 示例安裝庫代碼實現3. LightGBM 示例安裝庫代碼實現4. 關鍵參數對比5. 注意事項6. 輸出示例XGBoost 和 LightGBM 是兩…

局域網自動識別機器名和MAC并生成文件的命令

更新版本&#xff1a;添加了MAC 地址 確定了設備唯一性 V1.1 局域網自動識別機器名和MAC并生成文件的批處理命令 echo off setlocal enabledelayedexpansionREM 設置輸出文件 set outputFilenetwork_info.txtREM 清空或創建輸出文件 echo Scanning network from 192.168.20.1…

基于Python+Vue開發的體育用品商城管理系統源碼+開發文檔+課程作業

項目簡介 該項目是基于PythonVue開發的體育用品商城管理系統&#xff08;前后端分離&#xff09;&#xff0c;這是一項為大學生課程設計作業而開發的項目。該系統旨在幫助大學生學習并掌握Python編程技能&#xff0c;同時鍛煉他們的項目設計與開發能力。通過學習基于Python的體…

pyQT5簡易教程(一):制作一個可以選擇本地圖片并顯示的桌面應用

可以參考之前的教程安裝 PyQt 和 PyQt Designer https://blog.csdn.net/smx6666668/article/details/145909326?spm=1011.2415.3001.10575&sharefrom=mp_manage_link 一、打開pycharm中的QTdesigner 二、設計界面 和之前一樣,使用 PyQt Designer 來設計界面并保存為 .u…

LeetCode 解題思路 6(Hot 100)

解題思路&#xff1a; 初始化窗口元素&#xff1a; 遍歷前 k 個元素&#xff0c;構建初始單調隊列。若當前索引對應值大于等于隊尾索引對應值&#xff0c;移除隊尾索引&#xff0c;將當前索引加入隊尾。遍歷結束時當前隊頭索引即為當前窗口最大值&#xff0c;將其存入結果數組…

基于redis的位圖實現簽到功能

基于Redis位圖實現簽到功能是一種高效且節省內存的方法。以下是分步實現的詳細方案&#xff1a; 1. 鍵設計策略 采用 sign:<userId>:<YYYYMM> 格式存儲每月簽到數據 # 示例&#xff1a;用戶1001在2023年8月的簽到數據 sign_key "sign:1001:202308"2.…

C++ Qt OpenGL渲染FFmpeg解碼后的視頻

本篇博客介紹使用OpenGL渲染FFmpeg解碼后的視頻,涉及到QOpenGLWidget、QOpenGLFunctions、OpenGL shader以及紋理相關,播放效果如下: 開發環境:Win11 C++ Qt6.8.1、FFmpeg4.0、x64 ??注意:Qt版本不同時,Qt OpenGL API及用法可能差別比較大,FFmpeg版本不同時API調用可能…

deepseek部署:ELK + Filebeat + Zookeeper + Kafka

## 1. 概述 本文檔旨在指導如何在7臺機器上部署ELK&#xff08;Elasticsearch, Logstash, Kibana&#xff09;堆棧、Filebeat、Zookeeper和Kafka。該部署方案適用于日志收集、處理和可視化場景。 ## 2. 環境準備 ### 2.1 機器分配 | 機器編號 | 主機名 | IP地址 | 部署組件 |-…

2.數據結構:1.Tire 字符串統計

1.Tire 字符串統計 #include<algorithm> #include<cstring> #include<iostream>using namespace std;const int N100010; int son[N][26];//至多 N 層&#xff0c;每一層至多 26 個節點&#xff08;字母&#xff09; int cnt[N];//字符串至多 N 個&#xff…

算法(四)——位運算與位圖

文章目錄 位運算、位圖位運算基本位運算異或運算交換兩個數無比較返回最大值缺失的數字唯一出現奇數次的數唯二出現奇數次的數唯一出現次數少于m次的數 位運算進階判斷一個整數是不是2的冪判斷一個整數是不是3的冪大于等于n的最小的2的冪[left, right]內所有數字&的結果反轉…

本地部署deepseek大模型后使用c# winform調用(可離線)

介于最近deepseek的大火&#xff0c;我就在想能不能用winform也玩一玩本地部署&#xff0c;于是經過查閱資料&#xff0c;然后了解到ollama部署deepseek,最后用ollama sharp NUGet包來實現winform調用ollama 部署的deepseek。 本項目使用Vs2022和.net 8.0開發&#xff0c;ollam…

SpringBoot原理-02.自動配置-概述

一.自動配置 所謂自動配置&#xff0c;就是Spring容器啟動后&#xff0c;一些配置類、bean對象就自動存入了IOC容器當中&#xff0c;而不需要我們手動聲明&#xff0c;直接從IOC容器中引入即可。省去了繁瑣的配置操作。 我們可以首先將spring項目啟動起來&#xff0c;里面有一…

P10265 [GESP樣題 七級] 迷宮統計

題目描述 在神秘的幻想?陸中&#xff0c;存在著 n 個古老而神奇的迷宮&#xff0c;迷宮編號從 1 到 n。有的迷宮之間可以直接往返&#xff0c;有的可以?到別的迷宮&#xff0c;但是不能?回來。玩家小楊想挑戰?下不同的迷宮&#xff0c;他決定從 m 號迷宮出發。現在&#x…

Spring框架中的工廠模式

在Spring框架里&#xff0c;工廠模式的運用十分廣泛&#xff0c;它主要幫助我們創建和管理對象&#xff0c;讓對象的創建和使用分離&#xff0c;提高代碼的可維護性和可擴展性。下面為你詳細介紹Spring框架中工廠模式的具體體現和示例&#xff1a; 1. BeanFactory 作為工廠模式…

音視頻-WAV格式

1. WAV格式說明&#xff1a; 2. 格式說明&#xff1a; chunkId&#xff1a;通常是 “RIFF” 四個字節&#xff0c;用于標識文件類型。&#xff08;wav文件格式表示&#xff09;chunkSize&#xff1a;表示整個文件除了chunkId和chunkSize這 8 個字節外的其余部分的大小。Forma…

SQL Server Management Studio的使用

之前在https://blog.csdn.net//article/details/140961550介紹了在Windows10上安裝SQL Server 2022 Express和SSMS&#xff0c;這里整理下SSMS的簡單使用&#xff1a; SQL Server Management Studio(SSMS)是一種集成環境&#xff0c;提供用于配置、監視和管理SQL Server和數據…

數據集筆記:NUSMods API

1 介紹 NUSMods API 包含用于渲染 NUSMods 的數據。這些數據包括新加坡國立大學&#xff08;NUS&#xff09;提供的課程以及課程表的信息&#xff0c;還包括上課地點的詳細信息。 可以使用并實驗這些數據&#xff0c;它們是從教務處提供的官方 API 中提取的。 該 API 由靜態的…

劍指 Offer II 031. 最近最少使用緩存

comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20031.%20%E6%9C%80%E8%BF%91%E6%9C%80%E5%B0%91%E4%BD%BF%E7%94%A8%E7%BC%93%E5%AD%98/README.md 劍指 Offer II 031. 最近最少使用緩存 題目描述 運用所掌握的…

uniapp 測試 IPA 包安裝到測試 iPhone

將uniapp測試IPA包安裝到測試iPhone有以下幾種方法&#xff1a; 使用Xcode安裝 確保計算機上安裝了Xcode&#xff0c;并將iOS設備通過數據線連接到計算機。打開Xcode&#xff0c;在菜單欄中選擇Window->Devices and Simulators&#xff0c;在設備列表中找到要安裝的iPhone…

vcredist_x64 資源文件分享

vcredist_x64 是 Microsoft Visual C Redistributable 的 64 位版本&#xff0c;用于在 64 位 Windows 系統上運行使用 Visual C 開發的應用程序。它包含了運行這些應用程序所需的運行時組件。 vcredist_x64 資源工具網盤下載鏈接&#xff1a;https://pan.quark.cn/s/ef56f838f…