Search code examples
iosswiftxcodexib

NSUnknownKeyException when using an IBOutlet in UICollectionViewCell in .xib


I've been trying to add a label using an IBOutlet from an xib to a custom UICollectionViewCell class that is meant to be used as the cells for a UICollectionView that I have in another xib but when I add the outlet I get an NSUnknownKeyException on the label reference I've created, without the outlet reference the contents of the cell load properly but I want to be able to manipulate the label within the cell.

Heres what I have in my parent xib class:

class Calendar : UIView, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
   let nibName: String = "Calendar"
   let calendarDayNibName: String = "CalendarDay"
   let calendarReusableCellName: String = "CalendarCell"
   let calendarDaysLimit: Int = 35
   var contentView: UIView?

   @IBOutlet var sundayLabel: UILabel!
   @IBOutlet var mondayLabel: UILabel!
   @IBOutlet var tuesdayLabel: UILabel!
   @IBOutlet var wednesdayLabel: UILabel!
   @IBOutlet var thursdayLabel: UILabel!
   @IBOutlet var fridayLabel: UILabel!
   @IBOutlet var saturdayLabel: UILabel!
   @IBOutlet var calendarDays: UICollectionView!

   required init?(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)

       guard let view = self.loadViewFromNib() else { return }
       view.frame = self.bounds
       self.addSubview(view)
       contentView = view
       contentView?.isUserInteractionEnabled = true
   }

   override func awakeFromNib()
   {
       super.awakeFromNib()

       calendarDays.register(UINib(nibName: calendarDayNibName, bundle: nil), forCellWithReuseIdentifier:calendarReusableCellName)
       calendarDays.dataSource = self
   }

   func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
   {
       return calendarDaysLimit;
   }

   func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
   {
       let cell = collectionView.dequeueReusableCell(withReuseIdentifier: calendarReusableCellName, for: indexPath)
       configureCell(cell: cell)
       return cell
   }

   private func configureCell(cell: UICollectionViewCell)
   {
       //does nothing right now, placeholder for if configuring cell on
       //collection view load
   }

   private func loadViewFromNib() -> UIView? {
       let bundle = Bundle(for: type(of: self))
       let nib = UINib(nibName: nibName, bundle: bundle)
       self.isUserInteractionEnabled = true
       return nib.instantiate(withOwner: self, options: nil).first as? UIView
   }

   public func loadCalendarDays(month: Int)
   {
       //todo: write day loading logic here
   }
}

Here is the child xib class (UICollectionViewCell):

class CalendarDay: UICollectionViewCell
{
   @IBOutlet weak var dayLabel: UILabel!  
}

Here is my overall project if it helps to look at: https://github.com/CharlemagneVI/practice-calendar


Solution

  • You've set the classes and IBOutlet connections wrong... well, not-quite-right...

    In CalendarDay.xib, the class of File's Owner should be the default NSObject:

    enter image description here

    and it should not have any connections:

    enter image description here

    The class of the cell object itself should be CalendarDay:

    enter image description here

    and that is where you make your connection:

    enter image description here

    enter image description here

    That should do it :)