2017-09-18 2 views
1

Lorsque j'utilise des données de base pour enregistrer des images qui sont téléchargées à partir d'Internet dans la cellule collectionView, j'ai une erreur 'NSInternalInconsistencyException', raison: '- [UICollectionViewController loadview] chargé la pointe « BYZ-38-t0r-view-8BC-Xf-Vdc » mais n'a pas obtenu un UICollectionView.' Il est mon code de albumViewController:En utilisant les données de base, j'ai eu une erreur 'nib mais n'ai pas obtenu un UICollectionView.'

class albumViewController: coreDataCollectionViewController, MKMapViewDelegate { 

// Properties 

@IBOutlet weak var mapView: MKMapView! 
@IBOutlet weak var albumCollection: UICollectionView! 

override func viewDidLoad() { 
    super.viewDidLoad() 

    self.albumCollection.dataSource = self 
    self.albumCollection.delegate = self 
    // Show the pin 
    let spanLevel: CLLocationDistance = 2000 
    self.mapView.setRegion(MKCoordinateRegionMakeWithDistance(pinLocation.pinCoordinate, spanLevel, spanLevel), animated: true) 
    self.mapView.addAnnotation(pinLocation.pinAnnotation) 

    // Set the title 
    title = "Photo Album" 

    //Get the stack 
    let delegate = UIApplication.shared.delegate as! AppDelegate 
    let stack = delegate.stack 

    // Create a fetchrequest 
    let fr = NSFetchRequest<NSFetchRequestResult>(entityName: "Album") 
    fr.sortDescriptors = [NSSortDescriptor(key: "imageData", ascending: false),NSSortDescriptor(key: "creationDate", ascending: false)] 

    // Create the FetchedResultsController 
    fetchedResultsController = NSFetchedResultsController(fetchRequest: fr, managedObjectContext: stack.context, sectionNameKeyPath: nil, cacheName: nil) 

    // Put photos in core data 
    let photoURLs = Constants.photosUrl 
    for photoUrLString in photoURLs { 
     let photoURL = URL(string: photoUrLString) 
     if let photoData = try? Data(contentsOf: photoURL!) { 
      let photo = Album(imageData: photoData, context: fetchedResultsController!.managedObjectContext) 
     } else { 
      print("Image does not exist at \(photoURL)") 
     } 
    } 
} 

// Find number of items 
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    return 9 
} 


override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCollectionViewCell", for: indexPath) as! photoCollectionViewCell 
    let album = fetchedResultsController!.object(at: indexPath) as! Album 
    performUIUpdatesOnMain { 
     cell.photoImageView?.image = UIImage(data: album.imageData as! Data) 
    } 
    return cell 
} 

// Reload photos album 
@IBAction func loadNewPhotos(_ sender: AnyObject) { 
}  
} 

Il est mon code de

class coreDataCollectionViewController: UICollectionViewController { 

// Mark: Properties 
var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>? { 

    didSet { 
     // Whenever the frc changes, we execute the search and 
     // reload the table 
     fetchedResultsController?.delegate = self 
     executeSearch() 
     collectionView?.reloadData() 
    } 
} 

// Mark: Initializers 

init(fetchedResultsController fc: NSFetchedResultsController<NSFetchRequestResult>, collectionViewLayout: UICollectionViewFlowLayout) { 
    fetchedResultsController = fc 
    super.init(collectionViewLayout: collectionViewLayout) 
} 

// Do not worry about this initializer. I has to be implemented because of the way Swift interfaces with an Objective C protocol called NSArchiving. It's not relevant. 
required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
} 
} 

// Mark: CoreDataTableViewController (Subclass Must Implement) 
extension coreDataCollectionViewController { 

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    fatalError("This method MUST be implemented by a subclass of CoreDataTableViewController") 
} 
} 

// Mark: CoreDataTableViewController (Table Data Source) 

extension coreDataCollectionViewController { 

override func numberOfSections(in collectionView: UICollectionView) -> Int { 
    if let fc = fetchedResultsController { 
     return (fc.sections?.count)! 
    } else { 
     return 0 
    } 
} 

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    if let fc = fetchedResultsController { 
     return fc.sections![section].numberOfObjects 
    } else { 
     return 0 
    } 
} 
} 

// Mark: CoreDataTableViewController (Fetches) 

extension coreDataCollectionViewController { 

func executeSearch() { 
    if let fc = fetchedResultsController { 
     do { 
      try fc.performFetch() 
     } catch let error as NSError { 
      print("Error while trying to perform a search: \n\(error)\n\(fetchedResultsController)") 
     } 
    } 
} 

} 

// MARK: - CoreDataTableViewController: NSFetchedResultsControllerDelegate 

extension coreDataCollectionViewController: NSFetchedResultsControllerDelegate { 

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { 
} 
} 

Mais si je n'utilise pas co re données, je réussis. Y a-t-il une différence?

class albumViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, MKMapViewDelegate { 

// Properties 

@IBOutlet weak var mapView: MKMapView! 
@IBOutlet weak var albumCollection: UICollectionView! 

override func viewDidLoad() { 
    super.viewDidLoad() 
    let spanLevel: CLLocationDistance = 2000 
    self.mapView.setRegion(MKCoordinateRegionMakeWithDistance(location.pinCoordinate, spanLevel, spanLevel), animated: true) 
    self.mapView.addAnnotation(location.pinAnnotation) 
} 

// Find number of items 
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    return Constants.photosUrl.count 
} 


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCollectionViewCell", for: indexPath) as! photoCollectionViewCell 
    let photoURL = URL(string: Constants.photosUrl[(indexPath as NSIndexPath).item]) 
    if let photoData = try? Data(contentsOf: photoURL!) { 
     performUIUpdatesOnMain { 
      cell.photoImageView?.image = UIImage(data: photoData) 
     } 
    } else { 
     print("Image does not exist at \(photoURL)") 
    } 
    return cell 
} 

// Reload photos album 
@IBAction func loadNewPhotos(_ sender: AnyObject) { 
} 


} 

Par ailleurs, il est mon lien de code https://github.com/MartinSnow/MyVirtualTourist.git et mon projet est sur la branche « StoreLocation ».

Répondre

0

La principale différence entre ces deux implémentations, à l'exception de l'utilisation de CoreData, est que la version « de travail » est une sous-classe de UIViewController:

class albumViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, MKMapViewDelegate { .... } 

alors que la version jeter l'erreur est une sous-classe de UICollectionViewController :

class albumViewController: coreDataCollectionViewController, MKMapViewDelegate { .... } 
class coreDataCollectionViewController: UICollectionViewController { .... } 

UICollectionViewControllers exigent que leur racine view est un UICollectionView, ou une sous-classe de celle-ci. Dans votre storyboard, l'albumVC a une collection, mais n'est pas la vue racine.

La solution est de changer la définition de classe pour coreDataCollectionViewController à la sous-classe UIViewController et adopter la vue de la collecte des protocoles délégués et DataSource:

class albumViewController: coreDataCollectionViewController, MKMapViewDelegate { .... } 
class coreDataCollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource { .... } 

Notez également que l'erreur est effectivement lancée par votre scène mapViewController, qui est aussi une sous-classe de coreDataCollectionViewController et n'a pas de collectionView dans le storyboard. La correction ci-dessus devrait fonctionner pour cela aussi.

+0

J'ai essayé de remplacer 'UICollectionViewController' par 'UIViewController, UICollectionViewDelegate, UICollectionViewDataSource', mais il y a quelques erreurs dans le coreDataCollectionViewController. Et comment le résoudre? – Martin

+0

Difficile à résoudre, sans les détails de ces erreurs. Mais vous devrez supprimer les références à 'collectionView' car UIViewController n'a pas de propriété de ce nom (ou ajouter une propriété avec ce nom). – pbasdf