This question already has answers here:
Xcode - How to fix 'NSUnknownKeyException', reason: … this class is not key value coding-compliant for the key X" error?
(79 answers)
Closed 7 years ago.
I'm trying to create a UICollectionViewCell subclass with linked a xib, I have do this:
I have create a new xib file and I have add a UICollectionViewCell in it, then I have create this subclass file:
#interface MyCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *label;
#end
Also I have linked in the file owner custom class the MyCell class in interface builder, and I have added a UILabel, then in my UICollectionView viewDidLoad I do this:
[self.collectionView registerClass:[MyCell class] forCellWithReuseIdentifier:#"MyCell"];
UINib *cellNib = [UINib nibWithNibName:#"MyCell" bundle:nil];
[self.collectionView registerNib:cellNib forCellWithReuseIdentifier:#"MyCell"];
As well as in this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = (MyCell*)[cv dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
cell.label.text = #"Cell Text";
return cell;
}
However this doesn't work, I receive this error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x907eca0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key label.'
What did I do wrong? How can I connect a UICollectionViewCell subclass to a xib, and display it in a UICollectionView?
EDIT:
i have do this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = #"MyCell";
static BOOL nibMyCellloaded = NO;
if(!nibMyCellloaded)
{
UINib *nib = [UINib nibWithNibName:#"MyCell" bundle: nil];
[cv registerNib:nib forCellWithReuseIdentifier:identifier];
nibMyCellloaded = YES;
}
MyCell *cell = (MyCell*)[cv dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
cell.labelCell.text = #"Text";
return cell;
}
Make sure the cell on the .xib file know what's the type of the cell.
Select the cell on your interface builder
and then on the identity inspector
Subsequently associate your labels with your properties. (I think you already did that)
Then I'd recommend to verify if you already loaded the .xib file on your cellForItemAtIndexPath: method
NSString *identifier = #"MyCell";
static BOOL nibMyCellloaded = NO;
if(!nibMyCellloaded)
{
UINib *nib = [UINib nibWithNibName:#"MyCell" bundle: nil];
[cv registerNib:nib forCellWithReuseIdentifier:identifier];
nibMyCellloaded = YES;
}
You can find the answer in this document UICollectionView adding UICollectionCell.
Only UICollectionView inside StoryBoard have UICollectionViewCell inside. If use XIB, create a new XIB with CellName.xib, add CollectionViewCell to it, specify name of UICollectionView custom class. After that use registerNib.Sample code: https://github.com/lequysang/TestCollectionViewWithXIB
Related
i am using two different uicollectionview with different two different uicollectionviewcell and structure of cell is also different how to i register both cell class in one controller view .
[self.collectionView registerClass:[HCTabBarItemCell class]
forCellWithReuseIdentifier:[HCTabBarItemCell reuseIdentifier]];
In case if you load your custom UICollectionViewCell subclass from .xib file you should also register its nib:
[self.collectionView registerNib:[HCTabBarItemCell nibName]
forCellWithReuseIdentifier:[HCTabBarItemCell reuseIdentifier]];
where class methods nibName & reuseIdentifier are declared and implemented in your (base) custom cell class:
+ (NSString *)reuseIdentifier {
return NSStringFromClass([self class]);
}
+ (UINib *)nibName {
return [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil];
}
Then just get your custom cell in cellForRow method by reuseIdentifier:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
HCTabBarItemCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:[HCTabBarItemCell reuseIdentifier]
forIndexPath:indexPath];
return cell;
}
I want use registerNib: forCellReuseIdentifier: method in my app
when i was made custom cell with xib file is fine. (ex:SwitchTableViewCell2.xib )
because file name is xib name.
working well code:
[self.tableView registerNib:[UINib nibWithNibName:#"SwitchTableViewCell2" bundle:nil] forCellReuseIdentifier:#"xibcell"];
but did not working when i made prototypecells on tableview in mainStoryboard.
how to get xibname of prototypecell on storyboard?
anybody can test this link: github.com/Kernelzero/test_nav
add image files here
this controller name : 'PushSettingController'
this controller's storyboard id: 'pushSetting'
If you use prototype cell,Identifier name must same as dequeueReusableCellWithIdentifier name
NOTE:If you use prototype cell, you don't need to register the cell.Because Prototype cell is not a CustomCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"switchcell"];
if(cell == nil)
{
cell =[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"";
return cell;
}
But if you use custom cell,follow the below steps
1.in viewDidLoad you must register the custom cell
UINib *cellNib = [UINib nibWithNibName:#"SwitchTableViewCell2" bundle:[NSBundle mainBundle]];
[self.tableView registerNib:cellNib forCellReuseIdentifier:#"switchcell"];
2.OR in cellForRowAtIndexPath you can write the code below like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *customTableIdentifier=#"switchcell";
SwitchTableViewCell2 *cell=(SwitchTableViewCell2*)[tableView dequeueReusableCellWithIdentifier:customTableIdentifier];
if (cell==nil)
{
NSArray *nibs=[[NSBundle mainBundle]loadNibNamed:#"SwitchTableViewCell2" owner:self options:nil];
cell=[nibs objectAtIndex:0];
}
cell.yourSwitchTableViewCell2Label.text = #"";
cell.yourSwitchTableViewCell2TextField.text = #"";
cell.yourSwitchTableViewCell2Button.text = #"";
return cell;
}
Take the registerNib call out when using the Storyboard. If you've set the storyboard up correctly, the prototype cells are already registered to the tableView.
There's no need to load it from nib. Call:
Objective-C
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"switchcell];
Swift
let cell = tableView.dequeueReusableCellWithIdentifier("switchcell")
I am trying to create a custom table view cell with a xib but when I call:
CustomReferenceTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
I get the following:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x7aa59c00> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key
Here is my setup:
- (void)viewWillAppear:(BOOL)animated
{
[self.tableView registerNib:[UINib nibWithNibName:#"CustomReferenceTableViewCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:#"referenceCell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"referenceCell";
CustomReferenceTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[CustomReferenceTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.number.text = #"1";
cell.referenceName.text = #"Name";
cell.reference.text = #"The text of the reference";
return cell;
}
Here is a picture of my connections in interface builder. Also my cellIdentifiers match between class and xib:
I have seen this post here but I still can't seem to get it work.
Help would be greatly appreciated.
Edit
Here is a pic showing setting of custom class. Below that is my initialiser for the tableViewCell:
Here is the header:
#import <UIKit/UIKit.h>
#interface CustomReferenceTableViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *number;
#property (nonatomic, weak) IBOutlet UILabel *referenceName;
#property (nonatomic, weak) IBOutlet UILabel *reference;
#end
And here is the implementation:
#import "CustomReferenceTableViewCell.h"
#implementation CustomReferenceTableViewCell
- (void)awakeFromNib {
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
I think you are setting the file owner of the cell to your custom cell which you shouldn't do. The way to get things working for a custom cell is,
In your xib, have a Table View Cell component an populate the contents of the cell in its ContentView.
Make your class CustomReferenceTableViewCell as the Custom Class of that cell component.
Now, do NOT register the cell in your tableview; instead do the following in the cellForRowAtIndexPath when your cell is nil after [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; and then register it:
cell = [self.tableView dequeueReusableCellWithIdentifier:cellID];
if(cell == nil) {
[self.tableView registerNib:[UINib nibWithNibName:[#"CustomReferenceTableViewCell" ] bundle:nil] forCellReuseIdentifier:cellID];
NSArray *nibContents;
CustomReferenceTableViewCell *cell;
nibContents = [[NSBundle mainBundle]
loadNibNamed:nibName owner:self options:NULL];
NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
NSObject *nibItem = nil;
while ((nibItem = [nibEnumerator nextObject]) != nil) {
if ([nibItem isKindOfClass:[CustomReferenceTableViewCell class]]) {
cell = (CustomReferenceTableViewCell *)nibItem;
}
}
}
This method has been working out for me for the past 8 months. I have no reasons why it could cause a problem to you.
Try to set your static NSString *cellIdentifier = #"referenceCell"; above #interface
And change registerNib place from WillAppear to viewDidLoad. Also you can change cell creating
CustomReferenceTableViewCell *cell = (CustomReferenceTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle]loadNibNamed:#"CustomReferenceTableViewCell" owner:self options:nil] lastObject];
}
Just follow my coding for your app
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:#"Reuse"];
NSArray *nib=[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
if(cell == nil)
{
cell = [nib objectAtIndex:0];
}
cell.number.text = #"1";
cell.referenceName.text = #"Name";
cell.reference.text = #"The text of the reference";
return cell;
}
Firstly CodingVoldermort's answer helped me get to sort out the issue. I was setting the File's Owner to my custom class which you shouldn't do. This should be left as NSObject.
The reason I thought it needed to be changed was because I couldn't hook up my IBOutlets by holding control and clicking on the tableview image under placeholders and dragging to the appropriate view in the xib.
Instead I needed to go under 'Show the connection inspector' pane and control + click and drag from there to get the connections to work. Then my original posted code would work.
Many thanks for all the responses guys.
I am getting this error. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UICollectionViewCell label]: unrecognized selector sent to instance 0x1eead660' I am using a nib file as my cell and trying to displays the cells correctly. I am guessing that I am not returning cells correctly, but I am not too sure. Any help will be appreciated.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"Cell"];
Cell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
NSMutableArray *data = [sections objectAtIndex:indexPath.section];
cell.label.text = [data objectAtIndex:indexPath.item];
return cell;
}
UICollectionViewCell doesn't have a property called label.
Perhaps you meant:
[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:#"Cell"];
Assuming you subclassed UICollectionViewCell, added label, and called your subclass Cell.
Your nib file probably needs to be connected to your custom class ('Cell'?) somehow. That done, you'd call:
[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:#"Cell"];
As it stands right now, you are getting a vanilla UICollectionViewCell object back from dequeue..., and when you try to use it as a Cell, you get problems.
BTW, generally, your registerClass code should not go in cellForItemAtIndexPath. It only needs to be called once per view, e.g.
static NSString *cellIdentifier = #"Cell";
#implementation YourCollectionViewController
// ...
- (void)viewDidLoad
{
[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:#"Cell"];
}
// ...
#end
I'm trying to get a UICollectionView to display inside a modally presented view controller. The app is for iPad iOS 7.
I've created subclass of UIViewController (with a nib) and added it like this:
MyViewController *controller = [[MyViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
navController.modalPresentationStyle = UIModalPresentationFullScreen;
navController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
[self presentViewController:navController animated:YES completion:nil];
This view controller is to be the delegate and dataSource for my UICollectionView so I've added UICollectionViewDataSource and UICollectionViewDelegate to the header.
I've put a UICollectionView into the nib and added an outlet to MyViewController:
#property (strong, nonatomic) IBOutlet MyCollectionView *collectionViewController;
I've added this in viewDidLoad in MyViewController:
self.collectionViewController.dataSource = self;
self.collectionViewController.delegate = self;
I've also added the following to MyViewController:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
NSLog(#"Items in section: %d", itemsArray.count); // returns correct amount
return itemsArray.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cellForItemAtIndexPath %#", indexPath); // returns as expected
static NSString *identifier = #"MyCell";
[self.collectionViewController registerClass:[MyCollectionCell class] forCellWithReuseIdentifier:identifier];
MyCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *myImageView = (UIImageView *)[cell viewWithTag:100];
myImageView.image = [UIImage imageNamed:[itemsArray objectAtIndex:indexPath.row]];
return cell;
}
I've also set up a subclass of UICollectionViewCell with the identifier set to MyCell and added to it a UIImageView with the tag 100.
Whenever I bring up this view controller I'm getting the navigation bar as expected, but the UICollection view I've added to my nib is nowhere to be seen. All I'm seeing is black where the collection view should be. If I change the background colour of MyCollectionView from default to white, I see white where the collection view ought to be. It seems to be bringing up MyCollectionView, but not showing any cells.
One other point of interest is that if you set the cell's identifier in the nib or storyboard, don't register the nib/class in the collection view controller. Do one or the other, but not both.
If you link your collectionView and its own dataSource and delegate in your xib file, you don't need to set up this on your code.
Next, you need to register your UICollectionViewCell :
- (void)viewDidLoad
{
[super viewDidLoad];
// Register Nib
[self.collectionView registerNib:[UINib nibWithNibName:CollectionViewCell_XIB bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:CollectionViewCell_ID];
}
CollectionViewCell_XIB is the name of your cell xib
CollectionViewCell_ID is the ID of your cell
And you need to implement cellForItemAtIndexPath like this :
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *cell = (CollectionViewCell *)[self.collectionView dequeueReusableCellWithReuseIdentifier:CollectionViewCell_ID forIndexPath:indexPath];
// Configure cell with data
UIImageView *myImageView = (UIImageView *)[cell viewWithTag:100];
myImageView.image = [UIImage imageNamed:[itemsArray objectAtIndex:indexPath.row]];
// Return the cell
return cell;
}