Objective c NSFetchedResultsController不';即使在数据库中创建了项,也无法获取结果
我是iOS新手,所以如果这很简单,我道歉。。。在开始实现我的完整应用程序之前,我一直在反复研究一些小的概念验证应用程序,这样它就不会像以前那样让人难以承受了。当我按照苹果网站上的“你的第二个iOS应用程序”教程创建表视图时,我的表视图工作正常。现在我已经尝试在选项卡栏应用程序中创建它,但我发现NSFetchedResultsController存在问题,我不确定它是否与我在情节提要中出错的内容有关,或者与其他内容有关 我有一个选项卡栏控制器,它连接到嵌入在导航控制器中的表视图控制器(CatalogViewController.h/m)。表视图控制器配置为具有静态单元格。在第一个静态单元格中,我有一个到另一个表视图控制器(FoodCatalogViewController.h/m)的推送序列,该控制器配置为使用动态原型-这是我希望从数据库(从食物实体-当前仅显示名称和卡路里)中看到对象的视图。此视图有一个“添加”按钮,用于在数据库中创建新条目-添加按钮有一个到另一个静态表视图(AddFoodViewController.h/m)的模式序列,该静态表视图嵌入到它自己的导航控制器中。我知道“添加”按钮正在工作,并且它的视图正确连接到数据库(即,我正在正确传递/设置NSManagedObjectContext),因为如果我使用“sqlite数据库浏览器”打开应用程序的sqlite数据库文件,我会看到我在模拟器中添加的项目。我只是不明白为什么它们没有通过NSFetchedResultsController显示在我的表视图中。我使用断点逐步检查了代码,并确认正在我的FoodCatalogViewController的fetchedResultsController函数中调用performFetch代码。我在numberOfRowsInSection代码中添加了一个调试NSLog行,它似乎为零,因此我从未进入cellForRowAtIndexPath或configureCell。所以看起来NSFetchedResultsController是罪魁祸首-我只是不知道为什么它不能正确获取结果,以及我可以做些什么来进一步调试它。有人能帮我吗 为了通过层次结构传递核心数据信息,我有以下代码段: AppDelegate.m:Objective c NSFetchedResultsController不';即使在数据库中创建了项,也无法获取结果,objective-c,core-data,ios5,Objective C,Core Data,Ios5,我是iOS新手,所以如果这很简单,我道歉。。。在开始实现我的完整应用程序之前,我一直在反复研究一些小的概念验证应用程序,这样它就不会像以前那样让人难以承受了。当我按照苹果网站上的“你的第二个iOS应用程序”教程创建表视图时,我的表视图工作正常。现在我已经尝试在选项卡栏应用程序中创建它,但我发现NSFetchedResultsController存在问题,我不确定它是否与我在情节提要中出错的内容有关,或者与其他内容有关 我有一个选项卡栏控制器,它连接到嵌入在导航控制器中的表视图控制器(Catalo
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
// Setup the Catalogs Tab
UINavigationController *navigationController = [[tabBarController viewControllers] objectAtIndex:0];
CatalogViewController *catalogViewController = [[navigationController viewControllers] objectAtIndex:0];
catalogViewController.managedObjectContext = self.managedObjectContext;
return YES;
}
CatalogViewController.m(序列中的第一个表视图控制器-我将NSManagedObjectContext传递给它):
FoodCatalogViewController.h(序列中的第二个表视图控制器-我使用NSManagedObjectContext设置NSFetchedResultsController):
FoodCatalogViewController.m(要添加到数据库的AddFoodViewController协议代码):
更多调试信息奇怪-看起来fetchedResultsController在FoodCatalogViewController中无法正常工作,即使managedObjectContext似乎正在工作。。。下面是来自FoodCatalogViewController.m的修改过的fetchedResultsController函数,其中包含一些调试NSLog语句,并将self.fetchedResultsController替换为u fetchedResultsController(因为我想知道这是否是导致问题的原因) 以下是fetchedResultsController函数NSLog调用的输出:
2012-01-29 10:22:21.118 UltraTrack[19294:fb03] Result: (
"<Food: 0x6e651b0> (entity: Food; id: 0x6e64630 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p1> ; data: <fault>)",
"<Food: 0x6e653e0> (entity: Food; id: 0x6e61870 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p3> ; data: <fault>)",
"<Food: 0x6e65450> (entity: Food; id: 0x6e64420 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p4> ; data: <fault>)",
"<Food: 0x6e654c0> (entity: Food; id: 0x6e64430 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p5> ; data: <fault>)",
"<Food: 0x6e65530> (entity: Food; id: 0x6e64e80 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p2> ; data: <fault>)",
"<Food: 0x6e655b0> (entity: Food; id: 0x6e64e90 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p6> ; data: <fault>)"
)
2012-01-29 10:22:21.907 UltraTrack[19294:fb03] Number or objects: 6
有人认为部分是问题所在,因此我将numberOfSectionsInTableView硬编码为返回1,然后fetchResults中的第一个对象似乎得到了正确处理,但我得到了以下异常:
2012-01-29 10:29:27.296 UltraTrack[19370:fb03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no object at index 1 in section at index 0'
如果我将numberOfRowsInSection硬编码为也返回1,则数据库中的第一个对象将正确显示在表视图中。fetchedResultsController中的节信息可能有什么问题?我是否可以在序列图像板中为表视图设置一些与节有关的错误内容
下面是我尝试过硬编码的两个表视图函数:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
//NSLog(@"Number of sections in table view is %d", [[self.fetchedResultsController sections] count]);
//return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(@"Number or objects: %d", [self.fetchedResultsController.fetchedObjects count]);
// If I return 1, the object is displayed correctly, if I return count, I get the exception
//return 1;
return [self.fetchedResultsController.fetchedObjects count];
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
NSLog(@"Number of rows being returned is %d", [sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];
}
-(NSInteger)节数表视图:(UITableView*)表视图
{
返回1;
//NSLog(@“表视图中的节数为%d”,[[self.fetchedResultsController节数]);
//返回[[self.fetchedResultsController节]计数];
}
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节
{
NSLog(@“数量或对象:%d”,[self.fetchedResultsController.fetchedObject计数];
//如果我返回1,则对象显示正确;如果我返回count,则得到异常
//返回1;
返回[self.fetchedResultsController.fetchedObject计数];
//返回节中的行数。
id sectionInfo=[[self.fetchedResultsController节]objectAtIndex:section];
NSLog(@“返回的行数为%d”,[sectionInfo numberOfObjects]);
返回[sectionInfo numberOfObjects];
}
从您的描述来看,带章节的代码似乎是罪魁祸首。但实际上您并没有使用任何部分。因此,请尝试以下方法来简化:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.fetchedResultsController.fetchedObjects count];
}
如果仍然返回零行,请检查
fetchedResultsController
getter方法中的fetchedObject.count
如果在保存数据的情况下重新启动应用程序,是否会显示在表视图中?这只是一个令人耳目一新的问题吗?不-当我重新启动应用程序时,它也不会显示。它总是空的,表视图中没有显示任何值。能否包括SQL输出,以及创建新对象的“添加视图”控制器中的代码?@jrturton,我刚刚添加了其他代码。您希望看到什么SQL输出?您最近的错误是因为您使用%@作为整数的格式说明符-使用%d。我想你可能没问题——我唯一发现的就是自我。在您的访问器中,您似乎已经解决了这个问题。我尝试了这个,看起来它在该部分中必须返回非零行数,但现在在我的configureCell函数中
#import <UIKit/UIKit.h>
@protocol AddFoodViewControllerDelegate;
@interface AddFoodViewController : UITableViewController <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITextField *foodNameInput;
@property (weak, nonatomic) IBOutlet UITextField *caloriesInput;
@property (weak, nonatomic) id <AddFoodViewControllerDelegate> delegate;
- (IBAction)save:(id)sender;
- (IBAction)cancel:(id)sender;
@end
@protocol AddFoodViewControllerDelegate <NSObject>
- (void)addFoodViewControllerDidCancel:(AddFoodViewController *)controller;
- (void)addFoodViewControllerDidSave:(AddFoodViewController *)controller name:(NSString *)name calories:(NSNumber *)calories;
@end
#import "AddFoodViewController.h"
@implementation AddFoodViewController
@synthesize foodNameInput;
@synthesize caloriesInput;
@synthesize delegate = _delegate;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)viewDidUnload
{
[self setFoodNameInput:nil];
[self setCaloriesInput:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ((textField == self.foodNameInput) || (textField == self.caloriesInput )) {
[textField resignFirstResponder];
}
return YES;
}
- (IBAction)save:(id)sender {
int caloriesInt = [self.caloriesInput.text intValue];
NSNumber *caloriesNum = [NSNumber numberWithInt:caloriesInt];
[[self delegate] addFoodViewControllerDidSave:self name:self.foodNameInput.text calories:caloriesNum];
}
- (IBAction)cancel:(id)sender {
[[self delegate] addFoodViewControllerDidCancel:self];
}
@end
- (void)addFoodViewControllerDidCancel:(AddFoodViewController *)controller {
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (void)addFoodViewControllerDidSave:(AddFoodViewController *)controller name:(NSString *)name calories:(NSNumber *)calories {
if ([name length]) {
[self addFoodWithName:name calories:calories];
[[self tableView] reloadData];
}
[self dismissModalViewControllerAnimated:YES];
}
- (void) addFoodWithName:(NSString *)name calories:(NSNumber *)calories {
// Create a new instance of the entity managed by the fetched results controller.
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSLog(@"entity name is %@", [entity name]);
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template.
[newManagedObject setValue:name forKey:@"name"];
[newManagedObject setValue:calories forKey:@"calories"];
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
NSString* uuid = [NSString stringWithString:(__bridge NSString *)uuidStringRef];
[newManagedObject setValue:uuid forKey:@"uuid"];
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
2012-01-29 10:22:21.118 UltraTrack[19294:fb03] Result: (
"<Food: 0x6e651b0> (entity: Food; id: 0x6e64630 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p1> ; data: <fault>)",
"<Food: 0x6e653e0> (entity: Food; id: 0x6e61870 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p3> ; data: <fault>)",
"<Food: 0x6e65450> (entity: Food; id: 0x6e64420 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p4> ; data: <fault>)",
"<Food: 0x6e654c0> (entity: Food; id: 0x6e64430 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p5> ; data: <fault>)",
"<Food: 0x6e65530> (entity: Food; id: 0x6e64e80 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p2> ; data: <fault>)",
"<Food: 0x6e655b0> (entity: Food; id: 0x6e64e90 <x-coredata://8A10B827-9F10-4760-934C-0061A982B73C/Food/p6> ; data: <fault>)"
)
2012-01-29 10:22:21.907 UltraTrack[19294:fb03] Number or objects: 6
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil) {
return __fetchedResultsController;
}
// Set up the fetched results controller.
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Food" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
__fetchedResultsController = aFetchedResultsController;
NSArray *result = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
NSLog(@"Result: %@", result);
NSError *error = nil;
if (![__fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
NSLog(@"Number or objects: %d", [__fetchedResultsController.fetchedObjects count]);
return __fetchedResultsController;
}
2012-01-29 10:29:27.296 UltraTrack[19370:fb03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no object at index 1 in section at index 0'
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
//NSLog(@"Number of sections in table view is %d", [[self.fetchedResultsController sections] count]);
//return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(@"Number or objects: %d", [self.fetchedResultsController.fetchedObjects count]);
// If I return 1, the object is displayed correctly, if I return count, I get the exception
//return 1;
return [self.fetchedResultsController.fetchedObjects count];
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
NSLog(@"Number of rows being returned is %d", [sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.fetchedResultsController.fetchedObjects count];
}