views:

242

answers:

2

I have encountered a problem of placing data into the Table View. Here is my current code. I am unable to load the results from the class I tried to use NSFetchedResultsController, but it won't work. Can any one see the mistake. This is the header file.

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import <sqlite3.h>
#import "FlickrFetcher.h"
@interface PersonList : UITableViewController {
    FlickrFetcher *fetcher;
    NSArray *nameList;
    NSArray *names;
    NSFetchedResultsController *results;
    NSArray *photos;
}
@property (retain, nonatomic)NSArray *nameList;
@property (retain, nonatomic)NSArray *names;
@property (retain, nonatomic)NSArray *photos;
@property (retain, nonatomic)NSFetchedResultsController *results;
@end

This is the .m file.

#import "PersonList.h"


@implementation PersonList
@synthesize nameList,names,results,photos;

 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
      self.title=@"Contacts";
        // Custom initialization
    }
    return self;
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    fetcher = [FlickrFetcher sharedInstance];
    NSString *path=[[NSBundle mainBundle]pathForResource:@"FakeData" ofType:@"plist"];
    NSArray *array=[NSArray arrayWithContentsOfFile:path];
    NSManagedObjectContext *context=[fetcher managedObjectContext];
    if([fetcher databaseExists]==YES){
        for(NSDictionary *dic in array){
            PersonList *person=(PersonList *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
            [person setNameList:[dic objectForKey:@"user"]];
            [person setPhotos:[dic objectForKey:@"path"]];
            names=[fetcher fetchManagedObjectsForEntity:@"Person" withPredicate:nil];
            results=[fetcher fetchedResultsControllerForEntity:@"Person" withPredicate:nil];
        }       
    }
    [super viewDidLoad];
}


/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (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.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.names=nil;
}


- (void)dealloc {
    [fetcher release];
    [nameList release];
    [super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[results sections] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"NOT REACHED HERE");
    static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
                             SimpleTableIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc]
                 initWithStyle:UITableViewCellStyleDefault
                 reuseIdentifier:SimpleTableIdentifier] autorelease];
    }
    NSUInteger row = [indexPath row];
    cell.textLabel.text = [[results sections] objectAtIndex:row];
    return cell;
}
@end

This the method for the FlickrFetcher method

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

@interface FlickrFetcher : NSObject {
    NSManagedObjectModel *managedObjectModel;
    NSManagedObjectContext *managedObjectContext;
    NSPersistentStoreCoordinator *persistentStoreCoordinator;
}

// Returns the 'singleton' instance of this class
+ (id)sharedInstance;

// Checks to see if any database exists on disk
- (BOOL)databaseExists;

// Returns the NSManagedObjectContext for inserting and fetching objects into the store
- (NSManagedObjectContext *)managedObjectContext;

// Returns an array of objects already in the database for the given Entity Name and Predicate
- (NSArray *)fetchManagedObjectsForEntity:(NSString*)entityName withPredicate:(NSPredicate*)predicate;

// Returns an NSFetchedResultsController for a given Entity Name and Predicate
- (NSFetchedResultsController *)fetchedResultsControllerForEntity:(NSString*)entityName withPredicate:(NSPredicate*)predicate;

@end
+10  A: 
  1. Put your call to [super viewDidLoad] before your code. The only time a call to super should be after your code is in the -dealloc method.
  2. You are looping over array, getting a NSFetchedResultsController and doing nothing with it. You are not even keeping a reference. This is incorrect. You should have ONE NSFetchedResultsController per UITableViewController; you should retain reference to it; your UITableViewDatasource (which in this case is your UITableViewController) should be its delegate.
  3. You are not calling -performFetch: on the NSFetchedResultsController so there is no data being retrieved.
  4. Because you are not the delegate of the NSFetchedResultsController you would have no way of knowing when it got data back anyway because that is the singular way that it communicates data changes.

I would reconsider your design and review the Core Data iPhone sample projects again.

Update

The NSFetchedResultsController does not fire its delegate methods until you save the NSManagedObjectContext so that is why you are not seeing data.

As for the error you are getting, you are trying to set a property on an object that does not respond to that property. I would suggest loading your application into the debugger, putting a breakpoint on objc_exception_throw and see what object you are manipulating that is causing the problem. Most likely you are getting back one object and thinking it is another.

Marcus S. Zarra
Absolutely right - I deleted my hastily-postd misinformation. :-)
Joshua Nozzi
A: 

Ok, So I had done what you said, I placed super viewDidLoad method before my code. I had also placed it out the which only one will be NSFetchedResultsController per UITableView Controller, however I have a problem retrieving data. Do we have to save it or something. I had transferred most of it to the AppDelegate. I have been skimming through some sample projects, but I encountered a problem. The fecher method had a problem. Did I do something wrong? This is what is located on my appDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application {  

    tabBarController =[[UITabBarController alloc] init];
    // Override point for customization after app launch    
    PersonList *personList=[[PersonList alloc]initWithStyle:UITableViewStylePlain];
    UINavigationController *tableNavController=[[UINavigationController alloc]initWithRootViewController:personList];
    tableNavController.title=@"Contacts";
    tableNavController.tabBarItem=[[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemContacts tag:0];
    UINavigationController *recentNavController=[[UINavigationController alloc]init];
    recentNavController.title=@"Recents";
    recentNavController.tabBarItem=[[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemRecents tag:1];
    tabBarController.viewControllers=[NSArray arrayWithObjects:tableNavController,recentNavController,nil];

    // Override point for customization after app launch 
    [window addSubview:tabBarController.view];
    [tableNavController release];
    [recentNavController release];

    fetcher = [FlickrFetcher sharedInstance];
    NSString *path=[[NSBundle mainBundle]pathForResource:@"FakeData" ofType:@"plist"];
    NSArray *array=[NSArray arrayWithContentsOfFile:path];
    NSManagedObjectContext *context=[fetcher managedObjectContext];
    if([fetcher databaseExists]==YES){
        for(NSDictionary *dic in array){
            PersonList *person=(PersonList *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
            [person setNameList:[dic objectForKey:@"user"]];
            [person setPhotos:[dic objectForKey:@"path"]];

        }
        for(NSDictionary *dic in array){
        PhotoList *photo=(PhotoList *)[NSEntityDescription insertNewObjectForEntityForName:@"PhotoList" inManagedObjectContext:context];
        [photo setDetailName:[dic objectForKey:@"user"]];
        [photo setName:[dic objectForKey:@"name"]];
        [photo setPath:[dic objectForKey:@"path"]];
        }
    }
    [window makeKeyAndVisible];
}

Did I do it wrong??

Here is the area that I encountered a problem at on my .m file. Did I do anything wrong here the out put was: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath name not found in entity '

- (void)viewDidLoad {
    [super viewDidLoad];
    fetcher=[FlickrFetcher sharedInstance];
    NSPredicate *predicate=[NSPredicate predicateWithFormat:@"NameList == NameList"];
    NSArray *nas=[fetcher fetchManagedObjectsForEntity:@"Person" withPredicate:predicate];
    NSLog(@"%@",nas);
    results=[fetcher fetchedResultsControllerForEntity:@"Person" withPredicate:predicate];
    NSError *error;
    BOOL work=[results performFetch:&error];
    if(work ==YES){
        NSLog(@"Finally Worked");
    }else{
        NSLog(@" Wrong");
    }
    NSLog(@"%@",results);
}

Can anyone point out the error?

Instead of adding an answer with an additional question, you should amend your question. Otherwise people will miss your "update" for an answer and ignore it.
Marcus S. Zarra