将 NSFetchedResultsController 从 UITableViewController 迁移到 UIViewController

Posted

技术标签:

【中文标题】将 NSFetchedResultsController 从 UITableViewController 迁移到 UIViewController【英文标题】:Migrating NSFetchedResultsController to UIViewController from UITableViewController 【发布时间】:2013-07-27 22:51:29 【问题描述】:

为了规避 NSFetchedResultsController 固有的一些问题,我决定将我的 UITableViewController 更改为 UIViewController 并添加一个 tableView 属性。我没有使用故事板,而是以编程方式制作所有内容。这样做的目的是在 y 轴上从顶部开始留下大约 44 px 的空白空间(所以我可以在那里放置一个通用标题)的表格视图。基本上,我正在尝试将 tableview 向下移动 44 px。

问题是,我在 fetchedResultsController 处遇到断点错误。这是我的代码:

ViewController.h

@interface ToDoViewController : UIViewController <UITableViewDelegate, SettingsViewControllerDelegate, NSFetchedResultsControllerDelegate, UITableViewDataSource>
@property (nonatomic) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic) NSFetchedResultsController *fetchedResultsController;
@end

ViewController.m

@implementation ToDoViewController
@synthesize managedObjectContext;
@synthesize fetchedResultsController = _fetchedResultsController;
@synthesize tableView = _tableView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        UINavigationItem *i = [self navigationItem];
        [i setTitle:@"Task List"];
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 44, 320, 548) style:UITableViewStyleGrouped];
        [self.view addSubview:self.tableView];
        self.tableView = self.fetchedResultsController.delegate;

    
    return self;


-(void) viewDidLoad
    [super viewDidLoad];

   NSError *error;
    if (![[self fetchedResultsController] performFetch:&error])
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);
     

    [self.tableView setDelegate:self];
    [self.tableView setDataSource:self];

    [self.tableView setBackgroundView:nil];
    [self.tableView setBackgroundColor:baseColor];
    [self.view setBackgroundColor:baseColor];

- (NSFetchedResultsController *)fetchedResultsController 

    if (_fetchedResultsController != nil) 
        return _fetchedResultsController;
    

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"Tasks" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *isCompleted = [[NSSortDescriptor alloc]initWithKey:@"sectionString" ascending:NO];
    NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                              initWithKey:@"dateCreated" ascending:YES];
    [fetchRequest setSortDescriptors:@[isCompleted, sort]];
    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                        managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"sectionString"
                                                   cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;


问题是表格视图没有填充应该由 nsfetchedresultscontroller 获取的项目。我不知道这是为什么...可能是因为 tableview 不是委托或其他什么?

【问题讨论】:

【参考方案1】:

NSFetchedResultsControllerDelegate 用于监控核心数据实体的更改,因此您不需要

    self.tableView = self.fetchedResultsController.delegate;

您需要使用 NSFetchedResultsController 实现 UITableViewDelegate 方法。主要是

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section 
    id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController.sections objectAtIndex:section];
    return sectionInfo.numberOfObjects;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
    return cell;

注意:创建 NSFetchedResultsController 后,您还必须调用 performFetch:

您可以看到一个很好的示例,通过使用主从模板并选中“使用核心数据”来实现所有这些。

【讨论】:

我觉得问题是我将tableview添加为子视图,而NSFC不知道将其发送到tableview NSFC 不向 tableview 发送数据,它只是包含数据。表格视图应该要求您的视图控制器通过 UITableViewDataSource 协议提供数据。 如果我尝试创建 XIB 而不是以编程方式创建 tableview,则不会加载 tableview。我不知道为什么 把tableview的设置代码放到viewDidLoad中,看看有没有帮助 没问题,我猜 initWithNibName 由于某种原因没有被调用,或者在 viewDidLoad 之后被调用。【参考方案2】:

对我来说,从 UITableViewController 转到包含 UITableView 的 UIViewController,我必须执行以下操作才能使 NSFetchedResultsController 工作:

    让视图控制器处理 UITableView 和 UITableViewDataSource 的委托方法:

    @interface UIViewControllerName : UIViewController

    将 UITableView 的委托和数据源(在我的情况下,我使用情节提要的插座将其称为 tableView)设置为 self(在我的情况下为 viewDidLoad)

    [super viewDidLoad];
    
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    
    appDelegate = [[UIApplication sharedApplication] delegate];
    self.managedObjectContext = [appDelegate managedObjectContext];
    
    NSError *error;
    if (![self.fetchedResultsController performFetch:&error]) 
        // handle error
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1); // fail
    
    

【讨论】:

以上是关于将 NSFetchedResultsController 从 UITableViewController 迁移到 UIViewController的主要内容,如果未能解决你的问题,请参考以下文章

CoreData、NSFetchedResultsController 和 performFetch:

将自己的博客园,打造成个人知乎

如何将thinkcmf导入eclipse

如何将Ios文件上传到

Javascript 将正则表达式 \\n 替换为 \n,将 \\t 替换为 \t,将 \\r 替换为 \r 等等

如何将视频文件转换格式