UICollectionView Memory Leak Crash - objective-c

My CollectionView is retrieving images from the Parse network, and keeps crashing. I keep getting memory warnings right before the crash. I'm guessing I need to free up space. But the problem is i'm relatively new to coding so I don't know how to do this. I don't even know where the memory needs to be freed from. Could someone please help me understand what I am doing wrong in my code?
- (void)viewDidLoad {
[super viewDidLoad];
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"NavBar1.png"] forBarMetrics:UIBarMetricsDefault];
// self.navigationController.hidesBarsOnSwipe = true;
[self queryParseMethodCell];
// Do any additional setup after loading the view.
}
- (void)queryParseMethodCell {
NSLog(#"start Money");
PFQuery *query3 = [PFQuery queryWithClassName:#"MainWall"];
PFQuery *query4 = [PFQuery queryWithClassName:#"MainWall"];
[query3 orderByDescending:#"createdAt"];
[query4 orderByAscending:#"createdAt"];
[query3 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"check bobby");
imageFilesArray2 = [[NSArray alloc] initWithArray:objects];
[self.HomePost reloadData];
}
else{
NSLog(#"NO Good33");
}
}];
[query4 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"check bobby");
imageFilesArray3 = [[NSArray alloc] initWithArray:objects];
[self.HomePost reloadData];
}
else{
NSLog(#"NO Good44");
}
}];
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.lastContentOffset > scrollView.contentOffset.y) {
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
else if (self.lastContentOffset < scrollView.contentOffset.y){
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
else {
NSLog(#"Andy Error1");
}
}
- (IBAction)SwipeLeft:(UISwipeGestureRecognizer *)sender {
[self performSegueWithIdentifier:#"Notifications" sender:self];
}
- (IBAction)SwipeRight:(UISwipeGestureRecognizer *)sender{
[self performSegueWithIdentifier:#"FavWall" sender:self];
}
- (IBAction)MainWall:(id)sender{
[self performSegueWithIdentifier:#"MainWall" sender:self];
}
- (IBAction)FavWall:(id)sender{
[self performSegueWithIdentifier:#"FavWall" sender:self];
}
- (IBAction)Notifications:(id)sender{
[self performSegueWithIdentifier:#"Notifications" sender:self];
}
- (IBAction)Home:(id)sender{
[self performSegueWithIdentifier:#"Home" sender:self];
}
- (IBAction)YourAccount:(id)sender{
[self performSegueWithIdentifier:#"YourAccount" sender:self];
}
- (IBAction)UsersAccount:(id)sender{
[self performSegueWithIdentifier:#"UsersAccount" sender:self];
}
-(IBAction)PicTake:(id)sender{
[self performSegueWithIdentifier:#"Camera" sender:self];
}
#pragma mark Collection View
-(NSInteger )numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [imageFilesArray2 count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"TopCell";
DiscoverCell *cell = nil;
if (cell == nil) {
cell = (DiscoverCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
}
else {
NSLog(#"2Error");
}
PFObject *imageObject2 = [imageFilesArray2 objectAtIndex:indexPath.row];
cell.Username.text = [imageObject2 objectForKey:#"Name"];
PFFile *imageFile3 = [imageObject2 objectForKey:#"ProfilePicture"];
[imageFile3 getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
NSLog(#"CheckCash");
// cell.TopStory.image = [UIImage imageWithData:data];
cell.HomeImg.image = [UIImage imageWithData:data];
cell.Back.image = [UIImage imageWithData:data];
//cell.HomeImg2.image = [UIImage imageWithData:data];
}
else{
NSLog(#"NO Good");
}
cell.HomeImg.layer.cornerRadius = cell.HomeImg.frame.size.width /2;
cell.HomeImg.clipsToBounds = YES;
cell.Back.image = cell.HomeImg.image;
}];
PFObject *imageObject5 = [imageFilesArray3 objectAtIndex:indexPath.row];
cell.Username.text = [imageObject5 objectForKey:#"Name"];
PFFile *imageFile4 = [imageObject5 objectForKey:#"ProfilePicture"];
[imageFile4 getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
NSLog(#"CheckCash");
cell.TopStory.image = [UIImage imageWithData:data];
}
else{
NSLog(#"NO Good22");
}
}];
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

You have a memory leak. Everytime you scroll all images all reloaded. Something like this should solve the problem
//at start For every data DataisNotLoaded should be true
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
if dataisNotLoaded[index] {
DataisNotLoaded[index] = false
[imageFile3 getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
NSLog(#"CheckCash");
// cell.TopStory.image = [UIImage imageWithData:data];
cell.HomeImg.image = [UIImage imageWithData:data];
cell.Back.image = [UIImage imageWithData:data];
//cell.HomeImg2.image = [UIImage imageWithData:data];
}
else{
NSLog(#"NO Good");
}
}

Related

How to display video from ALAsset to UICollectionview Cell

I tried this code to add all ALAsset created video into my app and then play it. But the video doesn't show in UICollectionView. How is it possible?
I write this code in View Did Load.
_collectionView.dataSource=self;
_collectionView.delegate=self;
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
_allVideos = [[NSMutableArray alloc] init];
ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
[assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
if (group)
{
[group setAssetsFilter:[ALAssetsFilter allVideos]];
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
if (asset)
{
_dic = [[NSMutableDictionary alloc] init];
ALAssetRepresentation *defaultRepresentation = [asset defaultRepresentation];
NSString *uti = [defaultRepresentation UTI];
NSURL *videoURL = [[asset valueForProperty:ALAssetPropertyURLs] valueForKey:uti];
NSString *title = [NSString stringWithFormat:#"video %d", arc4random()%100];
UIImage *image = [self imageFromVideoURL:videoURL];
[_dic setValue:image forKey:#"image"];
[_dic setValue:title forKey:#"name"];
[_dic setValue:videoURL forKey:#"url"];
//[_allVideos addObject:_dic];
[_allVideos addObject:asset];
[_collectionView reloadData];
}
}];
}
}
failureBlock:^(NSError *error)
{
NSLog(#"error enumerating AssetLibrary groups %#\n", error);
}];
}
And One method is
- (UIImage *)imageFromVideoURL:(NSURL*)videoURL
{
// result
UIImage *image = nil;
// AVAssetImageGenerator
AVAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];;
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
imageGenerator.appliesPreferredTrackTransform = YES;
// calc midpoint time of video
Float64 durationSeconds = CMTimeGetSeconds([asset duration]);
CMTime midpoint = CMTimeMakeWithSeconds(durationSeconds/2.0, 600);
// get the image from
NSError *error = nil;
CMTime actualTime;
CGImageRef halfWayImage = [imageGenerator copyCGImageAtTime:midpoint actualTime:&actualTime error:&error];
if (halfWayImage != NULL)
{
// CGImage to UIImage
image = [[UIImage alloc] initWithCGImage:halfWayImage];
[_dic setValue:image forKey:#"name"];
NSLog(#"Values of dictionary==>%#", _dic);
NSLog(#"Videos Are:%#",videoURL);
CGImageRelease(halfWayImage);
}
return image;
}
And I wrote this in UICollectionView:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return _allVideos.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
NSLog(#"allvideo %#", _allVideos);
ALAsset *alasset = [_allVideos objectAtIndex:indexPath.row];
UIImageView *imageview=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 80, 80)];
imageview.image = [UIImage imageWithCGImage:alasset.thumbnail];
[cell.contentView addSubview:imageview];
return cell;
}
Write the code in ViewDidLoad
assets = [[NSMutableArray alloc] init];
_library = [[ALAssetsLibrary alloc] init];
UIImage *viewImage;
[_library writeImageToSavedPhotosAlbum:[viewImage CGImage] orientation:(ALAssetOrientation)[viewImage imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
NSLog(#"error");
} else {
NSLog(#"url %#", assetURL);
}
}];
[_library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop){
if (group != NULL) {
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop){
if ([[result valueForProperty:ALAssetsGroupPropertyName] isEqual:#"VideoMaker"]) {
NSLog(#"asset: %#", result);
[assets addObject:result];
}
}];
}
[self.collectionView reloadData];
//[self.activity stopAnimating];
//[self.activity setHidden:YES];
}
failureBlock:^(NSError *error){
NSLog(#"failure"); }];`} `
In this assets is NSMutableArray and library is the ALAssetLibrary.
In UIcollectionviewcell cell for rowAtIndexpath method
-(VideoCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
VideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CELL" forIndexPath:indexPath];
ALAsset *asset = [assets objectAtIndex:indexPath.row];
[cell.videoImageView setImage:[UIImage imageWithCGImage:[asset thumbnail]]];
return cell;
}

iCarousel + Parse: Loading Async Images from PFObject

I am trying to populate an iCarousel with a parse (parse.com, pfoject) object without success.
I can't find any example of how to do it, so it why i am asking here...
- (void)viewDidLoad
{
[super viewDidLoad];
_items = [NSMutableArray array];
PFQuery *query = [PFQuery queryWithClassName:#"testUser"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded. The first 100 objects are available in objects
[_items addObjectsFromArray:objects];
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
//configure carousel
_carousel.type = iCarouselTypeRotary;
//_carousel.viewpointOffset = CGSizeMake(0.0f, 100.0f);
[_carousel setContentOffset:CGSizeMake(0.0f, -60.0f)];
}
And at viewForItemAtIndex:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
//create new view if no view is available for recycling
if (view == nil)
{
view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 300.0f, 300.0f)];
}
PFObject *eachObject = [_items objectAtIndex:index];
PFFile *theImage = [eachObject objectForKey:#"image"];
NSData *imageData = [theImage getData];
UIImage *image = [UIImage imageWithData:imageData];
((UIImageView *)view).image = image;
view.contentMode = UIViewContentModeCenter;
return view;
}
Please, any help? :-(
In viewDidLoad, After the
[_items addObjectsFromArray:objects];
Put
[_carousel reloadData];
Otherwise the carousel won't be updated after the items have been added to the array, so you'll still be looking at an empty carousel.

UITableView stopped loading data in IOS7 and Xcode5

I have a simple view which has been successfully loading a table of data from CoreData for the last 18 months. It even works now on devices that have been upgraded to IOS 7. But when I upgraded to Xcode5 and run through the IOS7 3.5inch retina simulator my table is always empty. I have pasted my code below and I can confirm that the fetchRequests are returning the data because I can see this in the NSLog outputs. But why has be table stopped populating the cells?
I feel really stupid because I just cannot figure this one out…
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"listData count in numberOFRowsInSection is: %i", listData.count);
return [self.listData count];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Sessions *info = [_fetchedResultsController objectAtIndexPath:indexPath];
NSLog(#"info content is: %#", info.sport);
//Format cell data ready to be displayed
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EE, dd LLL yyyy"];
NSString *dateString = [dateFormat stringFromDate:info.date];
NSNumber *dist1Nbr = info.dist1;
int dist1Int = [dist1Nbr integerValue];
float distIntKorM = ([dist1Nbr integerValue])/1000;
NSString *dist1StrMeters = [[NSString alloc] initWithFormat:#"%i", dist1Int];
NSString *dist1StrKorM = [[NSString alloc] initWithFormat:#"%.01f", distIntKorM];
//Select image to display
if ([info.sport isEqualToString:#"Run"]) {
UIImage *image = [UIImage imageNamed:#"trainers-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
NSLog(#"Cell text for Runs shoudl be: %#", cell.textLabel.text);
} else if ([info.sport isEqualToString:#"Other"]) {
UIImage *image = [UIImage imageNamed:#"weights-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
} else if ([info.sport isEqualToString:#"Swim"]) {
UIImage *image = [UIImage imageNamed:#"goggles-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#m", info.sessiontype, dist1StrMeters];
NSLog(#"Cell text for Swims shoudl be: %#", cell.textLabel.text);
} else if ([info.sport isEqualToString:#"Cycle"]) {
UIImage *image = [UIImage imageNamed:#"bike-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
} else if ([info.sport isEqualToString:#"Brick"]) {
UIImage *image = [UIImage imageNamed:#"brick-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"editSession";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// this cell backgrond colour alternating works!
UIView *bgColor = [cell viewWithTag:100];
if (!bgColor) {
CGRect frame = CGRectMake(0, 0, 320, 50);
bgColor = [[UIView alloc] initWithFrame:frame];
bgColor.tag = 100;
[cell addSubview:bgColor];
[cell sendSubviewToBack:bgColor];
}
if (indexPath.row % 2 == 0) {
bgColor.backgroundColor = [UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1.0];
} else {
bgColor.backgroundColor = [UIColor clearColor]; }
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (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;
if (_context == nil)
{
_context = [(SGK_T4T_01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", _context);
}
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1);
} else {
NSLog(#"After fetchedResultsController: %#", _fetchedResultsController);
//NSLog(#"After managedObjectContext: %#", _fetchedResultsController);
}
self.title = #"Sessions";
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[self setListData:nil];
[self setSelectedSession:nil];
[self setSessionSport:nil];
//[self setRecordCount:nil];
[self setFetchedResultsController:nil];
[self setContext:nil];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
SGK_T4T_01AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDiscription = [NSEntityDescription entityForName:#"Sessions" inManagedObjectContext:context];
//NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"refid" ascending:YES];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDiscription];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil) {
NSLog(#"The fetch request returned an array == nil");
} else {
NSLog(#"The fetch request returned an array!!!");
NSLog(#"objects contents is: %#", objects);
NSLog(#"objects count = %i", [objects count]);
listData = objects;
NSLog(#"listData count = %i", [listData count]);
//NSUInteger *recordCount = [objects count];
recordCount = [objects count];
}
//reload tableView:dataSource from CoreData when view reappears...
if (_context == nil)
{
_context = [(SGK_T4T_01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", _context);
}
NSError *error1;
if (![[self fetchedResultsController] performFetch:&error1]) {
NSLog(#"Unresolved error %#, %#", error1, [error1 userInfo]);
exit(-1);
} else {
NSLog(#"viewWillAppear: fetchedResultsController: %#", _fetchedResultsController);
}
//end of reload tableView:dataSource from CoreData when view reappears...
[self.tableView reloadData];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//[self setFetchedResultsController:nil];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
//[self setFetchedResultsController:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[_context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
NSError *error = nil;
if (![_context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
[self.tableView reloadData];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
if (type == NSFetchedResultsChangeDelete) {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSUInteger index = indexPath.row;
//NSLog(#" Prep4Seg indexPath.row = %u", index);
//NSLog(#" Prep4Seg recordCount = %u", recordCount);
/*
Subtract the row index from the row count to get the correct position in the Array (because I am sorting on date order so tableCell position 0 is position 2 in the Array (if there are 3 only items in the table and array) so if you don't invert the indexPath you end up passing the last item instead of the first or second last item instead of the second and so on...
*/
NSUInteger arrayIndex = (recordCount-index-1);
//NSLog(#" Prep4Seg arrayIndex = %u", arrayIndex);
selectedSession = [listData objectAtIndex:arrayIndex];
//NSLog(#"listData = %#", listData);
//NSLog(#"SelectedSession = %#", selectedSession);
NSNumber *refId = [selectedSession valueForKey:#"refid"];
NSString *refIdToSend = [[NSString alloc] initWithFormat:#"%#", refId];
NSLog(#"Prep4Seg in tableView: refIdToSend = %#", refIdToSend);
if ([segue.identifier isEqualToString:#"editSession"]) {
SGK_T4T_EditSessionDetail *editSessionDetail = segue.destinationViewController;
editSessionDetail.delegate = (id)self;
editSessionDetail.returnFromDatePickerView = [[NSString alloc] initWithFormat:#"no"];
editSessionDetail.recedIndex = refIdToSend;
}
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
And my log output is:
2013-11-09 16:04:04.034 trainForTri copy[6509:a0b] After managedObjectContext: <NSManagedObjectContext: 0xb589bc0>
2013-11-09 16:04:04.036 trainForTri copy[6509:a0b] After fetchedResultsController: <NSFetchedResultsController: 0xb5e2c40>
2013-11-09 16:04:04.040 trainForTri copy[6509:a0b] The fetch request returned an array!!!
2013-11-09 16:04:04.041 trainForTri copy[6509:a0b] objects contents is: (
"<NSManagedObject: 0xb5c8570> (entity: Sessions; id: 0xb5ac970 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p1> ; data: <fault>)",
"<NSManagedObject: 0xb5d6320> (entity: Sessions; id: 0xb58a2a0 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p2> ; data: <fault>)",
"<NSManagedObject: 0xb5d0370> (entity: Sessions; id: 0xb5dc270 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p3> ; data: <fault>)",
"<NSManagedObject: 0xb5e3dd0> (entity: Sessions; id: 0xb5ebcc0 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p4> ; data: <fault>)",
"<NSManagedObject: 0xb585e40> (entity: Sessions; id: 0xb5e4e40 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p5> ; data: <fault>)"
)
2013-11-09 16:04:04.041 trainForTri copy[6509:a0b] objects count = 5
2013-11-09 16:04:04.042 trainForTri copy[6509:a0b] listData count = 5
2013-11-09 16:04:04.043 trainForTri copy[6509:a0b] viewWillAppear: fetchedResultsController: <NSFetchedResultsController: 0xb5a01e0>
2013-11-09 16:04:04.043 trainForTri copy[6509:a0b] listData count in numberOFRowsInSection is: 5
OK, found the issue with this. Eventually after almost wanting to throw my Macbook out of the window in frustration with Xcode5 I shut everything down and restarted. when I opened Xcode, built and ran my App it lo longer loaded an empty table - it now produced an error which indicated that there was something wrong with my NSFetchedResultsController. I traced it to an issue with the cache not clearing (or not being mutable) - so I removed the cache name and set it to nil and everything is working again. I am not sure if this is an IOS7/Xcode5 issue but it has not been a problem until this upgrade. For anyone searching for a similar fix here is the offending line of code:
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:#"Root"];
And this is the version that works!
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:nil];
I hope I'm not the only one ever to struggle with this and therefore just a thickie!

UITableView reload data takes forever

I parse a couple of things via JSON into a table view but I have the problem that the parsing takes about a second (I know this due to the network indicator) but then there is a huge delay until the data appears in the table view.
I tried to place [tableView reloadData]; at a couple of places already but no success.
Here is my code.
I have defined mainThreadQueue and myClassicoAPI as a macro.
- (void)viewDidLoad
{
[super viewDidLoad];
arrayNeuheiten = [[NSArray alloc] init];
arrayArtikelName = [[NSArray alloc] init];
dictionaryNewStuff = [[NSDictionary alloc] init];
[self parseJSONWithURL:myClassicoAPI];
//[self performSelector:#selector(updateTableView) withObject:nil afterDelay:NO];
[neuheietenTable reloadData];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[neuheietenTable reloadData];
}
-(void) updateTableView {
[neuheietenTable reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfRowsInSection:(NSInteger)section {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//return (self.arrayNeuheiten.count<17)?self.arrayNeuheiten.count : 17;
return MIN(18, arrayNeuheiten.count);
}
-(void) parseJSONWithURL: (NSURL *) jsonURL {
dispatch_async(mainThreadQueue, ^{
NSError *error = nil;
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSString *json =[NSString stringWithContentsOfURL:jsonURL encoding:NSJSONWritingPrettyPrinted error:&error];
if (error == nil) {
NSData *jsonData = [json dataUsingEncoding:NSJSONWritingPrettyPrinted];
dictionaryNewStuff = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
if (error == nil) {
dispatch_async(mainThreadQueue, ^{
arrayArtikelName = [[dictionaryNewStuff valueForKey:#"newstuff"] valueForKey:#"Neuheiten"];
arrayNeuheiten = [[dictionaryNewStuff valueForKey:#"newstuff"] valueForKey:#"Neuheiten"];
[neuheietenTable reloadData];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
});
} else {
nil;
}
} else {
nil;
}
});
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"NeuheitenCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [[arrayArtikelName objectAtIndex:indexPath.row] objectForKey:#"name"];
return cell;
}
Thanks in advance
Constantin
You're loading the data synchronous on the mainthread which is bad and blocking the interface.
Try loading your JSON data with NSURLConnection and reload your UITableView in the
(void)connectionDidFinishLoading:(NSURLConnection *)aConnection
method when you're done processing it.
Hello I am bit modify the code with one public url and its work fine. Look at the code which useful to solve your problem:
- (void)viewDidLoad
{
[super viewDidLoad];
arrayNeuheiten = [[NSArray alloc] init];
arrayArtikelName = [[NSArray alloc] init];
dictionaryNewStuff = [[NSDictionary alloc] init];
[neuheietenTable reloadData];
NSURL *url = [NSURL URLWithString:#"http://122.182.14.104:3004/build/product/15.json"];
[self parseJSONWithURL:url];
//[self performSelector:#selector(updateTableView) withObject:nil afterDelay:NO];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfRowsInSection:(NSInteger)section {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//return (self.arrayNeuheiten.count<17)?self.arrayNeuheiten.count : 17;
return arrayArtikelName.count;
}
-(void) parseJSONWithURL: (NSURL *) jsonURL {
NSError *error = nil;
NSString *json =[NSString stringWithContentsOfURL:jsonURL encoding:NSJSONWritingPrettyPrinted error:&error];
if (error == nil) {
NSData *jsonData = [json dataUsingEncoding:NSJSONWritingPrettyPrinted];
dictionaryNewStuff = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
if (error == nil) {
arrayArtikelName = [dictionaryNewStuff valueForKey:#"attributes"];
// arrayNeuheiten = [[dictionaryNewStuff valueForKey:#"newstuff"] valueForKey:#"Neuheiten"];
[neuheietenTable reloadData];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
} else {
nil;
}
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"NeuheitenCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [[arrayArtikelName objectAtIndex:indexPath.row] objectForKey:#"name"];
return cell;
}

NSFetchedResultsController & UITableViewController not communicating

I have some "details" saved into my Core Data, and I'm trying to call it out from an NSFetchedResultsController into my tableView. For whatever reason, the tableView isn't populating once the block is finished running.
I have been searching and asking everywhere I can to try and figure out this whole Core Data debacle. Hopefully, someone on here is kind enough to help me out!
HomeViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"Home";
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0 green:0.7 blue:2.3 alpha:1];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:#selector(addShindy:)];
self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"light_alu.png"]];
self.tableView.opaque = NO;
self.tableView.backgroundView = nil;
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(refresh:)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
[self setShindyDatabase:self.shindyDatabase];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.shindyDatabase) {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
self.shindyDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
}
}
- (void)refresh:(UIRefreshControl *)sender
{
[self useDocument];
[sender endRefreshing];
}
- (void)addShindy:(UIBarButtonItem *)sender
{
AddShindyViewController *addShindyViewController = [[AddShindyViewController alloc] initWithNibName:#"AddShindyViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addShindyViewController];
[self presentViewController:navController animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma Core Date Stack
- (void)fetchShindyDataIntoDocument:(UIManagedDocument *)document
{
dispatch_queue_t fetchIntoDocument = dispatch_queue_create("Fetch Into Document", nil);
dispatch_async(fetchIntoDocument, ^{
NSArray *shindys = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
for (NSDictionary *shindyInfo in shindys) {
[Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:document.managedObjectContext];
}
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
});
}
- (void)setShindyDatabase:(UIManagedDocument *)shindyDatabase
{
if (_shindyDatabase != shindyDatabase) {
_shindyDatabase = shindyDatabase;
[self useDocument];
}
}
- (void)useDocument
{
NSError *error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.shindyDatabase.fileURL path]]) {
NSLog(#"Create document");
[self.shindyDatabase saveToURL:self.shindyDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
[self fetchShindyDataIntoDocument:self.shindyDatabase];
if (!success) {
NSLog(#"error for creation of document: %#", [error localizedDescription]);
}
}];
} else if (self.shindyDatabase.documentState == UIDocumentStateClosed) {
NSLog(#"Closed document");
[self.shindyDatabase.managedObjectContext.parentContext performBlock:^{
[self setupFetchedResultsController];
}];
} else if (self.shindyDatabase.documentState == UIDocumentStateNormal) {
NSLog(#"Normal Document");
[self setupFetchedResultsController];
}
if (error) {
NSLog(#"Error in useDocument: %#", [error localizedDescription]);
}
}
- (void)setupFetchedResultsController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shindy"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"details" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
// request.predicate = [NSPredicate predicateWithFormat:#"details = %#", [self.shindyDatabase valueForKey:#"details"]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.shindyDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
#pragma mark - Table view data source
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 75;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
Shindy *shindy = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(#"%#", shindy.details);
cell.textLabel.text = shindy.details;
Shindy+CreateDB.m
+ (Shindy *)shindyWithShindyDBInfo:(NSDictionary *)shindyInfo
inManagedObjectContext:(NSManagedObjectContext *)context
{
Shindy *shindy = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shindy"];
// NSSortDescriptor *dateAndTimeSort = [NSSortDescriptor sortDescriptorWithKey:#"dateAndTime" ascending:YES];
NSSortDescriptor *detailsSort = [NSSortDescriptor sortDescriptorWithKey:#"details" ascending:YES];
// NSSortDescriptor *locationSort = [NSSortDescriptor sortDescriptorWithKey:#"location" ascending:YES];
// NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
// NSSortDescriptor *photoSort = [NSSortDescriptor sortDescriptorWithKey:#"photo" ascending:YES];
// NSSortDescriptor *timePostedSort = [NSSortDescriptor sortDescriptorWithKey:#"timePosted" ascending:YES];
// title
request.sortDescriptors = [NSArray arrayWithObject:detailsSort];
// request.sortDescriptors = [NSArray arrayWithObjects:dateAndTimeSort, detailsSort, locationSort, nameSort, photoSort, timePostedSort, nil];
NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
if (error) {
NSLog(#"document failed in file: %#", [error localizedDescription]);
}
if (!matches || ([matches count] > 1)) {
NSError *error = nil;
NSLog(#"error in DBInfo: %#", [error localizedDescription]);
} else if ([matches count] == 0) {
shindy = [NSEntityDescription insertNewObjectForEntityForName:#"Shindy" inManagedObjectContext:context];
// shindy.dateAndTime = [shindyInfo objectForKey:#"dateAndTime"];
shindy.details = [shindyInfo objectForKey:#"details"];
// shindy.location = [shindyInfo objectForKey:#"location"];
// shindy.name = [shindyInfo objectForKey:#"name"];
// shindy.photo = [shindyInfo objectForKey:#"photo"];
// shindy.timePosted = [shindyInfo objectForKey:#"timePosted"];
// title
// Guestlist? The rest?
// Use below for reference
// shindy.whoseShindy = [User userWithName:[shindyInfo objectForKey:#"whoseShindy"] inManagedObjectContext:context];
} else {
shindy = [matches lastObject];
}
return shindy;
}
EDIT:
I suppose I should have also shown a file of which I have set as a subclass of my HomeViewController. It's basically the same thing as the code that is given to you to paste in the Apple Documentation
CoreDataTableViewController.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface CoreDataTableViewController : UITableViewController <NSFetchedResultsControllerDelegate>
#property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
- (void)performFetch;
#property (nonatomic) BOOL suspendAutomaticTrackingOfChangesInManagedObjectContext;
#property BOOL debug;
#end
CoreDataTableViewController.m
#interface CoreDataTableViewController()
#property (nonatomic) BOOL beganUpdates;
#end
#implementation CoreDataTableViewController
#pragma mark - Properties
#synthesize fetchedResultsController = _fetchedResultsController;
#synthesize suspendAutomaticTrackingOfChangesInManagedObjectContext = _suspendAutomaticTrackingOfChangesInManagedObjectContext;
#synthesize debug = _debug;
#synthesize beganUpdates = _beganUpdates;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark - Fetching
- (void)performFetch
{
if (self.fetchedResultsController) {
if (self.fetchedResultsController.fetchRequest.predicate) {
if (self.debug) NSLog(#"[%# %#] fetching %# with predicate: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate);
} else {
if (self.debug) NSLog(#"[%# %#] fetching all %# (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName);
}
NSError *error;
[self.fetchedResultsController performFetch:&error];
if (error) NSLog(#"[%# %#] %# (%#)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]);
} else {
if (self.debug) NSLog(#"[%# %#] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
[self.tableView reloadData];
}
- (void)setFetchedResultsController:(NSFetchedResultsController *)newfrc
{
NSFetchedResultsController *oldfrc = _fetchedResultsController;
if (newfrc != oldfrc) {
_fetchedResultsController = newfrc;
newfrc.delegate = self;
if ((!self.title || [self.title isEqualToString:oldfrc.fetchRequest.entity.name]) && (!self.navigationController || !self.navigationItem.title)) {
self.title = newfrc.fetchRequest.entity.name;
}
if (newfrc) {
if (self.debug) NSLog(#"[%# %#] %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), oldfrc ? #"updated" : #"set");
[self performFetch];
} else {
if (self.debug) NSLog(#"[%# %#] reset to nil", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
[self.tableView reloadData];
}
}
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[[self.fetchedResultsController sections] objectAtIndex:section] name];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [self.fetchedResultsController sectionIndexTitles];
}
#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) {
[self.tableView beginUpdates];
self.beganUpdates = YES;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
if (self.beganUpdates) [self.tableView endUpdates];
}
- (void)endSuspensionOfUpdatesDueToContextChanges
{
_suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;
}
- (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend
{
if (suspend) {
_suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
} else {
[self performSelector:#selector(endSuspensionOfUpdatesDueToContextChanges) withObject:0 afterDelay:0];
}
}
#end
And then last, but not least, I have the header file for my HomeViewController of which I implement CoreDataTableViewController. Hopefully this is useful in better explaining what I've got.
HomeViewController.h
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#import "CoreDataTableViewController.h"
#interface HomeViewController : CoreDataTableViewController
#property (strong, nonatomic) UIManagedDocument *shindyDatabase;
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
#end
It's quite difficult to see what is going on, but, I think you need to do the following steps when the block has finished (I suppose this since I don't see any similar in your code).
execute the fetch request through the fetched controller
reload the data table
So,
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
// error handling here...
}
[yourTable reloadData];
Try and let me know. If doesn't work, try to edit a minimal question because there is too much code to follow.
Hope that helps.
I ended up figuring this, and many other Core Data issues I was having. I wasn't setting my managed object context to a store!! DUH!!!
self.managedObjectContext = [(AppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];
That did the trick. Everything began working after that.
I hope this is able to point out another duh to anybody out there forgetting the same thing I did!