React Native iOS端距离传感器原生模块代码排查及优化方案求助
现有代码问题排查
- 方法未导出:
activateProximitySensor没有使用RCT_EXPORT_METHOD宏导出,JS侧无法调用该方法开启传感器监听 - 内存泄漏风险:只添加了通知中心观察者,没有实现移除观察者的逻辑,模块销毁时会产生野指针,大概率导致崩溃
- 重复注册问题:多次调用激活方法会重复添加同一观察者,导致单次传感器状态变化触发多次回调
- 线程违规操作:UIDevice 相关的属性修改、系统通知回调都要求在主队列执行,RN原生模块默认运行在后台队列,直接操作会触发未定义行为
- 字段语义错误:事件回调的body参数用
name作为状态字段的key,语义完全不匹配,JS侧使用时容易产生误解 - 无错误反馈逻辑:部分不支持距离传感器的设备(如部分iPad型号)开启监听会失败,现有代码没有把失败状态同步给JS侧
优化后完整实现
头文件 RCTProximityModule.h 代码
#import <React/RCTEventEmitter.h> @interface RCTProximityModule : RCTEventEmitter @end
实现文件 RCTProximityModule.m 代码
#import "RCTProximityModule.h" #import <React/RCTLog.h> @implementation RCTProximityModule { BOOL _isObserving; } RCT_EXPORT_MODULE(ProximityModule); - (NSArray<NSString *> *)supportedEvents { return @[@"proximityChange"]; } /// 开启距离传感器监听 RCT_EXPORT_METHOD(activateProximitySensor:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { // 切到主队列执行UIKit相关操作 dispatch_async(dispatch_get_main_queue(), ^{ if (self->_isObserving) { resolve(@(YES)); return; } UIDevice *device = [UIDevice currentDevice]; device.proximityMonitoringEnabled = YES; if (device.proximityMonitoringEnabled) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(proximityChanged:) name:UIDeviceProximityStateDidChangeNotification object:device]; self->_isObserving = YES; resolve(@(YES)); } else { reject(@"DEVICE_NOT_SUPPORT", @"当前设备不支持距离传感器", nil); } }); } /// 关闭距离传感器监听 RCT_EXPORT_METHOD(deactivateProximitySensor) { dispatch_async(dispatch_get_main_queue(), ^{ if (!self->_isObserving) { return; } UIDevice *device = [UIDevice currentDevice]; device.proximityMonitoringEnabled = NO; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceProximityStateDidChangeNotification object:device]; self->_isObserving = NO; }); } /// 模块销毁时自动移除监听 - (void)invalidate { [self deactivateProximitySensor]; [super invalidate]; } - (void)proximityChanged:(NSNotification *)notification { UIDevice *device = [notification object]; BOOL proximityState = device.proximityState; RCTLogInfo(@"距离传感器状态更新:%@", proximityState ? @"靠近" : @"远离"); [self sendEventWithName:@"proximityChange" body:@{@"isClose": @(proximityState)}]; } @end
JS侧使用示例
import { NativeModules, NativeEventEmitter } from 'react-native'; const { ProximityModule } = NativeModules; const proximityEmitter = new NativeEventEmitter(ProximityModule); // 开启监听 const startProximityListen = async () => { try { await ProximityModule.activateProximitySensor(); // 注册状态变化回调 const subscription = proximityEmitter.addListener('proximityChange', (data) => { console.log('传感器状态:', data.isClose ? '物体靠近' : '物体远离'); }); // 不需要监听时调用remove移除 // subscription.remove(); } catch (e) { console.log('开启传感器失败:', e.message); } } // 关闭监听 const stopProximityListen = () => { ProximityModule.deactivateProximitySensor(); }
内容的提问来源于stack exchange,提问作者Иван Кайн
相关产品推荐
相关产品推荐

