I'm trying to copy specific events from all calendars to the target calendar. Unfortunately my events are not saving in target calendar.
Simply my code in steps:
Check permissions (success)
Load calendars (success)
Load events (success)
Save events (failed)
I'm sure there are events to save from terminal which prints "Trying to save" couple of times.
And it looks like code pass through "try self.eventStore.save(event, span: .thisEvent)" and exits function there without calling "Saved" or entering catch clause.
There is a source code:
import UIKit
import EventKit
class ViewController: UIViewController{
#IBOutlet weak var status: UILabel!
var calendars: [EKCalendar]?
var targetCalendar: EKCalendar?
var targetCalendarEvents: [EKEvent]?
let eventStore = EKEventStore()
let targetCalendarName = "TargetCalendarName"
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
DispatchQueue.main.async{
self.status.text = "Idle"
}
checkCalendarAuthorizationStatus()
}
func checkCalendarAuthorizationStatus() {
let status = EKEventStore.authorizationStatus(for: EKEntityType.event)
switch (status) {
case EKAuthorizationStatus.notDetermined:
// This happens on first-run
requestAccessToCalendar()
case EKAuthorizationStatus.authorized:
// Things are in line with being able to show the calendars in the table view
loadCalendars()
loadEvents()
case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied:
// We need to help them give us permission
print("Missing permissions [00]")
}
}
func requestAccessToCalendar() {
eventStore.requestAccess(to: EKEntityType.event, completion: {
(accessGranted: Bool, error: Error?) in
if accessGranted == true {
DispatchQueue.main.async(execute: {
self.loadCalendars()
self.loadEvents()
})
} else {
print("Missing permissions [01]")
}
})
}
func loadEvents(){
print("Loading..")
DispatchQueue.main.async{
self.status.text = "Loading"
}
let eventStore = EKEventStore()
var initialized = false
//Two months
let dateTo = NSDate(timeIntervalSinceNow: +30*24*3600 * 2)
for calendar in self.calendars! {
let predicate = eventStore.predicateForEvents(withStart: Date() as Date as Date, end: dateTo as Date, calendars: [calendar])
let events = eventStore.events(matching: predicate)
if calendar.title == targetCalendarName {
print("Initialized")
targetCalendar = calendar
targetCalendarEvents = events
initialized = true
}
}
if(!initialized){
print("Not Initialized")
} else {
for calendar in self.calendars! {
let predicate = eventStore.predicateForEvents(withStart: Date() as Date as Date, end: dateTo as Date, calendars: [calendar])
let events = eventStore.events(matching: predicate)
if calendar.title != targetCalendarName && calendar.title != "Contacts" {
//print("Loaded Calendar \(calendar.title)")
print("Loaded Calendar")
for event in events {
if(!(event.location?.isEmpty)!){
//print("Event \(event.location ?? "Missing Location") \(event.startDate) \(event.endDate)")
addEventToTarget(eventToAdd: event)
}
}
}
}
}
DispatchQueue.main.async {
self.status.text = "Done"
}
print("Done")
}
func loadCalendars() {
self.calendars = eventStore.calendars(for: EKEntityType.event)
}
func addEventToTarget(eventToAdd: EKEvent){
eventStore.requestAccess(to: .event) { (granted, error) in
for event in self.targetCalendarEvents! {
if(!(event.location?.isEmpty)!){
if(
eventToAdd.title == event.title &&
eventToAdd.startDate == event.startDate &&
eventToAdd.endDate == event.endDate
){
print("Possible duplicate - skipping")
return
}
}
}
if (granted) && (error == nil) {
let event:EKEvent = EKEvent(eventStore: self.eventStore)
event.title = eventToAdd.title
event.startDate = eventToAdd.startDate
event.endDate = eventToAdd.endDate
event.notes = ""
event.location = eventToAdd.location
event.calendar = self.targetCalendar
//print("Trying to save \(event.title) \(String(describing: event.location))")
print("Trying to save")
do {
try self.eventStore.save(event, span: .thisEvent)
print("Saved \(event.title) \(String(describing: event.location)) in \(event.calendar.title)")
} catch {
print("failed to save event with error : \(error as NSError)")
}
}
else{
print("failed to save event with error : \(String(describing: error)) or access not granted")
}
}
}
}
TargetCalendarName is correct calendar name
Sometimes there are events which saves successfully but only couple of them (2-5) for hundreds which should save. I don't have a clue why.
So 5 for 200 is not enough for me.
Thanks to #matt for proposing a solution.
Now I'm saving events ONCE (previously I was requesting access for every event which is very bad), so I request access to eventStore once and can save events succesfully.
func saveEvents(){
eventStore.requestAccess(to: .event) { (granted, error) in
if (granted) && (error == nil) {
for event in self.eventsToCopy {
print("Trying to save")
do {
try self.eventStore.save(event, span: .thisEvent)
print("Saved \(event.title) \(String(describing: event.location)) in \(event.calendar.title)")
} catch {
print("failed to save event with error : \(error as NSError)")
}
}
}
else{
print("failed to save event with error : \(String(describing: error)) or access not granted")
}
}
}
Related
After logging in with firebase Auth, I try to update the home page tableview using a delegate except I get this issue -
2020-07-16 10:58:51.078331-0700 Appname[44300:8867431] [AXRuntimeCommon] Unknown client: Appname
2020-07-16 10:58:51.084416-0700 Appname[44300:8867435] [AXRuntimeCommon] AX Lookup problem - errorCode:1100 error:Permission denied portName:'com.apple.iphone.axserver' PID:44186
Once the app loads it checks if the user is logged in on the home page with this function
func isLoggedIn() {
if Firebase.Auth.auth().currentUser == nil {
perform(#selector(handleLogout), with: nil, afterDelay: 0)
}
}
#objc func handleLogout() {
do {
try Auth.auth().signOut()
} catch let logoutError {
print("logout error", logoutError)
}
let startview = StartView()
startview.home = self
let nav = UINavigationController(rootViewController: startview)
nav.modalPresentationStyle = .fullScreen
present(nav, animated: false)
}
Then in the login page it logs the user in and runs the function from the home page but it just shows up as blank.
#objc func Login() {
Auth.auth().signIn(withEmail: EmailField.text!, password: PasswordField.text!) { [weak self] (user, error) in
guard let StrongSelf = self else {
return
}
guard let result = user, error == nil else {
print(error!._code)
self?.handleError(error!)
return
}
let user = result.user
print("logged in \(user)")
//NotificationCenter.default.post(name: NSNotification.Name(rawValue: "loadhome"), object: nil)
StrongSelf.navigationController?.dismiss(animated: true, completion: {
self?.home.loadfirstusers()
})
}
}
var home = HomePage()
It calls this function to update the user data and gets as far as printing sameunisamecourse but it doesn't call the print inside the dispatch.notify for some reason?
func SameUniSameCourse(completion: #escaping (_ success: Bool) -> Void) {
self.dispatchGroup.enter()
service.loadUniversityAndCourse { (uni, course) in
defer{ self.dispatchGroup.leave() }
let usersRef = Firestore.firestore().collection("users").order(by: "Created", descending: true).whereField("University", isEqualTo: uni).whereField("Course", isEqualTo: course)
self.dispatchGroup.enter()
usersRef.getDocuments { (snapshot, error) in
print("samecoursesameuni")
defer{ self.dispatchGroup.leave() }
if let error = error {
print(error.localizedDescription)
} else {
for document in snapshot!.documents {
let data = document.data()
//print(data)
if let dictionary = data as [String:AnyObject]? {
let Info = UserInfo(dictionary: dictionary)
if Info.uid == Auth.auth().currentUser?.uid {
//print(Info.username)
}
else {
self.sameUniSameCourse.append(Info)
//print(Info.username!)
}}}
}
}}
self.dispatchGroup.notify(queue: .main) {
print("dispatchNotifyCalled")
if self.sameUniSameCourse.isEmpty == true {
completion(false)
}
else {
self.masterArray.append(contentsOf: self.sameUniSameCourse)
self.spinner.stopAnimating()
completion(true)
}
}
}
I am using the below code to record a 5 second sound sample in an iOS Swift app. The code works fine for recording and also recognised headphone correctly if they are plugged in. However, if during the recording the headphones are added or removed, the recording is interrupted. I wonder why that is as otherwise it runs smoothly?
import AVFoundation
class RecorderViewController: UIViewController {
var recorder: AVAudioRecorder!
var uploadObjectSuccess = false
#IBOutlet weak var recordButton: UIButton!
#IBOutlet weak var statusLabel: UILabel!
#IBOutlet weak var progressView: UIProgressView!
var meterTimer: Timer!
var soundFileURL: URL!
override func viewDidLoad() {
super.viewDidLoad()
setSessionPlayback()
askForNotifications()
checkHeadphones()
}
func updateAudioMeter(_ timer:Timer) {
self.progressView.setProgress(0, animated: false)
if recorder != nil && recorder.isRecording {
let sec = Int(recorder.currentTime.truncatingRemainder(dividingBy: 60))
let s = String(format: "%02d", sec)
statusLabel.text = s
recorder.updateMeters()
self.progressView.setProgress(Float(sec*4), animated: true)
if (sec==6) && recorder != nil {
func aux()->Bool {
recorder.stop()
return true
}
if aux()==true {
if self.soundFileURL != nil {
self.uploadObjectSuccess = false
let path = Auth.auth().currentUser?.uid
let FIRStoragePath = Storage.storage().reference().child(path!).child(FileName!)
let uploadObject = FIRStoragePath.putFile(from: self.soundFileURL!, metadata: nil)
uploadObject.observe(.success) { snapshot in
// Upload completed successfully
self.uploadObjectSuccess = true
}
uploadObject.observe(.failure) { snapshot in
// Upload failed
self.uploadObjectSuccess = true
}
}
}
}
} else if (uploadObjectSuccess==true) {
self.statusLabel.text = "00"
self.recordButton.isEnabled = true
isPlaying = false
self.uploadObjectSuccess = false
} else {
self.statusLabel.text = "00"
}
}
#IBAction func record(_ sender: Any) {
if recorder != nil {
recorder.stop()
}
recordButton.isEnabled = false
recordWithPermission(true)
}
func setupRecorder() {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
self.soundFileURL = documentsDirectory.appendingPathComponent(self.currentFileName) //appendingPathComponent(currentFileName)
if FileManager.default.fileExists(atPath: soundFileURL.absoluteString) {
do {
try FileManager.default.removeItem(atPath: self.soundFileURL.absoluteString)
} catch let error as NSError {
print("Ooops! Something went wrong: \(error)")
}
}
let recordSettings:[String : AnyObject] = [
AVFormatIDKey: NSNumber(value:(kAudioFormatMPEG4AAC)),
AVEncoderAudioQualityKey : NSNumber(value:AVAudioQuality.min.rawValue),
//AVEncoderBitRateKey : NSNumber(value:16),
AVNumberOfChannelsKey: NSNumber(value:1),
AVSampleRateKey : NSNumber(value:16000.0)
]
do {
recorder = try AVAudioRecorder(url: soundFileURL, settings: recordSettings)
recorder.delegate = self
recorder.isMeteringEnabled = true
recorder.prepareToRecord() // creates/overwrites the file at soundFileURL
} catch let error as NSError {
recorder = nil
print(error.localizedDescription)
}
}
func recordWithPermission(_ setup:Bool) {
checkHeadphones()
setSessionPlayback()
askForNotifications()
let session:AVAudioSession = AVAudioSession.sharedInstance()
// ios 8 and later
if (session.responds(to: #selector(AVAudioSession.requestRecordPermission(_:)))) {
AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in
if granted {
print("Permission to record granted")
self.setSessionPlayAndRecord()
if setup {
self.setupRecorder()
}
self.recorder.record()
self.meterTimer = Timer.scheduledTimer(timeInterval: 0.1,
target:self,
selector:#selector(RecorderViewController.updateAudioMeter(_:)),
userInfo:nil,
repeats:true)
} else {
print("Permission to record not granted")
self.statusLabel.text = "00"
self.recordButton.isEnabled = true
self.uploadObjectSuccess = false
self.recorder.stop()
}
})
} else {
print("requestRecordPermission unrecognized")
self.statusLabel.text = "00"
self.recordButton.isEnabled = true
self.uploadObjectSuccess = false
self.recorder.stop()
}
}
func setSessionPlayback() {
let session:AVAudioSession = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayback)
} catch let error as NSError {
print("could not set session category")
print(error.localizedDescription)
}
do {
try session.setActive(true)
} catch let error as NSError {
print("could not make session active")
print(error.localizedDescription)
}
}
func setSessionPlayAndRecord() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch let error as NSError {
print("could not set session category")
print(error.localizedDescription)
}
do {
try session.setActive(true)
} catch let error as NSError {
print("could not make session active")
print(error.localizedDescription)
}
}
func askForNotifications() {
NotificationCenter.default.addObserver(self,
selector:#selector(RecorderViewController.background(_:)),
name:NSNotification.Name.UIApplicationWillResignActive,
object:nil)
NotificationCenter.default.addObserver(self,
selector:#selector(RecorderViewController.foreground(_:)),
name:NSNotification.Name.UIApplicationWillEnterForeground,
object:nil)
NotificationCenter.default.addObserver(self,
selector:#selector(RecorderViewController.routeChange(_:)),
name:NSNotification.Name.AVAudioSessionRouteChange,
object:nil)
}
#objc func background(_ notification:Notification) {
print("background")
if recorder != nil {
recorder.stop()
}
}
#objc func foreground(_ notification:Notification) {
print("foreground")
}
#objc func routeChange(_ notification:Notification) {
print("routeChange \(String(describing: (notification as NSNotification).userInfo))")
if let userInfo = (notification as NSNotification).userInfo {
//print("userInfo \(userInfo)")
if let reason = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt {
//print("reason \(reason)")
switch AVAudioSessionRouteChangeReason(rawValue: reason)! {
case AVAudioSessionRouteChangeReason.newDeviceAvailable:
print("NewDeviceAvailable")
print("did you plug in headphones?")
checkHeadphones()
case AVAudioSessionRouteChangeReason.oldDeviceUnavailable:
print("OldDeviceUnavailable")
print("did you unplug headphones?")
checkHeadphones()
case AVAudioSessionRouteChangeReason.categoryChange:
print("CategoryChange")
case AVAudioSessionRouteChangeReason.override:
print("Override")
case AVAudioSessionRouteChangeReason.wakeFromSleep:
print("WakeFromSleep")
case AVAudioSessionRouteChangeReason.unknown:
print("Unknown")
case AVAudioSessionRouteChangeReason.noSuitableRouteForCategory:
print("NoSuitableRouteForCategory")
case AVAudioSessionRouteChangeReason.routeConfigurationChange:
print("RouteConfigurationChange")
}
}
}
}
func checkHeadphones() {
// check NewDeviceAvailable and OldDeviceUnavailable for them being plugged in/unplugged
let currentRoute = AVAudioSession.sharedInstance().currentRoute
if currentRoute.outputs.count > 0 {
for description in currentRoute.outputs {
if description.portType == AVAudioSessionPortHeadphones {
print("headphones are plugged in")
break
} else {
print("headphones are unplugged")
}
}
} else {
print("checking headphones requires a connection to a device")
}
}
}
// MARK: AVAudioRecorderDelegate
extension RecorderViewController : AVAudioRecorderDelegate {
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder,
successfully flag: Bool) {
print("finished recording \(flag)")
}
func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder,
error: Error?) {
if let e = error {
print("\(e.localizedDescription)")
}
}
}
This is the way I am adding all the events in to my calendar, those events are coming from table view. I have a problem with deleting a specific even from the calendar when the row on the table view gets deleted. The code that I am trying seems not to find and identifier in the calendar. Can you please let me know what I am missing here
ADD TO CALENDAR
let eventStore : EKEventStore = EKEventStore()
// 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
eventStore.requestAccess(to: .event) { (granted, error) in
if (granted) && (error == nil) {
print("granted \(granted)")
print("error \(error)")
let event:EKEvent = EKEvent(eventStore: eventStore)
event.title = "Test Title"
event.startDate = Date()
event.endDate = Date()
event.notes = "This is a note"
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let error as NSError {
print("failed to save event with error : \(error)")
}
print("Saved Event")
}
else{
print("failed to save event with error : \(error) or access not granted")
}
}
DELETE FROM CALENDAR
func deleteEvent(_ storedEventID: String)
{
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil)
{
if let calendarEvent_toDelete = self.eventStore.event(withIdentifier: storedEventID){
//recurring event
if calendarEvent_toDelete.recurrenceRules?.isEmpty == false
{
let alert = UIAlertController(title: "Repeating Event", message:
"This is a repeating event.", preferredStyle: UIAlertControllerStyle.alert)
//delete this event only
let thisEvent_Action = UIAlertAction(title: "Delete this event", style: UIAlertActionStyle.default)
{
(result : UIAlertAction) -> Void in
//sometimes doesn't delete anything, sometimes deletes all reccurent events, not just current!!!
do{
try self.eventStore.remove(calendarEvent_toDelete, span: .thisEvent)
} catch let e as NSError{return}
}
alert.addAction(thisEvent_Action)
}
//not recurring event
else{
//works fine
do{
try self.eventStore.remove(calendarEvent_toDelete, span: EKSpan.thisEvent)
} catch let e as NSError{
return
}
}
}
}
})
}
What I am missing in your example is to commit the changes to the event store.
Commit the changes immediately or with a separate commit while bulk processing multiple events.
try? self.eventStore.remove(eventToRemove, span: .thisEvent, commit: true)
Good luck and success.
first get the event using even Id then delete the event
func removeEvent(eventId: String, eventStore: EKEventStore) {
if let eventToDelete = self.eventStore.event(withIdentifier: eventId){
do {
try eventStore.remove(eventToDelete, span: .thisEvent)
} catch let error as NSError {
print("failed to save event with error : \(error)")
}
print("removed Event")
}
}
Basically I am learning ios speech recognition module following this tutorial:
https://medium.com/ios-os-x-development/speech-recognition-with-swift-in-ios-10-50d5f4e59c48
But when I test it on my iphone6, I always got this error:
Error Domain=kAFAssistantErrorDomain Code=216 "(null)"
I searched it on the internet, but find very rare info about this.
Here is my code:
//
// ViewController.swift
// speech_sample
//
// Created by Peizheng Ma on 6/22/17.
// Copyright © 2017 Peizheng Ma. All rights reserved.
//
import UIKit
import AVFoundation
import Speech
class ViewController: UIViewController, SFSpeechRecognizerDelegate {
//MARK: speech recognize variables
let audioEngine = AVAudioEngine()
let speechRecognizer: SFSpeechRecognizer? = SFSpeechRecognizer(locale: Locale.init(identifier: "en-US"))
var request = SFSpeechAudioBufferRecognitionRequest()
var recognitionTask: SFSpeechRecognitionTask?
var isRecording = false
override func viewDidLoad() {
// super.viewDidLoad()
// get Authorization
self.requestSpeechAuthorization()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: properties
#IBOutlet weak var detectText: UILabel!
#IBOutlet weak var startButton: UIButton!
//MARK: actions
#IBAction func startButtonTapped(_ sender: UIButton) {
if isRecording == true {
audioEngine.stop()
// if let node = audioEngine.inputNode {
// node.removeTap(onBus: 0)
// }
audioEngine.inputNode?.removeTap(onBus: 0)
// Indicate that the audio source is finished and no more audio will be appended
self.request.endAudio()
// Cancel the previous task if it's running
if let recognitionTask = recognitionTask {
recognitionTask.cancel()
self.recognitionTask = nil
}
//recognitionTask?.cancel()
//self.recognitionTask = nil
isRecording = false
startButton.backgroundColor = UIColor.gray
} else {
self.recordAndRecognizeSpeech()
isRecording = true
startButton.backgroundColor = UIColor.red
}
}
//MARK: show alert
func showAlert(title: String, message: String, handler: ((UIAlertAction) -> Swift.Void)? = nil) {
DispatchQueue.main.async { [unowned self] in
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .cancel, handler: handler))
self.present(alertController, animated: true, completion: nil)
}
}
//MARK: Recognize Speech
func recordAndRecognizeSpeech() {
// Setup Audio Session
guard let node = audioEngine.inputNode else { return }
let recordingFormat = node.outputFormat(forBus: 0)
node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
self.request.append(buffer)
}
audioEngine.prepare()
do {
try audioEngine.start()
} catch {
self.showAlert(title: "SpeechNote", message: "There has been an audio engine error.", handler: nil)
return print(error)
}
guard let myRecognizer = SFSpeechRecognizer() else {
self.showAlert(title: "SpeechNote", message: "Speech recognition is not supported for your current locale.", handler: nil)
return
}
if !myRecognizer.isAvailable {
self.showAlert(title: "SpeechNote", message: "Speech recognition is not currently available. Check back at a later time.", handler: nil)
// Recognizer is not available right now
return
}
recognitionTask = speechRecognizer?.recognitionTask(with: request, resultHandler: { result, error in
if let result = result {
let bestString = result.bestTranscription.formattedString
self.detectText.text = bestString
// var lastString: String = ""
// for segment in result.bestTranscription.segments {
// let indexTo = bestString.index(bestString.startIndex, offsetBy: segment.substringRange.location)
// lastString = bestString.substring(from: indexTo)
// }
// self.checkForColorsSaid(resultString: lastString)
} else if let error = error {
self.showAlert(title: "SpeechNote", message: "There has been a speech recognition error.", handler: nil)
print(error)
}
})
}
//MARK: - Check Authorization Status
func requestSpeechAuthorization() {
SFSpeechRecognizer.requestAuthorization { authStatus in
OperationQueue.main.addOperation {
switch authStatus {
case .authorized:
self.startButton.isEnabled = true
case .denied:
self.startButton.isEnabled = false
self.detectText.text = "User denied access to speech recognition"
case .restricted:
self.startButton.isEnabled = false
self.detectText.text = "Speech recognition restricted on this device"
case .notDetermined:
self.startButton.isEnabled = false
self.detectText.text = "Speech recognition not yet authorized"
}
}
}
}
}
Thank you very much.
I had the same problem whilst following the same (excellent) tutorial, even when using the example code on GitHub. To solve it, I had to do two things:
Firstly, add request.endAudio() at the start of the code to stop recording in the startButtonTapped action. This marks the end of the recording. I see you've already done that in your sample code.
Secondly, in the recordAndRecognizeSpeech function, when 'recognitionTask' is started, if no speech was detected then 'result' will be nil and the error case is triggered. So, I tested for result != nil before attempting to assign the result.
So, the code for those two functions looks as follows:
1. Updated startButtonTapped:
#IBAction func startButtonTapped(_ sender: UIButton) {
if isRecording {
request.endAudio() // Added line to mark end of recording
audioEngine.stop()
if let node = audioEngine.inputNode {
node.removeTap(onBus: 0)
}
recognitionTask?.cancel()
isRecording = false
startButton.backgroundColor = UIColor.gray
} else {
self.recordAndRecognizeSpeech()
isRecording = true
startButton.backgroundColor = UIColor.red
}
}
And 2. Update within recordAndRecognizeSpeech from the recognitionTask = ... line:
recognitionTask = speechRecognizer?.recognitionTask(with: request, resultHandler: { (result, error) in
if result != nil { // check to see if result is empty (i.e. no speech found)
if let result = result {
let bestString = result.bestTranscription.formattedString
self.detectedTextLabel.text = bestString
var lastString: String = ""
for segment in result.bestTranscription.segments {
let indexTo = bestString.index(bestString.startIndex, offsetBy: segment.substringRange.location)
lastString = bestString.substring(from: indexTo)
}
self.checkForColoursSaid(resultString: lastString)
} else if let error = error {
self.sendAlert(message: "There has been a speech recognition error")
print(error)
}
}
})
I hope that helps you.
This will prevent two errors: The above mentioned Code=216 and the 'SFSpeechAudioBufferRecognitionRequest cannot be re-used' error.
Stop recognition with finish not with cancel
Stop audio
like so:
// stop recognition
recognitionTask?.finish()
recognitionTask = nil
// stop audio
request.endAudio()
audioEngine.stop()
audioEngine.inputNode.removeTap(onBus: 0) // Remove tap on bus when stopping recording.
P.S. audioEngine.inputNode seems to be no longer an optional value, therefore I used no if let construct.
hey i was getting the same error but now its working absoultely fine.hope this code helps to you too :).
import UIKit
import Speech
class SpeechVC: UIViewController {
#IBOutlet weak var slabel: UILabel!
#IBOutlet weak var sbutton: UIButton!
let audioEngine = AVAudioEngine()
let SpeechRecognizer : SFSpeechRecognizer? = SFSpeechRecognizer()
let request = SFSpeechAudioBufferRecognitionRequest()
var recognitionTask:SFSpeechRecognitionTask?
var isRecording = false
override func viewDidLoad() {
super.viewDidLoad()
self.requestSpeechAuthorization()
// Do any additional setup after loading the view, typically from a nib.
}
func recordAndRecognizeSpeech()
{
guard let node = audioEngine.inputNode else { return }
let recordingFormat = node.outputFormat(forBus: 0)
node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer , _ in
self.request.append(buffer)
}
audioEngine.prepare()
do
{
try audioEngine.start()
}catch
{
return print(error)
}
guard let myRecognizer = SFSpeechRecognizer() else {
return
}
if !myRecognizer.isAvailable
{
return
}
recognitionTask = SpeechRecognizer?.recognitionTask(with: request, resultHandler: { result, error in
if let result = result
{
let bestString = result.bestTranscription.formattedString
self.slabel.text = bestString
var lastString : String = ""
for segment in result.bestTranscription.segments
{
let indexTo = bestString.index(bestString.startIndex, offsetBy: segment.substringRange.location)
lastString = bestString.substring(from: indexTo)
}
}else if let error = error
{
print(error)
}
})
}
#IBAction func startAction(_ sender: Any) {
if isRecording == true
{
audioEngine.stop()
recognitionTask?.cancel()
isRecording = false
sbutton.backgroundColor = UIColor.gray
}
else{
self.recordAndRecognizeSpeech()
isRecording = true
sbutton.backgroundColor = UIColor.red
}
}
func cancelRecording()
{
audioEngine.stop()
if let node = audioEngine.inputNode
{
audioEngine.inputNode?.removeTap(onBus: 0)
}
recognitionTask?.cancel()
}
func requestSpeechAuthorization()
{
SFSpeechRecognizer.requestAuthorization { authStatus in
OperationQueue.main.addOperation {
switch authStatus
{
case .authorized :
self.sbutton.isEnabled = true
case .denied :
self.sbutton.isEnabled = false
self.slabel.text = "User denied access to speech recognition"
case .restricted :
self.sbutton.isEnabled = false
self.slabel.text = "Speech Recognition is restricted on this Device"
case .notDetermined :
self.sbutton.isEnabled = false
self.slabel.text = "Speech Recognition not yet authorized"
}
}
}
}
}
I had this error because I was running the app on the Simulator. Running on a regular device solves the issue.
I am new to swift and i am practicing "Adding a Calendar Event" from this website: http://www.ioscreator.com/tutorials/add-event-calendar-tutorial-ios8-swift, but I am getting the following errors at line
let result = store.saveEvent(event, span: .ThisEvent, commit: error)
Call can throw, but it is not marked with 'try' and the error is not handled
Cannot convert value of type 'NSError?' to expected argument type 'Bool'
Code:
import UIKit
import EventKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let eventStore = EKEventStore()
switch EKEventStore.authorizationStatusForEntityType(EKEntityType.Event) {
case .Authorized:
insertEvent(eventStore)
case .Denied:
print("Access denied")
case .NotDetermined:
// 3
eventStore.requestAccessToEntityType(EKEntityType.Event, completion:
{[weak self] (granted: Bool, error: NSError?) -> Void in
if granted {
self!.insertEvent(eventStore)
} else {
print("Access denied")
}
})
default:
print("Case Default")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func insertEvent(store : EKEventStore){
let calendars = store.calendarsForEntityType(EKEntityType.Event) as! [EKCalendar]
for calendar in calendars{
if calendar.title == "ioscreater"{
let startDate = NSDate()
let endDate = startDate.dateByAddingTimeInterval(2*60*60)
//Create event
var event = EKEvent(eventStore : store)
event.calendar = calendar
event.title = "New Meeting"
event.startDate = startDate
event.endDate = endDate
//Save event in Calendar
var error : NSError?
let result = store.saveEvent(event, span: .ThisEvent, commit: error)
if result == false{
if let theError = error{
print ("An error occured \(theError)")
}
}
}
}
}
}
I googled the errors but I could not find an appropriate solution.
This works for me in Swift 3.0
Firstly, You need to add "Privacy - Calendars Usage Description" in info.plist.
import EventKit
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event, completion: { (granted, error) in
if (granted) && (error == nil) {
let event = EKEvent(eventStore: eventStore)
event.title = title
event.startDate = startDate
event.endDate = endDate
event.notes = description
event.calendar = eventStore.defaultCalendarForNewEvents
do {
try eventStore.save(event, span: .thisEvent)
} catch let e as NSError {
completion?(false, e)
return
}
completion?(true, nil)
} else {
completion?(false, error as NSError?)
}
})
}
Then, you can easily call this method like the following:
addEventToCalendar(title: "Best friend birthday", description: "Remember you or miss you!", startDate: NSDate(), endDate: NSDate())
Thanks and enjoy coding!!!
func insertEvent(store : EKEventStore){
let calendars = store.calendarsForEntityType(EKEntityType.Event)
for calendar in calendars{
if calendar.title == "ioscreater"{
let startDate = NSDate()
let endDate = startDate.dateByAddingTimeInterval(2*60*60)
//Create event
var event = EKEvent(eventStore : store)
event.calendar = calendar
event.title = "New Meeting"
event.startDate = startDate
event.endDate = endDate
//Save event in Calendar
do {
try store.saveEvent(event, span: .ThisEvent)
} catch {
// Do error stuff here
}
}
Add saveEvent code in try,catch like below :
do {
try store.saveEvent(event, span: .ThisEvent)
} catch let err as NSError{
print ("An error occured \(err.description)")
}