原因是原方法下会有界面混乱的问题。
原方法是我滑倒最后一页,在往后滑一定距离就会发送通知请求数据,并刷新页面。但是最近发现如果我只是往后滑一些,然后不停有把它滑会原最后一页。数据会继续请求并刷新,但是页面计算会出问题。因为我是把新数据第一页直接放在当前页面,所以新数据第一页会覆盖掉原数据最后一页。因为我是在数据请求前先添加6页,之后再根据数据更改,如果我一直向后滑甚至会出现数组越界问题。我又想不出办法监控它滑完后到底在哪一页,又应该能把新数据第一页覆盖到哪一页,所以就换了一个办法。
新方法:
1. 关闭滚动弹性。当用户滑倒最后一页时,先给scrollView在添加一页空白,让用户能向后滑,却只能滑倒这里,防止数组越界。如果用户滑倒这一页空白就发送通知,请求网络数据。
- - (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
- if (self.scrollView.contentOffset.x == SCREEN_SIZE_WIDTH * self.numberOfStories) {
- [[NSNotificationCenter defaultCenter] postNotificationName:@"upDataRight" object:nil];
- return;
- }
- NSInteger number = self.scrollView.contentOffset.x / SCREEN_SIZE_WIDTH;
-
- [[NSNotificationCenter defaultCenter] postNotificationName:@"scrollViewDidEndDecelerating" object:nil userInfo:@{@"value":[NSNumber numberWithInteger:number]}];
-
- if (self.scrollView.contentOffset.x == SCREEN_SIZE_WIDTH * (self.numberOfStories - 1)) {
- self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width + SCREEN_SIZE_WIDTH, 0);
- }
- }
2. 主界面控制器接收通知并请求数据。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(upDataByStoriesUnlimitedRight) name:@"upDataRight" object:nil];
- - (void) upDataByStoriesUnlimitedRight {
- LastStoriesModel* lastStoriesModel = [self.lastStoriesModelArray lastObject];
- NSString* lastDate1 = lastStoriesModel.date;
-
-
- [self getLastStoriesWithDate:lastDate1];
- }
3. 请求到数据后,更新主界面视图,并发送通知。
- - (void) getLastStoriesWithDate:(NSString*)lastDate {
- [self.manage getLastTime:lastDate StoriesData:^(LastStoriesModel * _Nonnull lastStoriesModel) {
- if (self.lastStoriesModelArray == nil) {
- self.lastStoriesModelArray = [[NSMutableArray alloc] init];
- }
- [self.lastStoriesModelArray addObject:lastStoriesModel];
-
- dispatch_async(dispatch_get_main_queue(), ^{
- [self sendStoriserToView:lastStoriesModel];
- [self.interFaceView viewInit];
-
- NSMutableArray* array = [[NSMutableArray alloc] init];
- for (Stories* stories in lastStoriesModel.stories) {
- [array addObject:stories.id];
- }
- [[NSNotificationCenter defaultCenter] postNotificationName:@"upDataRight-Two" object:nil userInfo:@{@"value":array}];
- });
- } error:^(NSError * _Nonnull error) {
- NSLog(@"getLastModel error");
- }];
- }
4. 具体界面控制器接收通知并更新视图。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(upDataToStoriesUnlimitedRight:) name:@"upDataRight-Two" object:nil];
- - (void) upDataToStoriesUnlimitedRight:(NSNotification*)notification {
- for (NSString* ID in notification.userInfo[@"value"]) {
- [self.storiesModel.storiesIDArray addObject:ID];
- }
-
- self.storiesInterFace.numberOfStories = [self.storiesModel.storiesIDArray count];
- self.storiesInterFace.nowStoriesNumber = self.storiesNumber;
-
- StoriesUnlimitedRightInterFace* interFaceView = (StoriesUnlimitedRightInterFace*)self.storiesInterFace;
-
- [interFaceView upDataRightWebView];
- }
5. 视图层更新数据,给scrollView添加适合的页数。更新webView先计算到底在哪一页,发送更新那一页数据的通知。同时如果已经是最后一页,在后面添加空白页(防止这组数据只有一个,虽然不太可能)。
- - (void) upDataRightWebView {
- self.scrollView.contentSize = CGSizeMake(SCREEN_SIZE_WIDTH * self.numberOfStories, 0);
-
- NSInteger number = self.scrollView.contentOffset.x / SCREEN_SIZE_WIDTH;
-
- [[NSNotificationCenter defaultCenter] postNotificationName:@"scrollViewDidEndDecelerating" object:nil userInfo:@{@"value":[NSNumber numberWithInteger:number]}];
-
- if (self.scrollView.contentOffset.x == SCREEN_SIZE_WIDTH * (self.numberOfStories - 1)) {
- self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width + SCREEN_SIZE_WIDTH, 0);
- }
- }
首先先说我解决cell复用问题,其实很简单,就是建立一个集合。给每一个展开按钮和被回复长评论label一个相关联的tag值。
- cell.unFoldButton.tag = (indexPath.section + 1) * 11111 + (indexPath.row + 1) * 11;
-
- cell.replyComment.tag = (indexPath.section + 1) * 22222 + (indexPath.row + 1) * 22;
点击展开按钮后,将按钮的tag值存入集合,并按按钮的tag值得到label的tag值,进而得到label,改变label的状态使其展开。
- - (void)pressUnfold:(UIButton*)sender {
- if (!sender.tag) {
- return;
- }
- NSString* unfoldTagString = [NSString stringWithFormat:@"%ld", sender.tag];
- NSInteger replyCommentTag = sender.tag * 2;
- NSInteger unfoldLabelTag = sender.tag * 3;
-
-
- if ([self.unfoldSet containsObject:unfoldTagString]) {
-
- [self.unfoldSet removeObject:unfoldTagString];
-
- UILabel* label = (UILabel*)[sender.superview viewWithTag:replyCommentTag];
- label.numberOfLines = 2;
-
- [self.tableView reloadData];
- } else {
-
- [self.unfoldSet addObject:unfoldTagString];
-
- UILabel* label = (UILabel*)[sender.superview viewWithTag:replyCommentTag];
- label.numberOfLines = 0;
-
- [self.tableView reloadData];
- }
- }
每次建立新cell都会使用这个集合判断其是否展开。
- if ([self.unfoldSet containsObject:[NSString stringWithFormat:@"%ld", cell.unFoldButton.tag]]) {
- cell.replyComment.numberOfLines = 0;
- } else {
- cell.replyComment.numberOfLines = 2;
- }
但是这里我出现了一个伪复用问题,就是看起来很像复用问题,其实并不是,甚至不能算作问题,这只是一个特性。
这个问题是,当页面中有很多展开按钮时,我按下其中一个只有它的标题会变成收起。此时我再次按下它时,它的标题会变成展开全文。但是会有另一个标题原本是展开全文的按钮,它的标题会突然变成收起,然后变回展开全文。我一开始以为它是复用问题,但我错了。
我花了好久,一个断点一个断点的跑,确定我的设置标题的代码没有复用,才明白问题不在复用。这确实是复用造成的,但重点不在这里。
其实是因为我偷懒,设置按钮状态没有使用它的selected属性,而是直接更改标题。但是Button的设置标题的属性是默认带有动画的,可能是为了视觉体验流畅。总之,我看到的,一个无相关的cell的按钮标题突然改变其实是因为复用cell之后,重新设置按钮标题时由“收到”慢慢变成“展开全文”的动画。
解决方法也很暴力。我把这个按钮设成空白的,在它下面压了一个一摸一样大的label,然后通过改变label的text来改变按钮标题。