首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用核心数据,我得到了一个错误'nib但没有得到UICollectionView‘。

使用核心数据,我得到了一个错误'nib但没有得到UICollectionView‘。
EN

Stack Overflow用户
提问于 2017-09-19 07:19:44
回答 1查看 307关注 0票数 1

当我使用核心数据将从互联网上下载的一些图像保存在collectionView单元中时,我得到了一个错误‘NSInternalInconsistencyException’,原因是:‘-UICollectionViewController loadView加载了“BYZ-38-t0r-view-8bc-Xf-vdC”nib但没有获得UICollectionView。“下面是我的albumViewController代码:

代码语言:javascript
复制
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) {
}    
}

这是我的代码

代码语言:javascript
复制
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>) {
}
}

但如果我不使用核心数据,我就会成功。有什么不同吗?

代码语言:javascript
复制
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) {
}


} 

顺便说一下,这是我的代码链接https://github.com/MartinSnow/MyVirtualTourist.git,我的项目在"storeLocation“分支上。

EN

回答 1

Stack Overflow用户

发布于 2017-09-19 15:57:10

除了使用CoreData之外,这两种实现之间的关键区别在于,“工作”版本是UIViewController的子类

代码语言:javascript
复制
class albumViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, MKMapViewDelegate { .... }

而抛出错误的版本是UICollectionViewController的子类

代码语言:javascript
复制
class albumViewController: coreDataCollectionViewController, MKMapViewDelegate { .... }
class coreDataCollectionViewController: UICollectionViewController { .... }

UICollectionViewControllers要求它们的根viewUICollectionView或它的子类。在情节提要中,albumVC有一个collectionView,但不是根视图。

解决方案是将coreDataCollectionViewController的类定义更改为UIViewController的子类,并采用集合视图委托和数据源协议:

代码语言:javascript
复制
class albumViewController: coreDataCollectionViewController, MKMapViewDelegate { .... }
class coreDataCollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource { .... }

另请注意,该错误实际上是由mapViewController场景引发的,该场景也是coreDataCollectionViewController的子类,并且在故事板中没有collectionView。上面的修复方法也应该适用于此。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46289489

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档