My code is a little different to others, but it works.
I am new to app coding, but I would like to add some of
these into sections:
So some of them have their own group with a small title to each.
But my code looks like this:
and I don't know what to insert to do it right.
(The bottom half of that picture is the pictures in the detail view, that shows up in the detail view when you select something from the table view.)
(I know Xcode shows errors in my code, but it still works. )
Can anyone help me?
You have to implement some UITableView methods and delegate methods (and of course set your class as the delegate of the class) :
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//Here you must return the number of sectiosn you want
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//Here, for each section, you must return the number of rows it will contain
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
//For each section, you must return here it's label
if(section == 0) return #"header 1";
.....
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
cell.text = // some to display in the cell represented by indexPath.section and indexPath.row;
return cell;
}
With that, you can arrange your data as you want : One array for each section, one big array with sub arrays, ... as you want. Antthing will be ok as far as you can return the wanted values from the methods above.
Related
I have a UITableViewController created in storyboard. It has two sections. The first section's rows contain controls laid-out in storyboard. I want to update the rows in the second section using values in an array.
I'm fairly new to iOS development. I understand how to use a UITableViewDataSource to update a table based on the array, but not how to restrict the updates to a specific section. Can anyone outline how to do this?
EDIT This seemed like a simple problem, so I thought I code would just obscure the question. Maybe I was wrong. Heres what I have:
My numberOfRowsInSection function returns 1 in the section number is 0, because the first section (the one I designed in storyboard) has a single row, otherwise it returns the number of elements in the backing data array:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0)
return 1;
else
return [myData length];
}
My cellForRowAtIndexPath function creates a cell if the section number is 1. But I don't know what to do if the section number is zero. How do I avoid having to recreate the rows I laid-out in storyboard?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section == 1)
{
cell.textLabel.text = [myData objectAtindex:indexPath.row];
}
else
{
// What to do here?
}
}
Well If you only have few static controls in the first section why won't you put these controls in a table header view instead? Thus you'll only have one section to worry about :)
In your method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPathadd this
Create 2 differents UITableViewCells and reference them like this
if (indexPath.section == 1) {
NSString *CellIdentifier = #"DynamicCell";
VideoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//You are drawing your second section so you can use your array as values
cell.property1...
cell.property2...
cell.property3...
return cell;
}else{//If you have only 2 sections then else represent your first section
//You are drawing your first section
NSString *CellIdentifier = #"StaticCell";
VideoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
You can change the row value in the delegate method
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
To identify the section, just use:
indexPath.section
You can use reloadRowsAtIndexPaths: with an array of all the indexPaths that are in the wanted section, built with a loop and a NSMutableArray.
- (void)reloadSections:(NSIndexSet *)sections
withRowAnimation:(UITableViewRowAnimation)animation;
The parameter "section" is An index set identifying the sections to reload.
I have a table view which display the contacts from array. I setup the table view delegates by follows.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [contactArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"ContactCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [contactArray objectAtIndex:indexPath.row];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0;
}
But the first cell in the table view always empty. It starts display only from second cell. I thought it may be header view. So I removed the header using the following delegate methods.
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0.0;
}
But still have the problem. I attached the screenshot about this issue.
Any help will be appreciated.
Your TableView is fine and it is working correctly, this is due to some other problem that is included in iOS 7, that automatically scroll insets. To solve this problem, go to your storyboard and select the viewcontroller in which your TableView is and select the ViewController and select the Properties of that ViewController, and uncheck this checkbox, which is read as Adjust ScrollView Insets. See this screen shot,
Your table is correct.Just your table was auto adjusted by the viewController.
You can write self.automaticallyAdjustsScrollViewInsets = NO;
Your Deduction is wrong your first cell isn't missing, but your tableview has started by 64 points down. So change your frame of your tableview or your tableview constraints accordingly.
Tip : Try setting a background colour when you have to debug things like this to clear your doubts.
i got ios application with UITableView
I customize cells in this table, but when number of objects lower than visible cells on screen, all other cells look like simple UITableViewCells.
It should look like this
How should i customize all cells?
UPD Code for dataSource:
pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [dataBase.showMaps count];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 70;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
ShowMapCell *cell = (ShowMapCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ShowMapCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
ShowMap *sM = [dataBase.showMaps objectAtIndex:indexPath.row];
//cell.textLabel.text = sM.name;
[cell initShowMapCell:sM index:indexPath.row];
return cell;
}
You could have just set background color of the tableview. However that solution wont work because you are using different backgrounds for each cell.
So according to me to achieve what you want you need to add some extra (blank) rows to the table and for that you need to return your record + extra cell (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section method. And above that you need to set the background color of table view to one of the cell background because if you are using bouncing effect in the tableview you will find white color when you scroll the tableview up/down.
If you want your UITableView not to have 'empty cells', you will need to hide the cell separators and change the background colour of the tableview to match your colour scheme.
As katzenhut said in the comments, they aren't cells, they are placeholders for content. So if you hide the separators and add them in the xib file for your UITableViewCell ShowCell, then they will no longer be seen when there isn't a cell to place in the table.
So I'm trying to make two tableviews in one view and I'm having some trouble.
I've read some other response on how to do it but they don't exactly help me.
In my .h file I made two outlets for two views calling them myFirstViewText and mySecondViewTex
So in my m files for - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
I want to be able to print out seperate values in each different controller and I'm not too sure since you only return 1 cell?
So far i've Done this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Rx";
static NSString *CellIdentifier2 = #"allergies";
UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:CellIdentifier];
UITableViewCell *cell2 = [tableView dequeueReusableHeaderFooterViewWithIdentifier:CellIdentifier2];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (!cell2) {
cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
}
if (tableView == self.myFirstTextView ) {
cell.textLabel.text = #"HI JAZZY";//[RxDict objectAtIndex:indexPath.row];
}
if (tableView == self.mySecondTextView) {
cell.textLabel.text = #"BYE JAZZY";//[RxDict objectAtIndex:indexPath.row];
}
tableView = self.mySecondTextView;
cell2.textLabel.text = #"I love Jazzy :D";
return cell2;
This prints "I love Jazzy" in my first TableView and nothing gets printed in the second one. Why does this happen and how can I fix it?
Thanks :D
This method gets called by all tableViews that have an instance of your class set as their dataSource.
This means you need to check which tableView was asking for cell number so-and-so.
So, your method should basically look like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == rxTableView) {
//prepare and return the appropriate cell for *this* tableView
}
else if (tableView == allergiesTableView) {
//prepare and return the appropriate cell for *this* tableView
}
return nil; //because you don't expect any other tableView to call this method
}
My suggestion would be to set a tag on both of your table views and then in your tableview dataSource methods check for which the tag the table view your are in. So for instance some where in your code you can do:
myFirstTableView.tag = 1;
mySecondTableView.tag = 2;
later when your are in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.tag == 1)
cell.textLabel.text = #"HI JAZZY";//[RxDict objectAtIndex:indexPath.row];
if (tableView.tag == 2)
cell.textLabel.text = #"BYE JAZZY";
}
Also if you have 2 tableviews with different sizes you can achieve this like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView.tag == 1)
return 1;
else if (tableView.tag == 2)
return 2;
}
One approach I don't see implemented too often is actually to use a NSObject subclass to act as the delegate and datasource for each table, not the view controller. It removes the need for the "if (tableView == someTable) ..." code, and might make both your view controller and UITableView code maintainable and readable.
You'd create an NSObject subclass for each table. These subclasses would contain the desired implementation of your UITableView datasource and delegate methods. You'd then instantiate one of each in your view controller and hook each up to its appropriate table.
Problem 1:
tableView = self.mySecondTextView;
cell2.textLabel.text = #"I love Jazzy :D";
return cell2;
What you are doing here is always returning cell2, setting its text "I love jazzy :D" so it will always fill the first table view because you would not have set the tableView=mySecondTextView before entering into the method. The delegate is always targeting firstTableView.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Problem 2:
if (tableView == self.myFirstTextView ) {
cell.textLabel.text = #"HI JAZZY";
//[RxDict objectAtIndex:indexPath.row];
//for printing in first table view return cell here like
return cell;
}
if (tableView == self.mySecondTextView) {
cell.textLabel.text = #"BYE JAZZY";
//[RxDict objectAtIndex:indexPath.row];
//for printing in second tableview return cell two here
return cell2;
}
Make sure the table you want to target is set before entering into this function. You can set it in numberofsection method, the view didload method or somewhere else from where you want to show or target table view (like clicking on some button). But you can't set it here.
For example, I have 3 articles and when I display articles I want to display one more cell before the first one (that would be then 4 total).
I need to display that first article which is not in array and then articles which are in array.
UPDATE
I have tried next:
- (NSInteger)tableView:(
UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ([arr count] + 1);
}
But my app then crash sometimes and I see over NSLOG then that app enters cellForRowAtIndexPath before I call [tableView reloadData].
This is something you should not really do.
Well, you can cheat the framework by returning a view (from -tableView:cellForRowAtIndexPath:) which would contain 2 subviews: your "first article" cell and the original first cell; don't forget to modify -tableView:heightForCellAtIndexPath: as well (otherwise your view would get cut).
But in general, you should change you data model behind the table view to dispay 4 cells – this is just a more valid approach.
You can do like this :
Return an additional row using this method :
// Each row array object contains the members for that section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [YouArray count]+1;
}
At the end check for this added row :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Create a cell if one is not already available
UITableViewCell *cell = [self.mContactsTable dequeueReusableCellWithIdentifier:#"any-cell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"any-cell"] autorelease];
}
//Identify the added row
if(indexpath.row==0)
{
NSLog(#"This is first row");
}
else{
// Write your existing code
}
}
You need to add a extra value in the array using insertObject
[arr insertObject:[NSNull null] atIndex:0];
And implement the methods like:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arr count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if([arr onjectAtIndex:indexPath.row] == [NSNull null])
{
// 1st cell extra cell do your stuff
}
return cell;
}
Do you keep all your articles in an array? You should add the new article to the array too. The array is your datasource. I take it that you'd want to insert the new article as the first element in your array if you'd like it to appear in the top cell. As soon as you've updated your array you should call [mytableView reloadData] which triggers all the datasource methods to be called and reload your table's data.