iOS开发检测UILabel内容变化 变更时仅单次调用函数的实现方法
问题根因
CLLocationManager 的 locationManager(_:didRangeBeacons:in:) 回调是持续高频触发的(默认约1秒触发一次),只要设备处于信标信号覆盖范围内,每次回调命中信标判断逻辑时,都会无条件执行prueba.text赋值和addBeacon()调用,最终导致无限重复写入数据。不需要绕路实现UILabel的内容监听,直接在赋值、写库前做新旧值比对+已记录状态标记即可解决问题。
不推荐为了这个需求给UILabel添加KVO内容监听,你的写入触发点本来就是代码中主动给
prueba.text赋值的位置,在赋值前做拦截判断是性能开销最小、逻辑最可控的实现方式,额外加UI监听反而会增加不必要的复杂度,提高调试成本。
方案1:新旧值比对(完全匹配「文本变化才触发写入」的需求)
在给prueba.text赋值、调用addBeacon()之前,先判断要设置的新文本和当前label已有的文本是否一致,只有不一致的时候才执行赋值+写库操作。
修改didRangeBeacons内的信标判断逻辑如下:
func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) { guard beacons.count > 0, let nearestBeacon = beacons.first else { // 无信标时的逻辑 return } // 去掉冗余的for循环,原逻辑未用到循环内的单个beacon对象,重复判断无意义 switch nearestBeacon.proximity { case .far: break case .near, .immediate: let targetUUID = nearestBeacon.proximityUUID.uuidString // MyBeacon1 判断逻辑 if targetUUID == "15164A5A-F607-49AE-0000-66B7106A0000" { let newText = "Tracking beacon: \"MyBeacon 1\"" // 文本无变化直接跳过,不重复写入 guard prueba.text != newText else { return } prueba.text = newText addBeacon() isDetectedE = true stopScanningF() stopScanningE() } // MyBeacon2 判断逻辑 if targetUUID == "74278BDA-B644-4520-8F0C-720EAF059100" { let newText = "Tracking beacon: \"MyBeacon 2\"" guard prueba.text != newText else { return } prueba.text = newText addBeacon() isDetectedF = true stopScanningF() stopScanningE() } default: break } }
方案2:利用已有状态标记(更适配信标业务场景)
你代码中已经定义了isDetectedE、isDetectedF两个布尔标记位,本来就是用来标记对应信标是否已经被检测记录过,直接用这个标记做拦截更符合业务逻辑:如果需要「每次离开信标范围后,下次进入重新记录」,只要在信标离开回调、测距失败的逻辑里把对应标记位重置为false即可。
核心判断逻辑修改为:
// MyBeacon1 判断块 if targetUUID == "15164A5A-F607-49AE-0000-66B7106A0000" { // 已经记录过直接跳过 guard !isDetectedE else { return } prueba.text = "Tracking beacon: \"MyBeacon 1\"" addBeacon() isDetectedE = true stopScanningF() stopScanningE() } // MyBeacon2 判断块 if targetUUID == "74278BDA-B644-4520-8F0C-720EAF059100" { guard !isDetectedF else { return } prueba.text = "Tracking beacon: \"MyBeacon 2\"" addBeacon() isDetectedF = true stopScanningF() stopScanningE() }
内容的提问来源于stack exchange,提问作者VicMackey
相关产品推荐
相关产品推荐

