I am trying to gain some knowledge on UISearchDisplayController and going through some tutorial with examples, I have the below class ready with a search bar and table view with data on it.
Header file:
#import <UIKit/UIKit.h>
#interface MyClass : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate>
#property (nonatomic, strong) IBOutlet UITableView *suggestionsTableView;
#property (nonatomic, strong) IBOutlet UISearchBar *searchBar;
#end
Implementation file:
#import "MyClass.h"
#interface DVWNoteTypeSuggestionDisplayController ()
#property (nonatomic, strong) NSArray *items;
#property (nonatomic)BOOL isSearching;
#property (nonatomic, strong) NSMutableArray *filteredList;
#end
#implementation MyClass
- (id)init
{
self = [super initWithNibName:#"SuggestionDisplayController" bundle:BUNDLE];
if (self)
{
// Set the title.
self.title = #"test";
}
return self;
}
- (void)viewDidLoad
{
self.searchBar = [[UISearchBar alloc] init];
[[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.delegate = self;
self.searchBar.frame = CGRectMake(0, 0, 0, 38);
self.suggestionsTableView.tableHeaderView = self.searchBar;
self.items = [[NSArray alloc] initWithObjects:#"Item No. 1", #"Item No. 2", #"Item No. 3", #"Item No. 4", #"Item No. 5", #"Item No. 6", nil];
self.isSearching = NO;
self.filteredList = [[NSMutableArray alloc] init];
}
#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.
// // Usually the number of items in your array (the one that holds your list)
// return [self.items count];
//}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (self.isSearching)
{
//If the user is searching, use the list in our filteredList array.
return [self.filteredList count];
} else
{
return [self.items count];
}
}
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// //Where we configure the cell in each row
//
// static NSString *CellIdentifier = #"Cell";
// UITableViewCell *cell;
//
// cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// if (cell == nil) {
// cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// }
// // Configure the cell... setting the text of our cell's label
// cell.textLabel.text = [self.items objectAtIndex:indexPath.row];
// return cell;
//}
- (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];
}
// Configure the cell...
NSString *title;
if (self.isSearching && [self.filteredList count]) {
//If the user is searching, use the list in our filteredList array.
title = [self.filteredList objectAtIndex:indexPath.row];
} else
{
title = [self.items objectAtIndex:indexPath.row];
}
cell.textLabel.text = title;
return cell;
}
- (void)filterListForSearchText:(NSString *)searchText
{
[self.filteredList removeAllObjects]; //clears the array from all the string objects it might contain from the previous searches
for (NSString *title in self.items) {
NSRange nameRange = [title rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (nameRange.location != NSNotFound) {
[self.filteredList addObject:title];
}
}
}
#pragma mark - UISearchDisplayControllerDelegate
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
//When the user taps the search bar, this means that the controller will begin searching.
self.isSearching = YES;
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
//When the user taps the Cancel Button, or anywhere aside from the view.
self.isSearching = NO;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterListForSearchText:searchString]; // The method we made in step 7
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterListForSearchText:[self.searchDisplayController.searchBar text]]; // The method we made in step 7
// Return YES to cause the search result table view to be reloaded.
return YES;
}
#end
Whenever I try to search for any items in the data set (eg: "Item No. 5") its not hitting the breakpoints on any of the delegate i.e. actually the search is not working. Please suggest what am I missing here as this is just my learning project right now.
It appears that a UISearchDisplayController created programatically in this way is prematurely zeroing the delegate, even though the view controller is retaining the UISearchDisplayController as expected.
Add the following to the end of your viewDidLoad and you'll see that the first log will be a valid object, but the second will be null.
NSLog(#"Delegate should be %#", self.searchDisplayController.delegate);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(#"Delegate is %#", self.searchDisplayController.delegate);
});
The quickest way I've found to get around this is to store your own reference to the UISearchDisplayController via a private property or ivar.
If you have to create object for search bar controller and set delegate search bar its work.
UISearchBar *searchBar = [[UISearchBar alloc] init];
[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.delegate = self;
searchBar.frame = CGRectMake(0, 0, 0, 38);
self.tableView.tableHeaderView = searchBar;
Related
I have an app that was written for iOS 7 the I need to update as UISearchDisplayController is deprecated for UISearchController.
I have went through several tutorials and tried but I cannot get this to work, however I am close.
I am following this pattern.
The problem I am running into is that the pattern I am following loads the data from a son file into an NSDict object, but my data is in an Array. No problem, I just modified the search to use a predicate (I hard coded something for now, get all records with an E in the name).
But I am getting the following error:
2017-09-12 13:01:41.538 Scoular[7644:1963822] -[employee isEqualToString:]: unrecognized selector sent to instance 0x608000105580
2017-09-12 13:01:41.604 Scoular[7644:1963822] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[employee isEqualToString:]: unrecognized selector sent to instance 0x608000105580'
In the SearchResultsTableViewController.m file, at the line
cell.textLabel.text = self.searchResults[indexPath.row];
from the m file below. I am stumped. Any help would be greatly appreciated.
#import "SearchResultsTableViewController.h"
#interface SearchResultsTableViewController ()
#property (nonatomic, strong) NSArray *array;
#end
#implementation SearchResultsTableViewController
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.searchResults count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell" forIndexPath:indexPath];
cell.textLabel.text = self.searchResults[indexPath.row];
return cell;
}
#end
Header File
#import UIKit;
#class EmployeeDetailViewController;
#import <CoreData/CoreData.h>
#import "EmployeeDatabase.h"
#interface EmployeeListViewController : UITableViewController
#end
Implementation File
#import "EmployeeListViewController.h"
#import "EmployeeDetailViewController.h"
#import "SearchResultsTableViewController.h"
#interface EmployeeListViewController () <UISearchResultsUpdating>
#property (nonatomic, strong) NSMutableArray *employees;
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults;
#property (nonatomic,retain) NSMutableDictionary *sections;
#end
#implementation EmployeeListViewController
BOOL isSearching;
//Do I still need this
- (void)awakeFromNib {
if ([[UIDevice currentDevice] userInterfaceIdiom] ==
UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
}
[super awakeFromNib];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Get array of employees and sections
self.employees = [EmployeeDatabase getEmployees];
self.sections = [EmployeeDatabase getSections:_employees];
// There's no transition in our storyboard to our search results tableview or navigation controller
// so we'll have to grab it using the instantiateViewControllerWithIdentifier: method
UINavigationController *searchResultsController = [[self storyboard] instantiateViewControllerWithIdentifier:#"TableSearchResultsNavController"];
// Our instance of UISearchController will use searchResults
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
// The searchcontroller's searchResultsUpdater property will contain our tableView.
self.searchController.searchResultsUpdater = self;
// The searchBar contained in XCode's storyboard is a leftover from UISearchDisplayController.
// Don't use this. Instead, we'll create the searchBar programatically.
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x,
self.searchController.searchBar.frame.origin.y,
self.searchController.searchBar.frame.size.width, 44.0);
self.tableView.tableHeaderView = self.searchController.searchBar;
// Set the back bar button
UIBarButtonItem *backButton =
[[UIBarButtonItem alloc] initWithTitle:#"Employees"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
self.navigationItem.backBarButtonItem = backButton;
}
#pragma mark - Table Sections
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger tmpCount;
if (isSearching) {
tmpCount = 1;
} else {
tmpCount = [[self.sections allKeys] count];
}
return tmpCount;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.employees count];
}
#pragma mark - Table View
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
employee *thisEmployee =
[[self.sections
valueForKey:[[[self.sections allKeys]
sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)]
objectAtIndex:indexPath.section]]
objectAtIndex:indexPath.row];
cell.textLabel.text = thisEmployee.fulNme;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section {
NSString *tmpString;
//if (tableView == self.searchDisplayController.searchResultsTableView) {
//tmpString = nil;
//} else {
tmpString =
[[[self.sections allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:
)] objectAtIndex:section];
//}
return tmpString;
}
#pragma mark - Right side bar alphabetical index
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
NSArray *tmpTitle;
if (isSearching) {
tmpTitle = nil;
} else {
tmpTitle = [[self.sections allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
return tmpTitle;
}
#pragma mark - UISearchControllerDelegate & UISearchResultsDelegate
// Called when the search bar becomes first responder
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
// Set searchString equal to what's typed into the searchbar
NSString *searchString = self.searchController.searchBar.text;
[self updateFilteredContentForAirlineName:searchString];
// If searchResultsController
if (self.searchController.searchResultsController) {
UINavigationController *navController = (UINavigationController *)self.searchController.searchResultsController;
// Present SearchResultsTableViewController as the topViewController
SearchResultsTableViewController *vc = (SearchResultsTableViewController *)navController.topViewController;
// Update searchResults
vc.searchResults = self.searchResults;
// And reload the tableView with the new data
[vc.tableView reloadData];
}
}
// Update self.searchResults based on searchString, which is the argument in passed to this method
- (void)updateFilteredContentForAirlineName:(NSString *)employeeName
{
if (employeeName == nil) {
// If empty the search results are the same as the original data
self.searchResults = [self.employees mutableCopy];
} else {
NSArray *searchResults2 = [[NSMutableArray alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"fulNme contains 'E'"];
searchResults2 = [self.employees filteredArrayUsingPredicate:predicate];
self.searchResults = [searchResults2 mutableCopy];
}
}
#end
In your updateFilteredContentForAirlineName function you are searching from self.employees array which probably contains employee custom class object. For that reason your self.searchResults array also containing same class object.
But in your cellForRowAtIndexPath of SearchResultsTableViewController your are doing cell.textLabel.text = self.searchResults[indexPath.row]; that means you are adding employee object as string in cell.textLabel which causing your app to crash. Instead you can try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell" forIndexPath:indexPath];
employee *thisEmployee = self.searchResults[indexPath.row];
cell.textLabel.text = thisEmployee.fulNme;
return cell;
}
When I click the UITableViewCell , It have selection effect (grey background in clicked cell),But didSelectRowAtIndexPath is not calling ,what happen?
EDIT
this is my code
tableView.h file
#interface PopCardView : MMPopupView <UITableViewDataSource, UITableViewDelegate>
#end
tableView.m file
#property (nonatomic, strong) NSMutableArray *tagsArray;
#property (nonatomic, strong) UIView *backView;
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, assign) NSUInteger lastIndex;
#end
-(id)initWithTags:(NSMutableArray *)tags{
self = [super init];
if (self) {
self.backView = [[UIView alloc] init];
self.backView.backgroundColor = [UIColor whiteColor];
self.backView.layer.cornerRadius = 5;
self.backView.layer.masksToBounds = YES;
[self addSubview:self.backView];
[self.backView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.right.equalTo(self);
}];
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 324, 300) style:UITableViewStylePlain];
_tableView.tableFooterView =[[UIView alloc] init];
[self.backView addSubview:_tableView];
[_tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.bottom.equalTo(self.backView).insets(UIEdgeInsetsMake(45,0, 45, 15));
make.size.mas_equalTo(CGSizeMake(324, 200));
}];
[_tableView registerClass:[PopCardTagViewCell class] forCellReuseIdentifier:#"cell"];
_tableView.allowsSelection = YES;
_tableView.allowsSelectionDuringEditing = YES;
[_tableView setUserInteractionEnabled:YES];
_tableView.dataSource = self;
_tableView.delegate = self;
}
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[_tagsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PopCardData *data = (PopCardData *)obj;
data.selected = #"0";
if (idx == indexPath.row) {
data.selected = #"1";
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifer = #"cell";
PopCardTagViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifer];
if (!cell) {
cell = [[PopCardTagViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifer];
}
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
-(void)configureCell:(PopCardTagViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
PopCardData *data = (PopCardData *)[_tagsArray objectAtIndex:indexPath.row];
//configure cell
[cell setUserInteractionEnabled:YES];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _tagsArray.count;
}
EDIT2
this is my initialize code of PopCardView,it use swift
let pop = PopCardView(tags: self.m_model.getItmes())
pop.show()
The code you show does not set any delegate to the table view. Either this is the reason or you posted an incomplete code snippet.
self.tableView.delegate = self;
and add UITableViewDelegate to your interface like
#interface ClassName ()<UITableViewDelegate>
Make sure you don't have anything in the cell that can swallow the touch event. Things like buttons and textfields can cause this. Strip everything from your cell, test to see if it works, then add things back in slowly to find the culprit.
I'm trying to add a UISearchBar to a UITableView but the method TextDidBeginEditing is not being called. I think I am missing something simple but I can't figure it out.
Header File:
#interface TableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate>
#property (nonatomic, strong) NSMutableArray *initialCities;
#property (nonatomic, strong) NSMutableArray *filteredCities;
#property (nonatomic, strong) UISearchBar *searchBar;
#property BOOL isFiltered;
#end
Implementation File:
#import "TableViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize initialCities, filteredCities, isFiltered, searchBar;
- (void)loadView
{
[super loadView];
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 44.0)];
searchBar.delegate = self;
searchBar.autoresizingMask = (UIViewAutoresizingFlexibleWidth);
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.tableView.tableHeaderView = searchBar;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tableView.delegate = self;
initialCities = [[NSMutableArray alloc] initWithObjects:#"London", #"New York", #"Berlin", nil];
}
#pragma mark - UITableView DataSource Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isFiltered == YES)
{
return filteredCities.count;
}
else
{
return initialCities.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 (isFiltered == YES)
{
cell.textLabel.text = [filteredCities objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = [initialCities objectAtIndex:indexPath.row];
}
return cell;
}
#pragma mark - UITableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
#pragma mark - UISearchBar Delegate methods
- (void)searchBar:(UISearchBar *)searchBar TextDidBeginEditing:(NSString *)searchText
{
searchBar.showsCancelButton = YES;
if (searchText.length == 0)
{
isFiltered = NO;
}
else
{
isFiltered = YES;
filteredCities = [[NSMutableArray alloc] init];
for (NSString *cityName in initialCities)
{
NSRange cityNameRange = [cityName rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (cityNameRange.location != NSNotFound)
{
[filteredCities addObject:cityName];
}
}
}
[self.tableView reloadData];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The result is that the search bar is displayed, the table view is displayed, but when I type text into the search bar the table view is not filtered. There is no crash. Any help is appreciated. Thank you.
Try this
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)searchText
{
// Your filter code
}
The method you implemented is not even present in Protocol
– searchBar:textDidChange:
– searchBar:shouldChangeTextInRange:replacementText:
– searchBarShouldBeginEditing:
– searchBarTextDidBeginEditing:
– searchBarShouldEndEditing:
– searchBarTextDidEndEditing:
(void)searchBar:(UISearchBar *)searchBar TextDidBeginEditing:(NSString *)searchText
This method is not existed in searchBar's delegate.
Use searchBarTextDidBeginEditing.
Go through this tutorial. well explained.
http://www.appcoda.com/search-bar-tutorial-ios7/
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [actualData filteredArrayUsingPredicate:resultPredicate];
}
I'm very confusing with this.
I'm trying to create an UITableView grouped programmatically, using the single view template from Xcode. Looking at internet for some examples, there is no secret, the approach to do this is very simple. I'm not sure if my implementation are wrong or right, because the method tableView:cellForRowAtIndexPath: is never called, but the other ones are called and return a integer > 0.
There is code, any suggestions are welcome.
Thanks,
#import "ViewController.h"
#import "SimpleCell.h"
#interface ViewController () <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, strong) UITableView *table;
#property (nonatomic, strong) NSArray *sections;
#property (nonatomic, strong) NSArray *section1;
#property (nonatomic, strong) NSArray *section2;
#property (nonatomic, strong) NSArray *section3;
#end
#implementation ViewController
static NSString * const CellIdentfier = #"Cell";
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.table];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[table]|"
options:0
metrics:nil
views:#{#"table": self.table}]];
dispatch_async(dispatch_get_main_queue(), ^{
[self.table reloadData];
});
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UITableView *)table
{
if(!_table)
{
_table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
_table.delegate = self;
_table.dataSource = self;
_table.translatesAutoresizingMaskIntoConstraints = NO;
_table.rowHeight = 34.0f;
_table.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
_table.backgroundColor = [UIColor grayColor];
_table.showsVerticalScrollIndicator = NO;
[_table registerClass:[SimpleCell class] forCellReuseIdentifier:CellIdentfier];
}
return _table;
}
- (NSArray *)sections
{
if(!_sections)
{
_sections = #[#"Section1", #"Section2", #"Section3"];
}
return _sections;
}
- (NSArray *)section1
{
if(!_section1)
{
_section1 = #[#"Player a", #"Player b", #"Player c"];
}
return _section1;
}
- (NSArray *)section2
{
if(!_section2)
{
_section2 = #[#"Zone a", #"Zone b", #"Zone c"];
}
return _section2;
}
- (NSArray *)section3
{
if(!_section3)
{
_section3 = #[#"Area a", #"Area b", #"Area c"];
}
return _section3;
}
#pragma mark - UI Table View Delegate impl
#pragma mark - UI Table View Datasource impl
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
DLog();
SimpleCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentfier];
if(!cell)
cell = [[SimpleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentfier];
cell.label.text = [NSString stringWithFormat:#"Section: %i Row: %i", indexPath.section, indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger total = 0;
if(section == 0) total = self.section1.count;
if(section == 1) total = self.section2.count;
if(section == 2) total = self.section3.count;
DLog(#"Rows: %i", total);
return total;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
DLog();
return self.sections.count;
}
#end
Delete this:
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[table]|"
options:0
metrics:nil
views:#{#"table": self.table}]];
It should be called then.
EDIT:
Change this as well:
_table = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped];
This seems to fix it but I'm not sure why. I'm guessing that it has something to do with the table frame having to be larger than 0.
I am stucked in this problem for many hours and have n't found any solution on SO...
I have got a table as a subview in UIViewController. When view loads, all datasource methods are called for tableview, but as I receive data from server and call [someTable reloadData], none of the data source methods are called. I have confirmed through breakpoints that my array do contains 100 objects. Also both delegate and datasource are bind to File owner in IB.
What can be possibly missing ? Please help me... Thanks :(
OutLogController.h
#interface OutLogController : UIViewController<UITableViewDataSource,UITableViewDelegate,ASIHTTPRequestDelegate>
{
NSMutableArray *outstandingKeys;
}
#property (strong, nonatomic) IBOutlet UITableView *someTable;
#end
OutLogController.m
#interface OutLogController ()
#end
#implementation OutLogController
#synthesize someTable;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
outstandingKeys = [[NSMutableArray alloc] init];
someTable = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
someTable.rowHeight = 85;
[self retrieveOutstandingLogFromServer];
}
- (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 outstandingKeys.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];
}
// Configure the cell...
LogUnit *unit = [outstandingKeys objectAtIndex:indexPath.row];
cell.textLabel.text = unit.symbol;
return cell;
}
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 85;
}
-(void) requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"%#",request.responseString);
NSArray *list = [request.responseString JSONValue];//contains 100 objects
for (int i = 0; i < list.count; i++) {
NSArray *singleTrade = [[list objectAtIndex:i] JSONValue];
LogUnit *unit = [[LogUnit alloc] init];
unit.symbol = [singleTrade objectAtIndex:0];
unit.type = [singleTrade objectAtIndex:1];
unit.price = [singleTrade objectAtIndex:2];
unit.remaining = [singleTrade objectAtIndex:3];
unit.order = [singleTrade objectAtIndex:4];
unit.time = [singleTrade objectAtIndex:5];
[outstandingKeys addObject:unit];
}
if(outstandingKeys.count > 0)
{
[someTable reloadData];//does reload table
}
}
EDIT
After removing line:
someTable = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
Datasource methods are called except cellForRowAtIndexPath and table disappears from view since this method is not called. Any idea why it can't get called?
Note: I have confirmed that I have count = 100 after response from server.
someTable = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
You have already bind your UITableView from nib/storyboard. In this case you did not have to alloc again the tableview. Removing this line will do the work
someTable = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
You create new tableView and it doesn't add to current view.
check your outstandingKeys Count may it zero count
Try to reload data by performing it on main thread..
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableRating reloadData];
});
This will solve your problem. Happy Coding..