I am creating a today extension for my app, but there are some errors that I can't quite understand:
First:
Everything is Ok on the storyboard, but the button doesn't appear on the widget.
Second: When the tableview has more than one cell, the last cell gets cut.
Third: CellForRow is called, but don't change anything on the cell (Label is still "Label").
http://i.stack.imgur.com/Jp31V.png
Here's my Widget code:
#implementation TodayViewController{
NSMutableArray *listaFavoritos;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.widgetTableView.delegate = self;
self.widgetTableView.dataSource = self;
[self updateTableView];
self.preferredContentSize = self.widgetTableView.frame.size;
}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
completionHandler(NCUpdateResultNewData);
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(userDefaultsDidChange:)
name:NSUserDefaultsDidChangeNotification
object:nil];
}
return self;
}
- (void)userDefaultsDidChange:(NSNotification *)notification {
[self updateTableView];
}
- (void)updateTableView {
listaFavoritos = [[NSMutableArray alloc] init];
//listaFavoritos = [[self readArrayWithCustomObjFromUserDefaults:#"listaFavs"] mutableCopy];
[listaFavoritos addObject:#"test1"];
[listaFavoritos addObject:#"test2"];
NSLog(#"%#", listaFavoritos);
}
-(NSArray *)readArrayWithCustomObjFromUserDefaults:(NSString*)keyName
{
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.com.kazoowa.timers"];
NSData *data = [sharedDefaults objectForKey:keyName];
NSArray *myArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];
[sharedDefaults synchronize];
return myArray;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [listaFavoritos count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WidgetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"WidgetCell" forIndexPath:indexPath];
if (cell == nil)
{
cell.nomeTimer.text = [listaFavoritos objectAtIndex:indexPath.row];
}
NSLog(#"CellForRow");
return cell;
}
1)For your second problem, your cellIdentifier in tableView:cellForRowAtIndexPath will be "static" like this :
static NSString *cellName = #"WidgetCell";
WidgetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellName forIndexPath:indexPath];
2)this condition will be never execute because it's never nil :
if (cell == nil)
{
cell.nomeTimer.text = [listaFavoritos objectAtIndex:indexPath.row];
}
replace it by this :
if (cell != nil)
{
cell.nomeTimer.text = [listaFavoritos objectAtIndex:indexPath.row];
}
3)Please use Pragma Mark for separate properly your code like below:
#pragma mark-UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [listaFavoritos count];
}
#pragma mark-UITableViewDelegate
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WidgetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"WidgetCell" forIndexPath:indexPath];
if (cell == nil)
{
cell.nomeTimer.text = [listaFavoritos objectAtIndex:indexPath.row];
}
NSLog(#"CellForRow");
return cell;
}
Hope it helps :)
Try it :
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellName = #"WidgetCell";
WidgetTableViewCell *cell = (WidgetTableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellName];
if (cell == nil) {
cell = [[WidgetTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellName];
}
cell.textLabel.text = [listaFavoritos objectAtIndex:indexPath.row];;
return cell;
}
Related
I have one UITableView consisting of some custom UITableViewCells and one UISearchDisplayController connected to it. How can I show another custom Table View Cell if there are no results when you search for something?
Here's how the search and table view functions look like:
- (void)searchTableList:(UISearchBar*)searchBar {
NSString *searchString = searchBar.text;
for (NSArray *section in _celebs)
for (NSDictionary *row in section) {
if ([[row[#"name"] lowercaseString] rangeOfString:[searchString lowercaseString]].location!=NSNotFound)
[filteredContentList addObject:row];
}
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
isSearching = YES;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[filteredContentList removeAllObjects];
if (searchText.length) {
isSearching = YES;
[self searchTableList:searchBar];
} else isSearching = NO;
}
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller{
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
isSearching = NO;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self searchTableList:searchBar];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [tableView isEqual:self.searchDisplayController.searchResultsTableView]?1:_objects.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableView isEqual:self.searchDisplayController.searchResultsTableView]?filteredContentList.count:[_objects[section] count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return [tableView isEqual:self.searchDisplayController.searchResultsTableView]?0:25;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section {
return [self tableView:tableView heightForHeaderInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 55;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (NSDictionary *)getObjectFromIndexPath:(NSIndexPath*)indexPath tableView:(UITableView*)tableView {
BOOL search = [tableView isEqual:self.searchDisplayController.searchResultsTableView];
if (search)
return indexPath.row<filteredContentList.count?filteredContentList[indexPath.row]:nil;
else return indexPath.section<_objects.count?
(indexPath.row<[_objects[indexPath.section] count]?_objects[indexPath.section][indexPath.row]:nil)
:nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL search = [tableView isEqual:self.searchDisplayController.searchResultsTableView];
FirstTableViewCell *cell;
NoResultsTableViewCell *cell1;
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell = (FirstTableViewCell*)[self.tableView dequeueReusableCellWithIdentifier:#"FirstTableViewCell"];
} else {
cell = (FirstTableViewCell*)[self.tableView dequeueReusableCellWithIdentifier:#"FirstTableViewCell" forIndexPath:indexPath];
}
NSDictionary *object = [self getObjectFromIndexPath:indexPath tableView:tableView];
if (!object) return cell;
cell.object = celeb;
cell.objectName.text = [object objectForKey:#"name"];
}
}
return cell;
}
Make some changes like below:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]){
if (filteredContentList.count > 0){
return filteredContentList.count;
}else{
return 1; // the number of custom cells when there're no results
}
}else{
return [_objects[section] count];
}
}
- (NSDictionary *)getObjectFromIndexPath:(NSIndexPath*)indexPath tableView:(UITableView*)tableView {
BOOL search = [tableView isEqual:self.searchDisplayController.searchResultsTableView];
if (search)
return indexPath.row < filteredContentList.count? filteredContentList[indexPath.row]: theCustomCellDict; // use theCustomCellDict instead of nil
else return indexPath.section < _objects.count?
(indexPath.row < [_objects[indexPath.section] count]? _objects[indexPath.section][indexPath.row]: nil)
:nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL isSearch = [tableView isEqual:self.searchDisplayController.searchResultsTableView];
FirstTableViewCell *cell;
NoResultsTableViewCell *noReultsCell;
if ((isSearch && filteredContentList.count > 0) || !isSearch){
cell = (FirstTableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:#"FirstTableViewCell" forIndexPath:indexPath];
NSDictionary *object = [self getObjectFromIndexPath:indexPath tableView:tableView];
if (!object) return cell;
cell.object = celeb;
cell.objectName.text = [object objectForKey:#"name"];
return cell;
}else{
noResultsCell = (NoResultsTableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:#"NoResultsTableViewCell" forIndexPath:indexPath];
NSDictionary *object = [self getObjectFromIndexPath:indexPath tableView:tableView];
if (!object) return noResultsCell;
noResultsCell.object = celeb;
noResultsCell.objectName.text = [object objectForKey:#"name"];
return noResultsCell
}
}
If you want to just show information (for example there is no result found 'something' ) You don't need to use UITableViewCells. I will reccomend you to look DZNEmptyDataSet library.
GitHub link https://github.com/dzenbot/DZNEmptyDataSet
Here is my code which handles multiple selection of UITableview Cell properly.
Now, my question is here I had create two array in which one stores array data and second stores selected data. But, I want to do this using only one array. someone had given me solution that it can be done using KVC (valueForKeyPath) by giving key. But I have no exact idea how to do it.
If anyone knows please help me.
#import "NewTableViewController.h"
#implementation NewTableViewController
#synthesize attTableData ;
#synthesize arrSelectionData ;
- (void)viewDidLoad
{
[super viewDidLoad];
self.attTableData=[NSArray arrayWithObjects:#"Dhosa",#"Kahman",#"Dhokla",#"Handvo",#"chodafadi",#"Muthiya",#"Medu Vada",#"Patra",#"Thepla",#"Fafda",#"Gota",#"gathiya",#"Idali",#"Dalvada",#"Samosa",nil];
self.arrSelectionData=[NSMutableArray array];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.attTableData 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([self.arrSelectionData containsObject:indexPath])
{
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else
{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
cell.textLabel.text=[self.attTableData objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if([self.arrSelectionData containsObject:indexPath])
{
[self.arrSelectionData removeObject:indexPath];
}
else
{
[self.arrSelectionData addObject:indexPath];
}
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
//[tableView reloadData];
}
#end
Solution ::
Data in "Recipe List" File
[0]{
Item = Thepla;
selected = 0;
},
[1]
{
Item = Gota;
selected = 0;
},
[2]
{
Item = Handvo;
selected = 0;
},
[3]
{
Item = Idali;
selected = 0;
},
[4]
{
Item = Dalvada;
selected = 0;
},
Now My TableViewController
#import "NewTableViewController.h"
#import "TableViewCell.h"
#implementation NewTableViewController
#synthesize attTableData ;
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Recipe List" ofType:#"plist"];
attTableData = [[NSMutableArray alloc]initWithContentsOfFile:path];
attTableData = (NSMutableArray *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)attTableData, kCFPropertyListMutableContainers));
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.attTableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"UserCell";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
}
NSDictionary * dicTemp = [attTableData objectAtIndex:indexPath.row];
// NSNumber* attendingObject = [dicTemp objectForKey:#"selected"];
if([dicTemp objectForKey:#"selected"] == [NSNumber numberWithBool:NO])
{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
else
{
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
cell.lbl.text=[[self.attTableData objectAtIndex:indexPath.row]objectForKey:#"Item"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSMutableDictionary * dic = [attTableData objectAtIndex:indexPath.row];
//NSNumber* attendingObject = [dic objectForKey:#"selected"];
if ([dic objectForKey:#"selected"] == [NSNumber numberWithBool:NO])
{
[dic setValue:[NSNumber numberWithBool:YES] forKey:#"selected"];
}
else
{
[dic setValue:[NSNumber numberWithBool:NO] forKey:#"selected"];
}
[attTableData replaceObjectAtIndex:indexPath.row withObject:dic];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
#end
If you want to do it using a single array, instead of doing like this
self.attTableData=[NSArray arrayWithObjects:#"Dhosa",#"Kahman",#"Dhokla",#"Handvo",#"chodafadi",#"Muthiya",#"Medu Vada",#"Patra",#"Thepla",#"Fafda",#"Gota",#"gathiya",#"Idali",#"Dalvada",#"Samosa",nil];
Create a model class for your items
//pseudo code
class Item{
name = "Dhosa"
selected = false
}
So attTableData will be
self.attTableData=[Item1, Item2];
Now when you make a selection you can set the selected property of the item. In cellForRow check this property and set setAccessoryType.
I have 2 tables in one view controller and a search bar . The functionality of first view controller and the search bar was ok , untill i added the second table. Now when i want to search something , the research is in the table number one , and i don't want this .
Here is my code :
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.searchResult removeAllObjects];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchText];
self.searchResult = [NSMutableArray arrayWithArray: [self.tableData filteredArrayUsingPredicate:resultPredicate]];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView.tag==1) {
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResult count];
}
else
{return [self.tableData count];}
}
else return historique.count;
}
- (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section {
return [[content objectAtIndex:section] objectForKey:#"headerTitle"];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [content valueForKey:#"headerTitle"];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [indices indexOfObject:title];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView.tag==1) {
return [content count];
}else
return 1;
}
UITableViewCell *cell ;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
if (tableView.tag==0) {
cell = [tableView dequeueReusableCellWithIdentifier:#"cell2"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.searchResult objectAtIndex:indexPath.row];
}
else
cell.textLabel.text = [historique objectAtIndex:indexPath.row];
}
if (tableView.tag==1) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.searchResult objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = self.tableData[indexPath.row];
}}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DefinitionViewController *secondViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]]instantiateViewControllerWithIdentifier:#"definition"];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *str = cell.textLabel.text;
NSString *uu;
if ([[transaction valueForKey:str] isKindOfClass:[NSArray class]]) {
NSLog(#"yes");
NSArray *jsonArray = (NSArray *)[transaction valueForKey:str];
uu = [jsonArray componentsJoinedByString:#"\n"];
secondViewController.definitionsArray=jsonArray;
}
else{
uu=[transaction valueForKey:str];
}
NSMutableArray *values = [[NSMutableArray alloc] initWithArray:[[NSUserDefaults standardUserDefaults] arrayForKey:#"histroriqueValues"]];
[values addObject:uu];
[[NSUserDefaults standardUserDefaults] setObject:values forKey:#"histroriqueValues"];
historiqueValue = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"histroriqueValues"]mutableCopy];
[[NSUserDefaults standardUserDefaults] synchronize];
}
tableView.tag=0 is the table where i want to make the search. I put breakpoints , and when i click on search bar the table where the search is making is tableView.tag=1.
I have made a small example projects with a UITableViewController. If you need, i can push it to a github repo so you can grab it and build on it.
//
// ViewController.m
// filterExample
//
// Created by François Chabbey on 16.04.15.
// Copyright (c) 2015 François Chabbey. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
{
NSArray *content;
NSArray *filteredContent;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
content = #[#"CECI",#"CELA",#"CELUI-CI",#"ET CA",#"ETC"];
self.tableView.dataSource = self;
self.searchDisplayController.delegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchBar.delegate = self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchString];
filteredContent = [NSArray arrayWithArray:[content filteredArrayUsingPredicate:predicate]];
return YES;
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
return YES;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return content.count;
} else {
return filteredContent.count;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"test"];
if (tableView == self.tableView) {
cell.textLabel.text = content[indexPath.row];
} else {
cell.textLabel.text = filteredContent[indexPath.row];
}
return cell;
}
#end
I have new data that I wish to put in my tableView, can you please help me with this. Currently mt table is populated with greekLetters and imageNames. On button click I wish to put new data in the table: greekLetters2
#interface ViewController2 ()
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
self.greekLetters = #[#"BigBen",#"Colosseum",#"EiffelTower",#"GreatWallOfChina",#"StatueofLiberty",#"StBasils",#"Stonehenge",#"TajMahal",#"TowerOfPisa"];
self.imageNames = #[#"BigBen.jpg",#"Colosseum.jpg",#"EiffelTower.jpg",#"GreatWallOfChina.jpeg",#"StatueofLiberty.jpg",#"StBasils.jpg",#"Stonehenge.jpg",#"TajMahal.jpg",#"TowerOfPisa.jpg"];
self.greekLetters2 = #[#"BigBen2",#"Colosseum2",#"EiffelTower2",#"GreatWallOfChina2",#"StatueofLiberty2",#"StBasils2",#"Stonehenge2",#"TajMahal2",#"TowerOfPisa2"];
self.imageNames2 = #[#"BigBen2.jpg",#"Colosseum2.jpg",#"EiffelTower2.jpg",#"GreatWallOfChina2.jpeg",#"StatueofLiberty.jpg",#"StBasils2.jpg",#"Stonehenge2.jpg",#"TajMahal2.jpg",#"TowerOfPisa2.jpg"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.greekLetters count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *SimpleIdentifier = #"SimpleIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:SimpleIdentifier];
}
UIImage *image = [UIImage imageNamed:self.imageNames[indexPath.row]];
cell.imageView.image = image;
cell.textLabel.text = self.greekLetters[indexPath.row];
cell.textLabel.font = [UIFont boldSystemFontOfSize:30];
if (indexPath.row < 3)
{
cell.detailTextLabel.text = #"A";
}
else
{
cell.detailTextLabel.text = #"B";
}
return cell;
}
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0)
{
return nil;
}
else
{
return indexPath;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *rowValue = self.greekLetters[indexPath.row];
NSString *message = [[NSString alloc] initWithFormat:#"You selsected %#!",rowValue];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Row Selected" message:message delegate:nil cancelButtonTitle:#"Yes" otherButtonTitles:nil, nil];
[alert show];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
- (IBAction)SwitchTable:(id)sender
{
//repapulate
}
#end
The easiest way is to switch the two array when the button is pressed. greekLetters has to became greekLetters2 and viceversa. Then, simply reload the tableview data.
-(IBAction)SwitchTable:(id)sender {
NSArray *temp = [NSArray arrayFromArray:greekLetters];
greekLetters = [NSArray arrayFromArray:greekLetters2];
greekLetters2 = [NSArray arrayFromArray:temp];
[tableview reloadData];
}
Just have one nsmutablearray which will drive your tableview. If your greekLetters array would be nsmutablearray you would update it and then reload your tableview:
[self.greekLetters addObjectsFromArray:self.greekLetters2];
[self.tableView reloadData];
Fallow these two tutorials and they will guide you in achieving what you are looking for:
- https://www.youtube.com/watch?v=gT8ncroYdDw
- https://www.youtube.com/watch?v=NHzm-D9VsQA
So I've implemented a UIViewController with a tableview, and basically it loads as a set of "filters" for my uicollectionview.
Now, when I click on the checkmarks in my tableview, it "filters" my cells accordingly, but now when I reload the view again I want to display the most recent "checkmarks" I've used, or "filters."
I have seen this being implemented with NSUserDefaults, but I have not been able to successfully implement this.
If anyone could help me, that will be greatly appreciated.
CODE
FiltersViewController.m:
#import "FiltersViewController.h"
#interface FiltersViewController ()
#property (nonatomic, strong) NSMutableSet *selectedRowObjects;
//#property (nonatomic, strong) NSArray *filters;
#end
#implementation FiltersViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.selectedRowObjects = [NSMutableSet setWithCapacity:10];
}
- (IBAction)filtersSelected:(id)sender {
[self.delegate filtersSelected:self.selectedRowObjects];
}
- (IBAction)cancelFilterSelection:(id)sender {
[self.delegate filterSelectionCancelled];
}
- (NSString *)getKeyForIndex:(int)index
{
return [NSString stringWithFormat:#"KEY%d",index];
}
- (BOOL) getCheckedForIndex:(int)index
{
if([[[NSUserDefaults standardUserDefaults] valueForKey:[self getKeyForIndex:index]] boolValue]==YES)
{
return YES;
}
else
{
return NO;
}
}
- (void) checkedCellAtIndex:(int)index
{
BOOL boolChecked = [self getCheckedForIndex:index];
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:!boolChecked] forKey:[self getKeyForIndex:index]];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"filter" forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%u", indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *obj = cell.textLabel.text;
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedRowObjects removeObject:obj];
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedRowObjects addObject:obj];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
you need to check in cellForRowAtIndexPath also. Write this code in this
if([[NSUserDefaults standardUserDefaults] objectForKey:[self getKeyForIndex:indexPath.row]])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
And yes don't forget to call this method in didSelectRowAtIndexPath
[self checkedCellAtIndex:indexPath.row];
Enjoy.
You did almost everything right. You just need to put your logic for reading the NSUserDefault values (for the checked boxes) in the cellForRowAtIndexPath delegate method. That is the method that draws the UITableViewCells when they are displayed on screen. Something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"filter" forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%u", indexPath.row];
if ([self getCheckedForIndex:indexPath.row])
{
//code to set checkbox
}
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *simpleTableIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = ArrayOfObject[indexPath.row];
NSUserDefaults *ud =[NSUserDefaults standardUserDefaults];
if([[ud objectForKey:#"selectedObjectKey "]isEqualToString:ArrayOfObject[indexPath.row]])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
You have implemented perfectly. You just need to modify you cellForRowAtIndexPath Method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"filter" forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%u", indexPath.row];
BOOL checked = [self getCheckedForIndex:indexPath.row];
if(checked)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
Also Call [self checkedCellAtIndex:indexPath.row]; from didSelectRowAtIndexPath method of UITableView.
The best way to save tableView CheckMark with NSUserDefaults
#interface TableViewController (){
NSArray *TableTitles;
NSMutableArray *SelectedRows;
}
viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
// table view array
TableTitles = [NSArray arrayWithObjects:#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10", nil];
NSUserDefaults *userDef = [NSUserDefaults standardUserDefaults];
SelectedRows = [NSMutableArray arrayWithArray:[userDef objectForKey:#"SelectedRows"]];
}
cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = TableTitles[indexPath.row];
NSNumber *obj = [NSNumber numberWithInteger:indexPath.row];
if ([SelectedRows containsObject:obj])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
didSelectRowAtIndexPath
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSNumber *obj = [NSNumber numberWithInteger:indexPath.row];
if ([SelectedRows containsObject:obj])
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
[SelectedRows removeObject:obj];
[tableView reloadData];
}else{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
[SelectedRows addObject:obj];
[tableView reloadData];
}
NSUserDefaults *userDef = [NSUserDefaults standardUserDefaults];
[userDef setObject:SelectedRows forKey:#"SelectedRows"];
[userDef synchronize];
}
updated ...
i updated all code with a new way , it's the best way to save TableView CheckMarks and it's now easy and efficient, now only one array is used for saving and loading , code reduced too much :)
You should load data in NSUserDefaults while call cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"filter" forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%u", indexPath.row];
//You should set accessoryType here by NSUserDefaults data
if ([self getCheckedForIndex:indexPath.row]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
I think what you are looking for is to get the current state of the table for the filters when you enter and exit the view. You need to utilize the - (void)viewWillDisappear:(BOOL)animated to save the current state of the table to your NSUserDefaults, and then use - (void)viewDidLoad and - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to set the checkmark when the table reloads.
#interface FiltersViewController () {
NSMutableArray *_filterStates;
}
#end
- (void)viewDidLoad {
filterStates = [[NSMutableArray alloc] init];
// get state of your current filters in NSUserDefaults, these should be stored as [NSNumber numberWithBool:]
}
- (void)viewWillDisappear:(BOOL)animated {
// store all of your filters into your NSUserDefaults as [NSNumber numberWithBool:]
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// get your cell from the table
BOOL isChecked = [[_filterStates objectAtIndex:indexPath.row] boolValue];
// set the checkmark based on the current state for this filter
}