How to implement Nuance Speechkit when using CocoaPods in Swift - ios

Between the pod spec and what is currently on S.O. I had a tough time figuring out how to get speech-to-text working using SpeechKit + CocoaPod + Swift. Finally got it working so figured I'd help the next poor soul that comes looking for help! :)

First install the CocoaPod: https://cocoapods.org/pods/SpeechKit
Add #import <SpeechKit/SpeechKit.h> to your bridging header
Login to Nuance's dev portal and create an app: https://developer.nuance.com/
Clean up the demo code so that is is more organized. I just wanted as much of the code to be in one place as possible so you can see a fully working implementation.
Then create a UIViewController and add the following code with the correct credentials:
import UIKit
import SpeechKit
class SpeechKitDemo: UIViewController, SKTransactionDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//!!link this to a corresponding button on the UIViewController in I.B.
#IBAction func tappedButton(sender: AnyObject) {
// All fields are required.
// Your credentials can be found in your Nuance Developers portal, under "Manage My Apps".
let SKSAppKey = "[Get this from the nuance app info page]";
let SKSAppId = "[Get this from the nuance app info page]";
let SKSServerHost = "[Get this from the nuance app info page]";
let SKSServerPort = "[Get this from the nuance app info page]";
let SKSLanguage = "eng-USA";
let SKSServerUrl = "nmsps://\(SKSAppId)#\(SKSServerHost):\(SKSServerPort)"
let session = SKSession(URL: NSURL(string: SKSServerUrl), appToken: SKSAppKey)
//this starts a transaction that listens for voice input
let transaction = session.recognizeWithType(SKTransactionSpeechTypeDictation,
detection: .Short,
language: SKSLanguage,
delegate: self)
print(transaction)
}
//required delegate methods
func transactionDidBeginRecording(transaction: SKTransaction!) { }
func transactionDidFinishRecording(transaction: SKTransaction!) { }
func transaction(transaction: SKTransaction!, didReceiveRecognition recognition: SKRecognition!) {
//Take the best result
let topRecognitionText = recognition.text;
print("Best rec test: \(topRecognitionText)")
//Or iterate through the NBest list
let nBest = recognition.details;
for phrase in (nBest as! [SKRecognizedPhrase]!) {
let text = phrase.text;
let confidence = phrase.confidence;
print("\(confidence): \(text)")
}
}
func transaction(transaction: SKTransaction!, didReceiveServiceResponse response: [NSObject : AnyObject]!) { }
func transaction(transaction: SKTransaction!, didFinishWithSuggestion suggestion: String!) { }
func transaction(transaction: SKTransaction!, didFailWithError error: NSError!, suggestion: String!) { }
}

Related

How do I fix for the user inputs to be sent to Firebase database under the User's profile?

So, say user registration is done (this code is already correct) and the next window asks users to enter personal info (education etc), how do you code that this information goes to Firebase under the user's profile.
I have the registration page done and users created there already go to firebase.
This is what I have for the page after registration. No errors but obviously incomplete.
import UIKit
import Firebase
import CoreFoundation
import AVFoundation
import SwiftKeychainWrapper
import FirebaseDatabase
class FeedVC: UITableViewController {
override func viewDidLoad() {
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Sign Out", style: .plain, target: self, action: #selector(signOut))
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
post()
}
//override func didReceiveMemoryWarning() {
// super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
// }
// MARK: - Table view data source
//override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
//return 1
// }
// override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
//return 5
// }
//override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// return UITableViewCell()
//}
func post() {
let MainFunInterest = "MainFunInterest"
let SomethingInterestingIhaveRead = "SomethingInterestingIhaveRead"
let JobOrEducation = "JobOrEducation"
let WhatIamConsideringBuying = "WhatIamConsideringBuying"
let post : [String : AnyObject] = ["MainFunInterest" : MainFunInterest as AnyObject,
"SomethingInterestingIhaveRead" : SomethingInterestingIhaveRead as AnyObject,
"JobOrEducation" : JobOrEducation as AnyObject,
"WhatIamConsideringBuying" : WhatIamConsideringBuying as AnyObject]
let databaseRef = Database.database().reference()
databaseRef.child("personal info").childByAutoId().setValue(post)
}
#objc func signOut (_sender: AnyObject) {
KeychainWrapper.standard.removeObject(forKey: "uid")
do {
try Auth.auth().signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
dismiss(animated: true, completion: nil)
}
}
I can sign out of the page. When I register currently, what goes to firebase is just the stock description that user is expected to enter (for example "education" is registered in firebase rather than what user should type in.
I see you use FirebaseDatabase but I forgot if that's the new FirebaseFirestore or not. Anyway, in this case, you will either need read more firebase database related documentation to create your own database query or you will need to read the data from "education" first then write your own write, update, delete method to handle data changes then repost them or update them.
Hopefully helped!

Sinch framework (Objective C) and Swift not compatible

I am using Sinch SDK (link) which is written in Objective C.
But I am making a Swift application. I created bridge header and I added some basic functionality in the view controller:
import UIKit
class ViewController: UIViewController, SINMessageClientDelegate {
override func viewDidLoad() {
super.viewDidLoad()
initializeSinch()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func initializeSinch()
{
// Instantiate a Sinch client object
let sinchClient = Sinch.clientWithApplicationKey("xxxxxxxxxxxx", applicationSecret: "xxxxxxxxxx", environmentHost: "sandbox.sinch.com", userId: "user1")
sinchClient.setSupportMessaging(true)
sinchClient.start()
let messageClient = sinchClient.messageClient()
let message = SINOutgoingMessage(recipient: "user2", text: "Test 123, test 123")
messageClient.sendMessage(message)
}
// Tells the delegate that a message has been received.
func messageClient(messageClient: SINMessageClient, didReceiveIncomingMessage message: SINMessage) {
// Present a Local Notification if app is in background
if UIApplication.sharedApplication().applicationState == .Background {
var notification: UILocalNotification = UILocalNotification()
notification.alertBody = "Message from \(message.recipientIds[0])"
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}
else {
// Update UI in-app
}
}
// Tells the delegate that a message for a specific recipient has been sent by the local user.
func messageSent(message: SINMessage, recipientId: String) {
// var a = 1
}
//
// Tells the delegate that a message has been delivered (to a particular recipient).
func messageDelivered(info: SINMessageDeliveryInfo) {
// var a = 1
}
func messageFailed(message: SINMessage, info messageFailureInfo: SINMessageFailureInfo) {
// var a = 1
}
}
This is how the error looks like.
Can someone advice how can I fix this?
Have you added all the neccesary frameworks, and the linker flags?
AudioToolbox.framework
AVFoundation.framework
Security.framework
Some additional linker flags need to be added. In the Build Settings pane for the application target, set the following:
Other Linker Flags -> -ObjC -Xlinker -lc++
https://www.sinch.com/docs/voice/ios/

Stream 2 videos simultaneously Swift

I'm trying to stream two videos at the same time with swift on iphone. I already know that the AV Player can only stream one video at a time, but googling it I saw that it's still possible to stream different tracks at the same time. I also saw the picture in picture implementation. The real problem is that is all in objective-c and the code is quite old. I tried to understand it running the code as it is, but there are errors and some of the functions are deprecated.
Does someone know how to do that in swift? Also, I'm streaming video from the internet so merging them before playing is not an option.
Thank you!
Swift Version
The article you referenced is an interesting method of handling multiple video playback in iOS. The article appears to be related to Apple's Stitched Stream Player Sample Project. As an exercise in Swift 2.2, I've rewritten the code on the iOS Guy article.
You can find both the view and the view controller in Swift on my gist. I'm copying below as it is best practices to not use link only answers on SO.
Custom View Player
This custom view player allows one to swap out multiple AVPlayerItem(s).
import UIKit
import AVFoundation
class MNGVideoPlayerView: UIView {
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
override class func layerClass () -> AnyClass {
return AVPlayerLayer.self
}
func player () -> AVPlayer {
return (self.layer as! AVPlayerLayer).player!
}
func setPlayer(player:AVPlayer) {
(self.layer as! AVPlayerLayer).player = player
}
func setVideoFillMode(fillMode:String) {
let playerLayer = (self.layer as! AVPlayerLayer)
playerLayer.videoGravity = fillMode
}
}
Multiple Video Player View Controller
This controller manages the distribution and presentation of the different AVPlayerItem(s). Check my gist repos for additional updates. (ported from original objc source #iOS Guy)
import UIKit
import AVFoundation
class MNGVideoPlayerViewController: UIViewController {
let kTracksKey = "tracks";
let kStatusKey = "status";
let kRateKey = "rate";
let kPlayableKey = "playable";
let kCurrentItemKey = "currentItem";
let kTimedMetadataKey = "currentItem.timedMetadata";
var _URL:NSURL? = nil
var player:AVPlayer? = nil
var playerItem:AVPlayerItem? = nil
var playerView:MNGVideoPlayerView? = nil
var AVPlayerDemoPlaybackViewControllerStatusObservationContext = UnsafeMutablePointer<Void>()
var AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext = UnsafeMutablePointer<Void>()
var AVPlayerDemoPlaybackViewControllerStatusObservation = UnsafeMutablePointer<Void>()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Public methods
func setURL(url:NSURL) {
self._URL = url
let asset = AVURLAsset(URL: self._URL!)
let requestedKeys = [kTracksKey,kPlayableKey]
asset.loadValuesAsynchronouslyForKeys(requestedKeys) { () -> Void in
self.prepareToPlayAsset(asset, withKeys: requestedKeys)
}
}
func prepareToPlayAsset(asset:AVURLAsset, withKeys requestedKeys:NSArray) {
var error:NSErrorPointer = nil
for thisKey in requestedKeys {
let keyStatus = asset.statusOfValueForKey(thisKey as! String, error: error)
if keyStatus == .Failed {
return
}
}
if !asset.playable {
return
}
if (self.playerItem != nil) {
self.playerItem?.removeObserver(self, forKeyPath: kStatusKey)
NSNotificationCenter.defaultCenter().removeObserver(self, name: AVPlayerItemDidPlayToEndTimeNotification, object: self.playerItem)
}
self.playerItem = AVPlayerItem(asset: asset)
self.playerItem?.addObserver(self, forKeyPath: kStatusKey, options: [.Initial,.New], context: AVPlayerDemoPlaybackViewControllerStatusObservationContext)
if (self.player == nil) {
self.player = AVPlayer(playerItem: self.playerItem!)
self.player?.addObserver(self, forKeyPath: kCurrentItemKey, options: [.Initial,.New], context: AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext)
}
if self.player?.currentItem! != self.playerItem! {
self.player?.replaceCurrentItemWithPlayerItem(self.playerItem!)
}
}
// MARK: - Key Value Observing
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if context == AVPlayerDemoPlaybackViewControllerStatusObservation {
let status:Int = (change![NSKeyValueChangeNewKey]?.integerValue)!
if status == AVPlayerStatus.ReadyToPlay.rawValue {
self.player?.play()
}
} else if context == AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext {
let newPlayerItem = change![NSKeyValueChangeNewKey] as? AVPlayerItem
if newPlayerItem != nil {
self.playerView?.setPlayer(self.player!)
self.playerView?.setVideoFillMode(AVLayerVideoGravityResizeAspect)
}
} else {
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
It looks like http://iosguy.com/2012/01/11/multiple-video-playback-on-ios/ is the best solution at the moment. Nobody tried to convert it in swift yet.
I play multiple videos in my app at once, I just use multiple instances of AVPlayer.

Scan qrcode and barcode from camera and image which picked from image library in swift

I'm a newbie with Ios. i'm learning swift and overlooked object c.
Currently, i'm writing an demo with swift and xcode 6.1 which can scan qrcode and barcode from camera or an image from image library.
I know that AVFoundation framework support scanning qrcode and barcode, but it can only scan from camera.
I searched and found zbarSDK which support scan code from camera and image. I do as instructions in http://zbar.sourceforge.net/iphone/sdkdoc/ and NSFastEnumeration in Swift (convert code to swift). However, when i run app, after choosing image from library, it happen error.
This's my code
import UIKit
import AVFoundation
extension ZBarSymbolSet: SequenceType {
public func generate() -> NSFastGenerator {
return NSFastGenerator(self)
}
}
class FirstViewController: UIViewController, ZBarReaderDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let reader = ZBarReaderController()
#IBOutlet weak var lblResult: UILabel!
#IBOutlet weak var imgView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
reader.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func scanCode(sender: AnyObject) {
let scanner = reader.scanner
scanner.setSymbology(ZBAR_I25, config: ZBAR_CFG_ENABLE, to: 0)
reader.modalPresentationStyle = .Popover
presentViewController(reader, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
var results: NSFastEnumeration = info["ZBarReaderControllerResults"] as NSFastEnumeration
var symbolFound : ZBarSymbol?
// =============== Error here ==================
for symbol in results as ZBarSymbolSet {
symbolFound = symbol as? ZBarSymbol
break
}
var resultString = NSString(string: symbolFound!.data)
println(resultString)
}
}
here is error image
I will very grateful if someone let me know why it happen error and how to fix it or there's any way to scan code with an image using AVFoundation or there a other library (with detail document and sample) to do this (please give detail instructions because i have just learned swift and ios for 3 weeks).
Thanks.
I was also looking to read a QR code from an image and without Zbar.
You can use CIDetector instead. I found the solution here.
In my case, I pick up a photo from the library (supposed to be a QR code, here qrcodeImg) and then convert it in CIImage to be decoded by CIDetector.
qrCodeImageView.image=qrcodeImg
let detector:CIDetector=CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
let ciImage:CIImage=CIImage(image:qrcodeImg)
var qrCodeLink=""
let features=detector.featuresInImage(ciImage)
for feature in features as! [CIQRCodeFeature] {
qrCodeLink += feature.messageString
}
if qrCodeLink=="" {
print("nothing")
}else{
print("message: \(qrCodeLink)")
}
For Swift3 following code should work for you to get result from ZBarSDK
extension ZBarSymbolSet: Sequence {
public func makeIterator() -> NSFastEnumerationIterator {
return NSFastEnumerationIterator(self)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// ADD: get the decode results
let results: NSFastEnumeration = info[ZBarReaderControllerResults] as! NSFastEnumeration
var symbolFound : ZBarSymbol?
for symbol in results as! ZBarSymbolSet {
symbolFound = symbol as? ZBarSymbol
break
}
let resultString = symbolFound!.data
print(resultString)
}

NSFileManager - Swift - File Browser

I am new at ios development and I am trying to create an app in swift that will list all the files in the directory (all the files are PDF) and the user to be able to open them.
I have googling this for a the past two days and I am super confused. Can anyone suggest a tutorial or steps I would need to get this to work.
I have started with this in my ViewController.swift file:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
class func defaultManager()->NSFileManager{
}
}
I just don't know what to do next, very sad I know. I would appreciate any or all help.
Thanks,
J
let manager = NSFileManager.defaultManager()
var array = manager.contentsOfDirectoryAtPath(_ path: String,
error error: NSErrorPointer) -> [AnyObject]?
Swift 3.0 version
let manager = FileManager.default
let installed_files = try manager.contentsOfDirectory(atPath: "/Applications/")
Here is a more complete example and updated for Swift 2.
Add your files to a Folder (not a Group) in your project. Then use the following code to get a list of file names.
private func getListOfFileNames() -> Array<String> {
let docsPath = NSBundle.mainBundle().resourcePath! + "/DirectoryName"
let fileManager = NSFileManager.defaultManager()
let docsArray: Array<String>
do {
docsArray = try fileManager.contentsOfDirectoryAtPath(docsPath)
} catch {
print(error)
}
return docsArray
}
Maybe I am late to answer for you, but the answer may help others. I've found one library on github. This is a way to get access very easely to browse files. At here is example:
let fileBrowser = FileBrowser()
present(fileBrowser, animated: true, completion: nil)

Resources