首页 > 代码库 > iOS开发项目篇—39获取用户未读的微博信息(信息提醒)
iOS开发项目篇—39获取用户未读的微博信息(信息提醒)
iOS开发项目篇—39获取用户未读的微博信息(信息提醒)
一、简单说明
1.实现效果
2.实现
(1)新建一个类,封装请求
查看新浪官方要求的请求参数
该类中的代码设计
YYUnreadCountParam.h文件
1 // YYUnreadCountParam.h 2 //封装请求参数的类 3 4 #import "YYBaseParam.h" 5 6 @interface YYUnreadCountParam : YYBaseParam 7 /**uid true int64 需要获取消息未读数的用户UID,必须是当前登录用户。*/ 8 @property(nonatomic,copy)NSString *uid; 9 10 @end
YYUnreadCountParam.m文件不做额外的处理
(2)新建一个类,用来封装获取的返回数据
该类中的代码设计
YYUnreadCountResult.h文件
1 // 2 // YYUnreadCountResult.h 3 // 封装请求成功返回结果数据的类 4 5 #import <Foundation/Foundation.h> 6 7 @interface YYUnreadCountResult : NSObject 8 /**status int 新微博未读数*/ 9 @property(nonatomic,assign)int status;10 11 /**follower int 新粉丝数*/12 @property(nonatomic,assign)int follower;13 14 /**cmt int 新评论数*/15 @property(nonatomic,assign)int cmt;16 17 /**dm int 新私信数*/18 @property(nonatomic,assign)int dm;19 20 /**mention_status int 新提及我的微博数*/21 @property(nonatomic,assign)int dmention_status;22 23 /**mention_cmt int 新提及我的评论数*/24 @property(nonatomic,assign)int mention_cmt;25 26 /**消息未读数=新私信数+新评论数+新提及我的微博数+新提及我的评论数*/27 -(int)messageCount;28 29 /**所有未读数=新微博未读数+新粉丝数+新私信数+新评论数+新提及我的微博数+新提及我的评论数*/30 -(int)totalCount;31 @end
YYUnreadCountResult.m文件
1 // 2 // YYUnreadCountResult.m 3 // 4 5 #import "YYUnreadCountResult.h" 6 7 @implementation YYUnreadCountResult 8 -(int)messageCount 9 {10 return self.cmt+self.dm+self.mention_cmt+self.dmention_status;11 }12 13 -(int)totalCount14 {15 return self.messageCount + self.status + self.follower;16 }17 @end
(3)封装业务处理类
YYUserTool.h文件
1 // 2 // YYUserTool.h 3 // 4 5 #import <Foundation/Foundation.h> 6 #import "YYUserInfoParam.h" 7 #import "YYUserInfoResult.h" 8 #import "YYBaseTool.h" 9 #import "YYUnreadCountParam.h"10 #import "YYUnreadCountResult.h"11 12 @interface YYUserTool : YYBaseTool13 /**14 * 加载用户的个人信息15 *16 * @param param 请求参数17 * @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)18 * @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)19 */20 +(void)userInfoWithParam:(YYUserInfoParam *)param success:(void (^)(YYUserInfoResult *result))success failure:(void (^)(NSError *error))failure;21 22 /**23 * 加载未读的微博信息24 *25 * @param param 请求参数26 * @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)27 * @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)28 */29 +(void)unreadCountWithParam:(YYUnreadCountParam *)param success:(void (^)(YYUnreadCountResult *result))success failure:(void (^)(NSError *error))failure;30 @end
YYUserTool.m文件
1 // 2 // YYUserTool.m 3 // 4 5 #import "YYUserTool.h" 6 #import "YYHttpTool.h" 7 #import "MJExtension.h" 8 #import "YYUnreadCountResult.h" 9 10 11 @implementation YYUserTool12 +(void)userInfoWithParam:(YYUserInfoParam *)param success:(void (^)(YYUserInfoResult *result))success failure:(void (^)(NSError *error))failure13 {14 15 [self getWithUrl:@"https://api.weibo.com/2/users/show.json" param:param resultClass:[YYUserInfoResult class] success:success failure:failure];16 }17 18 +(void)unreadCountWithParam:(YYUnreadCountParam *)param success:(void (^)(YYUnreadCountResult *))success failure:(void (^)(NSError *))failure19 {20 [self getWithUrl:@"https://rm.api.weibo.com/2/remind/unread_count.json" param:param resultClass:[YYUnreadCountResult class] success:success failure:failure];21 }22 @end
二、细节处理
1.系统挂起
新的问题:一进入后台,定时器就停止,不再会发送请求,获取最新的未读数据。
如何解决?在程序进入到后台的那一刻,告诉系统,保持运行状态。
补充:
运行状态
停止状态(关闭·程序退出)
挂起状态(进入待后台·暂停)
因为手机的内存是及其有限的,因此它不可能随随便便让所有的程序进入到后台后都还处于运行状态。因此,如果程序进入后台,还想让其保持运行状态的话,需要程序进入到后台那一刻的时候进行申请。
提示:默认情况下,所有程序进入到后台,都将处于挂起状态(暂停)。
可以提醒操作系统,当前这个应用需要在后台开启一个线程执行任务,如果这样的话操作系统会允许程序在后台仍然保持运行状态(能够持续的时间是不确定的,随时可能会被杀掉)
说明:存在于内存中的程序可能是下面三种情况
(1)前台运行
(2)后台运行
(3)休眠(挂起,暂停)
当系统发生内存警告的时候,处于休眠状态的程序将最可能被杀死,因为它此时什么都没做,却还占据着内存空间。
发生内存警告时的优先级保证:(1)>(2)>(3)
如何让程序在系统中长时间存活?需要设置配置文件。
以欺骗的方式,告诉系统这个应用是播放音频的,不要关闭。可以在代理中,设置一个0kb的文件让其循环播放,以试图骗过系统。
使用上述业务类的代码设计:
YYTabBarViewController.m文件
1 // 2 // YYTabBarViewController.m 3 // 4 5 #import "YYTabBarViewController.h" 6 #import "YYHomeTableViewController.h" 7 #import "YYDiscoverViewController.h" 8 #import "YYMessageViewController.h" 9 #import "YYProfileViewController.h" 10 #import "UIImage+Extension.h" 11 #import "YYNavigationViewController.h" 12 #import "YYTabBar.h" 13 #import "YYComposeViewController.h" 14 #import "YYUnreadCountResult.h" 15 #import "YYUnreadCountParam.h" 16 #import "YYUserTool.h" 17 #import "YYAccountTool.h" 18 @interface YYTabBarViewController ()<UITabBarControllerDelegate,YYTabBarDelegate> 19 @property(nonatomic,weak)YYHomeTableViewController *home; 20 @property(nonatomic,weak)YYMessageViewController *message; 21 @property(nonatomic,weak)YYProfileViewController *profile; 22 @end 23 24 @implementation YYTabBarViewController 25 26 27 - (void)viewDidLoad 28 { 29 [super viewDidLoad]; 30 //添加四个子控制器 31 [self addAllChildVcs]; 32 33 // 调整tabbar 34 [self addCustomTabBar]; 35 36 //设置定时器,每隔两秒就获取一次未读微博信息 37 [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(getUnreadCount) userInfo:nil repeats:YES]; 38 } 39 40 -(void)getUnreadCount 41 { 42 //1.请求参数 43 YYUnreadCountParam *param=[YYUnreadCountParam param]; 44 param.uid=[YYAccountTool accountModel].uid; 45 46 47 //2.获取未读微博信息 48 [YYUserTool unreadCountWithParam:param success:^(YYUnreadCountResult *result) { 49 //显示新的微博数 50 if (result.status==0) { 51 self.home.tabBarItem.badgeValue=http://www.mamicode.com/nil; 52 }else 53 { 54 self.home.tabBarItem.badgeValue=http://www.mamicode.com/[NSString stringWithFormat:@"%d",result.status]; 55 } 56 57 //显示消息未读数 58 if (result.messageCount==0) { 59 self.message.tabBarItem.badgeValue=http://www.mamicode.com/nil; 60 }else 61 { 62 self.message.tabBarItem.badgeValue=http://www.mamicode.com/[NSString stringWithFormat:@"%d",result.messageCount]; 63 } 64 65 //显示新的粉丝数量 66 if (result.follower==0) { 67 self.profile.tabBarItem.badgeValue=http://www.mamicode.com/nil; 68 }else 69 { 70 self.profile.tabBarItem.badgeValue=http://www.mamicode.com/[NSString stringWithFormat:@"%d",result.follower]; 71 } 72 73 //在图标上显示所有的未读数 74 [UIApplication sharedApplication].applicationIconBadgeNumber=result.totalCount; 75 } failure:^(NSError *error) { 76 YYLog(@"请求失败"); 77 }]; 78 79 } 80 -(void)addAllChildVcs 81 { 82 YYHomeTableViewController *home=[[YYHomeTableViewController alloc]init]; 83 [self addOneChildVc:home title:@"首页" imageName:@"tabbar_home" selectedImageName:@"tabbar_home_selected"]; 84 self.home=home; 85 86 YYMessageViewController *message=[[YYMessageViewController alloc]init]; 87 [self addOneChildVc:message title:@"消息" imageName:@"tabbar_message_center" selectedImageName:@"tabbar_message_center_selected"]; 88 self.message=message; 89 90 YYDiscoverViewController *discover=[[YYDiscoverViewController alloc]init]; 91 [self addOneChildVc:discover title:@"发现" imageName:@"tabbar_discover" selectedImageName:@"tabbar_discover_selected"]; 92 93 YYProfileViewController *profile=[[YYProfileViewController alloc]init]; 94 [self addOneChildVc:profile title:@"我" imageName:@"tabbar_profile" selectedImageName:@"tabbar_profile_selected"]; 95 self.profile=profile; 96 } 97 98 -(void)addCustomTabBar 99 {100 YYTabBar *customTabBar = [[YYTabBar alloc] init];101 //设置代理102 customTabBar.delegate=self;103 // 更换系统自带的tabbar104 [self setValue:customTabBar forKeyPath:@"tabBar"];105 }106 107 108 #pragma mark-YYTabBarDelegate109 -(void)tabBarDidClickedPlusButton:(YYTabBar *)tabBar110 {111 //弹出发微博的控制器112 YYComposeViewController *compose=[[YYComposeViewController alloc]init];113 YYNavigationViewController *nav=[[YYNavigationViewController alloc]initWithRootViewController:compose];114 [self presentViewController:nav animated:YES completion:nil];115 }116 117 118 /**119 * 添加一个子控制器120 *121 * @param childVC 子控制对象122 * @param title 标题123 * @param imageName 图标124 * @param selectedImageName 选中时的图标125 */126 -(void)addOneChildVc:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName127 {128 //随机设置子控制器的背景颜色129 // childVc.view.backgroundColor=YYRandomColor;130 131 //设置标题132 childVc.title=title; //相当于设置了后两者的标题133 134 135 //设置图标136 childVc.tabBarItem.image=[UIImage imageWithName:imageName];137 //设置选中时的图标138 UIImage *selectedImage=[UIImage imageWithName:selectedImageName];139 140 //设置tabBarItem普通状态下文字的颜色141 NSMutableDictionary *textAttrs=[NSMutableDictionary dictionary];142 textAttrs[UITextAttributeTextColor]=[UIColor blackColor];143 textAttrs[UITextAttributeFont]=[UIFont systemFontOfSize:10];144 [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal];145 146 //设置tabBarItem普通状态下文字的颜色147 NSMutableDictionary *selectedtextAttrs=[NSMutableDictionary dictionary];148 selectedtextAttrs[UITextAttributeTextColor]=[UIColor orangeColor];149 [childVc.tabBarItem setTitleTextAttributes:selectedtextAttrs forState:UIControlStateSelected];150 151 if (iOS7) {152 // 声明这张图片用原图(别渲染)153 selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];154 }155 childVc.tabBarItem.selectedImage = selectedImage;156 157 // 添加为tabbar控制器的子控制器158 YYNavigationViewController *nav=[[YYNavigationViewController alloc]initWithRootViewController:childVc];159 160 [self addChildViewController:nav];161 162 }163 164 @end
程序的后台处理代码:
YYAppDelegate.m文件
1 // 2 // YYAppDelegate.m 3 // 4 5 #import "YYAppDelegate.h" 6 #import "YYOAuthViewController.h" 7 #import "YYControllerTool.h" 8 #import "YYAccountTool.h" 9 #import "YYAccountModel.h" 10 #import "SDWebImageManager.h" 11 #import "SDImageCache.h" 12 #import "AFNetworking.h" 13 #import "MBProgressHUD+MJ.h" 14 15 #import <AVFoundation/AVFoundation.h> 16 17 @implementation YYAppDelegate 18 19 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 20 { 21 //欺骗 22 // AVAudioPlayer *player=[[AVAudioPlayer alloc]initWithContentsOfURL:@"xxx" error:nil]; 23 // player.numberOfLoops=-1;//循环播放 24 // [player prepareToPlay];//缓冲 25 // [player play];//播放 26 27 28 //1.创建窗口 29 self.window=[[UIWindow alloc]init]; 30 self.window.frame=[UIScreen mainScreen].bounds; 31 32 33 //2.显示窗口(主窗口) 34 [self.window makeKeyAndVisible]; 35 36 //3.设置窗口的根控制器 37 YYAccountModel *account=[YYAccountTool accountModel]; 38 39 if (account) { // 存在成功授权的账号信息 40 [YYControllerTool chooseRootViewController]; 41 }else //没有登陆过 42 { 43 self.window.rootViewController=[[YYOAuthViewController alloc]init]; 44 } 45 46 //4.监控网络状态 47 AFNetworkReachabilityManager *mgr=[AFNetworkReachabilityManager sharedManager]; 48 //当网络状态改变的时候,就会调用 49 [mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { 50 switch (status) { 51 case AFNetworkReachabilityStatusUnknown://未知网络 52 case AFNetworkReachabilityStatusNotReachable://没有网络 53 YYLog(@"没有网络(断网)"); 54 [MBProgressHUD showError:@"网络异常,请检查网络设置!"]; 55 break; 56 case AFNetworkReachabilityStatusReachableViaWWAN://手机自带网络 57 YYLog(@"手机自带网络"); 58 break; 59 case AFNetworkReachabilityStatusReachableViaWiFi://WIFI 60 YYLog(@"WIFI"); 61 break; 62 } 63 }]; 64 //开始监控 65 [mgr startMonitoring]; 66 return YES; 67 } 68 69 70 - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application 71 { 72 // 赶紧清除所有的内存缓存 73 [[SDImageCache sharedImageCache] clearMemory]; 74 75 // 赶紧停止正在进行的图片下载操作 76 [[SDWebImageManager sharedManager] cancelAll]; 77 } 78 79 - (void)applicationWillResignActive:(UIApplication *)application 80 { 81 82 } 83 84 /**程序进入后台的时候调用*/ 85 - (void)applicationDidEnterBackground:(UIApplication *)application 86 { 87 //提醒这个操作系统:当前这个应用程序需要在后台开启一个任务 88 //操作系统会运行这个应用程序在系统中保持运行状态(能够持续的时间是不确定的) 89 UIBackgroundTaskIdentifier taskID=[application beginBackgroundTaskWithExpirationHandler:^{ 90 //后台运行的时间到期了,就会调用这个block 91 [application endBackgroundTask:taskID]; 92 }]; 93 } 94 95 - (void)applicationWillEnterForeground:(UIApplication *)application 96 { 97 98 } 99 100 - (void)applicationDidBecomeActive:(UIApplication *)application101 {102 103 }104 105 - (void)applicationWillTerminate:(UIApplication *)application106 {107 108 }109 110 @end
三、补充和修复
新的问题
(1)关于定时器:当滑动微博界面的时候,定时器就停止工作。原因是因为定时器是在项目的主线程处理的,默认情况下如果主线程正在处理UI事件的话是不会去处理定时器的。
告诉程序,尽量抽取时间爱哪去处理定时器,不应该在用户滚动页面的时候就把定时器给停了。
解决方法:把定时器添加到运行循环中,更改模式。
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 //添加四个子控制器 5 [self addAllChildVcs]; 6 7 // 调整tabbar 8 [self addCustomTabBar]; 9 10 //设置定时器,每隔两秒就获取一次未读微博信息11 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(getUnreadCount) userInfo:nil repeats:YES];12 [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];13 }
(2)关于多长时间发送一次请求
两秒发送一次请求太频繁,会很耗电。在开发中,设置为10秒钟左右就差不多了。
这样就带来了新的问题,下拉刷新之后,微博的提醒数字要稍微过一点儿时间才会清零。
所以,我们还需要监听下拉刷新事件,当下拉刷新成功的时候,立即对未读提醒进行清空。
YYHomeTableViewController.m文件中
1 /** 2 * 提示用户最新的微博数量 3 * 4 * @param count 最新的微博数量 5 */ 6 -(void)showNewStatusesCount:(int)count 7 { 8 //0.清零提醒数字 9 [UIApplication sharedApplication].applicationIconBadgeNumber -=self.tabBarItem.badgeValue.intValue;10 self.tabBarItem.badgeValue=http://www.mamicode.com/nil;11 12 //1.创建一个label13 UILabel *label=[[UILabel alloc]init];14 15 //2.设置label的文字
(3)当点击首页的时候,自动下拉刷新数据
说明:点击一次首页,回到之前所在的位置,点击两次首页,回到首页cell的顶部。
YYTabBarViewController.m文件
1 // 2 // YYTabBarViewController.m 3 // 4 5 #import "YYTabBarViewController.h" 6 #import "YYHomeTableViewController.h" 7 #import "YYDiscoverViewController.h" 8 #import "YYMessageViewController.h" 9 #import "YYProfileViewController.h" 10 #import "UIImage+Extension.h" 11 #import "YYNavigationViewController.h" 12 #import "YYTabBar.h" 13 #import "YYComposeViewController.h" 14 #import "YYUnreadCountResult.h" 15 #import "YYUnreadCountParam.h" 16 #import "YYUserTool.h" 17 #import "YYAccountTool.h" 18 @interface YYTabBarViewController ()<UITabBarControllerDelegate,YYTabBarDelegate> 19 @property(nonatomic,weak)YYHomeTableViewController *home; 20 @property(nonatomic,weak)YYMessageViewController *message; 21 @property(nonatomic,weak)YYProfileViewController *profile; 22 @property (nonatomic, weak) UIViewController *lastSelectedViewContoller; 23 @end 24 25 @implementation YYTabBarViewController 26 27 28 - (void)viewDidLoad 29 { 30 [super viewDidLoad]; 31 self.delegate=self;//自己成为自己的代理 32 33 //添加四个子控制器 34 [self addAllChildVcs]; 35 36 // 调整tabbar 37 [self addCustomTabBar]; 38 39 //设置定时器,每隔两秒就获取一次未读微博信息 40 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(getUnreadCount) userInfo:nil repeats:YES]; 41 [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 42 } 43 44 #pragma mark-代理方法 45 - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UINavigationController *)viewController 46 { 47 UIViewController *vc = [viewController.viewControllers firstObject]; 48 if ([vc isKindOfClass:[YYHomeTableViewController class]]) { 49 if (self.lastSelectedViewContoller == vc) { 50 [self.home refresh:YES]; 51 } else { 52 [self.home refresh:NO]; 53 } 54 } 55 56 self.lastSelectedViewContoller = vc; 57 } 58 59 -(void)getUnreadCount 60 { 61 //1.请求参数 62 YYUnreadCountParam *param=[YYUnreadCountParam param]; 63 param.uid=[YYAccountTool accountModel].uid; 64 65 66 //2.获取未读微博信息 67 [YYUserTool unreadCountWithParam:param success:^(YYUnreadCountResult *result) { 68 //显示新的微博数 69 if (result.status==0) { 70 self.home.tabBarItem.badgeValue=http://www.mamicode.com/nil; 71 }else 72 { 73 self.home.tabBarItem.badgeValue=http://www.mamicode.com/[NSString stringWithFormat:@"%d",result.status]; 74 } 75 76 //显示消息未读数 77 if (result.messageCount==0) { 78 self.message.tabBarItem.badgeValue=http://www.mamicode.com/nil; 79 }else 80 { 81 self.message.tabBarItem.badgeValue=http://www.mamicode.com/[NSString stringWithFormat:@"%d",result.messageCount]; 82 } 83 84 //显示新的粉丝数量 85 if (result.follower==0) { 86 self.profile.tabBarItem.badgeValue=http://www.mamicode.com/nil; 87 }else 88 { 89 self.profile.tabBarItem.badgeValue=http://www.mamicode.com/[NSString stringWithFormat:@"%d",result.follower]; 90 } 91 92 //在图标上显示所有的未读数 93 [UIApplication sharedApplication].applicationIconBadgeNumber=result.totalCount; 94 YYLog(@"%d",result.totalCount); 95 } failure:^(NSError *error) { 96 YYLog(@"请求失败"); 97 }]; 98 99 }100 -(void)addAllChildVcs101 {102 YYHomeTableViewController *home=[[YYHomeTableViewController alloc]init];103 [self addOneChildVc:home title:@"首页" imageName:@"tabbar_home" selectedImageName:@"tabbar_home_selected"];104 self.home=home;105 self.lastSelectedViewContoller=home;106 107 YYMessageViewController *message=[[YYMessageViewController alloc]init];108 [self addOneChildVc:message title:@"消息" imageName:@"tabbar_message_center" selectedImageName:@"tabbar_message_center_selected"];109 self.message=message;110 111 YYDiscoverViewController *discover=[[YYDiscoverViewController alloc]init];112 [self addOneChildVc:discover title:@"发现" imageName:@"tabbar_discover" selectedImageName:@"tabbar_discover_selected"];113 114 YYProfileViewController *profile=[[YYProfileViewController alloc]init];115 [self addOneChildVc:profile title:@"我" imageName:@"tabbar_profile" selectedImageName:@"tabbar_profile_selected"];116 self.profile=profile;117 }118 119 -(void)addCustomTabBar120 {121 YYTabBar *customTabBar = [[YYTabBar alloc] init];122 //设置代理123 customTabBar.delegate=self;124 // 更换系统自带的tabbar125 [self setValue:customTabBar forKeyPath:@"tabBar"];126 }127 128 129 #pragma mark-YYTabBarDelegate130 -(void)tabBarDidClickedPlusButton:(YYTabBar *)tabBar131 {132 //弹出发微博的控制器133 YYComposeViewController *compose=[[YYComposeViewController alloc]init];134 YYNavigationViewController *nav=[[YYNavigationViewController alloc]initWithRootViewController:compose];135 [self presentViewController:nav animated:YES completion:nil];136 }137 138 139 /**140 * 添加一个子控制器141 *142 * @param childVC 子控制对象143 * @param title 标题144 * @param imageName 图标145 * @param selectedImageName 选中时的图标146 */147 -(void)addOneChildVc:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName148 {149 //随机设置子控制器的背景颜色150 // childVc.view.backgroundColor=YYRandomColor;151 152 //设置标题153 childVc.title=title; //相当于设置了后两者的标题154 155 156 //设置图标157 childVc.tabBarItem.image=[UIImage imageWithName:imageName];158 //设置选中时的图标159 UIImage *selectedImage=[UIImage imageWithName:selectedImageName];160 161 //设置tabBarItem普通状态下文字的颜色162 NSMutableDictionary *textAttrs=[NSMutableDictionary dictionary];163 textAttrs[UITextAttributeTextColor]=[UIColor blackColor];164 textAttrs[UITextAttributeFont]=[UIFont systemFontOfSize:10];165 [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal];166 167 //设置tabBarItem普通状态下文字的颜色168 NSMutableDictionary *selectedtextAttrs=[NSMutableDictionary dictionary];169 selectedtextAttrs[UITextAttributeTextColor]=[UIColor orangeColor];170 [childVc.tabBarItem setTitleTextAttributes:selectedtextAttrs forState:UIControlStateSelected];171 172 if (iOS7) {173 // 声明这张图片用原图(别渲染)174 selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];175 }176 childVc.tabBarItem.selectedImage = selectedImage;177 178 // 添加为tabbar控制器的子控制器179 YYNavigationViewController *nav=[[YYNavigationViewController alloc]initWithRootViewController:childVc];180 181 [self addChildViewController:nav];182 183 }184 185 @end
YYHomeTableViewController.h文件
1 // 2 // YYHomeTableViewController.h 3 // 4 5 #import <UIKit/UIKit.h> 6 7 @interface YYHomeTableViewController : UITableViewController 8 9 /**10 * 刷新11 */12 - (void)refresh:(BOOL)fromSelf;13 @end
YYHomeTableViewController.m文件
1 // 2 // YYHomeTableViewController.m 3 // 4 5 #import "YYHomeTableViewController.h" 6 #import "YYOneViewController.h" 7 #import "YYTitleButton.h" 8 #import "YYPopMenu.h" 9 #import "YYAccountModel.h" 10 #import "YYAccountTool.h" 11 //#import "AFNetworking.h" 12 #import "UIImageView+WebCache.h" 13 #import "YYUserModel.h" 14 #import "YYStatusModel.h" 15 #import "MJExtension.h" 16 #import "YYloadStatusesFooter.h" 17 //#import "YYHttpTool.h" 18 #import "YYHomeStatusesParam.h" 19 #import "YYHomeStatusesResult.h" 20 #import "YYStatusTool.h" 21 #import "YYUserInfoParam.h" 22 #import "YYUserTool.h" 23 24 @interface YYHomeTableViewController ()<YYPopMenuDelegate> 25 @property(nonatomic,assign)BOOL down; 26 @property(nonatomic,strong)NSMutableArray *statuses; 27 @property(nonatomic,strong)YYloadStatusesFooter *footer; 28 @property(nonatomic,strong) YYTitleButton *titleButton; 29 @property (nonatomic, weak) UIRefreshControl *refreshControl; 30 @end 31 32 @implementation YYHomeTableViewController 33 34 #pragma mark- 懒加载 35 -(NSMutableArray *)statuses 36 { 37 if (_statuses==nil) { 38 _statuses=[NSMutableArray array]; 39 } 40 return _statuses; 41 } 42 - (void)viewDidLoad 43 { 44 [super viewDidLoad]; 45 46 //设置导航栏内容 47 [self setupNavBar]; 48 49 //集成刷新控件 50 [self setupRefresh]; 51 52 //设置用户的昵称为标题 53 //先显示首页标题,延迟两秒之后变换成用户昵称 54 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 55 [self setupUserInfo]; 56 }); 57 } 58 59 /** 60 *设置用户的昵称为标题 61 */ 62 -(void)setupUserInfo 63 { 64 //1.封装请求参数 65 // YYUserInfoParam *params=[[YYUserInfoParam alloc]init]; 66 // params.access_token=[YYAccountTool accountModel].access_token; 67 YYUserInfoParam *params=[YYUserInfoParam param]; 68 params.uid=[YYAccountTool accountModel].uid; 69 70 //2.发送网络请求 71 [YYUserTool userInfoWithParam:params success:^(YYUserInfoResult *result) { 72 73 //字典转模型 74 YYUserModel *user=result; 75 76 //设置标题 77 [self.titleButton setTitle:user.name forState:UIControlStateNormal]; 78 // 存储账号信息(需要先拿到账号) 79 YYAccountModel *account=[YYAccountTool accountModel]; 80 account.name=user.name; 81 //存储 82 [YYAccountTool save:account]; 83 } failure:^(NSError *error) { 84 YYLog(@"请求失败"); 85 }]; 86 } 87 88 //集成刷新控件 89 -(void)setupRefresh 90 { 91 // 1.添加下拉刷新控件 92 UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; 93 [self.tableView addSubview:refreshControl]; 94 self.refreshControl=refreshControl; 95 96 //2.监听状态 97 [refreshControl addTarget:self action:(@selector(refreshControlStateChange:)) forControlEvents:UIControlEventValueChanged]; 98 99 //3.让刷新控件自动进入到刷新状态100 [refreshControl beginRefreshing];101 102 //4.手动调用方法,加载数据103 //模拟网络延迟,延迟2.0秒104 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{105 [self refreshControlStateChange:refreshControl];106 });107 108 //5.上拉刷新数据109 YYloadStatusesFooter *footer=[YYloadStatusesFooter loadFooter];110 self.tableView.tableFooterView=footer;111 self.footer=footer;112 }113 114 /**115 * 当下拉刷新控件进入刷新状态(转圈圈)的时候会自动调用116 */117 -(void)refreshControlStateChange:(UIRefreshControl *)refreshControl118 {119 [self loadNewStatuses:refreshControl];120 }121 122 #pragma mark- 刷新123 -(void)refresh:(BOOL)fromSelf124 {125 if (self.tabBarItem.badgeValue) {//如果有数字126 //转圈圈127 [self.refreshControl beginRefreshing];128 129 //刷新数据130 [self loadNewStatuses:self.refreshControl];131 }else if(fromSelf) // 没有数字132 {133 //让表格回到最顶部134 NSIndexPath *firstRow=[NSIndexPath indexPathForItem:0 inSection:0];135 [self.tableView scrollToRowAtIndexPath:firstRow atScrollPosition:UITableViewScrollPositionTop animated:YES];136 137 }138 }139 #pragma mark-加载微博数据140 -(void)loadNewStatuses:(UIRefreshControl *)refreshControl141 {142 //1.封装请求参数143 // YYHomeStatusesParam *param=[[YYHomeStatusesParam alloc]init];144 // param.access_token=[YYAccountTool accountModel].access_token;145 YYHomeStatusesParam *param=[YYHomeStatusesParam param];146 YYStatusModel *firstStatus=[self.statuses firstObject];147 if (firstStatus) {148 param.since_id=@([firstStatus.idstr longLongValue]);149 }150 151 //2.加载微博数据152 [YYStatusTool homeStatusesWithParam:param success:^(YYHomeStatusesResult *result) {153 //获取最新的微博数组154 NSArray *newStatuses=result.statuses;155 156 //把新数据添加到旧数据的前面157 NSRange range=NSMakeRange(0, newStatuses.count);158 NSIndexSet *indexSet=[NSIndexSet indexSetWithIndexesInRange:range];159 [self.statuses insertObjects:newStatuses atIndexes:indexSet];160 YYLog(@"刷新了--%d条新数据",newStatuses.count);161 162 //重新刷新表格163 [self.tableView reloadData];164 //让刷新控件停止刷新(回复默认的状态)165 [refreshControl endRefreshing];166 [self showNewStatusesCount:newStatuses.count];167 168 } failure:^(NSError *error) {169 YYLog(@"请求失败");170 //让刷新控件停止刷新(回复默认的状态)171 [refreshControl endRefreshing];172 173 }];174 175 }176 177 /**178 * 加载更多的微博数据179 */180 - (void)loadMoreStatuses181 {182 //1.封装请求参数183 // YYHomeStatusesParam *param=[[YYHomeStatusesParam alloc]init];184 // param.access_token=[YYAccountTool accountModel].access_token;185 YYHomeStatusesParam *param=[YYHomeStatusesParam param];186 YYStatusModel *lastStatus=[self.statuses lastObject];187 if (lastStatus) {188 param.max_id=@([lastStatus.idstr longLongValue]-1);189 }190 191 //2.发送网络请求192 [YYStatusTool homeStatusesWithParam:param success:^(YYHomeStatusesResult *result) {193 194 //获取最新的微博数组195 NSArray *newStatuses=result.statuses;196 // 将新数据插入到旧数据的最后面197 [self.statuses addObjectsFromArray:newStatuses];198 // 重新刷新表格199 [self.tableView reloadData];200 // 让刷新控件停止刷新(恢复默认的状态)201 [self.footer endRefreshing];202 } failure:^(NSError *error) {203 YYLog(@"请求失败--%@", error);204 // 让刷新控件停止刷新(恢复默认的状态)205 [self.footer endRefreshing];206 }];207 }208 209 /**210 * 提示用户最新的微博数量211 *212 * @param count 最新的微博数量213 */214 -(void)showNewStatusesCount:(int)count215 {216 //0.清零提醒数字217 [UIApplication sharedApplication].applicationIconBadgeNumber -=self.tabBarItem.badgeValue.intValue;218 self.tabBarItem.badgeValue=http://www.mamicode.com/nil;219 220 //1.创建一个label221 UILabel *label=[[UILabel alloc]init];222 223 //2.设置label的文字224 if (count) {225 label.text=[NSString stringWithFormat:@"共有%d条新的微博数据",count];226 }else227 {228 label.text=@"没有最新的微博数据";229 }230 231 //3.设置label的背景和对其等属性232 label.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageWithName:@"timeline_new_status_background"]];233 label.textAlignment=UITextAlignmentCenter;234 label.textColor=[UIColor whiteColor];235 236 //4.设置label的frame237 label.x=0;238 label.width=self.view.width;239 label.height=35;240 // label.y=64-label.height;241 label.y=self.navigationController.navigationBar.height+20-label.height;242 243 //5.把lable添加到导航控制器的View上244 // [self.navigationController.view addSubview:label];245 //把label添加到导航控制器上,显示在导航栏的下面246 [self.navigationController.view insertSubview:label belowSubview:self.navigationController.navigationBar];247 248 //6.设置动画效果249 CGFloat duration=0.75;250 //设置提示条的透明度251 label.alpha=0.0;252 [UIView animateWithDuration:duration animations:^{253 //往下移动一个label的高度254 label.transform=CGAffineTransformMakeTranslation(0, label.height);255 label.alpha=1.0;256 } completion:^(BOOL finished) {//向下移动完毕257 258 //延迟delay秒的时间后,在执行动画259 CGFloat delay=0.5;260 261 [UIView animateKeyframesWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut animations:^{262 263 //恢复到原来的位置264 label.transform=CGAffineTransformIdentity;265 label.alpha=0.0;266 267 } completion:^(BOOL finished) {268 269 //删除控件270 [label removeFromSuperview];271 }];272 }];273 }274 275 /**276 UIViewAnimationOptionCurveEaseInOut = 0 << 16, // 开始:由慢到快,结束:由快到慢277 UIViewAnimationOptionCurveEaseIn = 1 << 16, // 由慢到块278 UIViewAnimationOptionCurveEaseOut = 2 << 16, // 由快到慢279 UIViewAnimationOptionCurveLinear = 3 << 16, // 线性,匀速280 */281 282 /**设置导航栏内容*/283 -(void)setupNavBar284 {285 self.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_friendsearch" highImageName:@"navigationbar_friendsearch_highlighted" target:self action:@selector(friendsearch)];286 self.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_pop" highImageName:@"navigationbar_pop_highlighted" target:self action:@selector(pop)];287 288 //设置导航栏按钮289 YYTitleButton *titleButton=[[YYTitleButton alloc]init];290 291 //设置尺寸292 // titleButton.width=100;293 titleButton.height=35;294 295 //设置文字296 YYAccountModel *account= [YYAccountTool accountModel];297 NSString *name=account.name;298 NSLog(@"%@",name);299 // name=@"yangye";300 //判断:如果name有值(上一次登录的用户名),那么就使用上次的,如果没有那么就设置为首页301 if (name) {302 [titleButton setTitle:name forState:UIControlStateNormal];303 }else{304 [titleButton setTitle:@"首页" forState:UIControlStateNormal];305 }306 //设置图标307 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal];308 //设置背景309 [titleButton setBackgroundImage:[UIImage resizedImage:@"navigationbar_filter_background_highlighted"] forState:UIControlStateHighlighted];310 311 //设置尺寸312 // titleButton.width=100;313 // titleButton.height=35;314 //监听按钮的点击事件315 [titleButton addTarget:self action:@selector(titleButtonClick:) forControlEvents:UIControlEventTouchUpInside];316 self.navigationItem.titleView=titleButton;317 self.titleButton=titleButton;318 }319 -(void)titleButtonClick:(UIButton *)titleButton320 {321 322 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_up"] forState:UIControlStateNormal];323 324 UITableView *tableView=[[UITableView alloc]init];325 [tableView setBackgroundColor:[UIColor yellowColor]];326 YYPopMenu *menu=[YYPopMenu popMenuWithContentView:tableView];327 [menu showInRect:CGRectMake(60, 55, 200, 200)];328 menu.dimBackground=YES;329 330 menu.arrowPosition=YYPopMenuArrowPositionRight;331 menu.delegate=self;332 }333 334 335 #pragma mark-YYPopMenuDelegate336 //弹出菜单337 -(void)popMenuDidDismissed:(YYPopMenu *)popMenu338 {339 YYTitleButton *titleButton=(YYTitleButton *)self.navigationItem.titleView;340 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal];341 }342 -(void)pop343 {344 YYLog(@"---POP---");345 }346 -(void)friendsearch347 {348 //跳转到one这个子控制器界面349 YYOneViewController *one=[[YYOneViewController alloc]init];350 one.title=@"One";351 //拿到当前控制器352 [self.navigationController pushViewController:one animated:YES];353 354 }355 356 #pragma mark - Table view data source357 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section358 {359 #warning 监听tableView每次显示数据的过程360 //在tableView显示之前,判断有没有数据,如有有数据那么就显示底部视图361 self.footer.hidden=self.statuses.count==0;362 return self.statuses.count;363 }364 365 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath366 {367 static NSString *ID = @"cell";368 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];369 if (!cell) {370 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];371 }372 373 //取出这行对应的微博字典数据,转换为数据模型374 YYStatusModel *status=self.statuses[indexPath.row];375 cell.textLabel.text=status.text;376 cell.detailTextLabel.text=status.user.name;377 NSString *imageUrlStr=status.user.profile_image_url;378 [cell.imageView setImageWithURL:[NSURL URLWithString:imageUrlStr] placeholderImage:[UIImage imageWithName:@"avatar_default_small"]];379 380 return cell;381 }382 383 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath384 {385 //点击cell的时候,跳到下一个界面386 UIViewController *newVc = [[UIViewController alloc] init];387 newVc.view.backgroundColor = [UIColor redColor];388 newVc.title = @"新控制器";389 [self.navigationController pushViewController:newVc animated:YES];390 }391 392 #pragma mark-代理方法393 - (void)scrollViewDidScroll:(UIScrollView *)scrollView394 {395 if (self.statuses.count <= 0 || self.footer.isRefreshing) return;396 397 // 1.差距398 CGFloat delta = scrollView.contentSize.height - scrollView.contentOffset.y;399 // 刚好能完整看到footer的高度400 CGFloat sawFooterH = self.view.height - self.tabBarController.tabBar.height;401 402 // 2.如果能看见整个footer403 if (delta <= (sawFooterH - 0)) {404 // 进入上拉刷新状态405 [self.footer beginRefreshing];406 407 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{408 // 加载更多的微博数据409 [self loadMoreStatuses];410 });411 }412 }413 @end