Ios 表视图单元格失去其顺序

Ios 表视图单元格失去其顺序,ios,objective-c,facebook,Ios,Objective C,Facebook,目标 我正在尝试创建一个类似Instegram主屏幕的表视图。 我已经做了一个自定义单元格,我正在用数据初始化它,假设该单元格持有“Post” 逻辑 我将每个单元格保存在NSMutableDictionary中,键是posts顺序的索引,值是post-it self 当前结果 我向下滚动,一切都很好。你看到的顺序是post1,post2,post3…post8,但当我向上滚动时,一切都乱了,post8,post6,post7,post8,post5。。。你明白了 (在这里提问之前,我试着用小对象

目标

我正在尝试创建一个类似Instegram主屏幕的表视图。 我已经做了一个自定义单元格,我正在用数据初始化它,假设该单元格持有“Post”

逻辑

我将每个单元格保存在NSMutableDictionary中,键是posts顺序的索引,值是post-it self

当前结果

我向下滚动,一切都很好。你看到的顺序是post1,post2,post3…post8,但当我向上滚动时,一切都乱了,post8,post6,post7,post8,post5。。。你明白了

(在这里提问之前,我试着用小对象来做这件事——一个只包含字符串的常规!(不是自定义的)单元格

  • 由于某种原因,它起作用了!订单非常完美。)
代码

这是我的UITableViewController-我的“主”屏幕“cellForRow”方法

如果我们向上滚动,并且Tableview的索引已经初始化,我会从字典中提取帖子

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
    static NSString *PC = @"PostCell";
    PostCell *Pcell = [tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];
    NSString *key = [[NSString alloc] initWithFormat:@"%i", indexPath.section];
    NSLog(@"Cell %i", indexPath.section);

    // Checking if alrdy visted this indexpath.
    if (![_allcells objectForKey:key]) {
         [self setPostUserName:[[NSString alloc] initWithFormat:@"username: %i", indexPath.section]:Pcell];
        // Saving a postcell I wont return, just to save in a dictionary.
        // When we get here again it will get another pointer like that my object wont change.
        PostCell* toSave = [[PostCell alloc] init];
        // saving it with current post data.
        [self copyPost:toSave :Pcell];
        [_allcells setObject:toSave forKey:key];
    }
    else {
        // Copying post daya
        [self copyPost:Pcell :[_allcells objectForKey:key]];
    }
    NSLog(@"Cell %i Returning: %@", indexPath.section, Pcell.userName.text);
    return Pcell;
}

// Check if it reached the end
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
    if (endScrolling >= scrollView.contentSize.height)
    {
        NSDictionary *temparr = [[NSDictionary alloc] initWithDictionary:_allcells];
        [self.tableView reloadData];
         _allcells = [[NSMutableDictionary alloc] initWithDictionary:temparr];
    }
}
@property (strong, nonatomic) NSDictionary *post;

//    To create an NSDictionary
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:@"74 degrees" forKeyPath:@"weather"];
post = tempDict;

//    To modify an NSDictionary
tempDict = [[NSMutableDictionary alloc] initWithDictionary:post];
[tempDict removeObjectForKey:@"weather"];
post = tempDict;
这是我的PostCell.h,所以你可以看到属性

@interface PostCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UIImageView *profilePic;
@property (strong, nonatomic) IBOutlet UILabel *userName;
@property (strong, nonatomic) IBOutlet UILabel *checkIn;
@property (strong, nonatomic) IBOutlet UILabel *uploadedAgo;
@property (strong, nonatomic) IBOutlet UIImageView *mainPic;
@property (strong, nonatomic) IBOutlet UILabel *likes;
@property (strong, nonatomic) IBOutlet UILabel *participants;

@end

顺便说一句,如果你有一个项目的例子,有一个类似的Instagram主屏幕的结果,它将是伟大的,如果你可以链接我到它

您不应该存储对单元格的引用,因为当单元格离开屏幕时,它们会被tableview重用。目前,在第一次向下滚动时,一切正常,因为您创建了新的单元格。向上滚动时,您会得到存储的引用,该引用现在指向一个新创建的单元格,因此看起来很混乱

您应该做的只是用正确的数据填充重用的单元格,并仅在需要时创建它们。比如:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *PC = @"PostCell";
    PostCell *Pcell = (PostCell*)[tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];

    // feed the needed data to the cell

    return Pcell;
}

不确定为什么只访问
indexPath.section
,因为通常情况下,您会使用
indexPath.row
,在每个节中使用多个单元格填充表格,所以不应该存储对单元格的引用,因为当单元格离开屏幕时,它们会被tableview重用。目前,在第一次向下滚动时,一切正常,因为您创建了新的单元格。向上滚动时,您会得到存储的引用,该引用现在指向一个新创建的单元格,因此看起来很混乱

您应该做的只是用正确的数据填充重用的单元格,并仅在需要时创建它们。比如:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *PC = @"PostCell";
    PostCell *Pcell = (PostCell*)[tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];

    // feed the needed data to the cell

    return Pcell;
}

不确定为什么只访问
indexPath.section
,因为通常情况下,您会使用
indexPath.row
,在每个节中使用多个单元格填充表格,所以不应该存储对单元格的引用,因为当单元格离开屏幕时,它们会被tableview重用。目前,在第一次向下滚动时,一切正常,因为您创建了新的单元格。向上滚动时,您会得到存储的引用,该引用现在指向一个新创建的单元格,因此看起来很混乱

您应该做的只是用正确的数据填充重用的单元格,并仅在需要时创建它们。比如:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *PC = @"PostCell";
    PostCell *Pcell = (PostCell*)[tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];

    // feed the needed data to the cell

    return Pcell;
}

不确定为什么只访问
indexPath.section
,因为通常情况下,您会使用
indexPath.row
,在每个节中使用多个单元格填充表格,所以不应该存储对单元格的引用,因为当单元格离开屏幕时,它们会被tableview重用。目前,在第一次向下滚动时,一切正常,因为您创建了新的单元格。向上滚动时,您会得到存储的引用,该引用现在指向一个新创建的单元格,因此看起来很混乱

您应该做的只是用正确的数据填充重用的单元格,并仅在需要时创建它们。比如:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *PC = @"PostCell";
    PostCell *Pcell = (PostCell*)[tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];

    // feed the needed data to the cell

    return Pcell;
}

不确定为什么只访问
indexPath.section
,因为通常情况下,使用
indexPath.row
,UITableView最适合于数组。此外,数组在索引时会保持顺序,而字典没有索引,因此不会保持顺序。同样,相同类型的单独单元格(在本例中为PostCell)不应具有不同的部分,而应具有不同的行。使用部分分隔不同类别的单元格

另一个提示;NSMutableDictionary比NSDictionary占用更多内存。在NSMutableDictionary中设置好所有内容后,将其存储在NSDictionary中。如果将来要修改它,请将其复制回NSMutableDictionary,修改它,然后将其再次存储为NSDictionary

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
    static NSString *PC = @"PostCell";
    PostCell *Pcell = [tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];
    NSString *key = [[NSString alloc] initWithFormat:@"%i", indexPath.section];
    NSLog(@"Cell %i", indexPath.section);

    // Checking if alrdy visted this indexpath.
    if (![_allcells objectForKey:key]) {
         [self setPostUserName:[[NSString alloc] initWithFormat:@"username: %i", indexPath.section]:Pcell];
        // Saving a postcell I wont return, just to save in a dictionary.
        // When we get here again it will get another pointer like that my object wont change.
        PostCell* toSave = [[PostCell alloc] init];
        // saving it with current post data.
        [self copyPost:toSave :Pcell];
        [_allcells setObject:toSave forKey:key];
    }
    else {
        // Copying post daya
        [self copyPost:Pcell :[_allcells objectForKey:key]];
    }
    NSLog(@"Cell %i Returning: %@", indexPath.section, Pcell.userName.text);
    return Pcell;
}

// Check if it reached the end
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
    if (endScrolling >= scrollView.contentSize.height)
    {
        NSDictionary *temparr = [[NSDictionary alloc] initWithDictionary:_allcells];
        [self.tableView reloadData];
         _allcells = [[NSMutableDictionary alloc] initWithDictionary:temparr];
    }
}
@property (strong, nonatomic) NSDictionary *post;

//    To create an NSDictionary
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:@"74 degrees" forKeyPath:@"weather"];
post = tempDict;

//    To modify an NSDictionary
tempDict = [[NSMutableDictionary alloc] initWithDictionary:post];
[tempDict removeObjectForKey:@"weather"];
post = tempDict;
然后将其存储在数组中

@property (strong, nonatomic) NSArray *allPosts;

//     NSMutableArray takes up more memory than NSArray
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithArray:allPosts];
[tempArray addObject:post];
allPosts = tempArray;
最后,在tableview中显示它

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *PC = @"PostCell";
    PostCell *pCell = [tableView dequeueReusableCellWithIdentifier:PC];

    if (!cell) {
        pCcell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PC];
    }

    NSDictionary *currentPost = [allPosts objectAtIndex:indexPath.row];


//  Instead of having post1, post2, post3 and so forth, each post is now in currentPost.  If there are 10 posts, then this function will run 10 times.  Just write the code as if you are handling one post, and the UITableView will automatically fill in the rest of the posts for you.        

    return cell;
}

UITableView与阵列配合使用效果最佳。此外,数组在索引时会保持顺序,而字典没有索引,因此不会保持顺序。同样,相同类型的单独单元格(在本例中为PostCell)不应具有不同的部分,而应具有不同的行。使用部分分隔不同类别的单元格

另一个提示;NSMutableDictionary比NSDictionary占用更多内存。在NSMutableDictionary中设置好所有内容后,将其存储在NSDictionary中。如果将来要修改它,请将其复制回NSMutableDictionary,修改它,然后将其再次存储为NSDictionary

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
    static NSString *PC = @"PostCell";
    PostCell *Pcell = [tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];
    NSString *key = [[NSString alloc] initWithFormat:@"%i", indexPath.section];
    NSLog(@"Cell %i", indexPath.section);

    // Checking if alrdy visted this indexpath.
    if (![_allcells objectForKey:key]) {
         [self setPostUserName:[[NSString alloc] initWithFormat:@"username: %i", indexPath.section]:Pcell];
        // Saving a postcell I wont return, just to save in a dictionary.
        // When we get here again it will get another pointer like that my object wont change.
        PostCell* toSave = [[PostCell alloc] init];
        // saving it with current post data.
        [self copyPost:toSave :Pcell];
        [_allcells setObject:toSave forKey:key];
    }
    else {
        // Copying post daya
        [self copyPost:Pcell :[_allcells objectForKey:key]];
    }
    NSLog(@"Cell %i Returning: %@", indexPath.section, Pcell.userName.text);
    return Pcell;
}

// Check if it reached the end
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
    if (endScrolling >= scrollView.contentSize.height)
    {
        NSDictionary *temparr = [[NSDictionary alloc] initWithDictionary:_allcells];
        [self.tableView reloadData];
         _allcells = [[NSMutableDictionary alloc] initWithDictionary:temparr];
    }
}
@property (strong, nonatomic) NSDictionary *post;

//    To create an NSDictionary
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:@"74 degrees" forKeyPath:@"weather"];
post = tempDict;

//    To modify an NSDictionary
tempDict = [[NSMutableDictionary alloc] initWithDictionary:post];
[tempDict removeObjectForKey:@"weather"];
post = tempDict;
然后将其存储在数组中

@property (strong, nonatomic) NSArray *allPosts;

//     NSMutableArray takes up more memory than NSArray
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithArray:allPosts];
[tempArray addObject:post];
allPosts = tempArray;
最后,在tableview中显示它

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *PC = @"PostCell";
    PostCell *pCell = [tableView dequeueReusableCellWithIdentifier:PC];

    if (!cell) {
        pCcell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PC];
    }

    NSDictionary *currentPost = [allPosts objectAtIndex:indexPath.row];


//  Instead of having post1, post2, post3 and so forth, each post is now in currentPost.  If there are 10 posts, then this function will run 10 times.  Just write the code as if you are handling one post, and the UITableView will automatically fill in the rest of the posts for you.        

    return cell;
}

UITableView与阵列配合使用效果最佳。此外,数组在索引时会保持顺序,而字典没有索引,因此不会保持顺序。同样,相同类型的单独单元格(在本例中为PostCell)不应具有不同的部分,而应具有不同的行。使用部分分隔不同类别的单元格

另一个提示;NSMutableDictionary比NSDictionary占用更多内存。在NSMutableDictionary中设置好所有内容后,将其存储在NSDictionary中。如果以后要修改它,请将其复制回