You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者Иван Кайн

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 01:39:04