UIAlertController中的自定义视图

我正在尝试在UIAlertController放置一个自定义视图。 我遇到了一些与自定义视图大小有关的奇怪问题。

我想要自定义视图跨越UIAlertController的宽度,无论可能。 我正在使用CGRectGetWidth(alertController.view.bounds)来获取警报控制器的宽度。 但是,这似乎是返回整个视图的宽度。 使用view.frame没有什么区别。

 UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"My Title" message:nil preferredStyle:UIAlertControllerStyleAlert]; UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(alertController.view.bounds), 50)]; view.backgroundColor = [UIColor blueColor]; [alertController.view addSubview:view]; [self presentViewController:alertController animated:YES completion:nil]; 

这产生了下面的结果。 我有相同的问题,试图获得UIAlertController X,Y宽度和高度属性。 有没有人知道我怎么可以不使用硬编码的数字位于警报控制器的中间这个观点?

在这里输入图像说明

你不应该这样做。 引用文档:

UIAlertController类旨在按原样使用,不支持子类。

这个类的视图层次是私有的,不能被修改。

如果你违背苹果这样明确的声明,那么所有的赌注都将被终止,即使你可以在当前的操作系统版本上运行它,它也可能会破坏未来的版本。

这是一个替代scheme。它不是将子视图添加到UIAlertControl的视图层次结构,而是将UIWindow添加到合适的位置。 为了跟踪UIAlertControl的视图框架,视图控制器使用obj-c runtime / swift扩展来调用UIViewController超类实现,并使用自定义的.view getter扩展。 这允许避免真正的视图的私有类依赖性,既不UIAlertControl或修改它的视图层次结构。

示例截图

Objective-C的

 #import <objc/runtime.h> #import <objc/message.h> @implementation AppDelegate + (UIView*)alertHelperView { static UIView *alertHelperView = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ alertHelperView = [UIView new]; alertHelperView.backgroundColor = [UIColor redColor]; alertHelperView.frame = CGRectZero; }); return alertHelperView; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self.window addSubview:[AppDelegate alertHelperView]]; return YES; } @end @implementation ViewController - (void)viewDidAppear:(BOOL)animated { Class class = [UIAlertController class]; class_addMethod(class, @selector(view), imp_implementationWithBlock(^(__unsafe_unretained UIAlertController* self) { struct objc_super super = { .receiver = self, .super_class = class_getSuperclass(class) }; id (*objc_msgSendSuper_typed)(struct objc_super *, SEL) = (void *)&objc_msgSendSuper; UIView* myView = objc_msgSendSuper_typed(&super, @selector(view)); CGRect newFrame = myView.frame; if (!self.isBeingPresented) { [AppDelegate alertHelperView].frame = CGRectZero; } else { [[AppDelegate alertHelperView].superview bringSubviewToFront:[AppDelegate alertHelperView]]; [AppDelegate alertHelperView].frame = CGRectMake(newFrame.origin.x, newFrame.origin.y, newFrame.size.width/2, newFrame.size.height/2); } return myView; }), "@@:"); UIAlertController * alert= [UIAlertController alertControllerWithTitle:@"Info" message:@"You are using UIAlertController" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { }]; UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { }]; [alert addAction:ok]; [alert addAction:cancel]; [self presentViewController:alert animated:YES completion:nil]; } @end 

Swift 3.1

 @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? static var alertHelperView : UIView! func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { AppDelegate.alertHelperView = UIView() AppDelegate.alertHelperView.backgroundColor = .red self.window?.addSubview(AppDelegate.alertHelperView!) return true } } extension UIAlertController { open override var view: UIView! { get { let newFrame : CGRect = super.view.frame if !self.isBeingPresented { AppDelegate.alertHelperView.frame = CGRect.zero } else { AppDelegate.alertHelperView.superview?.bringSubview(toFront: AppDelegate.alertHelperView) AppDelegate.alertHelperView.frame = CGRect(x:newFrame.origin.x,y:newFrame.origin.y,width:newFrame.size.width/2,height:newFrame.size.height/2) } return super.view } set(newValue) { super.view = newValue } } } class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { let alertController = UIAlertController(title: "Default Style", message: "A standard alert.", preferredStyle: .alert) let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { action in // ... } alertController.addAction(cancelAction) let OKAction = UIAlertAction(title: "OK", style: .default) { action in // ... } alertController.addAction(OKAction) self.present(alertController, animated: false) { } } } }