iOS - Custom table cell not full width of UITableView - ios

I may be going about this wrong. So I have created a UITableView that essentially has a auto-layout trailing space set to the main view. I am creating a custom cell for this table so I drug on a prototype cell, customized it, and created my class for it. That is all working just fine.
What I can't seem to solve is the custom cell isn't going the full width of the actual table cell so a white background just shows up. If I don't use the custom cell the entire width table cell gets utilized.
I set the constraints for the cell content so that the background image should fill the cell.
What am I doing wrong? Let me know what you need to help solve this.
ProfileCustomCell.h
#import <UIKit/UIKit.h>
#interface ProfileCustomCell : UITableViewCell {
}
#property (nonatomic, strong) IBOutlet UILabel *nameLabel;
#property (nonatomic, strong) IBOutlet UIImageView *profileImageView;
#end
ProfileCustomCell.m
#import "ProfileCustomCell.h"
#implementation ProfileCustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.nameLabel.text = nil;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
#end
UITableView
[tableView registerNib:[UINib nibWithNibName:#"ProfileCustomCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"Cell"];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
ProfileCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.nameLabel.text = [NSString stringWithFormat:#"%#", [child objectForKey:#"first_name"]];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

Can you post the code please .
Did you enable the Use Auto layout and Use Size Classes as below do that first in both table view and table view cell .and tell me your problem
1)After that select both image and label and do as below
2) Select the image and do below
3) select the label an do the following
Can you check the link below:
Table cell content(title) moving left after selecting cell

Instead of "filling", auto layout constraints to leading and trailing space to constant 0 and make sure they're not relative to margins.

select your table view cell's connection inspector and check if you haven't connected
editingAccessoryView by mistake

For those that are still having a similar issue and the above fixes are not working, make sure to set Estimated Size of the cell to None. This can be done in the Storyboard Size Inspector. Was stuck for much to long on this one!

Related

UITableView cells are not displaying text

I just finished a simple 5 minute UITableView tutorial. I even imported the tutorial's source code files into my own current xcode project, and I still cannot get this to work. I'm not sure if I'm doing something wrong, or if it's because the tutorial was created using a different version of xcode or what.
Anyways, I created a new objective-c file called "TVTViewController" which is a subclass of UIViewController. I then dragged a UIViewController onto the storyboard and set it's custom class in the attributes inspector to "TVTViewController".
Next, I dragged a UITableView object onto the UIViewController that I just dragged onto the storyboard.
I set the UITableView's "Content" setting to "Dynamic" and then set it's "Prototype Cells" setting to "1".
I then selected the prototype cell on the storyboard, and changed it's "Style" setting to "Subtitle", and changed it's "Identifier" setting to "SettingsCell".
Finally, here is my header file code:
#import <UIKit/UIKit.h>
#interface TVTViewController : UIViewController <UITableViewDataSource>
#end
And here is my main file's code:
#import "TVTViewController.h"
#interface TVTViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSArray *tweetsArray;
#end
#implementation TVTViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//1
self.tableView.dataSource = self;
//2
self.tweetsArray = [[NSArray alloc] initWithObjects:
#"Always put your fears behind you and your dreams in front of you.",
#"A relationship with no trust is like a cell phone with no service, all you can do is play games.",
#"People should stop talking about their problem and start thinking about the solution.",
#"Dear Chuck Norris, Screw you. I can grill burgers under water. Sincerely, Spongebob Squarepants.",
#"My arms will always be open for you, they will never close, not unless you're in them.",
nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//3
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.tweetsArray count];
}
//4
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//5
static NSString *cellIdentifier = #"SettingsCell";
//6
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSString *tweet = [self.tweetsArray objectAtIndex:indexPath.row];
//7
[cell.textLabel setText:tweet];
[cell.detailTextLabel setText:#"via Codigator"];
return cell;
}
#end
When I run my app on my iPhone, it shows the table view, but it is empty. None of the text is displayed in the table view's cells at all. This is pretty much copy and pasted from the tutorial's source code, and when I run the tutorial's source code app on my iPhone it displays the text in the cells just fine.
I don't understand why it is not working for me once I add the same code to my own app.
Thanks for the help.
EDIT:
I just figured it out on my own. The tutorial author neglected to tell you to connect the IBOutlet called "tableView" to the UITableView object. I just connected them and everything is displaying fine now. I would answer my own question but stackoverflow won't let me for another 8 hours.
A possible work around:
a) Check that the cell were actually created or not:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if( !cell )
{
cell = [[UITableViewCell alloc] init];
}
b) Set its delegate and datasource
Check out other ways to dequeue table view cells
Add UITableViewDelegate, like
#interface TVTViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
with
self.tableView.delegate = self;
And create cell as
if(cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

Custom UITableViewCell Created in StoryBoard Results in duplicated UILabels

I have been through many questions on SO before asking this.
I have an issue where i have created a custom UITableView cell in a StoryBoard. I have subclassed UITableViewCell and exposed properties to link my various components to within the cell.
I am NOT creating or adding any components to the cell in
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I simply use the
[tableView dequeueReusableCellWithIdentifier:cleanseCell forIndexPath: indexPath];
call to reuse cells. I do some customisation on the cells but I don't add anything new. I just modify an image, some labels and a text field . The cell reuse identifier is set correctly both in the code and on the component in the storyboard.
The problem is that when the cell is reused, somewhere under the hood the UILabels are being duplicated. I have a UITextField in there as well - it doesn't have this problem. Only the UILabels are somehow duplicated.
So the cell presents fine the first time with the correct information. Then the next time the cell is created its still fine. The third time the cell shows up with Overlapping UILabels. One with the new text and one with the text of the original cell. At any rate there are two UILabels in the cell now where there was only one before and I didn't add it there.
Anyone else experienced this or have some comment to make?
EDIT:
This is my UITableViewCell - There is nothing in the implementation other than synthesising the properties (which is not even required anyway)
#import <UIKit/UIKit.h>
#interface SJCleanseNotificationCell : UITableViewCell
#property (nonatomic)float openHeight;
#property (nonatomic, strong)IBOutlet UIImageView *iconView;
#property (nonatomic, strong)IBOutlet UILabel *dateTimeLabel;
#property (nonatomic, strong)IBOutlet UILabel *titleLabel;
#property (nonatomic, strong)IBOutlet UITextView *messageLabel;
-(IBAction)dismiss:(id)sender;
-(IBAction)activate:(id)sender;
#end
And this is the cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cleanseCell = #"CleanseCell";
NSDictionary *cleanse = sjTimer.cleanseNotification;
SJCleanseNotificationCell *cell;
if([_tableView respondsToSelector:#selector(dequeueReusableCellWithIdentifier:forIndexPath:)])
cell = (SJCleanseNotificationCell*)[_tableView dequeueReusableCellWithIdentifier:cleanseCell forIndexPath: indexPath];
else
cell = (SJCleanseNotificationCell*)[_tableView dequeueReusableCellWithIdentifier:cleanseCell];
[cell.dateTimeLabel setText:[cleanse objectForKey:#"date"]];
[cell.titleLabel setText:[cleanse objectForKey:#"title"]];
[cell.messageLabel setText:[cleanse objectForKey:#"message"]];
NSNumber *stage = (NSNumber*)[cleanse objectForKey:#"stage"];
if(stage)
[cell.iconView setImage:[[SJCleanseTimer instance]bottleImageForCleanseStage:stage.integerValue]];
cell.delegate = self;
cell.openHeight = 100;
return cell;
}
The problem was I had Clears Graphics Context unchecked in the inspector on the UILabel elements. After checking that checkbox it behaved normally.

Send UITableViewCell across View Controllers

I want to select a UITableViewCell from my table view in one view controller and pass the data of the cell into another view controller.
Code:
-(void)pushView
{
myView.mainCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathWithIndex:currentCell]];
[self.navigationController pushViewController:myView animated:YES];
}
myView is the view I want to push from my first view.
mainCell is a UITableViewCell property of myView. I want it be exactly what the selected cell is.
currentCell is just an integer that returns the row number of the cell selected.
How can I pass one cell across view controllers?
Actually you don't need to pass the cells as it will mess up the references as commented by many people. Take a look at this. Its discussing the same problem u r facing.
- (IBAction)nextScreenButtonTapped:(id)sender
{
DestinationViewController *destController = [[DestinationViewController alloc] init];
//pass the data here
destController.data = [SourceControllerDataSource ObjectAtIndex:currentCell];
[self.navigationController pushViewController:destController animated:YES];
}
Ah, I see what you want now.
What you want is to have some data displayed in a table view cell. Then to move somewhere else in the app and display the same data in a different table view but laid out in exactly the same way.
What you do then is this...
First create a new class which is a subclass of UITableViewCell call it something like MyTableViewCell.
The next part depends on whether you are using Interface Builder but I'll do everything in code for now.
In the new class create your interface properties in the .h file.
#interface MyTableViewCell : UITableViewCell
#property (nonatomic, strong) UILabel *nameLabel;
#property (nonatomic, strong) UIImageView *someImageView;
etc...
#end
Now in the .m file you can set it up like so...
#implementation MyTableViewCell
- (void)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//set up your labels and add to the contentView.
self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
[self.contentView addSubView:self.nameLabel];
self.someImageView = ...
[self.contentView addSubView:self.someImageView];
// and so on for all your interface stuff.
}
return self;
}
#end
Now in the UITableViewController that you want to use this cell you can do...
- (void)viewDidLoad
{
// other stuff
[self.tableView registerClass:[MyTableViewCell class] forCellReuseIdentifier:#"MyCustomCellReuseIdentifier"];
// other stuff
}
Then in cell for row...
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyTableViewCell *customCell = [tableView dequeueReusableCellWithIdentifier:#"MyCustomCellReuseIdentifier"];
customCell.nameLabel.text = //some string that you got from the data
customCell.someImageView.image = //some image that you got from the data
return customCell;
}
Doing this you can use the same cell layout in multiple places and all you have to do is populate the data.
When you pass the data to a new table view you can use the same cell class to re-populate it with the data that was passed around.
Never pass around a UIView or UIView subclass. They should not contain data that way. The are only used to display it.

TableView within ViewController not displaying cells

I'm fairly new to iOS development and I've been wrestling with a solution for this for about a day now and can't figure out why it is not working. I am trying to use a tableview within a viewcontroller as a small menu for the user to use. I have checked to see if the NSArray is being populated, and it is. I have also checked to see if the cell is being created, and it is. I just can't figure why it is not populating the tableview with the cells it creates. Below is my the code that I have so far. Thanks in advance for any help anyone can provide.
MainViewController.h
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *menuTableView;
#property (weak, nonatomic) IBOutlet UIButton *menuButton;
#property (strong, nonatomic) NSArray *menuItemsArray;
#property (weak, nonatomic) IBOutlet UILabel *menuLabel;
#end
MainViewController.m
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize menuItemsArray, menuTableView, menuButton, menuLabel;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Set TableView Delegate/DataSource to self
[self.menuTableView setDelegate:self];
[self.menuTableView setDataSource:self];
[self.menuTableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[self.menuTableView setBounces:NO];
[self.menuTableView setRowHeight:self.menuLabel.frame.size.height];
self.menuItemsArray = [[NSArray alloc] initWithObjects:#"Add Category", #"Add Item", #"Settings", nil];
NSLog(#"array: %#", menuItemsArray);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#pragma mark - UITableViewDelegate
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return ([self.menuItemsArray count]);
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"menuCell"];
[[cell textLabel]setText:[self.menuItemsArray objectAtIndex:indexPath.row]];
[[cell textLabel]setFont:[self.menuLabel font]];
return cell;
}
-(void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.menuTableView deselectRowAtIndexPath:indexPath animated:YES];
NSString *selectedString = [self.menuItemsArray objectAtIndex:indexPath.row];
self.menuLabel.text = selectedString;
}
I had the same problem, my table view was not getting displayed within a view controller.
I have found a solution.
You can create another view controller with a Container view on it. And put ur table view on a Table View controller. just embed the table view controller to the container view of ur mail view controller.
Make sure your initWithNib method is being called. If you are calling [[MainController alloc] init] your "menuTableView" will never be created from the Nib. Also, double-check the table view by setting the backgroundColor of the main table view to [UIColor red] or something just to make sure the tableView is present and that it has the frame you expect. It might be sitting behind one of your other views, have a frame of (0,0,0,0), or not be present in the view at all.
Also try calling [self.menuTableView reloadData] at the end of your 'viewDidLoad' or initialize the menuItemsArray before you set the data source and delegate (i.e. in your initWithNib method).
And when you do get it all working (you are very close) you will want to change your cellForRow method to something more like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:#"menuCell"];
if(!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"menuCell"];
}
[[cell textLabel]setText:[self.menuItemsArray objectAtIndex:indexPath.row]];
[[cell textLabel]setFont:[self.menuLabel font]];
return cell;
}
This will allow you to take advantage of the cell reuse that makes table views so efficient.
This is a bit late as you have found a way around it but I was having the same problem as you and found that I needed to connect the IBOutlet property to the table view in storyboard and then it all worked.
I hope this helps you in future.
One cause of the symptoms described is if you have placed the UITableView in the parent view using a container view in a storyboard, but are initialising and populating in code a different instance of the UITableView than the one that is actually being presented to the user. If you have placed the UITableView within the view using a container view, then you need to do the following:
Connect the UITableView to the container view with a segue, by Control-Dragging from the container view to the UITableView in the Storyboard.
Click on the segue, and give it a name e.g. tableViewSegue.
Set up the table by implementing prepareForSegue:sender:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString * segueName = segue.identifier;
if ([segueName isEqualToString: #"tableViewSegue"]) {
UIViewController * myTableView = [segue destinationViewController];
// Do any table setup here, such as injecting the data array into a property on the tableView.
}
}
If instead you have been creating a different UITableView in code, what you will see is an unpopulated UITableView that follows the specifications set up in the storyboard (e.g., row height spacing will be correct) and which is responding to user interaction, but is empty. The empty one is the one being initialised automatically for you by the storyboard, and meanwhile you've been creating another UITableView somewhere else:
// DON'T DO IT THIS WAY IF YOU'RE USING STORYBOARD.
- (void)viewDidLoad {
[super viewDidLoad];
// Incorrectly creating a tableview child table view that won't be the one presented.
self.myTableView = [MYTableViewClass new];
// ...further configuration of the table.
}
If you follow this incorrect path, the other UITableView you are creating is being built in memory, and populated with your data array, so you will see all the NSLog statements from that process and be able to see a UITableView in memory with the correct number of objects and so on as you step through the executing code, but what is hard to pick up is you're not looking at the one being presented to the user. So can be tricky to track down. :)
Just remove the code above, implement prepareForSegue:sender: and the universe will return to being a predictable place.
If you add UITableView inside the UIViewController, you need to set the frame size of the UITableView same as the frame size of the view inside the UIViewController, otherwise the tableview size may be 0, cannot display anything.
You can set the frame size if you create the UITableView by storyboard in your case:
- (void)viewDidLoad {
[super viewDidLoad];
// Set tableview delegate and datasource here
menuTableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}

Dynamic height for a UITableViewCell with a dynamic UILabel

I have a UITableViewController that displays a custom UITableViewCell (inherited from UITableViewCell). That same UITableViewCell has a UILabel that can have text of variable length. The challenge I am having is how to access this UILabel in my UITableViewController so that I can set the correct cell height in heightForRowAtIndexPath.
Or on a side note how do I solve my problem of having a dynamicically sized label.
thanks
Here is my code for the custom UITableViewCell:
header:
#import <UIKit/UIKit.h>
#interface MessagesCustomViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *message; <---- need to access this
#end
implementation:
#import "MessagesCustomViewCell.h"
#implementation MessagesCustomViewCell
#synthesize message=_message;
- (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
Using the way of measuring the font size mentioned by Ivan, you could additionally add a class metod to MessagesCustomViewCell,
+ (CGFloat)heightForMessage:(NSString *)message;
in which you calculate the height of message using the appropriate UILabel width/height, font etc. This could be called from heightForRowAtIndexPath: as such:
NSString *dynamicString = [self.mydata objectAtIndex:indexPath.row];
CGFloat height = [MessagesCustomViewCell heightForMessage:dynamicString];
return height;
Call [tableView reloadData] once data is updated.
Check the size with [yourString sizeWithFont:(UIFont*) forWidth(CGFloat) lineBreakMode:(NSLineBreakMode)] method in heightForRowAtIndex. The referred method will return a required size (including the height).

Resources