• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

iphone - NSFetchedResultsController numberOfObjects 在设备上运行时返回附加(重复)

[复制链接]
菜鸟教程小白 发表于 2022-12-13 07:41:58 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我已经使用 NSFetchedResultsController 实现了一个 UITableView 来从 sqllite 数据库加载数据。我从设备下载了数据库到模拟器,所以两者都是一样的。

我观察到奇怪的行为,当在模拟器上运行时,tableview 填充了正确数量的单元格(在初始基本情况下:一个单元格);但是,当我在设备上运行相同的代码时,numberOfObjects 返回 2,并且 tableview 显示两个(相同/重复)单元格。

当我检查 sqllite 文件时,其中确实只有 1 个对象/行...

我按照示例代码进行了实现,并没有做任何特别的事情。

- (NSInteger)numberOfSectionsInTableViewUITableView *)tableView {
    NSInteger count = [[fetchedResultsController sections] count];

    if (count == 0) {
        count = 1;
    }

    return count;
}


- (NSInteger)tableViewUITableView *)tableView numberOfRowsInSectionNSInteger)section {
    NSInteger numberOfRows = 0;

    if ([[fetchedResultsController sections] count] > 0) {
        id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
        numberOfRows = [sectionInfo numberOfObjects];
    }

    NSLog(@"SwoopListTableViewController::numberOfRowsInSection - numberOfRows:%d", numberOfRows);
    return numberOfRows;
}


- (UITableViewCell *)tableViewUITableView *)tableView cellForRowAtIndexPathNSIndexPath *)indexPath {
    // Dequeue or if necessary create a SwoopTableViewCell, then set its Swoop to the Swoop for the current row.            
    static NSString *SwoopCellIdentifier = @"SwoopCellIdentifier";

    SwoopTableViewCell *SwoopCell = (SwoopTableViewCell *)[tableView dequeueReusableCellWithIdentifier:SwoopCellIdentifier];
    if (SwoopCell == nil) {
        SwoopCell = [[[SwoopTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SwoopCellIdentifier] autorelease];
        SwoopCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }

    [self configureCell:SwoopCell atIndexPath:indexPath];
    return SwoopCell;
}

- (NSFetchedResultsController *)fetchedResultsController {
    // Set up the fetched results controller if needed.
    NSLog(@"SwoopListTableViewController::fetchedResultsController - started");

    if (fetchedResultsController == nil) {

        if (managedObjectContext == nil) 
        { 
            managedObjectContext = [(SwoopAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
            NSLog(@"SwoopListTableViewController::fetchedResultsController - set managedObjectContext");
        }

        // Create the fetch request for the entity.
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

        NSEntityDescription *entity = [NSEntityDescription entityForName"Swoop" inManagedObjectContext:managedObjectContext];
        [fetchRequest setEntity:entity];

        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey"creationDate" ascending:NO];
        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
        [fetchRequest setSortDescriptors:sortDescriptors];

        NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName"Root"];
        aFetchedResultsController.delegate = self;
        self.fetchedResultsController = aFetchedResultsController;

        [aFetchedResultsController release];
        [fetchRequest release];
        [sortDescriptor release];
        [sortDescriptors release];
    }

    return fetchedResultsController;
}  

我很困惑为什么相同的代码和相同的数据库会在模拟器(按预期工作)与设备(3GS - 显示重复的表格单元格)上表现出不同的行为。任何人都可以帮助/解释/提供一些关于我应该看什么的见解吗?

非常感谢, 埃里克

** 编辑 1: ** 我对 NSCoreData 和 NSFetchedResultsController 做了更多的调试。似乎 fetchRequest 确实从 managedContext 返回了一个重复的对象。这是代码和相应的控制台输出:

Controller 代码:

- (void)viewDidLoad {   
    NSError *error = nil;
    if (![[self fetchedResultsController] performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }       
    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:0];
    NSLog(@"SwoopListTableViewController::viewDidLoad - sectionInfo objects:%@", [sectionInfo objects] );        
}

控制台输出:

2011-05-14 17:54:53.388 Swoop[1471:307] SwoopListTableViewController::viewDidLoad - sectionInfo objects
    "<Swoop: 0x187d60> (entity: Swoop; id: 0x186480 <x-coredata://A9FF2CC0-77EE-4EFF-A3A6-5F085AA9CCAC/Swoop/p2> ; data: <fault>)",
    "<Swoop: 0x187d60> (entity: Swoop; id: 0x186480 <x-coredata://A9FF2CC0-77EE-4EFF-A3A6-5F085AA9CCAC/Swoop/p2> ; data: <fault>)",
    "<Swoop: 0x188180> (entity: Swoop; id: 0x143a60 <x-coredata://A9FF2CC0-77EE-4EFF-A3A6-5F085AA9CCAC/Swoop/p1> ; data: <fault>)"
)

我觉得奇怪的是 sectionInfo 中的前两个对象都具有相同的内存地址“0x187d60”并且都具有相同的 x-coredata 'path':“//A9FF2CC0-77EE-4EFF-A3A6-5F085AA9CCAC/Swoop/p2"...谁能解释一下这是什么意思,或者可能发生了什么?

谢谢, 埃里克



Best Answer-推荐答案


在对 NSCoreData 进行了更多阅读和挖掘之后,问题似乎是由于设备上内存管理方式的特殊性(我会假设相同的内存限制/管理将应用于模拟器,但我猜两者之间存在差异)——特别是,如果在内存不足警告下卸载 View ,则在再次重新加载 View 时将执行提取,这可能导致重复条目。

我发现以下链接中描述的问题/解决方案解决了我遇到的问题:

Duplicate NSManagedObject with NSFetchedResultsController

另一方面,通过将此参数传递给应用程序,了解能够启用不同级别的 NSCoreData 日志记录也很有帮助:

-com.apple.CoreData.SQLDebug 1

在这里阅读更多:

从 Apple 开发者库中,查看“核心数据疑难解答:Debugging Fetching

要通过 xcode 添加参数,请参阅本页 http://www.meandmark.com/xcodetips.html 上的“为命令行程序提供启动参数”

关于iphone - NSFetchedResultsController numberOfObjects 在设备上运行时返回附加(重复),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5975019/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap