iOS PSTAlertController 源碼泛讀

<code> PSTAlertController </code> 是為了能讓用戶從<code> iOS7</code>開始兼容 <code> UIAlertController </code>

why<code> UIAlertController</code>?

iOS8 以后出的新類,目標(biāo)就是為了替代 UIActionSheet
and UIAlertView
,接口也極其友好,容易創(chuàng)建,以<code>controller</code>的形式展示更方便點(diǎn)!

兼容iOS7 的痛苦,不能使用心得API 還好git上有這么多優(yōu)秀的開源項目!

話說,為什么我們現(xiàn)在還要兼容iOS7呢??

<code> PSTAlertController </code> 其實也沒有什么特別的地方通過判斷能不能使用<code> UIAlertController </code> 來創(chuàng)建的


- (BOOL)alertControllerAvailable {
    return [UIAlertController class] != nil; // iOS 8 and later.
}

以上就是判斷創(chuàng)建的時候生成view的時候生成哪個

- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message preferredStyle:(PSTAlertControllerStyle)preferredStyle {
    if ((self = [super init])) {
        _title = [title copy];
        _message = [message copy];
        _preferredStyle = preferredStyle;

        if ([self alertControllerAvailable]) {
            _alertController = [PSTExtendedAlertController alertControllerWithTitle:title message:message preferredStyle:(UIAlertControllerStyle)preferredStyle];
        } else {
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
            if (preferredStyle == PSTAlertControllerStyleActionSheet) {
                _strongSheetStorage = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
            } else {
                _strongSheetStorage = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
            }
#endif
        }
    }
    return self;
}

創(chuàng)建的時候再根據(jù)能不能使用<code>UIAlertController</code>和類型來創(chuàng)建
<code>UIAlertController</code> 或者 <code>UIActionSheet</code> 或者<code> UIAlertView </code>

- (UIAlertView *)alertView {
    return (UIAlertView *)(self.strongSheetStorage ?: self.weakSheetStorage);
}

- (UIActionSheet *)actionSheet {
    return (UIActionSheet *)(self.strongSheetStorage ?: self.weakSheetStorage);
}

獲取<code>alertView</code> 或者 <code>actionView</code>

- (void)addAction:(PSTAlertAction *)action {
    NSAssert([action isKindOfClass:PSTAlertAction.class], @"Must be of type PSTAlertAction");

    action.alertController = self; // weakly connect

    self.actions = [[NSArray arrayWithArray:self.actions] arrayByAddingObject:action];

    if ([self alertControllerAvailable]) {
        __weak typeof (self) weakSelf = self;
        UIAlertAction *alertAction = [UIAlertAction actionWithTitle:action.title style:(UIAlertActionStyle)action.style handler:^(UIAlertAction *uiAction) {
            weakSelf.executedAlertAction = action;
            [action performAction];
        }];
        [self.alertController addAction:alertAction];
    } else {
        if (self.preferredStyle == PSTAlertControllerStyleActionSheet) {
            NSUInteger currentButtonIndex = [self.actionSheet addButtonWithTitle:action.title];

            if (action.style == PSTAlertActionStyleDestructive) {
                self.actionSheet.destructiveButtonIndex = currentButtonIndex;
            } else if (action.style == PSTAlertActionStyleCancel) {
                self.actionSheet.cancelButtonIndex = currentButtonIndex;
            }
        } else {
            NSUInteger currentButtonIndex = [self.alertView addButtonWithTitle:action.title];

            // UIAlertView doesn't support destructive buttons.
            if (action.style == PSTAlertActionStyleCancel) {
                self.alertView.cancelButtonIndex = currentButtonIndex;
            }
        }
    }
}

添加點(diǎn)擊行為,也是根據(jù)<code> alertControllerAvailable </code>先判斷是不是iOS8 以前的系統(tǒng).如果不是,就調(diào)用 UIAlertView 或者 UIActionSheet的添加按鈕的方式添加。

- (NSInteger)addButtonWithTitle:(nullable NSString *)title;    // returns index of button. 0 based.

需要執(zhí)行的block則保存在actions 數(shù)組中。如果是iOS8之前的系統(tǒng),則會在UIAlertView或者UIActionSheet的代理中執(zhí)行,比如:

- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
    [self viewWillDismissWithButtonIndex:buttonIndex];
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    [self viewDidDismissWithButtonIndex:buttonIndex];
}

<strong>JCAlertController 一覽</strong>
更加豐富的從iOS7開始支持的彈窗還有JCAlertController 詳情見git地址。支持的樣式更多,而且支持以一個隊列的方式彈出。比如:

請看下面的偽代碼:

[self presentWithFIFO:alert1];
[self presentWithFIFO:alert2];
[self presentWithFIFO:alert3];

結(jié)果:
alert1第一個顯示, 被用戶關(guān)閉后, alert2第二個顯示, 被用戶關(guān)閉后, alert3第三個顯示
就像這樣: alert1 >> alert2 >> alert3

<code>JCAlertController</code>的源碼文件如下

|____.DS_Store
|____AlertView
| |____JCAlertView.h
| |____JCAlertView.m
|____ButtonItem
| |____JCAlertButtonItem.h
| |____JCAlertButtonItem.m
|____Category
| |____NSAttributedString+JCCalculateSize.h
| |____NSAttributedString+JCCalculateSize.m
| |____UIColor+JCHightlightedColor.h
| |____UIColor+JCHightlightedColor.m
| |____UIImage+JCColor2Image.h
| |____UIImage+JCColor2Image.m
| |____UIViewController+JCPresentQueue.h // present category
| |____UIViewController+JCPresentQueue.m
| |____UIWindow+JCBlur.h
| |____UIWindow+JCBlur.m
|____JCAlertController.h // import this
|____JCAlertController.m
|____Style
| |____JCAlertStyle.h
| |____JCAlertStyle.m
| |____JCAlertStyleAlertView.h
| |____JCAlertStyleAlertView.m
| |____JCAlertStyleBackground.h
| |____JCAlertStyleBackground.m
| |____JCAlertStyleButton.h
| |____JCAlertStyleButton.m
| |____JCAlertStyleButtonCancel.h
| |____JCAlertStyleButtonCancel.m
| |____JCAlertStyleButtonNormal.h
| |____JCAlertStyleButtonNormal.m
| |____JCAlertStyleButtonWarning.h
| |____JCAlertStyleButtonWarning.m
| |____JCAlertStyleContent.h
| |____JCAlertStyleContent.m
| |____JCAlertStyleSeparator.h
| |____JCAlertStyleSeparator.m
| |____JCAlertStyleTitle.h
| |____JCAlertStyleTitle.m

平時使用的時候,只要import <code>JCAlertController</code>即可!
JCAlertController 中定義了一些初始化和添加元素的方法。
同時定義了一個分類,是當(dāng)有鍵盤事件的時候怎么處理。

@interface JCAlertController (keyboardHandle)

看看 JCAlertController的組成

@interface JCAlertController ()

@property (nonatomic, strong) UIImageView *blurView;
@property (nonatomic, strong) UIButton *coverView;
@property (nonatomic, strong) JCAlertView *alertView;

@end

一個有模糊樣式的背景圖片。一個可以接收點(diǎn)擊的時間的遮擋按鈕,然后就是看到的提示框 <code>JCAlertView</code>

然后定義了 轉(zhuǎn)場動畫。

///消失的動畫
@interface JCDimissAnimation : NSObject <UIViewControllerAnimatedTransitioning>
@end
///彈出的動畫
@interface JCPresentAnimation : NSObject <UIViewControllerAnimatedTransitioning>
@end

用來展示提示框變化的過渡動畫!

- (void)viewDidLoad {
    [super viewDidLoad];
    ///設(shè)置背景模糊圖片
    [self setupBlurView];
  ///添加點(diǎn)擊按鈕
    [self setupAlphaCoverView];
///根據(jù)整體Style設(shè)置alertView
    [self setupAlertView];
}

唯一不能滿足的就是沒有ActionSheet的樣式

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

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,124評論 4 61
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協(xié)議。它實...
    香橙柚子閱讀 24,718評論 8 183
  • 老董說:“這幾天在看一部電視劇,迷戀上了就沒日沒夜茶飯不思神魂顛倒的?!?老董說:“不要輕易去愛一個人,愛上了就是...
    琳瑯南方雪閱讀 182評論 0 0
  • 星期天的下午,北京大雨,老婆在成都出差,午飯后,一個人在家,突然想回顧一下經(jīng)典港片無間道。 無間道算是80后每個人...
    風(fēng)笛手閱讀 371評論 0 0

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