This repository has been archived by the owner on Feb 28, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
995 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
30 changes: 30 additions & 0 deletions
30
Source/AlecrimAsyncKit/Additional Conditions/BooleanTaskCondition.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// BooleanTaskCondition.swift | ||
// AlecrimAsyncKit | ||
// | ||
// Created by Vanderlei Martinelli on 2015-09-06. | ||
// Copyright © 2015 Alecrim. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// A condition that is satisfied according a boolean value. | ||
public final class BooleanTaskCondition: TaskCondition { | ||
|
||
/// Initializes a `BooleanTaskCondition` that will be satisfied if the passed closure returns `true`. | ||
/// | ||
/// - parameter valueClosure: The closure that will return `true` if the condition is satisfied, `false` otherwise. | ||
/// | ||
/// - returns: An initialized `BooleanTaskCondition` that will be satisfied if the passed closure returns `true` | ||
public init(@autoclosure(escaping) _ valueClosure: () -> Bool) { | ||
super.init() { result in | ||
if valueClosure() { | ||
result(.Satisfied) | ||
} | ||
else { | ||
result(.NotSatisfied) | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
Source/AlecrimAsyncKit/Convenience Conditions/EventStorePermissionTaskCondition.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// | ||
// EventStorePermissionTaskCondition.swift | ||
// AlecrimAsyncKit | ||
// | ||
// Created by Vanderlei Martinelli on 2015-09-06. | ||
// Copyright © 2015 Alecrim. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import EventKit | ||
|
||
// `EKEventStore` takes a while to initialize, so we use a shared instance. | ||
private let _sharedEventStore = EKEventStore() | ||
|
||
/// A condition for verifying access to the user's calendar. | ||
public final class EventStorePermissionTaskCondition: TaskCondition { | ||
|
||
private static func asyncRequestAuthorization(entityType: EKEntityType) -> Task<Void> { | ||
return asyncEx(condition: MutuallyExclusiveTaskCondition(.Alert)) { task in | ||
let status = EKEventStore.authorizationStatusForEntityType(entityType) | ||
|
||
switch status { | ||
case .NotDetermined: | ||
dispatch_async(dispatch_get_main_queue()) { | ||
_sharedEventStore.requestAccessToEntityType(entityType) { _, error in | ||
if let error = error { | ||
task.finishWithError(error) | ||
} | ||
else { | ||
task.finish() | ||
} | ||
} | ||
} | ||
|
||
default: | ||
task.finish() | ||
} | ||
} | ||
} | ||
|
||
/// Initializes a condition for verifying access to the user's calendar. | ||
/// | ||
/// - parameter entityType: The authorization needed (event or reminder). | ||
/// | ||
/// - returns: A condition for verifying access to the user's calendar. | ||
public init(entityType: EKEntityType) { | ||
super.init(dependencyTask: EventStorePermissionTaskCondition.asyncRequestAuthorization(entityType)) { result in | ||
switch EKEventStore.authorizationStatusForEntityType(entityType) { | ||
case .Authorized: | ||
result(.Satisfied) | ||
|
||
default: | ||
result(.NotSatisfied) | ||
} | ||
} | ||
} | ||
|
||
} |
115 changes: 115 additions & 0 deletions
115
Source/AlecrimAsyncKit/Convenience Conditions/LocationPermissionTaskCondition.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// | ||
// LocationPermissionTaskCondition.swift | ||
// AlecrimAsyncKit | ||
// | ||
// Created by Vanderlei Martinelli on 2015-09-05. | ||
// Copyright © 2015 Alecrim. All rights reserved. | ||
// | ||
|
||
#if os(iOS) | ||
|
||
import Foundation | ||
import CoreLocation | ||
|
||
/// A condition for verifying access to the user's location. | ||
public final class LocationPermissionTaskCondition: TaskCondition { | ||
|
||
public enum Usage { | ||
case WhenInUse | ||
case Always | ||
} | ||
|
||
private static func asyncRequestAuthorizationIfNeededForUsage(usage: LocationPermissionTaskCondition.Usage) -> Task<Void> { | ||
return asyncEx(condition: MutuallyExclusiveTaskCondition(.Alert)) { task in | ||
/* | ||
Not only do we need to handle the "Not Determined" case, but we also | ||
need to handle the "upgrade" (.WhenInUse -> .Always) case. | ||
*/ | ||
switch (CLLocationManager.authorizationStatus(), usage) { | ||
case (.NotDetermined, _), (.AuthorizedWhenInUse, .Always): | ||
let locationManager = LocationManager() | ||
locationManager.didChangeAuthorizationStatusClosure = { status in | ||
task.finish() | ||
} | ||
|
||
let key: String | ||
|
||
switch usage { | ||
case .WhenInUse: | ||
key = "NSLocationWhenInUseUsageDescription" | ||
dispatch_async(dispatch_get_main_queue()) { | ||
locationManager.requestWhenInUseAuthorization() | ||
} | ||
|
||
case .Always: | ||
key = "NSLocationAlwaysUsageDescription" | ||
dispatch_async(dispatch_get_main_queue()) { | ||
locationManager.requestAlwaysAuthorization() | ||
} | ||
} | ||
|
||
// This is helpful when developing the app. | ||
assert(NSBundle.mainBundle().objectForInfoDictionaryKey(key) != nil, "Requesting location permission requires the \(key) key in your Info.plist") | ||
|
||
|
||
default: | ||
task.finish() | ||
} | ||
} | ||
} | ||
|
||
/// Initializes a condition for verifying access to the user's location. | ||
/// | ||
/// - parameter usage: The needed usage (when app is in use only or always). | ||
/// | ||
/// - returns: A condition for verifying access to the user's location. | ||
public init(usage: LocationPermissionTaskCondition.Usage) { | ||
super.init(dependencyTask: LocationPermissionTaskCondition.asyncRequestAuthorizationIfNeededForUsage(usage)) { result in | ||
let enabled = CLLocationManager.locationServicesEnabled() | ||
let actual = CLLocationManager.authorizationStatus() | ||
|
||
// There are several factors to consider when evaluating this condition | ||
switch (enabled, usage, actual) { | ||
case (true, _, .AuthorizedAlways): | ||
// The service is enabled, and we have "Always" permission -> condition satisfied. | ||
result(.Satisfied) | ||
|
||
case (true, .WhenInUse, .AuthorizedWhenInUse): | ||
// The service is enabled, and we have and need "WhenInUse" permission -> condition satisfied. | ||
result(.Satisfied) | ||
|
||
default: | ||
/* | ||
Anything else is an error. Maybe location services are disabled, | ||
or maybe we need "Always" permission but only have "WhenInUse", | ||
or maybe access has been restricted or denied, | ||
or maybe access hasn't been request yet. | ||
|
||
The last case would happen if this condition were wrapped in a `SilentCondition`. | ||
*/ | ||
result(.NotSatisfied) | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
private final class LocationManager: CLLocationManager, CLLocationManagerDelegate { | ||
|
||
private var didChangeAuthorizationStatusClosure: ((CLAuthorizationStatus) -> Void)? = nil | ||
|
||
private override init() { | ||
super.init() | ||
self.delegate = self | ||
} | ||
|
||
@objc private func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) { | ||
self.didChangeAuthorizationStatusClosure?(status) | ||
|
||
self.delegate = nil | ||
self.didChangeAuthorizationStatusClosure = nil | ||
} | ||
|
||
} | ||
|
||
#endif |
33 changes: 33 additions & 0 deletions
33
Source/AlecrimAsyncKit/Convenience Conditions/PassLibraryAvailableCondition.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// PassLibraryAvailableCondition.swift | ||
// AlecrimAsyncKit | ||
// | ||
// Created by Vanderlei Martinelli on 2015-09-05. | ||
// Copyright © 2015 Alecrim. All rights reserved. | ||
// | ||
|
||
#if os(iOS) | ||
|
||
import Foundation | ||
import PassKit | ||
|
||
/// A condition for verifying that Passbook exists and is accessible. | ||
public final class PassLibraryAvailableCondition: TaskCondition { | ||
|
||
/// Initializes a condition for verifying that Passbook exists and is accessible. | ||
/// | ||
/// - returns: A condition for verifying that Passbook exists and is accessible. | ||
public init() { | ||
super.init() { result in | ||
if PKPassLibrary.isPassLibraryAvailable() { | ||
result(.Satisfied) | ||
} | ||
else { | ||
result(.NotSatisfied) | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
#endif |
Oops, something went wrong.