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
Related
FirstPage.h
#import <UIKit/UIKit.h>
#import "StudentPage.h"
#interface FirstPage : UIViewController <UITableViewDelegate,UITableViewDataSource,StudentInfoDelegates>
#property (strong, nonatomic) IBOutlet UITableView *tableView;
- (IBAction)addButtonAction:(id)sender;
#end
FirstPage.m
#import "FirstPage.h"
#interface FirstPage ()
#end
#implementation FirstPage
{
NSMutableArray *firstPageArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib
//[self performSegueWithIdentifier:#"StudentInfo" sender:sender];
/*StudentPage *student=[[StudentPage alloc]init];
student.delegates=self;*/
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//the next following didn't created..
//the RowAtIndexPath are not been executed..
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *concateValue=#"";
NSMutableDictionary *studentSecondDictionary=[[NSMutableDictionary alloc]init];
static NSString *CellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
cell=[[UITableViewCell alloc]initWithFrame:CGRectZero];
[cell setBackgroundColor:[UIColor redColor]];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell setIndentationWidth:0.0];
studentSecondDictionary=[firstPageArray objectAtIndex:indexPath.row];
NSString *name1=[studentSecondDictionary valueForKey:#"NAME"];
NSString *regno1=[studentSecondDictionary valueForKey:#"REGNO"];
NSString *marks1=[studentSecondDictionary valueForKey:#"MARKS"];
NSString *rank1=[studentSecondDictionary valueForKey:#"RANK"];
concateValue=[[[[[[name1 stringByAppendingString:#" "]stringByAppendingString:regno1]stringByAppendingString:#" "]stringByAppendingString:marks1]stringByAppendingString:#" "]stringByAppendingString:rank1];
cell.textLabel.text=concateValue;
}
return cell;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return firstPageArray.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
- (IBAction)addButtonAction:(id)sender {
StudentPage *stdView=[self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
stdView.delegates=self;
[self.navigationController pushViewController:stdView animated:YES];
//[self.view addSubview:stdView.view];
}
-(void)didFinishSave:(NSMutableArray *)in_studentList{
firstPageArray=[[NSMutableArray alloc]init];
firstPageArray=in_studentList;
[self.tableView reloadData];
}
#end
StudentPage.h
#import <UIKit/UIKit.h>
#protocol StudentInfoDelegates
-(void)didFinishSave:(NSMutableArray*)in_studentList;
#end
#interface StudentPage : UIViewController<UITextFieldDelegate>
#property(assign,nonatomic)id<StudentInfoDelegates> delegates;
#property (strong, nonatomic) IBOutlet UITextField *name;
#property (strong, nonatomic) IBOutlet UITextField *regno;
#property (strong, nonatomic) IBOutlet UITextField *marks;
#property (strong, nonatomic) IBOutlet UITextField *rank;
- (IBAction)save:(UIButton *)sender;
#end
StudentPage.m
#import "StudentPage.h"
#import "FirstPage.h"
#implementation StudentPage
{
NSMutableArray *studentArray;
NSMutableDictionary *StudentDictionary;
}
#synthesize name,regno,marks,rank;
#synthesize delegates;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
[super touchesBegan:touches withEvent:event];
}
- (IBAction)save:(UIButton *)sender {
studentArray=[[NSMutableArray alloc]init];
StudentDictionary=[[NSMutableDictionary alloc]init];
[StudentDictionary setValue:name.text forKey:#"NAME"];
[StudentDictionary setValue:regno.text forKey:#"REGNO"];
[StudentDictionary setValue:marks.text forKey:#"MARKS"];
[StudentDictionary setValue:rank.text forKey:#"RANK"];
[studentArray addObject:StudentDictionary];
[delegates didFinishSave:studentArray];
NSLog(#"%#",studentArray);
FirstPage *firstView=[self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier1"];
[self.navigationController pushViewController:firstView animated:YES];
}
#end
As #BiWoj said in the comments, you are checking for
if (cell==nil)...
and rely on that check to go through the first time so you can fill out your data. This is wrong, you instead dequeue the cell and then when it's not nil you can start putting your data in its views. The only reason that cell will be nil is when you dequeue, using a non-existent identifier i.e. it should never happen.
First just check your delegate method is getting called or not when you click on save button.
I think you forgot to set delegate to self before
[delegates didFinishSave:studentArray];
It should be
self.delegate = delegates
[delegates didFinishSave:studentArray];
If this does not work please check that, you are pushing student page from first page like this
- (IBAction)addButtonAction:(id)sender {
StudentPage *stdView=[self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
stdView.delegates=self;
[self.navigationController pushViewController:stdView animated:YES];}
And one again on your save action method of student page you are pushing first page like this.
FirstPage *firstView=[self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier1"];
[self.navigationController pushViewController:firstView animated:YES];
Well i guess instead of that you have to just use
[self.navigationController popToRootViewControllerAnimated:YES];
There is no need to push again the same controller you just have to pop to base controller.
After hours if trying to solve this error i decided to reach out for
help. I Keep on getting the same error :
"Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '***
-[__NSCFConstantString stringByAppendingString:]: nil argument'"
#import <UIKit/UIKit.h>
#interface BrowseTableViewController : UITableViewController
#property (strong) NSMutableArray *emp; //An array to store all the information of clicked entries
#end
#import <CoreData/CoreData.h>
#import "BrowseClickViewController.h"
#import "ItemTableViewCell.h"
#interface BrowseTableViewController ()<UITableViewDelegate, UITableViewDataSource>
#end
#implementation BrowseTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
[self.tableView registerNib:[UINib nibWithNibName:#"ItemTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"Cell1"];
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//add code here for when you hit delete
[_emp removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadData];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (NSManagedObjectContext *)managedObjectContext
{
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Employee"];
self.emp = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy]; // Obtaining all the entries of persistance store to show in Table view
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.emp.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell1";
ItemTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSManagedObject *empp = [self.emp objectAtIndex:indexPath.row]; //obtaining the informatio of selected row in empp object
[cell.itemName setText:[NSString stringWithFormat:#"%#", [empp valueForKey:#"name"]]];
[cell.quantityLabel setText:[NSString stringWithFormat:#"%#", [empp valueForKey:#"quantity"]]];
[cell.shopLabel setText:[NSString stringWithFormat:#"%#", [empp valueForKey:#"store"]]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
BrowseClickViewController *initViewController = [storyBoard instantiateViewControllerWithIdentifier:#"Click"];
[self.navigationController presentViewController:initViewController animated:YES completion:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{ //Segue which is called when user selects any row, and this segue modifies the value of emp object of BrowseClickViewController with the clicked row details.
if ([segue.identifier isEqualToString:#"recordClicked"]){
NSManagedObject *selectedEmp = [self.emp objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
BrowseClickViewController *destViewController = segue.destinationViewController;
destViewController.emp = selectedEmp;
}
}
#end
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface BrowseClickViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIScrollView *scroller;
#property (weak, nonatomic) IBOutlet UILabel *barcodeLabel;
#property (weak, nonatomic) IBOutlet UILabel *categoryLabel;
#property (weak, nonatomic) IBOutlet UILabel *nameLabel;
#property (weak, nonatomic) IBOutlet UILabel *priceLabel;
#property (weak, nonatomic) IBOutlet UILabel *quantityLabel;
#property (weak, nonatomic) IBOutlet UILabel *storeLabel;
#property (weak, nonatomic) IBOutlet UIImageView *imagePicture;
#property (strong) NSManagedObject *emp;
#property (weak, nonatomic) NSString *picLabel;
#end
#import "BrowseClickViewController.h"
#import "BrowseTableViewController.h"
#import <CoreData/CoreData.h>
#import "ItemTableViewCell.h"
#interface BrowseClickViewController ()
#end
#implementation BrowseClickViewController
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (void)viewDidLoad {
[super viewDidLoad];
_nameLabel.text=[#"Name:" stringByAppendingString:[self.emp valueForKey:#"name"]];
_barcodeLabel.text=[#"Barcode:" stringByAppendingString:[self.emp valueForKey:#"barcode"]];
_categoryLabel.text=[#"Category:" stringByAppendingString:[self.emp valueForKey:#"category"]];
_priceLabel.text=[#"Price:"stringByAppendingString:[self.emp valueForKey:#"price"]];
_quantityLabel.text=[#"Quantity:" stringByAppendingString:[self.emp valueForKey:#"quantity"]];
_storeLabel.text=[#"Store:" stringByAppendingString:[self.emp valueForKey:#"store"]];
_picLabel=[self.emp valueForKey:#"pic"];
_imagePicture.image=[self loadImage:_picLabel];
}
-(UIImage *)loadImage: (NSString *)name
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithString:name]];
UIImage* image = [UIImage imageWithContentsOfFile:path];
return image;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
#import <UIKit/UIKit.h>
#interface ItemTableViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *itemName;
#property (nonatomic, weak) IBOutlet UILabel *quantityLabel;
#property (nonatomic, weak) IBOutlet UILabel *shopLabel;
#end
#import "ItemTableViewCell.h"
#import "BrowseClickViewController.h"
#implementation ItemTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
BrowseClickViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
}
#end
Most possibly , reason is that some of your appended strings values are nil.Do defensive coding.Check the below code sample and change all your code accordingly.
if([self.emp valueForKey:#"name"])
{
_nameLabel.text=[#"Name:" stringByAppendingString:[self.emp valueForKey:#"name"]];
}
I am trying to copy the array from tableview controller to view controller. I have checked the code multiple times and it seems to be okay.
//Delegate class
#import <UIKit/UIKit.h>
#protocol Category <NSObject>
#required
-(void) delegateMethodForCategory : (NSMutableArray *) arrayOfCategory;
#end
#interface Categories : UIViewController <UITableViewDelegate,UITableViewDataSource>
#property (nonatomic) id<Category> delegate;
#property (nonatomic,strong) NSArray *sports;
#property (strong, nonatomic) IBOutlet UITableView *tableview;
#property (nonatomic,strong) NSMutableArray *selectedIndexes;
#end
//Delegate methods
#import "Categories.h"
#interface Categories ()
{
NSMutableArray *array ;
}
#end
#implementation Categories
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_sports= [[NSArray alloc] initWithObjects: #"Baseball", #"Soccer", #"Hockey",
#"Other",nil];
}
- (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 _sports.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
array = [[NSMutableArray alloc]init];
// Configure the cell...
cell.textLabel.text=[self.sports objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryNone)
{ [tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;
[array addObject:cellText];
}else if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryCheckmark){
[tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryNone;
[array removeObject:cellText];
}
}
- (IBAction)doneButton:(id)sender {
[self.delegate delegateMethodForCategory:array];
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
#import <UIKit/UIKit.h>
#import "Categories.h"
#interface ActivityCreator : UIViewController <UIPopoverPresentationControllerDelegate, Category>
#property (nonatomic) Categories *requestClass;
#property (nonatomic,strong) NSMutableArray *arrayOfSports;
#end
//This class implements delegate
import "ActivityCreator.h"
#interface ActivityCreator ()
#end
#implementation ActivityCreator
- (void)viewDidLoad {
[super viewDidLoad];
[self settingUp];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller{
return UIModalPresentationNone;
}
-(void)settingUp{
_requestClass = [[Categories alloc]init];
self.requestClass.delegate = self;
}
#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 {
if([segue.identifier isEqualToString:#"hubabuba"]){
Categories *pop = (Categories *)segue.destinationViewController;
pop.modalPresentationStyle = UIModalPresentationPopover;
pop.popoverPresentationController.delegate = self;
}
}
-(void) delegateMethodForCategory : (NSMutableArray *) arrayOfCategory {
_arrayOfSports = arrayOfCategory;
NSLog(#"%#",_arrayOfSports);
}
Any guidance where I am doing wrong will be of great help. Have been stuck on this for a while.
The delegate method is not being called at all.
Thanks
Set the delegate of Categories class in prepareForSegue method instead of setting in settingUp method.
Write
pop.delegate = self;
In prepareForSegue method.
I've gone through the XCode app development tutorial a few times now and keep coming up with the same error.
source.ToDoItem gives the error "no getter method to read from property"
Any ideas on how to resolve this? I can't seem to write a correct getter method and I can't find an example in the development tutorial to go off of.
- (IBAction)unwindToList:(UIStoryboardSegue *)segue {
AddToDoItemViewController *source = [segue sourceViewController];
ToDoItem *item = source.ToDoItem;
if (item != nil) {
[self.toDoItems addObject:item];
[self.tableView reloadData];
}
}
ToDoItem.h
#import <Foundation/Foundation.h>
#interface ToDoItem : NSObject
#property NSString *itemName;
#property BOOL completed;
#property (readonly) NSDate *creationDate;
#end
ToDoItem.m
#import "ToDoItem.h"
#implementation ToDoItem
#end
ToDoListTableViewController
#import "ToDoListTableViewController.h"
#import "AddToDoItemViewController.h"
#import "ToDoItem.h"
#interface ToDoListTableViewController ()
#property NSMutableArray *toDoItems;
#end
#implementation ToDoListTableViewController
- (void)loadInitialData {
ToDoItem *item1 = [[ToDoItem alloc] init];
item1.itemName = #"things";
[self.toDoItems addObject:item1];
ToDoItem *item2 = [[ToDoItem alloc] init];
item2.itemName = #"Things to do with things";
[self.toDoItems addObject:item2];
ToDoItem *item3 = [[ToDoItem alloc] init];
item3.itemName = #"Write Ethics Paper";
[self.toDoItems addObject:item3];
}
- (IBAction)unwindToList:(UIStoryboardSegue *)segue {
AddToDoItemViewController *source = [segue sourceViewController];
ToDoItem *item = source.ToDoItem;
if (item != nil) {
[self.toDoItems addObject:item];
[self.tableView reloadData];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
self.toDoItems = [[NSMutableArray alloc] init];
[self loadInitialData];
// 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 {
#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 [self.toDoItems count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ListPrototypeCell" forIndexPath:indexPath];
ToDoItem *toDoItem = [self.toDoItems objectAtIndex:indexPath.row];
cell.textLabel.text = toDoItem.itemName;
// Configure the cell...
if (toDoItem.completed) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
ToDoItem *tappedItem = [self.toDoItems objectAtIndex:indexPath.row];
tappedItem.completed = !tappedItem.completed;
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
#end
and ToDoListTableViewController.h
#import <UIKit/UIKit.h>
#import "ToDoItem.h"
#import "AddToDoItemViewController.h"
#interface ToDoListTableViewController : UITableViewController
- (IBAction)unwindToList:(UIStoryboardSegue *)segue;
#end
AddToDoItemViewController.m
#import "AddToDoItemViewController.h"
#import "ToDoItem.h"
#interface AddToDoItemViewController ()
#property (weak, nonatomic) IBOutlet UITextField *textField;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButton;
#end
#implementation AddToDoItemViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#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 {
if (sender != self.saveButton) return;
if (self.textField.text.length > 0) {
}
self.toDoItem = [[ToDoItem alloc] init];
self.toDoItem.itemName = self.textField.text;
self.toDoItem.completed = NO;
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
#end
AddToDoItemViewController.h
#import <UIKit/UIKit.h>
#import "ToDoItem.h"
#interface AddToDoItemViewController : UIViewController
#property ToDoItem *toDoItem;
#property NSString *itemName;
#property BOOL completed;
#property (readonly) NSDate *creationDate;
#end
In AddToDoItemViewController you have
#property ToDoItem *toDoItem;
but in the code you use it as:
ToDoItem *item = source.ToDoItem;
where it should be:
ToDoItem *item = source.toDoItem;
Note the naming convention. The class name starts with a capital letter and the property name starts with a lower case letter.
Try to change these two lines:
#property NSString *itemName;
#property BOOL completed;
For this:
#property (nonatomic, strong) NSString *itemName;
#property (nonatomic, readwrite) BOOL completed;
I am lost with segue. I tried to do it through this tutorial.
Everything is working but only one line write me error and I don`t know how to fix it.
Image with error:
TableViewController.h
#import <UIKit/UIKit.h>
#import "Parse/Parse.h"
#import "CustomCell.h"
#import "DetailViewController.h"
#interface TableViewController : UITableViewController <UITableViewDelegate,UISearchDisplayDelegate, UISearchBarDelegate> {
NSArray *colorsArray;
NSArray *searchResults;
}
#property (strong, nonatomic) IBOutlet UITableView *colorsTable;
#property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
#property (strong, nonatomic) IBOutlet UISearchDisplayController *searchBarController;
#end
TableViewController.m
#import "TableViewController.h"
#import "CustomCell.h"
#import "DetailViewController.h"
#interface TableViewController (){
}
#end
#implementation TableViewController
#synthesize colorsTable;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{ if ([segue.identifier isEqualToString:#"displayDetail"]){
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
PFObject *object = [self.objects objectAtIndex:indexPath.row];
UINavigationController *nav = [segue destinationViewController];
DetailViewController *detailViewController = (DetailViewController *) nav.topViewController;
detailViewController.exam = object;
}
}
- (void) retrieveFromParse {
PFQuery *retrieveColors = [PFQuery queryWithClassName:#"Hracky1"];
[retrieveColors findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
colorsArray= [[NSArray alloc] initWithArray:objects];
}
[colorsTable reloadData];
}];
[self.colorsTable reloadData];
[self.refreshControl endRefreshing];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self performSelector:#selector(retrieveFromParse)];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
self.refreshControl = refreshControl;
[refreshControl addTarget:self action:#selector(retrieveFromParse) forControlEvents:UIControlEventValueChanged];
}
- (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 colorsArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"colorsCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
PFObject *tempObject = [colorsArray objectAtIndex:indexPath.row];;
[cell.imageview setFile: [tempObject objectForKey:#"ImageURL"]];
[cell.imageview loadInBackground];
cell.cellTitle.text = [tempObject objectForKey:#"cellTitle"];
cell.cellDescript.text = [tempObject objectForKey:#"cellDescript"];
return cell;
}
#end
DetailedViewController.h
#import <UIKit/UIKit.h>
#import "Parse/Parse.h"
#interface DetailViewController : UIViewController <UITextViewDelegate>
#property (nonatomic, strong) PFObject *exam;
#property (nonatomic, strong) IBOutlet UITextView *descriptext;
#end
DetailViewcontrolled.m
#import "DetailViewController.h"
#import "Parse/Parse.h"
#import "TableViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];{
self.descriptext.text = [self.exam objectForKey:#"TextView"];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
From what I read from your code it is because you are using a normal UITableViewController. To be able to access the property "self.objects" you have to be using Parse's subclassed UITableViewController called "PFTableViewController". They have included the property "objects".
I can recommend this tutorial to get an understanding of the PFTableViewController
http://www.appcoda.com/ios-programming-app-backend-parse/
If you want it to work without the PFTableView you can do the following:
I can see that you have an array called colorsArray and that you add the Parse objects into that array.
So instead of doing this:
PFObject *object = [self.objects objectAtIndex:indexPath.row];
You can do this:
PFObject *object = [colorsArray objectAtIndex:indexPath.row];
I hope it works out for you!
Along with doing the tutorial which another answer here has suggested, perhaps you ought not to pass the PFObject itself...
Figure out and query whatever text you are trying to show in your detail view controller, retrieve it in the table view controller, then ONLY pass that (instead of a entire PFObject).