SlideShare a Scribd company logo
Reusable
UI Components
in
@ray_deck
Why Would I Ever Do This?
Why Build a UI Component?
1. Deep Cut
Specific need in an otherwise-available component (visionkit)
2. Native Capabilities
Access to previously-unavailable or new subsystems (AR, VR)
3. Third Party Integration
External functionality to orchestrate through RN (CocoaPods)
Be Different
User Experiences
UseCases
Familiar
Terse
Type-Safe
First-Class Support from Apple
Mature (v4.0)
Static Library Support (Xcode 9.0)
react-native-swift
yarn add react-native-swift
RCTBridge
JavascriptCore
RCTBridgeModule
RCTEventEmitter
RCTRootView
RCTViewManager
#import <React/RCTViewManager.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(RNSBoston, RCTEventEmitter)
RCT_EXTERN_METHOD(demo:(NSString *)message
success:(RCTPromiseResolveBlock)success
reject:(RCTPromiseRejectBlock)reject);
RCT_EXTERN_METHOD(delayedSend:(NSString *)message
ms:(NSInteger)ms);
@end
@interface RCT_EXTERN_MODULE(RNSBostonBasicViewManager,
RCTViewManager)
@end
@interface RCT_EXTERN_MODULE(RNSBostonViewManager,
Takeaways
1. The RCTBridge is the core.
2. There is one bridge module instance per class
per bridge
3. Modules are exposed to the bridge using
objective-C macros (RCT_EXPORT_MODULE,
RCT_EXTERN_MODULE, etc)
RCTBridge
JavascriptCore
RCTBridgeModule
RCTViewManager
RCTRootView
RCTViewManager
UIView
UIView
UIView
Takeaways
1. RCTViewManagers are bridge modules, and
follow these rules
2. Views are generated from the ViewManagers
3. RN will control layout and lifecycle of views
emitted from ViewManagers
A Winding Road
Swift
React Native
Bridge
Objective C
Bridge
(.m)
JavascriptCore
react-native-swift-bridge
react-native-swift-bridge --watch
A Less-Winding Road
Swift
React Native
Bridge
react-native-
swift-bridge
JavascriptCore
react-native-swift-cli
yarn global add react-native-swift-cli
1. Start with templates from
react-native-swift-cli
2. Open your app as project for
editing
3. Edit or add files in your static
library – not the app proper
4. Use yarn watch to have your
bridge keep up
>_ yarn global add react-native-swift-cli
rns init RNBoston ; rns makeapp RNBostonApp RNBoston
cd RNBoston; code .
cd ../RNBostonApp; code . ; react-native xcode
Making React Native UI Components with Swift
import Foundation
@objc(RNBostonBasicViewManager)
class RNBostonBasicViewManager: RCTViewManager {
//MARK: RCTViewManager key methods
override func view() -> UIView {
let newView = UIView()
newView.backgroundColor = UIColor.green
return newView
}
override class func requiresMainQueueSetup() -> Bool {
return false;
}
}
Takeaways
1.@objc attribute for code we want to
expose to React native
2.view() is the only method that really
matters
3. requiresMainQueueSetup() should return
false
Making React Native UI Components with Swift
import { requireNativeComponent } from "react-native";
import React, { Component } from "react";
const NativeComponent = requireNativeComponent(
”RNBostonBasicView",
BasicView
);
class BasicView extends Component {
render() {
return <NativeComponent {...this.props} />;
}
}
export default BasicView;
import { BasicView } from “RNBoston”
…
<View style={{height: 90,…}} >
<View style={{ height: 40 }}>
<Text>
Starting with a basic native view. That's the green
thing. Pretty boring.
</Text>
</View>
<BasicView style={{ height: 50, width: "50%" }} />
</View>
Takeaways
1.requireNativeComponent exposes the native
view for a React component wrapper
2. You must create a React component that has
the specific job of wrapping the native view
3. React is kind of awesome
we can do better
Making React Native UI Components with Swift
import Foundation
@objc(RNBostonViewManager)
class RNBostonViewManager: RCTViewManager {
var currentView:RNBostonView?
//MARK: RCTViewManager key methods
override func view() -> RNBostonView {
let newView = RNBostonView()
currentView = newView
return newView
}
override class func requiresMainQueueSetup() -> Bool {
return false;
}
Takeaways
1. Using a custom view class to expose props and
manage a nontrivial UX
2. Connect your view to the view manager through a
reference at creation time
3. Use Caution!
import UIKit
import AVKit
@objc(RNBostonView)
class RNBostonView: UIView {
//MARK: Private (non-RN-managed) properties
var thisSession = AVCaptureSession?
var previewLayer = AVCaptureVideoPreviewLayer?
var isFront:Bool = false
//MARK: React-native exposed props
@objc var onStart:RCTBubblingEventBlock?
@objc var cameraFront:Bool {
get { return isFront }
set(b) {
isFront = b
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { success in
guard success else { return }
guard
let device = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera, mediaType:
AVMediaTypeVideo, position: b ? AVCaptureDevice.Position.front : AVCaptureDevice.Position.back),
let input = try? AVCaptureDeviceInput(device: device)
else { return }
let s = AVCaptureSession()
s.addInput(input)
s.startRunning()
guard let pl = AVCaptureVideoPreviewLayer(session: s) else { return }
DispatchQueue.main.async(){
pl.frame = self.bounds
pl.videoGravity = AVLayerVideoGravityResizeAspectFill
self.layer.addSublayer(pl)
self.previewLayer = pl
if let o = self.onStart { o([:]) }
}
}
}
@objc(RNBostonView)
class RNBostonView: UIView {
//MARK: Private (non-RN-managed) properties
var thisSession = AVCaptureSession?
var previewLayer = AVCaptureVideoPreviewLayer?
var isFront:Bool = false
//MARK: React-native exposed props
@objc var onStart:RCTBubblingEventBlock?
@objc var cameraFront:Bool {
get { return isFront }
set(b) {
isFront = b
AVCaptureDevice.requestAccess…
Takeaways
1. Properties, not methods, are exposed.
2. Properties can be simple “var” declarations or use
get/set pattern
3. Cheat lifecycle events with prop setters
4. Function props are RCTBubblingEventBlocks
5. Declare RCTBubblingEventBlocks as optional (using ?)
Making React Native UI Components with Swift
import { requireNativeComponent } from "react-native";
import React, { Component } from "react";
const NativeVision = requireNativeComponent(”RNBostonView",
CameraView);
class CameraView extends Component {
render() {
return <NativeVision {...this.props} />;
}
}
CameraView.defaultProps = {
onStart: () => {
console.log("I am starting for reals");
},
cameraFront: true
};
export default CameraView;
Takeaways
1. Still Easy
2. Default props make your life easier
3. React – still awesome
One More Thing
import Foundation
@objc(RNBostonViewManager)
class RNBostonViewManager: RCTViewManager {
var currentView:RNBostonView?
//MARK: RCTViewManager key methods
override func view() -> RNBostonView {
let newView = RNBostonView()
currentView = newView
return newView
}
override class func requiresMainQueueSetup() -> Bool {
return false;
}
@objc(RNBostonViewManager)
class RNBostonViewManager: RCTViewManager,
AVCapturePhotoCaptureDelegate {
…
@objc func takePicture(_ resolve:@escaping
RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) {
guard let view = currentView else { reject("no_view",
"No view loaded", nil); return }
guard let session = view.thisSession else {
reject("no_session", "No AV capture session running", nil);
return }
if let p = self.photoOutput {
session.removeOutput(p)
self.photoOutput = nil
Takeaways
1. The ViewManager is a Native Module!
2. Add native module methods to add imperative
logic to your view
3. Use promises (RCTPromiseResolveBlock and
RCTPromiseRejectBlock) to return data
4. Give your app superpowers!
Making React Native UI Components with Swift
import { requiresNativeComponent, NativeModules } from "react-native";
import React, { Component } from "react";
const NativeView = requiresNativeComponent("RNBostonView", CameraView);
class CameraView extends Component {
…
CameraView.takePicture = async () => {
try {
return await NativeModules.RNBostonViewManager.takePicture();
} catch (e) {
return null;
}
};
export default CameraView;
<TouchableOpacity
onPress={async () => {
const result = await CameraView.takePicture();
const newText = result
? "Took a picture!"
: "Error taking picture";
this.setState({ cameraText: newText, imageURL: result.url })
}}
>
<CameraView
style={{ width: "100%", height: "100%" }}
cameraFront={this.state.cameraFront}
/>
</TouchableOpacity>
Takeaways
1. Add imperative functions as class methods for
easy access
2. Return data via async/await for brevity
3. Superpowers.
Up, Up and Away
User Experiences
UseCases
github.com/rhdeck @ray_deck
Ad

Recommended

Scala, Functional Programming and Team Productivity
Scala, Functional Programming and Team Productivity
7mind
 
AngularJS Unit Test
AngularJS Unit Test
Chiew Carol
 
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
distage: Purely Functional Staged Dependency Injection; bonus: Faking Kind Po...
7mind
 
Izumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala Stack
7mind
 
Test Driven Development with JavaFX
Test Driven Development with JavaFX
Hendrik Ebbers
 
ScalaUA - distage: Staged Dependency Injection
ScalaUA - distage: Staged Dependency Injection
7mind
 
Hyper-pragmatic Pure FP testing with distage-testkit
Hyper-pragmatic Pure FP testing with distage-testkit
7mind
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
Jim Lynch
 
Java 9 New Features
Java 9 New Features
Ali BAKAN
 
Gradle talk, Javarsovia 2010
Gradle talk, Javarsovia 2010
Tomek Kaczanowski
 
JavaFX Pitfalls
JavaFX Pitfalls
Alexander Casall
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQuery
Knoldus Inc.
 
Getting Started with React v16
Getting Started with React v16
Benny Neugebauer
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
Hendrik Ebbers
 
Spring Boot
Spring Boot
Jiayun Zhou
 
AngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and Jasmine
foxp2code
 
In the Brain of Hans Dockter: Gradle
In the Brain of Hans Dockter: Gradle
Skills Matter
 
JavaFX8 TestFX - CDI
JavaFX8 TestFX - CDI
Sven Ruppert
 
vJUG - The JavaFX Ecosystem
vJUG - The JavaFX Ecosystem
Andres Almiray
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
Visual Engineering
 
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Julian Robichaux
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
Visual Engineering
 
Architecting your GWT applications with GWT-Platform - Lesson 02
Architecting your GWT applications with GWT-Platform - Lesson 02
rhemsolutions
 
Advanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit Testing
Lars Thorup
 
React native by example by Vadim Ruban
React native by example by Vadim Ruban
Lohika_Odessa_TechTalks
 
The JavaFX Ecosystem
The JavaFX Ecosystem
Andres Almiray
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
FITC
 
Angular performance slides
Angular performance slides
David Barreto
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenment
Artur Szott
 
JSAnkara Swift v React Native
JSAnkara Swift v React Native
Muhammed Demirci
 

More Related Content

What's hot (20)

Java 9 New Features
Java 9 New Features
Ali BAKAN
 
Gradle talk, Javarsovia 2010
Gradle talk, Javarsovia 2010
Tomek Kaczanowski
 
JavaFX Pitfalls
JavaFX Pitfalls
Alexander Casall
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQuery
Knoldus Inc.
 
Getting Started with React v16
Getting Started with React v16
Benny Neugebauer
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
Hendrik Ebbers
 
Spring Boot
Spring Boot
Jiayun Zhou
 
AngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and Jasmine
foxp2code
 
In the Brain of Hans Dockter: Gradle
In the Brain of Hans Dockter: Gradle
Skills Matter
 
JavaFX8 TestFX - CDI
JavaFX8 TestFX - CDI
Sven Ruppert
 
vJUG - The JavaFX Ecosystem
vJUG - The JavaFX Ecosystem
Andres Almiray
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
Visual Engineering
 
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Julian Robichaux
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
Visual Engineering
 
Architecting your GWT applications with GWT-Platform - Lesson 02
Architecting your GWT applications with GWT-Platform - Lesson 02
rhemsolutions
 
Advanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit Testing
Lars Thorup
 
React native by example by Vadim Ruban
React native by example by Vadim Ruban
Lohika_Odessa_TechTalks
 
The JavaFX Ecosystem
The JavaFX Ecosystem
Andres Almiray
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
FITC
 
Angular performance slides
Angular performance slides
David Barreto
 
Java 9 New Features
Java 9 New Features
Ali BAKAN
 
Gradle talk, Javarsovia 2010
Gradle talk, Javarsovia 2010
Tomek Kaczanowski
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQuery
Knoldus Inc.
 
Getting Started with React v16
Getting Started with React v16
Benny Neugebauer
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
Hendrik Ebbers
 
AngularJS Unit Testing w/Karma and Jasmine
AngularJS Unit Testing w/Karma and Jasmine
foxp2code
 
In the Brain of Hans Dockter: Gradle
In the Brain of Hans Dockter: Gradle
Skills Matter
 
JavaFX8 TestFX - CDI
JavaFX8 TestFX - CDI
Sven Ruppert
 
vJUG - The JavaFX Ecosystem
vJUG - The JavaFX Ecosystem
Andres Almiray
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
Visual Engineering
 
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Julian Robichaux
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
Visual Engineering
 
Architecting your GWT applications with GWT-Platform - Lesson 02
Architecting your GWT applications with GWT-Platform - Lesson 02
rhemsolutions
 
Advanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit Testing
Lars Thorup
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
FITC
 
Angular performance slides
Angular performance slides
David Barreto
 

Similar to Making React Native UI Components with Swift (20)

MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenment
Artur Szott
 
JSAnkara Swift v React Native
JSAnkara Swift v React Native
Muhammed Demirci
 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack
Codifly
 
Intro react js
Intro react js
Vijayakanth MP
 
Spring Performance Gains
Spring Performance Gains
VMware Tanzu
 
React & The Art of Managing Complexity
React & The Art of Managing Complexity
Ryan Anklam
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
Ryan Boland
 
Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!
Roberto Franchini
 
React Native for multi-platform mobile applications
React Native for multi-platform mobile applications
Matteo Manchi
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
Visual Engineering
 
L0020 - The Basic RCP Application
L0020 - The Basic RCP Application
Tonny Madsen
 
Angular 2 Migration - JHipster Meetup 6
Angular 2 Migration - JHipster Meetup 6
William Marques
 
React Native Androidはなぜ動くのか
React Native Androidはなぜ動くのか
Yukiya Nakagawa
 
Rcp by example
Rcp by example
tsubramanian80
 
Building cross-platform mobile apps with React Native (Jfokus 2017)
Building cross-platform mobile apps with React Native (Jfokus 2017)
Maarten Mulders
 
reactjs-quiz..docs.pdf
reactjs-quiz..docs.pdf
AyanSarkar78
 
React & Redux for noobs
React & Redux for noobs
[T]echdencias
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
Elyse Kolker Gordon
 
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
Daniel Bryant
 
Connect.js - Exploring React.Native
Connect.js - Exploring React.Native
joshcjensen
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenment
Artur Szott
 
JSAnkara Swift v React Native
JSAnkara Swift v React Native
Muhammed Demirci
 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack
Codifly
 
Spring Performance Gains
Spring Performance Gains
VMware Tanzu
 
React & The Art of Managing Complexity
React & The Art of Managing Complexity
Ryan Anklam
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
Ryan Boland
 
Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!
Roberto Franchini
 
React Native for multi-platform mobile applications
React Native for multi-platform mobile applications
Matteo Manchi
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
Visual Engineering
 
L0020 - The Basic RCP Application
L0020 - The Basic RCP Application
Tonny Madsen
 
Angular 2 Migration - JHipster Meetup 6
Angular 2 Migration - JHipster Meetup 6
William Marques
 
React Native Androidはなぜ動くのか
React Native Androidはなぜ動くのか
Yukiya Nakagawa
 
Building cross-platform mobile apps with React Native (Jfokus 2017)
Building cross-platform mobile apps with React Native (Jfokus 2017)
Maarten Mulders
 
reactjs-quiz..docs.pdf
reactjs-quiz..docs.pdf
AyanSarkar78
 
React & Redux for noobs
React & Redux for noobs
[T]echdencias
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
Elyse Kolker Gordon
 
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
Daniel Bryant
 
Connect.js - Exploring React.Native
Connect.js - Exploring React.Native
joshcjensen
 
Ad

More from Ray Deck (6)

Augmented Reality with JavaScript
Augmented Reality with JavaScript
Ray Deck
 
What's Inside the Box from PAPIs.io 2018
What's Inside the Box from PAPIs.io 2018
Ray Deck
 
Machine Learning and React Native
Machine Learning and React Native
Ray Deck
 
AI On Your Phone: CoreML and Tensorflow Lite
AI On Your Phone: CoreML and Tensorflow Lite
Ray Deck
 
Making Swift Native Modules in React Native
Making Swift Native Modules in React Native
Ray Deck
 
Unboxing ML Models... Plus CoreML!
Unboxing ML Models... Plus CoreML!
Ray Deck
 
Augmented Reality with JavaScript
Augmented Reality with JavaScript
Ray Deck
 
What's Inside the Box from PAPIs.io 2018
What's Inside the Box from PAPIs.io 2018
Ray Deck
 
Machine Learning and React Native
Machine Learning and React Native
Ray Deck
 
AI On Your Phone: CoreML and Tensorflow Lite
AI On Your Phone: CoreML and Tensorflow Lite
Ray Deck
 
Making Swift Native Modules in React Native
Making Swift Native Modules in React Native
Ray Deck
 
Unboxing ML Models... Plus CoreML!
Unboxing ML Models... Plus CoreML!
Ray Deck
 
Ad

Recently uploaded (20)

"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
Fwdays
 
Python Conference Singapore - 19 Jun 2025
Python Conference Singapore - 19 Jun 2025
ninefyi
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
Securing AI - There Is No Try, Only Do!.pdf
Securing AI - There Is No Try, Only Do!.pdf
Priyanka Aash
 
FIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance
 
10 Key Challenges for AI within the EU Data Protection Framework.pdf
10 Key Challenges for AI within the EU Data Protection Framework.pdf
Priyanka Aash
 
9-1-1 Addressing: End-to-End Automation Using FME
9-1-1 Addressing: End-to-End Automation Using FME
Safe Software
 
FIDO Seminar: Perspectives on Passkeys & Consumer Adoption.pptx
FIDO Seminar: Perspectives on Passkeys & Consumer Adoption.pptx
FIDO Alliance
 
PyCon SG 25 - Firecracker Made Easy with Python.pdf
PyCon SG 25 - Firecracker Made Easy with Python.pdf
Muhammad Yuga Nugraha
 
cnc-processing-centers-centateq-p-110-en.pdf
cnc-processing-centers-centateq-p-110-en.pdf
AmirStern2
 
UserCon Belgium: Honey, VMware increased my bill
UserCon Belgium: Honey, VMware increased my bill
stijn40
 
FIDO Seminar: New Data: Passkey Adoption in the Workforce.pptx
FIDO Seminar: New Data: Passkey Adoption in the Workforce.pptx
FIDO Alliance
 
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik
 
Improving Data Integrity: Synchronization between EAM and ArcGIS Utility Netw...
Improving Data Integrity: Synchronization between EAM and ArcGIS Utility Netw...
Safe Software
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
2025_06_18 - OpenMetadata Community Meeting.pdf
2025_06_18 - OpenMetadata Community Meeting.pdf
OpenMetadata
 
Lessons Learned from Developing Secure AI Workflows.pdf
Lessons Learned from Developing Secure AI Workflows.pdf
Priyanka Aash
 
OpenACC and Open Hackathons Monthly Highlights June 2025
OpenACC and Open Hackathons Monthly Highlights June 2025
OpenACC
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
Fwdays
 
Python Conference Singapore - 19 Jun 2025
Python Conference Singapore - 19 Jun 2025
ninefyi
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
Securing AI - There Is No Try, Only Do!.pdf
Securing AI - There Is No Try, Only Do!.pdf
Priyanka Aash
 
FIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance
 
10 Key Challenges for AI within the EU Data Protection Framework.pdf
10 Key Challenges for AI within the EU Data Protection Framework.pdf
Priyanka Aash
 
9-1-1 Addressing: End-to-End Automation Using FME
9-1-1 Addressing: End-to-End Automation Using FME
Safe Software
 
FIDO Seminar: Perspectives on Passkeys & Consumer Adoption.pptx
FIDO Seminar: Perspectives on Passkeys & Consumer Adoption.pptx
FIDO Alliance
 
PyCon SG 25 - Firecracker Made Easy with Python.pdf
PyCon SG 25 - Firecracker Made Easy with Python.pdf
Muhammad Yuga Nugraha
 
cnc-processing-centers-centateq-p-110-en.pdf
cnc-processing-centers-centateq-p-110-en.pdf
AmirStern2
 
UserCon Belgium: Honey, VMware increased my bill
UserCon Belgium: Honey, VMware increased my bill
stijn40
 
FIDO Seminar: New Data: Passkey Adoption in the Workforce.pptx
FIDO Seminar: New Data: Passkey Adoption in the Workforce.pptx
FIDO Alliance
 
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik
 
Improving Data Integrity: Synchronization between EAM and ArcGIS Utility Netw...
Improving Data Integrity: Synchronization between EAM and ArcGIS Utility Netw...
Safe Software
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
2025_06_18 - OpenMetadata Community Meeting.pdf
2025_06_18 - OpenMetadata Community Meeting.pdf
OpenMetadata
 
Lessons Learned from Developing Secure AI Workflows.pdf
Lessons Learned from Developing Secure AI Workflows.pdf
Priyanka Aash
 
OpenACC and Open Hackathons Monthly Highlights June 2025
OpenACC and Open Hackathons Monthly Highlights June 2025
OpenACC
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 

Making React Native UI Components with Swift

  • 2. Why Would I Ever Do This?
  • 3. Why Build a UI Component? 1. Deep Cut Specific need in an otherwise-available component (visionkit) 2. Native Capabilities Access to previously-unavailable or new subsystems (AR, VR) 3. Third Party Integration External functionality to orchestrate through RN (CocoaPods)
  • 6. First-Class Support from Apple Mature (v4.0) Static Library Support (Xcode 9.0)
  • 9. #import <React/RCTViewManager.h> #import <React/RCTEventEmitter.h> #import <React/RCTBridgeModule.h> @interface RCT_EXTERN_MODULE(RNSBoston, RCTEventEmitter) RCT_EXTERN_METHOD(demo:(NSString *)message success:(RCTPromiseResolveBlock)success reject:(RCTPromiseRejectBlock)reject); RCT_EXTERN_METHOD(delayedSend:(NSString *)message ms:(NSInteger)ms); @end @interface RCT_EXTERN_MODULE(RNSBostonBasicViewManager, RCTViewManager) @end @interface RCT_EXTERN_MODULE(RNSBostonViewManager,
  • 10. Takeaways 1. The RCTBridge is the core. 2. There is one bridge module instance per class per bridge 3. Modules are exposed to the bridge using objective-C macros (RCT_EXPORT_MODULE, RCT_EXTERN_MODULE, etc)
  • 12. Takeaways 1. RCTViewManagers are bridge modules, and follow these rules 2. Views are generated from the ViewManagers 3. RN will control layout and lifecycle of views emitted from ViewManagers
  • 13. A Winding Road Swift React Native Bridge Objective C Bridge (.m) JavascriptCore
  • 15. A Less-Winding Road Swift React Native Bridge react-native- swift-bridge JavascriptCore
  • 16. react-native-swift-cli yarn global add react-native-swift-cli
  • 17. 1. Start with templates from react-native-swift-cli 2. Open your app as project for editing 3. Edit or add files in your static library – not the app proper 4. Use yarn watch to have your bridge keep up
  • 18. >_ yarn global add react-native-swift-cli rns init RNBoston ; rns makeapp RNBostonApp RNBoston cd RNBoston; code . cd ../RNBostonApp; code . ; react-native xcode
  • 20. import Foundation @objc(RNBostonBasicViewManager) class RNBostonBasicViewManager: RCTViewManager { //MARK: RCTViewManager key methods override func view() -> UIView { let newView = UIView() newView.backgroundColor = UIColor.green return newView } override class func requiresMainQueueSetup() -> Bool { return false; } }
  • 21. Takeaways 1.@objc attribute for code we want to expose to React native 2.view() is the only method that really matters 3. requiresMainQueueSetup() should return false
  • 23. import { requireNativeComponent } from "react-native"; import React, { Component } from "react"; const NativeComponent = requireNativeComponent( ”RNBostonBasicView", BasicView ); class BasicView extends Component { render() { return <NativeComponent {...this.props} />; } } export default BasicView;
  • 24. import { BasicView } from “RNBoston” … <View style={{height: 90,…}} > <View style={{ height: 40 }}> <Text> Starting with a basic native view. That's the green thing. Pretty boring. </Text> </View> <BasicView style={{ height: 50, width: "50%" }} /> </View>
  • 25. Takeaways 1.requireNativeComponent exposes the native view for a React component wrapper 2. You must create a React component that has the specific job of wrapping the native view 3. React is kind of awesome
  • 26. we can do better
  • 28. import Foundation @objc(RNBostonViewManager) class RNBostonViewManager: RCTViewManager { var currentView:RNBostonView? //MARK: RCTViewManager key methods override func view() -> RNBostonView { let newView = RNBostonView() currentView = newView return newView } override class func requiresMainQueueSetup() -> Bool { return false; }
  • 29. Takeaways 1. Using a custom view class to expose props and manage a nontrivial UX 2. Connect your view to the view manager through a reference at creation time 3. Use Caution!
  • 30. import UIKit import AVKit @objc(RNBostonView) class RNBostonView: UIView { //MARK: Private (non-RN-managed) properties var thisSession = AVCaptureSession? var previewLayer = AVCaptureVideoPreviewLayer? var isFront:Bool = false //MARK: React-native exposed props @objc var onStart:RCTBubblingEventBlock? @objc var cameraFront:Bool { get { return isFront } set(b) { isFront = b AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { success in guard success else { return } guard let device = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: b ? AVCaptureDevice.Position.front : AVCaptureDevice.Position.back), let input = try? AVCaptureDeviceInput(device: device) else { return } let s = AVCaptureSession() s.addInput(input) s.startRunning() guard let pl = AVCaptureVideoPreviewLayer(session: s) else { return } DispatchQueue.main.async(){ pl.frame = self.bounds pl.videoGravity = AVLayerVideoGravityResizeAspectFill self.layer.addSublayer(pl) self.previewLayer = pl if let o = self.onStart { o([:]) } } } }
  • 31. @objc(RNBostonView) class RNBostonView: UIView { //MARK: Private (non-RN-managed) properties var thisSession = AVCaptureSession? var previewLayer = AVCaptureVideoPreviewLayer? var isFront:Bool = false //MARK: React-native exposed props @objc var onStart:RCTBubblingEventBlock? @objc var cameraFront:Bool { get { return isFront } set(b) { isFront = b AVCaptureDevice.requestAccess…
  • 32. Takeaways 1. Properties, not methods, are exposed. 2. Properties can be simple “var” declarations or use get/set pattern 3. Cheat lifecycle events with prop setters 4. Function props are RCTBubblingEventBlocks 5. Declare RCTBubblingEventBlocks as optional (using ?)
  • 34. import { requireNativeComponent } from "react-native"; import React, { Component } from "react"; const NativeVision = requireNativeComponent(”RNBostonView", CameraView); class CameraView extends Component { render() { return <NativeVision {...this.props} />; } } CameraView.defaultProps = { onStart: () => { console.log("I am starting for reals"); }, cameraFront: true }; export default CameraView;
  • 35. Takeaways 1. Still Easy 2. Default props make your life easier 3. React – still awesome
  • 37. import Foundation @objc(RNBostonViewManager) class RNBostonViewManager: RCTViewManager { var currentView:RNBostonView? //MARK: RCTViewManager key methods override func view() -> RNBostonView { let newView = RNBostonView() currentView = newView return newView } override class func requiresMainQueueSetup() -> Bool { return false; }
  • 38. @objc(RNBostonViewManager) class RNBostonViewManager: RCTViewManager, AVCapturePhotoCaptureDelegate { … @objc func takePicture(_ resolve:@escaping RCTPromiseResolveBlock, reject:RCTPromiseRejectBlock) { guard let view = currentView else { reject("no_view", "No view loaded", nil); return } guard let session = view.thisSession else { reject("no_session", "No AV capture session running", nil); return } if let p = self.photoOutput { session.removeOutput(p) self.photoOutput = nil
  • 39. Takeaways 1. The ViewManager is a Native Module! 2. Add native module methods to add imperative logic to your view 3. Use promises (RCTPromiseResolveBlock and RCTPromiseRejectBlock) to return data 4. Give your app superpowers!
  • 41. import { requiresNativeComponent, NativeModules } from "react-native"; import React, { Component } from "react"; const NativeView = requiresNativeComponent("RNBostonView", CameraView); class CameraView extends Component { … CameraView.takePicture = async () => { try { return await NativeModules.RNBostonViewManager.takePicture(); } catch (e) { return null; } }; export default CameraView;
  • 42. <TouchableOpacity onPress={async () => { const result = await CameraView.takePicture(); const newText = result ? "Took a picture!" : "Error taking picture"; this.setState({ cameraText: newText, imageURL: result.url }) }} > <CameraView style={{ width: "100%", height: "100%" }} cameraFront={this.state.cameraFront} /> </TouchableOpacity>
  • 43. Takeaways 1. Add imperative functions as class methods for easy access 2. Return data via async/await for brevity 3. Superpowers.
  • 44. Up, Up and Away User Experiences UseCases