Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMitch Little
11,870 PointsRestaurant Reviews App - Cannot update button when location permission is allowed by user.
When I allow the location request on the simulator, the button does not update as defined in authorizationSuceeded().
See permissions controller and location manager classes.
import UIKit
import OAuth2
import CoreLocation
class PermissionsController: UIViewController, LocationPermissionsDelegate {
let oauth = OAuth2ClientCredentials(settings: [
"client_id": "n2p6xlomYrHxVlbwOyN9fQ",
"client_secret": "9Z9PgLquQ6gSRGWJpY4PwJC3bBBKpS2qxcLQsKyEd44Hd78crGZsk3Ac7r48jrJd",
"authorize_uri": "https://api.yelp.com/oauth2/token",
"secret_in_body": true,
"keychain": false
])
lazy var locationManager: LocationManager = {
return LocationManager(permissionsDelegate: self)
}()
var isAuthorizedForLocation: Bool
var isAuthenticatedWithToken: Bool
lazy var locationPermissionButton: UIButton = {
let title = self.isAuthorizedForLocation ? "Location Permissions Granted" : "Request Location Permissions"
let button = UIButton(type: .system)
let controlState = self.isAuthorizedForLocation ? UIControlState.disabled : UIControlState.normal
button.isEnabled = !self.isAuthorizedForLocation
button.setTitle(title, for: controlState)
button.addTarget(self, action: #selector(PermissionsController.requestLocationPermissions), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = UIColor(red: 62/255.0, green: 71/255.0, blue: 79/255.0, alpha: 1.0)
button.setTitleColor(UIColor(red: 178/255.0, green: 187/255.0, blue: 185/255.0, alpha: 1.0), for: .disabled)
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 5
button.clipsToBounds = true
return button
}()
lazy var oauthTokenButton: UIButton = {
let title = self.isAuthenticatedWithToken ? "OAuth Token Granted" : "Request OAuth Token"
let button = UIButton(type: .system)
let controlState = self.isAuthenticatedWithToken ? UIControlState.disabled : UIControlState.normal
button.isEnabled = !self.isAuthenticatedWithToken
button.setTitle(title, for: controlState)
button.addTarget(self, action: #selector(PermissionsController.requestOAuthToken), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = UIColor(red: 62/255.0, green: 71/255.0, blue: 79/255.0, alpha: 1.0)
button.setTitleColor(UIColor(red: 178/255.0, green: 187/255.0, blue: 185/255.0, alpha: 1.0), for: .disabled)
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 5
button.clipsToBounds = true
return button
}()
lazy var activityIndicator: UIActivityIndicatorView = {
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .white)
indicator.hidesWhenStopped = true
indicator.translatesAutoresizingMaskIntoConstraints = false
return indicator
}()
lazy var dismissButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Dismiss", for: .normal)
button.tintColor = .white
button.addTarget(self, action: #selector(PermissionsController.dismissPermissions), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init coder not implemented")
}
init(isAuthorizedForLocation authorized: Bool, isAuthenticatedWithToken authenticated: Bool) {
self.isAuthorizedForLocation = authorized
self.isAuthenticatedWithToken = authenticated
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 95/255.0, green: 207/255.0, blue: 128/255.0, alpha: 1.0)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let stackView = UIStackView(arrangedSubviews: [locationPermissionButton, oauthTokenButton])
stackView.alignment = .center
stackView.axis = .vertical
stackView.distribution = .equalSpacing
stackView.spacing = 16.0
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
view.addSubview(dismissButton)
view.addSubview(activityIndicator)
NSLayoutConstraint.activate([
locationPermissionButton.heightAnchor.constraint(equalToConstant: 64.0),
locationPermissionButton.leadingAnchor.constraint(equalTo: stackView.leadingAnchor),
locationPermissionButton.trailingAnchor.constraint(equalTo: stackView.trailingAnchor),
oauthTokenButton.heightAnchor.constraint(equalToConstant: 64.0),
oauthTokenButton.leadingAnchor.constraint(equalTo: stackView.leadingAnchor),
oauthTokenButton.trailingAnchor.constraint(equalTo: stackView.trailingAnchor),
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 32.0),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -32.0),
dismissButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -16),
dismissButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
activityIndicator.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 175),
activityIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
}
@objc func requestLocationPermissions() {
do {
try locationManager.requestLocationAuthorisation()
} catch LocationError.disallowedByUser {
// show alert to user
} catch let error {
print("Location Authorisation Error: \(error.localizedDescription)")
}
}
@objc func requestOAuthToken() {
self.activityIndicator.startAnimating()
oauth.authorize { authParams, error in
if let params = authParams {
guard let token = params["access_token"] as? String,
let expiration = params["expires_in"] as? TimeInterval else {
return
}
let account = YelpAccount(accessToken: token, expiration: expiration, grantDate: Date())
do {
try account.save()
self.oauthTokenButton.setTitle("Oauth Token Granted", for: .disabled)
self.oauthTokenButton.isEnabled = false
self.activityIndicator.stopAnimating()
} catch let error {
print(error)
self.oauthTokenButton.setTitle("Error", for: .disabled)
self.oauthTokenButton.isEnabled = false
self.activityIndicator.stopAnimating()
}
} else {
print("Authorisation was cancelled or went wrong: \(error!)")
}
}
}
@objc func dismissPermissions() {
dismiss(animated: true, completion: nil)
}
// MARK: Location Permissions Delegate
func authorizationSucceeded() {
locationPermissionButton.setTitle("Location Permissions Granted", for: .disabled)
locationPermissionButton.isEnabled = false
}
func authorizationFailedWithStatus(_ status: CLAuthorizationStatus) {
//
}
}
import Foundation
import CoreLocation
enum LocationError: Error {
case unknownError
case disallowedByUser
case unableToFindLocation
}
protocol LocationPermissionsDelegate: class {
func authorizationSucceeded()
func authorizationFailedWithStatus(_ status: CLAuthorizationStatus)
}
// if location services implementation failes - check to see if the appropriate location services are available for you to use, as described in 'Determining the Availability of Location Services'.
class LocationManager: NSObject, CLLocationManagerDelegate {
// 3. Create an instance of the CLLocationManager class and store a strong reference to it somewhere in your app.
private let manager = CLLocationManager()
weak var permissionsDelegate: LocationPermissionsDelegate?
init(permissionsDelegate: LocationPermissionsDelegate?) {
self.permissionsDelegate = permissionsDelegate
super.init()
manager.delegate = self
}
func requestLocationAuthorisation() throws {
let authorisationStatus = CLLocationManager.authorizationStatus()
// 1. Check to see if your app is authorized to use location services and request permission if your app's authorization status is not yet determined, as described in Requesting Permission to Use Location Services.
if authorisationStatus == .restricted || authorisationStatus == .denied {
throw LocationError.disallowedByUser
} else if authorisationStatus == .notDetermined {
// making location authorisation request
manager.requestWhenInUseAuthorization()
} else {
return
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
permissionsDelegate?.authorizationSucceeded()
} else {
permissionsDelegate?.authorizationFailedWithStatus(status)
}
}
}
}
Any help would be greatly appreciated.
Thank you,
Mitch
1 Answer
Mitch Little
11,870 PointsWhoops. Simple syntactical error.
Placed locationManager(didChangeAuthorisation:) within requestionLocationAuthorisation().
All fixed.
Thank you,
Mitch