iOS開發(fā)之自定義Window

前言

這篇文章主要記錄在我在開發(fā)中針對 UIWindow 的使用。

遇到的問題

通常境況下,我在新建一個新的 iOS 項目后,每次都會刪除 main.storyboard 這個文件。然后自己在 AppDelegate 中自己來創(chuàng)建一個 window 對象。大致就是下面這個樣子的:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    
    self.window.backgroundColor = [UIColor blueColor];
    
    self.window.rootViewController = [ViewController new];
    
    [self.window makeKeyAndVisible];
    
    return YES;
}

最近在項目中遇到一個場景:

App 啟動后,此時需要 App 進行強制更新。強制更新,就要求強制更新的按鈕在最頂層,我發(fā)現(xiàn)之前代碼是通過 [UIApplication sharedApplication].delegate.window 獲取到 window 對象,并在此之上添加強制更新的視圖作為它的子視圖。貌似好像沒有什么問題,其實不然。因為這個強制更新的視圖不一定是在最頂層的。因為 Modal 出來的 Controller 會把它蓋住。不信你就試試,這樣一來可以進行別的操作算哪門子的強制更新?

解決方案

既然 KeyWindow 解決不了這個問題,我的解決方案是通過自定義 window,并設(shè)置 window 的級別,這樣他就在最頂層了。而自己創(chuàng)建一個 window 對象是有一些小細節(jié)的。還是通過代碼具體看一下:

我打算怎么設(shè)計

  • 自定義 YMUpdateView 繼承自 UIView,提供一個 show 接口
  • 重寫 \- (**instancetype**)initWithFrame:(CGRect)frame 方法,自定義 UI 視圖,主要就是自定義 window 對象。window 里面的子視圖,可以根據(jù)自己的業(yè)務(wù)和 UI 設(shè)計稿進行自己定制

我的實現(xiàn)

部分代碼如下:

#import "YMUpdateView.h"

@interface UpdateView ()

@property (nonatomic, strong) UIWindow *window;

@end

@implementation UpdateView

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        
        
        _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        _window.windowLevel = UIWindowLevelStatusBar;
        _window.rootViewController = [[UIViewController alloc] init];
        _window.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
        
        
    }
    return self;
}


- (void)show {
    _window.hidden = NO;
}

@end

  • 核心代碼就是 \- (**instancetype**)initWithFrame:(CGRect)frame 中自己創(chuàng)建一個 window 對象。更好一點可以封裝一個方法專門來創(chuàng)建 UI 視圖。在 layoutSubviews 方法中進行布局。
  • 注意一點就是,window 對象必須是被強引用的
  • windowLevel 設(shè)置為 UIWindowLevelStatusBar 級別,它和狀態(tài)欄在一個級別,一定是在最頂層的
  • 在使用的時候,也要用 strong 修飾的屬性,進行強引用。
@interface ViewController ()
@property (nonatomic, strong) UpdateView *uv;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.uv = [[UpdateView alloc] init];
    [self.uv show];
    
    
    // 模擬出現(xiàn) modal Controller 蓋住的情況
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        TestViewController *vc = [[TestViewController alloc] init];

        vc.modalPresentationStyle = UIModalPresentationFullScreen;
        [self presentViewController:vc animated:YES completion:nil];
    });

} /* viewDidLoad */

結(jié)束語

東西不難,但在工作中還比較實用。這只是一個簡單的場景。我們經(jīng)常在一些 App 中見到懸浮球的功能,我覺得也可以通過自定義 window 對象來實現(xiàn),需要處理的是手勢和邊界的計算。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容