I have UIview contains tableview with search display controller
after searching it display the same table my expectation I have a problem with :
TableView numberOfRowsInSection# so I debugged it. it display search view but it doesn't fire the if statement
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == aSearchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}
else
{
return [collection count];
}
}
The first parameter in your delegate function is called theTableView and not tableView, so you should compare
if (theTableView == aSearchDisplayController.searchResultsTableView)
...
Related
I'm trying to make a UITableView present a determined number of rows for a section, but even when I verify that its data source is returning x number of rows for numberOfRowsInSection, the table view shows x-1.
The exception to this unexpected behavior is if the numberOfRowsInSection is less than 3.
I've even put a breakpoint in cellForRowAtIndexPath and I confirmed it's being called for the row that is not appearing.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == SectionNumber_One) {
return 6;
} else {
return self.numberOfProjectRows; // This returns x, but x-1 rows are being shown
}
}
For example, if self.numberOfProjectRows is 5, only 4 rows are shown for the second section.
If I increase it manually to 6, it shows 5 rows but the data that should be in the 5th position, isn't there.
It doesn't seem to be related to screen size as I tested it on an iPad with same results.
Why is this happening? Is there some other possible modifier of the number of rows in a section?
I'm attaching an screenshot if it's of any help.
EDIT - Here are my delegate methods:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Cell with reuse identifier setup
if (section == SectionNumber_One) {
// cell setup for section one that's showing up ok
} else if (section == SectionNumber_Two) {
UITextField *projectField = cell.projectTextField;
if ([self.userProjectKeys count] > row) {
projectField.text = self.availableProjects[self.userProjectKeys[row]];
}
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Hide the password row for existing users
if (indexPath.row == FieldTag_Password && ![self.user.key vol_isStringEmpty]) {
return 0.0f;
} else {
return UITableViewAutomaticDimension;
}
}
The problem is probably not in your Datasource methods, but your Delegate methods, tableView(_:heightForRowAt:).
If you do not return a correct height for the cell, it won't show up.
It doesn't matter if you write 1000 cells in your datasource. If you don't return the height, they wont show up.
You are not comforming to the MVC pattern in implementing the table. You must return the count of the tableView's datasource, not variables of it.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == SectionNumber_One) {
return 6;
} else {
return [_displayingArray count]; // <-- here
}
}
If you want different items for each sections, then declare different datasource (ie array) for each of them.
EDIT: Even returning constant 6 is dangerous in the other section - you ought to add items to another fixed array and return that array's count in this delegate.
I'm having trouble deciding.
I created a model class, and another one as a singleton,
the singleton uses a NSMutableArray and returns a NSArray as a copy.
One of the UITableViewController will show the array of data.
The question is, if I want to show different data on each UITableViewController should i create multiple arrays and methods that save and edit the arrays or is there a better way to do this?
On your UITableViewDataSource methods, you can decide what information to return based on which TableView is calling the method. For example:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//Check which tableview is calling
if (tableview == self.tableView1) {
// Return the number of sections for each possible Table
return 1;
} else {
return 2;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
// If you're serving data from an array, return the length of the array:
if (tableview == self.tableView1) {
// Return the number of sections for each possible Table
return [dataArray1 count];
} else {
return [dataArray2 count];
}
}
And the same for any DataSource/Delegate methods you may need to implement.
Hope that helps!!
I Have a one table view and i have two array. My arrays name AllItems and SpecialItems. I Use segment control. I wantto if segment value is 0 tableview load AllItems Array, When change segment value and value is = 1 than mytableview reload tada but SpecialItems array. Can u help me please. Thanks.
I solved this problem with table tag.
- (IBAction)segmentControlChanged:(UISegmentedControl *)sender {
if (sender.selectedSegmentIndex == 1) {
mytable.tag = 1;
}
else
{
mytable.tag = 0;
}
[mytable reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(tableView.tag==1)
{
return [specialItems count];
}
else
return [allItems count];
}
You could create two data source classes that implement all the UITableViewDataSource methods: one for AllItems and one for SpecialItems. To switch between the two, connect a valueChanged action. In the method that is called, set the data source and reload the table view.
- (void)valueChange:(UISegmentedControl *)sender
{
if (/* condition for all items */) {
self.tableView.dataSource = self.allItemsDataSource;
} else {
self.tableView.dataSource = self.specialItemsDataSource;
}
[self.tableView reloadData];
}
I would personally create an array which the data is loaded from. Put this in your implementation:
NSArray * _tableData
Then in your viewDidLoad just allocate this for the array which we want it to start on.
_tableData = [[NSArray alloc] initWithArray:allItems];
This initially loads the data we will always see as the segment control starts on index 0. We have to set the initial data somewhere so the tableView loads with some data in it.
Then set the number of rows and the cellForRowAtIndex to pick up from the _tableData array
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _tableData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView_ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView_ dequeueReusableCellWithIdentifier:bCell];
// Here we use the specific array as we would normally
return cell;
}
This step means the tableView will load with the array. Even if the array is empty the view will still load as the number of cells will be zero.
Now in our value changed function we can reset the array as we need to:
- (IBAction)segmentControlChanged:(UISegmentedControl *)sender {
if (sender.selectedSegmentIndex == 1) {
_tableData = allItems;
}
else {
_tableData = specialItems;
}
[self.tableView reloadData];
}
You just need to make sure the segment control changed is linked up in the XIB file (or programatically) and that you reload the table after choosing the array.
This kind of thing is actually really easy to do. I would definitely recommend working it through step by step if you're having trouble. Make sure each step is working before applying the next:
Get the tableView loading with both sets of data individually
Confirm that the segment control is calling the change function when clicked
Then that should do it
I have two tables in the same class, I need each table contains different data but i have a trouble with the delegate... How can make each table contains a separate delegate? Thanks, sorry for my English.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1; }
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [dataTable1 count];
}
-(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CeldaFamilia *cell = (CeldaFamilia *)[aTableView dequeueReusableCellWithIdentifier:#"CeldaFamilia"];
if (!cell) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CeldaFamilia" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.propTextFamilia.text =[dataTable1 objectAtIndex:indexPath.row];
return cell;
}
You can do this by looking at the tableView argument that was passed in. Example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView1) {
return [dataTable1 count];
} else /* tableView == self.tableView2 */ {
return [dataTable2 count];
}
}
With this pattern, you need to put if statements in all of your UITableViewDataSource and UITableViewDelegate methods.
Another way to do it is to make one method that returns the array of data for the table view:
- (NSArray *)dataTableForTableView:(UITableView *)tableView {
if (tableView == self.tableView1) {
return dataTable1;
} else /* tableView == self.tableView2 */ {
return dataTable2;
}
}
Then use that function in each of your data source/delegate methods. Example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self dataTableForTableView:tableView] count];
}
Your tableView:cellForRowAtIndexPath: method might still need to have an if statement, depending on what the data looks like for each table.
However, I recommend you don't use either of those patterns. Your code will be better organized and easier to understand if you make a separate data source/delegate for each table view. You can use two instances of the same class, or you can make two different classes and use one instance of each class, depending on your needs.
If you set the tags of each tableView to different numbers, you can use that to differentiate them.
For example, you can do
tableView1.tag = 1;
tableView2.tag = 2;
Then in your delegate and dataSource methods, you can do:
if (tableView.tag == 1) {
//first table data
}
else if (tableView.tag == 2) {
//second table data
}
You can add other class for second table (secondTable) and implement in it data source and delegate table view protocols. And in your view controller, which contains 2 tables in viewDidLoad :
SecondTable *second=[SecondTable alloc] init];
second.delegate=self;
second.datasource=second;
And your second table would be a object of SecondTable class, and first table you do like always.
I have two UITableView which appears according to UISegmentControl.selectedSegmentIndex. The first table is grouped style and the second is plain.
NSFetchedResultsController is for the first UITableView, and NSMutableArray for the second.
In my numberOfSectionsInTableView:
return [_fetchedResultsController.sections count];
In this case the second UITableView's data displays for 3 times (because FirstTableView section count = 3).
I would like for the second tableView numberOfSectionsInTableView
return 1;
You should check which tableview you are displaying before returning the count. You can use the tableView input param for this.
For eg:-
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView == self.firstTableView) //or (tableView == firstTableView)
return [_fetchedResultsController.sections count];
else
return 1;
}
You can use the following condition...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
if(tableView == firstTableView)
return 1;
else if (tableView == secondTableView)
return 2;
//... and so on you can do like this....
}
All the best !!!
I guess you are setting the same data source for both table views. If that is the case, then in your:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
if(tableView == firstTableView){ //assuming you have a reference to the first table view
return [_fetchedResultsController.sections count];
}else{
return 1;
}
}
You will have to do this in all your datasource methods. Instead it would be easier to make the datasource of the tableviews different.
To do this you can drag an object (the blue cube ) from the object library and set its class as say, SecondTableDatasource. And then set this object as the datasource for your second table, and implement the corresponding datasource methods in that class.
You can add tag for each tableView and check for each tag in numberOfSectionsInTableView