My iOS app has been rejected by Apple as the app crashes if a user selected "Dont allow" location access. And the proceeds to tap on my Map button.
How can I wrap this button in check to see if the user has given permission, And if not how can I ask for permission again?
//Map Button Action - Opens Maps - Gives choice of Google or Apple maps
#IBAction func googleMapBtn(_ sender: UIButton) {
UIDevice.current.isBatteryMonitoringEnabled = true
let state = UIDevice.current.batteryState
//If user is in Loop - Cant open maps
if state == .charging {
print("In Loop - Cant open maps")
}
//Present Map Options
else {
let alertController = UIAlertController.init(title: "Open Map", message: "", preferredStyle: .alert)
alertController.addAction(UIAlertAction.init(title: "Google Maps", style: .default, handler: { (action) in
self.googleMapsOpen()
}))
alertController.addAction(UIAlertAction.init(title: "Apple Maps", style: .default, handler: { (action) in
self.appleMapsOpen()
}))
alertController.addAction(UIAlertAction.init(title: "Back", style: .default, handler: { (action) in
self.dismiss(animated: true, completion: nil)
}))
self.present(alertController, animated: true) {
}
}
}
The code crashes whenever a user selects a map type Google/Apple and the self.googleMapsOpen() or self.appleMapsOpen() are executed. Specifically is crashed on the let scheme=
func googleMapsOpen(){
print("Google Maps Pressed")
let scheme = "comgooglemaps://?center=\(LocationManager.sharedInstance.location.coordinate.latitude),\(LocationManager.sharedInstance.location.coordinate.longitude)&zoom=15"
self.open(scheme: scheme)
}
func appleMapsOpen(){
print("Apple Maps Pressed")
let scheme = "http://maps.apple.com/?ll=\(LocationManager.sharedInstance.location.coordinate.latitude),\(LocationManager.sharedInstance.location.coordinate.longitude)&zoom=15"
self.open(scheme: scheme)
}
You can do something like this :
func checkLocationPermissionEnabled()
{
if CLLocationManager.locationServicesEnabled()
{
switch(CLLocationManager.authorizationStatus())
{
case .notDetermined, .restricted, .denied:
self.openDeviceLocationSetting()
return
case .authorizedAlways, .authorizedWhenInUse:
//do whatever you want to do with location
return
}
}
else
{
self.openDeviceLocationSetting()
return
}
}
func openDeviceLocationSetting()
{
let alertController = UIAlertController(title: "", message:"For best results, let your device turn on location using Google's location service.", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
self.isAlertShowing = false
let settingsUrl = NSURL(string: UIApplicationOpenSettingsURLString)
if let url = settingsUrl {
UIApplication.shared.openURL(url as URL)
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.default) {
UIAlertAction in
}
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}
Related
I have a problem trying to put an alert message after completing the action. The application crashes.
#IBAction func deleteAccountAction(_ sender: Any) {
let userID = prefs.value(forKey: "userId") as! String
print("user id: \(userID)")
let alert = UIAlertController(title: "Delete account", message: "Are you sure you want to delete your account?, This action cannot be reversed.", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) in
// ...
}
let okayAction = UIAlertAction(title: "OK", style: .default) { (action) in
RestAPIManager.sharedInstance.deleteAccount(userID: userID){
(json, error) in
if(json != JSON.null){
print(json)
if(json["success"] == true){
//here i want succes alert
}else{
self.errorAlert()
}
}else{
}
}
}
alert.addAction(okayAction)
alert.addAction(cancelAction)
self.present(alert, animated: true)
}
func errorAlert(){
var dialogMessage = UIAlertController(title: "Error", message: "Error", preferredStyle: .alert)
self.present(dialogMessage, animated: true, completion: nil)
}
I tried to put an alert message after the action but I can't.
is solved needs to be async.
DispatchQueue.main.async {
self.errorAlert()
}
I would like to add a method to my ViewController that shows a message with text as an alert with a Yes and a No button. The result should be of type Bool (Yes/No).
What I have tried is the following:
func YesNoBox(msg: String) -> Bool
{
var retVal = false
let alert = UIAlertController(title: "", message: msg, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler:
{ _ in NSLog("The \"Yes\" alert occured."); retVal = true })
let action_no = UIAlertAction(title: "No", style: .cancel, handler:
{ _ in NSLog("The \"No\" alert occured."); retVal = false })
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
return retVal
}
However, the value of retVal is always false. If I was in C/C++, I guess I could resolve this issue with a pointer, but this is Swift (and I am pretty new to this).
Any idea anyone how I could get this working?
EDIT: The problem that I have is the following. On a ViewController I have a TextField. When I tap on the text field, the app should ask the user whether they want to paste the text from the clipboard. If yes, paste, otherwise give the TextField the focus (i.e. let the cursor blink in it). I tried to do this with 'textFieldShouldBeginEditing' and in this method I display the YesNoBox. The problem is that the TextField never gets the focus after the YesNoBox is closed. And when I use 'becomeFirstResponder()' after the Box call, the app freezes. I don't know what to do?
Use a completion
func yesNoBox(msg: String,completion:#escaping(Bool) -> ())
{
let alert = UIAlertController(title: "", message: msg, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler:
{ _ in
NSLog("The \"Yes\" alert occured.");
completion(true)
})
let action_no = UIAlertAction(title: "No", style: .cancel, handler:
{ _ in
NSLog("The \"No\" alert occured.");
completion(false)
})
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
}
call
yesNoBox(msg:"someMessage") { yes in
if yes {
// do yes action
}
else {
// do no action
}
}
2 Callbacks:
This function has 2 completions ( imagine we have a function that uploads an image and notifies the progress with a completion and another 1 to say done )
func uploadImage(data: Data,progress:#escaping(Float) -> (),completion:#escaping(Bool) -> ()) {
// implementation here
}
To call
self.uploadImage(someData) { progress in
print(progress)
}) { done in
print(done)
}
This can be achieved with completion handlers.
func showAlertWithOptions(title: String, message: String, completionHandler: #escaping (Bool) -> Void) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler: { _ in
completionHandler(true)
})
let action_no = UIAlertAction(title: "No", style: .cancel, handler: { _ in
completionHandler(false)
})
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
}
Now call the function and add any other functions or actions that you want to perform depending on the action selected.
showAlertWithOptions(title: "Any title", message: "Any message") { success in
if success {
NSLog("The \"Yes\" alert occured.")
} else {
NSLog("The \"No\" alert occured.")
}
}
I am requesting users to accept access to both photo library and camera use. I would like to be able to handle the case for when a user does not accept, but I am having issues doing so. Here is the code for when I check user permission:
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { granted in
if granted {
if(!self.captureSession.isRunning){
self.setupCustomCamera()
}
} else {
self.takePhotoButton.alpha = 0.5
self.takePhotoButton.isEnabled = false
self.showNeedAccessMessage()
}
}
And my showNeedAccessMessage() as follows:
func showNeedAccessMessage() {
let alert = UIAlertController(title: "Camera Settings", message: "Please adjust your device settings to grant access to camera use.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { (action: UIAlertAction) -> Void in
self.dismiss(animated: true, completion: nil)
}))
show(alert, sender: nil)
}
The issue here is that when the granted case is not met, I would like to show an alert. Instead of my alert showing, my application attempts to open the 'Image Settings' page, which shows up as follows:
Is there a default handling for this case? If so, any ideas how I would go about fixing the black 'Image Settings' screen?
Thank you in advance!
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (granted :Bool) -> Void in
if granted == true
{
// User granted
}
else
{
let alert = UIAlertController(title: "Error", message: "This app is not authorized to use Camera.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Setting", style: .default, handler: { (_) in
DispatchQueue.main.async {
if let settingsURL = URL(string: UIApplicationOpenSettingsURLString) {
UIApplication.shared.openURL(settingsURL)
}
}
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
});
I have created my code for the authorizations of photos and camera but fore some reason the code runs but never is displayed in the privacy settings. I am clearly missing something but I'm been trying to work it out for almost 12 hours and can't find it out. Is there like a checklist that needs for all options to be ticked before the permission shows up in the privacy settings.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if PHPhotoLibrary.authorizationStatus() != PHAuthorizationStatus.Authorized {
PHPhotoLibrary.requestAuthorization({(status: PHAuthorizationStatus) in
let settings = NSURL(string: UIApplicationOpenSettingsURLString)
// Create the alert controller
let alertController = UIAlertController(title: "Access Photos", message: "ClubVIP requires access to your Photos, please enable access in Privacy Settings.", preferredStyle: .Alert)
// Create the actions
let privacySettingsAction = UIAlertAction(title: "Settings", style: UIAlertActionStyle.Default) {
UIAlertAction in
//Take to Privacy Settings
UIApplication.sharedApplication().openURL(settings!)
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) {
UIAlertAction in
NSLog("")
}
// Add the actions
alertController.addAction(privacySettingsAction)
alertController.addAction(cancelAction)
// Present the controller
self.presentViewController(alertController, animated: true, completion: nil)
})
}
if AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) != AVAuthorizationStatus.Authorized {
let settings = NSURL(string: UIApplicationOpenSettingsURLString)
//let settings = NSURL(string: UIApplicationOpen)
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { granted in
if !granted {
// Create the alert controller
let alertController = UIAlertController(title: "Access Camera", message: "Access to your Camera has been denied, please enable access in Privacy Settings.", preferredStyle: .Alert)
// Create the actions
let privacySettingsAction = UIAlertAction(title: "Settings", style: UIAlertActionStyle.Default) {
UIAlertAction in
//Take to Privacy Settings
UIApplication.sharedApplication().openURL(settings!)
}
// Add the actions
alertController.addAction(privacySettingsAction)
// Present the controller
self.presentViewController(alertController, animated: true, completion: nil)
}
})
}
}
I want to make the label that on click on it to make call to number. I know that iOS has this option, but how can I do it in Swift?
I found just how to do it in ObjC:
-(IBAction)callPhone:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel:2135554321"]];
}
Can anyone help me with it?
UIApplication.sharedApplication().openURL(NSURL(string: "tel://2135554321"))
example
if let CallURL:NSURL = NSURL(string:"tel://\(yourMobileNUmber)") {
let application:UIApplication = UIApplication.sharedApplication()
if (application.canOpenURL( CallURL)) {
application.openURL( CallURL);
}
else
{
// your number not valid
let tapAlert = UIAlertController(title: "Alert!!!", message: "Your mobile number is invalid", preferredStyle: UIAlertControllerStyle.Alert)
tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
self.presentViewController(tapAlert, animated: true, completion: nil)
}
}
Type-2
// add gesture to your Label
var tapGesture = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
yourLabelName.userInteractionEnabled=true
yourLabelName.addGestureRecognizer(tapGesture)
// handle the function of UILabel
func handleTap(sender:UITapGestureRecognizer){
if let CallURL:NSURL = NSURL(string:"tel://\(yourMobileNUmber)") {
let application:UIApplication = UIApplication.sharedApplication()
if (application.canOpenURL( CallURL)) {
application.openURL( CallURL);
}
else
{
// your number not valid
let tapAlert = UIAlertController(title: "Alert!!!", message: "Your mobile number is invalid", preferredStyle: UIAlertControllerStyle.Alert)
tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
self.presentViewController(tapAlert, animated: true, completion: nil)
}
}
}