100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 山寨新浪微博客户端与新浪微博API调用的总结

山寨新浪微博客户端与新浪微博API调用的总结

时间:2024-03-26 01:09:51

相关推荐

山寨新浪微博客户端与新浪微博API调用的总结

这次是我第一次写的项目总结,虽然这只是一个小项目,但确实是获益良多。虽然说是独立完成,但其实在做的过程中,也有和大家交流了很多意见。尽管如此,我对这个尚不能算写好的项目,还是有非常多的不满意。不过碍于能力有限,不满意的地方也就先将就将就。日后有兴趣的话,肯定会再次改进,完善得更好。

项目的主要内容就是用Xcode写出一个具有基本功能的iPhone新浪微博客户端,其中必不可少地需要调用新浪微博应用的API,途中遇到的“难题”也不少,不过大部分都算解决了。

一、获取用户Access Token

一开始的第一个麻烦,由于微博使用OAuth2.0的授权方式,主要流程是去指定的网页,在用户输入账号和密码授权后,获取回调网页地址上的Access Token。往后对API的调用,全部都是通过Access Token来进行身份认证,一个Access Token对应一个应用和一个用户,都是唯一的。具体新建微博应用的过程,我也不多说,主要就对调用API获取Access Token进行说明。

/wiki/Oauth2 这里已经有基本的说明,我主要调用的是“Javascript Client的验证授权”,因为返回的地址里已经包含了Access Token,不需要二次调用。我在UIViewController上面拉了一个UIWebView,UIWebView用了Outlet。

代码如下:

1 - (void) viewDidAppear:(BOOL)animated2 {3NSString *urlStr = [[NSString alloc] initWithFormat:@"%@?client_id=%@&redirect_uri=%@&response_type=token&display=%@", AuthorizeUrl, AppKey, RedirectUri, DisplayMode];45NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]];6[accessWebView loadRequest:request];7accessWebView.delegate = self;8 }

其中AuthorizeUrl为

#define AuthorizeUrl @"/oauth2/authorize"

AppKey可以在“应用信息”找到,不过RedirectUri必须和自己在应用中填写的网址一样,否则会出错。

然后,等用户授权完,就要判断网址是否有我们需要的Access Token,有的话再进行下一步。这里就要用到<UIWebViewDelegate>协议,来使用方法webViewDidFinishLoad,

1 - (void)webViewDidFinishLoad:(UIWebView *)webView 2 { 3NSURL *url = [webView.request URL]; 45if ([url.lastPathComponent isEqualToString:CmpUrl]) { 6 tokenData *tmp = [self.userToken initWithUrl:url]; 7 if (tmp != nil) { 8 self.userToken = tmp; 9 [self.userToken saveToken];10 [self performSegueWithIdentifier:@"FirstView" sender:nil];11 } else {12 [webView goBack];13 }14}

我在这里封装了几个方法,saveToken是用plist进行保存token的方法,用于后续登陆免输密码,这里先跳过。主要是[url.lastPathComponent isEqualToString:CmpUrl],由于请求用户授权时,加载完成后也会调用webViewDidFinishLoad,所以必须判断Access Token出现了没有。如果去到了回调网址“/oauth2/default.html”,则url.lastPathComponent为“default.html”。根据这点再提取Access Token,具体方法就是用NSString的方法去提取URL里Access Token的位置。不过我也做了一个错误处理,以防用户按了“取消”后,程序就“无处可点”。所以如果页面网址类似“/oauth2/default.html#error_uri=%2Foauth2%2Fauthorize”,就重新返回授权的页面。(好吧,我承认我有点猥琐)

具体initWithUrl的方法

1 - (id) initWithUrl:(NSURL *)url 2 { 3if (self = [super init]) { 4 NSString *urlStr = [url absoluteString]; 5 NSArray *strarr = [urlStr componentsSeparatedByString:@"&"]; 67 if ([[strarr objectAtIndex:0] isEqualToString:ErrUrl]) { 8 NSLog(@"Error!!\n"); 9 return nil;10 } else {11 NSString *tmpToken = [[strarr objectAtIndex:0] substringFromIndex:55];12 NSString *tmpUid = [[strarr objectAtIndex:3] substringFromIndex:4];13 14 NSDictionary *tmpDic = [weiboUrl weiboAPIUserShowWithToken:tmpToken andUid:tmpUid OrScreenName:nil];15 16 self.token = tmpToken;17 self.uid = tmpUid;18 self.userName = [tmpDic objectForKey:@"name"];19 }20}2122return self;23 }

新浪微博的API又被我封装到另一个类weiboUrl中,其中weiboAPIUserShowWithToken: andUid: OrScreenName:就是返回用户个人资料字典的一个类方法。

1 + (NSDictionary *)weiboAPIUserShowWithToken:(NSString *)token andUid:(NSString *)uid OrScreenName:(NSString *)screenname 2 { 3NSError *error; 4NSString *urlstr; 5if (!screenname) 6 urlstr = [NSString stringWithFormat:@"%@?access_token=%@&uid=%@", UserShow, token, uid]; 7else 8 urlstr = [NSString stringWithFormat:@"%@?access_token=%@&screen_name=%@", UserShow, token, [screenname stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 910NSURL *url = [[NSURL alloc]initWithString:urlstr];11NSData* data = [NSData dataWithContentsOfURL: url];12NSDictionary *returnDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];1314return returnDic;15 }

由于新浪微博返回的都是JSON数据,所以可以直接用NSJSONSerialization的方法进行编码。

二、调用API和处理数据

微博API众多,如果每次都要打一次API,查错的时候必定非常麻烦。所以我就封装了几个常用的API。

1 //以下是封装WeiboAPI的方法 2 3 //根据用户ID获取用户信息,返回NSDictionary类型的数据 4 + (NSDictionary *) weiboAPIUserShowWithToken:(NSString *)token andUid:(NSString *)uid OrScreenName:(NSString *)screenname; 5 6 //获取当前登录用户及其所关注用户的最新微博,返回其微博的NSMutableArray数组,可指定参数since_id, max_id, count,对应即比since_id时间晚的微博, 7 //小于或等于max_id的微博,单页返回的记录条数 8 + (NSMutableArray *) weiboAPIHomeTimeLineWithToken:(NSString *)token andSinceid:(NSString *)sinceid andMaxid:(NSString *)maxid andCount:(NSString *)count; 9 10 //测试status的汉字数是否超过140个11 + (BOOL) testStatusLengthWithString:(NSString *)sourceString;12 13 //发布一条新微博14 + (NSDictionary *) weiboAPIUpdateStatusesWithToken:(NSString *)token andStatus:(NSString *)status andLat:(float)latitude andLong:(float)longtitude;15 16 //对一条微博进行评论17 + (NSDictionary *) weiboAPICreateCommentsWithToken:(NSString *)token andComment:(NSString *)comment andID:(NSString *)ID andCommentori:(int)comment_ori;18 19 //转发一条微博20 + (NSDictionary *) weiboAPIRepostStatusesWithToken:(NSString *)token andStatus:(NSString *)status andID:(NSString *)ID andIscomment:(int)is_comment;21 22 //添加一条微博到收藏里23 + (NSDictionary *) weiboAPICreateFavouritesWithToken:(NSString *)token andID:(NSString *)ID;24 25 //根据微博ID返回某条微博的评论列表26 + (NSMutableArray *) weiboAPICommentsShowWithToken:(NSString *)token andSinceid:(NSString *)sinceid andMaxid:(NSString *)maxid andCount:(NSString *)count andID:(NSString *)ID;27 28 //获取当前登录用户所接收到的评论列表29 + (NSMutableArray *) weiboAPICommentsToMeWithToken:(NSString *)token andSinceid:(NSString *)sinceid andMaxid:(NSString *)maxid andCount:(NSString *)count;30 31 //获取最新的提到登录用户的微博列表,即@我的微博32 + (NSMutableArray *) weiboAPIStatusesMentionsWithToken:(NSString *)token andSinceid:(NSString *)sinceid andMaxid:(NSString *)maxid andCount:(NSString *)count;33 34 //回复一条评论35 + (NSDictionary *) weiboAPICommentsReplyWithToken:(NSString *)token andComment:(NSString *)comment andID:(NSString *)ID andCID:(NSString *)CID;36 37 //获取当前登录用户的收藏列表38 + (NSMutableArray *) weiboAPIFavouritesWithToken:(NSString *)token andCount:(int)count andPage:(int)page;

不过,这里不得说一下,说来惭愧,我有很多的API都未严格按照新浪给出的类型封装,很多都直接使用NSString类型。由于赶时间所以这么做,但其实严格按照类型封装会更好,我后面还会提到为什么这样说。

封装好API以后,每次就不用复制、粘贴一大段新浪API,而且可读性相对好了点。不过由于,这类API我都只是对数据进行了一点“粗加工”,使用起来还不方便(因为返回的要么是NSDictionary类型,要么就是NSMutableArray,里面也是NSDictionary)。所以还要再将数据再封装一次,说到这里,我又惭愧了,因为我将评论和微博等都全封装成同一个类型。如果科学点,其实也是要分开的。我封装的类大概有这些属性

1 @property (strong, nonatomic) NSString *ID; 2 @property (strong, nonatomic) NSString *SID; 3 @property (strong, nonatomic) NSString *text; 4 @property (strong, nonatomic) NSString *source; 5 @property (strong, nonatomic) NSString *time; 6 @property (strong, nonatomic) NSString *userName; 7 8 @property (strong, nonatomic) NSURL *originalPicURL; 9 @property (strong, nonatomic) NSURL *bmiddlePicURL;10 @property (strong, nonatomic) NSURL *profileImageURL;11 @property (strong, nonatomic) NSURL *largeImageURL;12 13 @property (strong, nonatomic) UIImage *profileImage;14 @property (strong, nonatomic) UIImage *largeImage;15 @property (strong, nonatomic) UIImage *bmiddleImage;16 17 @property (strong, nonatomic) NSString *retweetName;18 @property (strong, nonatomic) NSString *retweetText;

里面还封装了用字典初始化属性各个值的方法

+ (weiboCellData *) weiboCellDataWithSourceDictionary: (NSDictionary *)sourceDictionary

最后再新建一个NSMutableArray的类别来生成全部weiCellData类型的数组,这个就不多说了。

下一步在首页的ControllerviewDidLoad方法

self.cellsDataArray = [NSMutableArray weiboCellDataArrayWithSourceArray:[weiboUrl weiboAPIHomeTimeLineWithToken:self.userToken.token andSinceid:@"0" andMaxid:@"0" andCount:@"50"]];

这样,tableView所有Cell的内容就都已经有了,接下来就是处理Cell内容的排列。由于微博博文长短不一,所以高度必须要为每一个Cell进行特别的设置。

1 static NSString *CellIdentifier = @"weiboCell"; 23UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 4if (cell == nil) { 5 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; 6} 789weiboCellData *myCell = [self.cellsDataArray objectAtIndex:indexPath.row];10UILabel *cellName = (UILabel *)[cell viewWithTag:1];11UILabel *cellText = (UILabel *)[cell viewWithTag:2];12UILabel *cellRetweet = (UILabel *)[cell viewWithTag:3];13UIImageView *cellImage = (UIImageView *)[cell viewWithTag:4];141516cellName.text = myCell.userName;17cellText.text = myCell.text;1819//设置原文的label高度20CGSize constraint = CGSizeMake(cellText.frame.size.width, 20000.0f);21CGSize textSize = [cellText.text sizeWithFont:[UIFont systemFontOfSize:14.0] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];22[cellText setFrame:CGRectMake(cellText.frame.origin.x, cellText.frame.origin.y, cellText.frame.size.width, textSize.height)];232425if (myCell.retweetText != nil) {26 cellRetweet.text = [NSString stringWithFormat:@"%@:%@", myCell.retweetName, myCell.retweetText];27 //设置转发文的高度28 constraint = CGSizeMake(cellRetweet.frame.size.width, 20000.0f);29 CGSize retweetSize = [cellRetweet.text sizeWithFont:[UIFont systemFontOfSize:14.0] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];30 [cellRetweet setFrame:CGRectMake(cellRetweet.frame.origin.x, cellText.frame.origin.y + textSize.height + frameGap, cellRetweet.frame.size.width, retweetSize.height)];31} else32 [cellRetweet setFrame:CGRectMake(cellRetweet.frame.origin.x, cellText.frame.origin.y + textSize.height + frameGap, cellRetweet.frame.size.width, 0)];

其中frameGap = 5.0,textSize主要为获取一个系统字体为14的合适label大小,再通过setFrame,就可以设置好原文的label。下面转发文的原理基本一样,不过需要判断一下是否有转发和修改一下origin。另外还要重载tableView的一个方法,

1 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 2 { 3static NSString *CellIdentifier = @"weiboCell"; 45UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 6if (cell == nil) { 7 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; 8} 910UILabel *cellText = (UILabel *)[cell viewWithTag:2];11UILabel *cellRetweet = (UILabel *)[cell viewWithTag:3];12weiboCellData *myCell = [self.cellsDataArray objectAtIndex:indexPath.row];1314CGSize constraint = CGSizeMake(cellText.frame.size.width, 20000.0f);15CGSize textSize = [myCell.text sizeWithFont:[UIFont systemFontOfSize:14.0] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];1617cellRetweet.text = [NSString stringWithFormat:@"%@:%@", myCell.retweetName, myCell.retweetText];18constraint = CGSizeMake(cellRetweet.frame.size.width, 20000.0f);19CGSize retweetSize = [cellRetweet.text sizeWithFont:[UIFont systemFontOfSize:14.0] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];if (myCell.retweetText != nil)22 return (43.0 + textSize.height + 3 * frameGap + retweetSize.height);23else24 return (43.0 + textSize.height + 2 * frameGap);25 }

这段也不需要解释,和之前差不多,这种写法的好处是可以先在storyboard设置好custom的Cell调整好位置,最后才在代码匹配高度。就算以后改变Cell的位置,代码也基本不用改,在storyboard那里改动就好。原本我想直接在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath设置Cell的大小,不过都失败了。还没有知道什么原因,知道的话,能告诉我一下么。

至于cellImage就用GCD异步下载,我也并不是很熟悉其中的用法。而且我的程序刚开始也出现了一个关键的问题,当滑动速度非常快的时候,头像会出现闪动和错误,不过这个问题总算解决了。

1dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 23if (myCell.profileImage) { 4 cellImage.image = myCell.profileImage; 5} else if ([self.imageDic objectForKey:myCell.userName]) { 6 cellImage.image = [self.imageDic objectForKey:myCell.userName]; 7 myCell.profileImage = cellImage.image; 8} else { 9 dispatch_async(concurrentQueue, ^{10 11 dispatch_sync(concurrentQueue, ^{12 //for (int i = 0; i < 100000000; i++);/*模拟长时间下载*/13 [myCell downloadProfileImage];14 if (myCell.profileImage)15 [self.imageDic setObject:myCell.profileImage forKey:myCell.userName];16 });17 18 dispatch_sync(dispatch_get_main_queue(), ^{19 cellImage.image = [self.imageDic objectForKey:cellName.text];20 });21 });22}

由于我不想每次都使用字典这种比较耗时的操作,所以尽可能使用属性来读取头像。具体思路很简单,就是先查看Cell对应的数组属性profileImage有没下载好的头像,没有就去Controller的字典imageDic,根据cellName来寻找,并将对应的数组元素赋值。由于cellName相同的,头像必相同,所以可以通过这一点减少重复头像的下载。如果依然没有,那就只能够下载了,这里使用了一个异步里面包含了两个同步,头像下载好后,再根据cellName来对cellImage赋值。这样做,就可以防止跳图的现象产生。另外NSMutableDictionary不可以添加nil,所以添加前必须进行一次简单的判断。此外,我又做了一个很猥琐的设计,将存放头像的字典改为全局静态变量。因此其他Controller都可以在加载完成后,立即匹配头像,再一次跳过下载重复头像。其实这么做主要是为了应对低网速下的环境,如果每次都重复下载头像,体验肯定会大打折扣。

微博必不可少的刷新,我也实现了,不过并不是单纯的刷新,属于增量加载。判断一下比已加载的最新一条微博还要新的微博是否达到50条,如果超过就直接替换原数组,否则就将原数组加在新数组后面。这样就不会错过任何的微博,而且刷新卡顿时间短一些,毕竟大多数情况下都不会有达到50条的新微博,而且可以减少加载后面更多微博的压力。不过,内存会使用得更多,也有不足。

1 - (IBAction)refreshButton:(UIBarButtonItem *)sender { 2NSString *tmpSinceid = [[self.cellsDataArray objectAtIndex:0] ID]; 3__block NSMutableArray *refreshDataArray; 45dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 6 refreshDataArray = [NSMutableArray weiboCellDataArrayWithSourceArray:[weiboUrl weiboAPIHomeTimeLineWithToken:self.userToken.token andSinceid:tmpSinceid andMaxid:@"0" andCount:@"50"]]; 7 dispatch_async(dispatch_get_main_queue(), ^{ 8 9 if ([refreshDataArray count]) {10 if ([refreshDataArray count] >= 50) {11 self.cellsDataArray = refreshDataArray;12 } else {13 [refreshDataArray addObjectsFromArray:self.cellsDataArray];14 self.cellsDataArray = refreshDataArray;15 }16 }17 18 [self.tableView reloadData];19 });20});21 }

然后“查看更多”的按键也是类似的做法。不过由于我封装API的时候,把max_id也改成NSString,所以在加载好后面微博的时候,还要把第一条重复的微博删掉,真的很马虎。由于微博的API我都封装了,这里没有看到具体实现。其实微博API就GET和POST两种调用方法,GET是获取数据的时候用,POST是发送数据,下面我会举两个具体的例子。

三、发微博和需要注意的小细节

GET方法

1 + (NSDictionary *)weiboAPIUserShowWithToken:(NSString *)token andUid:(NSString *)uid OrScreenName:(NSString *)screenname 2 { 3NSError *error; 4NSString *urlstr; 5if (!screenname) 6 urlstr = [NSString stringWithFormat:@"%@?access_token=%@&uid=%@", UserShow, token, uid]; 7else 8 urlstr = [NSString stringWithFormat:@"%@?access_token=%@&screen_name=%@", UserShow, token, [screenname stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 910NSURL *url = [[NSURL alloc]initWithString:urlstr];11NSData* data = [NSData dataWithContentsOfURL: url];12NSDictionary *returnDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];1314return returnDic;15 }

POST方法

1 + (NSDictionary *)weiboAPIUpdateStatusesWithToken:(NSString *)token andStatus:(NSString *)status andLat:(float)latitude andLong:(float)longtitude 2 { 3if ([weiboUrl testStatusLengthWithString:status] == NO) 4 return nil; 56NSString *requestStr = [NSString stringWithFormat:@"&access_token=%@&status=%@&lat=%f&long=%f", token, status, latitude, longtitude]; 7const char *requestCstr = [requestStr UTF8String]; 8910NSData *RequestData = [NSData dataWithBytes:requestCstr length:strlen(requestCstr)];111213NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: UpdateStatuses]];14[request setHTTPMethod:@"POST"]; 15[request setHTTPBody:RequestData];16NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];1718NSDictionary *returnDic = [NSJSONSerialization JSONObjectWithData:returnData options:kNilOptions error:nil];1920return returnDic;21 }

POST以后会有返回数据,根据返回的数据可以判断微博是否发送成功等状态,所以我封装的时候都会有返回数据的字典。说到POST,就不得不说微博“内容不超过140个汉字”的限制。微博所说的汉字是一个汉字或者汉字的标点就计数加1,英文或者英文的标点就计数加0.5,总计数是向上取整。全角等我尚未测试,所以不做解释。主要问题是如何计算字数出是否符合“内容不超过140个汉字”的标准。这里我提供三种方法给大家,其中一种是借鉴Kay_Sprint的《ios小项目——新浪微博客户端总结》其中的方法。

第一种是我自己想出来的

1 + (BOOL) testStatusLengthWithString:(NSString *)sourceString 2 { 3const char *UTFStr = [sourceString UTF8String]; 4 5unsigned int A = strlen(UTFStr);//汉字UTF8编码在strlen中每个占3位 6unsigned int B = [sourceString length]; //NSString length方法汉字和英文均占用1位 78unsigned int x = (A - B) / 2; //解二元一次方程,可得汉字和英文的个数 9unsigned int y = B - x;101112if (2 * x + y > 280) {//微博API接口限制汉字为140个,英文两个算一个汉字13 UIAlertView *al = [[UIAlertView alloc] initWithTitle:@"Error!" message:@"内容不超过140个汉字" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];14 [al show];15 return (NO);16} else17 return YES;18 }

如果超出字数,就会弹出UIAlertView的警告。这个理解起来应该不算难吧??

第二种是我从网上找回来的

1 NSString *test = [NSString stringWithString:@"这是一个中文test1"];2 NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);3 NSLog(@”%@ length is: %d”,test,[test lengthOfBytesUsingEncoding:enc]);

出处是/blog/archives/327,这样的话,要计算相对的长度也不是什么问题。不过由于这种编码方法,我也不是很清楚,所以具体会遇到什么问题,我也不知道。

第三种就是Kay_Sprint的

1 -(int)textLength:(NSString *)dataString 2{ 3 float sum = 0.0; 4 for(int i=0;i<[dataString length];i++) 5 { 6 NSString *character = [dataString substringWithRange:NSMakeRange(i, 1)]; 7 if([character lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 3) 8 { 9 sum++; 10 } 11 else 12 sum += 0.5; 13 } 14 15 return ceil(sum); 16}

具体作用可以看Kay_Sprint的说明。

这样的话,调用新浪微博API的障碍就基本扫清了,其余的接口都是大同小异,不会有什么大的变化。

不过转发的时候也要注意转发的文字,光标位置在最前面,而且键盘是自动打开的。

此外,为了不要每次都重复提取Access Token,我还用plist做了一下储存

1 - (void) saveToken2 {3NSString *tokenFile = [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"];4NSArray *tmpArray = [[NSArray alloc]initWithObjects:self.token, self.uid, self.userName, nil];56[tmpArray writeToFile:tokenFile atomically:YES];7 }

加载Access Token

1 + (id) loadToken 2 { 3tokenData *tmpid = [[tokenData alloc] init]; 45NSString *tokenFile = [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"]; 6NSArray *tmpArray = [[NSArray alloc] initWithContentsOfFile:tokenFile]; 78if (tmpArray == nil) 9 return nil;1011tmpid.token = [tmpArray objectAtIndex:0];12tmpid.uid = [tmpArray objectAtIndex:1];13tmpid.userName = [tmpArray objectAtIndex:2];1415return tmpid;16 }

如何要注销账号,我就先清空Access Token,然后dismissModal。最后返回最初的Controller的时,只要判定一下Access Token是否存在和是否过期即可。

四、View的复用

我先发我那充满违和感的storyboard出来吧

很明显看到我有几个View是密集地多次指向的,因为那些都是经过多次复用的,不过在这视图上看的确充满违和感。但是View复用可以减少大量的冗余代码,我是通过View的Controller属性的状态来判断现在的应该执行什么操作,改变其状态则可以在prepareForSegue等发生时进行操作。例如发新微博的View其实还可以用于评论、转发,那么新建一个独立的View作用不大。而且,查看微博内容的View也会被经常调用,就只是微博的ID不同。对它做小小的改动,完全可以胜任任何环境。

具体的操作,我也会在源代码里给出来。

五、最后的话

这个山寨新浪微博客户端还有很多的不足,特别是错误异常处理做得很不好,空微博、空收藏、无网络连接下的POST问题等等,我都没有去解决。这些就导致了闪退、假死的问题。类封装马虎的问题,导致了我每次发现有需要添加的新属性,都往同一个类加。最后变得很臃肿,经常有大量的属性没有切实使用。虽然我也有几个View复用了,但其实还有可以提升的空间。功能的不完善是很明显的,主流客户端都做了缓存,即便在低网速的环境也不会在加载View的时候卡顿太久。网络切换时容易造成闪退等等各种问题暂时就先搁置,留待以后我有能力解决再一一慢慢除虫。最后还是要感谢Kay_Sprint等人的指导和交流,不然我一个星期也搞不出这货。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。