I want to display webservies array values in tableview for each cell i need to display two values Ex:total ten values mean each cell display 2 values in each row. webservies total value nine means each display two values last cell display one value. how can i achieve this help me. new for development.
Follow this tutorial for custom cell and design it the way you want:
Crafting Custom UITableView Cells
This is the method where you can set the values for the custom cell labels from each array:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
return cell;
}
Create a custom class of UITableViewCell say CustomCell and add 2 labels to it both occupying half of the space or as per your design what you need. Now say that they are labelOne and labelTwo.
From your Controller class you got the array of objects that you need to display in lables. In UITableViewDataSource method use this code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return (dataArray.count+1)/2; //This will provide correct row count for odd data set, such as when count is 9
}
and use this code to populate cell label text
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"customCell"];
}
cell.lableOne.text = [dataArray objectAtIndex:indexPath.row*2];
if((indexPath.row*2)+1 < dataArray.count){
cell.lableTwo.text = [dataArray objectAtIndex:(indexPath.row*2)+1];
}
return cell;
}
In cellForRow: you should send the cell the values from the array at [yourArray objectAtIndex:(indexPath.row * 2)] and [yourArray objectAtIndex:(indexPath.row * 2 + 1)]. so row 6 will get the objects for indexes 12 and 13.
Also you should always check if the objects exists. something like - if (yourArray.count > (indexPath.row * 2)) and if (yourArray.count > (indexPath.row * 2 + 1)) than send to cell else don't. (than you will get one object in cell when you get odd number of values.
Using % fetch the number of rows for the table view. Then for the last cell if value is null then display blank... you can have a basic logic for that. Take 2 lbls in each cell and display on those lables which contains value in it.
Related
I have a populated array which I can display in the tableview, but I want to hide 3 of the cells text (out of 7 cells). I know the below code is wrong, but in this case I only want to show the text in cell 0.
cell.animal.text[0] = animalarray[0]
cell.animal.hidden = true
Because you don't have codes, I can only use words to describe how it should be done.
You need to have an array of the unwanted text that you do not want to show.
Inside your cellForRowAtIndexPath, you need to have a for loop, to go through the animalarray, and within the for loop, have an if-else statement to check whether if(unwantedtext == animalarray), then cell!.textLabel.text = " "
You need to show me codes for me to help you.
I'm gonna try to help you in Objective C, hopefully I can make the logic so clear the language difference doesn't matter.
Generally you are telling the TableView what to print for each cell in the below delegate method in your ViewController.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.textLable.text = animalArray[indexPath.row];
return cell;
}
This is where you will decided which index in the animalArray you do or do not want to print. If your requirement is a static the simplest is to hardcode the the blocking.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(!(indexPath.row == self.indexIDontWantToPrint)) {
cell.textLable.text = animalArray[indexPath.row];
}
return cell;
}
If the indexes you do not want to print is dynamic and submitted to you by say an array.
You need to replace if(!(indexPath.row == self.indexIDontWantToPrint)) with checking if indexPath.row is inside the array of indexes you are to ignore.
NSArray has a handy containsObject method you can use to check if the array contains the current index the tableView wants to print. Be careful of the type difference of indexPath.row is NSInteger while NSArray needs to carry NSNumber for simple numeric numbers.
Adding more efficient logic than jo3birdtalk
1) Instead of having a extra array, you can creat an Object which contains a string & Bool.Add these objects in animalarray
2) Get the object from array at indexpath & check
if(animal.isShow == YES),if Yes show the text else hide label Or set blank string whatever you required
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
Animal * animal = animalArray[indexPath.row];
if(animal.isShow == YES)
{
show the text
}else
{
hide label Or set blank string whatever you requered
}
return cell;
}
So I want to add a cell to the bottom of a UITableView that only appears when there is no more content.
The goal is that when there is no more users in the list I want to have a cell that shows up with Twitter, Facebook etc buttons so the user can invite more users. Any hints?
All the best
Start off by creating different NSTableViewCell's - one for your regular data and one for your "Social Media" cell at the end.
In the UITableViewDataSource you can report the number of rows as being one greater than the total number of rows for your data
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [mDataSource count] + 1;
}
Then, in your cellForRowAtIndexPath method, check if it's the last row, and return your "social media" cell.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
NSString *cellIdentifier = #"Cell";
if (indexPath.row == [mDataSource count] + 1) {
cellIdentifier = #"SocialCell";
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
...
}
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 tableView with sections, which could be opened and closed. So, when I tap on a section to open it, it is getting filled up with cells and -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) get called exactly as much times as I provided in -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section.
Is that correct? Shouldn't it be just number of visible cells?
Because in my case I have bad situation: I have a lot of custom cells (50~100 cells) and calling -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) for each cell slows down the opening of a section, cause each time reading from nib is performed and cell content is being populated with image.
I've check visibility of cell inside -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) like this:
if ([[self.tableView indexPathsForVisibleRows] containsObject:indexPath])
NSLog(#"visible %#", indexPath);
and it shows that from out of 45 cells, only 6 or 7 are visible. Others are out of visible area. But creating cells still performed.
Here is the code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"IVCell";
IVCamera *camera = [server.cameras objectAtIndex:indexPath.row];
IVServerListViewCell *cell = (IVServerListViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"IVServerListCell" owner:self options:nil];
cell = (IVServerListViewCell*)_tableViewCell;
self.tableViewCell = nil;
}
[cell textLabel].text = camera.cameraName;
cell.preview = camera.preview;
cell.userData = camera;
cell.isEnabled = (server.isInactive)?NO:camera.isOnline;
return cell;
}
Is it still correct? Or am I missing something?
increase your
estimatedRowHeight of UITableview.
Well, I somehow dealt with my problem. Here are my ideas and thoughts how I came to the solution. Maybe it could be helpful to somebody.
I've instructed memory allocations and call stack using Instruments during opening section events. It showed me, that the majority of time is spent on loading cell from nib file.
Firstly, that I've done was reducing the size of nib file, i.e. minimizing the number of views used in custom tableview cell (now its only 2 views and 2 labels, instead of 6 views, 2 images and 2 labels before). It gave me some improve in cells loading. Apple documentation suggests to use as few as possible views and do not use transparency. So be attentive to these suggestions.
Secondly, as I discovered earlier, that not all cell are visible which are created by -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *), I decided to reduce somehow the number of loadings new cells from nib file. To achieve this, I've came to simple idea: return blank default cells for invisible rows, while load custom cells from nib for visible ones. Here is the piece of code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self index:indexPath isInvisibleInTableView:tableView])
return [self getBlankCellForTableView:tableView];
// the rest of the method is the same
...
}
-(BOOL)index:(NSIndexPath*)indexPath isInvisibleInTableView:(UITableView*)tableView
{
NSMutableArray *visibleIndexPaths = [self getExtendedVisibleIndexPathsForTableView:tableView];
return ![visibleIndexPaths containsObject:indexPath];
}
-(UITableViewCell*)getBlankCellForTableView:(UITableView*)tableView
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"IVBlankCell"];
if (!cell)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"IVBlankCell"] autorelease];
return cell;
}
As you can see, I'm not using just -(NSArray*)indexPathsForVisibleRows method of tableview for detecting visible cells. Instead, I've wrote my own method -(NSMutableArray*)getExtendedVisibleIndexPathsForTableView:(UITableView*)tableView. It was necessary because for some reason, when using -(NSArray*)indexPathsForVisibleRows the cells that are next to the last one visible cell or the cells that are previous to the first one visible cell were created as blank cells and looked like empty cells while scrolling. To overcome this, in -(NSMutableArray*)getExtendedVisibleIndexPathsForTableView: (UITableView*)tableView i'm adding border cells to the visible array cells:
-(NSMutableArray*)getExtendedVisibleIndexPathsForTableView:(UITableView*)tableView{
NSArray *visibleIPs = [tableView indexPathsForVisibleRows];
if (!visibleIPs || ![visibleIPs count])
return [NSMutableArray array];
NSIndexPath *firstVisibleIP = [visibleIPs objectAtIndex:0];
NSIndexPath *lastVisibleIP = [visibleIPs objectAtIndex:[visibleIPs count]-1];
NSIndexPath *prevIndex = ([firstVisibleIP row])?[NSIndexPath indexPathForRow:[firstVisibleIP row]-1 inSection:[firstVisibleIP section]]:nil;
NSIndexPath *nextIndex = [NSIndexPath indexPathForRow:[lastVisibleIP row]+1 inSection:[lastVisibleIP section]];
NSMutableArray *exVisibleIndexPaths = [NSMutableArray arrayWithArray:[tableView indexPathsForVisibleRows]];
if (prevIndex)
[exVisibleIndexPaths addObject:prevIndex];
[exVisibleIndexPaths addObject:nextIndex];
return exVisibleIndexPaths;
}
Thereby, I've reduced the time of opening sections with large number of custom cells, which was proved by Instruments tracing and felt while experiencing the app.
Simply add estimated height for UITableViewCell
Problem In my case was: cellforRowAtIndexPath was getting called array.count number of times, whereas, displayed cells where less than array.count.
To resolve this issue, I have just replaced,
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
with,
(CGFloat)tableView:(UITableView )tableView estimatedHeightForRowAtIndexPath:(nonnull NSIndexPath )indexPath;
check your tableview size.
may be that your tableview height is very large that it keep loading cells until your cell fills all tableview size..
This seems correct yes. the idea about optimizing the loading itself lies within how "dequeueReusableCellWithIdentifier" works.
if u are loading the image from a remote location this is where u would want to optimize the code. but not from the loading of cells as this looks correct here.
I used some similar technique but since indexPathsForVisibleRows is sorted you don't need to use containsObject. Instead you can just do:
//
// Checks if indexPath is visible in current scroll state, we are expanding bounds by 1
// because the cells that are next to the last one visible or the cells that are previous
// to the first one visible could look empty while scrolling.
//
- (BOOL)isIndexPathVisible:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
NSArray *visible = [self.tableView indexPathsForVisibleRows];
NSInteger count = [visible count];
NSInteger first = (count > 0) ? MAX([visible[0] row] - 1, 0): 0;
NSInteger last = (count > 1) ? [visible[1] row] + 1: first + 2;
return row >= first && row <= last;
}
By the way; this assumes that you are using only one section. It won't work for more than one section.
Adding an else solved my problem.
Where I reseted any changes that were made to the cell.
if (! self.cell) {
self.cell = [[LanguageCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
self.cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
self.cell.checkImage.image = NO;
}
I want to create a table-view with 495 cells.
I want to import cells with NSArray, is it right way?
If yes, how can create 495 cells with simple code?
Not like this :
#"Cell 1" # "cell 2" #"cell 3", #"cell 4", #"cell 5" ............. #"cell 495"
you will have to return the value of 495 in the '-tableView:numberOfRowsInSection:' method like
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Returning num rows");
return 495;
}
then populating the table with your array
- (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];
}
NSUInteger row = [indexPath row];
cell.text = [array objectAtIndex:row];
return cell;
}
here i assumed that you are storing text data in the cells.
Also create the array in viewDidLoad method.
The thing to remember with tables is that there is complete separation between the data and the actual cells displayed in the interface. The data list can be arbitrarily long but the tableview will only display as many actual cells as needed to fill up the physical screen. This is what -tableView:cellForRowAtIndexPath: is for. The table tracks which rows are actually visible to the user and then ask the datasource for data just for the displayed rows.
You can use an NSArray to hold your data and the easiest way to populate the array is to read it in from a file. You can create a plist file with the /Developer/Applications/Utilities/Property List Editor.app (part of the standard developers tools) that NSArray can read in directly with initWithContentsOfFile:. (If you just want to create a long list of data to experiment with, you can use NSMutableArray and populate it with a loop.)
In your case, you have 495 entries but the table will only display about 9 cells at a time (just simple default text cells). At the start it will display tables indexed 0-8. The table will call -tableView:cellForRowAtIndexPath: 9 times passing one index i.e. 0,1,2...7,8 each time. Your method will then find the the object in your array at that index e.g. [myArray objectAtIndex:index]. As the user scrolls, the index passed changes. When rows 300-308 are displayed the indexes passed are 300,301,...307,308.
No, this is not the correct way. See the documentation for UITableViewDataSource. Specifically, you'll want to implement -tableView:numberOfRowsInSection: and -tableView:cellForRowAtIndexPath:.