<修正一點:這里我選擇切換根視圖的方式是因為我們首頁的數據也是post請求,在token過期的情況下會直接強制彈回到登陸頁面。如果是放在首頁上面的一個view的話token過期時會造成沖突(閃了一下廣告瞬間彈出登陸失效然后彈回登陸頁面)。如果首頁是get請求完全不必這樣,直接首頁加上個view,還能有漸隱效果>
這個效果似乎成了一個趨勢了,微博、UC之類的玩的樂此不疲,產品汪們見了自然也是不會放過這個效果。這周提的需求里面其中就有這個。。。
具體的需求如下:
有條件加載網絡請求回來的圖片時顯示網絡請求的圖片,無法加載時加載本地準備好的一張圖片(注意我的需求可能不同,我是默認就要加載一張本地的圖片,以下方案也是按我的需求在設計)
個人覺得這個不難實現,網上搜了搜之前別人寫的,看了幾眼就不想看了,光寫代碼不寫思路的文章看不下去,索性自己做,中間肯定一堆坑,挖了坑自己填。
先上思路,這個思路是我跳坑挑了幾次之后完善的:
1.首先為appdelegate建個分類appdelegate+launchImage,這個不解釋了
2.為了減少對其它模塊的侵入性決定使用切換根視圖的方式
3.要考慮到兩個狀態:能在有限的時間從網絡上請求下來圖片加載好的狀態和沒有在有限的時間請求完畢的狀態
4.要考慮到網絡請求是在根視圖出現之后才開始“正式”啟動(這里我也不懂為什么視圖出現了網絡請求才算正式開始,這個坑我跳了半個小時),這就意味著你的視圖優先于請求完成
綜合3和4這兩個問題,我給出的方式如下:
1.控制單元為viewController
2.viewController中有兩個imageView和一個image,第一個imageView視圖是正常的啟動頁視圖(為了避免控制器出現網絡請求才開始的奇怪的坑,創造一個假象),第二個才是正常的imageView,上面有跳過和倒計時按鈕。image的作用是傳遞給第二個imageView.image
3.給1秒的時間去加載圖片,加載成功傳遞image,加載失敗不再處理,然后remove掉第一個假象imageView。這個時候圖像是什么就是什么
viewController代碼如下
.h代碼
@protocol JWLaunchImageControllerDelegate <NSObject>
/**
* 點擊跳過按鈕切換window根視圖
*/
- (void)appdelegateShouldChangeRootViewController;
@end
@interface JWLaunchImageController : UIViewController
@property (nonatomic,strong) UIImage *launchImage; //需要加載的imageview
@property (nonatomic,weak) id<JWLaunchImageControllerDelegate> delegate; //切換根視圖代理
@end
.m代碼
#import "JWLaunchImageController.h"
@interface JWLaunchImageController ()
{
NSInteger timerCount;
}
@property (nonatomic,strong) UIImageView *launchImageView; //圖片視圖
@property (nonatomic,strong) UIButton *disMissBtn; //跳過按鈕
@property (nonatomic,strong) UILabel *timerLab; //倒計時lab
@property (nonatomic,strong) NSTimer *timer; //計時器
@property (nonatomic,strong) UIImageView *realLaunchImageView; //真是啟動頁面
@end
@implementation JWLaunchImageController
- (void)viewDidLoad {
[super viewDidLoad];
[self setUpViews];
// Do any additional setup after loading the view.
}
#pragma mark 布局
- (void)setUpViews {
timerCount = 3;
//啟動圖
__weak typeof (self)weakSelf = self;
self.launchImageView = [[UIImageView alloc] init];
_launchImageView.image = self.launchImage;
_launchImageView.userInteractionEnabled = YES;
[self.view addSubview:_launchImageView];
[_launchImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.and.bottom.equalTo(weakSelf.view);
}];
//跳過按鈕
self.disMissBtn = [UIButton buttonWithType:(UIButtonTypeCustom)];
[_disMissBtn setTitle:@"跳過" forState:(UIControlStateNormal)];
[_disMissBtn addTarget:self action:@selector(clickDisMissBtn:) forControlEvents:(UIControlEventTouchUpInside)];
[_launchImageView addSubview:_disMissBtn];
[_disMissBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(weakSelf.launchImageView).offset(-20);
make.top.equalTo(weakSelf.launchImageView).offset(20);
}];
//計時lab
self.timerLab = [[UILabel alloc] init];
_timerLab.text = @"3";
_timerLab.textColor = [UIColor redColor];
[_launchImageView addSubview:_timerLab];
[_timerLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(weakSelf.disMissBtn).offset(-1);
make.right.equalTo(weakSelf.disMissBtn.mas_left).offset(-8);
}];
//計時器
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(setUpValueForTimerLab) userInfo:nil repeats:YES];
//真實加載頁
self.realLaunchImageView = [[UIImageView alloc] init];
_realLaunchImageView.image = [UIImage imageNamed:@"launchImageForJiaZai"];
[self.view addSubview:_realLaunchImageView];
[_realLaunchImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.and.bottom.equalTo(weakSelf.view);
}];
[self.view bringSubviewToFront:_realLaunchImageView];
}
#pragma mark 代理事件 :點擊跳過按鈕切換window根視圖
- (void)clickDisMissBtn:(UIButton *)btn {
if (self.delegate && [self.delegate respondsToSelector:@selector(appdelegateShouldChangeRootViewController)]) {
[self.delegate appdelegateShouldChangeRootViewController];
}
}
#pragma mark 倒計時為lab賦值
- (void)setUpValueForTimerLab {
timerCount--;
if (timerCount < 0) {
[self.timer invalidate];
} else if (timerCount == 2) { //給1秒時間加載
self.launchImageView.image = _launchImage;
[self.realLaunchImageView removeFromSuperview];
}
self.timerLab.text = [NSString stringWithFormat:@"%ld",timerCount];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.timer invalidate];
self.timer = nil;
}
appdelegate + launchImage代碼如下
.h文件
#import "AppDelegate.h"
#import "JWLaunchImageController.h"
@interface AppDelegate (LaunchImage)<JWLaunchImageControllerDelegate>
@property (nonatomic,copy) NSDictionary *dictionaryData;
@property (nonatomic,strong) NSTimer *timer;
@property (nonatomic,strong) JWLaunchImageController *launchImageVC;
/**
* 設置window的根視圖
*/
- (void)setUpWindowRootViewControllerWithImage:(UIImage *)imageView withTabBar:(int)tabBarIndex accountInfo:(NSArray *)accountInfo;
/**
* 請求網絡圖片
*/
- (void)requestImageFromNet;
@end
.m文件
#import "AppDelegate+LaunchImage.h"
#import "JWLaunchImageController.h"
#import <objc/runtime.h>
#import "AppDelegate.h"
#import <AFHTTPSessionManager.h>
#import <SDWebImageDownloader.h>
@implementation AppDelegate (LaunchImage)
const char launchVCKey;
const char dictionaryDataKey;
const char timerKey;
#pragma mark 設置window的根視圖
- (void)setUpWindowRootViewControllerWithImage:(UIImage *)image withTabBar:(int)tabBarIndex accountInfo:(NSArray *)accountInfo {
self.dictionaryData = @{@"tabBarIndex":@(tabBarIndex),@"accountInfo":accountInfo};
self.launchImageVC = [[JWLaunchImageController alloc] init];
self.launchImageVC.delegate = self;
self.launchImageVC.launchImage = image;
self.window.rootViewController = self.launchImageVC;
self.timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(disMissLaunchImageVCWithDictionaryData) userInfo:nil repeats:NO];
}
#pragma mark disMissLaunchImageVC
- (void)disMissLaunchImageVCWithDictionaryData {
[self.timer invalidate];
[self chooseRootVCWithTabBarIndex:[self.dictionaryData[@"tabBarIndex"] intValue] accountInfo:self.dictionaryData[@"accountInfo"]];
}
#pragma mark JWLaunchImageControllerDelegate
- (void)appdelegateShouldChangeRootViewController {
[self disMissLaunchImageVCWithDictionaryData];
}
#pragma mark 請求網絡圖片
- (void)requestImageFromNet {
__weak typeof (self)weakSelf = self;
//先設置為本地圖片,如果請求成功變為網絡圖片
self.launchImage = [UIImage imageNamed:@"guideImage3"];
//網絡請求。。。
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:kLaunchImageURL parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *dataDic = responseObject[@"body"];
[weakSelf downLoadLaunchImageWithURL:[NSURL URLWithString:dataDic[@"imgUrl"]]];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
#pragma mark 下載加載頁圖片
- (void)downLoadLaunchImageWithURL:(NSURL *)url {
__weak typeof (self)weakSelf = self;
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:url options:(SDWebImageDownloaderLowPriority) progress:^(NSInteger receivedSize, NSInteger expectedSize) {
} completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.launchImageVC.launchImage = image;
});
}];
}
#pragma mark setUpSetterAndGetter
- (void)setDictionaryData:(NSArray *)dictionaryData {
objc_setAssociatedObject(self, &dictionaryDataKey, dictionaryData, OBJC_ASSOCIATION_COPY);
}
- (NSArray *)dictionaryData {
return objc_getAssociatedObject(self, &dictionaryDataKey);
}
- (void)setTimer:(NSTimer *)timer {
objc_setAssociatedObject(self, &timerKey, timer, OBJC_ASSOCIATION_RETAIN);
}
- (NSTimer *)timer {
return objc_getAssociatedObject(self, &timerKey);
}
- (void)setLaunchImageVC:(JWLaunchImageController *)launchImageVC {
objc_setAssociatedObject(self, &launchVCKey, launchImageVC, OBJC_ASSOCIATION_RETAIN);
}
- (JWLaunchImageController *)launchImageVC {
return objc_getAssociatedObject(self, &launchVCKey);
}
@end
over~~~