Skip to content

Commit

Permalink
Merge pull request #98 from iosphere/fix/availability
Browse files Browse the repository at this point in the history
Refactor to use compiler-verifyable availability checks
  • Loading branch information
Sebastian Hagedorn authored Sep 5, 2018
2 parents 4ff9a38 + 8cc92e4 commit 8f59fa8
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 77 deletions.
3 changes: 3 additions & 0 deletions ISHPermissionKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -761,6 +762,7 @@
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -825,6 +827,7 @@
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down
12 changes: 6 additions & 6 deletions ISHPermissionKit/ISHPermissionCategory.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ typedef NS_ENUM(NSUInteger, ISHPermissionCategory) {
* ISHPermissionRequestPhotoLibraryEnabled. This will link the
* Photos frameworks.
*/
ISHPermissionCategoryModernPhotoLibrary NS_ENUM_AVAILABLE_IOS(8_0) = 5050,
ISHPermissionCategoryModernPhotoLibrary = 5050,
#endif

#ifdef ISHPermissionRequestCameraEnabled
Expand Down Expand Up @@ -250,7 +250,7 @@ typedef NS_ENUM(NSUInteger, ISHPermissionCategory) {
* ISHPermissionRequestContactsEnabled. This will link the Contacts
* framework.
*/
ISHPermissionCategoryContacts NS_ENUM_AVAILABLE_IOS(9_0) = 8500,
ISHPermissionCategoryContacts = 8500,
#endif

#ifdef ISHPermissionRequestCalendarEnabled
Expand Down Expand Up @@ -297,7 +297,7 @@ typedef NS_ENUM(NSUInteger, ISHPermissionCategory) {
* ISHPermissionRequestSiriEnabled. This will link the Intents
* framework.
*/
ISHPermissionCategorySiri NS_ENUM_AVAILABLE_IOS(10_0) = 9000,
ISHPermissionCategorySiri = 9000,
#endif

#ifdef ISHPermissionRequestSpeechEnabled
Expand All @@ -312,7 +312,7 @@ typedef NS_ENUM(NSUInteger, ISHPermissionCategory) {
* ISHPermissionRequestSpeechEnabled. This will link the Speech
* framework.
*/
ISHPermissionCategorySpeechRecognition NS_ENUM_AVAILABLE_IOS(10_0) = 10000,
ISHPermissionCategorySpeechRecognition = 10000,
#endif

#ifdef ISHPermissionRequestNotificationsEnabled
Expand All @@ -334,7 +334,7 @@ typedef NS_ENUM(NSUInteger, ISHPermissionCategory) {
* ISHPermissionRequestNotificationsEnabled. This will link UIKit and
* the UserNotification framework.
*/
ISHPermissionCategoryUserNotification NS_ENUM_AVAILABLE_IOS(10_0) = 6500,
ISHPermissionCategoryUserNotification = 6500,
#endif

#ifdef ISHPermissionRequestMusicLibraryEnabled
Expand All @@ -349,7 +349,7 @@ typedef NS_ENUM(NSUInteger, ISHPermissionCategory) {
* ISHPermissionRequestMusicLibraryEnabled. This will link the MediaPlayer
* framework.
*/
ISHPermissionCategoryMusicLibrary NS_ENUM_AVAILABLE_IOS(9.3) = 11000,
ISHPermissionCategoryMusicLibrary = 11000,
#endif
};

Expand Down
24 changes: 11 additions & 13 deletions ISHPermissionKit/Requests/ISHPermissionRequestMusicLibrary.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
@implementation ISHPermissionRequestMusicLibrary

- (ISHPermissionState)permissionState {
if (![MPMediaLibrary respondsToSelector:@selector(requestAuthorization:)]) {
if (@available(iOS 9.3, *)) {
return [self permissionStateForMediaLibraryState:[MPMediaLibrary authorizationStatus]];
} else {
// prior to iOS 9.3, authorization is not required
return ISHPermissionStateAuthorized;
}

return [self permissionStateForMediaLibraryState:[MPMediaLibrary authorizationStatus]];
}

- (ISHPermissionState)permissionStateForMediaLibraryState:(MPMediaLibraryAuthorizationStatus)state {
- (ISHPermissionState)permissionStateForMediaLibraryState:(MPMediaLibraryAuthorizationStatus)state API_AVAILABLE(ios(9.3)){
switch (state) {
case MPMediaLibraryAuthorizationStatusAuthorized:
return ISHPermissionStateAuthorized;
Expand All @@ -46,19 +46,17 @@ - (void)requestUserPermissionWithCompletionBlock:(ISHPermissionRequestCompletion
return;
}

if (![MPMediaLibrary respondsToSelector:@selector(requestAuthorization:)]) {
if (@available(iOS 9.3, *)) {
[MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, [self permissionStateForMediaLibraryState:status], nil);
});
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, ISHPermissionStateUnsupported, nil);
});

return;
}

[MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, [self permissionStateForMediaLibraryState:status], nil);
});
}];
}

#if DEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ - (void)ISHPermissionNotificationApplicationDidRegisterUserNotificationSettings:

// we also load a new instance of the related user notification so it can update
// its internal state
__unused id modernPermission = [[ISHPermissionRequestUserNotification alloc] init];
if (@available(iOS 10.0, *)) {
__unused id modernPermission = [[ISHPermissionRequestUserNotification alloc] init];
}
}

@end
Expand Down
24 changes: 11 additions & 13 deletions ISHPermissionKit/Requests/ISHPermissionRequestSiri.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
@implementation ISHPermissionRequestSiri

- (ISHPermissionState)permissionState {
if (![INPreferences class]) {
if (@available(iOS 10.0, *)) {
return [self permissionStateForSiriState:[INPreferences siriAuthorizationStatus]];
} else {
return ISHPermissionStateUnsupported;
}

return [self permissionStateForSiriState:[INPreferences siriAuthorizationStatus]];
}

- (ISHPermissionState)permissionStateForSiriState:(INSiriAuthorizationStatus)siriState {
- (ISHPermissionState)permissionStateForSiriState:(INSiriAuthorizationStatus)siriState API_AVAILABLE(ios(10.0)){
switch (siriState) {
case INSiriAuthorizationStatusAuthorized:
return ISHPermissionStateAuthorized;
Expand All @@ -45,19 +45,17 @@ - (void)requestUserPermissionWithCompletionBlock:(ISHPermissionRequestCompletion
return;
}

if (![INPreferences class]) {
if (@available(iOS 10.0, *)) {
[INPreferences requestSiriAuthorization:^(INSiriAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, [self permissionStateForSiriState:status], nil);
});
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, ISHPermissionStateUnsupported, nil);
});

return;
}

[INPreferences requestSiriAuthorization:^(INSiriAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, [self permissionStateForSiriState:status], nil);
});
}];
}

#if DEBUG
Expand Down
24 changes: 11 additions & 13 deletions ISHPermissionKit/Requests/ISHPermissionRequestSpeechRecognition.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
@implementation ISHPermissionRequestSpeechRecognition

- (ISHPermissionState)permissionState {
if (![SFSpeechRecognizer class]) {
if (@available(iOS 10.0, *)) {
return [self permissionStateForSpeechState:[SFSpeechRecognizer authorizationStatus]];
} else {
return ISHPermissionStateUnsupported;
}

return [self permissionStateForSpeechState:[SFSpeechRecognizer authorizationStatus]];
}

- (ISHPermissionState)permissionStateForSpeechState:(SFSpeechRecognizerAuthorizationStatus)state {
- (ISHPermissionState)permissionStateForSpeechState:(SFSpeechRecognizerAuthorizationStatus)state API_AVAILABLE(ios(10.0)){
switch ([SFSpeechRecognizer authorizationStatus]) {
case SFSpeechRecognizerAuthorizationStatusAuthorized:
return ISHPermissionStateAuthorized;
Expand All @@ -45,19 +45,17 @@ - (void)requestUserPermissionWithCompletionBlock:(ISHPermissionRequestCompletion
return;
}

if (![SFSpeechRecognizer class]) {
if (@available(iOS 10.0, *)) {
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, [self permissionStateForSpeechState:status], nil);
});
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, ISHPermissionStateUnsupported, nil);
});

return;
}

[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, [self permissionStateForSpeechState:status], nil);
});
}];
}

#if DEBUG
Expand Down
64 changes: 33 additions & 31 deletions ISHPermissionKit/Requests/ISHPermissionRequestUserNotification.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ @implementation ISHPermissionRequestUserNotification
- (instancetype)init {
self = [super init];

if (self && [UNUserNotificationCenter class]) {
// we can only update the internal state asynchrounously,
// so we do it as early as possible
[self updateInternalPermissionState];
self.desiredOptions = UNAuthorizationOptionAlert;
if (self) {
if (@available(iOS 10.0, *)) {
// we can only update the internal state asynchrounously,
// so we do it as early as possible
[self updateInternalPermissionState];
self.desiredOptions = UNAuthorizationOptionAlert;
}
}

return self;
}

- (void)updateInternalPermissionState {
- (void)updateInternalPermissionState API_AVAILABLE(ios(10.0)) {
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
ISHPermissionState state = [self permissionStateForNotificationSettings:settings];
[self setInternalPermissionState:state];
Expand All @@ -40,25 +42,26 @@ - (BOOL)allowsConfiguration {
}

- (ISHPermissionState)permissionState {
if (![UNUserNotificationCenter class]) {
if (@available(iOS 10.0, *)) {
// we cannot get the current state synchrounously, but update
// it when initializing the class
return [self internalPermissionState];
} else {
// cannot request using the new API: should use
// ISHPermissionCategoryNotificationRemote/...Local
return ISHPermissionStateUnsupported;
}

// we cannot get the current state synchrounously, but update
// it when initializing the class
return [self internalPermissionState];
}

- (ISHPermissionState)permissionStateForNotificationSettings:(UNNotificationSettings *)settings {
- (ISHPermissionState)permissionStateForNotificationSettings:(UNNotificationSettings *)settings API_AVAILABLE(ios(10.0)) {
switch (settings.authorizationStatus) {
case UNAuthorizationStatusAuthorized:
return ISHPermissionStateAuthorized;

case UNAuthorizationStatusDenied:
return ISHPermissionStateDenied;

#ifdef __IPHONE_12_0
/**
* You can ask for provisional permission (you must do this explicitly via desiredOptions,
* which will allow you to send one quiet (no alert/sound, but in the notification center)
Expand All @@ -69,6 +72,7 @@ - (ISHPermissionState)permissionStateForNotificationSettings:(UNNotificationSett
* which is why we treat it as UNAuthorizationStatusNotDetermined here.
*/
case UNAuthorizationStatusProvisional:
#endif
case UNAuthorizationStatusNotDetermined:
return ISHPermissionStateUnknown;
}
Expand All @@ -82,29 +86,27 @@ - (void)requestUserPermissionWithCompletionBlock:(ISHPermissionRequestCompletion
return;
}

if (![UNUserNotificationCenter class]) {
if (@available(iOS 10.0, *)) {
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:self.desiredOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
NSSet *deniedError = [NSSet setWithObject:@(UNErrorCodeNotificationsNotAllowed)];
NSError *externalError = [[self class] externalErrorForError:error validationDomain:UNErrorDomain denialCodes:deniedError];

// granted is only YES when all options were granted, but our auth status
// should reflect whether it is generally possible to use the API, i.e.,
// any option was granted
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
dispatch_async(dispatch_get_main_queue(), ^{
ISHPermissionState newState = [self permissionStateForNotificationSettings:settings];
[self setInternalPermissionState:newState];
completion(self, newState, externalError);
});
}];
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
completion(self, ISHPermissionStateUnsupported, nil);
});

return;
}

[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:self.desiredOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
NSSet *deniedError = [NSSet setWithObject:@(UNErrorCodeNotificationsNotAllowed)];
NSError *externalError = [[self class] externalErrorForError:error validationDomain:UNErrorDomain denialCodes:deniedError];

// granted is only YES when all options were granted, but our auth status
// should reflect whether it is generally possible to use the API, i.e.,
// any option was granted
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
dispatch_async(dispatch_get_main_queue(), ^{
ISHPermissionState newState = [self permissionStateForNotificationSettings:settings];
[self setInternalPermissionState:newState];
completion(self, newState, externalError);
});
}];
}];
}

@end
Expand Down

0 comments on commit 8f59fa8

Please sign in to comment.