Make native component for React Native in iOS/macOS to proper position, proper props and accept mouse click

45 views Asked by At

I am making a simple "check box" native component for React Native. It is for macOS, but it has made similar way as iOS.

This is my code:

RNCCheckBox.m:

#import <AppKit/AppKit.h>

@interface RNCCheckBox : NSView

@property (nonatomic, copy) NSString *title;
@property (nonatomic, assign) BOOL isSelected;

@end

@implementation RNCCheckBox

- (instancetype)init
{
    self = [super initWithFrame:NSMakeRect(50, -100, 50, -100)]; // weird value, but this works, positive values does not.
    if (self) {
        _title = @"";
        _isSelected = YES; // or NO
        NSButton *cb = [[NSButton alloc] initWithFrame:self.frame];
        [cb setTitle:_title];
        [cb setButtonType:NSButtonTypeSwitch];
        [cb setTarget:self];
        [cb setState:_isSelected];
        [cb setAction:@selector(clicked:)];
        [self addSubview:cb];

    //  [cb performClick:self]; this works, but mouse click does not.
    }
    return self;
}

- (void)setTitle:(NSString *)title
{
    if (![_title isEqual:title])
        _title = [title copy];
}

- (void)setIsSelected:(BOOL)isSelected
{
    if (_isSelected != isSelected)
        _isSelected = isSelected;
}

- (void)clicked:(id)sender // does not invokes
{
    NSButton *cb = (NSButton *)sender;
    [cb setState:_isSelected];
}

@end

RNCCheckBoxManager.m:

#import <React/RCTViewManager.h>
#import "RNCCheckBox.h"

@interface RNCCheckBoxManager : RCTViewManager
@end

@implementation RNCCheckBoxManager

RCT_EXPORT_MODULE()

- (NSView *)view
{
    NSView *view = [RNCCheckBox new];
    return view;
}

RCT_EXPORT_VIEW_PROPERTY(title, NSString *)
RCT_EXPORT_VIEW_PROPERTY(isSelected, BOOL)

@end

CheckBox.tsx:

import React from 'react';
import { requireNativeComponent } from "react-native";

const RNCCheckBox = requireNativeComponent('RNCCheckBox');

export class CheckBox extends React.Component<{ title: string, isSelected: boolean }> {
    render() {
        return (
            <RNCCheckBox { ...this.props } /> // props does not injected
        );
    }
}

module.exports = CheckBox;

App.tsx in my app:

import React from 'react';
import { View } from 'react-native';
import { CheckBox } from 'react-native-my-checkbox';

export default class App extends React.Component<undefined, { checked: boolean }> {
    constructor(props: undefined) {
        super(props);
        this.state = { checked: false };
    }

    render() {
        return (
            <View>
                <CheckBox title={'Test'} isSelected={ this.state.checked } />
            </View>
        );
    }
}

These code doesn't work properly - check box appears, but not clickable, and props are not injected.

Also its position doesn't follow its <View />, so I have to set it manually by initWithFrame. enter image description here

If I change to init, only blue dot shows on upper left corner.

Where am I doing wrong?

0

There are 0 answers