let eventStore = EKEventStore()
// 2
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")
}
I am getting error: cannot convert value of type '(bool,nserror!) -->void' to expected argument type 'ekeventstorerequestaccescompletionhandler'
at this line:
eventStore.requestAccessToEntityType(EKEntityType.Event, completion:
{[weak self] (granted: Bool, error: NSError!) -> Void in
Try to remove [weak self], in my case this one works:
eventStore.requestAccessToEntityType(EKEntityType.Event, completion: {
(accessGranted: Bool, error: NSError?) in
if accessGranted && (error == nil) {
dispatch_async(dispatch_get_main_queue(), { completion(true) })
} else {
dispatch_async(dispatch_get_main_queue(), { completion(false) })
}
})
Related
I'm building a Widget with dynamic configuration. I provide a dynamic list of options with an Intents Extension - inside Intent Handler (code below).
However only sampleData shows up, but not the userScrums when tapping on "Edit Widget".
Why it doesn't load userScrums?
import Intents
class IntentHandler: INExtension {
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
}
extension IntentHandler: ScrumSelectionIntentHandling {
func provideScrumOptionsCollection(for intent: ScrumSelectionIntent) async throws -> INObjectCollection<ScrumType> {
let sampleScrums = DailyScrum.sampleData.map { scrum in
ScrumType(identifier: scrum.title, display: scrum.title)
}
let userScrums = try? await ScrumStore.load().map { scrum in
ScrumType(identifier: scrum.title, display: scrum.title)
}
let allScrums = sampleScrums + (userScrums ?? [])
let collection = INObjectCollection(items: allScrums)
return collection
}
// func provideScrumOptionsCollection(for intent: ScrumSelectionIntent, with completion: #escaping (INObjectCollection<ScrumType>?, Error?) -> Void) {}
}
import Foundation
import SwiftUI
class ScrumStore: ObservableObject {
#Published var scrums: [DailyScrum] = []
private static func fileURL() throws -> URL {
try FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
.appendingPathComponent("scrums.data")
}
static func load() async throws -> [DailyScrum] {
try await withCheckedThrowingContinuation { continuation in
load { result in
switch result {
case .failure(let error):
continuation.resume(throwing: error)
case .success(let scrums):
continuation.resume(returning: scrums)
}
}
}
}
static func load(completion: #escaping (Result<[DailyScrum], Error>)->Void) {
DispatchQueue.global(qos: .background).async {
do {
let fileURL = try fileURL()
guard let file = try? FileHandle(forReadingFrom: fileURL) else {
DispatchQueue.main.async {
completion(.success([]))
}
return
}
let dailyScrums = try JSONDecoder().decode([DailyScrum].self, from: file.availableData)
DispatchQueue.main.async {
completion(.success(dailyScrums))
}
} catch {
DispatchQueue.main.async {
completion(.failure(error))
}
}
}
}
#discardableResult
static func save(scrums: [DailyScrum]) async throws -> Int {
try await withCheckedThrowingContinuation { continuation in
save(scrums: scrums) { result in
switch result {
case .failure(let error):
continuation.resume(throwing: error)
case .success(let scrumsSaved):
continuation.resume(returning: scrumsSaved)
}
}
}
}
static func save(scrums: [DailyScrum], completion: #escaping (Result<Int, Error>)->Void) {
DispatchQueue.global(qos: .background).async {
do {
let data = try JSONEncoder().encode(scrums)
let outfile = try fileURL()
try data.write(to: outfile)
DispatchQueue.main.async {
completion(.success(scrums.count))
}
} catch {
DispatchQueue.main.async {
completion(.failure(error))
}
}
}
}
}
Folks, The following works except for the catch, xcode errors out with expected member name following '.'
Is this the proper way to promisify with PromiseKit?
All suggestions welcome! Thanks!
#IBAction func loginButtonTapped(sender: AnyObject) {
let email = userEmail.text!
let password = userPassword.text!
func onSuccess(success:Bool, message:String, token: String) -> Promise<Void> {
if success {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isUserLoggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
self.dismissViewControllerAnimated(true, completion: nil)
} else {
let myAlert = UIAlertController(title: "Alert", message: message, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "Try Again", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
}
return Promise { resolve, reject in
return resolve()
}
}
func onFailure(error:NSError) -> Promise<Void> {
return Promise { resolve, reject in
return reject(error)
}
}
Login(email, password: password).then(onSuccess).catch(onFailure)
}
private func Login(email: String, password: String) -> Promise<(success:Bool, message:String, token: String)> {
let parameters: [String: String] = [
"username" : email,
"password" : password
];
let endpoint = "https://api.foo.bar/login"
return Promise { resolve, reject in
Alamofire.request(.POST, endpoint, parameters: parameters, encoding: .JSON)
.validate()
.responseJSON { (response) in
guard response.result.error == nil else {
logger.debug(response)
let result:(success:Bool, message:String, token: String) = (false, "Login Failed", "")
return resolve(result)
}
if let value = response.result.value {
let apiResponseJSONBody = JSON(value)
let result:(success:Bool, message:String, token: String) = (true, "", token: apiResponseJSONBody["token"].string!)
return resolve(result)
}
}
}
}
I have this code:
let login: FBSDKLoginManager = FBSDKLoginManager()
login.logInWithPublishPermissions(["publish_actions"], handler: { (result: FBSDKLoginManagerLoginResult!, error: NSError!) -> Void in
if error != nil {
NSLog(error.localizedFailureReason!)
} else if result.isCancelled {
NSLog("Canceled")
} else if result.grantedPermissions.contains("publish_actions") {
self.loginFacebookButtin.hidden = true
}
})
This code worked ok, but I have this warning message:
'logInWithPublishPermissions(_:handler:)' is deprecated: use logInWithPublishPermissions:fromViewController:handler: instead
I tried to fix this warning but I could not. Someone knows how to fix it?
According to the FBSDK API:
The way you're using the method is deprecated. It wants you to use the new way it indicated in its documentation, as seen below:
- (void)
logInWithPublishPermissions: (NSArray *)permissions
handler: (FBSDKLoginManagerRequestTokenHandler)handler
__attribute__((deprecated("use logInWithPublishPermissions: fromViewController:handler: instead")));
Therefore you would use it like so:
let login: FBSDKLoginManager = FBSDKLoginManager()
login.logInWithPublishPermissions(["publish_actions"], fromViewController: self, handler: { (response: FBSDKLoginManagerLoginResult!, error: NSError!) in
if (error != nil) {
NSLog(error.localizedFailureReason!)
} else if result.isCancelled {
NSLog("Canceled")
} else if result.grantedPermissions.contains("publish_actions") {
self.loginFacebookButtin.hidden = true
}
})
You need to call the function like this:
let login: FBSDKLoginManager = FBSDKLoginManager()
login.logInWithPublishPermissions(["publish_actions"], fromViewController: self, handler: { (result: FBSDKLoginManagerLoginResult!, error: NSError!) -> Void in
if error != nil {
NSLog(error.localizedFailureReason!)
} else if result.isCancelled {
NSLog("Canceled")
} else if result.grantedPermissions.contains("publish_actions") {
self.loginFacebookButtin.hidden = true
}
})
I coded a function for OSX 10.10 that is willing to open a text file from an URL and display its content.
Everything is working but if the URL cannot be reach then the App will crash. How could I handle this type of Error?
I guess it comes from the completionHandler closure but I am not sure.
here is my code
#IBAction func checkAdminMessage(sender: NSMenuItem) {
let messageURL = NSURL(string: "http://www.xxxxxx.com/text.txt")
// The Network stuff will be handled in a background thread
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(messageURL!,
completionHandler: {
(location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
var urlContents = NSString(contentsOfURL: location, encoding: NSUTF8StringEncoding, error: nil)
// Check if text.txt has NULL as content
if urlContents! == "NULL" {
// Have to use Grand Central Dispatch to put NSAlert in the main thread
let noMessage = NSLocalizedString("Nothing there", comment: "Text to dislay when the file is empty" )
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.displayAlertNotification(notification: noMessage)
}
} else {
// If the file is not empty then we display the content of this file
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.displayAlertNotification(notification: urlContents!)
}
}
})
downloadTask.resume()
}
Thank you
EDIT: Here is the updated code but the App still crashed
#IBAction func checkAdminMessage(sender: NSMenuItem) {
if let messageURL = NSURL(string: "http://www.xxxxxx.com/text.txt") {
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(messageURL,
completionHandler: {
(location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
var urlContents = NSString(contentsOfURL: location, encoding: NSUTF8StringEncoding, error: nil )
if urlContents == "NULL" {
println(urlContents)
// Have to use Grand Central Dispatch to put NSAlert in the main thread
let noMessage = NSLocalizedString("Nothing there", comment: "Text to dislay when the file is empty" )
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.displayAlertNotification(notification: noMessage)
}
}
else {
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.displayAlertNotification(notification: urlContents!)
}
}
})
downloadTask.resume()
}
else {
println("Error")
}
}
NSURL(string: ...) returns an optional, so the result may be nil due to several reasons.
Wrap your code in a conditional unwrap:
if let messageURL = NSURL(string: "http://www.xxxxxx.com/text.txt") {
// success
...
}
else {
// error
}
I figured it out with the helps of the people that commented my question.
I was getting a nil from 'location' in downloadTaskWithUrl, then the var urlContents was receiving a nil as well.
The solution is to check if 'location' is nil :
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(messageURL,
completionHandler: {
(location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
**if (location != nil) {**
var urlContents = NSString(contentsOfURL: location, encoding: NSUTF8StringEncoding, error: nil ) ...
I want to add a new photo to certain album, I'm trying to do it like that:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
albumName = "\(data.objectAtIndex(indexPath.row))"
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Choose image source", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)
actionSheet.addAction(UIAlertAction(title: "Take Photo", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
imagePickerController.sourceType = UIImagePickerControllerSourceType.Camera
self.presentViewController(imagePickerController, animated: true, completion: {})
}))
actionSheet.addAction(UIAlertAction(title: "Camera Roll", style: UIAlertActionStyle.Default, handler: { (alert:UIAlertAction!) -> Void in
imagePickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(imagePickerController, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
self.presentViewController(actionSheet, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
let image:UIImage = info[UIImagePickerControllerOriginalImage] as UIImage
var groupToAddTo: ALAssetsGroup = ALAssetsGroup()
self.library.enumerateGroupsWithTypes(ALAssetsGroupType(ALAssetsGroupAlbum),
usingBlock: {
(group: ALAssetsGroup!, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
if group.valueForProperty(ALAssetsGroupPropertyName).isEqualToString(self.albumName){
groupToAddTo = group
}
},
failureBlock: {
(myerror: NSError!) -> Void in
println("error occurred: \(myerror.localizedDescription)")
})
var img: CGImageRef = image.CGImage
self.library.writeImageToSavedPhotosAlbum(img, metadata: nil, completionBlock: {
(assetUrl: NSURL!, error: NSError!) -> Void in
if error.code == 0 {
println("saved image completed: \(assetUrl)")
self.library.assetForURL(assetUrl, resultBlock: { (asset: ALAsset!) -> Void in
groupToAddTo.addAsset(asset)
return
}, failureBlock: {
(myerror: NSError!) -> Void in
println("error occurred: \(myerror.localizedDescription)")
})
} else {
println("saved image failed. \(error.localizedDescription) code \(error.code)")
}
} )
}
However, when I run this code, I get this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
in this line:
if group.valueForProperty(ALAssetsGroupPropertyName).isEqualToString(self.albumName){
So, the question is that, how to save an image to certain album in swift?
I am betting albumName is an optional value.
You should put an if statement to judge if almbumName is nil. When it's nil, create a newalbum name on your iPhone.
First:
if group != nil {
if group.valueForProperty(ALAssetsGroupPropertyName).isEqualToString(self.albumNames[indexPath.row]){
groupToAddTo = group
}
}
Second, when error = nil your app will crash because of "if error.code == 0." Do "if error == nil" instead.