问题
Please help! :) Im a huge noobie here. I've gathered this code from various sources so i don't really know what I'm doing. My alert controller displays a textfield that I can write in, a 'cancel' action, an 'ok' action, and it also displays multiple 'input keyword to label' actions.
It has so many actions (around 20 keyword actions that i need) that it either doesn't fit in the screen, it is covered by the keyboard, or it is in the way of the keyboard. It looks ugly and some of the buttons you cannot touch. Is there a way to scroll through my actions to make it fit within this space?
This is my code for that last image:
//Quality Text Box (9)
@IBOutlet weak var QualityLabel: UILabel!
@IBAction func QualityTapped(_ sender: UIButton) {
print("Quality Button Tapped")
openQualityAlert()
}
func openQualityAlert() {
//Create Alert Controller
let alert9 = UIAlertController (title: "Quality:", message: nil, preferredStyle: UIAlertControllerStyle.alert)
//Create "Keyword -> label" actions
let bt1 = UIAlertAction(title: "Abuse", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Abuse"}
alert9.addAction(bt1)
let bt2 = UIAlertAction(title: "Hemmorhage", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Hemmorhage"}
alert9.addAction(bt2)
let bt3 = UIAlertAction(title: "Discomfort", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Discomfort"}
alert9.addAction(bt3)
let bt4 = UIAlertAction(title: "Acute", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Acute"}
alert9.addAction(bt4)
let bt5 = UIAlertAction(title: "Disease", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Disease"}
alert9.addAction(bt5)
let bt6 = UIAlertAction(title: "Rash", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Rash"}
alert9.addAction(bt6)
let bt7 = UIAlertAction(title: "Itch", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Itch"}
alert9.addAction(bt7)
let bt8 = UIAlertAction(title: "Burn", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Burn"}
alert9.addAction(bt8)
let bt9 = UIAlertAction(title: "Abuse", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Abuse"}
alert9.addAction(bt9)
let bt10 = UIAlertAction(title: "Hemmorhage", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Hemmorhage"}
alert9.addAction(bt10)
let bt11 = UIAlertAction(title: "Discomfort", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Discomfort"}
alert9.addAction(bt11)
let bt12 = UIAlertAction(title: "Acute", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Acute"}
alert9.addAction(bt12)
let bt13 = UIAlertAction(title: "Disease", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Disease"}
alert9.addAction(bt13)
let bt14 = UIAlertAction(title: "Rash", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Rash"}
alert9.addAction(bt14)
let bt15 = UIAlertAction(title: "Itch", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Itch"}
alert9.addAction(bt15)
let bt16 = UIAlertAction(title: "Burn", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Burn"}
alert9.addAction(bt16)
let bt17 = UIAlertAction(title: "Abuse", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Abuse"}
alert9.addAction(bt17)
let bt18 = UIAlertAction(title: "Hemmorhage", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Hemmorhage"}
alert9.addAction(bt18)
let bt19 = UIAlertAction(title: "Discomfort", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Discomfort"}
alert9.addAction(bt19)
let bt20 = UIAlertAction(title: "Acute", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Acute"}
alert9.addAction(bt20)
let bt21 = UIAlertAction(title: "Disease", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Disease"}
alert9.addAction(bt21)
let bt22 = UIAlertAction(title: "Rash", style: UIAlertActionStyle.default){
(action) in self.QualityLabel.text = "Rash"}
alert9.addAction(bt22)
//Create Cancel Action
let cancel9 = UIAlertAction(title: "CANCEL", style: UIAlertActionStyle.cancel, handler: nil)
alert9.addAction(cancel9)
//Create OK Action
let ok9 = UIAlertAction(title: "INPUT TEXTFIELD", style: UIAlertActionStyle.default) { (action: UIAlertAction) in print("OK")
let textfield = alert9.textFields?[0]
print(textfield?.text!)
self.QualityLabel.text = textfield?.text!
}
alert9.addAction(ok9)
//Add Text Field
alert9.addTextField { (textfield: UITextField) in
textfield.placeholder = "Quality"
}
//Present Alert Controller
self.present(alert9, animated:true, completion: nil)
}
回答1:
Although I found a way to scroll to the top of UIAlertController actions,
I don't recommend doing this, because I don't know if your app would get rejected.
I think this answer is only relevant for iOS 10+
self.present(alert, animated: true, completion: {
//print(alert.view) // _UIAlertControllerView
//print(alert.view.subviews) // [UIView]
//print(alert.view.subviews[0].subviews) // [_UIAlertControllerInterfaceActionGroupView]
//print(alert.view.subviews[0].subviews[0].subviews) // [_UIDimmingKnockoutBackdropView, UIView]
//print(alert.view.subviews[0].subviews[0].subviews[0].subviews) // [UIView, UIVisualEffectView]
//print(alert.view.subviews[0].subviews[0].subviews[1].subviews) // [_UIInterfaceActionGroupHeaderScrollView, _UIInterfaceActionItemSeparatorView_iOS, _UIInterfaceActionRepresentationsSequenceView]
// _UIInterfaceActionRepresentationsSequenceView <- This is what we want
// In this view are all your added actions. It is a subview of UIScrollView, so just cast it and set the contentOffset to zero
if let scrollView = alert.view.subviews[0].subviews[0].subviews[1].subviews[2] as? UIScrollView {
scrollView.setContentOffset(.zero, animated: true)
}
})
This may not work sometime, because I don't check if the subviews are in this order.
A future iOS update could also completely crash this method.
Also I just tested this on an iPhone. I don't know if it works on an iPad.
A more or less safe way (suggestions welcome):
self.present(alert, animated: true, completion: {
guard alert.view.subviews.count >= 1 else { return }
guard alert.view.subviews[0].subviews.count >= 1 else { return }
guard alert.view.subviews[0].subviews[0].subviews.count >= 2 else { return }
guard alert.view.subviews[0].subviews[0].subviews[1].subviews.count >= 3 else { return }
if let scrollView = alert.view.subviews[0].subviews[0].subviews[1].subviews[2] as? UIScrollView {
scrollView.setContentOffset(.zero, animated: true)
}
})
回答2:
This finds the scrollView and scrolls to the top. We search all subviews because more than one subview responds to setContentOffset, but don't bother checking which one.
- (void)methodThatCreatesTheAlertController
{
// make the alertController here, add actions, and then...
[self presentViewController:alertController animated:YES completion:^{
[self scrollToTopOfAlertControllerView:alertController.view];
}];
}
- (void)scrollToTopOfAlertControllerView:(UIView *)view
{
for ( UIView *aSubview in view.subviews ) {
if ( [aSubview respondsToSelector:@selector(setContentOffset:animated:)] ) {
// _UIInterfaceActionGroupHeaderScrollView
// _UIInterfaceActionRepresentationsSequenceView <-- this is the one that scrolls
[((UIScrollView *)aSubview) setContentOffset:CGPointZero animated:YES];
}
[self scrollToTopOfAlertControllerView:aSubview]; // recurse
}
}
回答3:
set your alertcontroller class with this code
https://gist.github.com/petrpavlik/0c5feaada5913cafde8a
来源:https://stackoverflow.com/questions/42423698/how-to-scroll-through-actions-in-alert-controller-xcode-8-swift-3-ios