ReactNative

ReactNative_ IOS 커스텀 RCTEmitter 생성 및 적용

JunsC 2024. 3. 5. 22:01
728x90

알람앱을 만들면서 ReactNative의 DeviceEventEmitter 를 직접적으로 커스터마이징이 필요한 상황이 오게 되었다.

IOS 에서 어떻게 RCTEmitter 를 커스터마이징하여 적용할지 찾아보았다.

흔들기 기능을 추가하려면 흔들기 감지하고 그것을 실시간 보내주어야 하는데, 그부분을 모듈화하여 ReactNative 안에서 실행하려고 했다.

우선 , .Swift  와 .h 을 만들어야한다 . 그리고 흔들기 기능관련된 부분을 추가해준다.

 

 

import Foundation

import UIKit

import AVFoundation

import React

import CoreMotion

 

@objc(ShakeModule)

class ShakeModule : RCTEventEmitter {

  

  var motionManager: CMMotionManager!

  

  override init() {

    super.init()

    self.motionManager = CMMotionManager()

    self.motionManager.accelerometerUpdateInterval = 0.2    

  }

  

  override class func requiresMainQueueSetup() -> Bool {

    return true

  }

  

  override func supportedEvents() -> [String] {

    return ["ShakeEvent"]

  }

  

  @objc

  func startAccelerometerUpdates() {

    self.motionManager.startAccelerometerUpdates(to: .main) { [weak self] data, error in

      guard let x = data?.acceleration.x,

            let y = data?.acceleration.y,

            let z = data?.acceleration.z else {

        return

      }

      

      let speed = sqrt(pow(x, 2)) + sqrt(pow(y, 2)) + sqrt(pow(z, 2))

      if speed > 2.0 {

        self?.sendEvent(withName: "ShakeEvent", body: ["isShake": true])

      } else {

        self?.sendEvent(withName: "ShakeEvent", body: ["isShake": false])

      }

    }

  }

  

  @objc

  func stopAccelerometerUpdates() {

    self.motionManager.stopAccelerometerUpdates()

  }    

}

 

 

 

#import <Foundation/Foundation.h>

#import <React/RCTBridgeModule.h>

#import <React/RCTEventEmitter.h>

#import <React/RCTEventDispatcher.h>

 

 

@interface RCT_EXTERN_REMAP_MODULE(RNShake ,ShakeModule, RCTEventEmitter)

 

_RCT_EXTERN_REMAP_METHOD(startShakeInit, startAccelerometerUpdates, false)

_RCT_EXTERN_REMAP_METHOD(stopShakeInit, stopAccelerometerUpdates, false)

 

@end

 

그리고 React Native에서 

 

위와 같이 EventEmitter라고 선언해주고 그 값들을 형변환하여 가져온다.

 

 

그리고 위와 같이 사용하면 커스터마이징 된 Emitter를 사용할 수 있게 된다 !!

끝!!

 

 

참고 *

ReactNative IOS 에서 UIViewController 도 역시 커스터마이징 가능하다

 

NSDictionary *initProps = [self prepareInitialProps];

  UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"alarm", initProps);

  rootView.backgroundColor = [UIColor whiteColor];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

  MainViewController *rootViewController = [MainViewController new];

  rootViewController.view = rootView;

  self.myAlarm = [[Alarm alloc] init];

  [self.myAlarm initBridgeWithBridge:bridge];

  [application setApplicationSupportsShakeToEdit:YES];

  [application registerForRemoteNotifications];

  [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

  center.delegate = self;

  AVAudioSession * session = [AVAudioSession sharedInstance];

  [session setCategory: AVAudioSessionCategoryPlayback error: nil];

  [FIRApp configure];

  if (@available(iOS 13.0, *)) {

    [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:@"com.alarm.backgroundTasking" usingQueue:nil launchHandler:^(BGTask *task) {

      [self.myAlarm appTerminated];

    }];

    [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:@"com.alarm.backgroundAppRefresh" usingQueue:nil launchHandler:^(BGTask *task) {

      

    }];

  } else {

    UIApplication* app = [UIApplication sharedApplication];

    __block UIBackgroundTaskIdentifier backgroundTask;

    backgroundTask = [app beginBackgroundTaskWithExpirationHandler:^{

      [app endBackgroundTask:backgroundTask];

    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

      [app endBackgroundTask:backgroundTask];

    });

  }

728x90
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."