So I wanted to check if I have access to the user location on iOS14 or not & I found this code but XCode(12) yells at me with this:
'authorizationStatus()' was deprecated in iOS 14.0
And here is the code:
func hasLocationPermission() -> Bool {
var hasPermission = false
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() { // <= 'authorizationStatus()' was deprecated in iOS 14.0
case .notDetermined, .restricted, .denied:
hasPermission = false
case .authorizedAlways, .authorizedWhenInUse:
hasPermission = true
#unknown default:
hasPermission = false
}
} else {
hasPermission = false
}
return hasPermission
}
So what should I use instead?
iOS 14 and earlier version
func locationAuthorizationStatus() -> CLAuthorizationStatus {
let locationManager = CLLocationManager()
var locationAuthorizationStatus : CLAuthorizationStatus
if #available(iOS 14.0, *) {
locationAuthorizationStatus = locationManager.authorizationStatus
} else {
// Fallback on earlier versions
locationAuthorizationStatus = CLLocationManager.authorizationStatus()
}
return locationAuthorizationStatus
}
In iOS 14 'authorizationStatus()' is deprecated :
https://developer.apple.com/documentation/corelocation/cllocationmanager/1423523-authorizationstatus
You should use locationManagerDidChangeAuthorization instead:
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .authorizedAlways , .authorizedWhenInUse:
break
case .notDetermined , .denied , .restricted:
break
default:
break
}
switch manager.accuracyAuthorization {
case .fullAccuracy:
break
case .reducedAccuracy:
break
default:
break
}
}
iOS 14 Check user is allow permission
extension CLLocationManager {
func checkLocationPermission() {
if self.authorizationStatus != .authorizedWhenInUse && self.authorizationStatus != .authorizedAlways {
self.requestAlwaysAuthorization()
}
}
}
Use
self.LocationManager.checkLocationPermission()
Related
I am trying to show an Open Ad from Google Admob in my SwiftUI app. I am not too familiar with UIKit and stuff...
I am keep getting this error in my console: " Status bar could not be hidden for full screen ad. Ensure that your app is configured to allow full screen ads to control the status bar. For example, consider whether you need to set the childViewControllerForStatusBarHidden property on your ad's rootViewController."
How do I solve this?
// Extending Application to get RootView..
extension UIApplication {
func getRootViewController() -> UIViewController {
guard let scene = self.connectedScenes.first as? UIWindowScene else {
return .init()
}
guard let root = scene.windows.first?.rootViewController else {
return .init()
}
return root
}
}
final class OpenAd: NSObject, GADFullScreenContentDelegate {
var appOpenAd: GADAppOpenAd?
var loadTime = Date()
func currentDeviceOrientation() -> UIInterfaceOrientation {
let currentOrientation = UIDevice.current.orientation
switch currentOrientation {
case .unknown:
return .unknown
case .portrait:
return .portrait
case .portraitUpsideDown:
return .portraitUpsideDown
case .landscapeLeft:
return .landscapeLeft
case .landscapeRight:
return .landscapeRight
case .faceUp:
return .portrait
case .faceDown:
return .portrait
#unknown default:
return .unknown
}
}
func showAdForFirstLaunch() {
let request = GADRequest()
GADAppOpenAd.load(withAdUnitID: "ca-app-pub-3940256099942544/5662855259",
request: request,
orientation: UIInterfaceOrientation.portrait,
completionHandler: { (appOpenAdIn, _) in
self.appOpenAd = appOpenAdIn
self.appOpenAd?.fullScreenContentDelegate = self
self.loadTime = Date()
self.appOpenAd?.present(fromRootViewController: UIApplication.shared.getRootViewController())
})
}
func requestAppOpenAd() {
let request = GADRequest()
GADAppOpenAd.load(withAdUnitID: "ca-app-pub-3940256099942544/5662855259",
request: request,
orientation: UIInterfaceOrientation.portrait,
completionHandler: { (appOpenAdIn, _) in
self.appOpenAd = appOpenAdIn
self.appOpenAd?.fullScreenContentDelegate = self
self.loadTime = Date()
print("[OPEN AD] Ad is ready")
})
}
func tryToPresentAd() {
if let gOpenAd = self.appOpenAd, wasLoadTimeLessThanNHoursAgo(thresholdN: 4) {
gOpenAd.present(fromRootViewController: UIApplication.shared.getRootViewController())
} else {
self.requestAppOpenAd()
}
}
func wasLoadTimeLessThanNHoursAgo(thresholdN: Int) -> Bool {
let now = Date()
let timeIntervalBetweenNowAndLoadTime = now.timeIntervalSince(self.loadTime)
let secondsPerHour = 3600.0
let intervalInHours = timeIntervalBetweenNowAndLoadTime / secondsPerHour
return intervalInHours < Double(thresholdN)
}
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
print("[OPEN AD] Failed: \(error)")
requestAppOpenAd()
}
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
requestAppOpenAd()
print("[OPEN AD] Ad dismissed")
}
}
I have the following code which should return the setting of the NotificationCenter, but when I run this code the variable notificationSetting returns nothing.
How can I solve this so that the application waits for the result?
func getNotificationSetting() -> String{
var notificationSetting = ""
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
switch settings.authorizationStatus {
case .authorized, .provisional:
notificationSetting = "Authorized"
case .denied:
notificationSetting = "Denied"
case .notDetermined:
notificationSetting = "NotDetermined"
#unknown default:
notificationSetting = "NotDetermined"
}
}
return notificationSetting
}
getNotificationSettings execute asynchronously.
func getNotificationSetting(completionHandler: #escaping (String) -> Void) {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
switch settings.authorizationStatus {
case .authorized, .provisional:
completionHandler("Authorized")
case .denied:
completionHandler("Denied")
case .notDetermined:
completionHandler("NotDetermined")
#unknown default:
completionHandler("NotDetermined")
}
}
}
func getSettings() {
self.getNotificationSetting(completionHandler: { (notificationSetting) in
// do what you want
print(notificationSetting)
})
}
I'm new to asking questions.
I need help in creating a feature of the app which is to unlock the tabbar when a purchase is made.
I used this code to lock my tabbar which is in the override func viewDidLoad()
I would really appreciate if someone could sort this out for me! I have been researching all day with no answers. Thanks!
if let arrayOfTabBarItems = tabBarController?.tabBar.items as AnyObject as? NSArray,let tabBarItem1 = arrayOfTabBarItems[0] as? UITabBarItem {
tabBarItem1.isEnabled = true
}
if let arrayOfTabBarItems = tabBarController?.tabBar.items as AnyObject as? NSArray,let tabBarItem2 = arrayOfTabBarItems[1] as? UITabBarItem {
if nonConsumablePurchaseMade == true {
tabBarItem2.isEnabled = true
print("done")
} else
{
tabBarItem2.isEnabled = false
print("failed")
}
}
if let arrayOfTabBarItems = tabBarController?.tabBar.items as AnyObject as? NSArray,let tabBarItem3 = arrayOfTabBarItems[2] as? UITabBarItem {
tabBarItem3.isEnabled = false
}
if let arrayOfTabBarItems = tabBarController?.tabBar.items as AnyObject as? NSArray,let tabBarItem4 = arrayOfTabBarItems[3] as? UITabBarItem {
tabBarItem4.isEnabled = false
}
and this might help. They are the functions for the purchases.
func purchaseProduct(with id: String){
SwiftyStoreKit.retrieveProductsInfo([id]) { result in
if let product = result.retrievedProducts.first {
SwiftyStoreKit.purchaseProduct(product, quantity: 1, atomically: true) { result in
switch result {
case .success(let product):
// fetch content from your server, then:
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
case .error(let error):
switch error.code {
case .unknown: print("Unknown error. Please contact support")
case .clientInvalid: print("Not allowed to make the payment")
case .paymentCancelled: break
case .paymentInvalid: print("The purchase identifier was invalid")
case .paymentNotAllowed: print("The device is not allowed to make the payment")
case .storeProductNotAvailable: print("The product is not available in the current storefront")
case .cloudServicePermissionDenied: print("Access to cloud service information is not allowed")
case .cloudServiceNetworkConnectionFailed: print("Could not connect to the network")
case .cloudServiceRevoked: print("User has revoked permission to use this cloud service")
}
}
}
}
}
}
func verifyPurchase(with id: String , sharedSecret: String) {
let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: sharedSecret)
SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
switch result {
case .success(let receipt):
let productId = "myID"
// Verify the purchase of Consumable or NonConsumable
let purchaseResult = SwiftyStoreKit.verifyPurchase(
productId: id,
inReceipt: receipt)
switch purchaseResult {
case .purchased(let receiptItem):
print("\(productId) is purchased: \(receiptItem)")
if self.product_ID == self.productId {
// Save your purchase locally (needed only for Non-Consumable IAP)
self.nonConsumablePurchaseMade = true
UserDefaults.standard.set(self.nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade")
}
case .notPurchased:
print("The user has never purchased \(productId)")
}
case .error(let error):
print("Receipt verification failed: \(error)")
}
}
}
#objc func returnTextView(gesture: UIGestureRecognizer) {
guard activeField != nil else {
return
}
activeField?.resignFirstResponder()
activeField = nil
}
I want to be able to use Airpods in my app, and I have some solution that works (almost).
func playSound(soundSpeech: String) {
let audioSession = AVAudioSession.sharedInstance()
selectDevice(audioSession: audioSession)
...
}
func selectDevice(audioSession: AVAudioSession) {
print("select device")
var headphonesExist = false
var bluetoothExist = false
var speakerExist = false
let currentRoute = AVAudioSession.sharedInstance().currentRoute
for output in audioSession.currentRoute.outputs {
print(output)
if output.portType == AVAudioSessionPortHeadphones || output.portType == AVAudioSessionPortHeadsetMic {
headphonesExist = true
}
if output.portType == AVAudioSessionPortBluetoothA2DP || output.portType == AVAudioSessionPortBluetoothHFP {
bluetoothExist = true
print("bluetooth is enabled")
}
if output.portType == AVAudioSessionPortBuiltInSpeaker {
speakerExist = true
}
}
print("headphones: \(headphonesExist) bluetooth: \(bluetoothExist) speakerExist: \(speakerExist)")
if bluetoothExist == true {
do { try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: AVAudioSessionCategoryOptions.allowBluetoothA2DP) } catch {
print("error with audiosession: bluetooth")
}
} else {
do { try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: AVAudioSessionCategoryOptions.defaultToSpeaker) } catch {
print("error with audiosession: default speaker")
}
}
}
The problem is it does work only if (or after) I switch to other app with sound (i.e. YouTube app) and back. After that it works like a charm, but I believe it should work from the start.
All, I created the following function:
func determineStatus() -> Bool {
let status = ABAddressBookGetAuthorizationStatus()
var ok = false
switch status {
case .NotDetermined:
println("Asking for Grant")
ABAddressBookRequestAccessWithCompletion(nil) {
(granted:Bool, err:CFError!) in
ok = granted
println("Granted Status: \(granted)")
}
case .Authorized:
println("Authorized")
ok = true
case .Restricted:
println("Restricted")
ok = false
case .Denied:
println("Denied")
ok = false
}
if ok == true {
println("Creating AB Instance")
return self.createAddressBook()
} else {
self.adbk = nil
println("Not Authorized")
return false
}
}
And I call it from within my Master - Detail View.
The first time I call it the view appears before the alert window asking for authorization, and it's empty.
I get in my console:
Asking for Grant
Not Authorized
And, after I authorize:
Granted Status: true
So the if ok == true part of determineStatus get executed before the ABAddressBookRequestAccessWithCompletion(nil) completes.
The second time I run it I get the data displayed.
How can I change determineStatus in order for the if ok == true statement to be executed after ABAddressBookRequestAccessWithCompletion(nil) finishes?
I found a working solution here.
Credits go to #matt, I just copy/pasted his code and added a call to the class for this example:
class MyAddressBook {
var adbk : ABAddressBook!
func createAddressBook() -> Bool {
if self.adbk != nil {
return true
}
var err : Unmanaged<CFError>? = nil
let adbk : ABAddressBook? = ABAddressBookCreateWithOptions(nil, &err).takeRetainedValue()
if adbk == nil {
println(err)
self.adbk = nil
return false
}
self.adbk = adbk
return true
}
func determineStatus() -> Bool {
let status = ABAddressBookGetAuthorizationStatus()
switch status {
case .Authorized:
return self.createAddressBook()
case .NotDetermined:
var ok = false
ABAddressBookRequestAccessWithCompletion(nil) {
(granted:Bool, err:CFError!) in
dispatch_async(dispatch_get_main_queue()) {
if granted {
ok = self.createAddressBook()
}
}
}
if ok == true {
return true
}
self.adbk = nil
return false
case .Restricted:
self.adbk = nil
return false
case .Denied:
self.adbk = nil
return false
}
}
func getContactNames() {
if !self.determineStatus() {
println("not authorized")
return
}
let people = ABAddressBookCopyArrayOfAllPeople(adbk).takeRetainedValue() as NSArray as [ABRecord]
for person in people {
println(ABRecordCopyCompositeName(person).takeRetainedValue())
}
}
}
And elsewhere, likely in a controller (I've tested in viewDidLoad of a simple test app, it works well), do this:
let myABInstance = MyAddressBook()
let result = myABInstance.determineStatus()
println("Succeeded: \(result)")
myABInstance.getContactNames()
What I've got:
true
Kate Bell
Daniel Higgins Jr.
John Appleseed
Anna Haro
Hank M. Zakroff
David Taylor