Add a UITableView to an existing ViewController - ios

I'm trying to add a UITableView to an existing UIViewController programmatically.
My run.h file has this:
#interface runTests : UIViewController <UINavigationControllerDelegate,UITextFieldDelegate,UIAlertViewDelegate,UITableViewDelegate,UITableViewDataSource> {NSTimer *Timer;}
#property (strong, nonatomic) UITableView *tableView;
My app runs through a speed test and at the end of the test I'm trying to add a TableView to the View. At the moment I have this:
-(void)addSpeedTable {
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.tableView.rowHeight = 45;
self.tableView.sectionFooterHeight = 22;
self.tableView.sectionHeaderHeight = 22;
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"newCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"Testing";
return cell;
}
The app never makes it into the cellForRowAtIndexPath method but does make it into the other two above. I can't see any error in the Xcode output.
Anything I need to be doing here:
When the app fails all I get is this:

If width of UITableView is zero, it will never call datasource
So change your code like this
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
Good luck!

You should init your UITableView with a frame (and optionally a style), or at least define the frame somewhere.
For example:
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 200, 200) style:UITableViewStylePlain];

You need to assign the property tableView to the instance you are creating in the addSpeedTable method, then reference it using self.tableView.
-(void)addSpeedTable {
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.tableView.rowHeight = 45;
self.tableView.sectionFooterHeight = 22;
self.tableView.sectionHeaderHeight = 22;
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
}
Edit
As pointed out by the other answers, you'll probably need to set the frame on the UITableView as well:
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;

You use init method to initialize a view, which means the view's frame is CGRectZero.
So the numberOfRowsInSection is called but SDK finds no cell need to be shown as the frame is CGRectZero.
-(void)addSpeedTable {
.....
tableView.frame = self.view.bounds;
[self.view addSubview:tableView];
}
What's more you should assign your tableView to the property by self.tableView = tableView or your tableView property will never be valid state.

You can add breakpoint at the thirdLine, and print out the frame see if one of its bounds is 0.

I think you may have declare the wrong syntax. I can't upload image, So notice the difference the code below. The capitalization may be the problem.
{
// 服务条款
static NSString * cellId = #"justCommon";
static NSString *CellIdentifier = #"newCell";
}

Related

Programmatically creating custom cells in objective c?

I'm having issues getting customs cells to show up. Below I've posted a simplified version of my code:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
NSLog(#"Being Called?");
//reuseID = #"newtableid";
self.backgroundColor = [UIColor redColor];
self.name = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 50)];
self.name.backgroundColor = [UIColor redColor];
[self addSubview:self.name];
return self;
}
In my viewController, I set up the tableView in the ViewDidLoad method:
self.table = [[UITableView alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 400) style:UITableViewStylePlain];
self.table.delegate = self;
self.table.dataSource = self;
self.table.backgroundColor = [UIColor blackColor];
[self.view addSubview:self.table];
[self.table registerClass:NewTableViewCell.class forCellReuseIdentifier:#"Cell"];
Then, I complete the cellForRowAt method like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"Cell";
NewTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[NewTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.backgroundColor = [UIColor blackColor];
cell.name.text = [_familyDetails objectAtIndex:indexPath.row];
return cell;
}
The problem is, I don't get anything to show up on my cells. My NewTableVIewCell constructor is called, but the cells show up blank (without color, label, etc.) What am I doing wrong?
If you're creating the cell programatically, make sure you register your cell to your table view.
[self.tableView registerClass:UITableViewCell.class forCellReuseIdentifier:"yourCellId"];
I am using a generic UITableViewCell in this case. You can try to change the text label of it in cellForRowAtIndexPath to see whether that works.
Be sure to change it to your custom cell class if needed.
In order to dequeueReusableCellWithIdentifier, you have to use
- (void)registerClass:(Class)cellClass
forCellReuseIdentifier:(NSString *)identifier
and normally you will not even have to instantiate NewTableViewCell if you use dequeueReusableCellWithIdentifier:forIndexPath:. However, if you still use dequeueReusableCellWithIdentifier: then you still need to instantiate your cell subclass (thanks for reminding me Alejandro Ivan).
EDIT: So you have to write something like this, in your viewDidLoad for example :
- (void)viewDidLoad {
[super viewDidLoad];
// Your stuff...
[self.table registerClass:[NewTableViewCell class] forCellReuseIdentifier: simpleTableIdentifier];
}

cellForRowAtIndexPath is not be called

I have a viewcontroller called BNRItemViewcontroller
In the implementation:
- (instancetype)init{
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
for (int i = 0; i < 5; i++) {
[[BNRItemStore sharedStore]createItem];
}
}
return self;
}
- (instancetype)initWithStyle:(UITableViewStyle)style{
return [self init];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[BNRItemStore sharedStore] allItems] count];
}
I add a breakpoint in the cellForRowAtIndexPath: method,but it didn't get in the method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell" forIndexPath:indexPath];
NSArray *items = [[BNRItemStore sharedStore] allItems];
BNRItem *item = items[indexPath.row];
cell.textLabel.text = [item description];
return cell;
}
Try this in cellForRowAtIndexPath to fix the crash issue and also check that the delegate properly set or not
static NSString *CellIdentifier = #"yourCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Thank you
Please make sure you have followed these steps:
Step 1: Conform to UITableViewDataSourceDelegate and UITableViewDelegate
Step 2: Set self.tableView.delegate = self and self.tableView.datasource = self
Please check that you have properly connected "Data Source" and "Delegate" of the tableview to the View Controller either from Code or from storyboard.
Please confirm
add Protocols in your BNRItemViewcontroller just like this : #interface BNRItemViewcontroller() <UITableViewDelegate,UITableViewDataSource>
if you use Storyboard or xib, you should confirm dataSource & delegate with the outlets of Storyboard/xib or write self.tableview.dataSource = self & self.tableview.delegate = self instead.
there are 2 ways
1.Please check that you have properly connected "Data Source" and "Delegate" of tableview
2. self.tableView.delegate = self & self.tableView.datasource = self
Make sure numberOfRowsInSection is not return 0;
- (instancetype)init{
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
self.tableView.dataSource = self;
self.tableView.delegate = self;
for (int i = 0; i < 5; i++) {
[[BNRItemStore sharedStore]createItem];
}
}
return self;
}
EDIT
write this line in init method.
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"UITableViewCell"];
There can be seven reasons:
Like in accepted answer
Controller needs to conform to UITableViewDataSourceDelegate and UITableViewDelegate
You must assign delegates self.tableView.delegate = self and self.tableView.datasource = self
Futhermore:
numberOfSectionsInTableView must return number > 0 (1 if you want to have one main section)
numberOfRowsInSection must return number > 0
UITableView needs different frame than CGRectZero. You should't create UITableView in that way: self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
heightForRowAtIndexPath must return number > 0
Some other controller (in inheritance) can take delegate methods. Only if you have one tableView for more than one controller.

Reload data is not calling cellForRowAtIndexPath:

I've been banging my head against the wall since I thought I tried everything possible on stackoverflow.
So currently I am creating a table like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
NSLog(#"CHECK IF THIS IS CALLED");
static NSString *CellIdentifer = #"CellIdentifier";
CBPeripheral *placeHolder;
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifer];
// Using a cell identifier will allow your app to reuse cells as they come and go from the screen.
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifer];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
placeHolder = _connectedPeripherals[indexPath.row];
cell.textLabel.text = placeHolder.name;
}
return cell;
}
and I am calling [self.tableView reloadData] from another function that I call. I know it's getting called in that function, but cellForRowAtIndexPath does not get called again.
I created a UITableView property on my .h file
#property (strong, nonatomic) UITableView *tableView;
And created the table like this
self.tableView = [[UITableView alloc] init];
self.tableView.rowHeight = 60.0f;
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.tableView];
[self.view addConstraints:#[ [HTConstraints leftAlignView:self.tableView
toView:self.view
withSpacing:5],
[HTConstraints topAlignView:self.tableView
toView:self.view
withSpacing:5],
[HTConstraints rightAlignView:self.tableView
toView:self.view
withSpacing:5],
[HTConstraints bottomAlignView:self.tableView
toView:self.view
withSpacing:5],
]];
So far what I've tried was making sure that [self.tableView reloadData] was being called in the Main thread. Making sure my sections did not return 0.
Edit
This is my reloadData function and is called in another class
by [[RootViewController sharedInstance] reloadData]; and the log prints when I call it.
- (void)reloadData {
NSLog(#"Reloading");
[self.tableView reloadData];
}
set a break point inside -(void)reloadData or try to append the count of your UITableView datasource in your NSLog.
Usually cellForRowAtIndexPath is not getting call because it does not have anything to display.
I saw, in your code you forgot to add your tableView as a subView to the controller.
Add below code after your tableView's initialization
[self.view addSubview:tableView];

Get height of item from another .m file

I have a custom cell in a UITableView. I programatically created a label with a height of 200 and a width of 50. When I do an NSLog in the customCell.m of the label's width and height, it gives me w: 50 and h: 200. But when I do an NSLog in mainViewController.m it gives me 0 for the height and width.
Not sure why it does that. I need to get the real height of the label in the mainViewController.m
Here's my code:
customCell.m
- (void)awakeFromNib {
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setBackgroundColor:[UIColor yellowColor]];
[self.label setText:#"Hello"];
[self.myView addSubview:self.label];
CGRect myFrame = self.myView.frame;
myFrame.size.height = self.label.frame.size.height;
self.myView.frame = myFrame;
NSLog(#"%f", self.label.frame.size.height); // Results: 200.0000
}
mainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
customCell *cellVC = [[cutsomCell alloc] init];
NSLog(#"%f, %f", cellVC.label.frame.size.height, cellVC.frame.size.height); // Results: 0.0000, 44.0000
}
I setmyViewto 0 in the storyBoard.
If you don't understand something, please ask and I will be happy to explain.
Update
Here is my code:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setBackgroundColor:[UIColor yellowColor]];
[self.label setText:#"Hello"];
[self.myView addSubview:self.label];
view
}
return self;
}
viewDidLoad
[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:#"cellID"];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *customCell = #"customCell";
customCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellID" forIndexPath:indexPath];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:customCell owner:nil options:nil] objectAtIndex:0];
}
return cell;
}
The problem now is that when I run the app, no cells get shown. But I do get the correct NSLog.
In your mainViewController you just programmatically created the cellVC using alloc and then init, you did not create it from the nib, like you did it in the customCell.m so the awakeFromNib method was not called on it.
Update
Change back to using the custom cell from xib (instead of registerCell)
[self.tableView registerNib:[UINib nibWithNibName:#"CustomCellxib"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:#"CustomCellReuseID"]; // in the viewDidLoad of the mainViewController
Then deque the cell - you do not really need to check if the cell is nil because dequeue is now guaranteed to return a cell
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"customCellReuseID" forIndexPath:indexPath];
in your tableview datasource method
Keep the code currently in your awakeFromNib to initialize the custom cell added from nib. The default cell from the xib is fully initialized here so you should be able to customize the custom view. You do not need the initWithIdentifer anymore
You can optionally implement the table view delegate methods like:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// calculate the row height or return a constant
return 200.0;
}
The problem is that -awakeFromNib does not get called directly after -init
Try this:
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setBackgroundColor:[UIColor yellowColor]];
[self.label setText:#"Hello"];
[self.myView addSubview:self.label];
CGRect myFrame = self.myView.frame;
myFrame.size.height = self.label.frame.size.height;
self.myView.frame = myFrame;
NSLog(#"%f", self.label.frame.size.height); // Results: 200.0000
return self;
}

Trying to add a Tableview inside of a UIView. What am I doing wrong here?

I'm not sure how to approach this. I'm loading a separate table view controller nib file to my viewcontroller. How do I position it the way I want? Also, Is the below query all I need, or am I missing something? It keeps crashing on me.
- (void)viewDidLoad
{
[super viewDidLoad];
HSTableViewController *tableViews = [[HSTableViewController alloc]initWithNibName:#"HSTableViewController" bundle:nil];
[self addChildViewController:tableViews];
tableViews.view.frame = CGRectMake(0, 0, 100, 100);
//tableViews.view.frame = self.view.bounds;
[self.view addSubview:tableViews.view];
[tableViews didMoveToParentViewController:self];
To add a tableview in code to a view controller wherein that VC will act as both the data source and delegate you would do the following.
- (void)viewDidLoad
{
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.textLabel.text = #"Hello World";
return cell;
}
And then in your .H file you need to inform the program that you're going to act as both the Delegate and DataSource
#interface NSSViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
From what I gathered out of your question, that should get you where you need to go. I will edit accordingly if you require further assistance.
Set your UITableView's frame in -viewWillAppear: like this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
tableViews.view.frame = self.view.bounds;
}
If anyone else needs this. See this tutorial I found on youtube that helped a lot. Thanks for all the help.
http://www.youtube.com/watch?v=DzedmcFlm1c

Resources