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

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

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

导致问题:

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

截图:

当排序首选项改变时,我实际上是在杀死我的 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 开发的新手,所以如果有人有需要看的东西的指针(但不是事实上的解决方案),它也会有所帮助。

标签: iphone ios uitableview core-data


【解决方案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]; 

【讨论】:

  • 效果很好。我找错地方了,所以这很有帮助。
猜你喜欢
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多