Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView, nib from a framework target registered as a cell fails at runtime

I have a UICollectionViewCell drawn out in a xib and accompanied by swift class file. These two files are part of my app's UI framework target (called SomeUI).

In the view controller of my collection view (in the app target) I register the nib as a collection view cell. My view controller code is as follows;

import UIKit
import SomeUI

let reuseIdentifier = "Cell"

class ACollectionViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView.registerNib(UINib(nibName: "JamesTheCollectionViewCell", bundle: NSBundle(identifier: "SomeUI")), forCellWithReuseIdentifier: reuseIdentifier)
    }

    override func numberOfSectionsInCollectionView(collectionView: UICollectionView!) -> Int {
        return 1
    }

    override func collectionView(collectionView: UICollectionView!, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    override func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell! {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as JamesTheCollectionViewCell
        cell.titleLabel.text = "yippee"
        return cell
    }
}

In the nib, the cell view has its custom class set appropriately; JamesTheCollectionViewCell in module SomeUI.

screengrab of cell xib in xcode

While Xcode seems quite happy with this setup, at runtime i get an error as the class defined in JamesTheCollectionView.swift cannot be found.

Unknown class _TtC19collectionViewThing26JamesTheCollectionViewCell in Interface Builder file.

If I switch the target membership for JamesTheCollectionView.swift from the framework to the application (but leave the xib as part of the framework), everything runs fine. But, I asked the xib file to load the class from the framework… what am i missing, why doesn't it work when the cell implementation class is part of the framework?

For reference, here is the cell implementation file:

import UIKit

public class JamesTheCollectionViewCell: UICollectionViewCell {
    @IBOutlet public weak var titleLabel: UILabel!
}
like image 999
alexkent Avatar asked Aug 05 '14 12:08

alexkent


1 Answers

Solved.

TL:DR; When changing target membership for files, remember to do Product > Clean before next build!

Explanation: The problem was that "SomeUI" isn't a valid UIBundle identifier and so NSBundle(identifier: "SomeUI") returned nil, so the registerNib line registered a nib from the application bundle not the framework. The application bundle didn't contain the cell implementation class so it crashed.

But… the application bundle shouldn't have contained the nib either? So what was going on there? I had been switching the target membership for the nib and implementation file. I had not been running 'Clean' between builds, so a copy of the nib was left in the application target build folder.

The solution to original problem was to correctly load the nib from the SomeUI framework by replacing NSBundle(identifier: "SomeUI") with NSBundle(forClass: JamesTheCollectionViewCell.self)

like image 67
alexkent Avatar answered Nov 04 '22 05:11

alexkent