My app have UITableViewController and DetailViewController.
UITableViewController with multi cell selection and Detail accessory button.
If the user select multiple cell and tap on TOTAL Button Alert message show the total of courses price.
And if user tap on Detail accessory button it Segue to DetailViewController.
OK now my problem is how could I do that with my code:
UITableViewController.m
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[object valueForKey:#"courseCode"] description];
cell.detailTextLabel.text = [[object valueForKey:#"courseName"] description];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[[segue destinationViewController] setDetailItem:object];
}
}
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([[[object valueForKey:#"creditHours"] description]isEqualToString: #""]) {
}
//some thing doing if the user deselect the cell..
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([[[object valueForKey:#"creditHours"] description]isEqualToString: #""]) {
}
//some thing doing if the user deselect the cell..
}
- (IBAction)doneButton:(id)sender {
given the total...
}
DetailViewController.h
#property (strong, nonatomic) id detailItem;
#property (weak, nonatomic) IBOutlet UITextField *courseCodeLabel;
#property (weak, nonatomic) IBOutlet UITextField *courseNameLabel;
#property (weak, nonatomic) IBOutlet UITextField *creditHoursLabel;
#property (weak, nonatomic) IBOutlet UITextField *preRequisitesLabel;
#property (weak, nonatomic) IBOutlet UITextField *coursePriceLabel;
#property (weak, nonatomic) IBOutlet UITextField *courseEPPLabel;
#property (weak, nonatomic) IBOutlet UITextView *courseDetailLabel;
DetailViewController.m
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController
#synthesize detailItem = _detailItem;
#synthesize courseCodeLabel = _courseCodeLabel;
#synthesize courseNameLabel = _courseNameLabel;
#synthesize creditHoursLabel = _creditHoursLabel;
#synthesize preRequisitesLabel = _preRequisitesLabel;
#synthesize coursePriceLabel = _coursePriceLabel;
#synthesize courseEPPLabel = _courseEPPLabel;
#synthesize courseDetailLabel = _courseDetailLabel;
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
[self configureView];
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.courseCodeLabel.text = [[self.detailItem valueForKey:#"courseCode"] description];
self.courseNameLabel.text = [[self.detailItem valueForKey:#"courseName"] description];
self.creditHoursLabel.text = [[self.detailItem valueForKey:#"creditHours"] description];
self.preRequisitesLabel.text = [[self.detailItem valueForKey:#"preRequisites"] description];
self.coursePriceLabel.text = [[self.detailItem valueForKey:#"coursePrice"] description];
self.courseEPPLabel.text = [[self.detailItem valueForKey:#"courseEPP"] description];
self.courseDetailLabel.text = [[self.detailItem valueForKey:#"courseDetails"] description];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureView];
}
Notice that the segue working good in the normal way.
I think currently your segue links a tableview cell (that prototype) with your detail controller. You can try instead link the tableview controller itself (i.e. the entire thing) with your detail controller. (just ctrl drag from the bottom of your tableview controller to do that)
Then you handle your -prepareForSegue method as usual, but you will need to call -performSegue to actually trigger the segue. Tapping on the cell will have no effect. So in your -tableView:tableViewaccessory.... method you can call performSegue to do your navigation, and handle your didSelectRow.. method as you wish.
Related
What I'm trying to do is have a list of counties in a table view. When you click a county, another table view will show a list of resources you can select. I am using storyboards and Objective-C.
Here is my storyboard.
I don't want to nest the options into one table view because I think there are too many choices to be efficiently nested.
Here is my .h file for the county list table view:
// SecondViewController.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
#end
My .m file for the county list table view:
// SecondViewController.m
#import "SecondViewController.h"
#import "DetailViewController.h"
#interface SecondViewController ()
#property (nonatomic, strong) NSArray *tableData;
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableData = #[#"Carter", #"Greene", #"Hancock", #"Hawkins", #"Johnson", #"Sullivan", #"Unicoi", #"Washington"];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[DetailViewController class]])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *name = self.tableData[indexPath.row];
[(CountyViewController *)segue.destinationViewController setName:name];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.tableData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.tableData[indexPath.row];
return cell;
}
#end
The County Resources .h file I want to display in table view format:
// CountyViewController.h
#import <UIKit/UIKit.h>
#interface CountyViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#end
The .m file:
// CountyViewController.m
#import "CountyViewController.h"
#import "CountyDetail.h"
#interface CountyViewController ()
#end
#implementation CountyViewController {
NSArray *counties;
}
#synthesize tableView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize table data
counties = [NSArray arrayWithObjects:#"Resource1", #"Resource2", #"Resource3", #"Resource4", #"Resource5", #"Resource6", #"Resource7", #"Resource8", #"Resource9", nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [counties count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [counties objectAtIndex:indexPath.row];
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showCountyInfo"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
CountyDetail *destViewController = segue.destinationViewController;
destViewController.countyName = [counties objectAtIndex:indexPath.row];
}
}
#end
Lastly, the detail of the resource clicked:
// CountyDetail.h
#import <UIKit/UIKit.h>
#interface CountyDetail : UIViewController
#property (nonatomic, strong) IBOutlet UILabel *countyLabel;
#property (nonatomic, strong) NSString *countyName;
#end
And the .m file:
// CountyDetail.m
#import "CountyDetail.h"
#interface CountyDetail ()
#end
#implementation CountyDetail
#synthesize countyLabel;
#synthesize countyName;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Set the Label text with the selected county
countyLabel.text = countyName;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
So my goal is to have the county selection go to another array of resources in another table view. I'm guessing I'm going to need a lot more arrays, but I just don't know the format or structure. I hope this is enough information, and if anyone can explain their answer, that would be extremely helpful. Thanks!
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
You can follow this delegate send the message to another tableView or others.
In my application, there's a Navigation View(Embed In), a Table View Controller, and a View Controller. And in the ViewController.h, there are...
#property (strong, nonatomic) IBOutlet UILabel *timeDisplay;
#property (strong, nonatomic) IBOutlet UILabel *minuteDisplay;
#property (strong, nonatomic) IBOutlet UILabel *timerDisplay;
#property (strong, nonatomic) IBOutlet UILabel *titleLabel;
and more outlets. The code below is TableViewController.m file. I have a action button(plusbtn), which needs to add a cell in the table view. So, I tried to make the 'plusbtn' do it, but it didn't work. What should I do? Please help me...
#import "TableViewController.h"
#import "TableViewCell.h"
#import "ViewController.h"
#interface TableViewController ()
#property (nonatomic) ViewController *viewController;
#property (strong, nonatomic) NSMutableArray *titleArray;
#property (strong, nonatomic) NSMutableArray *tsArray;
#property (strong, nonatomic) NSMutableArray *tmArray;
#property (strong, nonatomic) NSMutableArray *ttArray;
#property (strong, nonatomic) NSString *cellplustitle;
#property (strong, nonatomic) NSString *cellplustime;
#property (strong, nonatomic) NSString *cellplusmin;
#property (strong, nonatomic) NSString *cellplussec;
#end
#implementation TableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_cellplustitle = self.viewController.titleLabel.text;
_cellplustime = self.viewController.timeDisplay.text;
_cellplusmin = self.viewController.minuteDisplay.text;
_cellplussec = self.viewController.timerDisplay.text;
self.titleArray = [NSMutableArray new];
self.tsArray = [NSMutableArray new];
self.tmArray = [NSMutableArray new];
self.ttArray = [NSMutableArray new];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// 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.
}
#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.titleArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TableViewCell" forIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.celltitle.text = [self.titleArray objectAtIndex:indexPath.row];
cell.cellmd.text = [self.tmArray objectAtIndex:indexPath.row];
cell.cellsd.text = [self.tsArray objectAtIndex:indexPath.row];
cell.celltd.text = [self.ttArray objectAtIndex:indexPath.row];
// Configure the cell...
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// 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;
}
*/
/*
#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.
}
*/
- (IBAction)plusbtn:(id)sender {
[self.tableView beginUpdates];
[self.titleArray addObject:self.cellplustitle];
[self.tsArray addObject:self.cellplussec];
[self.tmArray addObject:self.cellplusmin];
[self.ttArray addObject:self.cellplustime];
NSIndexPath *indexPathOfNewItem = [NSIndexPath indexPathForRow:(self.titleArray.count - 1) inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPathOfNewItem] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
[self.tableView scrollToRowAtIndexPath:indexPathOfNewItem atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
#end
ReloadData should work. If its not working if you put if between beginUpdate and endupdate, then comment rest code and simply try to reload table view after adding item in array. Like...
- (IBAction)plusbtn:(id)sender {
[self.titleArray addObject:self.cellplustitle];
[self.tsArray addObject:self.cellplussec];
[self.tmArray addObject:self.cellplusmin];
[self.ttArray addObject:self.cellplustime];
[self.tableview reloadData];}
Hope this helps?
you have to reload the uitableview using
[self.tableView reloadData];
Hope it helps!
I am learning to use Search Bars a Search Display Controllers in iOS. I made a simple test project with two views, one view contains a UITableView and a UISearchBar, when you select an row from the table view, the new view shows a label with the name of the row. I'm getting a couple of problems, first when I start to add text in the search bar and the search display appears, the search bar is gone. The filtered results are shown, but when I select a row it does not take me to the next view, this only happens when the table is filtered. Here is the code:
ViewController.h
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchDisplayDelegate, UISearchBarDelegate>
#property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) NSArray *objects;
#property (nonatomic, strong) NSArray *filteredObjects;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_objects = [[NSMutableArray alloc] initWithObjects:#"One", #"Two", #"Three", #"Four", #"Five", #"Six", #"Seven", #"Eight", #"Nine", #"Ten", nil];
_tableView.delegate = self;
_tableView.dataSource = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [_filteredObjects count];
} else {
return [_objects count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [_filteredObjects objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [_objects objectAtIndex:indexPath.row];
}
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ToDetail"]) {
DetailViewController *detailViewController = [segue destinationViewController];
if (self.searchDisplayController.active) {
NSIndexPath *indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
detailViewController.detailString = [_filteredObjects objectAtIndex:indexPath.row];
} else {
NSIndexPath *indexPath = [_tableView indexPathForSelectedRow];
detailViewController.detailString = [_objects objectAtIndex:indexPath.row];
}
}
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchText];
_filteredObjects = [_objects filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
Thanks for the help!
when I select a row it does not take me to the next view, this only happens when the table is filtered
Because you have no implementation of tableView:didSelectRowAtIndexPath:.
Remember, there is really no such thing as a "filtered table view". There are two table views: the normal one, and the one that appears because of the search display controller. That is a different table view (basically appearing in front of yours), and you must configure it for whatever you want it to do and however you want it to look.
I have two view controllers, HomeViewController (hereafter HVC) and AddActivityViewController (hereafter AAVC). In AAVC, I've declared a delegate protocol:
#protocol AddActivityViewControllerDelegate;
and defined it thusly:
#protocol AddActivityViewControllerDelegate
-(void) addActivityViewControllerDidSave;
-(void) addActivityViewControllerDidCancel:(ListActivity *) activityToDelete;
#end
Next, I implemented the two methods in HVC (the delegate) like this:
-(void) addActivityViewControllerDidSave
{
[self.moc MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
-(void) addActivityViewControllerDidCancel:(ListActivity *) activityToDelete
{
[activityToDelete MR_deleteEntity];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
I get this error "Use of undeclared identifier 'addActivityViewControllerDidSave' even though it's clearly declared in the protocol.
I should mention that before this, I was dealing with what was apparently an "import loop," which caused an "undeclared protocol" error. That error seems to have been fixed.
Here are the #import statements from the HomeViewController.h file:
#import <UIKit/UIKit.h>
#import "ListActivity.h"
#import "AddActivityViewController.h"
#import "TimedActivity.h"
#interface HomeViewController : UIViewController <AddActivityViewControllerDelegate>
#property (strong, nonatomic) IBOutlet UITableView *myTableView;
#property NSManagedObjectContext * moc;
- (IBAction)dumpMemory:(UIButton *)sender;
#end
And from the AddActivityViewController.h file:
#import <UIKit/UIKit.h>
#import "ListActivity.h"
#protocol AddActivityViewControllerDelegate;
#interface AddActivityViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *activityField;
#property (weak, nonatomic) IBOutlet UITextField *categoryField;
#property (strong, nonatomic) ListActivity *thisActivity;
#property (nonatomic, weak) id <AddActivityViewControllerDelegate> delegate;
- (IBAction)saveButton:(UIBarButtonItem *)sender;
- (IBAction)cancelButton:(UIBarButtonItem *)sender;
#end
#protocol AddActivityViewControllerDelegate
-(void) addActivityViewControllerDidSave;
-(void) addActivityViewControllerDidCancel:(ListActivity *) activityToDelete;
#end
I can post the full content of all four class files if that is helpful.
Many thanks for helping!
Edit: Here's the full code from HomeViewController.m:
//
// HomeViewController.m
// MRExample
//
// Created by Tim Jones on 1/15/14.
// Copyright (c) 2014 TDJ. All rights reserved.
//
#import "HomeViewController.h"
#import "ListActivity.h"
#interface HomeViewController ()
{
NSFetchedResultsController *frc;
}
#end
#implementation HomeViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.automaticallyAdjustsScrollViewInsets = NO;
[self refreshData];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationNewActivityAdded:) name:#"newActivityAdded" object:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) notificationNewActivityAdded:(NSNotification*)notification
{
[self refreshData];
}
#pragma mark Table View data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[frc sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id<NSFetchedResultsSectionInfo> sectionInfo = [[frc sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
// Customize the appearance of table view cells.
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
// Configure the cell to show the activity's name
ListActivity *thisActivity = [frc objectAtIndexPath:indexPath];
cell.textLabel.text = thisActivity.activityName;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
cell.textLabel.textColor = [UIColor redColor];
NSAttributedString *attString;
attString = cell.textLabel.attributedText;
return cell;
}
// Section Label
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *sectionLabel = [[[frc sections] objectAtIndex:section]name];
return [sectionLabel uppercaseString];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
ListActivity *thisActivity = [frc objectAtIndexPath:indexPath];
TimedActivity *currentActivity = [TimedActivity MR_createInContext:localContext];
currentActivity.timedActivityName = thisActivity.activityName;
currentActivity.category = thisActivity.activityCategory;
currentActivity.timedActivityTapped = [NSDate date];
[localContext MR_saveToPersistentStoreAndWait];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
ListActivity *activityToTrash = [frc objectAtIndexPath:indexPath];
// Delete the row from the data source
[activityToTrash MR_deleteEntity];
[localContext MR_saveToPersistentStoreAndWait];
[self refreshData];
}
}
-(void) refreshData
{
//This was the turning point for proper MR grouping. The two Properties (activityCategory and activityName) are used as Sort descriptors in the underlying core data methods
frc = [ListActivity MR_fetchAllSortedBy:#"activityCategory,activityName" ascending:YES withPredicate:nil groupBy:#"activityCategory" delegate:nil];
[self.myTableView reloadData];
}
- (IBAction)dumpMemory:(UIButton *)sender
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[ListActivity MR_truncateAllInContext:localContext];
[localContext MR_saveToPersistentStoreAndWait];
[self refreshData];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSManagedObjectContext *localContext = [[NSManagedObjectContext alloc] init];
if ([[segue identifier] isEqualToString:#"addActivity"])
{
AddActivityViewController *aavc = (AddActivityViewController *) [segue destinationViewController];
aavc.delegate = self;
ListActivity *newActivity = [ListActivity MR_createInContext:localContext];
aavc.thisActivity = newActivity;
}
-(void) addActivityViewControllerDidSave
{
[self.moc MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
-(void) addActivityViewControllerDidCancel:(ListActivity *) activityToDelete
{
[activityToDelete MR_deleteEntity];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
}
#end
Okay, just as I thought. The problem is that you're missing a bracket "}" at the end of the - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender method. Also you have an extra bracket at the end of the class (right above the #end keyword). That's probably the missing bracket. Fix that and your problem will go away.
Hope this helps!
I don't know if it's the problem, but move the declaration of your delegate (with the #class directive) to the top of AddActivityViewController, like this:
#import <UIKit/UIKit.h>
#import "ListActivity.h"
#class AddActivityViewController;
#protocol AddActivityViewControllerDelegate
- (void)addActivityViewControllerDidSave;
- (void)addActivityViewControllerDidCancel:(ListActivity *) activityToDelete;
#end
#interface AddActivityViewController : UIViewController
#property (nonatomic, weak) id <AddActivityViewControllerDelegate> delegate;
#property (nonatomic, weak) IBOutlet UITextField *activityField;
#property (nonatomic, weak) IBOutlet UITextField *categoryField;
#property (nonatomic, strong) ListActivity *thisActivity;
- (IBAction)saveButton:(UIBarButtonItem *)sender;
- (IBAction)cancelButton:(UIBarButtonItem *)sender;
#end
Whenever I search for something from a search bar, I get the correct results. When I click on those results, it links me to the same place that the original results would have linked me to. In other words, I have teacher a-e, I type in 'e', and get only the result 'e', but when I click on that cell, it links me to the teacher 'a' profile.
Here is what I have so far.
#import <UIKit/UIKit.h>
#interface ListTableViewController : UITableViewController
#end
---
#import "ListTableViewController.h"
#import "DetailsViewController.h"
#interface ListTableViewController () <UISearchDisplayDelegate>
#property (strong, nonatomic) NSArray *className;
#property (strong, nonatomic) NSArray *teacherName;
#property (strong, nonatomic) NSArray *blockNumber;
#property (strong, nonatomic) NSArray *myNew;
#property (strong, nonatomic) NSArray *searchResults;
#end
#implementation ListTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.className = [NSArray arrayWithObjects:#"Biology",#"English III",#"Chemistry",#"Algebra II",#"Morality", nil];
self.teacherName = [NSArray arrayWithObjects:#"Teacher A",#"Teacher B",#"Teacher C",#"Teacher D",#"Teacher E", nil];
self.blockNumber = [NSArray arrayWithObjects:#"B1",#"B3",#"B6",#"B2",#"B1", nil];
NSMutableArray *combinedArray = [[NSMutableArray alloc]init];
for (int i = 0; i < [self.className count]; i++)
{
NSString *combinedString = [NSString stringWithFormat:#"%# | %# | %#",[self.className objectAtIndex:i],[self.teacherName objectAtIndex:i],[self. blockNumber objectAtIndex:i]];
[combinedArray addObject:combinedString];
}
self.myNew = combinedArray;
}
- (void)filterContentForSearchText: (NSString *) searchText
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF CONTAINS[cd] %#", searchText];
self.searchResults = [self.myNew filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString];
return YES;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.tableView) {
return [self.myNew count];
} else { // (tableView == self.searchDisplayController.searchResultsTableView)
return [self.searchResults count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (tableView == self.tableView) {
cell.textLabel.text = [self.myNew objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
}
return cell;
}
#pragma mark - Table view delegate
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showDetails"]) {
DetailsViewController *dvc = segue.destinationViewController;
NSIndexPath *indexPath = nil;
if ([self.searchDisplayController isActive]) {
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
dvc.sendLabel = [self.searchResults objectAtIndex:indexPath.row];
dvc.teachersendLabel = [self.teacherName objectAtIndex:indexPath.row];
return;
} else{
indexPath = [self.tableView indexPathForSelectedRow];
dvc.sendLabel = [self.myNew objectAtIndex:indexPath.row];
dvc.teachersendLabel = [self.teacherName objectAtIndex:indexPath.row];
return;
}
}
}
#end
In my DetailsViewController
#import <UIKit/UIKit.h>
#interface DetailsViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (strong, nonatomic) NSString *sendLabel;
#property (weak, nonatomic) IBOutlet UILabel *teacherlabel;
#property (strong, nonatomic) NSString *teachersendLabel;
#end
---
#implementation DetailsViewController
#synthesize label;
- (void)viewDidLoad
{
[super viewDidLoad];
self.teacherlabel.text = [NSString stringWithFormat:#"%#", self.teachersendLabel];
self.label.text = [NSString stringWithFormat:#"%#", self.sendLabel];
}
#end
Looking at your code it wouldn't seem there to be any problem. The are only two things I can think of:
1) I'm not sure how you're displaying the 'main' tableView and the search results one. Might it be that your touches are actually getting handled by the 'main' tableView? This might happen if you have the two tables aligned on top of each other and the bottom one is still visible and with userInteractionEnabled set to YES when the search one 'isActive'. In this case the view hierarchy should look similar to this:
- UIView
- UITableView (main)
- UITableView (search)
2) the use of -[UITableView indexPathForSelectedRow] in prepareForSegue:sender:. If you're using Storyboard the sender is the selected cell. You may want to check that the sender is an actual cell or an indexPath isKindOfClass. If the sender is an indexPath you can use it, if it's a cell you can call the method -[UITableView indexPathForCell:]. Using this approach you make sure your segue is actually triggering for the right event (e.g. you can programmatically select a cell, but this won't fire a segue and you can later decide to call -performSegueWithIdentifier:sender: and this would break your implementation).