React-Native Scrollview Implementation

IOS SDK

Add PrimisPlayer to a react-native application as a Native UI Component

📘

Please remember to add PrimisPlayer SDK and IMA SDK to your xcode project as described earlier.

Create an RCTViewManager for PrimisPlayer

Add a new Objective-c file to your XCode project: PrimisPlayerManager.m

// PrimisPlayerManager.m
 
#import <React/RCTViewManager.h>
#import <PrimisPlayerSdk/PrimisPlayerSdk-Swift.h>
 
@protocol PrimisRNContainerDelegate <NSObject>
-(void)onContainerLayout:(UIView*)view;
@end
 
@interface PrimisRNContainerView : UIView
@property(nonatomic,copy) NSString* placementID;
@property(nonatomic,copy) NSString* floatingParentID;
@property(nonatomic,copy) NSString* additionalParams;
@property(nonatomic,assign) BOOL debugLogActive;
@property(nonatomic,retain) PrimisPlayer *player;
@property(nonatomic, strong) id<PrimisRNContainerDelegate> delegate;
@property(atomic, assign) BOOL doOnce;
@end
 
@implementation PrimisRNContainerView
- (void)layoutSubviews {
  [super layoutSubviews];
  if (!_doOnce) {
    _doOnce = YES;
    // Set width/height constraints
    CGFloat width = self.frame.size.width ? self.frame.size.width : self.reactSuperview.frame.size.width;
    self.translatesAutoresizingMaskIntoConstraints = NO;
    [self.widthAnchor constraintEqualToConstant: width].active = YES;
    [self.heightAnchor constraintEqualToConstant: 0].active = YES;
    // Notify the view manager
    [_delegate onContainerLayout:self];
  }
}

-(void)didSetProps:(NSArray<NSString *> *)changedProps {
  RCTLog(@"didSetProps: %@", changedProps.description);
  if (!_placementID) { _placementID = @""; }
  if (!_floatingParentID) { _floatingParentID = @""; }
  if (!_additionalParams) { _additionalParams = @""; }
}
 
- (void) willMoveToSuperview: (UIView *) newSuperview{
    if(newSuperview == nil){
      RCTLog(@"willMoveToSuperview: The container view was removed from superview. Removing Primis player.");
      [_player remove];
      _player = nil;
    }
}
@end
 
 
@interface PrimisPlayerManager : RCTViewManager <PrimisRNContainerDelegate>
@end
 
@implementation PrimisPlayerManager
 
RCT_EXPORT_MODULE(PrimisPlayerViewManager1)
 
RCT_EXPORT_VIEW_PROPERTY(floatingParentID, NSString);
RCT_EXPORT_VIEW_PROPERTY(placementID, NSString);
RCT_EXPORT_VIEW_PROPERTY(debugLogActive, BOOL);
RCT_EXPORT_VIEW_PROPERTY(additionalParams, NSString);
 
/// Force running on main thread
+ (BOOL)requiresMainQueueSetup {
  return YES;
}
 
/// Return a container view to react-native
- (UIView *)view {
  PrimisRNContainerView *view = [[PrimisRNContainerView alloc] init];
  view.delegate = self;
  return view;
}
 
/// Delegate method of PrimisRNContainerDelegate, called by PrimisRNContainerView when layoutSubviews is called
- (void)onContainerLayout:(UIView *)view {
  RCTLog(@"onContainerLayout");
  PrimisRNContainerView* containerView = (PrimisRNContainerView*)view;
  UIView *floatParentView = [self findFloatingParentView:containerView];
  containerView.player = [self setupPrimisPlayer:containerView floatParentView:floatParentView];
}
 
/// Create Primis player and configure it with props values
- (PrimisPlayer*)setupPrimisPlayer: (PrimisRNContainerView *)container floatParentView:(UIView*)floatParentView {
  // Create a player
  NSMutableDictionary* config = @{
    @(PrimisConfigKeyContainerView): container,
    @(PrimisConfigKeyDebugLogActive): @(container.debugLogActive),
    @(PrimisConfigKeyPlacementId): container.placementID,
    @(PrimisConfigKeyAdditionalParams): container.additionalParams,
  }.mutableCopy;
  
  if (floatParentView) {
    config[@(PrimisConfigKeyFlowParentView)] = floatParentView;
  }
  
  PrimisPlayer* player = [[PrimisPlayer alloc] init];
  [player configure:config];
  [player addTo: container.reactViewController];
  return player;
}
 
/// A  helper method to find the floating Parent view by 'nativeID', allowing only a single result.
- (UIView *)findFloatingParentView:(PrimisRNContainerView*)containerView {
  // Find all views with a specified nativeID
  NSMutableArray *array = @[].mutableCopy;
  if (containerView.floatingParentID.length) {
    [self recursiveFindView:containerView.reactViewController.view nativeId:containerView.floatingParentID results:array];
  }
  // Allow only a single result
  switch (array.count) {
    case 0:
      RCTLog(@"Couldn't find a floatingParentView with nativeID %@", containerView.floatingParentID);
      return nil;
    case 1:
      RCTLog(@"Found a floatingParentView with nativeID %@", containerView.floatingParentID);
      return  array.firstObject;
    default:
      RCTLog(@"Found multiple floatingParentViews with nativeID %@. Aborting", containerView.nativeID);
      return nil;
  }
}
 
/// A recursive helper method to find views by 'nativeID'
- (void)recursiveFindView: (UIView*)currentView nativeId:(NSString*)nativeId results:(NSMutableArray*)array  {
  if ([currentView.nativeID isEqualToString: nativeId]) {
    [array addObject:currentView];
  }
  for (UIView *subview in currentView.subviews) {
    [self recursiveFindView:subview nativeId:nativeId results:array];
  }
}
 
@end

Create a native component

Create a file named PrimisPlayerView.js and add it to the root directory of your react-native app.

// PrimisPlayerView.js
 
import { requireNativeComponent } from 'react-native';
 
// requireNativeComponent automatically resolves 'RNTMap' to 'RNTMapManager'
module.exports = requireNativeComponent('PrimisPlayerViewManager');

Add Primis Player view to your page

Add the following to your App.js file

// App.js

import PrimisPlayerView from './PrimisPlayerView.js';

 . . .
 
<PrimisPlayerView 
       placementID={'YOUR_PLACEMENT_ID'} 
       debugLogActive={true} 
       style=... 
/>

Optional: Add nativeID to specify a custom floating parent view

// App.js

import PrimisPlayerView from './PrimisPlayerView.js';

<View nativeID={'UNIQUE_ID'}>
  
 . . .
 
<PrimisPlayerView 
       ...
       floatingParentID={'UNIQUE_ID'} />
         
</View>