Skip to content

Instantly share code, notes, and snippets.

@sjmueller
Created June 22, 2015 01:10
Show Gist options
  • Save sjmueller/1ba0b5d5496b88a55327 to your computer and use it in GitHub Desktop.
Save sjmueller/1ba0b5d5496b88a55327 to your computer and use it in GitHub Desktop.
Example of a custom react-native component, written in swift. Original author @euforic
// Barcode.swift
import UIKit;
import AVFoundation;
@objc(BarcodeScanner)
public class BarcodeScanner: UIView, AVCaptureMetadataOutputObjectsDelegate {
let session : AVCaptureSession = AVCaptureSession()
var previewLayer : AVCaptureVideoPreviewLayer!
var highlightView : UIView = UIView()
var bridge : RCTEventDispatcher!
var enabled : Bool {
set(newValue) {
println("Setting isScanning to:", newValue)
if newValue {
self.startScanner();
return
}
self.stopScanner();
}
get {
return self.session.running;
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
public func initWithEventDispatcher(bridge: RCTEventDispatcher) -> UIView {
self.bridge = bridge;
// Select the color you want for the completed scan reticle
self.highlightView.layer.borderColor = UIColor.greenColor().CGColor
self.highlightView.layer.borderWidth = 3
// Add it to our controller's view as a subview.
self.addSubview(self.highlightView)
// For the sake of discussion this is the camera
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
// Create a nilable NSError to hand off to the next method.
// Make sure to use the "var" keyword and not "let"
var error : NSError? = nil
let input : AVCaptureDeviceInput? = AVCaptureDeviceInput.deviceInputWithDevice(device, error: &error) as? AVCaptureDeviceInput
// If our input is not nil then add it to the session, otherwise we're kind of done!
if input != nil {
session.addInput(input)
}
else {
// This is fine for a demo, do something real with this in your app. :)
println(error)
}
let output = AVCaptureMetadataOutput()
output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
session.addOutput(output)
output.metadataObjectTypes = output.availableMetadataObjectTypes
previewLayer = AVCaptureVideoPreviewLayer.layerWithSession(session) as! AVCaptureVideoPreviewLayer
previewLayer.frame = self.bounds
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
self.layer.addSublayer(previewLayer)
return self;
}
@objc public func startScanner() {
if !self.session.running {
self.session.startRunning();
}
}
@objc public func stopScanner() {
if self.session.running {
self.session.stopRunning();
}
}
override public func layoutSubviews() {
self.previewLayer.frame = self.bounds
if !self.session.running {
self.session.startRunning()
}
}
// This is called when we find a known barcode type with the camera.
public func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
var highlightViewRect = CGRectZero
var barCodeObject : AVMetadataObject!
var detectionString : String!
let barCodeTypes = [AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeQRCode,
AVMetadataObjectTypeAztecCode
]
// The scanner is capable of capturing multiple 2-dimensional barcodes in one scan.
for metadata in metadataObjects {
for barcodeType in barCodeTypes {
if metadata.type == barcodeType {
barCodeObject = self.previewLayer.transformedMetadataObjectForMetadataObject(metadata as! AVMetadataMachineReadableCodeObject)
highlightViewRect = barCodeObject.bounds
detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue
self.session.stopRunning()
break
}
}
}
if detectionString != nil {
self.bridge.sendDeviceEventWithName("capture", body: detectionString);
}
self.highlightView.frame = highlightViewRect
self.bringSubviewToFront(self.highlightView)
}
}
// BarcodeViewManager.h
#import "RCTViewManager.h"
#import "RCTBridgeModule.h"
@interface BarcodeScannerViewManager: RCTViewManager
@end
// BarcodeViewManager.m
#import "BarcodeScannerViewManager.h"
#import "techtime-Swift.h"
#import "RCTEventDispatcher.h"
#import "RCTBridge.h"
#import "RCTBridgeModule.h"
@implementation BarcodeScannerViewManager
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE();
- (UIView *)view {
return [[[BarcodeScanner alloc] init ] initWithEventDispatcher:_bridge.eventDispatcher];
}
RCT_EXPORT_VIEW_PROPERTY(enabled, BOOL);
@end
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "RCTView.h"
#import "RCTViewManager.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "RCTUtils.h"
#import "UIView+React.h"
#import "RCTLog.h"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment