草庐IT

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

coder 2024-01-27 原文

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

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

导致问题:

  1. 启动应用程序并更改排序 - 例如从 Date Changed 到 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;
}

最佳答案

你的问题出在这几行,

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

关于iphone - UITableViewCell 在编辑模式下移动时显示两个不同的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6170049/

有关iphone - UITableViewCell 在编辑模式下移动时显示两个不同的项目的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  6. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  7. c - mkmf 在编译 C 扩展时忽略子文件夹中的文件 - 2

    我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。

  8. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

  9. ruby - 具有两个参数的 block - 2

    我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

  10. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

随机推荐