Verified Commit 586ae6e4 authored by Geoff Pado's avatar Geoff Pado

Display alert when photo library permission is denied

parent 4b3642b2
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
041EFF76225C3DF10058D8EE /* PhotoLibraryViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041EFF75225C3DF10058D8EE /* PhotoLibraryViewLayout.swift */; }; 041EFF76225C3DF10058D8EE /* PhotoLibraryViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041EFF75225C3DF10058D8EE /* PhotoLibraryViewLayout.swift */; };
04D68BC5225EE2C000D09BBD /* GeometryExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D68BC4225EE2C000D09BBD /* GeometryExtensions.swift */; }; 04D68BC5225EE2C000D09BBD /* GeometryExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D68BC4225EE2C000D09BBD /* GeometryExtensions.swift */; };
04D68BC7225EE2FD00D09BBD /* PhotoLibraryViewCellImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D68BC6225EE2FD00D09BBD /* PhotoLibraryViewCellImageView.swift */; }; 04D68BC7225EE2FD00D09BBD /* PhotoLibraryViewCellImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D68BC6225EE2FD00D09BBD /* PhotoLibraryViewCellImageView.swift */; };
04D68BC92262B0C400D09BBD /* PhotoPermissionsRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D68BC82262B0C400D09BBD /* PhotoPermissionsRequester.swift */; };
04D68BCC2262B35700D09BBD /* PhotoPermissionsDeniedAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04D68BCB2262B35700D09BBD /* PhotoPermissionsDeniedAlertController.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
...@@ -74,6 +76,8 @@ ...@@ -74,6 +76,8 @@
041EFF75225C3DF10058D8EE /* PhotoLibraryViewLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryViewLayout.swift; sourceTree = "<group>"; }; 041EFF75225C3DF10058D8EE /* PhotoLibraryViewLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryViewLayout.swift; sourceTree = "<group>"; };
04D68BC4225EE2C000D09BBD /* GeometryExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeometryExtensions.swift; sourceTree = "<group>"; }; 04D68BC4225EE2C000D09BBD /* GeometryExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeometryExtensions.swift; sourceTree = "<group>"; };
04D68BC6225EE2FD00D09BBD /* PhotoLibraryViewCellImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryViewCellImageView.swift; sourceTree = "<group>"; }; 04D68BC6225EE2FD00D09BBD /* PhotoLibraryViewCellImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoLibraryViewCellImageView.swift; sourceTree = "<group>"; };
04D68BC82262B0C400D09BBD /* PhotoPermissionsRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPermissionsRequester.swift; sourceTree = "<group>"; };
04D68BCB2262B35700D09BBD /* PhotoPermissionsDeniedAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPermissionsDeniedAlertController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
...@@ -180,6 +184,7 @@ ...@@ -180,6 +184,7 @@
041EFF4C225302B90058D8EE /* Intro View */, 041EFF4C225302B90058D8EE /* Intro View */,
041EFF69225C36130058D8EE /* Photo Library */, 041EFF69225C36130058D8EE /* Photo Library */,
041EFF6D225C38800058D8EE /* PhotoSelectionViewController.swift */, 041EFF6D225C38800058D8EE /* PhotoSelectionViewController.swift */,
04D68BCA2262B34600D09BBD /* Photo Permissions */,
); );
path = "Photo Selection"; path = "Photo Selection";
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -193,6 +198,15 @@ ...@@ -193,6 +198,15 @@
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
04D68BCA2262B34600D09BBD /* Photo Permissions */ = {
isa = PBXGroup;
children = (
04D68BC82262B0C400D09BBD /* PhotoPermissionsRequester.swift */,
04D68BCB2262B35700D09BBD /* PhotoPermissionsDeniedAlertController.swift */,
);
path = "Photo Permissions";
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
...@@ -304,6 +318,8 @@ ...@@ -304,6 +318,8 @@
041EFF72225C3DC00058D8EE /* PhotoLibraryDataSource.swift in Sources */, 041EFF72225C3DC00058D8EE /* PhotoLibraryDataSource.swift in Sources */,
041EFEFB2251A9F30058D8EE /* AppViewController.swift in Sources */, 041EFEFB2251A9F30058D8EE /* AppViewController.swift in Sources */,
041EFF6E225C38800058D8EE /* PhotoSelectionViewController.swift in Sources */, 041EFF6E225C38800058D8EE /* PhotoSelectionViewController.swift in Sources */,
04D68BCC2262B35700D09BBD /* PhotoPermissionsDeniedAlertController.swift in Sources */,
04D68BC92262B0C400D09BBD /* PhotoPermissionsRequester.swift in Sources */,
041EFF192251AAFE0058D8EE /* UIViewControllerExtensions.swift in Sources */, 041EFF192251AAFE0058D8EE /* UIViewControllerExtensions.swift in Sources */,
041EFF52225303430058D8EE /* PromptButton.swift in Sources */, 041EFF52225303430058D8EE /* PromptButton.swift in Sources */,
041EFEF92251A9F30058D8EE /* AppDelegate.swift in Sources */, 041EFEF92251A9F30058D8EE /* AppDelegate.swift in Sources */,
......
...@@ -7,6 +7,8 @@ class AppViewController: UIViewController { ...@@ -7,6 +7,8 @@ class AppViewController: UIViewController {
init() { init() {
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
UIView.appearance().tintColor = .primary
let navigationController = NavigationController(rootViewController: PhotoSelectionViewController()) let navigationController = NavigationController(rootViewController: PhotoSelectionViewController())
embed(navigationController) embed(navigationController)
} }
......
...@@ -8,4 +8,10 @@ ...@@ -8,4 +8,10 @@
"IntroView.promptLabelText" = "Black Highlighter needs permission to edit your photos."; "IntroView.promptLabelText" = "Black Highlighter needs permission to edit your photos.";
"IntroView.promptButtonTitle" = "Grant Access"; "IntroView.promptButtonTitle" = "Grant Access";
"PhotoPermissionsDeniedAlertController.alertTitle" = "No Access to Your Photos";
"PhotoPermissionsDeniedAlertController.alertMessage" = "Black Highlighter needs permission to edit your photos. Open Settings to grant access.";
"PhotoPermissionsDeniedAlertController.actionButtonTitle" = "Open Settings";
"PhotoPermissionsDeniedAlertController.cancelButtonTitle" = "Dismiss";
"PhotoSelectionViewController.navigationItemTitle" = "Photos"; "PhotoSelectionViewController.navigationItemTitle" = "Photos";
// Created by Geoff Pado on 4/1/19. // Created by Geoff Pado on 4/1/19.
// Copyright © 2019 Cocoatype, LLC. All rights reserved. // Copyright © 2019 Cocoatype, LLC. All rights reserved.
import Photos
import UIKit import UIKit
class IntroViewController: UIViewController { class IntroViewController: UIViewController {
...@@ -14,21 +13,29 @@ class IntroViewController: UIViewController { ...@@ -14,21 +13,29 @@ class IntroViewController: UIViewController {
} }
@objc func requestPermission() { @objc func requestPermission() {
PHPhotoLibrary.requestAuthorization { status in permissionsRequester.requestAuthorization { [weak self] status in
print("got status: \(status)") switch status {
case .authorized:
if status == .authorized { UIApplication.shared.sendAction(#selector(PhotoSelectionViewController.showPhotoLibrary), to: nil, from: self, for: nil)
DispatchQueue.main.async { case .restricted:
UIApplication.shared.sendAction(#selector(PhotoSelectionViewController.showPhotoLibrary), to: nil, from: self, for: nil) #warning("handle restricted state")
} fatalError("handle restricted state")
case .denied:
self?.present(PhotoPermissionsDeniedAlertController(), animated: true)
case .notDetermined:
fallthrough
@unknown default:
break
} }
} }
print("permission requested")
} }
// MARK: Boilerplate // MARK: Boilerplate
private let permissionsRequester = PhotoPermissionsRequester()
@available(*, unavailable) @available(*, unavailable)
required init(coder: NSCoder) { required init(coder: NSCoder) {
let className = String(describing: type(of: self)) let className = String(describing: type(of: self))
......
// Created by Geoff Pado on 4/13/19.
// Copyright © 2019 Cocoatype, LLC. All rights reserved.
import UIKit
class PhotoPermissionsDeniedAlertController: UIAlertController {
init() {
super.init(nibName: nil, bundle: nil)
title = PhotoPermissionsDeniedAlertController.alertTitle
message = PhotoPermissionsDeniedAlertController.alertMessage
addAction(settingsAction)
addAction(cancelAction)
}
private let settingsAction = UIAlertAction(title: PhotoPermissionsDeniedAlertController.actionButtonTitle, style: .default, handler: { _ in
guard let settingsURL = URL(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(settingsURL)
})
private let cancelAction = UIAlertAction(title: PhotoPermissionsDeniedAlertController.cancelButtonTitle, style: .cancel, handler: nil)
// MARK: Boilerplate
override var preferredStyle: UIAlertController.Style { return .alert }
private static let alertTitle = NSLocalizedString("PhotoPermissionsDeniedAlertController.alertTitle", comment: "Title for the photo permissions denied alert")
private static let alertMessage = NSLocalizedString("PhotoPermissionsDeniedAlertController.alertMessage", comment: "Message for the photo permissions denied alert")
private static let actionButtonTitle = NSLocalizedString("PhotoPermissionsDeniedAlertController.actionButtonTitle", comment: "Title for the settings button on the photo permissions denied alert")
private static let cancelButtonTitle = NSLocalizedString("PhotoPermissionsDeniedAlertController.cancelButtonTitle", comment: "Title for the cancel button on the photo permissions denied alert")
@available(*, unavailable)
required init(coder: NSCoder) {
let className = String(describing: type(of: self))
fatalError("\(className) does not implement init(coder:)")
}
}
// Created by Geoff Pado on 4/13/19.
// Copyright © 2019 Cocoatype, LLC. All rights reserved.
import Photos
class PhotoPermissionsRequester: NSObject {
func requestAuthorization(_ handler: @escaping (PHAuthorizationStatus) -> Void) {
PHPhotoLibrary.requestAuthorization { authorizationStatus in
DispatchQueue.main.async {
handler(authorizationStatus)
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment