16

We can control custom native UI components' properties by exporting native properties using RCT_EXPORT_VIEW_PROPERTY.

But how to export instance methods of native UI components?

2 Answers 2

16

Thanks to @alinz's suggestion.

This can be done within the custom native component's view manager.

  1. Obj-c side: In the native view manager expose a native method like this:

The key is to pass in the reactTag which is the reference to the native component.

MyCoolViewManager.m:

RCT_EXPORT_METHOD(myCoolMethod:(NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback) {
  [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
    MyCoolView *view = viewRegistry[reactTag];
    if (![view isKindOfClass:[MyCoolView class]]) {
      RCTLogMustFix(@"Invalid view returned from registry, expecting MyCoolView, got: %@", view);
    }
    // Call your native component's method here
    [view myCoolMethod];
  }];
}
  1. JS side: Add API in the react component class:

MyCoolView.js:

var React = require('react-native');
var NativeModules = require('NativeModules');
var MyCoolViewManager = NativeModules.MyCoolViewManager;
var findNodeHandle = require('findNodeHandle');

class MyCoolView extends React.Component{
    // ...
    myCoolMethod() {
        return new Promise((resolve, reject) => {
            MyCoolViewManager.myCoolMethod(
                findNodeHandle(this),
                (error, result) => {
                    if (error) {
                        reject(error);
                    } else {
                        resolve(result);
                    }
                }
            );
        });
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

This solution doesn't seem to work with new version of react native. addUIBlock is no longer callable from uiManager. Trying figure out how to resolve this.
I found a working example on github. Check it out. github.com/ProjectSeptemberInc/gl-react-native/blob/master/ios/…
FYI, I needed this for Android, and posted solution here: stackoverflow.com/a/45684685/194065
@Patm did you figure out what to do now that addUiBlock is no longer callable?
-1

I'm not an Objective C expert but a Swift developer.

I better use this way just for readability (maybe there are drawbacks in Obj-C?):

  • In Manager: store a reference to your view in an instance private property
  • it will then help to call your view's method

Obj-C side - component manager:

@implementation RNAnalogClockManager {
  RNAnalogClock* _AnalogClock;
}

RCT_EXPORT_MODULE()

- (UIView *)view
{
  // keep a reference to the view before returning it
  _AnalogClock = [[RNAnalogClock alloc] init];
  return _AnalogClock;
}

// export method and easily call view method 
RCT_EXPORT_METHOD(startRealTime) {
  [_AnalogClock startRealTime];
};

JS side remains the same

NOTE: I don't need callback in my example but it does not change the principle it is just another parameter.

3 Comments

what happens if the start method is called before the view method? then the _AnalogClock is nil and all things are broken..
Component manager is the way RN can play with native AnalogClock. View() method is called by RN to create an instance of the Native. RN can't call start timer method before it is instantiated so it can't occur.
This does not seem to allow to have multiple instances of AnalogClock.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.