Custom delegate/protocol didnt work like it should - objective-c

I've been writing an app that has custom protocol to send the data from the child view to parent view the classes is
MainViewController
AddViewController (child to mainviewcontroller)
DaysViewController (child to addviewcontroller)
the custom protocol was declared in DaysViewController and implemented in AddViewController
AddViewController.h
#import <UIKit/UIKit.h>
#import "DaysViewController.h"
#import "Course.h"
#import "Student.h"
#interface AddViewController : UITableViewController<UIActionSheetDelegate,UIPickerViewDelegate,UIPickerViewDataSource,UIPickerViewAccessibilityDelegate,UITextFieldDelegate,DaysViewControllerDelegate>
{
NSArray *hoursarray;
UIActionSheet *aac;
IBOutlet UITextField *NameTx,*HoursTx,*DaysTx,*TimeTx;
Student *st;
Course *cc;
}
-(void) pickerDoneClick;
-(IBAction)fillTheOtherData;
#property (nonatomic ,strong) UIActionSheet *aac;
#end
AddViewController.m
#import "AddViewController.h"
#interface AddViewController ()
#end
#implementation AddViewController
#synthesize aac;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 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;
//viewP.frame = CGRectMake(0, 154, 320, 205);
hoursarray = [[NSArray alloc]initWithObjects:#"2",#"3",#"4", nil];
[self.tableView setScrollEnabled:NO];
[DaysTx setEnabled:NO];
[TimeTx setEnabled:NO];
[HoursTx setKeyboardType:UIKeyboardTypeDecimalPad];
cc = [[Course alloc]init];
//UITapGestureRecognizer *tapgr = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapped:)];
//[self.view addGestureRecognizer:tapgr];
}
-(void)tapped:(UITapGestureRecognizer *)tap
{
[self.view endEditing:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [hoursarray count];
}
//-(IBAction)addCourse
//{
// [UIView beginAnimations:#"view" context:nil];
// [UIView setAnimationDuration:1];
// viewP.frame = CGRectMake(0, 500, 320, 205);
// [UIView commitAnimations];
//
//}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [hoursarray objectAtIndex:row];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 3)
{
aac = [[UIActionSheet alloc]initWithTitle:#"How many ?" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil, nil];
UIPickerView *picker = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 44, 0, 0)];
picker.delegate = self;
picker.dataSource = self;
UIToolbar *pickerToolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
[pickerToolBar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc]init];
UIBarButtonItem *flexspace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexspace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDoneClick)];
[barItems addObject:doneBtn];
[pickerToolBar setItems:barItems animated:YES];
[aac addSubview:pickerToolBar];
[aac addSubview:picker];
[aac showInView:self.view];
[aac setBounds:CGRectMake(0, 0, 320, 464)];
}
else if (indexPath.row == 2)
{
DaysViewController *days = [self.storyboard instantiateViewControllerWithIdentifier:#"Days"];
days.delegate = self;
[self.navigationController pushViewController:days animated:YES];
}
}
-(void) pickerDoneClick
{
[aac dismissWithClickedButtonIndex:0 animated:YES];
}
-(void)chooseDays:(DaysViewController *)controller withArray:(NSArray *)theDaysArray
{
NSLog(#"I'm # chooseDays method");
NSLog(#"Before the add !!");
NSLog(#"chooseDays Method and the array is %#",theDaysArray);
cc.days = [NSMutableArray arrayWithObject:theDaysArray];
NSLog(#"After the add");
NSLog(#"chooseDays Method and the array is %#",cc.days);
// [self dismissViewControllerAnimated:YES completion:nil];
}
-(void)cancelChooseDays:(DaysViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(IBAction)fillTheOtherData
{
cc.name = NameTx.text;
cc.hour = [HoursTx.text integerValue];
NSLog(#"The name is %# and the hour credit is %d",cc.name,cc.hour);
}
#end
DaysViewController.h
#import <UIKit/UIKit.h>
#import "Course.h"
#class DaysViewController;
#protocol DaysViewControllerDelegate <NSObject>
#required
-(void)chooseDays:(DaysViewController *)controller withArray:(NSArray *)theDaysArray;
-(void)cancelChooseDays:(DaysViewController *)controller;
#end
#interface DaysViewController : UITableViewController
{
Course *courseDays;
NSArray *days;
NSMutableArray *dayChosen;
}
#property (nonatomic,weak) id<DaysViewControllerDelegate> delegate;
-(IBAction)done:(id)sender;
-(IBAction)cancel:(id)sender;
#end
DaysViewController.m
#import "DaysViewController.h"
#interface DaysViewController ()
#end
#implementation DaysViewController
#synthesize delegate;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 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;
days = [[NSArray alloc]initWithObjects:#"Saturday",#"Sunday",#"Monday",#"Teusday",#"Wednesday",#"Thursday",#"Friday", nil];
dayChosen = [[NSMutableArray alloc]init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return [days count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DaysCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"DaysCell"];
}
cell.textLabel.text = [days objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)done:(id)sender
{
//Course *course = [[Course alloc]init];
//[course.days addObject:dayChosen];
//NSArray *daysArray = [NSArray arrayWithObject:dayChosen];
NSLog(#"The Days are %#",dayChosen);
[self.delegate chooseDays:self withArray:dayChosen];
[self dismissViewControllerAnimated:YES completion:nil];
}
-(IBAction)cancel:(id)sender
{
[self.delegate cancelChooseDays:self];
}
/*
// 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 - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[dayChosen addObject:[days objectAtIndex:indexPath.row]];
NSLog(#"Days are %#",dayChosen);
}
#end
MainViewController has a button that take me to AddViewController and AddViewController has same button that takes me to DaysViewController , all the views has a UITableView .
what I want to do is when I send the data from DaysViewController to AddViewController to put it in an array and dismiss the view AddViewController should show up but instead MainViewController shows and this is what I dont want it to be.
AddViewController and DaysViewController have a UINavigationController but MainViewController doesn't.
Thank you in advance.

Okay, I think I know what your problem is. In your cancel function, try and switch this line of code:
[self dismissViewControllerAnimated:YES completion:nil];
With this line of code:
[self.navigationController popViewControllerAnimated:YES];
Let me know if that helps.

Related

After creating an NSMutableArray and adding objects, count shows as 0

The fast enumeration works, and shows the memory address for my 3 objects. But a simple count on my brothersArray (brothersArray.count) comes up with 0. I'm a bit of a noob. What I am missing?
I'm not receiving any errors or warnings. Everything appears to work fine. I just can't figure out why my array.count comes up as zero. Thanks in advance!
Here is my entire MasterViewController.m
// MasterViewController.m
// Matt_Bug
//
// Created by Matthew Toto on 5/17/14.
// Copyright (c) 2014 Matthew Toto. All rights reserved.
//
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "MPTBrothers.h"
#interface MasterViewController () {
NSMutableArray *_objects;
}
#end
#implementation MasterViewController
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Brothers";
MPTBrothers *First = [[MPTBrothers alloc]initWithInfo:#"JP" age:37 height:5];
MPTBrothers *Second = [[MPTBrothers alloc]initWithInfo:#"Matt" age:33 height:6];
MPTBrothers *Third = [[MPTBrothers alloc]initWithInfo:#"Kevin" age:27 height:5];
NSMutableArray *brothersArray = [NSMutableArray arrayWithObjects:First, Second, Third, nil];
for (id brotherObjects in brothersArray) {
NSLog(#"%#", brotherObjects);
}
NSLog(#"The array count is %lu",brothersArray.count);
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)insertNewObject:(id)sender
{
if (!_objects) {
_objects = [[NSMutableArray alloc] init];
}
[_objects insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
MPTBrothers *brotherCell = [self.brothersArray objectAtIndex:indexPath.row];
cell.textLabel.text = brotherCell.name;
NSLog(#"BrotherCell Name = %#", brotherCell.name);
// NSDate *object = _objects[indexPath.row];
// cell.textLabel.text = [object description];
return cell;
}
Here is my MPTBrothers.m
#import "MPTBrothers.h"
#implementation MPTBrothers
-(id)initWithInfo:(NSString *)name age:(int)age height:(int)height {
if (self = [self init])
_name = name;
_age = age;
_height = height;
return self;
}

Property not found in cellForRowAtIndexPath: method

I am getting an error which I don't understand because I have declared the property/ies. Have commented out the error in the AllListViewController.m file in the cellForRowAtIndexPath: method.
Here are the files:
Checklist.h
#import <Foundation/Foundation.h>
#interface Checklist : NSObject <NSCoding>
#property (nonatomic, copy) NSString *name;
#property (nonatomic, strong) NSMutableArray *items;
#property (nonatomic, copy) NSString *iconName;
-(int)countUncheckedItems;
#end
Checklist.m
#import "Checklist.h"
#import "ChecklistItem.h"
#implementation Checklist
-(id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super init])) {
self.name = [aDecoder decodeObjectForKey:#"Name"];
self.items = [aDecoder decodeObjectForKey:#"Items"];
self.iconName = [aDecoder decodeObjectForKey:#"IconName"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:#"Name"];
[aCoder encodeObject:self.items forKey:#"Items"];
[aCoder encodeObject:self.iconName forKey:#"IconName"];
}
-(id)init
{
if ((self = [super init])) {
self.items = [[NSMutableArray alloc] initWithCapacity:20];
self.iconName = #"Appointments";
}
return self;
}
-(int)countUncheckedItems
{
int count = 0;
for (ChecklistItem *item in self.items) {
if (!item.checked) {
count += 1;
}
}
return count;
}
-(NSComparisonResult)compare:(Checklist *)otherChecklist
{
return [self.name localizedStandardCompare:otherChecklist.name];
}
#end
AllListsViewController.h
#import <UIKit/UIKit.h>
#import "ListDetailViewController.h"
#class DataModel;
#interface AllListsViewController : UITableViewController <ListDetailViewControllerDelegate, UINavigationControllerDelegate>
#property (nonatomic, strong) DataModel *dataModel;
#end
AllListsViewController.m
#import "AllListsViewController.h"
#import "Checklist.h"
#import "ChecklistViewController.h"
#import "ChecklistItem.h"
#import "DataModel.h"
#interface AllListsViewController ()
#end
#implementation AllListsViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 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.
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.dataModel setIndexOfSelectedChecklist:indexPath.row];
Checklist *checklist = self.dataModel.lists[indexPath.row];
[self performSegueWithIdentifier:#"ShowChecklist" sender:checklist];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowChecklist"]) {
ChecklistViewController *controller = segue.destinationViewController;
controller.checklist = sender;
}
else if ([segue.identifier isEqualToString:#"AddChecklist"]) {
UINavigationController *navigationController = segue.destinationViewController;
ListDetailViewController *controller = (ListDetailViewController *)navigationController.topViewController;
controller.delegate = self;
controller.checklistToEdit = nil;
}
}
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
UINavigationController *navigationController = [self.storyboard instantiateViewControllerWithIdentifier:#"ListNavigationController"];
ListDetailViewController *controller = (ListDetailViewController *)navigationController.topViewController;
controller.delegate = self;
Checklist *checklist = self.dataModel.lists[indexPath.row];
controller.checklistToEdit = checklist;
[self presentViewController:navigationController animated:YES completion:nil];
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.dataModel.lists count];
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.dataModel.lists removeObjectAtIndex:indexPath.row];
NSArray *indexPaths = #[indexPath];
[tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
}
- (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];
cell.imageView.image = [UIImage imageNamed:Checklist.iconName]; /* Use of undeclared identifier; did you mean 'Checklist'? or Property 'iconName' not found on object of type 'Checklist'*/
return cell;
}
Checklist *checklist = self.dataModel.lists[indexPath.row];
cell.textLabel.text = checklist.name;
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d Remaining", [checklist countUncheckedItems]];
int count = [checklist countUncheckedItems];
if ([checklist.items count] == 0) {
cell.detailTextLabel.text = #"(No Items)";
} else if (count == 0) {
cell.detailTextLabel.text = #"All Done";
} else {
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d Remaining", count];
}
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 story board-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.
}
*/
-(void)listDetailViewControllerDidCancel:(ListDetailViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)listDetailViewController:(ListDetailViewController *)controller didFinishAddingChecklist:(Checklist *)checklist
{
[self.dataModel.lists addObject:checklist];
[self.dataModel sortChecklists];
[self.tableView reloadData];
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)listDetailViewController:(ListDetailViewController *)controller didFinishEditingChecklist:(Checklist *)checklist
{
[self.dataModel sortChecklists];
[self.tableView reloadData];
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if(viewController == self) {
[self.dataModel setIndexOfSelectedChecklist:-1];
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.navigationController.delegate = self;
NSInteger index = [self.dataModel indexOfSelectedChecklist];
if(index >= 0 && index < [self.dataModel.lists count]) {
Checklist *checklist = self.dataModel.lists[index];
[self performSegueWithIdentifier:#"ShowChecklist" sender:checklist];
}
}
#end
You have not declared the variable "Checklist" & trying to access the "iconName". Actually you are trying to access it directly via class name.
I can see you have created an instance if "Checklist" few lines down. So better create that instance before using Checklist.iconName
May be in the beginning of function after CellIdentifier creation.
Checklist *checklist = self.dataModel.lists[indexPath.row];
cell.imageView.image = [UIImage imageNamed:checklist.iconName]; /* Use of undeclared identifier; did you mean 'Checklist'? or Property 'iconName' not found on object of type 'Checklist'*/
return cell;
}
As per your code, "Checklist" is your class name, whereas the instance starts with small "c" as "checklist". So you also might have got confused.
Hope that helps.

addItemViewController:didFinishEditingItem does not pass edited item to main view controller

Have added a method and protocol to pass the addItemViewController:didFinishEditingItem method to the main view controller (ChecklistsViewController) after completing a text edit. (The edit command and segue are invoked by pressing a disclosure detail button on the Checklists main page.)
Problem is that after completing the edit and pressing the "Done" button, no completed text edit gets passed back to the original Checklists page, which means that the original edit was was not passed over. I have had no compiling warning messages.
Can you tell me what's wrong and why no completed edit is getting passed back to Checklists? Thanks in advance.
AddItemViewController.h
import
#class AddItemViewController;
#class ChecklistItem;
#protocol AddItemViewControllerDelegate <NSObject>
- (void)addItemViewControllerDidCancel:(AddItemViewController *)controller;
- (void)addItemViewController:(AddItemViewController *)controller didFinishAddingItem:(ChecklistItem *)item;
- (void)addItemViewController:(AddItemViewController *)controller didFinishEditingItem:(ChecklistItem *)item;
#end
#interface AddItemViewController : UITableViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *textField;
#property (strong, nonatomic) IBOutlet UIBarButtonItem *doneBarButton;
#property (nonatomic, weak) id <AddItemViewControllerDelegate> delegate;
#property (nonatomic, strong) ChecklistItem *itemToEdit;
- (IBAction)cancel;
- (IBAction)done;
#end
AddItemViewController.m
#import "AddItemViewController.h"
#import "ChecklistItem.h"
#interface AddItemViewController ()
#end
#implementation AddItemViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(self.itemToEdit != nil) {
self.title = #"Edit Item";
self.textField.text = self.itemToEdit.text;
self.doneBarButton.enabled = YES;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (IBAction)cancel
{
[self.delegate addItemViewControllerDidCancel:self];
}
- (IBAction)done
{
if(self.itemToEdit == nil) {
ChecklistItem *item = [[ChecklistItem alloc] init];
item.text = self.textField.text;
item.checked = NO;
[self.delegate addItemViewController:self didFinishAddingItem:item];
} else {
self.itemToEdit.text = self.textField.text;
[self.delegate addItemViewController:self didFinishEditingItem:self.itemToEdit];
}
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
return nil;
}
- (void)viewDidUnload {
[self setTextField:nil];
[self setDoneBarButton:nil];
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.textField becomeFirstResponder];
}
- (BOOL)textField:(UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newText = [theTextField.text stringByReplacingCharactersInRange:range withString:string];
self.doneBarButton.enabled = ([newText length] > 0);
return YES;
}
#end
ChecklistsViewController.h
#import <UIKit/UIKit.h>
#import "AddItemViewController.h"
#interface ChecklistsViewController : UITableViewController <AddItemViewControllerDelegate>
#end
ChecklistsViewController.m
#import "ChecklistsViewController.h"
#import "ChecklistItem.h"
#interface ChecklistsViewController ()
#end
#implementation ChecklistsViewController {
NSMutableArray *items;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
items = [[NSMutableArray alloc] initWithCapacity:20];
ChecklistItem *item;
item = [[ChecklistItem alloc]init];
item.text = #"Walk the dog";
item.checked = NO;
[items addObject:item];
item = [[ChecklistItem alloc]init];
item.text = #"Brush my teeth";
item.checked = YES;
[items addObject:item];
item = [[ChecklistItem alloc]init];
item.text = #"Learn iOS development";
item.checked = YES;
[items addObject:item];
item = [[ChecklistItem alloc]init];
item.text = #"Soccer practice";
item.checked = NO;
[items addObject:item];
item = [[ChecklistItem alloc]init];
item.text = #"Eat ice cream";
item.checked = YES;
[items addObject:item];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [items count];
}
- (void)configureCheckmarkForCell:(UITableViewCell *)cell withChecklistItem:(ChecklistItem *)item
{
UILabel *label = (UILabel *)[cell viewWithTag:1001];
if(item.checked) {
label.text =#"√";
} else {
label.text = #"";
}
}
- (void)configureTextForCell:(UITableViewCell *)cell withChecklistItem:(ChecklistItem *)item
{
UILabel *label = (UILabel *)[cell viewWithTag:1000];
label.text = item.text;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ChecklistItem"];
ChecklistItem *item = [items objectAtIndex:indexPath.row];
[self configureTextForCell:cell withChecklistItem:item];
[self configureCheckmarkForCell:cell withChecklistItem:item];
return cell;
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
ChecklistItem *item = [items objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"EditItem" sender:item];
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
ChecklistItem *item = [items objectAtIndex:indexPath.row];
[item toggleChecked];
[self configureCheckmarkForCell:cell withChecklistItem:item];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[items removeObjectAtIndex:indexPath.row];
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
}
- (void)addItemViewControllerDidCancel:(AddItemViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)addItemViewController:(AddItemViewController *)controller didFinishAddingItem:(ChecklistItem *)item
{
int newRowIndex = [items count];
[items addObject:item];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:0];
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)addItemViewController:(AddItemViewController *)controller didFinishEditingItem:(ChecklistItem *)item
{
int index = [items indexOfObject:item];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self configureCheckmarkForCell:cell withChecklistItem:item];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"AddItem"]) {
UINavigationController *navigationController = segue.destinationViewController;
AddItemViewController *controller = (AddItemViewController *)navigationController.topViewController;
controller.delegate = self;
} else if ([segue.identifier isEqualToString:#"EditItem"]) {
UINavigationController *navigationController = segue.destinationViewController;
AddItemViewController *controller = (AddItemViewController *)navigationController.topViewController;
controller.delegate = self;
controller.itemToEdit = sender;
}
}
#end

Parse.com - How to get PFQueryTableViewController , Pagination working with UISearchDisplayController?

I am trying to add Search to Todo demo application. I have below code so far with Search working. The issue with below code is that the Pagination doesn't work anymore. There is simlilar question about pagination but when "number of rows in section + 1" returned, the app crashes with [__NSArrayM objectAtIndex:] error. How do I get the Pagination working?
// MyTableController.h
#import <Parse/Parse.h>
#interface MyTableController : PFQueryTableViewController
#end
// MyTableController.m
#import "MyTableController.h"
#interface MyTableController() <UISearchDisplayDelegate> {
}
#property (nonatomic, strong) UISearchBar *searchBar;
#property (nonatomic, strong) UISearchDisplayController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults;
#end
#implementation MyTableController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
self.className = #"Todo";
self.keyToDisplay = #"text";
self.pullToRefreshEnabled = YES;
self.paginationEnabled = YES;
self.objectsPerPage = 5;
}
return self;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
self.tableView.tableHeaderView = self.searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar
contentsController:self];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.searchController.delegate = self;
CGPoint offset = CGPointMake(0, self.searchBar.frame.size.height);
self.tableView.contentOffset = offset;
self.searchResults = [NSMutableArray array];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName: self.className];
[query whereKey:#"text" containsString:searchTerm];
NSArray *results = [query findObjects];
[self.searchResults addObjectsFromArray:results];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return self.objects.count;
} else {
return self.searchResults.count ;
}
}
#pragma mark - Parse
- (void)objectsDidLoad:(NSError *)error {
[super objectsDidLoad:error];
}
- (void)objectsWillLoad {
[super objectsWillLoad];
}
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.className];
if ([self.objects count] == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
[query orderByAscending:#"priority"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [object objectForKey:#"text"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Priority: %#", [object objectForKey:#"priority"]];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
}
#end
In your own implementation of numberOfRowsInSection you must return numberOfRows + 1. But then you must write your code considering you have more cells than query returning. Check out your heightForRowAtIndexPath and others methods: there can be calls to [self.objects objectAtIndex:self.objects.count]. I mean, if indexPath.row == self.objects.count, its a "Load More" cell.
If you overriding willSelectRowAtIndexPath or didSelectRowAtIndexPath, you must do this in the top of method
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
or add this (previous case is prefered)
if (indexPath.row == self.objects.count)
{
[self loadNextPage];
}
Customization of Load More cell placed in -(PFTableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:(NSIndexPath *)indexPath
And im using
-(PFTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath
instead of
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:

Preventing parent views UIGestureRecongnizer executing within a UITableVIew subview

Problem:
I have a UIView that has a UITableView as a subview. The UIView has a UITapGestureRecognizer configured.
My Problem is that taps on the table are consumed by the UIView's gesture recognizer. The result is the table view never gets to see taps.
How can I either make the recognizer fail when a point is within the table's frame OR make the table the default consumer of the tap.
I have tried (as the code examples show) a number of methods pointInside:withEvent, hitTest:withEvent but can't quite figure out how to do it.
Here is code representing the problem:
Controller:
#import <UIKit/UIKit.h>
#import "ABCDTableView.h"
#interface ABCDFirstView : UIView
#property (nonatomic,strong) ABCDTableView *tableView;
#end
#import "ABCDFirstView.h"
#implementation ABCDFirstView
#synthesize tableView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self awakeFromNib];
}
return self;
}
- (void)awakeFromNib
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(viewTouch:)];
[self addGestureRecognizer:tap];
}
- (void)viewTouch:(UIGestureRecognizer *)gesture {
NSLog(#"view touched");
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if (CGRectContainsPoint(self.tableView.bounds, point)) {
NSLog(#"point in table point as well as view");
return NO;
}
else if (CGRectContainsPoint(self.bounds, point)) {
NSLog(#"point only in view");
return YES;
}
NSLog(#"point not in view");
return NO;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *view = [super hitTest:point withEvent:event];
NSLog(#"view hittest res: %#",view);
return view;
}
#end
TableView
#import <UIKit/UIKit.h>
#interface ABCDTableView : UITableView
<UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) NSArray *list;
#end
#import "ABCDTableView.h"
#implementation ABCDTableView
#synthesize list;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self awakeFromNib];
}
return self;
}
- (void)awakeFromNib
{
self.delegate = self;
self.dataSource = self;
// create table list
self.list = [[NSArray alloc]
initWithObjects: #"one",#"two",#"three",#"four",#"five",
#"six", #"seven", #"eight", #"nine", #"ten", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.list count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cell";
UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.textLabel.text = [self.list objectAtIndex:[indexPath row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"row selected");
}
#end
View
#import <UIKit/UIKit.h>
#import "ABCDTableView.h"
#interface ABCDFirstView : UIView
#property (nonatomic,strong) ABCDTableView *tableView;
#end
#import "ABCDFirstView.h"
#implementation ABCDFirstView
#synthesize tableView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self awakeFromNib];
}
return self;
}
- (void)awakeFromNib
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(viewTouch:)];
[self addGestureRecognizer:tap];
}
- (void)viewTouch:(UIGestureRecognizer *)gesture {
NSLog(#"view touched");
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if (CGRectContainsPoint(self.tableView.bounds, point)) {
NSLog(#"point in table point as well as view");
return NO;
}
else if (CGRectContainsPoint(self.bounds, point)) {
NSLog(#"point only in view");
return YES;
}
NSLog(#"point not in view");
return NO;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *view = [super hitTest:point withEvent:event];
NSLog(#"view hittest res: %#",view);
return view;
}
#end
Use the UIGestureRecognizerDelegate method
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
and check if the touch.view is the same view as the one that should receive the gesture recognizer.