From 3e3aed457ffd105f8e41d1a97fa181910f9f07e0 Mon Sep 17 00:00:00 2001 From: Lorenzo De Nobili Date: Wed, 5 Oct 2016 16:17:14 -0400 Subject: [PATCH 1/3] refactor(ios): Convert iOS implementation to Swift 3 --- src/ios/QRScanner.swift | 201 ++++++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 100 deletions(-) diff --git a/src/ios/QRScanner.swift b/src/ios/QRScanner.swift index c4a0dad4..9f2d7b7b 100644 --- a/src/ios/QRScanner.swift +++ b/src/ios/QRScanner.swift @@ -14,6 +14,7 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { var backCamera: AVCaptureDevice? var scanning: Bool = false + var scanned: Bool = false var nextScanningCommand: CDVInvokedUrlCommand? enum QRScannerError: Int32 { @@ -28,36 +29,35 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { OPEN_SETTINGS_UNAVAILABLE = 8 } - enum CaptureError: ErrorType { + enum CaptureError: Error { case backCameraUnavailable case frontCameraUnavailable case couldNotCaptureInput(error: NSError) } - enum LightError: ErrorType { + enum LightError: Error { case torchUnavailable } override func pluginInitialize() { - super.pluginInitialize() - NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(pageDidLoad), name: CDVPageDidLoadNotification, object: nil) - self.cameraView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width, height: UIScreen.mainScreen().bounds.height)) + super.pluginInitialize() + NotificationCenter.default.addObserver(self, selector: #selector(pageDidLoad), name: NSNotification.Name.CDVPageDidLoad, object: nil) + self.cameraView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)) } func sendErrorCode(command: CDVInvokedUrlCommand, error: QRScannerError){ - let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAsInt: error.rawValue) - commandDelegate!.sendPluginResult(pluginResult, callbackId:command.callbackId) + let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.rawValue) + commandDelegate!.send(pluginResult, callbackId:command.callbackId) } // utility method func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) { if #available(iOS 8.0, *) { - dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.rawValue), 0)) { - if(background != nil){ + DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async { + if (background != nil) { background!() } - let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) - dispatch_after(popTime, dispatch_get_main_queue()) { + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay * Double(NSEC_PER_SEC)) { if(completion != nil){ completion!() } @@ -75,24 +75,24 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { } func prepScanner(command: CDVInvokedUrlCommand) -> Bool{ - let status = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) - if (status == AVAuthorizationStatus.Restricted) { - self.sendErrorCode(command, error: QRScannerError.CAMERA_ACCESS_RESTRICTED) + let status = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) + if (status == AVAuthorizationStatus.restricted) { + self.sendErrorCode(command: command, error: QRScannerError.CAMERA_ACCESS_RESTRICTED) return false - } else if status == AVAuthorizationStatus.Denied { - self.sendErrorCode(command, error: QRScannerError.CAMERA_ACCESS_DENIED) + } else if status == AVAuthorizationStatus.denied { + self.sendErrorCode(command: command, error: QRScannerError.CAMERA_ACCESS_DENIED) return false } do { - if (captureSession?.running != true){ - cameraView.backgroundColor = UIColor.whiteColor() + if (captureSession?.isRunning != true){ + cameraView.backgroundColor = UIColor.white self.webView!.superview!.insertSubview(cameraView, belowSubview: self.webView!) - let availableVideoDevices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) + let availableVideoDevices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) for device in availableVideoDevices as! [AVCaptureDevice] { - if device.position == AVCaptureDevicePosition.Back { + if device.position == AVCaptureDevicePosition.back { backCamera = device } - else if device.position == AVCaptureDevicePosition.Front { + else if device.position == AVCaptureDevicePosition.front { frontCamera = device } } @@ -106,7 +106,7 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { captureSession!.addInput(input) metaOutput = AVCaptureMetadataOutput() captureSession!.addOutput(metaOutput) - metaOutput!.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue()) + metaOutput!.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) metaOutput!.metadataObjectTypes = [AVMetadataObjectTypeQRCode] captureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession) captureVideoPreviewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill @@ -116,14 +116,14 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { } return true } catch CaptureError.backCameraUnavailable { - self.sendErrorCode(command, error: QRScannerError.BACK_CAMERA_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.BACK_CAMERA_UNAVAILABLE) } catch CaptureError.frontCameraUnavailable { - self.sendErrorCode(command, error: QRScannerError.FRONT_CAMERA_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.FRONT_CAMERA_UNAVAILABLE) } catch CaptureError.couldNotCaptureInput(let error){ print(error.localizedDescription) - self.sendErrorCode(command, error: QRScannerError.CAMERA_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.CAMERA_UNAVAILABLE) } catch { - self.sendErrorCode(command, error: QRScannerError.UNEXPECTED_ERROR) + self.sendErrorCode(command: command, error: QRScannerError.UNEXPECTED_ERROR) } return false } @@ -153,8 +153,8 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { } func makeOpaque(){ - self.webView?.opaque = true - self.webView?.backgroundColor = UIColor.whiteColor() + self.webView?.isOpaque = true + self.webView?.backgroundColor = UIColor.white } func boolToNumberString(bool: Bool) -> String{ @@ -166,13 +166,13 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { } func configureLight(command: CDVInvokedUrlCommand, state: Bool){ - var useMode = AVCaptureTorchMode.On + var useMode = AVCaptureTorchMode.on if(state == false){ - useMode = AVCaptureTorchMode.Off + useMode = AVCaptureTorchMode.off } do { // torch is only available for back camera - if(backCamera == nil || backCamera!.hasTorch == false || backCamera!.torchAvailable == false || backCamera!.isTorchModeSupported(useMode) == false){ + if(backCamera == nil || backCamera!.hasTorch == false || backCamera!.isTorchAvailable == false || backCamera!.isTorchModeSupported(useMode) == false){ throw LightError.torchUnavailable } try backCamera!.lockForConfiguration() @@ -180,16 +180,15 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { backCamera!.unlockForConfiguration() self.getStatus(command) } catch LightError.torchUnavailable { - self.sendErrorCode(command, error: QRScannerError.LIGHT_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.LIGHT_UNAVAILABLE) } catch let error as NSError { print(error.localizedDescription) - self.sendErrorCode(command, error: QRScannerError.UNEXPECTED_ERROR) + self.sendErrorCode(command: command, error: QRScannerError.UNEXPECTED_ERROR) } } // This method processes metadataObjects captured by iOS. - - func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) { + func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) { if metadataObjects == nil || metadataObjects.count == 0 || scanning == false { // while nothing is detected, or if scanning is false, do nothing. return @@ -197,86 +196,88 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { let found = metadataObjects[0] as! AVMetadataMachineReadableCodeObject if found.type == AVMetadataObjectTypeQRCode && found.stringValue != nil { scanning = false - let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAsString: found.stringValue) - commandDelegate!.sendPluginResult(pluginResult, callbackId: nextScanningCommand?.callbackId!) + let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: found.stringValue) + commandDelegate!.send(pluginResult, callbackId: nextScanningCommand?.callbackId!) nextScanningCommand = nil } } func pageDidLoad() { - self.webView?.opaque = false - self.webView?.backgroundColor = UIColor.clearColor() + self.webView?.isOpaque = false + self.webView?.backgroundColor = UIColor.clear } // ---- BEGIN EXTERNAL API ---- - func prepare(command: CDVInvokedUrlCommand){ - let status = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) - if (status == AVAuthorizationStatus.NotDetermined) { + func prepare(_ command: CDVInvokedUrlCommand){ + let status = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) + if (status == AVAuthorizationStatus.notDetermined) { // Request permission before preparing scanner - AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted) -> Void in + AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (granted) -> Void in // attempt to prepScanner only after the request returns - self.backgroundThread(0, completion: { - if(self.prepScanner(command)){ + self.backgroundThread(delay: 0, completion: { + if(self.prepScanner(command: command)){ self.getStatus(command) } }) }) } else { - if(self.prepScanner(command)){ + if(self.prepScanner(command: command)){ self.getStatus(command) } } } - func scan(command: CDVInvokedUrlCommand){ - if(self.prepScanner(command)){ + func scan(_ command: CDVInvokedUrlCommand){ + if(self.prepScanner(command: command)){ nextScanningCommand = command + scanned = false scanning = true } } - func cancelScan(command: CDVInvokedUrlCommand){ - if(self.prepScanner(command)){ + func cancelScan(_ command: CDVInvokedUrlCommand){ + if(self.prepScanner(command: command)){ scanning = false + scanned = false if(nextScanningCommand != nil){ - self.sendErrorCode(nextScanningCommand!, error: QRScannerError.SCAN_CANCELED) + self.sendErrorCode(command: nextScanningCommand!, error: QRScannerError.SCAN_CANCELED) } self.getStatus(command) } } - func show(command: CDVInvokedUrlCommand) { - self.webView?.opaque = false - self.webView?.backgroundColor = UIColor.clearColor() + func show(_ command: CDVInvokedUrlCommand) { + self.webView?.isOpaque = false + self.webView?.backgroundColor = UIColor.clear self.getStatus(command) } - func hide(command: CDVInvokedUrlCommand) { + func hide(_ command: CDVInvokedUrlCommand) { self.makeOpaque() self.getStatus(command) } - func pausePreview(command: CDVInvokedUrlCommand) { - captureVideoPreviewLayer?.connection.enabled = false + func pausePreview(_ command: CDVInvokedUrlCommand) { + captureVideoPreviewLayer?.connection.isEnabled = false self.getStatus(command) } - func resumePreview(command: CDVInvokedUrlCommand) { - captureVideoPreviewLayer?.connection.enabled = true + func resumePreview(_ command: CDVInvokedUrlCommand) { + captureVideoPreviewLayer?.connection.isEnabled = true self.getStatus(command) } // backCamera is 0, frontCamera is 1 - func useCamera(command: CDVInvokedUrlCommand){ + func useCamera(_ command: CDVInvokedUrlCommand){ let index = command.arguments[0] as! Int if(currentCamera != index){ // camera change only available if both backCamera and frontCamera exist if(backCamera != nil && frontCamera != nil){ // switch camera currentCamera = index - if(self.prepScanner(command)){ + if(self.prepScanner(command: command)){ do { captureSession!.beginConfiguration() let currentInput = captureSession?.inputs[0] as! AVCaptureDeviceInput @@ -286,22 +287,22 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { captureSession!.commitConfiguration() self.getStatus(command) } catch CaptureError.backCameraUnavailable { - self.sendErrorCode(command, error: QRScannerError.BACK_CAMERA_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.BACK_CAMERA_UNAVAILABLE) } catch CaptureError.frontCameraUnavailable { - self.sendErrorCode(command, error: QRScannerError.FRONT_CAMERA_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.FRONT_CAMERA_UNAVAILABLE) } catch CaptureError.couldNotCaptureInput(let error){ print(error.localizedDescription) - self.sendErrorCode(command, error: QRScannerError.CAMERA_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.CAMERA_UNAVAILABLE) } catch { - self.sendErrorCode(command, error: QRScannerError.UNEXPECTED_ERROR) + self.sendErrorCode(command: command, error: QRScannerError.UNEXPECTED_ERROR) } } } else { if(backCamera == nil){ - self.sendErrorCode(command, error: QRScannerError.BACK_CAMERA_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.BACK_CAMERA_UNAVAILABLE) } else { - self.sendErrorCode(command, error: QRScannerError.FRONT_CAMERA_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.FRONT_CAMERA_UNAVAILABLE) } } } else { @@ -310,22 +311,22 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { } } - func enableLight(command: CDVInvokedUrlCommand) { - if(self.prepScanner(command)){ - self.configureLight(command, state: true) + func enableLight(_ command: CDVInvokedUrlCommand) { + if(self.prepScanner(command: command)){ + self.configureLight(command: command, state: true) } } - func disableLight(command: CDVInvokedUrlCommand) { - if(self.prepScanner(command)){ - self.configureLight(command, state: false) + func disableLight(_ command: CDVInvokedUrlCommand) { + if(self.prepScanner(command: command)){ + self.configureLight(command: command, state: false) } } - func destroy(command: CDVInvokedUrlCommand) { + func destroy(_ command: CDVInvokedUrlCommand) { self.makeOpaque() if(self.captureSession != nil){ - backgroundThread(0, background: { + backgroundThread(delay: 0, background: { self.captureSession!.stopRunning() self.captureVideoPreviewLayer!.removeFromSuperlayer() self.captureVideoPreviewLayer = nil @@ -342,42 +343,42 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { } } - func getStatus(command: CDVInvokedUrlCommand){ + func getStatus(_ command: CDVInvokedUrlCommand){ - let authorizationStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo); + let authorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo); var authorized = false - if(authorizationStatus == AVAuthorizationStatus.Authorized){ + if(authorizationStatus == AVAuthorizationStatus.authorized){ authorized = true } var denied = false - if(authorizationStatus == AVAuthorizationStatus.Denied){ + if(authorizationStatus == AVAuthorizationStatus.denied){ denied = true } var restricted = false - if(authorizationStatus == AVAuthorizationStatus.Restricted){ + if(authorizationStatus == AVAuthorizationStatus.restricted){ restricted = true } var prepared = false - if(captureSession?.running == true){ + if(captureSession?.isRunning == true){ prepared = true } var previewing = false if(captureVideoPreviewLayer != nil){ - previewing = captureVideoPreviewLayer!.connection.enabled + previewing = captureVideoPreviewLayer!.connection.isEnabled } var showing = false - if(self.webView!.backgroundColor == UIColor.clearColor()){ + if(self.webView!.backgroundColor == UIColor.clear){ showing = true } var lightEnabled = false - if(backCamera?.torchMode == AVCaptureTorchMode.On){ + if(backCamera?.torchMode == AVCaptureTorchMode.on){ lightEnabled = true } @@ -387,7 +388,7 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { } var canEnableLight = false - if(backCamera?.hasTorch == true && backCamera?.torchAvailable == true && backCamera?.isTorchModeSupported(AVCaptureTorchMode.On) == true){ + if(backCamera?.hasTorch == true && backCamera?.isTorchAvailable == true && backCamera?.isTorchModeSupported(AVCaptureTorchMode.on) == true){ canEnableLight = true } @@ -397,30 +398,30 @@ class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate { } let status = [ - "authorized": boolToNumberString(authorized), - "denied": boolToNumberString(denied), - "restricted": boolToNumberString(restricted), - "prepared": boolToNumberString(prepared), - "scanning": boolToNumberString(scanning), - "previewing": boolToNumberString(previewing), - "showing": boolToNumberString(showing), - "lightEnabled": boolToNumberString(lightEnabled), - "canOpenSettings": boolToNumberString(canOpenSettings), - "canEnableLight": boolToNumberString(canEnableLight), - "canChangeCamera": boolToNumberString(canChangeCamera), + "authorized": boolToNumberString(bool: authorized), + "denied": boolToNumberString(bool: denied), + "restricted": boolToNumberString(bool: restricted), + "prepared": boolToNumberString(bool: prepared), + "scanning": boolToNumberString(bool: scanning), + "previewing": boolToNumberString(bool: previewing), + "showing": boolToNumberString(bool: showing), + "lightEnabled": boolToNumberString(bool: lightEnabled), + "canOpenSettings": boolToNumberString(bool: canOpenSettings), + "canEnableLight": boolToNumberString(bool: canEnableLight), + "canChangeCamera": boolToNumberString(bool: canChangeCamera), "currentCamera": String(currentCamera) ] - let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAsDictionary: status) - commandDelegate!.sendPluginResult(pluginResult, callbackId:command.callbackId) + let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: status) + commandDelegate!.send(pluginResult, callbackId:command.callbackId) } func openSettings(command: CDVInvokedUrlCommand) { if #available(iOS 8.0, *) { - UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!) + UIApplication.shared.openURL(NSURL(string: UIApplicationOpenSettingsURLString)! as URL) self.getStatus(command) } else { - self.sendErrorCode(command, error: QRScannerError.OPEN_SETTINGS_UNAVAILABLE) + self.sendErrorCode(command: command, error: QRScannerError.OPEN_SETTINGS_UNAVAILABLE) } } } From dca1f7e58d04b1cff12707750920c0451192282a Mon Sep 17 00:00:00 2001 From: Jason Dreyzehner Date: Wed, 5 Oct 2016 19:57:35 -0400 Subject: [PATCH 2/3] feat(ios): remove need for the swift-support hook, remove script The plugin now requires cordova-plugin-swift-support as a dependency. This package handles the job more effectively, and doesn't require cordova-plugin-qrscanner consumers to make any special configuration changes to install the plugin on iOS. --- plugin.xml | 4 +- scripts/swift-support.js | 143 ---------------------------- src/ios/QRScanner-Bridging-Header.h | 5 - tests/project/config.xml | 4 - tests/project/package.json | 2 +- 5 files changed, 3 insertions(+), 155 deletions(-) delete mode 100644 scripts/swift-support.js delete mode 100644 src/ios/QRScanner-Bridging-Header.h diff --git a/plugin.xml b/plugin.xml index 0d26cc12..507fee52 100755 --- a/plugin.xml +++ b/plugin.xml @@ -1,7 +1,7 @@ + version="2.3.4"> QRScanner @@ -35,7 +35,7 @@ - + The camera is used to scan QR codes. diff --git a/scripts/swift-support.js b/scripts/swift-support.js deleted file mode 100644 index 6577dbd1..00000000 --- a/scripts/swift-support.js +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -// This hook is derived from iosrtc-swift-support.js in cordova-plugin-iosrtc -// -// Usage in cordova project config.xml: -// -// -// - -var - fs = require('fs'), - path = require('path'), - xcode = require('xcode'), - - BUILD_VERSION = '7.0', - SWIFT_VERSION_XCODE = '2.3', - BUILD_VERSION_XCODE = '"' + BUILD_VERSION + '"', - RUNPATH_SEARCH_PATHS = '@executable_path/Frameworks', - RUNPATH_SEARCH_PATHS_XCODE = '"' + RUNPATH_SEARCH_PATHS + '"', - ENABLE_BITCODE = 'NO', - ENABLE_BITCODE_XCODE = '"' + ENABLE_BITCODE + '"', - BRIDGING_HEADER_END = '/Plugins/cordova-plugin-qrscanner/QRScanner-Bridging-Header.h', - COMMENT_KEY = /_comment$/; - - -// Helpers - -// Returns the project name -function getProjectName(protoPath) { - var - cordovaConfigPath = path.join(protoPath, 'config.xml'), - content = fs.readFileSync(cordovaConfigPath, 'utf-8'); - - return /([\s\S]*)<\/name>/mi.exec(content)[1].trim(); -} - -// Drops the comments -function nonComments(obj) { - var - keys = Object.keys(obj), - newObj = {}, - i = 0; - - for (i; i < keys.length; i += 1) { - if (!COMMENT_KEY.test(keys[i])) { - newObj[keys[i]] = obj[keys[i]]; - } - } - - return newObj; -} - -function debug (msg) { - console.log('swift-support.js [INFO] ' + msg); -} - -function debugerror(msg) { - console.error('swift-support.js [ERROR] ' + msg); -} - -// Starting here - -module.exports = function (context) { - var - projectRoot = context.opts.projectRoot, - projectName = getProjectName(projectRoot), - xcconfigPath = path.join(projectRoot, '/platforms/ios/cordova/build.xcconfig'), - xcodeProjectName = projectName + '.xcodeproj', - xcodeProjectPath = path.join(projectRoot, 'platforms', 'ios', xcodeProjectName, 'project.pbxproj'), - swiftBridgingHead = projectName + BRIDGING_HEADER_END, - swiftBridgingHeadXcode = '"' + swiftBridgingHead + '"', - swiftOptions = [''], // <-- begin to file appending AFTER initial newline - xcodeProject; - - debug('Enabling Swift for cordova-plugin-qrscanner.'); - - // Checking if the project files are in the right place - if (!fs.existsSync(xcodeProjectPath)) { - debugerror('an error occurred searching the project file at: "' + xcodeProjectPath + '"'); - - return; - } - debug('".pbxproj" project file found: ' + xcodeProjectPath); - - if (!fs.existsSync(xcconfigPath)) { - debugerror('an error occurred searching the project file at: "' + xcconfigPath + '"'); - - return; - } - debug('".xcconfig" project file found: ' + xcconfigPath); - - xcodeProject = xcode.project(xcodeProjectPath); - - // Showing info about the tasks to do - debug('fixing issues in the generated project files:'); - debug('- "iOS Deployment Target" and "Deployment Target" to: ' + BUILD_VERSION_XCODE); - debug('- "Runpath Search Paths" to: ' + RUNPATH_SEARCH_PATHS_XCODE); - debug('- "Objective-C Bridging Header" to: ' + swiftBridgingHeadXcode); - debug('- "ENABLE_BITCODE" set to: ' + ENABLE_BITCODE_XCODE); - - - // Massaging the files - - // "build.xcconfig" - swiftOptions.push('LD_RUNPATH_SEARCH_PATHS = ' + RUNPATH_SEARCH_PATHS); - swiftOptions.push('SWIFT_OBJC_BRIDGING_HEADER = ' + swiftBridgingHead); - swiftOptions.push('IPHONEOS_DEPLOYMENT_TARGET = ' + BUILD_VERSION); - swiftOptions.push('ENABLE_BITCODE = ' + ENABLE_BITCODE); - // NOTE: Not needed - // swiftOptions.push('EMBEDDED_CONTENT_CONTAINS_SWIFT = YES'); - fs.appendFileSync(xcconfigPath, swiftOptions.join('\n')); - debug('file correctly fixed: ' + xcconfigPath); - - // "project.pbxproj" - // Parsing it - xcodeProject.parse(function (error) { - var configurations, buildSettings; - - if (error) { - debugerror('an error occurred during the parsing of the project file'); - - return; - } - - - configurations = nonComments(xcodeProject.pbxXCBuildConfigurationSection()); - // Adding or changing the parameters we need - Object.keys(configurations).forEach(function (config) { - buildSettings = configurations[config].buildSettings; - buildSettings.LD_RUNPATH_SEARCH_PATHS = RUNPATH_SEARCH_PATHS_XCODE; - buildSettings.SWIFT_OBJC_BRIDGING_HEADER = swiftBridgingHeadXcode; - buildSettings.IPHONEOS_DEPLOYMENT_TARGET = BUILD_VERSION_XCODE; - buildSettings.ENABLE_BITCODE = ENABLE_BITCODE_XCODE; - buildSettings.SWIFT_VERSION = SWIFT_VERSION_XCODE; - }); - - // Writing the file again - fs.writeFileSync(xcodeProjectPath, xcodeProject.writeSync(), 'utf-8'); - debug('file correctly fixed: ' + xcodeProjectPath); - }); -}; diff --git a/src/ios/QRScanner-Bridging-Header.h b/src/ios/QRScanner-Bridging-Header.h deleted file mode 100644 index af802d69..00000000 --- a/src/ios/QRScanner-Bridging-Header.h +++ /dev/null @@ -1,5 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - -#import diff --git a/tests/project/config.xml b/tests/project/config.xml index b92e527e..ef979c38 100644 --- a/tests/project/config.xml +++ b/tests/project/config.xml @@ -21,13 +21,9 @@ - - - The test app uses the camera to scan QR codes. - diff --git a/tests/project/package.json b/tests/project/package.json index b3c65c30..fc215ec5 100644 --- a/tests/project/package.json +++ b/tests/project/package.json @@ -4,7 +4,7 @@ "scripts": { "clean": "rm -rf node_modules && rm -rf platforms && rm -rf plugins", "postinstall": "node scripts/timestamp.js && cordova prepare", - "test:ios": "cordova build ios && open platforms/ios/CvQRScnTst.xcodeproj", + "test:ios": "cordova prepare ios && cordova build ios && open platforms/ios/CvQRScnTst.xcodeproj", "test:browser": "cordova run browser", "test:android": "cordova build android && open -a /Applications/Android\\ Studio.app platforms/android" }, From 74a4d0ef414481033ed9c52155f798ddb09e1951 Mon Sep 17 00:00:00 2001 From: Jason Dreyzehner Date: Wed, 5 Oct 2016 19:58:27 -0400 Subject: [PATCH 3/3] docs(readme): remove references to the old swift-support hook for iOS --- readme.md | 48 +----------------------------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/readme.md b/readme.md index cd20724a..2147f4a1 100755 --- a/readme.md +++ b/readme.md @@ -13,7 +13,7 @@ QRScanner's native camera preview is rendered behind the Cordova app's webview, cordova plugin add cordova-plugin-qrscanner ``` -On most platforms, simply adding the plugin to the Cordova project will make the `window.QRScanner` global object available once the `deviceready` event propagates. +Simply adding this plugin to the Cordova project will make the `window.QRScanner` global object available once the `deviceready` event propagates. ### Usage @@ -79,52 +79,6 @@ QRScanner.show(); Please see the [full API docs](#api) for details about each method, [error handling](#error-handling), and [platform specific details](#platform-specific-details). -### iOS Installation - -This plugin requires some additional installation steps for the iOS platform. - -The iOS component of the plugin is written in Swift 2.3. To enable it, be sure you're running the lastest version of Xcode, then add the following hook and setting to the iOS platform in your Cordova app's `config.xml`: - -```xml - - - - The camera is used to scan QR codes. - - -``` - -The script requires the `xcode` npm module. (This will already be installed as a dependency of `cordova-plugin-qrscanner` if you install this package via npm.) - -```bash -npm install --save xcode -``` - -Swift will now be enabled during your build, and the `QRScanner` plugin will be available in your app. - -Starting with iOS 10, a non-empty `NSCameraUsageDescription` string is also required to avoid a runtime exit. This field can be provided in a single language or localized using the `InfoPlist.strings` file. (Note: Apps with an empty `NSCameraUsageDescription` will not exit at runtime, but are rejected by iTunes Connect when uploaded for distribution.) - -#### Using multiple Cordova plugins written in Swift - -Because Cordova is written in Objective-C, Cordova plugins written in Swift [require a `bridging header` to interact with Cordova](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html). - -A project can only have one bridging header. If your app uses plugins other than `cordova-plugin-qrscanner` which are also written in Swift, you will need to create a master bridging header to import each. Create a new bridging header and import each of the plugins' bridging headers, for example: - -```c -// MyProject-Bridging-Header.h -// Use this file to import your target's public headers that you would like to expose to Swift. - -//cordova-plugin-apple-watch -#import "Watch-Bridge.h" - -//com.eface2face.iosrtc -#import "iosrtc-Bridging-Header.h" - -//cordova-plugin-qrscanner -#import "QRScanner-Bridging-Header.h" -``` -Copy the script from `cordova-plugin-qrscanner/scripts/swift-support.js` into your project (eg. into the `hooks` folder), and modify the `BRIDGING_HEADER_END` variable to point to your new bridging header. Finally, remove and re-add the ios platform to trigger the hook. See [this issue](https://github.com/eface2face/cordova-plugin-iosrtc/issues/9) for more information. - ### Electron or NW.js usage without `cordova-browser` If your app uses the Cordova Browser platform, simply adding the plugin to the Cordova project will make the `window.QRScanner` global object available once the `deviceready` event propagates. For apps not using `cordova-browser`, this plugin is also available as a simple javascript library.