iOS开发项目篇—34获取用户信息
一、简单说明
需求:获取当前用户的昵称 ,需要获取当前登录用户的个人信息。
查看接口
要求传递的参数
这里要获取的时用户的昵称(所以使用用户id作为参数传入)
二、实现代码
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 //设置导航栏内容 6 [self setupNavBar]; 7 8 //集成刷新控件 9 [self setupRefresh]; 10 11 //设置用户的昵称为标题 12 [self setupUserInfo]; 13 } 14 15 /** 16 *设置用户的昵称为标题 17 */ 18 -(void)setupUserInfo 19 { 20 //1.获得请求管理者 21 AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; 22 23 //2.封装请求参数 24 NSMutableDictionary *params=[NSMutableDictionary dictionary]; 25 params[@"access_token"] =[YYAccountTool accountModel].access_token; 26 params[@"uid"]=[YYAccountTool accountModel].uid; 27 28 //3.发送Get请求 29 [mgr GET:@"https://api.weibo.com/2/users/show.json" parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*userDict) { 30 31 //字典转模型 32 YYUserModel *user=[YYUserModel objectWithKeyValues:userDict]; 33 //设置标题 34 [self.titleButton setTitle:user.name forState:UIControlStateNormal]; 35 36 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 37 38 }]; 39 }
显示效果:
新的问题:用户的昵称过长,导致在标题显示的时候出现问题。
三、完善
解决思路:可以根据用户的昵称(字体的长度)来设置标题按钮的实际宽度。而不是使用一个固定的值。
实现效果:
注意点:注意需要调整设置按钮宽度和高度值的代码在代码段中的位置,如果在[titleButton setTitle:@"首页" forState:UIControlStateNormal];之后再进行设置,那么self.height的值为0。
YYTitleButton.m文件
1 // 2 // YYTitleButton.m 3 // 4 5 #import "YYTitleButton.h" 6 7 @implementation YYTitleButton 8 9 - (id)initWithFrame:(CGRect)frame 10 { 11 self = [super initWithFrame:frame]; 12 if (self) { 13 //设置图片居中 14 self.imageView.contentMode=UIViewContentModeCenter; 15 //当高亮的时候,不调整图片 16 self.adjustsImageWhenHighlighted=NO; 17 //设置文字对齐方式为右对齐 18 self.titleLabel.textAlignment=NSTextAlignmentRight; 19 //设置文字颜色为黑色 20 [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 21 //设置文字的字体为统一的20号字体 22 self.titleLabel.font=YYNavigationTitleFont; 23 } 24 return self; 25 } 26 27 //设置内部图标的frame 28 -(CGRect)imageRectForContentRect:(CGRect)contentRect 29 { 30 CGFloat imageY=0; 31 CGFloat imageW=self.height; 32 CGFloat imageH=imageW; 33 CGFloat imageX=self.width-imageW; 34 return CGRectMake(imageX, imageY, imageW, imageH); 35 36 } 37 //设置内部文字的frame 38 -(CGRect)titleRectForContentRect:(CGRect)contentRect 39 { 40 CGFloat titleY=0; 41 CGFloat titleX=0; 42 CGFloat titleH=self.height; 43 //图片为正方形 44 CGFloat titleW=self.width-self.height; 45 return CGRectMake(titleX, titleY, titleW, titleH); 46 } 47 48 //设置title的宽度 49 -(void)setTitle:(NSString *)title forState:(UIControlState)state 50 { 51 [super setTitle:title forState:state]; 52 53 //计算文字的尺寸 54 CGSize titleSize=[title sizeWithFont:self.titleLabel.font]; 55 56 //计算按钮的宽度 57 //整个标题按钮的宽度=用户昵称文字的宽度+图片的宽度+10个间距 58 self.width=titleSize.width+self.height+10; 59 } 60 @end
先显示首页标题,延迟两秒之后变换成用户昵称
1 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 2 3 [self setupUserInfo]; 4 5 });
把获取的用户昵称保存起来,下次登录的时候直接使用即可。
在账号(YYAccountModel)模型中添加一个name属性,用来保存获取的用户昵称,注意需要归档等也需要修改。
YYAccountModel.h文件
1 // 2 // YYAccountModel.h 3 // 4 5 #import <Foundation/Foundation.h> 6 7 @interface YYAccountModel : NSObject <NSCoding> 8 /**access_token string 用于调用access_token,接口获取授权后的access token。*/ 9 @property(nonatomic,copy)NSString *access_token; 10 11 /**expires_in string access_token的生命周期,单位是秒数。*/ 12 @property(nonatomic,copy)NSString *expires_in; 13 14 /**uid string 当前授权用户的UID。*/ 15 @property(nonatomic,copy)NSString *uid; 16 17 /** 18 *expires_time nsdate access_token的过期时间。 19 */ 20 @property(nonatomic,copy)NSDate *expires_time; 21 22 /** string 用户昵称*/ 23 @property(nonatomic,copy)NSString *name; 24 25 +(instancetype)accountModelWithDcit:(NSDictionary *)dict; 26 @end
YYAccountModel.m文件
1 // 2 // YYAccountModel.m 3 // 4 5 #import "YYAccountModel.h" 6 7 @implementation YYAccountModel 8 +(instancetype)accountModelWithDcit:(NSDictionary *)dict 9 { 10 //注意,json中返回的数据和model中的成员属性不对应,因此不能直接使用KVC 11 YYAccountModel *model=[[self alloc]init]; 12 model.access_token=dict[@"access_token"]; 13 model.expires_in=dict[@"expires_in"]; 14 model.uid=dict[@"uid"]; 15 16 //确定账号的过期时间= 账号创建的时间 + 有效期 17 NSDate *now=[NSDate date]; 18 model.expires_time=[now dateByAddingTimeInterval:model.expires_in.doubleValue]; 19 return model; 20 } 21 22 /** 23 *从文件中解析出一个对象的时候调用 24 *在这个方法中写清楚:怎么解析文件中的数据 25 */ 26 -(id)initWithCoder:(NSCoder *)aDecoder 27 { 28 if (self=[super init]) { 29 self.access_token=[aDecoder decodeObjectForKey:@"access_token"]; 30 self.expires_in=[aDecoder decodeObjectForKey:@"expires_in"]; 31 self.uid=[aDecoder decodeObjectForKey:@"uid"]; 32 self.expires_time=[aDecoder decodeObjectForKey:@"expires_time"]; 33 self.name=[aDecoder decodeObjectForKey:@"name"]; 34 } 35 return self; 36 } 37 38 /** 39 *将对象写入到文件中的时候调用 40 *在这个方法中写清楚:要存储哪些对象的哪些属性,以及怎样存储属性 41 */ 42 -(void)encodeWithCoder:(NSCoder *)aCoder 43 { 44 [aCoder encodeObject:self.access_token forKey:@"access_token"]; 45 [aCoder encodeObject:self.expires_in forKey:@"expires_in"]; 46 [aCoder encodeObject:self.uid forKey:@"uid"]; 47 [aCoder encodeObject:self.expires_time forKey:@"expires_time"]; 48 [aCoder encodeObject:self forKey:@"name"]; 49 } 50 @end
在首页设置标题的时候进行判断,如果用户的昵称已经存在,那么就使用已经保存到模型中的用户昵称,如果不存在则可以先设置为“首页”,之后读取昵称之后,再进行设置。
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 18 @interface YYHomeTableViewController ()<YYPopMenuDelegate> 19 @property(nonatomic,assign)BOOL down; 20 @property(nonatomic,strong)NSMutableArray *statuses; 21 @property(nonatomic,strong)YYloadStatusesFooter *footer; 22 @property(nonatomic,strong) YYTitleButton *titleButton; 23 @end 24 25 @implementation YYHomeTableViewController 26 27 #pragma mark- 懒加载 28 -(NSMutableArray *)statuses 29 { 30 if (_statuses==nil) { 31 _statuses=[NSMutableArray array]; 32 } 33 return _statuses; 34 } 35 - (void)viewDidLoad 36 { 37 [super viewDidLoad]; 38 39 //设置导航栏内容 40 [self setupNavBar]; 41 42 //集成刷新控件 43 [self setupRefresh]; 44 45 //设置用户的昵称为标题 46 //先显示首页标题,延迟两秒之后变换成用户昵称 47 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 48 [self setupUserInfo]; 49 }); 50 } 51 52 /** 53 *设置用户的昵称为标题 54 */ 55 -(void)setupUserInfo 56 { 57 //1.获得请求管理者 58 AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; 59 60 //2.封装请求参数 61 NSMutableDictionary *params=[NSMutableDictionary dictionary]; 62 params[@"access_token"] =[YYAccountTool accountModel].access_token; 63 params[@"uid"]=[YYAccountTool accountModel].uid; 64 65 //3.发送Get请求 66 [mgr GET:@"https://api.weibo.com/2/users/show.json" parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*userDict) { 67 68 //字典转模型 69 YYUserModel *user=[YYUserModel objectWithKeyValues:userDict]; 70 71 //设置标题 72 [self.titleButton setTitle:user.name forState:UIControlStateNormal]; 73 // 存储账号信息(需要先拿到账号) 74 YYAccountModel *account=[YYAccountTool accountModel]; 75 account.name=user.name; 76 //存储 77 [YYAccountTool save:account]; 78 79 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 80 81 }]; 82 } 83 84 //集成刷新控件 85 -(void)setupRefresh 86 { 87 // 1.添加下拉刷新控件 88 UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; 89 [self.tableView addSubview:refreshControl]; 90 91 //2.监听状态 92 [refreshControl addTarget:self action:(@selector(refreshControlStateChange:)) forControlEvents:UIControlEventValueChanged]; 93 94 //3.让刷新控件自动进入到刷新状态 95 [refreshControl beginRefreshing]; 96 97 //4.手动调用方法,加载数据 98 //模拟网络延迟,延迟2.0秒 99 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 100 [self refreshControlStateChange:refreshControl]; 101 }); 102 103 //5.上拉刷新数据 104 YYloadStatusesFooter *footer=[YYloadStatusesFooter loadFooter]; 105 self.tableView.tableFooterView=footer; 106 self.footer=footer; 107 } 108 109 /** 110 * 当下拉刷新控件进入刷新状态(转圈圈)的时候会自动调用 111 */ 112 -(void)refreshControlStateChange:(UIRefreshControl *)refreshControl 113 { 114 //1.获得请求管理者 115 AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; 116 117 //2.封装请求参数 118 NSMutableDictionary *params=[NSMutableDictionary dictionary]; 119 params[@"access_token"] =[YYAccountTool accountModel].access_token; 120 //取出当前微博模型中的第一条数据,获取第一条数据的id 121 YYStatusModel *firstStatus=[self.statuses firstObject]; 122 if (firstStatus) { 123 params[@"since_id"]=firstStatus.idstr; 124 } 125 126 //3.发送Get请求 127 [mgr GET:@"https://api.weibo.com/2/statuses/home_timeline.json" parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*accountDict) { 128 // 微博字典 -- 数组 129 NSArray *statusDictArray = accountDict[@"statuses"]; 130 //微博字典数组---》微博模型数组 131 NSArray *newStatuses =[YYStatusModel objectArrayWithKeyValuesArray:statusDictArray]; 132 133 //把新数据添加到旧数据的前面 134 NSRange range=NSMakeRange(0, newStatuses.count); 135 NSIndexSet *indexSet=[NSIndexSet indexSetWithIndexesInRange:range]; 136 [self.statuses insertObjects:newStatuses atIndexes:indexSet]; 137 YYLog(@"刷新了--%d条新数据",newStatuses.count); 138 139 //重新刷新表格 140 [self.tableView reloadData]; 141 //让刷新控件停止刷新(回复默认的状态) 142 [refreshControl endRefreshing]; 143 144 [self showNewStatusesCount:newStatuses.count]; 145 146 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 147 YYLog(@"请求失败"); 148 //让刷新控件停止刷新(回复默认的状态) 149 [refreshControl endRefreshing]; 150 }]; 151 152 } 153 154 /** 155 * 加载更多的微博数据 156 */ 157 - (void)loadMoreStatuses 158 { 159 // 1.获得请求管理者 160 AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; 161 162 // 2.封装请求参数 163 NSMutableDictionary *params = [NSMutableDictionary dictionary]; 164 params[@"access_token"] = [YYAccountTool accountModel].access_token; 165 YYStatusModel *lastStatus = [self.statuses lastObject]; 166 if (lastStatus) { 167 // max_id false int64 若指定此参数,则返回ID小于或等于max_id的微博,默认为0。 168 params[@"max_id"] = @([lastStatus.idstr longLongValue] - 1); 169 } 170 171 // 3.发送GET请求 172 [mgr GET:@"https://api.weibo.com/2/statuses/home_timeline.json" parameters:params 173 success:^(AFHTTPRequestOperation *operation, NSDictionary *resultDict) { 174 // 微博字典数组 175 NSArray *statusDictArray = resultDict[@"statuses"]; 176 // 微博字典数组 ---> 微博模型数组 177 NSArray *newStatuses = [YYStatusModel objectArrayWithKeyValuesArray:statusDictArray]; 178 179 // 将新数据插入到旧数据的最后面 180 [self.statuses addObjectsFromArray:newStatuses]; 181 182 // 重新刷新表格 183 [self.tableView reloadData]; 184 185 // 让刷新控件停止刷新(恢复默认的状态) 186 [self.footer endRefreshing]; 187 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 188 YYLog(@"请求失败--%@", error); 189 // 让刷新控件停止刷新(恢复默认的状态) 190 [self.footer endRefreshing]; 191 }]; 192 } 193 194 /** 195 * 提示用户最新的微博数量 196 * 197 * @param count 最新的微博数量 198 */ 199 -(void)showNewStatusesCount:(int)count 200 { 201 //1.创建一个label 202 UILabel *label=[[UILabel alloc]init]; 203 204 //2.设置label的文字 205 if (count) { 206 label.text=[NSString stringWithFormat:@"共有%d条新的微博数据",count]; 207 }else 208 { 209 label.text=@"没有最新的微博数据"; 210 } 211 212 //3.设置label的背景和对其等属性 213 label.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageWithName:@"timeline_new_status_background"]]; 214 label.textAlignment=UITextAlignmentCenter; 215 label.textColor=[UIColor whiteColor]; 216 217 //4.设置label的frame 218 label.x=0; 219 label.width=self.view.width; 220 label.height=35; 221 // label.y=64-label.height; 222 label.y=self.navigationController.navigationBar.height+20-label.height; 223 224 //5.把lable添加到导航控制器的View上 225 // [self.navigationController.view addSubview:label]; 226 //把label添加到导航控制器上,显示在导航栏的下面 227 [self.navigationController.view insertSubview:label belowSubview:self.navigationController.navigationBar]; 228 229 //6.设置动画效果 230 CGFloat duration=0.75; 231 //设置提示条的透明度 232 label.alpha=0.0; 233 [UIView animateWithDuration:duration animations:^{ 234 //往下移动一个label的高度 235 label.transform=CGAffineTransformMakeTranslation(0, label.height); 236 label.alpha=1.0; 237 } completion:^(BOOL finished) {//向下移动完毕 238 239 //延迟delay秒的时间后,在执行动画 240 CGFloat delay=0.5; 241 242 [UIView animateKeyframesWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut animations:^{ 243 244 //恢复到原来的位置 245 label.transform=CGAffineTransformIdentity; 246 label.alpha=0.0; 247 248 } completion:^(BOOL finished) { 249 250 //删除控件 251 [label removeFromSuperview]; 252 }]; 253 }]; 254 } 255 256 /** 257 UIViewAnimationOptionCurveEaseInOut = 0 << 16, // 开始:由慢到快,结束:由快到慢 258 UIViewAnimationOptionCurveEaseIn = 1 << 16, // 由慢到块 259 UIViewAnimationOptionCurveEaseOut = 2 << 16, // 由快到慢 260 UIViewAnimationOptionCurveLinear = 3 << 16, // 线性,匀速 261 */ 262 263 /**设置导航栏内容*/ 264 -(void)setupNavBar 265 { 266 self.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_friendsearch" highImageName:@"navigationbar_friendsearch_highlighted" target:self action:@selector(friendsearch)]; 267 self.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_pop" highImageName:@"navigationbar_pop_highlighted" target:self action:@selector(pop)]; 268 269 //设置导航栏按钮 270 YYTitleButton *titleButton=[[YYTitleButton alloc]init]; 271 272 //设置尺寸 273 // titleButton.width=100; 274 titleButton.height=35; 275 276 //设置文字 277 YYAccountModel *account= [YYAccountTool accountModel]; 278 NSString *name=account.name; 279 NSLog(@"%@",name); 280 // [email protected]"yangye"; 281 //判断:如果name有值(上一次登录的用户名),那么就使用上次的,如果没有那么就设置为首页 282 if (name) { 283 [titleButton setTitle:name forState:UIControlStateNormal]; 284 }else{ 285 [titleButton setTitle:@"首页" forState:UIControlStateNormal]; 286 } 287 //设置图标 288 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal]; 289 //设置背景 290 [titleButton setBackgroundImage:[UIImage resizedImage:@"navigationbar_filter_background_highlighted"] forState:UIControlStateHighlighted]; 291 292 //设置尺寸 293 // titleButton.width=100; 294 // titleButton.height=35; 295 //监听按钮的点击事件 296 [titleButton addTarget:self action:@selector(titleButtonClick:) forControlEvents:UIControlEventTouchUpInside]; 297 self.navigationItem.titleView=titleButton; 298 self.titleButton=titleButton; 299 } 300 -(void)titleButtonClick:(UIButton *)titleButton 301 { 302 303 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_up"] forState:UIControlStateNormal]; 304 305 UITableView *tableView=[[UITableView alloc]init]; 306 [tableView setBackgroundColor:[UIColor yellowColor]]; 307 YYPopMenu *menu=[YYPopMenu popMenuWithContentView:tableView]; 308 [menu showInRect:CGRectMake(60, 55, 200, 200)]; 309 menu.dimBackground=YES; 310 311 menu.arrowPosition=YYPopMenuArrowPositionRight; 312 menu.delegate=self; 313 } 314 315 316 #pragma mark-YYPopMenuDelegate 317 //弹出菜单 318 -(void)popMenuDidDismissed:(YYPopMenu *)popMenu 319 { 320 YYTitleButton *titleButton=(YYTitleButton *)self.navigationItem.titleView; 321 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal]; 322 } 323 -(void)pop 324 { 325 YYLog(@"---POP---"); 326 } 327 -(void)friendsearch 328 { 329 //跳转到one这个子控制器界面 330 YYOneViewController *one=[[YYOneViewController alloc]init]; 331 one.title=@"One"; 332 //拿到当前控制器 333 [self.navigationController pushViewController:one animated:YES]; 334 335 } 336 337 #pragma mark - Table view data source 338 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 339 { 340 #warning 监听tableView每次显示数据的过程 341 //在tableView显示之前,判断有没有数据,如有有数据那么就显示底部视图 342 self.footer.hidden=self.statuses.count==0; 343 return self.statuses.count; 344 } 345 346 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 347 { 348 static NSString *ID = @"cell"; 349 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 350 if (!cell) { 351 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 352 } 353 354 //取出这行对应的微博字典数据,转换为数据模型 355 YYStatusModel *status=self.statuses[indexPath.row]; 356 cell.textLabel.text=status.text; 357 cell.detailTextLabel.text=status.user.name; 358 NSString *imageUrlStr=status.user.profile_image_url; 359 [cell.imageView setImageWithURL:[NSURL URLWithString:imageUrlStr] placeholderImage:[UIImage imageWithName:@"avatar_default_small"]]; 360 361 return cell; 362 } 363 364 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 365 { 366 //点击cell的时候,跳到下一个界面 367 UIViewController *newVc = [[UIViewController alloc] init]; 368 newVc.view.backgroundColor = [UIColor redColor]; 369 newVc.title = @"新控制器"; 370 [self.navigationController pushViewController:newVc animated:YES]; 371 } 372 373 #pragma mark-代理方法 374 - (void)scrollViewDidScroll:(UIScrollView *)scrollView 375 { 376 if (self.statuses.count <= 0 || self.footer.isRefreshing) return; 377 378 // 1.差距 379 CGFloat delta = scrollView.contentSize.height - scrollView.contentOffset.y; 380 // 刚好能完整看到footer的高度 381 CGFloat sawFooterH = self.view.height - self.tabBarController.tabBar.height; 382 383 // 2.如果能看见整个footer 384 if (delta <= (sawFooterH - 0)) { 385 // 进入上拉刷新状态 386 [self.footer beginRefreshing]; 387 388 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 389 // 加载更多的微博数据 390 [self loadMoreStatuses]; 391 }); 392 } 393 } 394 @end
错误提示:name
iOS开发项目篇—34获取用户信息,布布扣,bubuko.com
时间: 2024-08-02 11:02:32