I have created my custom table cell class:
#interface CommonCell : UITableViewCell{
...
}
#end
In the implementation file of it, I have created a custom initializer method: initWithCellHeight:reuseIdentifier:showName
which called the [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]) , like below:
#implementation CommonCell
- (id)initWithCellHeight:(float)cellHeight reuseIdentifier:(NSString *)reuseIdentifier showName:(BOOL)showName
{
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier])) {
[self createViews: showName];
}
return self;
}
When I use my cell class in my controller in the following way:
#import "CommonCell.h"
...
cell = [[[CommonCell alloc] initWithCellHeight:150 reuseIdentifier:#"CommonCellId" showName:YES] autorelease];
I got warning message : instance method "initWithCellHeight:reuseIdentifier:showName" not found
Why? Why I can not use my custom initialiser for my table cell?
Why is - (id)initWithCellHeight:(float)cellHeight reuseIdentifier:(NSString *)reuseIdentifier showName:(BOOL)showName not present in the header file? You will need to declare it before using it to remove the warning.
Related
So I have a custom UITableViewCell:
TestTableViewCell.h
#import <UIKit/UIKit.h>
#interface TestTableViewCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *testCellLabel;
#end
TestTabelViewCell.m
#import "TestTableViewCell.h"
#implementation TestTableViewCell
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
_testCellLabel = [[UILabel alloc] init];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
And then I have view controller with a table view that uses the custom table view cell. However this issue is that I don't want to use dequeueReusableCellWithIdentifier within the cellForRowAtIndexPath. I instead want to have an array of cells.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#end
ViewController.m
#import "ViewController.h"
#import "TestTableViewCell.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSArray *myTableViewCells;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSArray *)myTableViewCells {
TestTableViewCell *cell1 = [[TestTableViewCell alloc] init];
cell1.testCellLabel.text = #"one";
cell1.backgroundColor = [UIColor blueColor];
TestTableViewCell *cell2 = [[TestTableViewCell alloc] init];
cell2.testCellLabel.text = #"two";
cell1.backgroundColor = [UIColor greenColor];
if (!_myTableViewCells) {
_myTableViewCells = #[cell1, cell2];
}
return _myTableViewCells;
}
#pragma mark - UITableView delegate functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.myTableViewCells.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TestTableViewCell *cell = self.myTableViewCells[indexPath.row];
return cell;
}
#end
The problem is that there is no testCellLabel appearing in the table view cell. I know the cells are there, because I set their background colour.
After talking to a few people, apparently I need to do some sort of loading from the XIB or the NIB for the UI to load properly? Even though the label is defined in the cell in the storyboard.
I know this is going against the norm and that Apple really wants you to use dequeueReusableCellWithIdentifier, but I know it won't work in the situation I need it in. I have done the reading on that much so please don't just tell me to use it. This code example is just very basic for example sake and ease of use.
Any help would be greatly appreciated.
TestTableViewCell *cell1 = [[TestTableViewCell alloc] init];
Creates a new TestTableViewCell object and does not instantiate it from the storyboard like you're thinking it does. Therefor all outlets created will be nil and simply not show up. The fact that you can set the background colour is not evidence that your implementation works.
You need to use dequeueReusableCellWithIdentifier. You say that it doesn't work for your problem.. show me how it doesn't work and I will tell you why you're wrong.
Edit
I see in your comments you say your cell needs a custom setter. Well, when you use dequeueReusableCellWithIdentifier you can do all setup work in awakeFromNib (If using a xib file) OR initWithCoder if you are using the storyboard.
You can create cell without dequeueResableCellWithIdentifer.
[[UITableViewCell alloc]initWithStyle:<#UITableCellStyle#> resueIdentifier:<#(nullable *NSString)#>]
Due to the limitations of Storyboard I am creating a UICollectionView programmatically. This is working all fine and when I want to add a UICollectionViewCell I do the following:
[collectionView registerClass:[Cell class] forCellWithReuseIdentifier:#"ID"];
What I was wondering is how can I use a custom init method from the class "Cell", because I can't do something like the following:
[collectionView registerClass:[[Cell class]init_custom]forCellWithReuseIdentifier:#"ID"];
Question: How can I use a custom init method from a custom UICollectionViewCell class?
If I understand you correctly, then I would create subclasses of your collection view cell.
First setup your cell with everything you want.
#interface MyCollectionViewCell : UICollectionViewCell
// Your custom cell
#end
#implementation MyCollectionViewCell
// Your custom cell
#end
Then for each collection view create a subclass which only overrides init.
#interface MyCollectionViewCellForCollectionView1 : MyCollectionViewCell
#end
#implementation MyCollectionViewCellForCollectionView1
- (instancetype)init // Only override -init
{
self = [super init];
if (self) {
// Setup for collection view one
}
return self;
}
#end
#interface MyCollectionViewCellForCollectionView2 : MyCollectionViewCell
#end
#implementation MyCollectionViewCellForCollectionView2
- (instancetype)init // Only override -init
{
self = [super init];
if (self) {
// Setup for collection view two
}
return self;
}
#end
Then for each different collection view, you register one of your subclasses.
[collectionView1 registerClass:[MyCollectionViewCellForCollectionView1 class] forCellWithReuseIdentifier:#"ID"];
[collectionView2 registerClass:[MyCollectionViewCellForCollectionView2 class] forCellWithReuseIdentifier:#"ID"];
This will get you the separate custom init methods you wish, but be sure to keep all your functionality in the base class.
I have an image property on my table view cell. I want to populate this image to an image.
My cell looks like:
//.h
#interface GAFriendStatusTableViewCell : PFTableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *friendImage;
#end
//.m
#import "GAFriendStatusTableViewCell.h"
#implementation GAFriendStatusTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.friendImage.image = [UIImage imageNamed:#"user.png"];
}
return self;
}
- (void)awakeFromNib
{
// Initialization code
}
#end
This doesn't set the image. How can I set the image for this cell within the cell class?
Since your image view is an IBOutlet, I'm assuming you've got your cell layout defined in a .xib or storyboard. That being the case, your initialization code should go in the awakeFromNib method. This is the method that is called when the cell is created from the nib. That's why the //Initialization code comment is there. initWithStyle:reuseIdentifier: is never called in this scenario, which is why your image is not appearing.
Set it in - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
Otherwise if you have a Nib or Storyboard you're using then set the default in the prototype cell you are using.
I'm testing UITableView with a custom TableViewCell. The custom cell is designed in a .xib file and has its own class called cell, which is a subclass of UITableViewCell:
Cell.m
#import "Cell.h"
#implementation Cell
- (void)awakeFromNib
{
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
return self;
}
#end
The ViewController class has the UITableView called table in it. It is also Delegate and Datasource for it. Both is set in the Storyboard. Its code looks like this:
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.table registerClass:[Cell class] forCellReuseIdentifier:#"cell" ];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [self.table dequeueReusableCellWithIdentifier:#"cell"];
return cell;
}
#end
If I run the app, I can see the table and it has the right number of cells. But the custom cell is not shown. Each cell of the table is just white.
I read a couple of post on issues like this but no one helped me. Different Tutorials say it should work like this but it doesn't. I think there may is a stupid mistake in it. Thanks for your help.
You said you're using xib files to instantiate your cells, but you're registering a class instead of xib with this line
[self.table registerClass:[Cell class] forCellReuseIdentifier:#"cell" ];
try using registerNib:forCellReuseIdentifier: instead
I'm guessing You forget to set your custom class name in the *.xib file.
Set Custom Class property to "cell" in *.xib properties. Please check that property.
I know how to call a method of one class to another class. However This time its not working for me and its just driving me nuts. Below is my code
MenuPageCell.h
#import <UIKit/UIKit.h>
#class MenuPageViewController;
#interface MenuPageCell : UITableViewCell{
NSInteger m_cellIndex;
MenuPageViewController *m_parentViewController;
}
#property(nonatomic, assign) NSInteger m_cellIndex;
#property(nonatomic, strong) MenuPageViewController *m_parentViewController;
-(IBAction) addToCart;
#end
MenuPAgeCell.m
#import "MenuPageCell.h"
#import "MenuPageViewController.h"
#implementation MenuPageCell
#synthesize m_cellIndex;
#synthesize m_parentViewController;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
-(IBAction) addToCart
{
NSLog(#"Add To cart = %d",self.m_cellIndex);
[m_parentViewController addItemToCart:self.m_cellIndex];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
MenuPageViewController.m
-(void) addItemToCart:(NSInteger)aIndexItem
{
NSLog(#"In Add to Cart method");
}
Now, This code works fine for non ARC Used project but its not working for me. I know it should be silly mistake but I'm unable to figure it out.
Thanks & regards
Mayur
Referencing ViewController from a cell is a design flaw, consider using delegate instead. But if you really need the ViewController property, make it weak instead of strong because currently you end up with retain cycle.
#protocol MenuPageCellDelegate<NSObject>
- (void)addItemToCart:(NSInteger)aIndexItem;
#end
#interface MenuPageCell : UITableViewCell {
NSInteger m_cellIndex;
}
#property(nonatomic, assign) NSInteger m_cellIndex;
#property(nonatomic, weak) id<MenuPageCellDelegate> delegate;
-(IBAction) addToCart;
#end
#implementation MenuPageCell
...
-(IBAction) addToCart
{
NSLog(#"Add To cart = %d",self.m_cellIndex);
if ([self.delegate responsToSelector:#selector(addItemToCart:)]) {
[self.delegate addItemToCart:self.m_cellIndex];
}
}
...
#end
Add MenuPageCellDelegate to the list of implemented protocols of MenuPageViewController and (if it's implementing UITableViewDataSource protocol) in the tableView:cellForRowAtIndexPath: method write cell.delegate = self; instead of cell.m_parentViewController = self;
initialize your m_parentViewController in viewDidLoad method.
such like
m_parentViewController = [[yourViewControllerName alloc] init];
and then call
[m_parentViewController addItemToCart:self.m_cellIndex];
in the cellforrow method of your tableview add a selector to the cell button and also set the tag equal to the indexpath. now in the selector just distinguish between the different cells with the help of sender.tag.