iOS Dev cannot delete Calendar event using eventIdentifier programmatically - ekeventkit

I can save event into Calendar user
do {
try self.store.save(event, span: .thisEvent, commit: true)
self.addedEventId = event.eventIdentifier
print("\(self.addedEventId) has been added")
}
catch let error as NSError {
print("\(error.localizedDescription), userInfo: \(error.userInfo)")
}
it saved the event, and print eventIdentifier
61211649-CED1-4C74-A140-843AE0C38F44:8B7BDC14DD804F069D455E7B8F3534EF0
but when I try to delete the saved event using
if let eventToRemove = self.store.event(withIdentifier: self.addedEventId)
{
do {
try self.store.remove(eventToRemove, span: .thisEvent)
print("\(self.addedEventId) removed")
} catch let error as NSError {
print("\(error.userInfo)")
}
}
Seems I cannot find the event using eventIdentifier, the error I have from the console reads
Error getting event with identifier 61211649-CED1-4C74-A140-843AE0C38F44:8B7BDC14DD804F069D455E7B8F3534EF0: Error Domain=EKCADErrorDomain Code=1010 "(null)

After half day research, I finally found a way around is instead of using eventIdentifier, using calenderItemIdentifier

Related

I can detect workout started on backgroun with apple watch, but how can I detect workout finished?

I can detect workout started on backgroun with apple watch, with below code
let workoutevent = HKObjectType.workoutType()
if store.authorizationStatus(for: workoutevent) != HKAuthorizationStatus.notDetermined {
store.enableBackgroundDelivery(for: workoutevent, frequency: .immediate, withCompletion: { (worked, error) in
print(worked)
print(error)
print("workoutevent enableBackgroundDelivery")
guard worked else {
self.logger.error("Unable to set up background delivery from HealthKit: \(error!.localizedDescription)")
print("workoutevent unable to set up background ")
fatalError()
}
if error != nil {
print("workoutevent error is ")
print(error)
}
})
backgroundObserver3 =
HKObserverQuery(sampleType: workoutevent,
predicate: nil,
updateHandler: processUpdate3(query:completionHandler3:error:))
if let queryworkout = backgroundObserver3 {
print("Starting workoutevent333 the background observer query.\(queryworkout)")
store.execute(queryworkout)
}
}else{
print("not determined....")
}
whenever I started workout on apple watch, it goes to
processUpdate3
very well,
but what I need to know is to when user finish workout.
how can I detect it ?
func processUpdate3(query: HKObserverQuery,
completionHandler3: #escaping () -> Void,
error: Error?) {
print("come here when work out started ")
...........
}
I don't see it in your code. But somewhere you must have an HKWorkoutSession. My app is set up to track running and I configure the session to begin like so;
let configuration = HKWorkoutConfiguration()
configuration.activityType = .running
do {
// HKWorkoutSession is set up here.
session = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)
workoutBuilder = session.associatedWorkoutBuilder()
} catch {
// handle errors
}
When the users taps the end workout button I call session.end()
Here is a link to the documentation.

Swift CoreData: Unrecognised Selector sent to Instance

I am implementing Swift CoreData into my application, However I continue to face the error 'Unrecognised selector sent to Instance' when adding data to the class set up as you can see below. I realise that this is probably a rookie error, so thanks for your patience.
func coreDataRequest(){
container = NSPersistentContainer(name: "tileData")
container.loadPersistentStores { StoreDescription, error in
if let error = error {
print("Unresolved Error \(error)")
}
}
var campaign = Campaign()
campaign.countryName = "France"
}
The Error
unrecognized selector sent to instance
Here is my XCDataModel
Have you generate Campaign() class, that you add to tileData.xcdatamodeld?
if so create a NSManagedObjectContext like this:
var context: NSManagedObjectContext = {
return persistentContainer.viewContext
}()
and then use it to create Campaign like this:
var campaign = Campaign(context: context)
campaign.countryName = "France"
then if you want to store your object you have to call save on the context:
func saveContext () {
if context.hasChanges {
do {
try context.save()
} catch {
context.rollback()
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
I recommend you to look through few tutorials, it would save your time in future. There are a lot of them, just google it.
Without seeing all your code its difficult to say what is wrong, just from what I can see the container is missing a "let" in-front unless that was declared outside the function. This is a really good tutorial on setting up and using CoreData https://www.raywenderlich.com/books/core-data-by-tutorials/v7.0/chapters/3-the-core-data-stack#toc-chapter-006-anchor-011

How can I gracefully handle denied authorization in AVCaptureDeviceInput.init?

The documentation for AVCaptureDeviceInput.init(device:) documents its parameters as:
device
The device from which to capture input.
outError
If an error occurs during initialization, upon return contains an NSError object describing the problem.
This outError out-parameter is, in Swift, represented as a thrown Error. I can catch and display this like so:
do {
let deviceInput = try AVCaptureDeviceInput(device: device)
// ...
}
catch {
print("Error: \(error)")
}
There is one specific case I want to handle gracefully: when the user has denied authorization for application to use the camera. In this case, I get the following output:
Error: Error Domain=AVFoundationErrorDomain Code=-11852 "Cannot use FaceTime HD Camera (Built-in)" UserInfo={NSLocalizedFailureReason=This app is not authorized to use FaceTime HD Camera (Built-in)., AVErrorDeviceKey=<AVCaptureDALDevice: 0x100520a60 [FaceTime HD Camera (Built-in)][0x8020000005ac8514]>, NSLocalizedDescription=Cannot use FaceTime HD Camera (Built-in)}
I need to distinguish this error type from other unexpected errors, like so:
do {
let deviceInput = try AVCaptureDeviceInput(device: device)
// ...
}
catch AVError.Code.applicationIsNotAuthorizedToUseDevice {
// Expected error, handle gracefully
errorMessageBox(errorText: "You have denied authorization to access your camera. Fix this in System Preferences > Security & Privacy.")
}
catch {
// Unexpected errors
errorMessageBox("Error: \(error)")
}
This is pseudocode and does not compile. I know that the error code -11852 is AVError.Code.applicationIsNotAuthorizedToUseDevice. However, I don't know how to get the error code out of the opaque error object in order to test it.
What is the specific type of the error thrown by AVCaptureDeviceInput.init(device:)? How do I extract the AVError.Code from it in order to handle this specific error?
There are two possible approaches. One is to check before you even attempt, e.g.
if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
offerToOpenSettings()
return
}
The other approach is to catch the not authorized error:
let input: AVCaptureDeviceInput
do {
input = try AVCaptureDeviceInput(device: camera)
} catch AVError.applicationIsNotAuthorizedToUseDevice {
offerToOpenSettings()
return
} catch {
print("some other error", error)
return
}
Note, that’s catching AVError.applicationIsNotAuthorizedToUseDevice, not AVError.Code.applicationIsNotAuthorizedToUseDevice.
If, for example, this was an iOS app, you could have a function to offer to redirect the user to settings app:
func offerToOpenSettings() {
guard
let settings = URL(string: UIApplication.openSettingsURLString),
UIApplication.shared.canOpenURL(settings)
else { return }
let alert = UIAlertController(title: nil, message: "Would you like to open Settings to enable permission to use the camera?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Settings", style: .default) { _ in
UIApplication.shared.open(settings)
})
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
present(alert, animated: true)
}
Note, since this is potentially presenting an alert, you don’t want to trigger this in viewDidLoad (which is too early in the process), but rather viewDidAppear.
Or, on macOS, maybe something like:
func offerToOpenSettings() {
let preferences = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Camera")!
let alert = NSAlert()
alert.messageText = #"The camera is disabled. Please go to the “Camera” section in Security System Preferences, and enable this app."#
alert.addButton(withTitle: "System Preferences")
alert.addButton(withTitle: "Cancel")
if alert.runModal() == .alertFirstButtonReturn {
NSWorkspace.shared.open(preferences)
}
}

CLSLogv logs are not coming in Crashlytics

Its an Ionic app with some code written in native. Its uses cordova-plugin-firebase that for logging Crashlytics.
In the native part for iOS as well, we are trying to use Crashlytics to enable logging. However no matter what I try logs sent using CLSLogv aren't visible in dashboard.
Here is my code.
#objc(ImageUpload) class ImageUpload : CDVPlugin {
var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
//https://docs.fabric.io/apple/crashlytics/enhanced-reports.html#custom-logging-in-swift
private func sendErrorToCrashlytics(error: String) {
NSLog("Error in send error function is \(error)")
CLSLogv("%#", getVaList([error]))
}
#objc(imageUpload:)
func imageUpload(command: CDVInvokedUrlCommand) {
registerBackgroundTask()
func execute() {
let db = SQLiteDatabase()
var recToUpLoad: PayloadModel? = nil
while(toCheck) {
do {
let record = try db.readValues() // THIS METHOD THROWS EXCEPTION
} catch Exceptions.SQLiteError(let error) {
self.sendErrorToCrashlytics(error: error) // IT COMES HERE AFTER EXCEPTION
}
}
}
DispatchQueue(label: "imageUploadPlugin",qos: .background).async
{
execute()
}
}
}
However CLSLogv is not visible at all in Crashlytics. However when I do Crashlytics.sharedInstance().throwException()
, I can see it in the dashboard.
Exceptions is enum
enum Exceptions: Error {
case SQLiteError(message: String)
case JSONError(message: String)
}
Hoping it may help someone. Somehow I couldn't get CLSLogv to work. I ended up creating an NSError object and log that in Crashlytics in catch block.
catch Exceptions.SQLiteError(let error) {
let userInfo = [NSLocalizedDescriptionKey: error.message, "query": error.query]
let errorObj = NSError(domain: "sqlite", code: 400, userInfo: userInfo)
Crashlytics.sharedInstance().recordError(errorObj)
}

Error Getting Default Calendar For New Events - Swift

I encountered an issue trying to create a new event on iOS's Calendar application while using Swift.
This is what I have so far:
func addToCal(){
let eventStore = EKEventStore()
eventStore.requestAccessToEntityType(EKEntityTypeReminder) {
(granted: Bool, err: NSError!) in
if granted && !err {
var event:EKEvent = EKEvent(eventStore: eventStore)
event.title = self.eventTitle!.text
event.startDate = self.eventData.startDateObj
event.endDate = self.eventData.endDateObj
event.calendar = eventStore.defaultCalendarForNewEvents
eventStore.saveEvent(event, span: EKSpanThisEvent, error: nil)
println("Saved Event")
}
}
This is the error that I'm getting:
Error getting default calendar for new events: Error Domain=EKCADErrorDomain Code=1013 "The operation couldn’t be completed. (EKCADErrorDomain error 1013.)"
I checked my syntax and I'm pretty sure I got it right, so can anyone help me figure out where I'm going wrong?
Additional Information
iOS 8 Beta 5
Xcode 6 Beta 5
Issue occurs on iPad Mini w/ Retina Display (real device)
Update
Changing EKEntityTypeReminder to EKEntityTypeEvent (Sorry, my mistake) actually doesn't produce an error, but now the event doesn't even show up in Calendar. I checked the outputs of granted and err and I see false and nil, respectively.
I think your main problem was that you weren't committing the new event to be saved. The following code is what I use, and the prime difference is that my code includes a commit and allows my error to be changed from 'nil' if there is one. The conditional at the end just prints any reports of save errors or save successes to the Debug Area.
let eventStore = EKEventStore()
let event = EKEvent(eventStore: eventStore)
event.title = "Your Event Title Here" // Sets event's title
event.startDate = NSDate() // Sets event's start date
event.endDate = event.startDate.dateByAddingTimeInterval(20000) // Sets event's end date
event.calendar = eventStore.defaultCalendarForNewEvents // Selects default calendar
var saveError : NSError? = nil // Initially sets errors to nil
eventStore.saveEvent(event, span: EKSpanThisEvent, commit: true, error: &saveError) // Commits changes and allows saveEvent to change error from nil
//// Following checks for errors and prints result to Debug Area ////
if saveError != nil {
println("Saving event to Calendar failed with error: \(saveError!)")
} else {
println("Successfully saved '\(event.title)' to '\(event.calendar.title)' calendar.")
}
Hope this helps!
-Gorowski
Once access has been granted, you need to set the 'eventStore':
eventStore.requestAccess(to: .event) { (granted, error) in
if (granted) && (error == nil) {
//Set event store now access granted
eventStore = EKEventStore()
//Save calendar event here...
} else {
}
}