I would like to create a tableview where I can move people from different departments into other departments, and I have some code posted below.
I have an issue with this, I can never seem to get it to get the usual ui gadget to move rows. I don't want the user to edit/delete the rows; simply move them about however the "move" buttons never seem to appear.
Is there something I am doing wrong?
Also I am not sure if I am doing the move code right.
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Departments";
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.tableView.allowsSelectionDuringEditing = YES;
_objects = [NSMutableArray array];
NSDictionary *sales = #{ #"name" : #"sales",
#"employees" : #[ #"Mike", #"Tom", #"Alex"] };
NSDictionary *marketing = #{ #"name" : #"marketing",
#"employees" : #[ #"Heather", #"Richard", #"Simon"] };
[_objects addObject:sales];
[_objects addObject:marketing];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
}
#pragma mark - IBActions
-(IBAction) editButton:(id)sender
{
[self setEditing:!self.editing animated:YES];
}
#pragma mark - UITableView delegate
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return [_objects count];
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *department = [_objects objectAtIndex:section];
NSArray *employees = department[#"employees"];
return [employees count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellId" forIndexPath:indexPath];
// Configure the cell...
NSDictionary *department = [_objects objectAtIndex:indexPath.section];
NSArray *employees = department[#"employees"];
NSString *employeeName = [employees objectAtIndex:indexPath.row];
cell.textLabel.text = employeeName;
return cell;
}
-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSDictionary *department = [_objects objectAtIndex:section];
return department[#"name"];
}
- (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
if( fromIndexPath == toIndexPath ) return;
NSDictionary *department = [_objects objectAtIndex:fromIndexPath.section];
NSArray *employees = department[#"employees"];
NSString *employeeName = [employees objectAtIndex:fromIndexPath.row];
[self.tableView beginUpdates];
[_objects removeObjectAtIndex:fromIndexPath.row];
[_objects insertObject:employeeName atIndex:toIndexPath.row];
[self.tableView endUpdates];
[tableView reloadData];
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
if (indexPath.section == 1 && [_objects count] > 1)
{
return YES;
}
return NO;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if(editingStyle == UITableViewCellEditingStyleDelete){
[_objects removeObjectAtIndex:indexPath.row];
NSArray *rows = [NSArray arrayWithObject:indexPath];
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:rows withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
}
call this method after your array initialised. [self.tableView reloadData]
This will load the table data once again.
Related
When a row is deleted it always slides to left no matter what animation value I pass. I would like it to slide up similar to many of the stock apps.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
self.tableData = [][[self.tableData mutableCopy] removeObjectAtIndex:indexPath.row] copy];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
}
Here is the full tableview controller code, it is has a lot in it. That is the reason I didn't post it at first.
#interface FMListViewController ()
#property (strong) NSArray *currentLocations;
#property (assign) BOOL isEditing;
#end
#implementation FMListViewController
- (void)viewDidLoad {
[super viewDidLoad];
UISegmentedControl *viewType = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"List", #"Map", nil]];
CGRect viewTypeRect = viewType.frame;
viewTypeRect.size.width = 150.0f;
viewType.frame = viewTypeRect;
viewType.selectedSegmentIndex = 0;
[viewType addTarget:self action:#selector(viewTypeChange:) forControlEvents:UIControlEventValueChanged];
self.navigationItem.titleView = viewType;
self.currentLocations = [[FMLocations sharedManager] allLocations];
//watch for weather updates
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(weatherUpdated) name:#"weatherUpdated" object:nil];
//watch for changes to saved locations
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(locationsUpdated) name:#"locationsUpdated" object:nil];
self.isEditing = NO;
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// this UIViewController is about to re-appear, make sure we remove the current selection in our table view when swiping back occurs
NSIndexPath *tableSelection = [self.tableView indexPathForSelectedRow];
[self.tableView deselectRowAtIndexPath:tableSelection animated:NO];
[self.navigationController setToolbarHidden:YES animated:NO];
}
- (void)viewTypeChange:(UISegmentedControl *)segControl{
NSLog(#"change to map");
[(FMNavController *)[self navigationController] changeViewType];
segControl.selectedSegmentIndex = 0;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)weatherUpdated{
[self.tableView reloadData];
[self.refreshControl endRefreshing];
}
- (void)locationsUpdated{
if(self.isEditing){
self.currentLocations = [[FMLocations sharedManager] savedLocations];
}else{
self.currentLocations = [[FMLocations sharedManager] allLocations];
}
[self.tableView reloadData];
}
#pragma mark - Table Editing Stuff
- (IBAction)toggleEditing:(id)sender{
if(self.isEditing){
self.isEditing = NO;
self.currentLocations = [[FMLocations sharedManager] allLocations];
[self.tableView reloadData];
UIBarButtonItem *newRightItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(toggleEditing:)];
self.navigationItem.rightBarButtonItem = newRightItem;
[self.tableView setEditing:NO animated:YES];
}else{
self.isEditing = YES;
self.currentLocations = [[FMLocations sharedManager] savedLocations];
[self.tableView reloadData];
UIBarButtonItem *newRightItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(toggleEditing:)];
self.navigationItem.rightBarButtonItem = newRightItem;
[self.tableView setEditing:YES animated:YES];
}
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 0 && [[FMLocations sharedManager] currentLocation] && !self.isEditing){
return NO;
}
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//add code here for when you hit delete
NSMutableArray *newLocations;
int arrayOffset = 0;
if([[FMLocations sharedManager] currentLocation] && !self.isEditing){
arrayOffset = -1;
}
newLocations = [[[FMLocations sharedManager] savedLocations] mutableCopy];
int itemToRemove = (int)indexPath.row + arrayOffset;
if(itemToRemove < 0 || itemToRemove > [newLocations count]){
NSLog(#"invalid item to remove");
}else{
[newLocations removeObjectAtIndex:itemToRemove];
[[FMLocations sharedManager] saveSavedLocations:[newLocations copy]];
if(self.isEditing){
self.currentLocations = [[FMLocations sharedManager] savedLocations];
}else{
self.currentLocations = [[FMLocations sharedManager] allLocations];
}
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 0 && [[FMLocations sharedManager] currentLocation] && !self.isEditing){
return NO;
}
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
NSMutableArray *editableLocations = [[[FMLocations sharedManager] savedLocations] mutableCopy];
if(editableLocations && [editableLocations count] > sourceIndexPath.row && [editableLocations count] > destinationIndexPath.row){
NSInteger fromIndex = sourceIndexPath.row;
NSInteger toIndex = destinationIndexPath.row;
id object = [editableLocations objectAtIndex:fromIndex];
[editableLocations removeObjectAtIndex:fromIndex];
[editableLocations insertObject:object atIndex:toIndex];
[[FMLocations sharedManager] saveSavedLocations:[editableLocations copy]];
}
}
#pragma mark - Refresh control action
- (IBAction)doRefreshTable:(id)sender{
[[ForecastManager sharedManager] updateForecasts];
}
#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.
return [self.currentLocations count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//NSLog(#"getting cell");
FMTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"FMLocationCell" forIndexPath:indexPath];
NSDictionary *theLocation = [self.currentLocations objectAtIndex:indexPath.row];
// Configure the cell...
cell.locationLabel.text = [[theLocation objectForKey:#"name"] uppercaseString];
WeatherObject *locationWeather = [[ForecastManager sharedManager] weatherObjectForLocation:[[theLocation objectForKey:#"id"] intValue]];
[cell setCurrentTemp:locationWeather.currentTemp];
[cell configureForecastViews:locationWeather.forecastObjects];
[cell.weatherPreviewContainer setNeedsDisplay];
return cell;
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if([segue.identifier isEqualToString:#"showLocation"]){
FMDetailViewController *detailController = [segue destinationViewController];
NSDictionary *theLocation = [self.currentLocations objectAtIndex:self.tableView.indexPathForSelectedRow.row];
detailController.navigationItem.title = [theLocation objectForKey:#"name"];
detailController.detailLocation = theLocation;
}
}
You can try below solutions:
1) Replace your line with the below one
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationTop];
2) Change the code with the below one:
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
Hope this helps!
please try with that
don't delete cell directly first make its cellheight to zero using. NSIndexPath *deleteIndexPath;
wirte below code before delete
[tbl beginUpdates];
deleteIndexPath = indexPath;
[tbl reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tbl endUpdates];
and in set hight method use
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ if (indexPath == deleteIndexPath) {
return 0;
}
return 50;
}
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;
}
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've hardcoded all of the titles of my cells, and am looking to link each individual cell to a different blog post. The section titles are my keys, and the values are an array of the information pertaining to the title. How would I go about this? I'm a bit confused because due to the fact I have sections, the row selected number restarts as I begin the next section. There's some code involving a search bar so disregard that. An example would be so helpful!
#interface InfoTableViewController () {
NSDictionary *names;
NSArray *sectionTitles;
}
#end
#implementation InfoTableViewController {
NSArray *items;
NSArray *searchResults;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
names = #{#"Green Manual" : #[#"Basic Rules", #"Pledge Mom Interview", #"Pledge Class Song", #"Code of Conduct", #"History of XXX", #"Founding Sisters of XX", #"Inter-Chapter Council", #"General Facts", #"Crest of XXX", #"Sister of Mine", #"Greek Alphabet", #"Delta Chapter History",#"Actives", #"Associates, Recessives, Retired Actives, Inactives", #"Alumnae", #"Family Tree"],
#"Interviews" : #[#"Alyson Au", #"Jazzmin Boo", #"Shuki Chan", #"Ivy Cheng", #"Julie Ha", #"Jenny Hong", #"Linde Huang", #"Erica Jon", #"Jenny Lau", #"Jean Lin", #"Vivian Lo", #"Jackie Nguyen", #"Nhi Nguyen", #"Sarah Pham", #"Jasmine Ta", #"Diane Tran", #"Joyce Wong", #"Kathie Wong", #"Jennifer Xu"]};
sectionTitles = [[names allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [sectionTitles count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *sectionTitle = [sectionTitles objectAtIndex:section];
NSArray *sectionNames = [names objectForKey:sectionTitle];
return [sectionNames count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [sectionTitles objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath*)indexPath
{
//static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSString *sectionTitle = [sectionTitles objectAtIndex:indexPath.section];
NSArray *sectionNames = [names objectForKey:sectionTitle];
NSString *name = [sectionNames objectAtIndex:indexPath.row];
cell.textLabel.text = name;
NSLog(#"Row selected: %d", indexPath.row);
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name BEGINSWITH[cd] %#", searchText];
searchResults = [items filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
I assume you are trying to select a cell and detect that in order to move to a different controller, which then would display some of your content.
Even though you have
NSLog(#"Row selected: %d", indexPath.row);
in your method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath*)indexPath
That's not the method that actually detects a cell selection. You should use:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
which is a method from TableViewDelegate, and not TableViewDataSource. Your controller needs to implement both. You also need to connect your tableView to your delegate, in this case, your own controller.
Try NSLogging inside didSelectRowAtIndexPath method to track your selection and further push a new controller, or perform a Storyboard Segue.
I'm fairly new to Xcode and am having trouble getting my head around why the table view data isn't displaying in the searchbar. Basically trying to return fetched results to a searchbar. Thanks in advance!
#import "DeviceViewController.h"
#import "DeviceDetailViewController.h"
#interface DeviceViewController ()
#property (strong) NSMutableArray *devices;
#end
#implementation DeviceViewController
{
NSArray *recipes;
NSArray *searchResults;
}
#synthesize recipe;
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
//label.backgroundColor = [UIColor clearColor];
label.font = [UIFont fontWithName:#"HelveticaNeue-thin" size:28];
//label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textColor = [UIColor blackColor];
self.navigationItem.titleView = label;
label.text = #"TapNotes";
[label sizeToFit];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Device"];
self.devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return self.devices.count;
}
//return self.devices.count;
}
- (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]; }
NSManagedObject *device = [self.devices objectAtIndex:indexPath.row];
[cell.textLabel setText:[NSString stringWithFormat:#"%#", [device valueForKey:#"name"]]];
[cell.detailTextLabel setText:[NSString stringWithFormat:#"%#",[device valueForKey:#"version"]]];
if (tableView == self.searchDisplayController.searchResultsTableView) {
recipe = [searchResults objectAtIndex:indexPath.row];
} else {
[self.devices objectAtIndex:indexPath.row];
}
// cell.thumbnailImageView.image = [UIImage imageNamed:recipe.image];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete object from database
[context deleteObject:[self.devices objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Can't Delete! %# %#", error, [error localizedDescription]);
return;
}
// Remove device from table view
[self.devices removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"UpdateDevice"]) {
NSManagedObject *selectedDevice = [self.devices objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
DeviceDetailViewController *destViewController = segue.destinationViewController;
destViewController.device = selectedDevice;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 55;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#end
Things don't look right here.
Why are you not using a NSFetchedResultsConteroller?
What is the connection between recipes and devices arrays
You are not setting the recipes array (you filter it on filterContentForSearchText:)
Your cellForRowAtIndexPath: always set data for cell by the devices array
You have a lot of "dead" code
It looks like you took this code from an example and modified it, but only half way.