UITableViewCell 在编辑模式下移动时显示两个不同的项目

Posted

技术标签:

【中文标题】UITableViewCell 在编辑模式下移动时显示两个不同的项目【英文标题】:UITableViewCell showing two different items while I move it in edit mode 【发布时间】:2011-05-29 19:53:34 【问题描述】:

我有一个由 Core Data 支持的基本“待办事项列表”iPhone 应用程序。我在实现允许用户选择排序顺序(Alpha、创建日期、自定义)的系统时遇到问题。如果他们选择自定义,那么他们可以通过编辑模式手动移动项目。

现在,表格显示和核心数据正确反映了排序选择。但是,如果我执行以下操作,则会出现如下屏幕截图所示的奇怪情况。

导致问题:

    启动应用程序并更改排序 - 比如从更改日期到 Alpha 更改为自定义排序 尝试在编辑模式下移动项目(错误仅在我按住并拖动项目时出现)

截图:

当排序首选项改变时,我实际上是在杀死我的 NSManagedResultsFetcher,用新的排序描述符创建一个新的并重新加载表

- (void)startFetcher

    BOOL                            success;
    NSError *                       error;
    NSFetchRequest *                fetchRequest;
    NSSortDescriptor *              sortDescriptor;
    OurListsAppDelegate*    delegate;

    delegate = [[UIApplication sharedApplication] delegate]; 

    assert([ListMaster sharedListMaster] != nil);
    assert([ListMaster sharedListMaster].managedObjectContext != nil);

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                              @"(parentCreatedUdid = %@) AND (parentCreatedDate = %@)", self.parentCreatedUdid, self.parentCreatedDate];

    if (self.parentItem != nil)
    
        sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:self.parentItem.sortPreference ascending:YES] autorelease];
    
    else
    
       sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:delegate.rootSortPreference ascending:YES] autorelease];
    

    assert(sortDescriptor != nil);

    fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    assert(fetchRequest != nil);

    [fetchRequest setPredicate:predicate];

    [fetchRequest setEntity:[ListMaster sharedListMaster].listEntity];
    [fetchRequest setFetchBatchSize:20];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

    assert(self.fetcher == nil);
    self.fetcher = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[ListMaster sharedListMaster].managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    assert(self.fetcher != nil);

    self.fetcher.delegate = self;

    success = [self.fetcher performFetch:&error];
    if ( ! success ) 
        [[QLog log] logWithFormat:@"viewer fetch failed %@", error];
    

以及当排序顺序改变时调用的方法

- (void)restartFetcher

    [_fetcher release];
    self.fetcher = nil;
    [self startFetcher];
    [self reloadTable];

编辑:根据请求在下面添加代码

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath


    UITableViewCell *   result;

    assert(tv == self.tableView);
    assert(indexPath != NULL);

    if ( [self hasNoItems] )
    

        // There are no items to display; return a cell that simple says "No items".

        result = [self.tableView dequeueReusableCellWithIdentifier:@"cell"];
        if (result == nil) 
            result = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"] autorelease];
            assert(result != nil);

            result.textLabel.text = @"No items";
            result.textLabel.textColor = [UIColor darkGrayColor];
            result.textLabel.textAlignment = UITextAlignmentCenter;
        
        result.selectionStyle = UITableViewCellSelectionStyleNone;
     
    else
    
        ListItem *         item;


        item = [self.fetcher objectAtIndexPath:indexPath];
        assert([item isKindOfClass:[ListItem class]]);

        UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"cell"];

        if (cell == nil)
        
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"] autorelease];
            assert(cell != nil);

            assert(cell.selectionStyle == UITableViewCellSelectionStyleBlue);;
        

        ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
        toggleControl.tag = indexPath.row;  
        [cell.contentView addSubview: toggleControl];

        [toggleControl release];

        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];

        label.text = item.name;
        label.textAlignment = UITextAlignmentLeft;

        [cell.contentView addSubview:label];
        [label release];        


        if ([item.isList boolValue] == YES)
        
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        
        else
        
            cell.accessoryType = UITableViewCellAccessoryNone;
        

        result = cell;
    

    return result;

【问题讨论】:

你能发布你的tableView:cellForRowAtIndexPath:吗? 按要求发布了 tableView:cellForRowAtIndexPath。谢谢你看看这个。我是 iPhone 开发的新手,所以如果有人有需要看的东西的指针(但不是事实上的解决方案),它也会有所帮助。 【参考方案1】:

你的问题出在这几行,

ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
toggleControl.tag = indexPath.row;  
[cell.contentView addSubview: toggleControl];

[toggleControl release];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];

label.text = item.name;
label.textAlignment = UITextAlignmentLeft;

[cell.contentView addSubview:label];
[label release]; 

这是单元重用的问题。每次配置可重用单元之前,都需要对其进行重置。在这种情况下,当我注意到一个单元格的内容与另一个单元格的内容合并时,我意识到这就是问题所在。当这种事情发生时,通常就是问题所在。您做错的是,每次重用单元格时,您都在添加您在上面创建的两个对象。在切换控件的情况下,它们会重叠,您不会注意到,但文本会发生变化并且重叠突出。

你能做什么?

您可以搜索这两个对象并将它们从单元格中删除,然后执行上述操作,或者您可以创建UITableViewCell 的自定义子类并添加两个retained 属性——一个用于切换控件和一个用于标签,稍后执行此操作,

ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
toggleControl.tag = indexPath.row;  
cell.toggleControl = toggleControl;

[toggleControl release];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];

label.text = item.name;
label.textAlignment = UITextAlignmentLeft;

cell.label = label;
[label release]; 

【讨论】:

效果很好。我找错地方了,所以这很有帮助。

以上是关于UITableViewCell 在编辑模式下移动时显示两个不同的项目的主要内容,如果未能解决你的问题,请参考以下文章

使用 Interface Builder 编辑 UITableViewCell 的模式

在编辑模式下重新排序时更改 UITableViewCell 的背景颜色

动画 UITableViewCell ContentView 在进入编辑模式时淡出

深挖UITableViewCell-编辑多选模式下,引发的深思

如何在编辑模式下调整 UITableViewCell 背景的大小

iPhone UITableViewCell selectionStyle 编辑时?