我正在尝试将自定义视图放在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宽度和高度属性。有没有人知道如何在不使用硬编码的数字的情况下将此视图放在警报控制器的中间?
答案 0 :(得分:5)
你不应该这样做。引用文档:
UIAlertController类旨在按原样使用,不支持子类化。
此类的视图层次结构是私有的,不得修改。
如果你反对像Apple这样明确的声明,所有的赌注都已关闭,即使你可以让它在当前的操作系统版本上工作,它也可能会破坏任何未来的版本。
答案 1 :(得分:1)
这是一个替代方案。它不会将子视图添加到UIAlertControl
的视图层次结构中,而是添加到UIWindow
的适当位置。为了跟踪UIAlertControl
的视图帧,视图控制器使用obj-c runtime / swift扩展来扩展自定义.view getter,该扩展调用UIViewController
超类实现。这允许避免真正的视图的私有类依赖,既不是子类UIAlertControl
或修改它的视图层次结构。
<强>目标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) {
}
}
}
}