《優(yōu)雅的插入開屏廣告》-- 不改動任何一行代碼
在這個基礎(chǔ)上再添加了引導(dǎo)頁鞍盗,
=============================================
代碼還是不錯的斋荞,但是個人覺得跑芳,上訴代碼的耦合性還是太強了善玫,需要對 AppDelegate 和 ViewController 等代碼進(jìn)行入侵官硝。如果按照模塊化方式來開發(fā)龄恋,后續(xù)廣告要擴(kuò)展和維護(hù)都是很艱難的趴生,因為你要擔(dān)心你埋入的那些代碼被其他人員改動了阀趴。
下面是我使用的一套方案。真正做到模塊化苍匆,即插即用刘急!
實現(xiàn)原理
自啟動 & 監(jiān)聽
///在load 方法中,啟動監(jiān)聽浸踩,可以做到無注入
+ (void)load
{
[self shareInstance];
}
- (instancetype)init
{
self = [super init];
if (self) {
///如果是沒啥經(jīng)驗的開發(fā)叔汁,請不要在初始化的代碼里面做別的事,防止對主線程的卡頓检碗,和 其他情況
///應(yīng)用啟動, 首次開屏廣告
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
///要等DidFinished方法結(jié)束后才能初始化UIWindow据块,不然會檢測是否有rootViewController
dispatch_async(dispatch_get_main_queue(), ^{
[self checkAD];
});
}];
///進(jìn)入后臺
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
[self request];
}];
///后臺啟動,二次開屏廣告
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
[self checkAD];
}];
}
return self;
}
iOS的通知是一個神器,它會發(fā)出應(yīng)用的啟動折剃,退到后臺等事件通知另假,有了通知我們就可以做到對AppDelegate的無入侵。
只有通知還是沒有用的怕犁,我們還需要顯示边篮。
核心突破點:顯示
- (void)show
{
///初始化一個Window, 做到對業(yè)務(wù)視圖無干擾奏甫。
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
///廣告布局
[self setupSubviews:window];
///設(shè)置為最頂層戈轿,防止 AlertView 等彈窗的覆蓋
window.windowLevel = UIWindowLevelStatusBar + 1;
///默認(rèn)為YES,當(dāng)你設(shè)置為NO時阵子,這個Window就會顯示了
window.hidden = NO;
///來個漸顯動畫
window.alpha = 0;
[UIView animateWithDuration:0.3 animations:^{
window.alpha = 1;
}];
///防止釋放思杯,顯示完后 要手動設(shè)置為 nil
self.window = window;
}
其實大家一般蓋視圖,習(xí)慣在 KeyWindow 上直接AddSubview款筑, 其實這是不好的智蝠。首先KeyWindow 會被AlertView覆蓋, 還有可能別的業(yè)務(wù)代碼也進(jìn)行了AddSubview 這樣就會把你的廣告給覆蓋了奈梳。
而使用我這種 UIWindow 的初始化杈湾,可以讓你的視圖出現(xiàn)在最頂層,不用怕亂七八糟
的業(yè)務(wù)邏輯覆蓋攘须。
調(diào)用KeyWindow 還有個壞處漆撞。下面會說到。
跳轉(zhuǎn)
其實倒計時跟跳轉(zhuǎn)是個很普通的功能點,沒啥說的浮驳。有個關(guān)鍵點還是要說的 就是KeyWindow的調(diào)用
///不直接取KeyWindow 是因為當(dāng)有AlertView 或者有鍵盤彈出時悍汛, 取到的KeyWindow是錯誤的。
UIViewController* rootVC = [[UIApplication sharedApplication].delegate window].rootViewController;
[[rootVC imy_navigationController] pushViewController:[IMYWebViewController new] animated:YES];
其實 [UIApplication sharedApplication].keyWindow
取到的Window 不一定是你想要的至会。 因為KeyWindow 是會變的离咐,所以勁量使用 [Delegate Window]
來獲取顯示的Window。 做 OS X 的應(yīng)該體會多點奉件。
在送上一個擴(kuò)展宵蛀,獲取任意ViewController的navigationController
@implementation UIViewController (IMYPublic)
- (UINavigationController*)imy_navigationController
{
UINavigationController* nav = nil;
if ([self isKindOfClass:[UINavigationController class]]) {
nav = (id)self;
}
else {
if ([self isKindOfClass:[UITabBarController class]]) {
nav = [((UITabBarController*)self).selectedViewController imy_navigationController];
}
else {
nav = self.navigationController;
}
}
return nav;
}
@end
demo(gif圖,會動的县貌。术陶。)
然后我在上面的基礎(chǔ)上添加了一個引導(dǎo)頁的視圖,引導(dǎo)頁就是一個scrollview煤痕。實現(xiàn)起來應(yīng)該也沒什么難度
//這段代碼是我做測試的時候用的梧宫,是為了每次啟動都去跑引導(dǎo)頁
NSArray *images = @[@"1", @"2", @"3", @"4"];
XTGuidePagesViewController *xt = [[XTGuidePagesViewController alloc] init];
[mainNavVC addChildViewController:xt];
//self.window.rootViewController = xt;
xt.delegate = self;
[xt guidePageControllerWithImages:images];```
//正常的視圖
BOOL y = [XTGuidePagesViewController isShow];
if (y) {
XTGuidePagesViewController *xt = [[XTGuidePagesViewController alloc] init];
self.window.rootViewController = xt;
xt.delegate = self;
[xt guidePageControllerWithImages:images];
}else{
[self clickEnter];
然后最開始集成的時候,發(fā)現(xiàn)老有問題摆碉,然后看視圖才知道我界面順序沒加對塘匣,開屏頁的根視圖是navigationController。而那個引導(dǎo)頁的根視圖是UIViewController, 改一下appdelegate 里面的東西就可以了
然后如果你要用導(dǎo)航頁的話 吧工程里面的GuidePage里面的文件拖到你的項目里面巷帝,圖片的話可以加載本地的也可以去網(wǎng)上加載馆铁,看你自己項目需要,然后在appdelegate里面插入以下代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *mainVC = [[UIViewController alloc] init];
UINavigationController *mainNavVC = [[UINavigationController alloc] initWithRootViewController:mainVC];
[mainNavVC.navigationBar setHidden:YES];
self.window.rootViewController = mainNavVC;
[self.window makeKeyAndVisible];
BOOL y = [XTGuidePagesViewController isShow];
if (y) {
XTGuidePagesViewController *xt = [[XTGuidePagesViewController alloc] init];
self.window.rootViewController = xt;
xt.delegate = self;
[xt guidePageControllerWithImages:images];
}else{
[self clickEnter];
}
return YES;
}
- (void)clickEnter
{
ViewController *vc = [[ViewController alloc] init];
UINavigationController *mainNavVC = [[UINavigationController alloc] initWithRootViewController:vc];
[mainNavVC.navigationBar setHidden:YES];
self.window.rootViewController = mainNavVC;
[self.window.layer transitionWithAnimType:TransitionAnimTypeRippleEffect subType:TransitionSubtypesFromTop curve:TransitionCurveDefault duration:1.0f];
}
然后這個動畫是只有開屏頁的锅睛,集成了之后 不知道怎么錄gif··
工程目錄:https://github.com/SSnowCat/SNCLaunchDemo-master