来自NSFetchedResults objectAtIndex:0返回0

时间:2010-11-30 08:20:54

标签: iphone objective-c cocoa

我现在已经在这个特定问题上敲了大约2个小时,阅读文档和示例,我无法绕过它。我有核心数据模型Person和Photo,它们是相互关联的。我正在尝试显示带有内容和

的UITableView
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

一直返回0.以下是相关代码。 我知道我的核心数据中有数据,因为我可以在终端使用sqlite查看它。

AppDelegate.h

@interface PaparazziAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;

    UITabBarController *tabController;
    UINavigationController *mainNavController;
    UINavigationController *recentsNavController;
    PersonListViewController  *personListView;
    PhotoListViewController *recentsList;
    PhotoDetailViewController *photoDetail;

    FlickrFetcher *fetcher;
    NSManagedObjectContext *currentContext;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

@property (nonatomic, retain) IBOutlet UITabBarController *tabController;
@property (nonatomic, retain) IBOutlet UINavigationController *mainNavController, *recentsNavController;

@end

AppDelegate.m

#import "PaparazziAppDelegate.h"

@implementation PaparazziAppDelegate

@synthesize window;
@synthesize tabController, mainNavController, recentsNavController;

#pragma mark -
#pragma mark Application lifecycle

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {   

    // Setup the database instances for access.
    fetcher = [FlickrFetcher sharedInstance];

    // Check to see if the database exists, if not, load the plist and populate.
    if ([fetcher databaseExists])
        NSLog(@"I'm here!");
    else {
        NSLog(@"No database yet!");

        currentContext = [fetcher managedObjectContext];

        /* -- REMOVED FOR READABILITY -- 
        A chunk of code for creating fresh data from a plist if the database doesn't yet exist.
        I know this part works because I can see the data using the terminal */

        [currentContext release];
    }
    // End of the plist loading and database creation.

    personListView = [[PersonListViewController alloc] initWithStyle:UITableViewStylePlain];
    personListView.title = @"Contacts";
    [mainNavController pushViewController:personListView animated:NO];
    [personListView release];

    recentsList = [[PhotoListViewController alloc] initWithNibName:@"PhotoListViewController" bundle:[NSBundle mainBundle]];
    recentsList.title = @"Recents";
    [recentsNavController pushViewController:recentsList animated:NO];
    [recentsList release];

    // setting up view icons
    UITabBarItem *contactsIcon = [[UITabBarItem alloc]
                          initWithTabBarSystemItem:UITabBarSystemItemContacts tag:0];
    mainNavController.tabBarItem = contactsIcon;
    [contactsIcon release];
    UITabBarItem *recentsIcon = [[UITabBarItem alloc]
                                  initWithTabBarSystemItem:UITabBarSystemItemRecents tag:0];
    recentsNavController.tabBarItem = recentsIcon;
    [recentsIcon release];

    [self.window addSubview:tabController.view];

    // Override point for customization after application launch.

    [self.window makeKeyAndVisible];

    return YES;
}

- (void)dealloc {
    [window release];
    [tabController release];
    [mainNavController release];
    [recentsNavController release];

    [fetcher release];

    [super dealloc];
}


@end

PersonListViewController.h

#import <UIKit/UIKit.h>
#import "FlickrFetcher.h"
#import "Person.h"
#import "Photo.h"

@interface PersonListViewController : UITableViewController {
    NSArray *listOfPeople;

    FlickrFetcher *fetcher;
    NSManagedObjectContext *currentContext;
    NSFetchedResultsController *fetchedResultsController;
}

@property (nonatomic, retain) NSArray *listOfPeople;
@property (nonatomic, retain) NSManagedObjectContext *currentContext;
@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;

@end

麻烦文件,PersonListViewController.m

#import "PersonListViewController.h"

@implementation PersonListViewController

@synthesize listOfPeople, currentContext, fetchedResultsController;

#pragma mark -
#pragma mark Initialization

- (id)initWithStyle:(UITableViewStyle)style {
    // Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization.
        fetcher = [FlickrFetcher sharedInstance];
        currentContext = [fetcher managedObjectContext];

        fetchedResultsController = [fetcher fetchedResultsControllerForEntity:@"Person" withPredicate:nil];
    }
    return self;
}

#pragma mark -
#pragma mark View lifecycle


- (void)viewDidLoad {
    [super viewDidLoad];

    self.title = @"Contacts";
}

#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.    
    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    Person *person = [fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [person name];

    // Configure the cell...

    return cell;
}

#pragma mark -
#pragma mark Memory management

- (void)dealloc {
    [super dealloc];
}

@end

我有一种感觉,我错过了一些简单或一次性的东西,但我似乎无法找到它。 [FlickrFetcher sharedInstance]返回一个单例,如果我在每个.m文件中输入几个断点,我可以看到每个区域中* fetcher的对象id是相同的。

2 个答案:

答案 0 :(得分:1)

看起来您没有使用performFetch:来执行提取的结果控制器请求。 viewWillAppear:通常是一个好地方:

 - (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    NSError *error = nil;
    if (![fetchedResultsController performFetch:&error]) {
        NSLog(@"fetch error: %@", error);
    }
 }

答案 1 :(得分:1)

顺便说一下 - 您可以考虑在viewDidLoad而不是initWithStyle:中初始化fetchedResultsController,然后您可以将其放在viewDidUnload中,从而在操作系统需要卸载时释放一些内存视图控制器。