I am getting an odd compiler message when presenting a totally innocuous alert controller from a tableViewController:
let ac = UIAlertController(title: "Add item", message: nil, preferredStyle: .alert)
ac.addTextField()
let cancelAction = UIAlertAction(title: "Cancel", style: .default) { _ in return }
ac.addAction(cancelAction)
present(ac, animated: true)
The message reads: "Changing the translatesAutoresizingMaskIntoConstraints property of a UICollectionViewCell that is managed by a UICollectionView is not supported, and will result in incorrect self-sizing". I am puzzled, because I am not changing that property anywhere in my code. Also, I find it curious that tracing execution with the debugger shows that the message appears when the alert controller is presented, not when doing anything actually related to the table. This was not happening in Xcode 13. Where could that message be coming from? Can it be safely ignored? Thanks.
This is an internal layout error / warning message.
If you inspect the full message (it will look like this, with different object hex values for you):
[LayoutConstraints] Changing the translatesAutoresizingMaskIntoConstraints property of a
UICollectionViewCell that is managed by a UICollectionView is not supported,
and will result in incorrect self-sizing.
View: <_UIAlertControllerTextFieldViewCollectionCell: 0x7f7a6ff1ba70;
frame = (0 0; 270 24); gestureRecognizers = <NSArray: 0x6000024fb0c0>;
layer = <CALayer: 0x600002adb1c0>>
If you use Debug View Hierarchy and find that View you'll see that it is a collection view cell inside the alert controller:
You can safely ignore this message.
Related
I am getting a very strange error. I think the compiler is trying to tell me that it can't segue to another view controller until it is done executing all the code in my current view controller but I am not sure.
I'm literally getting input by using an alert box (i.e. calling a function called generateTextField).
Then when I am done I'm saying "Hey I want you to go to another view controller" - but the the compiler instead tells me "Hey I don't think so".
Here is my error:
Warning: Attempt to present HairStyle1ViewController: 0x7...> on browseBarbersViewController: 0x7...> which is already presenting
Warning: Attempt to present HairStyle1ViewController: 0x7..> on browseBarbersViewController: 0x7...> which is already presenting
#IBAction func AddNewStyleButtonClicked(sender: AnyObject)
{
// Get the "hairstyle name" from the user
generateTextField();
// OK We are done with that function, now transition to the
// next screen
performSegueWithIdentifier("HairStyle1", sender: self);
}
// Generate a text field for user input (i.e. call the alert function)
func generateTextField()
{
//1. Create the alert controller.
var tempStyle = "";
var alert = UIAlertController(title: "Add a New Style", message: "Enter the name of the new hairstyle below", preferredStyle: .Alert);
//2. Add the text field. You can configure it however you need.
alert.addTextFieldWithConfigurationHandler({ (textField) -> Void in
textField.placeholder = "Your New Hairstyle Goes Here..";
})
//3. Grab the value from the text field, and print it when the user clicks OK.
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
let textField = alert.textFields![0] as UITextField
tempStyle = textField.text!;
print("New Style Added is: " + tempStyle);
HairStyle = tempStyle;
}))
// 4. Present the alert.
self.presentViewController(alert, animated: true, completion: nil)
}
It's also weird that when I take out the generateTextField() function it performs the segue perfectly. I'm very confused.
Wow, I figured it out. I had to instead, segue in the body of the alert function.
I fixed this by adding
self.performSegueWithIdentifier("HairStyle1", sender: self);
after the
HairStyle = tempStyle; line
So the first thing my app does is get a list of movies from an API. I'm trying to handle if there's a network issue. Currently, in my viewDidLoad method, I call "updateApiInfo", which contains the following code:
if self.movies == nil {
print("stuff went wrong")
let alert = UIAlertController(title: "Network Error", message: "There was a nework error.\nYou must be connected to the internet to use Flicks.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Exit", style: UIAlertActionStyle.Default, handler: {(UIAlertAction) in
UIControl().sendAction(Selector("suspend"), to: UIApplication.sharedApplication(), forEvent: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
When viewDidLoad calls updateApiInfo, I get this message:
Warning: Attempt to present <UIAlertController: 0x7fad10e3ad80> on <Flicks.MoviesViewController: 0x7fad10e35cc0> whose view is not in the window hierarchy!
When I call updateApiInfo just from the user refreshing, the error pops up as expected.
I'm assuming that viewDidLoad only gets called before the view gets displayed to the user, which I guess is causing this error. Is there a method I can stick this code in for after the view is displayed to the user, so the problem can presumably get fixed?
You need to use viewDidAppear: to make sure the view is already in the window hierarchy.
There's a pretty good explanation of the order in which the methods are called here:
What is the process of a UIViewController birth (which method follows which)?
I have an alertController with a button in it. Here's how I created the button:
var myButton : UIAlertAction!
// Later...
self.myButton = UIAlertAction(title: "myButton", style: .Default, handler: {action -> Void in
self.myButton.title = "✔︎\(myButton)"
})
After the button get's selected, I want to add a "✔︎" at the beginning of the title. (As you can see in the last line of code above.) When I try doing that, I get the following error:
Cannot assign to the result of this expression
What can I do to fix that? If myButtons title is read-only, then is there a valid workaround to it?
The error is not about the "✔︎". It's because of myButton. It means nothing to assign a UIAlertAction to String. That's how you get the error.
I was under the impression that if the normal action is a destructive action and the other is a cancel action in their UIAlertController that the destructive one should be on the left and the cancel should be on the right.
If the normal action is not destructive, then the normal action should be on the right and the cancel should be on the left.
That said, I have the following:
var confirmLeaveAlert = UIAlertController(title: "Leave", message: "Are you sure you want to leave?", preferredStyle: .Alert)
let leaveAction = UIAlertAction(title: "Leave", style: .Destructive, handler: {
(alert: UIAlertAction!) in
//Handle leave
}
)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
confirmLeaveAlert.addAction(leaveAction)
confirmLeaveAlert.addAction(cancelAction)
self.presentViewController(confirmLeaveAlert, animated: true, completion: nil)
I was under the impression that if I add the leaveAction first, then the cancelAction that the leaveAction would be the button on the left. This was not the case. I tried adding the buttons in the opposite order as well and it also resulted in the buttons being added in the same order.
Am I wrong? Is there no way to achieve this?
My solution to this was to use the .Default style instead of .Cancel for the cancelAction.
Since iOS9 there is a preferredAction property on UIAlertController. It places action on right side. From docs:
When you specify a preferred action, the alert controller highlights the text of that action to give it emphasis. (If the alert also contains a cancel button, the preferred action receives the highlighting instead of the cancel button.)
The action object you assign to this property must have already been added to the alert controller’s list of actions. Assigning an object to this property before adding it with the addAction: method is a programmer error.
i'm making a draw application, and i want a slider to appear when the user taps on a button, for example to set the width of a line .
Can I just add an alert and put a slider in it ?
Using Swift 3.0, you can add a slider (or other object) to a UIAlertController subview. The following example is triggered by an #IBAction button to use and update the UserDefaults: Example of a UISider inside a UIAlertController
#IBAction func sliderButton(_ sender: AnyObject) {
//get the Slider values from UserDefaults
let defaultSliderValue = UserDefaults.standard.float(forKey: "sliderValue")
//create the Alert message with extra return spaces
let sliderAlert = UIAlertController(title: "Update Defaults", message: "Increase/Decrease the slider…\n\n\n\n\n\n", preferredStyle: .alert)
//create a Slider and fit within the extra message spaces
//add the Slider to a Subview of the sliderAlert
let slider = UISlider(frame:CGRect(x: 10, y: 100, width: 250, height: 80))
slider.minimumValue = 1
slider.maximumValue = 100
slider.value = defaultSliderValue
slider.isContinuous = true
slider.tintColor = UIColor.red
sliderAlert.view.addSubview(slider)
//OK button action
let sliderAction = UIAlertAction(title: "OK", style: .default, handler: { (result : UIAlertAction) -> Void in
UserDefaults.standard.set(slider.value, forKey: "sliderValue")
})
//Cancel button action
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
//Add buttons to sliderAlert
sliderAlert.addAction(sliderAction)
sliderAlert.addAction(cancelAction)
//present the sliderAlert message
self.present(sliderAlert, animated: true, completion: nil)
}
The subview can be positioned just about anywhere. To make room for the slider, I added a few extra line breaks in the message to open up some space. The slider will appear and disappear with the Alert message.
Welcome to Stack Overflow.
Your question is more of a basic programming question than a Swift question.
I don't think you can put a slider in an alert. Apple introduced the UIAlertController class recently, and their docs say you should us that rather than UIAlertView for new development.
A UIAlertController lets you create alerts and action sheets, and add actions. The actions are shown as buttons. There is also a facility for adding text fields. I don't think there is any facility for adding other view objects like sliders however.
The now-deprecated UIAlertView is also not set up for adding custom fields like sliders.
You could put the slider on your view somewhere and set it's hidden property to true, then in the buttons action method, set mySlider.hidden = false.
However it sounds like you want your slider to appear on top of your UI, then go away when the user is done with it.
You could create a view with a slider and a dismiss button on it, put it on top of your view controller's content view, and set it's hidden flag to true. When the user taps your button, set hidden = false and the view will appear on top, rather like an alert does. You'd set up constraints so the slider-containing view would be centered on the screen and sized appropriately.
toggle the hidden property.
slider.hidden = true//hide it
slider.hidden = false//show it