I'm trying to add a "favorite button" to a custom cell in a UIableView.
The cell has a label and detailLabel that show fine. I must be doing something wrong but I can't figure out what it is. My code is below, and I changed my original method (commented) after studying this question.
My code is as follows:
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyCustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
}
cell.nameLabel.text = [myMutableArray valueForKey:#"Name"];
cell.detailLabel.text = [myMutableArray valueForKey:#"Detail"];
if (isFavorite)
{
NSLog(#"fave");
UIImage *btnImage = [UIImage imageNamed:#"goldStar.png"];
[cell.favoriteButton setImage:btnImage forState:UIControlStateNormal];
//[cell.favoriteButton setImage:[UIImage imageNamed:#"yellowStar.png"] forState:UIControlStateNormal];
} else {
NSLog(#"out of fave");
UIImage *btnImage = [UIImage imageNamed:#"greyStar.png"];
[cell.favoriteButton setImage:btnImage forState:UIControlStateNormal];
//[cell.favoriteButton setImage:[UIImage imageNamed:#"greyStar.png"] forState:UIControlStateNormal];
}
return cell;
}
MyCustomCell.h
#interface MyCustomCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *nameLabel;
#property (nonatomic, weak) IBOutlet UILabel *detailLabel;
#property (nonatomic, strong) IBOutlet UIButton *favoriteButton;
MyCustomCell.m
#implementation MyCustomCell
#synthesize nameLabel = _nameLabel;
#synthesize detailLabel = _detailLabel;
#synthesize favoriteButton = _favoriteButton;
- (void)awakeFromNib {
_favoriteButton = [[DBTileButton alloc] init];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
I've checked and the button is hooked up ok in IB. Thanks ahead for any advice.
UPDATE I notice in the log message that the image frame is set at 0,0,0,0. I'm attaching a shot of the custom cell IB setup. Is something amiss there?
As far as I know IBOutlet for any sub classes of UIView shouldn't be strong! Anyway you no need to use IBOutlet, if you wanna initialize your button programmatically: at first, you forgot to set frame of your button and add it to cell view via addSubview. But it is easier way: just add button on storyboard, set custom class and remove this:
_favoriteButton = [[DBTileButton alloc] init];
EDIT: set class for your storyboard's button like on picture
Then change your outlet:
#property (nonatomic, weak) IBOutlet DBTileButton *favoriteButton;
And finally don't forget to connect outlet to your button and remove programmatically initializing.
Related
I have a viewController that contains a programmatically created tableView.
#property (strong, nonatomic) UITableView *numbersTableView;
//...
self.numbersTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, -100, self.view.frame.size.width-20, 50)];
self.numbersTableView.delegate = self;
self.numbersTableView.dataSource = self;
self.numbersTableView.tag = 1;
self.numbersTableView.layer.cornerRadius = 5;
[self.numbersTableView setBounces:false];
[self.numbersTableView setHidden:true];
[self.numbersTableView registerClass:[AZGCountryCell class] forCellReuseIdentifier:#"NumbersTableViewCell"];
[self.view addSubview:self.numbersTableView];
For the prototype cell I want to use a prototype that I created somewhere else in another viewController and I designed It in storyboard.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if (tableView.tag == 1) { //tableView == self.numbersTableView
NSString *cellID = #"NumbersTableViewCell";
AZGCountryCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[AZGCountryCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.countryName.text = self.numbersArray[indexPath.row].number;
cell.flagImageView.image = [UIImage imageNamed:self.numbersArray[indexPath.row].country];
return cell;
}
}
And my custom cell contains one UIImageView and one UILabel but when I run the code the cells are empty and I can see the UIImageView and UILabel are nil!
#import <UIKit/UIKit.h>
#interface AZGCountryCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UIImageView *flagImageView;
#property (strong, nonatomic) IBOutlet UILabel *countryName;
#property (strong, nonatomic) IBOutlet UILabel *countryCode;
#end
#import "AZGCountryCell.h"
#implementation AZGCountryCell
#synthesize flagImageView;
#synthesize countryName;
- (void)awakeFromNib {
[super awakeFromNib];
self.flagImageView.layer.cornerRadius = self.flagImageView.frame.size.width/2;
self.flagImageView.layer.masksToBounds = YES;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
#end
Then what should I do to have properly filled cells in my numbersTableView?
Unfortunately you can't reuse a table cell you've defined in a table view in a storyboard in your separate class.
In order for you to be able to share your cell between the different views, you'll have to extract the view to a separate nib and register that nib go be used on both tables.
Alternatively you can implement the cell's UI in code in the table view cell subclass.
You getting empty cell because custom tableview cell not registered, use
[self.numbersTableView registerNib:[UINib nibWithNibName:#"AZGCountryCell" bundle:nil] forCellReuseIdentifier:#"NumbersTableViewCell"];
instead of
[self.numbersTableView registerClass:[AZGCountryCell class] forCellReuseIdentifier:#"NumbersTableViewCell"];
I'm new in iPhone development and have problem with prototype cell.
In my storyboard, I have navigation controller. I pushed it with view controller (as main window), it has a button, when I click it I open tableView controller with custom prototype cell
- (IBAction)searchClick:(id)sender {
CNCarTableController *car = [[CNCarTableController alloc]init];
[self.navigationController pushViewController:car animated:TRUE];
}
But when it opens it has empty rows
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: ( NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TransportCell";
CNTransportCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if(cell == nil){
cell = [[CNTransportCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//cell.textLabel.text = #"bmv";
cell.name = (UILabel*) [cell viewWithTag:100];
[cell.name setText:#"a text"];
cell.number.text = #"number";
cell.car.text = #"car";
return cell;
}
But if will use cell.textLabel.text = #"bmv"; all works ok. But for custom cell way with tags or cell.lbl.text don't work. What is wrong there? Can it be a nuance of navigation controller with view controller?
Custom cell code:
#interface CNTransportCell : UITableViewCell
#property (nonatomic,weak) IBOutlet UILabel *name;
#property (nonatomic,weak) IBOutlet UILabel *number;
#property (nonatomic,weak) IBOutlet UILabel *car;
#end
#implementation CNTransportCell
#synthesize name;
#synthesize number;
#synthesize car;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
you have done small mistake there. Your custom cell class is "CNPlayerCell" & you are allocating new cells from "CNTransportCell" class.
One more thing, have you assigned custom class to your prototype cell in IB? (In identity inspector)
Hi in my app i have to load images to UITableViewCell .which are coming from the server.so the problem is when ever i scroll the tableview images are loading every time and its loading lazy so i tried to stop reusing cells but its not working ,How to stop reusing the cells in UITableView.
my code is
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=#"Cell";
RestaurantCustomCell *cell =(RestaurantCustomCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSArray *topLevelObjects ;
topLevelObjects= [[NSArray alloc]init];
if(cell==nil)
{
topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RestaurantCustomCell" owner:self options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (RestaurantCustomCell *) currentObject;
break;
}
}
}
NSDictionary *dict=[restauarantsArr objectAtIndex:indexPath.row];
NSString *imgStr=[dict valueForKey:#"Img"];
[self processImageDataWithURLString:imgStr andBlock:^(NSData *imageData) {
if (self.view.window)
{
UIImage *img = [UIImage imageWithData:imageData];
if(img!=nil)
{
UIGraphicsBeginImageContext(CGSizeMake(100, 100));
[img drawInRect:CGRectMake(0,0,100,100)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
cell.restaurantImg.image=newImage;
UIGraphicsEndImageContext();
}
}
}];
cell.nameLbl.text=[dict valueForKey:#"Restaurants"];
cell.typeLbl.text=[dict valueForKey:#"Rest_Cuisine"];
cell.timingsLbl.text=[dict valueForKey:#"Rest_Timings"];
cell.categoryLbl.text=[dict valueForKey:#"Rest_Category"];
cell.addressLbl.text=[dict valueForKey:#"Address"];
return cell;
}
You can not doing this in default table view cell. If you want to create this kind of things then you need to create custom tableview cell anbd do it what you want.
You have to make a custom cell like that:
RestaurantCustomCell.h
#import <UIKit/UIKit.h>
#interface RestaurantCustomCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *nameLbl;
#property (weak, nonatomic) IBOutlet UILabel *typeLbl;
#property (weak, nonatomic) IBOutlet UILabel *timingsLbl;
#property (weak, nonatomic) IBOutlet UILabel *categoryLbl;
#property (weak, nonatomic) IBOutlet UILabel *addressLbl;
#property (weak, nonatomic) IBOutlet UIImageView *restauranImg;
#end
RestaurantCustomCell.m
#import "RestaurantCustomCell.h"
#implementation RestaurantCustomCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)prepareForReuse{
self.nameLbl.text = #"";
self.typeLbl.text = #"";
self.timingsLbl.text = #"";
self.categoryLbl.text = #"";
self.addressLbl.text = #"";
}
#end
after in IB you add a new UITableViewCell at your UITableView and the class of it with you new custom cell set the Identify ID like "RestaurantCustomCell" add your labels and imageView to your custom cell and connect the Outlet, then you modify you tableView:cellForRowAtIndexPath: like that:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=#"RestaurantCustomCell";
RestaurantCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *dict=[restauarantsArr objectAtIndex:indexPath.row];
NSString *imgStr=[dict valueForKey:#"Img"];
[self processImageDataWithURLString:imgStr andBlock:^(NSData *imageData) {
if (self.view.window)
{
UIImage *img = [UIImage imageWithData:imageData];
if(img!=nil)
{
UIGraphicsBeginImageContext(CGSizeMake(100, 100));
[img drawInRect:CGRectMake(0,0,100,100)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
cell.restaurantImg.image=newImage;
UIGraphicsEndImageContext();
}
}
}];
cell.nameLbl.text=[dict valueForKey:#"Restaurants"];
cell.typeLbl.text=[dict valueForKey:#"Rest_Cuisine"];
cell.timingsLbl.text=[dict valueForKey:#"Rest_Timings"];
cell.categoryLbl.text=[dict valueForKey:#"Rest_Category"];
cell.addressLbl.text=[dict valueForKey:#"Address"];
return cell;
I Know this question is asked again and again here, but did not find any solutions for my problem.I'm creating a Custom UITableViewCell through xib and trying to load it.in my VC called ACSummaryVC
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"SimpleTableCell";
AcSummaryCell *cell = (AcSummaryCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"AcSummaryCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
}
AcSummaryCell is a subclass of UITableViewCelland it has an UILabel IBOutlate called acLabel.when i compile the project i get following error-
`Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<ACSummaryVC 0x71465c0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key acLabel.'`
i have created connection of acLabel in AcSummayCell class, but i'm getting error from ACSummaryVC? What i'm doing wrong?
Edit:- according to Mani's answer bellow i'm connecting outlate to file owner and it is wrong instead i've to connect outlate to custom cell.but when i try this i did not get my outlate to connect with instead i'm getting like this image -
Now question is How to connect my outlate with custom cell?
here is my AcSummayCell.h
#interface AcSummayCell : UITableViewCell
#property(nonatomic, retain)IBOutlet UILabel* acLabel;
#property(nonatomic, retain)IBOutlet UILabel* namelbl;
#property(nonatomic, retain)IBOutlet UILabel* cBalancelbl;
#property(nonatomic, retain)IBOutlet UILabel* avBalancelbl;
and AcSummayCell.m
#import "AcSummayCell.h"
#implementation AcSummayCell
#synthesize acLabel = _acLabel;
#synthesize namelbl = _namelbl;
#synthesize cBalancelbl = _cBalancelbl;
#synthesize avBalancelbl = _avBalancelbl;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
You have setup a wrong outlet connection. Its because you have connected your label's outlet to your file's owner. Remove that label outlet connection out of file's owner and connect the outlet pointing to your custom cell. It should work.
follow this... for custom tableview cell
UITableViewCell Space between Title and Subtitle -iOS
or this awesome tutorial
http://www.appcoda.com/customize-table-view-cells-for-uitableview/
follow this code properly....
AudioCell.h
#import<UIKit/UIKit.h>
#interface AudioCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *titleLabel;
#property (strong, nonatomic) IBOutlet UILabel *artistLabel;
...
#end
AudioCell.m
#import "AudioCell.h"
#implementation AudioCell
#synthesize titleLabel = _titleLabel, artistLabel = _artistLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
Now implement this code in your class at the TableView Data Source....
#import "AudioCell.h"
.....
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"AudioCell";
AudioCell *cell = (AudioCell *)[self.audioFeedTable dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (AudioCell *)[nibArray objectAtIndex:0];
[cell configurePlayerButton];
}
// Configure the cell..
cell.titleLabel.text = [nameArray objectAtIndex:indexPath.row];
cell.artistLabel.text = [commentsArray objectAtIndex:indexPath.row];
....
return cell;
}
Link your custom TableViewCell with the subClass by the same way....
I see your mistakes:
You don't specify Cell class and reuse identifier in your customCell
Create custom cell AcSummaryCell:UITableViewCell first then choose class for tableCell in the nib Cell. Also assign cell identifier in NIB. If correct , your cell must display
AcSummaryCell-SimpleTableCell in Object field.
For hookup to IBOutlet, just choose editor(show assistant editor) -> then choose Automatic-AcSummaryCell.h -> then drag and hookup IBOutlet you want.
I'm a newbie in objective-c and iOS
I created several custom table cells with outlets in it. But I'm not sure if I use the right way.
What I want to do is to get the property of an Outlet which is inside the custom cell, by an IBAction defined in the table view controller.
I have a custom table cell called KolonNumberCell, and a UISlider in it.
I want to define an IBAction called playNumbers in the UITableViewController. The slider seems to work fine in the custom cell. I can get its value.
But I cannot figure out how to get the value of this slider when the playButton outlet is tapped.
I would be so grateful if you could give me some information or show me a way.
Thanks in advance
TableController.h
#import <UIKit/UIKit.h>
#class KolonNumberCell;
#class BankoNumberCell;
#interface TableViewController : UITableViewController{
NSArray *bundleArray;
IBOutlet KolonNumberCell *kolonCell;
IBOutlet BankoNumberCell *bankoCell;
UIButton *playButton;
}
#property (strong) IBOutlet KolonNumberCell *kolonCell;
#property (strong) IBOutlet BankoNumberCell *bankoCell;
#property (nonatomic,retain) NSArray *bundleArray;
#property (nonatomic,retain) IBOutlet UIButton *playButton;
- (void)playNumbers:(id)sender;
#end
part of TableController.m
#import "TableViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize bundleArray,kolonCell,bankoCell,playButton;
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *bundle1 = [[[NSBundle mainBundle] loadNibNamed:#"KolonNumberCell" owner:self options:nil] objectAtIndex:0];
NSArray *bundle2 = [[[NSBundle mainBundle] loadNibNamed:#"BankoNumberCell" owner:self options:nil] objectAtIndex:0];
bundleArray = [[NSArray alloc] initWithObjects:bundle1,bundle2, nil];
}
- (void)playNumbers:(id)sender
{
NSLog(#"button");
// Get the value of the slider in KolonNumberCell... but how?
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
tableView.allowsSelection = NO;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [bundleArray objectAtIndex:indexPath.section];
}
return cell;
}
#end
One of my customtableviewcell implementation file
#import "KolonNumberCell.h"
#implementation KolonNumberCell
#synthesize label,slider;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
self.backgroundView = [[UIImageView alloc] initWithImage:[ [UIImage imageNamed:#"doubleRound.png"] stretchableImageWithLeftCapWidth:0.0 topCapHeight:0.0]];
}
- (IBAction)sliderChanged:(id)sender
{
[label setText:[NSString stringWithFormat:#"%i",(int)slider.value]];
}
+ (NSString *)reuseIdentifier {
return #"Cell";
}
#end
Your design is odd because your code will become really messy with more Cells.
Matt Gallagher has a nice implementation for Custom TableViews. He is using the TableViewCell as a Controller and puts all the logic related to cell in the cells class. The discussion thread on Stack Overflow:
CustomTableViewController
If you still want to do it your way:
Give your Slider a tag: slider.tag = x //Make sure that the tag is unique
In PlayNumbers:
UISlider *slider = (UISlider *)[[[bundleArray objectAtIndex:0] contentView] viewWithTag:x];
NSLog(#"%i",(int)slider.value);
Edit: thanks for correcting the syntax