Adding an activity indicator to a UIAlertController - ios

I implemented the accepted answer from here How to display activity indicator in center of UIAlertController?
But it doesn't work, all that is displayed is the title "Creating New User" and no activity indicator is displayed. While running in the debugger I noticed that with the posted code indicator by default has its visibility set to false, so I explicitly added a line to set it to true, but it made no difference.
Here then is the code from the accepted answer, with that additional line added. Why is the activity indicator not displayed?
func displaySignUpPendingAlert() -> UIAlertController
{
//create an alert controller
let pending = UIAlertController(title: "Creating New User", message: nil, preferredStyle: .alert)
let indicator = UIActivityIndicatorView(frame: pending.view.bounds)
indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight]
//add the activity indicator as a subview of the alert controller's view
pending.view.addSubview(indicator)
indicator.isUserInteractionEnabled = false // required otherwise if there buttons in the UIAlertController you will not be able to press them
indicator.isHidden = false
indicator.startAnimating()
self.present(pending, animated: true, completion: nil)
return pending
}

Related

How to show an alert view on the top of the launch screen in iOS?

I am using LaunchScreen.storyboard for showing the splash screen which is just a static image. Now the problem is i want to show an alert on the top of this splash screen if a particular condition is not met . For this i did the following code . But unfortunately the alert is shown only after the splash screen. How can i show the alert on the top of splash screen? As of now this is the following code which I am implementing but the splash screen does not shows the alert instead it shows only after the splash screen.
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
​
if conditionMet
{
print("Condition met!")
}
else
{
let storyboard : UIStoryboard = UIStoryboard(name: "Launch Screen", bundle: nil)
let launchScreenCtrler = storyboard.instantiateViewController(identifier: "LAUNCH_SCREEN")
let alertViewFrame = CGRect(x: 100, y: 300, width: 120, height: 80)
let newView : UIView = UIView(frame: alertViewFrame)
launchScreenCtrler.view.addSubview(newView)
launchScreenCtrler.view.bringSubviewToFront(newView)
alert.show(launchScreenCtrler, sender: newView)
}
}
You can't control what is visible over Launch Screen or for how much time it is displayed.
Here's what you should do -
Create a new screen called SplashViewController that has identical layout as LaunchScreen.storyboard.
Make sure this SplashViewController is the first screen to be visible to user in the app.
Inside this screen you now have full control over what you want to do - show an alert, any other animation etc.
In case you find out that you need to show the alert, you enter the new flow with alert.
In case you find out that you don't need to show the alert, you enter the old flow without the alert.
Launch screen does not support any code insertion, it is just "image"screen rendered from Interface builder which is loaded before the app loads itself. I recommend using some other UIViewController that will look identical to your LaunchScreen and displays right after launchScreen, on this 'standard' UIViewControler you can perform any code you want as usual.
First of all Alert can be presented on View Controller and
I think you should use UIAlertController which is an object which displays an alert message to user
Following is the code you can try it will show the alert on top of ViewController
let alert = UIAlertController(title: "Your title", message: "Your message", preferredStyle: .alert)
let ok = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(ok)
DispatchQueue.main.async {
self.present(alert, animated: true)
}
Here self is referred to the my mainClass:ViewController on which i have to show alert and Dispatch Queue is used to show my UI if i am doing heavy operations in background or in another thread as UI can only be updated on main thread.

Change UIAlertController Background Tint

Yes, I know. You can't change the appearance of a UIAlertController. I don't want to change the background of the UIAlertController itself, I want to change the tint of the view's background. You know how it's like a transparent black color? I want to change that color to clear. How would I do this?
For swift 3 UIAlertController change background color.
let alert = UIAlertController(title: "validate",message: "Check the process", preferredStyle: .alert)
let dismissAction = UIAlertAction(title: "Dismiss", style: .destructive, handler: nil)
alert.addAction(dismissAction)
self.present(alert, animated: true, completion: nil)
// change the background color
let subview = (alert.view.subviews.first?.subviews.first?.subviews.first!)! as UIView
subview.layer.cornerRadius = 1
subview.backgroundColor = UIColor(red: (195/255.0), green: (68/255.0), blue: (122/255.0), alpha: 1.0)
No you cannot change the transparent background color. That does not belong to part of UIAlertController variable that you can control.
You will have to fix it by presenting a new view controller with a transparent background and a faked alert-controller-like UI element.
To further approve you does not have control for the alert controller, create another view with frame origin on 0,0 and then add to your alert controller's view. It will show on the top left corner of your pop up window, not the window of your window
You can change the background colour as follows:
let alert = UIAlertController(title: "TITLE", message: "My message", preferredStyle: .alert)
if let subview = alert.view.subviews.first?.subviews.first?.subviews.first {
subview.backgroundColor = .red
}
alert.view.tintColor = UIColor.black
Try this..
[alert.view setBackgroundColor:[UIColor whiteColor]];
Try changing whiteColor to whatever colour u wish.
To fix the corner extra color, add corner radius and run.
Hope this helps!
You can create CustomAlertController, set your color in method viewWillAppear and show this controller instead of default UIAlertController. It's bad but working solution.
final class CustomAlertController: UIAlertController {
//MARK: - Lifecycle
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
view.superview?.backgroundColor = yourColor
}
}

Reposition UIAlertView

I am want to simple a UIAlertView on the bottom of the screen when opening a ViewController.
Right now, I create an alert view, show it after 2 seconds and hide the alert.
However, the alert view only shows in the center of the screen.
How do I reposition it on the bottom of the screen?
Here is my code:
let alert = UIAlertController(title: "", message: "Please Swipe To Refresh After 2 seconds", preferredStyle: .alert)
alert.view.frame.origin.x = 150
alert.view.frame.origin.y = 250
self.present(alert, animated: true, completion: nil)
let indicator = UIActivityIndicatorView(frame: alert.view.bounds)
indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight]
alert.view.addSubview(indicator)
indicator.isUserInteractionEnabled = false
indicator.startAnimating()
let when = DispatchTime.now() + 2
DispatchQueue.main.asyncAfter(deadline: when) {
alert.dismiss(animated: true, completion: nil)
}
You can't move and UIAlertControllerwith its presentation style set and even if there will be a workaround don't use it. In order to achieve what you want you have different options:
Use a simple UIView subclass that simply requires in the show method the view you want to use as a super view
Create a UIViewController subclass and present it using a UIPresentationController, this could be pretty hard if you are new to iOS development
Use one of the already available libraries on github, for instance this
Use (.... , preferredStyle: .actionSheet) in the constructor of UIAlertController

Unable to present UIAlertController within a UITableViewController in Swift

I have got a UIAlertController that I would like to present within a UITableViewController. However when I run the code I get the following error:
Warning: Attempt to present on
whose view is not in the
window hierarchy!
My code seem to reflect what suggested in this answer. What am I doing wrong?
override func viewDidLoad() {
super.viewDidLoad()
// Check for force touch feature, and add force touch/previewing capability.
if traitCollection.forceTouchCapability == .available {
registerForPreviewing(with: self, sourceView: view)
}
else {
// Create an alert to display to the user.
alertController = UIAlertController(title: "3D Touch Not Available", message: "Unsupported device.", preferredStyle: .alert)
self.present(alertController!, animated: false, completion: nil)
}
Suppose, in viewDidLoad you still don't have a view in the window hierarchy, like said in message. Try to move your code to viewDidAppear instead

UIBarButtonItem gives me wrong frame for popoverPresentationController

I have a toolbar with a UIBarButtomItem at the left corner with the label Admin
I need to show a popover when it taps it, but it appears in a wrong place, it appears at the top left of the screen:
This is the function to open the popover:
// this IBAction is assigned only to the Admin bar button item
#IBAction func openAdmin(sender: UIBarButtonItem) {
let alertController = UIAlertController(title: nil, message: "Elige una opción", preferredStyle: .ActionSheet)
// action button initializations... ... ...
let barButtonItemSize = sender.valueForKey("view")
alertController.popoverPresentationController?.sourceView = self.view
alertController.popoverPresentationController?.sourceRect = barButtonItemSize!.frame
presentViewController(alertController, animated: true, completion: nil)
}
Also I get this warning on the console when I touch the Admin bar button:
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates
What am I doing wrong? or What do I need to do to present the popover at the top of the Admin?
Replace
alertController.popoverPresentationController?.sourceView = self.view
alertController.popoverPresentationController?.sourceRect = barButtonItemSize!.frame
with
alertController.popoverPresentationController?.sourceView = sender
alertController.popoverPresentationController?.barButtonItem = sender

Resources