2017-04-19 63 views
1

我試圖在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寬度和高度屬性。有誰知道我可以如何將這個視圖置於警報控制器的中間而不使用硬編碼的數字?

enter image description here

回答

4

你不應該這樣做。引用文檔:

UIAlertController類旨在按原樣使用,不支持子類化。

該類的視圖層次結構是私有的,不能修改。

如果您違反蘋果公司的明確聲明,則所有投注都將關閉,即使您可以在當前操作系統版本上使用它,它也可能會破壞任何未來版本。

+0

我要補充的是使用'UIPresentationController'你可以很容易地複製'UIAlertController'的行爲並提供你想要的任何視圖/控制器。 – jjatie

+0

@jjatie,你有沒有使用'UIPresentationController'來複制/擴展'UIAlertController'行爲的示例項目/ tuts?我還沒有使用'UIPresentationController'。 –

+0

這是一個起點。 CoolPresentationController將會關閉。 https://developer.apple.com/library/content/samplecode/LookInside/Introduction/Intro.html#//apple_ref/doc/uid/TP40014643還有一個關聯的WWDC視頻 – jjatie

1

下面是一個替代方案。它不是將子視圖添加到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) { 
      } 
     } 
    } 
}