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

时间:2011-05-29 19:53:34

标签: iphone ios uitableview core-data

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

现在,表格显示和核心数据正确反映了排序选择。但是,如果我做了类似下面的事情,我会得到一个奇怪的情况,如下面的截图所示。

导致问题:

  1. 启动应用并更改排序 - 例如从更改日期更改为Alpha
  2. 更改为自定义排序
  3. 尝试在编辑模式下移动项目(仅在我按住并拖动项目时出现错误)
  4. 截图:

    Image of problem

    当更改排序首选项时,我实质上是在杀死我的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;
    }
    

1 个答案:

答案 0 :(得分: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的自定义子类并添加两个retain ed属性 - 一个用于切换控制,一个用于标签,稍后执行此操作,

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];