How to manipulate properties of React Native - Native UI Component?

713 views Asked by At

I am working on a React Native app.

The app consists of both web-based views and native ui views (components).

While the rendering of the web-based views and also the native ui views works, I am not able to manipulate properties of the native ui view like, for example, the background color.

I have to say that my project structure is not that simple because I have done a lot of bridging, from React to Objective-C, from Objective-C to Swift and the other way around.

A brief introduction to my project structure:

MyUIView.h

#import <UIKit/UIKit.h>

// Define which methods and properties have to be implemented in MyUIView
@interface MyUIView : UIView

@end

MyUIView.m

#import "MyUIView.h"

// Represents the native MyUIView
@implementation MyUIView
  -(instancetype) init {
    self = [super init];
    if (self) {
      [self setUp];
    }
    return self;
  }

  -(void) setUp {
    UIView * myUIView = [[UIView alloc] initWithFrame:CGRectMake(-50, -250, 100, 100)];
    [myUIView setBackgroundColor:[UIColor grayColor]];
    [self addSubview:myAudioRecorderUIView];
  }

@end

MyUIManager.h

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <React/RCTViewManager.h>

@interface MyUIManager : RCTViewManager
  @property (nonatomic, strong) UIView *myUIView;

  - (void) changeBackgroundColor: (UIColor*)color;
@end

MyUIManager.m

#import "MyUIManager.h"
#import "reactnative-Swift.h"

#import "MyUIView.h"
#import <UIKit/UIKit.h>

@import UIKit;

// Controls the rendering of native view in the React part of our application
@implementation MyUIManager
  MyUIManager *myUIManager;
  MyUIView *myUIView;

  + (void) initialize {
    myUIManager = [MyUIManager allocWithZone: nil];
    myUIView = [[MyUIView alloc] init];
  }

  + (id) allocWithZone:(NSZone *)zone {
    static MyUIManager *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
      sharedInstance = [super allocWithZone:zone];
    });
    return sharedInstance;
  }

  - (void) changeBackgroundColor: (UIColor*)color {
    dispatch_sync(dispatch_get_main_queue(), ^{
      self.myUIView.backgroundColor = UIColor.redColor;
    });
  }

  RCT_EXPORT_MODULE()

  - (UIView *) view
  {
    return myUIView;
  }

@end

MyViewController.swift

import Foundation
import UIKit

@objc open class MyViewController : UIViewController {

  let myUIManager: MyUIManager = MyUIManager();

  @objc func changeColor() {
    myUIManager.changeBackgroundColor(UIColor.red)
  }
}

What I expect is that calling the changeColor method from my Swift class, changes the color of my native ui view, since the changeBackgroundColor of myUIManager is called where the color is set then. However the color does change. It stays gray like it was defined in the setUp method of MyUIView.m.

Any suggestions?

1

There are 1 answers

0
Michael Andorfer On BEST ANSWER

There have to be done some adaptions to get it working, the most important thing is to wrap the view which should be manipulated into another view and return the parent view instead of the child view then:

MyUIView.m

#import "MyUIView.h"

// Represents the native MyUIView
@implementation MyUIView
  -(instancetype) init {
    self = [super init];
    if (self) {
      [self setUp];
    }
    return self;
  }

  - (instancetype)initWithFrame:(CGRect)frame {
    NSLog(@"init with frame: %@", NSStringFromCGRect(frame));
    self = [super initWithFrame:frame];
    if ( self ) {
      [self setUp];
    }
    return self;
  }

  - (void)setUp {
    self.backgroundColor = [UIColor grayColor];
  }

  - (void)layoutSubviews {
    NSLog(@"layout subviews");
  }

@end

MyUIManager.h

#import <UIKit/UIKit.h>
#import <React/RCTViewManager.h>

@interface MyUIManager : RCTViewManager
  @property (nonatomic) UIView *myParentUIView;
  @property (nonatomic) UIView *myUIView;

  - (void) changeBackgroundColor: (UIColor*)color;
@end

MyUIManager.m

#import "MyUIManager.h"
#import "reactnative-Swift.h"

#import "MyUIManager.h"
#import "MyUIView.h"
#import <UIKit/UIKit.h>

// Controls the rendering of native view in the React part of our application
@implementation MyUIManager
  MyUIView *myParentUIView;
  MyUIView *myUIView;

  // Instantiate MyUIView (parent and child)
  + (void) initialize {
    myParentUIView = [[MyUIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
    myUIView = [[MyUIView alloc] initWithFrame:CGRectMake(-50, -250, 100, 100)];
    [myParentUIView addSubview:myUIView];
  }

  // Change background color of view
  - (void) changeBackgroundColor: (UIColor*)color {
    dispatch_sync(dispatch_get_main_queue(), ^{
      myParentUIView.subviews.firstObject.backgroundColor = color;
    });
  }

  RCT_EXPORT_MODULE()

  - (UIView *)view {
    return myParentUIView;
  }

@end