I'm populating a TableViewController given an array of NSManagedObjects of class "SampleClass". Although the number of objects in the fetched array returns correctly (i.e. if the table is to display 59 objects, 59 rows are created), the other parameters for the cell are "glitchy" to display.
For example, where there should be a title set by object.name, "null" until you click on the the cell, select another cell, and then come back to the initial cell.
I've tried `[tableview reloadData]' in the view will appear, and it still takes too long to load the data. Is there a better way to fill in the cell instead of:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
Class *classObject = [dataArray objectAtIndex:indexPath.row];
cell.textLabel.text = [classObject name].....
where dataArray points to the NSMutableFetchedArray from a coreData call
Note: the simulator misses filling more of the cells than the actual iPad. once another tab is selected however, all the cells display correctly when you return to the tab.`
You may want to look into NSFetchedResultsController
http://developer.apple.com/library/iOS/ipad/#documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html
It is a special class which is meant specifically for populating a table with results from a core data query.
In the past when using core data I have always used this class over other means.
Related
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.
Hi I am trying to make table view that has 5 cell and each cell automatically fills from the data or data type I have stored. here is the an example of what I have in mind, Please let me know if my question wasn't clear enough
cheers.
Maybe I asked my question in a wrong way, I'll try to explain it more.
So the Application I am making works this way:
I have 5 different Drill type that each has different condition, and I need to make a different drill recording stats (UI) and tableView for each drill type,
So in the first table view that call Drills I have a cell that should show drill type and date that user made also one Create drill button that takes the user to create drill (UI ), that has some attributes in it for example name, date , and DrillType(only 5 option),
After this I have to make 5 different table and scoringViewControl for each drill type specifically that they be able to insert their stats as many times as they want.
And here I have problem, I don’t know what is the best way to manage navigating my cells in to the correct [drilltype] tableview..
(if I didn’t have to have some condition in create drill I would just made 5 statics Cell and navigate them into different direction)
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.drill.drillType isEqual: #"Grouping"] ){
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Drill *drill = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = drill.drillType;
cell.detailTextLabel.text = drill.drillDate;
return cell;
}
else if([self.drill.drillType isEqual: #"Normal"] ){
static NSString *CellIdentifier = #"Cell2";
UITableViewCell *cell2 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Drill *drill = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell2.textLabel.text = drill.drillType;
cell2.detailTextLabel.text = drill.drillDate;
return cell2;
}
return 0;
}
If you need want to have many cells you should use dynamic dispatch. Use dictionary to map type of cell to the key (if statement). Here is code
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *cellIds = #{#"Grouping" : #"GroupingCellId", #"Normal" : #"NormalCellId"};
Drill *drill = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString *CellIdentifier = cellIds[drill.drillType];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[self configureCell:cell withObject:drill];
return cell;
}
Also if you need to do some specific configuration for cells you could do it in 2 ways:
1 - Subclass a UITableViewCell and implement method that does cells configuration. different cells will implement this method in different ways. This technic is called "Polymorphism". Some explanation
[cell setDrill:drill]
2 - Make a dynamic dispatch (call a method) depending on what type is it. The same tech nick as for getting different cells for different type.
NSDictionary *configMethods = #{#"Grouping" : #"configGrouping", #"Normal" : #"configNormal"};
NSString *method = configMethods[drill.drillType];
[self performSelector:NSSelectorFromString(method) withObject:cell withObject:drill];
I was having troubles using the dequeue mechanism in my tableview, i have a custom cell with a uiTextField.
When a put some value on it and do a scroll, the value of the TextField goes to another cell.
Anybody can help me on it ?
Thanks guys.
Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MyPedidoItemCell";
PedidoItemCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (!cell) {
cell = [[PedidoItemCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Produto *produto = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.lblNome.text = produto.nome;
cell.lblCodigo.text = produto.codigo;
cell.lblFuncao.text = produto.funcao;
return cell;
}
When you call dequeueReusableCellWithIdentifier it may return a cell that has scrolled out of view but still contains data in the UITextField. If you don't clear the content of the UITextField or set it to the proper value for the row, you may see unwanted data.
The code you showed is using CoreData to load data for cell, but you mentioned that you don't store the data anywhere.
I suspect that the you are getting object with no data from your fetchedResultsController because you did not store any data.
So quite possibly the produto is nil and you are not setting any values on cell.
Eventually the cell you updated manually gets reused and you see the text again.
You need to first store the data that you typed into the UITextField before you can retrieve it from core data.
I've created a navigation controller based application that uses core data. Without modifying much of the code from the starting application first, I'd like to be able to add rows by having the option to add rows via a dynamic row after I push edit.
Other examples I've found such as the one found at this site show the desired functionality however it does not use core data, so I haven't been able to translate this correctly using core data.
I've looked at the sample application iPhoneCoreDataRecipes and that application includes the desired functionality, however the sample is incredibly complex. Based on the sample app, i've added the following to my - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath function
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// For the Ingredients section, if necessary create a new cell and configure it with an additional label for the amount. Give the cell a different identifier from that used for cells in other sections so that it can be dequeued separately.
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:0];
NSInteger rows = [sectionInfo numberOfObjects];
NSUInteger ingredientCount = rows;
NSInteger row = indexPath.row;
if (indexPath.row < ingredientCount) {
// If the row is within the range of the number of ingredients for the current recipe, then configure the cell to show the ingredient name and amount.
static NSString *IngredientsCellIdentifier = #"IngredientsCell";
cell = [tableView dequeueReusableCellWithIdentifier:IngredientsCellIdentifier];
if (cell == nil) {
// Create a cell to display an ingredient.
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:IngredientsCellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
}
//
[self configureCell:cell atIndexPath:indexPath];
} else {
// If the row is outside the range, it's the row that was added to allow insertion (see tableView:numberOfRowsInSection:) so give it an appropriate label.
NSLog(#"---- IN ADD INGREDIENTS SECTION ----");
static NSString *AddIngredientCellIdentifier = #"AddIngredientCell";
cell = [tableView dequeueReusableCellWithIdentifier:AddIngredientCellIdentifier];
if (cell == nil) {
// Create a cell to display "Add Ingredient".
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AddIngredientCellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.textLabel.text = #"Add Ingredient";
}
return cell;
}
When I click the edit button I can delete rows, however I'm not getting the added row to click to add rows. The sample app is much to complex to tell what i'm missing. Is there a function to add to automatically add the 'add row' button the end of the table?
EDIT: Added all of my .M file for reference # http://pastebin.com/Ld7kVts7
When I run my NSLog's 1-12 show in the console. I'm not currently trying to add the "add row" row to core data because that row is added or removed every time the user pushes the edit button in the navigation bar.
Have you changed your the numberOfRowsInSection method of your datasource to account for the extra row that you need?
What you need to do is add the new object to your database, then, assuming your tableView's dataSource is an array form your database, call reloadData on the tableView.
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:.