2013-07-25 55 views
4

我正在開發一個iOS應用程序,並在某個時間點存儲用戶在Core Data中繪製的圖像。 現在我想將所有錄製的圖像加載到UICollectionView中,以便用戶可以選擇一個並在社交網絡上共享。 除了這最後一部分,我的應用程序中的所有東西都可以工作。 我跟着網上的各種教程,但我可以在UICollectionView上找到的所有例子都是使用來自Flickr或類似網站的圖片。從核心數據加載UICollectionView

這是我在這一點上代碼:

#import "LibraryViewController.h" (The name of the class we're in) 
#import "SocialViewController.h" 
#import "CollectionViewCell.h" 


static NSString *cellIdentifier = @"MemeCell"; 

@implementation LibraryViewController { 
    NSMutableArray *_objectChanges; 
    NSMutableArray *_sectionChanges; 
} 


#pragma mark - View Controller LifeCycle 

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

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    _objectChanges = [NSMutableArray array]; 
    _sectionChanges = [NSMutableArray array]; 

    self.title = @"Meme collection"; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:@"share"]) { 
     NSIndexPath *indexPath = [[self.collectionView indexPathsForSelectedItems] lastObject]; 
     NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 
     SocialViewController *destViewController = segue.destinationViewController; 
     [destViewController setDetailItem:object]; 
    } 
} 

#pragma mark - UICollectionView 

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
{ 

    id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section]; 
    return [sectionInfo numberOfObjects]; 
} 

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    CollectionViewCell *cell = (CollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier 
                          forIndexPath:indexPath]; 

    NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    [cell setImage:[UIImage imageWithData:[object valueForKey:@"image"]]]; 

    return cell; 
} 


#pragma mark - Fetched results controller 

- (NSFetchedResultsController *)fetchedResultsController 
{ 
    if (_fetchedResultsController != nil) { 
     return _fetchedResultsController; 
    } 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    // Edit the entity name as appropriate. 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Meme" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    [fetchRequest setFetchBatchSize:20]; 
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"]; 
    aFetchedResultsController.delegate = self; 
    self.fetchedResultsController = aFetchedResultsController; 

    NSError *error = nil; 
    if (![self.fetchedResultsController performFetch:&error]) { 
    // Replace this implementation with code to handle the error appropriately. 
    // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
} 

    return _fetchedResultsController; 
} 

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
     atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type 
{ 
    NSMutableDictionary *change = [NSMutableDictionary new]; 

    switch(type) { 
     case NSFetchedResultsChangeInsert: 
      change[@(type)] = @(sectionIndex); 
      break; 
     case NSFetchedResultsChangeDelete: 
      change[@(type)] = @(sectionIndex); 
      break; 
    } 

    [_sectionChanges addObject:change]; 
} 

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject 
    atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type 
    newIndexPath:(NSIndexPath *)newIndexPath 
{ 
    NSMutableDictionary *change = [NSMutableDictionary new]; 
    switch(type) 
    { 
     case NSFetchedResultsChangeInsert: 
      change[@(type)] = newIndexPath; 
      break; 
     case NSFetchedResultsChangeDelete: 
      change[@(type)] = indexPath; 
      break; 
     case NSFetchedResultsChangeUpdate: 
      change[@(type)] = indexPath; 
      break; 
     case NSFetchedResultsChangeMove: 
      change[@(type)] = @[indexPath, newIndexPath]; 
      break; 
    } 
    [_objectChanges addObject:change]; 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
    if ([_sectionChanges count] > 0) 
    { 
     [self.collectionView performBatchUpdates:^{ 

      for (NSDictionary *change in _sectionChanges) 
      { 
       [change enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, id obj, BOOL *stop) { 

        NSFetchedResultsChangeType type = [key unsignedIntegerValue]; 
        switch (type) 
        { 
         case NSFetchedResultsChangeInsert: 
          [self.collectionView insertSections:[NSIndexSet indexSetWithIndex:[obj unsignedIntegerValue]]]; 
          break; 
         case NSFetchedResultsChangeDelete: 
          [self.collectionView deleteSections:[NSIndexSet indexSetWithIndex:[obj unsignedIntegerValue]]]; 
          break; 
         case NSFetchedResultsChangeUpdate: 
          [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:[obj unsignedIntegerValue]]]; 
          break; 
        } 
       }]; 
      } 
     } completion:nil]; 
    } 

    if ([_objectChanges count] > 0 && [_sectionChanges count] == 0) 
    { 
     [self.collectionView performBatchUpdates:^{ 

      for (NSDictionary *change in _objectChanges) 
      { 
       [change enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, id obj, BOOL *stop) { 

        NSFetchedResultsChangeType type = [key unsignedIntegerValue]; 
        switch (type) 
        { 
         case NSFetchedResultsChangeInsert: 
          [self.collectionView insertItemsAtIndexPaths:@[obj]]; 
          break; 
         case NSFetchedResultsChangeDelete: 
          [self.collectionView deleteItemsAtIndexPaths:@[obj]]; 
          break; 
         case NSFetchedResultsChangeUpdate: 
          [self.collectionView reloadItemsAtIndexPaths:@[obj]]; 
          break; 
         case NSFetchedResultsChangeMove: 
          [self.collectionView moveItemAtIndexPath:obj[0] toIndexPath:obj[1]]; 
          break; 
        } 
       }]; 
      } 
     } completion:nil]; 
    } 

    [_sectionChanges removeAllObjects]; 
    [_objectChanges removeAllObjects]; 
} 

@end 

當我運行,並嘗試訪問該視圖控制器,應用程序崩潰與此錯誤消息: 2013年7月25日23:08:11.832 MemeGen [ 87259:C07] *終止應用程序由於未捕獲的異常「NSInvalidArgumentException」,原因是:「+ entityForName:無不是合法的NSManagedObjectContext參數搜索實體名稱‘梅梅’」 *第一擲調用堆棧:

和它指向這行代碼:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Meme" inManagedObjectContext:self.managedObjectContext]; 

顯然self.managedObjectContext爲零。 我應該如何分配它?當用戶首次啓動應用程序並且核心數據爲空時,我應該如何管理它?禁止訪問,只要沒有圖像?

否則,我知道如何將繪製圖像存儲在文件系統上。如果有人知道在UICollectionView中加載它的方法,它也可能是我可以接受的解決方案。

回答

0

您將希望獲得對您的ManagedObjectContext的引用。通常這會在應用程序委託中創建。在這種情況下,你會想這樣的事情 -

NSManagedObjectContext *aManagedObjectContext = ((AppDelegate *)[UIApplication sharedApplication].delegate).managedObjectContext; 

如果你願意,你可以做到這一點在你的viewDidLoad並將其分配給self.managedObjectContext。

+0

謝謝你的幫助!我發現丟失了什麼,現在存儲的圖像被加載,並且不再崩潰...... 我需要在fetchedResultsController方法中添加這些行: NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@「image」ascending:NO]; NSArray * sortDescriptors = @ [sortDescriptor]; – lweingart

+0

並添加此方法: - (NSManagedObjectContext *)managedObjectContext { NSManagedObjectContext * context = nil; id delegate = [[UIApplication sharedApplication] delegate]; if([delegate performSelector:@selector(managedObjectContext)]){context = [delegate managedObjectContext]; } return context; } – lweingart

1

除非您使用外部存儲功能,否則我不建議將圖像存儲在覈心數據中。大的二進制對象很少是你想要存儲在覈心數據之類的東西。當然,您可以將文件系統路徑或URL存儲在指向文件系統映像的核心數據對象上。

要使用帶有UICollectionView的Core Data,請查看NSFetchedResultsController。 這裏有一個example使用這兩者來幫助你入門。

+0

謝謝你的回答。實際上,我發現我的代碼中缺少什麼(但我不能在超過8小時之前發佈它:-))。如果我在覈心數據中創建我的對象時選擇外部存儲,是否足夠?否則,我很樂意學習從應用程序的Document文件夾中加載這些圖像的方法......我將查看您提供的鏈接。非常感謝您的幫助 ! – lweingart

+0

我去看你提供的鏈接,由Ash Furrow編寫的文件屬於其中一個我遵循的教程,這幫助我編寫了這門課程。 (是你嗎?)再次感謝。 – lweingart