Swift多追踪函数优化:避免重复遍历terms数组
解决Swift中重复遍历追踪类的方案
这是个很好的问题——重复的遍历逻辑不仅冗余,还增加了后续维护的成本(比如加新追踪方法时要改N处循环)。咱们可以通过协议抽象+逻辑封装来彻底解决这个问题,下面给你两种实用的方案:
方案1:给协议数组添加扩展(轻量直接)
首先,我们先把所有追踪类的公共方法抽象成一个协议,让Privacy、Search、Stores都遵守这个协议:
// 定义追踪协议,包含所有需要的公共方法 protocol TrackingProtocol { func trackScreen(_ screenName: String) func trackBanner(_ bannerId: String) // 后续新增的追踪方法都加在这里 } // 让三个类遵守协议(原有方法实现不变,只需声明遵守) class Privacy: TrackingProtocol { func trackScreen(_ screenName: String) { // 你的原有实现 print("Privacy track screen: \(screenName)") } func trackBanner(_ bannerId: String) { // 你的原有实现 print("Privacy track banner: \(bannerId)") } } class Search: TrackingProtocol { func trackScreen(_ screenName: String) { print("Search track screen: \(screenName)") } func trackBanner(_ bannerId: String) { print("Search track banner: \(bannerId)") } } class Stores: TrackingProtocol { func trackScreen(_ screenName: String) { print("Stores track screen: \(screenName)") } func trackBanner(_ bannerId: String) { print("Stores track banner: \(bannerId)") } }
接下来,给Array写一个限定元素为TrackingProtocol的扩展,把遍历逻辑封装进去:
extension Array where Element: TrackingProtocol { // 封装trackScreen的遍历调用 func trackScreen(_ screenName: String) { self.forEach { $0.trackScreen(screenName) } } // 封装trackBanner的遍历调用 func trackBanner(_ bannerId: String) { self.forEach { $0.trackBanner(bannerId) } } // 后续加新方法时,只需要在这里新增一个封装方法即可 }
现在调用的时候就不用写循环了,直接用数组调用方法:
let terms: [TrackingProtocol] = [Privacy(), Search(), Stores()] terms.trackScreen("HomePage") terms.trackBanner("SummerPromo")
方案1的优势:
- 轻量,不需要额外创建管理类,直接复用原有的数组
- 调用方式直观,和原有逻辑衔接自然
方案2:创建追踪管理类(集中管控)
如果你的追踪逻辑后续可能需要更复杂的处理(比如添加日志、过滤某些追踪器、动态添加/移除追踪器),推荐用一个管理类来封装所有逻辑:
// 同样先定义协议(和方案1一致) protocol TrackingProtocol { func trackScreen(_ screenName: String) func trackBanner(_ bannerId: String) } // 三个类遵守协议(代码同方案1,省略) // 创建管理类,封装追踪数组和遍历逻辑 class TrackerManager { private var trackers: [TrackingProtocol] init(trackers: [TrackingProtocol]) { self.trackers = trackers } // 支持动态添加追踪器 func addTracker(_ tracker: TrackingProtocol) { trackers.append(tracker) } // 封装trackScreen调用 func trackScreen(_ screenName: String) { trackers.forEach { $0.trackScreen(screenName) } } // 封装trackBanner调用 func trackBanner(_ bannerId: String) { trackers.forEach { $0.trackBanner(bannerId) } } }
使用时,先初始化管理类,再调用方法:
let trackerManager = TrackerManager(trackers: [Privacy(), Search(), Stores()]) trackerManager.trackScreen("HomePage") trackerManager.trackBanner("SummerPromo") // 后续可以动态添加新的追踪器 trackerManager.addTracker(NewTracker())
方案2的优势:
- 集中管理所有追踪逻辑,后续扩展更灵活
- 可以轻松添加额外功能(比如日志、过滤、动态管理追踪器)
两种方案都遵循了开闭原则:后续新增追踪方法时,只需要在TrackingProtocol里添加方法,然后在扩展/管理类里封装一次遍历逻辑,各个追踪类实现新方法即可,不用修改任何调用处的代码。
内容的提问来源于stack exchange,提问作者jayn
相关产品推荐
相关产品推荐

