UITableView with data from NSMutableArray returns empty - ios

I want to fill the content of a TableView according to selections made in a PickerView view. The code I have so far is:
- (IBAction)findOwnerButtonPressed:(id)sender
{
findShip.hidden = NO;
shipOwners.hidden = NO;
boatsTableView.hidden = YES;
boatOwners = [NSArray arrayWithObjects:#"Owner1",#"Owner2",#"Owner3", nil];
}
- (IBAction)findShipButtonPressed:(id)sender
{
shipOwners.hidden = YES;
findShip.hidden = YES;
boatsTableView.hidden = NO;
}
PickerView Data Source
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [boatOwners count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
return [boatOwners objectAtIndex:row];
}
PickerView Delegate
- (void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
NSString *boatsFromOwner = [boatOwners objectAtIndex:[shipOwners selectedRowInComponent:0]];
boatsForOwner = [NSMutableArray arrayWithObjects:nil];
if ([boatsFromOwner isEqualToString:#"Owner1"]) {
[self.boatsForOwner addObject:#"Titanic"];
}
NSLog(#"%#",boatsFromOwner);
}
TableView DataSource & Delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [boatsForOwner count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [boatsForOwner objectAtIndex:indexPath.row];
return cell;
}
This is supposed to return the boat owner company from a PickerWheel, and give me their boats in the table. This code returns nothing in the table. The PickerWheel logs 'Owner1' when I select it.
Is my error in how I add objects to the array or how I initialize the table or how I compare PickerWheel result to a word?

After you do
[self.boatsForOwner addObject:#"Titanic"];
You will manually need to refresh you tableview.. so after that do
[_yourTableView reloadData];
I would also initialize your arrays like this:
boatsForOwner = [NSMutableArray new];

I think first alloc & init the array "boatsForOwner "
replace your picker didSelectRow method with
-(void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
NSString *boatsFromOwner = [boatOwners objectAtIndex:[shipOwners selectedRowInComponent:0]];
if(boatsForOwner) {
[boatsForOwner release];
boatsForOwner = nil;
}
boatsForOwner = [NSMutableArray alloc] init];
if ([boatsFromOwner isEqualToString:#"Owner1"]) {
[self.boatsForOwner addObject:#"Titanic"];
}
NSLog(#"%#",boatsFromOwner);
[tableObject reloadData];
}
and release boatsForOwner when you dealloc.

Related

Filter Tableview

How to filter tableview based on a picker value?
I have the following NSMutableArray:
[0]:Object 1 (name1, October)
[1]:Object 2 (name2, November)
[2]:Object 3 (name3, March)
[3]:Object 4 (name4, April)
[4]:Object 5 (name5, April)
The table view displays the value of these objects.
and I have a picker with month values (January, February,... etc)
so based on the user selection of picker value, the table view should display values for example if I choose month April, only these values object 3 and 4 should appear.
Solution code, thanks to Fennelouski: (just thought I'd put it here In case someone needs it)
NSMutableArray *array;
NSMutableArray *filteredArray;
int monthInt;
NSString *monthString;
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Titles *object1 = [[Titles alloc]init];
[object1 setTitle:#"Title1"];
[object1 setMonth:#"10"];
Titles *object2 = [[Titles alloc]init];
object2.title = #"Title2";
object2.month = #"10";
Titles *object3 = [[Titles alloc]init];
object3.title = #"Title3";
object3.month = #"4";
array = [[NSMutableArray alloc]init];
filteredArray = [[NSMutableArray alloc]init];
[array addObject:object1];
[array addObject:object2];
[array addObject:object3];
pickerData = #[#"Jan", #"Feb", #"March", #"April", #"May", #"June", #"July", #"Aug", #"Sept", #"October", #"Nov", #"Dec"];
NSDate *currentDate = [NSDate date];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:currentDate];
monthInt= [components month];
monthString = [NSString stringWithFormat:#"%li",(long)monthInt];
for (Titles *item in array)
{
if([item.month isEqualToString:monthString])
{
[filteredArray addObject:item];
}
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [filteredArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
Titles *titles = filteredArray[indexPath.row];
cell.textLabel.text = titles.title;
cell.imageView.image = [UIImage imageNamed:#"totoro.jpg"];
NSLog(#"Cell is %#", [array objectAtIndex:indexPath.row]);
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (int)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
// The number of rows of data
- (int)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return pickerData.count;
}
// The data to return for the row and component (column) that's being passed in
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return pickerData[row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(#"Row: %li", (long)row);
monthString = [NSString stringWithFormat:#"%li",row+1];
[filteredArray removeAllObjects];
for (Titles *item in array)
{
if([item.month isEqualToString:monthString])
{
[filteredArray addObject:item];
}
}
[self.tableview reloadData];
}
It seems like you're following the design pattern of having your table view represent information stored in a separate data structure. That's good and makes filtering much easier.
Fortunately, you don't have to really do much with the table view to filter the results. All you need to do is filter the data structure that your table view is reading from and then update the table view.
I'd recommend adding an array in between your mutable array and the table view.
Something like this should work well for you
NSMutableArray *filteredObjects = [NSMutableArray new];
for (MYObjectClass *object in myMutableArray) {
if ([object.stringProperty isEqualToString:#"Filter"]) {
[filteredObjects addObject:object];
}
}
Then have your table view reference filteredObjects rather than the array you're using that has all of your data.

Return first character of string in NSArray for UIPickerView didSelectRow

I have a UIPickerView which returns an NSArray with 4 strings. When the user scrolls the UIPickerView, a UITextField gets updated with the selected row. I would like to return the first character of each string in the NSArray and update the UITextField with that character.
As you can see from my code, I have tried to achieve this functionality by using self.noiseLevelArray = [noiseArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];, which I found on a few different stack overflow questions.
Here is the code for the picker:
// Noise picker
self.noisePicker = [[UIPickerView alloc]init];
[noisePicker setDataSource:self];
[noisePicker setDelegate:self];
self.noiseArray = [[NSArray alloc]initWithObjects:#"4: Extreme Noise (Impossible)", #"3: Very Noisy (Loud Shouting)", #"2: Noisy (Shouting)", #"1: Not Noisy (Normally)", nil];
//self.noiseLevelArray = [noiseArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
// Call noisePicker method
[self noisePickerTextField];
Here is the code for my picker:
// Picker components
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [noiseArray count];
//return [noiseLevelArray count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [noiseArray objectAtIndex:row];
//return [noiseLevelArray objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *noiseString = [[NSString alloc]initWithFormat:#"%#", [noiseArray objectAtIndex:row]];
//NSString *noiseString = [noiseLevelArray objectAtIndex:0];
if ([self.empNoise1 isFirstResponder]) {
self.empNoise1.text = noiseString;
}
else if ([self.empNoise2 isFirstResponder]) {
self.empNoise2.text = noiseString;
}
...
As you can see, the UITextField gets updated with the full string of whichever row is selected in the UIPickerView. I would like it to still display the full string, but update the UITextField with the first character only (in this case 1, 2, 3, or 4). Any help is much appreciated!
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *noiseString = [[NSString alloc]initWithFormat:#"%#", [[noiseArray objectAtIndex:row] substringToIndex:1]];
//NSString *noiseString = [noiseLevelArray objectAtIndex:0];
if ([self.empNoise1 isFirstResponder]) {
self.empNoise1.text = noiseString;
}
else if ([self.empNoise2 isFirstResponder]) {
self.empNoise2.text = noiseString;
}
}
Try this. It uses the following method:
NSString * firstLetter = [word substringToIndex:1];
Try this.. `
self.empNoise1.text = [noiseString substringToIndex:1];`
Returns a new string containing the characters of the receiver up to, but not including, the one at a given index.
Link

Insert element at NSMutableArray's end

I am loading an array from a web service and displaying them in picker and all works fine. My array contains random number of questions for every category of questions. Now what i want is that i wanna add one more entry "Your own question" at the end of array so that the last row of picker displays "Your own question". How can i do this
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *retval = (id)view;
if (!retval) {
retval= [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [pickerView rowSizeForComponent:component].width, [pickerView rowSizeForComponent:component].height)];
}
// retval.text = [idAndNameArray objectAtIndex:row];
if([pickerType isEqualToString:#"picker"])
{
retval.text = [idAndNameArray objectAtIndex:row];
}
else
{
retval.text = [quesArray objectAtIndex:row];
}
retval.font = [UIFont boldSystemFontOfSize:14];
retval.numberOfLines = 3;
return retval;
}
This code only displays number of rows(questions) fetched from the web service.
EDIT 1:
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component
{
if([pickerType isEqualToString:#"picker"])
{
return [idAndNameArray count];
}
else
{
return [quesArray count];
}
}
EDIT 2:
Resolved by making another NSMutableArray with my custom object "Your own question" and then appending it with the array fetched from web service
NSMutableArray *customObj = [NSMutableArray arrayWithObject: #"test"];
[quesArray addObjectsFromArray:customObj];
In UIPickerViewDataSource's method called pickerView:numberOfRowsInComponent: return your array's count plus one value(return arr.count+1;), and in the method of UIPickerVIewDelegatethat you have implemented return your label with the text when the component is greater than arr.count-1 (if(row>(arr-1)){//return the label with 'Your own question'}). Good Luck!
EDIT:
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component
{
if([pickerType isEqualToString:#"picker"])
{
return [idAndNameArray count];
}
else
{
return [quesArray count]+1;
}
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *retval = (id)view;
if (!retval) {
retval= [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [pickerView rowSizeForComponent:component].width, [pickerView rowSizeForComponent:component].height)];
}
// retval.text = [idAndNameArray objectAtIndex:row];
if([pickerType isEqualToString:#"picker"])
{
retval.text = [idAndNameArray objectAtIndex:row];
}
else
{
if(row>quesArray.count-1){
retval.text = #"You own question";
}
else{
retval.text = [quesArray objectAtIndex:row];
}
}
retval.font = [UIFont boldSystemFontOfSize:14];
retval.numberOfLines = 3;
return retval;
}

UISearchBar misses elements in the non-visible part of the tableView

I have a TableView with many rows, most are not visible at the time of loading viewController. The rows of UITableView are extracted from a SQLite database. How can I make do that the SearchBar search between all rows and not just the visible ones?
In header file:
#interface ExhibitorsViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate>{
BOOL isSearchOn;
BOOL canSelectRow;
NSMutableArray * listOfExpositors;
NSMutableArray * searchResult;
}
//....
#end
In implementation file
-(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if(isSearchOn){
return [searchResult count];
//In this array there are the elements after use of searchBar
}else{
int number=[self.mutableArray count];
//In this array there are all elements of database, extracts in viewDidLoad()
return number;
}
}
- (UITableViewCell *)tableView:(UITableView *)aTableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] ;
}
if(isSearchOn){
NSString * cellValue = [searchResult objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
}else{
//loading data from the database
Database *currow =[self.mutableArray objectAtIndex:indexPath.row];
cell.textLabel.text = currow.name;
[listOfExpositors addObject:cell.textLabel.text];
//here only loads the list of names visible and not the entire table
//How do I put all the elements in this array?
NSLog(#" %#", listOfExpositors);
isSearchOn = NO;
canSelectRow = YES;
}
}
-(void) doneSearching{
isSearchOn = NO;
canSelectRow = YES;
self.tableView.scrollEnabled = YES;
[self.searchBar resignFirstResponder];
[self.tableView reloadData];
}
-(void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
isSearchOn = YES;
if(self.searchBar.text.length>0){
canSelectRow=YES;
self.tableView.scrollEnabled = YES;
}else{
canSelectRow= NO;
self.tableView.scrollEnabled = NO;
}
}
-(void) searchExpositorsTableView{
[searchResult removeAllObjects];
for (NSString *str in listOfExpositors){
NSRange titleResultsRange = [str rangeOfString:self.searchBar.text options:
NSCaseInsensitiveSearch];;
if (titleResultsRange.length >0) {
[searchResult addObject:str];
}
}
NSLog(#"%#", searchResult);
}
-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if([searchText length]>0){
canSelectRow = YES;
self.tableView.scrollEnabled = YES;
[self searchExpositorsTableView];
}else{
canSelectRow = NO;
self.tableView.scrollEnabled = NO;
}
[self.tableView reloadData];
}
-(void) searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[self searchExpositorsTableView];
[self.searchBar resignFirstResponder];
}
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if(canSelectRow){
return indexPath;
}else{
return nil;
}
NSLog(#"%d", indexPath.row);
}
It was wrong to use the array created in cellForRowAtIndexPath because it was limited only to the visible elements. I then used the NSMutableArray created in viewDidLoad () that does contain all the elements of the database. I changed the following methods:
- (UITableViewCell *)tableView:(UITableView *)aTableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//....
if(isSearchOn){
NSString * cellValue = [searchResult objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
}else{
Database *currow =[self.mutableArray objectAtIndex:indexPath.row];
cell.textLabel.text = currow.name;
//Should be removed this array and used to another, self.mutableArray
//[listOfExpositors addObject:cell.textLabel.text];
// NSLog(#" %#", listOfExpositors);
isSearchOn = NO;
canSelectRow = YES;
}
}
Method for research
-(void) searchExpositorsTableView{
[searchResult removeAllObjects];
for (Database *currow in self.mutableArray){
/*In self.mutableArray there are all elements because is created in
viewDidLoad*/
NSLog(#"list of expositors %#", self.mutableArray);
NSRange titleResultsRange = [currow.name rangeOfString:self.searchBar.text options: NSCaseInsensitiveSearch];
if (titleResultsRange.length >0) {
[searchResult addObject:currow.name];
}
}
NSLog(#"%#", searchResult);
}

UITableView cell not display correct detail

I created tableview and searchbar.
Name for cell 1 is iPhone.
When I click on the cell iPhone, on detail view it writes iPhone. When I search iPod it became the first cell in the search list but when I click this ,it writes iPhone instead of iPod. I try insert all code to here.
- (BOOL)shouldAutootateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table View Methods
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [displayItems count];
}
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.textLabel.text = [displayItems objectAtIndex:indexPath.row];
return cell;
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if ([searchText length] == 0) {
[displayItems removeAllObjects];
[displayItems addObjectsFromArray:allItems];
} else {
[displayItems removeAllObjects];
for (NSString * string in allItems ){
NSRange r =[string rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (r.location != NSNotFound){
[displayItems addObject:string];
}
}
[tableView reloadData];
}
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)asearchBar {
[searchBar resignFirstResponder];
}
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellAccessoryDisclosureIndicator;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *DVC = [[DetailViewController alloc] init];
//Pass the row to the DVC
DVC.characterNumber = [indexPath row];
//Push the DetailViewController object onto the stack
[self.navigationController pushViewController:DVC animated:YES];
}
#end
You are passing to detail controller row number for allItems array, but it is not same that in displayItems
DVC.characterNumber = [indexPath row];
There is you should assing correct row from allItems array, not displayItems array
Update:
NSString *item = [displayItems objectAtIndex:indexPath.row;
DVC.characterNumber = [allItems indexOfObject:item];

Resources