Swift: Prevent ABPeoplePickerNavigationController from Closing - ios

I'd like to figure out a way so that, if the user presses the "Cancel" button (which I don't believe can be removed) in an ABPeoplePickerNavigationController, the view controller either doesn't close, or will be automatically reopened.
For example, given the following:
var picker = ABPeoplePickerNavigationController()
picker.peoplePickerDelegate = self
self.presentViewController(picker, animated: true, completion: nil)
I'd like to be able to do something like:
if (self.presentedViewController != picker && !userContinuedPastPicker) {
//where userContinuedPastPicker is a boolean set to false
//in a delegate method called when the user clicks on an a contact
//(meaning the user didn't press the cancel button but instead clicked on a contact)
//create and present a UIAlertAction informing the user they must select a contact
//present picker again
self.presentViewController(picker, animated: true, completion: nil)
}
This doesn't work; however, because the if statement won't "wait" until the user has pressed the cancel button or pressed a contact.

I'm not sure there is a way to remove the cancel button, or prevent it from working, but you could respond to the func peoplePickerNavigationControllerDidCancel(_ peoplePicker: ABPeoplePickerNavigationController!) delegate to handle the case where the cancel button is pressed.
I would recommend rather than immediately reopening the picker, you open an alert telling the user they need to pick someone, then open it back up from there. It may feel broken if they cancel and it immediately opens back up.
Reference
edit:
Presenting an alert or the picker probably needs to be delayed long enough for the previous picker to close. dispatch_after

Related

Black screen after presenting model view controller in current context from tab controller

I'm creating a Popup error message for my own app. I have followed a tutorial in Youtube. As my app is a tab bar app when Popup, comes up and a user presses another tab and then get back to that specific tab the background is changed !!!! any Idea what is happening here?
1. This is when the popUp comes up
2.This one is when has change the tab and then came back to that specific tab
3.This is the last state when the user close the popup after they changed the tab
none of these bugs happens if the user closes the pop up at the beginning!
let next = self.storyboard?.instantiateViewController(withIdentifier: "ErrorVC")
self.present(next!, animated: true, completion: nil)
and this is the code I have used in my page to show the pop when it meets the conditions !!!
I have 2 viewController and second one is the pop up.
Set definesPresentationContext property to true of UIViewController in first viewController where you're displaying pop-view
override func viewDidLoad() {
super.viewDidLoad()
definesPresentationContext = true
}

dialog window in iOS does not show when called from another class after application has been loaded

I have created a function in Class A that creates a dialog window that should appear whenever my application has been loaded. So in my AppDelegate.swift file I would call instance of Class A. This instance calls the function that should show dialog window. The problem is that when my application loads and even when my application finishes loading I am not seeing my dialog window. I believe that the problem is that whenever I call in my funcion:
present(refreshAlert, animated: true, completion: nil)
that at that point my view controller is still visible. I think that I need to figure out that the refreshAlert is presented on the top of window hierarchy. Can anybody help me to figure out this issue.
Thanks,
In case you want to present the controller from App Delegate try this:
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
If you are not sure why the alert is not displayed in your class that is loaded from App Delegate, try to put a debugger there on the alert and see if the control passes to the alert at the same time as the class loads.
If that's the case, then you should try to put a delay and then present the alert something like:
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.5, execute: {
present(alert, animated: true, completion: nil)
})
or maybe try to put the alert in the func viewDidAppear(_ animated: Bool) or trigger it after the control reaches viewDidAppear .
Most probably you are not calling it from the main thread.
Use DispatchQueue.main.async to send it to the main thread

Segue performing on separate button click

I'm following a course online, the app I'm building is basically a cut down version of Instagram as you can see on the left hand side I have a view for signing in, on the right hand side I have a view for signing up.
Pretty straight forward right, now I have created a Seque from the signin page from the button Register which when pressed takes you to the registration view (one on the right), this works as expected however if I'm on the signin page and click sign in and it errors for whatever reason I display the error message but straight after is performs the Seque to the registration screen even though I never pressed register
This is my storyboard:
This is my code behind the Sign In button located on the left view
#IBAction func btnSignIn(sender: AnyObject) {
if txtUsername.text == "" || txtPassword.text == "" {
displayAlert("Error", message: "Username and Password required!")
}
}
I have no other code inside this controller which would cause the Seque to initialise.
If someone can shed some light into how I can stop this Seque from happening on Sign In click and only happen when I press Register I'd appreciate it.
Update
After further investigation this seems to be an issue with my alert box I'm displaying. If I comment out the alert box and press signin and let it error yet not display anything then click register which takes me to the view on the right, click sign in and get taken back to view on the left and then press Sign In display the alert box and when it closes it seems like it thinks the view controller that's being displayed in the one previous to the current one on the page, which is odd. This is my alert function:
func displayAlert(title: String, message: String) { // Display alert message to user. Passing in title and message which will be displayed.
if #available(iOS 8.0, *) {
let a = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
a.addAction((UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
})))
self.presentViewController(a, animated: true, completion: nil)
} else {
// Fallback on earlier versions
}
}
You don't need to dismiss the alert view controller in the action. When the user selects an action, the alert controller is automatically dismissed.
Since you are calling dismissViewControllerAnimated you are going back to the previous view controller.
Right click on Sign-in button and check Connections Inspector, may be you have copy-pasted these two buttons so the action of both sign-in and register button would be same.

Swift: Buggy Navigation Bar Behavior With popViewControllerAnimated

I want to use a push segue to edit an "entry" that is otherwise added via a present modally segue. It doesn't dismiss using the normal dismissViewControllerAnimated method when pressing cancel. Because of this I had to combine the popViewControllerAnimated method at the same time, so that depending on whether they click cancel when editing an entry or adding it, it will try both.
Both are done via NSNotifcation, because of objects I need to carry back from the last viewcontroller to the first:
func cancel(notification: NSNotification){
println("Cancel Executed")
let userInfo:Dictionary<String,EntryItem!> = notification.userInfo as Dictionary<String,EntryItem!>
entry = userInfo["Object"]
tableView.reloadData()
self.navigationController?.popViewControllerAnimated(true)
dismissViewControllerAnimated(true, completion: nil)
dataModel.saveEntries()
}
The problem with this is that if I go through the segues to arrive at the third view controller (in a string of 5), I cancel, and it goes back to the entries screen, but a messed up looking navigation bar takes the place of what is supposed to be there. There's no title showing either. It has a cancel button which causes a crash if you press it.
Here's what it's supposed to look like:
Here's what the popViewControllerAnimated does to it.

UIAutomation : Cancel button on Alert view is tapped without actually doing it

I'm facing this weird problem in UIAutomation.
I am checking an alert. In that, I am trying to log alert title and alert message. My code for this is:
UIATarget.onAlert = function onAlert(alert) {
UIALogger.logMessage("alert Shown");
UIALogger.logMessage(frontApp.alert().name());
UIALogger.logMessage(frontApp.alert().staticTexts()[1].value());
}
var target = UIATarget.localTarget().frontMostApp().mainWindow();
target.scrollViews()[0].buttons()["saveB"].tap();
UIATarget.localTarget().delay(2);
I am not tapping on cancel button in the alert to dismiss it. But, it is getting tapped automatically. I don't know why. Even in the logMessages, I see
target.frontMostApp().alert().cancelButton().tap()
this line getting executed automatically. I don't have this line anywhere in my script file. Is it a bug in iOS?
The cancel button on an alert is always tapped to keep the application from blocking unless the onAlert callback returns true. By returning true, you are telling the alert handling mechanism that you will handle tapping the appropriate button to dismiss the alert.
Change your alert callback to look like this:
UIATarget.onAlert = function onAlert(alert) {
UIALogger.logMessage("alert Shown");
UIALogger.logMessage(frontApp.alert().name());
UIALogger.logMessage(frontApp.alert().staticTexts()[1].value());
return true; // <-- Adding this line
}
Conversely, returning false or leaving out a return value altogether signals to the alert handling mechanism that the cancel button should be tapped.

Resources