更换tabbar的图表并不难, 难在动态更换时的思路, 我们可以先看看设置tabbarItem代码找思路:
UITabBarItem *item4 = [[UITabBarItem alloc] initWithTitle:@"我" image:[[UIImage imageNamed:@"tab_me_normal"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"tab_me_click"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
分析代码我们可以知道, 入口只有image和selectImage, 自己想出了两种方法, 如下:
- 及时更新法, 每次下载一套图片, 包括一个按钮的普通状态跟选中状态的图片, 下载完之后就及时更新, 下次再进入APP, 直接查找缓存, 不用再次下载 (此方法会出现的问题, 比如四个tabbarItem, 会出现图标不统一的问题, 即有的图标为新图标, 有的图标为老图标, 但是网络状态好的情况下, 一般不会出现这种问题, 再说更换tabbarItme的图标,不是经常性操作, 所以我目前就用的这种方法, 已经满足我的开发需要)
- 等待四套图标全部下载完, 再统一更新, 如果有部分图标下载不完成, 则不进行更换操作 (要与安卓商量好, 看看哪种方法适合, 我现在只写出上面那种方法, 这种方法请按上述方法进行扩展)
我写了一个Tabbar下载图片的工具类, 下面是.h文件 以及.m文件
#import <Foundation/Foundation.h> #import "PORouterModel.h" #import "SDImageCache.h" #import "SDWebImageDownloader.h" NS_ASSUME_NONNULL_BEGIN @interface POTabbarTool : NSObject /// 异步下载tabbar图片, (同时下载normal 跟 select图片, 两张图片都下载完成后 再触发最终的回调block) /// @param routerModel tabbar的图片 要从routerModel.image中获取url /// @param block 最终返回下载normal 跟 select图片 - (void)downloadImageWithPORouterMode:(PORouterModel *)routerModel AndReturnImageBlock:(void(^)(UIImage *normalImage, UIImage *selectImage, PORouterModel *routerModel))block; @end NS_ASSUME_NONNULL_END
#import "POTabbarTool.h" @implementation POTabbarTool /// 异步下载tabbar图片, (同时下载normal 跟 select图片, 两张图片都下载完成后 再触发最终的回调block) /// @param routerModel tabbar的图片 要从routerModel.image中获取url /// @param block 最终返回下载normal 跟 select图片 - (void)downloadImageWithPORouterMode:(PORouterModel *)routerModel AndReturnImageBlock:(void(^)(UIImage *normalImage, UIImage *selectImage, PORouterModel *routerModel))block{ __block UIImage *needNormalImage; __block UIImage *needSelectImage; dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_group_enter(group);//开启任务一 dispatch_group_async(group, queue, ^{ [self toSearchCacheWithUrlString:routerModel.image2 completed:^(UIImage *image) { needNormalImage = image; dispatch_group_leave(group);//任务一完成 }]; }); dispatch_group_enter(group);//开启任务二 dispatch_group_async(group, queue, ^{ [self toSearchCacheWithUrlString:routerModel.image1 completed:^(UIImage *image) { needSelectImage = image; dispatch_group_leave(group);//任务二完成 }]; }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ block(needNormalImage,needSelectImage,routerModel);//返回任务一跟任务二的数据 }); } - (void)toSearchCacheWithUrlString:(NSString *)urlString completed:(void (^)(UIImage *image))block{///<用SDImageCache去查找或下载图片, 最终返回图片 UIImage *needImage; SDImageCache *normalImageCache = [SDImageCache sharedImageCache]; needImage = [normalImageCache imageFromMemoryCacheForKey:urlString];//从内存中获取图片 if (!needImage) { needImage = [normalImageCache imageFromDiskCacheForKey:urlString];//从硬盘中获取图片 if (!needImage) {//如果都没有则下载图片 [SDWebImageDownloader.sharedDownloader downloadImageWithURL:[NSURL URLWithString:urlString] completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) { if (image && finished) { [normalImageCache storeImage:image forKey:urlString toDisk:YES completion:nil];//执行缓存图片 (包括缓存到内存和本地) [normalImageCache storeImage:image forKey:urlString toDisk:YES completion:^{//本来有想过在这里直接处理过的图片, 但是发现图片会出问题, 所以处理图片的逻辑就放最外层了 block(image); }]; } }]; } else{ block(needImage); } } else{ block(needImage); } }
看懂上面的方法, 就可以任意扩展了, 在返回的block内更新tabbarItem的图标即可, 需要注意的是, 在返回的block内, 尽量少使用局部变量, 防止循环引用造成一些奇奇怪怪的问题
再多补充一些block内的伪代码
//声明, 不可在以下block内调用局部变量, 导致局部变量所对应的VC不释放, 会出现奇怪的tabbarUI问题, 现在以下block内写法没有问题 WEAKSELF [self.tabbarTool downloadImageWithPORouterMode:routerModel AndReturnImageBlock:^(UIImage * _Nonnull normalImage, UIImage * _Nonnull selectImage, PORouterModel * _Nonnull routerModel) { UIImage *newNormalImage = [UIImage imageWithCGImage:normalImage.CGImage scale:2 orientation:normalImage.imageOrientation]; newNormalImage = [newNormalImage sd_resizedImageWithSize:CGSizeMake(29, 29) scaleMode:SDImageScaleModeAspectFit]; UIImage *newSelectImage = [UIImage imageWithCGImage:selectImage.CGImage scale:2 orientation:selectImage.imageOrientation]; newSelectImage = [newSelectImage sd_resizedImageWithSize:CGSizeMake(29, 29) scaleMode:SDImageScaleModeAspectFit]; weakSelf.needChangeVC.tabBarItem.image = [normalImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; weakSelf.needChangeVC.tabBarItem.selectedImage = [selectImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; }];