草庐IT

ios - 具有多个子类 UICollectionViewCell 的 UICollectionView

coder 2023-07-30 原文

我的 UICollectionView 中有多个部分按“datasetType”分组。

我也有每个部分的自定义 UICollectionViewCell。

如何在 cellForItemAtIndexPath 方法中确定我需要哪个自定义 UICollectionViewCell

我的第一个想法是基于 [sectionInfo name]:

id sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:indexPath.section];

if ([[sectionInfo name] isEqualToString:@"DatasetA"]) {
    DatasetACell *datasetACell = [collectionView dequeueReusableCellWithReuseIdentifier:datasetACellIdentifer forIndexPath:indexPath];

    DatasetA *datasetA = [self.fetchedResultsController objectAtIndexPath:indexPath];
}

但我遇到了一个问题,它试图加载错误的数据集单元格。

这应该有效吗?我需要在其他地方寻找错误吗?还是我这部分做错了?

编辑:

我所拥有的应该可以工作。问题是索引没有对齐。

对于我的 fetchedResultsController,我将其创建为:

_fetchedResultsController = [Dataset MR_fetchAllSortedBy:NAME
                                               ascending:TRUE
                                           withPredicate:predicate
                                                 groupBy:@"datasetType"
                                                delegate:self.fetchedResultsController.delegate
                                               inContext:[NSManagedObjectContext MR_contextForCurrentThread]];

这会获取它们并按名称对它们进行排序。我在项目中使用了 Magical Record,并且我使用了它的获取 Controller ,因为我无法让 Core Data 获取 Controller 工作:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Dataset" inManagedObjectContext:[NSManagedObjectContext MR_contextForCurrentThread]];

[fetchRequest setEntity:entity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:NAME ascending:TRUE selector:@selector(caseInsensitiveCompare:)];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

[fetchRequest setSortDescriptors:sortDescriptors];

NSError *error;

NSArray *fetchedArray = [[NSManagedObjectContext MR_contextForCurrentThread] executeFetchRequest:fetchRequest error:&error];
NSLog(@"fetchedArray: %@", fetchedArray);

NSFetchedResultsController *FRC = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[NSManagedObjectContext MR_contextForCurrentThread] sectionNameKeyPath:nil cacheName:nil];
FRC.delegate = self;

我在这段代码中执行的 fetchRequest 返回实体,一旦我将它放入 fetch Controller ,它总是不返回任何内容。我认为它不喜欢 MR 的语境。/难以置信

当我尝试填充每个子类 UICollectionViewCell(DatasetACell、DataseetBCell 等)时,它可能会检索到错误的数据单元格。

所以在 NSFetchedResultsController 中的 indexPath (0,0)

[self.fetchedResultsController sections] objectAtIndex:indexPath]

将返回一个datasetA实体,而collection view为相同的索引

[collectionView dequeueReusableCellWithReuseIdentifier:datasetACell forIndexPath:indexPath] 

返回一个数据集BCell。

NSFetchedResultsController 排序时出现问题,而 [collectionView dequeueResuableCellwithReuseIdentifier:forIndexPath] 未排序。

完整代码:

-(NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"boundary.boundaryID == %@", self.dataseter.boundaryID];

    _fetchedResultsController = [Dataset MR_fetchAllSortedBy:NAME
                                                   ascending:TRUE
                                               withPredicate:predicate
                                                     groupBy:@"datasetType"
                                                    delegate:_fetchedResultsController.delegate
                                                   inContext:[NSManagedObjectContext MR_contextForCurrentThread]];

    return _fetchedResultsController;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    id sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:indexPath.section];
    NSLog(@"indexPath: %@", indexPath);
    NSLog(@"[sectionInfo name]: %@", [sectionInfo name]);


    if ([[sectionInfo name] isEqualToString:SAVED_ANALYSIS]) {
        NSLog(@"section name is DATASET A");

        DatasetCellA *datasetCellA = (DatasetCellA *)[collectionView dequeueReusableCellWithReuseIdentifier:datasetcellAIdentifier forIndexPath:indexPath];

        DatasetA *datasetA = [self.fetchedResultsController objectAtIndexPath:indexPath];
        NSLog(@"datasetA.id: %@", datasetA.id);
        NSLog(@"datasetA: %@", datasetA);

        // configure and return cell
    }
    else if ([[sectionInfo name] isEqualToString:EDITED_IMAGES]) {
        NSLog(@"section name is DATASET B");

        DatasetCellB *datasetCellB = (DatasetCellB *)[collectionView dequeueReusableCellWithReuseIdentifier:datasetCellBIdentifer forIndexPath:indexPath];

        DatasetB *datasetB = [self.fetchedResultsController objectAtIndex:indexPath];
        NSLog(@"editedImage.id: %@", datasetB.id);
    NSLog(@"editedImage: %@", datasetB);

        // configure and return cell
    }
}

日志:

2013-04-04 10:59:38.697 [2380:14003] indexPath: <NSIndexPath 0x19b645c0> 2 indexes [0, 0]
2013-04-04 10:59:38.697 [2380:14003] [sectionInfo name]: Dataset B
2013-04-04 10:59:38.697 [2380:14003] section name is DATASET B
2013-04-04 10:59:38.702 [2380:14003] datasetB.id: 1581
2013-04-04 10:59:38.703 [2380:14003] datasetB: <DatasetA: 0x1c193ac0> (entity: DatasetA; id: 0x16141bd0 <x-coredata://9313C8D3-0AA8-4F3F-B32D-F1F7843D4FA1/DatasetA/p168> ; data: {

})
2013-04-04 10:59:38.703 [2380:14003] indexPath: <NSIndexPath 0x19b64560> 2 indexes [1, 0]
2013-04-04 10:59:38.703 [2380:14003] [sectionInfo name]: Dataset A
2013-04-04 10:59:38.704 [2380:14003] section name is DATSET A
2013-04-04 10:59:38.709 [2380:14003] datasetA.id: 75
2013-04-04 10:59:38.709 [2380:14003] datasetA: <DatasetB: 0x1c15a830> (entity: DatasetB; id: 0x16141b30 <x-coredata://9313C8D3-0AA8-4F3F-B32D-F1F7843D4FA1/DatasetB/p165> ; data: {

})
2013-04-04 10:59:38.724 [2380:14003] -[DatasetB mode]: unrecognized selector sent to instance 0x1c15a830
2013-04-04 10:59:38.725 [2380:14003] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[DatasetB mode]: unrecognized selector sent to instance 0x1c15a830'
*** First throw call stack:
(0x1c19012 0x1a3ee7e 0x1ca44bd 0x1c08bbc 0x1c0894e 0x80028 0xe862da 0xe878f4 0xe89b91 0x9d32dd 0x1a526b0 0x56cfc0 0x56133c 0x561150 0x4df0bc 0x4e0227 0x4e08e2 0x1be1afe 0x1be1a3d 0x1bbf7c2 0x1bbef44 0x1bbee1b 0x28cc7e3 0x28cc668 0x982ffc 0x1ebd 0x1de5)
libc++abi.dylib: terminate called throwing an exception

对于第一个索引 (0,0),代码认为它是 DatasetB 但实际上是 DatasetA。在第二个索引 (1,0) 中则相反;代码认为它是一个 DatasetA 但实际上是一个 DatasetB。在这个集合中,有 1 个 DatasetB 和许多 DatasetA。

当获取 Controller 对其进行排序时,它首先对数据集 B 进行排序。 Collection View 需要一个 DatasetB,但获取 Controller 正在为同一索引返回一个 DatasetA。

最佳答案

看来排序有问题,需要排序。

但我的问题是,您为什么要打开版 block 名称?为什么不直接打开项目的类别?

id object = [self.fetchedResultsController objectAtIndexPath:indexPath];

if ([object isKindOfClass:[DatasetA class]] {
  // Do your DatasetCellA stuff
} else if ([object isKindOfClass:[DatasetB class]) {
  // Do your DatasetCellB stuff
}

至少这样你在排序时没有问题

您可能想更正您的提取请求,以便按 datasetType 排序,然后按 name 排序。

- (NSFetchedResultsController *)fetchedResultsController
{
  if (!_fetchedResultsController) {
    return _fetchedResultsController;
  }

  NSFetchRequest *request = [[NSFetchRequest alloc] init];
  request.entity          = [Dataset MR_entityDescription];
  request.sortDescriptors = @[
                            [NSSortDescriptor sortDescriptorWithKey:@"datasetType" ascending:YES],
                            [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO],
                            ];

  _fetchedResultsController = 
    [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                        managedObjectContext:[NSManagedObjectContext MR_context]
                                          sectionNameKeyPath:@"datasetType"
                                                   cacheName:nil];

  NSError *error = nil;
  if (![_fetchedResultsController performFetch:&error]) {
    NSLog(@"Could not perform fetch %@", [error localizedDescription]);
  }

  _fetchedResultsController.delegate = <..your delegate..>;

  return _fetchedResultsController;
}

另外,您自制的 fetchResultsController 可能没有返回任何内容的原因是因为您没有自己使用提取请求执行提取,而是通过 fetchedResultsController 来完成

if ([fetchedResultsController performFetch:&error]) {
   //...

关于ios - 具有多个子类 UICollectionViewCell 的 UICollectionView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15668616/

有关ios - 具有多个子类 UICollectionViewCell 的 UICollectionView的更多相关文章

  1. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

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

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

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  7. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  8. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  9. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  10. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

随机推荐