Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift UIAlertController-将自定义视图添加到操作表_Swift_Ios9_Uialertcontroller - Fatal编程技术网

Swift UIAlertController-将自定义视图添加到操作表

Swift UIAlertController-将自定义视图添加到操作表,swift,ios9,uialertcontroller,Swift,Ios9,Uialertcontroller,当我们试图像截图一样附加一张图片时,我正在尝试制作iOS上消息应用程序中显示的操作表 我意识到在新的UIAlertController中,我们不能适应任何自定义视图。我有没有办法做到这一点 我的代码看起来很标准 let alertController = UIAlertController(title: "My AlertController", message: "tryna show some images here man", preferredStyle: UIAlertCont

当我们试图像截图一样附加一张图片时,我正在尝试制作iOS上消息应用程序中显示的操作表

我意识到在新的UIAlertController中,我们不能适应任何自定义视图。我有没有办法做到这一点

我的代码看起来很标准

    let alertController = UIAlertController(title: "My AlertController", message: "tryna show some images here man", preferredStyle: UIAlertControllerStyle.ActionSheet)

        let okAction = UIAlertAction(title: "oks", style: .Default) { (action: UIAlertAction) -> Void in
        alertController.dismissViewControllerAnimated(true, completion: nil)
    }
    let cancelAction = UIAlertAction(title: "Screw it!", style: .Cancel) { (action: UIAlertAction) -> Void in
        alertController.dismissViewControllerAnimated(true, completion: nil)
    }

    alertController.addAction(okAction)
    alertController.addAction(cancelAction)

    self.presentViewController(alertController, animated: true, completion: nil)

UIAlertController扩展了UIViewController,它具有视图属性。您可以将子视图添加到该视图中,以满足您的需求。唯一的问题是正确调整警报控制器的大小。你可以这样做,但下一次苹果调整UIAlertController的设计时,这可能很容易被打破

Swift 3

    let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)

    let margin:CGFloat = 10.0
    let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120)
    let customView = UIView(frame: rect)

    customView.backgroundColor = .green
    alertController.view.addSubview(customView)

    let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")})

    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")})

    alertController.addAction(somethingAction)
    alertController.addAction(cancelAction)

    DispatchQueue.main.async {
        self.present(alertController, animated: true, completion:{})
    }
Swift

let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)

let margin:CGFloat = 10.0
let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120)
let customView = UIView(frame: rect)

customView.backgroundColor = .green
alertController.view.addSubview(customView)

let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")})

let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")})

alertController.addAction(somethingAction)
alertController.addAction(cancelAction)

self.present(alertController, animated: true, completion:{})
目标-C

  UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"\n\n\n\n\n\n" message:nil preferredStyle:UIAlertControllerStyleActionSheet];

  CGFloat margin = 8.0F;
  UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(margin, margin, alertController.view.bounds.size.width - margin * 4.0F, 100.0F)];
  customView.backgroundColor = [UIColor greenColor];
  [alertController.view addSubview:customView];

  UIAlertAction *somethingAction = [UIAlertAction actionWithTitle:@"Something" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {}];
  UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {}];
  [alertController addAction:somethingAction];
  [alertController addAction:cancelAction];
  [self presentViewController:alertController animated:YES completion:^{}];
也就是说,一种不太老练的方法是创建自己的视图子类,该子类的工作方式类似于UIAlertController的UIAlertActionStyle布局。事实上,同样的代码在iOS 8和iOS 9中看起来略有不同

iOS 8

iOS 9

iOS 10

对于懒惰的人,Swift 3.0和iOS>=9是@Keller答案的优化版本:

let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)

let margin:CGFloat = 10.0
let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120)
let customView = UIView(frame: rect)

customView.backgroundColor = .green
alertController.view.addSubview(customView)

let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")})

let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")})

alertController.addAction(somethingAction)
alertController.addAction(cancelAction)

self.present(alertController, animated: true, completion:{})

我为UIAlertController(在Swift 4中)编写了一个扩展,它使用autolayout解决了布局问题。甚至还有一个回退消息字符串,以防出现问题(由于UIAlertController布局的未来更改)

下面是一个使用示例:

// Create a custom view for testing...
let customView = UIView()
customView.translatesAutoresizingMaskIntoConstraints = false
customView.backgroundColor = .red

// Set the custom view to a fixed height. In a real world application, you could use autolayouted content for height constraints
customView.addConstraint(NSLayoutConstraint(item: customView,
                                            attribute: .height,
                                            relatedBy: .equal,
                                            toItem: nil,
                                            attribute: .notAnAttribute,
                                            multiplier: 1,
                                            constant: 100))

// Create the alert and show it
let alert = UIAlertController(title: "Alert Title",
                                customView: customView,
                                fallbackMessage: "This should be a red rectangle",
                                preferredStyle: .actionSheet)

alert.addAction(UIAlertAction(title: "Yay!", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

self.present(alert, animated: true, completion: nil)
这将显示如下内容:

我试图绕过
UIAlertController
的限制,但无论我如何管理,它都不够好。如果你还在为此挣扎,我已经创造了一个可能会有所帮助。它允许您使用一组内置类型创建自定义图纸。它还可以进行扩展和重新设置样式。

到目前为止,我使用自动布局约束找到的最干净的解决方案:

func showPickerController() {
    let alertController = UIAlertController(title: "Translation Language", message: nil, preferredStyle: .actionSheet)
    let customView = UIView()
    alertController.view.addSubview(customView)
    customView.translatesAutoresizingMaskIntoConstraints = false
    customView.topAnchor.constraint(equalTo: alertController.view.topAnchor, constant: 45).isActive = true
    customView.rightAnchor.constraint(equalTo: alertController.view.rightAnchor, constant: -10).isActive = true
    customView.leftAnchor.constraint(equalTo: alertController.view.leftAnchor, constant: 10).isActive = true
    customView.heightAnchor.constraint(equalToConstant: 250).isActive = true

    alertController.view.translatesAutoresizingMaskIntoConstraints = false
    alertController.view.heightAnchor.constraint(equalToConstant: 430).isActive = true

    customView.backgroundColor = .green

    let selectAction = UIAlertAction(title: "Select", style: .default) { (action) in
        print("selection")
    }

    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    alertController.addAction(selectAction)
    alertController.addAction(cancelAction)
    self.present(alertController, animated: true, completion: nil)
}
输出:


这是@Cesare解决方案的Objective-C版本

- (void) showPickerController {
    UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"Translation Language" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    UIView *customView = [[UIView alloc] init];
    [alertController.view addSubview:customView];
    customView.translatesAutoresizingMaskIntoConstraints = NO;
    [customView.topAnchor constraintEqualToAnchor:alertController.view.topAnchor constant:45].active = YES;
    [customView.rightAnchor constraintEqualToAnchor:alertController.view.rightAnchor constant:-10].active = YES;
    [customView.leftAnchor constraintEqualToAnchor:alertController.view.leftAnchor constant:10].active = YES;
    [customView.heightAnchor constraintEqualToConstant:250].active = YES;

    alertController.view.translatesAutoresizingMaskIntoConstraints = NO;
    [alertController.view.heightAnchor constraintEqualToConstant:430].active = YES;
    
    customView.backgroundColor = [UIColor greenColor];
    
    UIAlertAction* selectAction = [UIAlertAction actionWithTitle:@"Select" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
    }];
    UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
    }];
    [alertController addAction:selectAction];
    [alertController addAction:cancelAction];
    
    [self presentViewController:alertController animated:YES completion:nil];
}

这真是太棒了,真的很有帮助。我在页边空白处的绿色视图后面还有一条线。我想我会在绿色视图周围放置一个容器视图。0页边距。谢谢,伙计。这太棒了。刚对自定义视图的宽度进行了轻微调整,但一切都很好!干杯,这代码太卑鄙了。当字体大小在iOS设备上因设置不同而不同时,我们不应该使用字符间距!这就是为什么我在回答中提到“一种不那么粗糙的方法是创建自己的视图子类,该子类的工作方式类似于UIAlertController的UIAlertActionStyle布局。事实上,相同的代码在iOS 8和iOS 9中看起来略有不同。”问题是向UIAlertController添加子视图,我相信UIAlertController的初始帧大小与UIView相同。在iPhone上,上述代码工作正常,因为alertController占据了设备的整个宽度。在iPad上,alertController的大小已调整。要使子视图自动调整大小,请设置大小调整掩码customView.autoresizingMask=UIViewAutoresizingFlexibleWidth;这很有效。只是想知道这是否会在审查过程中被拒绝,知道吗?没有涉及到私有API,所以我不知道苹果为什么要拒绝它。只面临一个问题,
customView
以灰色而不是红色显示。有什么想法吗?这看起来是一个很好的、干净的解决方案,但我认为人们强烈建议不要扩展
UIAlertController
,因为苹果不希望你这样做,而且可能会在将来的更新中打破你的“黑客”。这个解决方案可能也是这样吗?我试图尽可能优雅地处理任何失败。如果苹果公司有任何结构上的变化,最坏的结果应该是,警报只显示回退文本消息,而不是自定义视图,这正是该情况下API的一部分。这是最好的答案,而不是“选择”的答案。我很高兴有人正确地做到了这一点:-)关于该主题的最佳答案。想知道为什么这不是一个公认的答案。
- (void) showPickerController {
    UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"Translation Language" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    UIView *customView = [[UIView alloc] init];
    [alertController.view addSubview:customView];
    customView.translatesAutoresizingMaskIntoConstraints = NO;
    [customView.topAnchor constraintEqualToAnchor:alertController.view.topAnchor constant:45].active = YES;
    [customView.rightAnchor constraintEqualToAnchor:alertController.view.rightAnchor constant:-10].active = YES;
    [customView.leftAnchor constraintEqualToAnchor:alertController.view.leftAnchor constant:10].active = YES;
    [customView.heightAnchor constraintEqualToConstant:250].active = YES;

    alertController.view.translatesAutoresizingMaskIntoConstraints = NO;
    [alertController.view.heightAnchor constraintEqualToConstant:430].active = YES;
    
    customView.backgroundColor = [UIColor greenColor];
    
    UIAlertAction* selectAction = [UIAlertAction actionWithTitle:@"Select" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
    }];
    UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
    }];
    [alertController addAction:selectAction];
    [alertController addAction:cancelAction];
    
    [self presentViewController:alertController animated:YES completion:nil];
}