下面是一個替代方案。它不是將子視圖添加到UIAlertControl
的視圖層次結構中,而是將UIWindow
改爲適當的位置。要跟蹤UIAlertControl
的視圖框架,視圖控制器將使用obj-c運行時/ swift擴展(它調用UIViewController
超類實現)的自定義.view getter進行擴展。這可以避免真正的視圖的私有類依賴性,既不能繼承UIAlertControl
也不能修改它的視圖層次結構。
Example screenshot
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
雨燕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) {
}
}
}
}
我要補充的是使用'UIPresentationController'你可以很容易地複製'UIAlertController'的行爲並提供你想要的任何視圖/控制器。 – jjatie
@jjatie,你有沒有使用'UIPresentationController'來複制/擴展'UIAlertController'行爲的示例項目/ tuts?我還沒有使用'UIPresentationController'。 –
這是一個起點。 CoolPresentationController將會關閉。 https://developer.apple.com/library/content/samplecode/LookInside/Introduction/Intro.html#//apple_ref/doc/uid/TP40014643還有一個關聯的WWDC視頻 – jjatie