Delegate Method is not getting called - ios

I am trying to pass selected cell text from CategoryViewController to DescribeViewController. But it does not call the method in the DescribeViewController method.
CategoryViewController.h
#import <UIKit/UIKit.h>
#protocol CategoryViewControllerDelegate <NSObject>
- (void)didSelectRow:(NSString *)cellDataString;
#end
#interface CategoryViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) id<CategoryViewControllerDelegate> delegate;
#end
CategoryViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [categoryTableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
[self.delegate didSelectRow:cellText];
[[self navigationController] popViewControllerAnimated:YES];
}
DescribeViewController.h
#import <UIKit/UIKit.h>
#import "CategoryViewController.h"
#interface DescribeViewController : ProductAwareBaseViewController<UITextFieldDelegate, CategoryViewControllerDelegate>
The following didSelectRow method is not getting called. I could not able to find out the root of the problem.
DescribeViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
CategoryViewController *popoverTableViewController = [[CategoryViewController alloc] init];
popoverTableViewController.delegate = self;
}
- (void)didSelectRow:(NSString *)cellDataString
{
self.cellDataString = cellDataString;
}
ProductAwareBaseViewController.h
#import UIKit;
#class Product;
#interface ProductAwareBaseViewController : UIViewController
#property (nonatomic, strong) Product *product;
#end
ProductAwareBaseViewController.m
#import "ProductAwareBaseViewController.h"
#import "Product.h"
#interface ProductAwareBaseViewController ()
#end
#implementation ProductAwareBaseViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[ProductAwareBaseViewController class]]) {
ProductAwareBaseViewController *vc = (ProductAwareBaseViewController *)segue.destinationViewController;
vc.product = self.product;
}
}
#end

Try setting the delegate object in didSelectRow. And call that delegate method after that. Because delegate is weak, may be it is released from the memory.
CategoryViewController *popoverTableViewController = [[CategoryViewController alloc] init];
popoverTableViewController.delegate = self;
UITableViewCell *cell = [categoryTableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
[self.delegate didSelectRow:cellText];
[[self navigationController] popViewControllerAnimated:YES];

Most common reason for delegate method not being called is dealing with incorrect objects.
Ensure that CategoryViewController object created from
DescribeViewController is the same which you are presenting on
screen and that the delegate is being set on the same object. I truly believe you are creating a new CategoryViewController object and setting delegate on that.
In DescribeViewController, before calling delegate, check the
existence of delegate and that it implements the protocol method (if
its an optional method). This is a safety check, you can also put a NSLog statement to double check if your delegate exists or not. You are failing here.
->
if (delegate && [delegate respondsToSelector:(didSelectRow:)]) {
[self.delegate didSelectRow:cellText];
}
PS: If you are segueing from DescribeViewController to CategoryViewController then you set delegate in prepareForSegue:.
Follow these guidelines and I am sure you would be able to fix your issue!

try
#property (nonatomic, weak) id <CategoryViewControllerDelegate> delegate;
for declaring your delegate.
EDITED
try for checking the delegate is returning some value or not.
By this, whenever yo are setting the values.
if(self.delegate && [self.delegate respondsToSelector:#selector(didSelectRow:)])
{
[self.delegate didSelectRow:(NSString *) cellDataString];
}
and also if you are using the segue to transfer the data between two controllers then check there for the delegates.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
DescribeViewController *obj = (DescribeViewController *)segue.destinationViewController;
obj.delegate =self;
}
i think this will help you.

Related

The value get by delegate method is been clear?

In tableViewControllerA.h I declare a delegate ,and in tableViewControllerA.m I implement the method when click a cell of the tableView, A will pass the value to B, and execute the perfromSegueWithIdentifier to jump to tableViewControllB,in tableViewControllB.m the getting method is called, and I get the value, but after the viewDidLoad() method call, the value become nil. Please help me to solve the problem.By the way , the property of the value is strong,nonatomic.
DTZHomeTableViewController.h
#import <UIKit/UIKit.h>
#import "PassData.h"
#protocol PassDataDelegate
-(void)passData:(PassData*) dataToProgram;
#end
#interface DTZHomeTableViewController :
UITableViewController<UITableViewDelegate,UITableViewDataSource>
#property(assign,nonatomic) id<PassDataDelegate> dataDelegate;
#end
PassData is an user-defined class
DTZHomeTableViewController.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ProgramTableViewController *programViewController=
[[ProgramTableViewController alloc]init];
self.dataDelegate=programViewController;;
PassData *jump=[[PassData alloc]init];
jump.livingStatus=YES;
jump.role=0;
jump.index=indexPath.row;
jump.curOnlineNum=305605;
[self.dataDelegate passData:jump];
[self performSegueWithIdentifier:#"showSelectedProgram" sender:self];
}
ProgramTableViewController.h
#import <UIKit/UIKit.h>
#import "DTZHomeTableViewController.h"
#interface ProgramTableViewController :
UITableViewController<PassDataDelegate,UITableViewDataSource,UITableViewDelegate>
#property(strong,nonatomic) PassData * dataFromHome;
#end
ProgramTableViewController.m
#implementation ProgramTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"view did load%#",self.dataFromHome); // log :null
}
- (void) passData:(PassData *)dataToProgram
{
self.dataFromHome=dataToProgram;
}
#end
Delegation isn't the proper way to pass data to a segued view controller. Instead, you want to pass the data in prepareForSegue:sender:
Remove the protocol and delegate.
Add properties to your ProgramTableViewController for the data you want to pass.
#property (nonatomic, assign) BOOL livingStatus;
#property (nonatomic, assign) NSInteger role;
#property (nonatomic, assign) NSInteger row;
#property (nonatomic, assign) NSInteger curOnlineNum;
In prepareForSegue:sender:, set the ProgramTableViewController's passed properties to the values associated with the selected row:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ProgramTableViewController *controller = (ProgramTableViewController *)[segue destinationViewController];
controller.livingStatus = YES;
controller.role = 0;
controller.row = indexPath.row;
controller.curOnlineNum = 305605;
}
}
You shouldn't allocate and init ProgramTableViewController in tableView:didSelectRowAtIndexPath:. Your segue will instantiate the destination view controller for you.
You don't even need to have a tableView:didSelectRowAtIndexPath: method. You can create a push segue from the tableViewCell to ProgramTableViewController, right within Storyboard. Give the segue an identifier (such as "showDetail"). Then in prepareForSegue, you assign the values, as I explained.
When you tap on that row, the segue will create a ProgramTableViewController, set the parameters, and present it for you.

using iOS delegates

im new to iOS and its developing .there i have used iOS delegates to pass values in between view controllers
1. Essentialinfocontroller - its got TableView
2. detailcontroller -
i want to pass values of Essentialinfocontroller to detailcontroller
to do that i used delegates but nothing print on console please help me.
Essentialinfocontroller.h
#import <UIKit/UIKit.h>
#protocol sendTestData <NSObject>
-(void)sendDataToA:(NSArray *)array;
#end
#interface Essentialinfocontroller : UIViewController<UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *info;
#property (nonatomic,strong) NSDictionary * courses;
#property (nonatomic, strong)NSArray *coursekeys;
#property(nonatomic,strong) NSString* customeLink;
#property (nonatomic,retain)NSArray * array;
#property(nonatomic,assign)id delegate;
#end
Essentialinfocontroller.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row==0){
[self giveValuestoNSmutableArray];
[delegate sendDataToA:array];
}
}
-(void)giveValuestoNSmutableArray
{
array = [NSArray arrayWithObjects:#"Jill Valentine", #"Peter Griffin", #"Meg Griffin", #"Jack Lolwut",
#"Mike Roflcoptor", #"Cindy Woods", #"Jessica Windmill", #"Alexander The Great",
#"Sarah Peterson", #"Scott Scottland", #"Geoff Fanta", #"Amanda Pope", #"Michael Meyers",
#"Richard Biggus", #"Montey Python", #"Mike Wut", #"Fake Person", #"Chair",
nil];
}
detailcontroller.h
#import <UIKit/UIKit.h>
#import "Essentialinfocontroller.h"
#interface detailcontroller : UIViewController <sendTestData>
#end
detailcontroller.m
#import "detailcontroller.h"
#interface detailcontroller ()
#end
#implementation detailcontroller
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
Essentialinfocontroller * acontollerobject=[[Essentialinfocontroller alloc] initWithNibName:#"Essentialinfocontroller" bundle:nil];
acontollerobject.delegate=self; // protocol listener
[self.navigationController pushViewController:acontollerobject animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)sendDataToA:(NSArray *)array
{
for (NSString *string in array) {
NSLog(#"%#", string);
}
}
#end
You've got the relationship between controllers and delegates a little backwards. A delegate is used to pass information back. Your tableViewController is the detailController's delegate, and detailController shouldn't be allocating an EssentialInfoController inside it. You're basically creating a whole new EssentialInfoController that's different from the first one.
The easiest way to pass data is just to set it when the detailController is allocated. Also, since you're using storyboards, you have to use (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender to allocate the detailController.
Here's what I would do:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row==0){
[self performSegueWithIdentifier:#"OpenDetailsController"];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
DetailController *controller = (DetailController *)[segue destinationViewController];
NSArray *array = <your array here>;
[controller setArray:array];
}
In your storyboard, set the Storyboard Segue Identifier for that segue to "OpenDetailsController".
A delegate function is defined through a protocol, and you would have the DetailController call its delegate like this:
[self.delegate doSomething];
And in the EssentialInfoViewController you have to define the delegate function
-(void)doSomething {
}

UITableView's custom delegate doesn't get called when displayed from UIPopoverController

Hoping someone had to solve related issues .. this is driving me nuts :/
My UITableViewController implements a custom delegate method:
.h
#protocol folderDelegate
#required
- (void)folderViewDidSelectPlan:(NSString*)planId;
#end
#interface FolderViewController : UITableViewController
#property (nonatomic, assign) id delegate;
#end
.m
#implementation FolderViewController
#synthesize delegate;
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
NSDictionary *row = [self->resultsPlan objectAtIndex:indexPath.row];
if ([delegate respondsToSelector:#selector(folderViewDidSelectPlan:)]) {
[delegate folderViewDidSelectPlan:[row objectForKey:#"id"]];
}
}
In my iPad's MainView I'm displaying this UITableView via UIPopoverController:
#interface ProjectViewController ()<folderDelegate>
...
- (void) selectPlan:(UIBarButtonItem*)sender
{
if([self->popoverSelectPlanController isPopoverVisible]){
[self->popoverSelectPlanController dismissPopoverAnimated:YES];
}
FolderViewController *folder = [[FolderViewController alloc] initWithStyle:UITableViewStyleGrouped withInstallation:self->_installationId withProjectId:self->_projectId withParentFolderId:#""];
folder.delegate = self;
UINavigationController *folderNavView = [[UINavigationController alloc] initWithRootViewController:folder];
self->popoverSelectPlanController = [[UIPopoverController alloc] initWithContentViewController:folderNavView];
[self->popoverSelectPlanController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
And handling the delegate via:
- (void) folderViewDidSelectPlan:(NSString *)planId
{
NSLog(#"called");
}
However, folderViewDidSelectPlan never get's called - I'm really stuck here, hope anyone has an idea how to solve this.
Thanks a lot!
Try to change declaration of the property to:
#property (assign) id<folderDelegate> delegate;
And also use self.delegate instead of in your UITableViewController.m file every time instead of just delegate.
If you don't have to support iOS4 or less remove synthesise from UITableViewController.m.

my protocol isn't working

i've been trying to implement this protocol for several hours and it doesn't seem to work for some reason. Basically i have a split view which has a view controller and a table controller, one class holds these two together. The main class creates an instance of the table and runs perfectly, but if i select a cell i want the view controller to react. So i wanted to create a protocol for when a table cell is selected it will do something in the main class.
TableSplitViewController, this is the main class:
#interface TableSplitViewController : UIViewController <updateView>
{
ChildrenTableViewController *firstController;
IBOutlet UITableView *firstTable;
IBOutlet UITableViewCell *tablecell;
NSString *name;
}
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) IBOutlet UILabel *childnamelabel;
#end
THis is the TableSplitViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
if (firstController == nil) {
firstController = [[ChildrenTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
}
[firstTable setDataSource:firstController];
[firstTable setDelegate:firstController];
firstController.view = firstController.tableView;
// Do any additional setup after loading the view.
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowChildrenDetails"]) {
ChildrenDetailViewController *detailViewController = [segue destinationViewController];
NSIndexPath *myIndexPath = [firstController.tableView indexPathForSelectedRow];
detailViewController.childrenDetailModel = [[NSArray alloc]
initWithObjects: [firstController.childname objectAtIndex:[firstController.index row]], nil];
}
}
- (void) setNameLabel:(NSString *)sender
{
// self.name = sender;
NSLog(#"ran");
}
This is the ChildrenTableViewController.h:
#protocol updateView <NSObject>
#required
- (void) setNameLabel:(NSString *)sender;
#end
#interface ChildrenTableViewController : UITableViewController
{
NSIndexPath *index;
id <updateView> delegate1;
}
#property (nonatomic, strong) NSMutableArray *childname;
#property (nonatomic, strong) NSIndexPath *index;
#property (retain) id delegate1;
#end
This is the critical part of ChildrenTableViewController.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[self delegate1] setNameLabel:[self.childname objectAtIndex:[indexPath row]]];
NSLog(#"rannn");
As you can see in the last code i'm trying to call the method using the protocol function. It doesn't seem to work for some reason, i've put in NSLOG and it doesn't even run the setNameLabel method at all. :( Will appreciate any help offered :)
In the code above I cant see you setting the delegate as so:
- (void)viewDidLoad
{
[super viewDidLoad];
if (firstController == nil) {
firstController = [[ChildrenTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
}
[firstTable setDataSource:firstController];
[firstTable setDelegate:firstController];
firstController.view = firstController.tableView;
// Set up the delegate for the controller
[firstController setDelegate1:self];
// Do any additional setup after loading the view.
}
Also, the delegate property should usually be (weak) rather than (retain).

Delegate not working when selecting row on UITableView

I have a UITableView, which when I select a row, I want to segue to another view, where the details of the tank are displayed... The segue happens, but the delegate does not send the object etc over... I think I have my knickers in a twist over where the delegate is declared/synthesized and implemented etc...
Here is where I declare the delegate in the header file of the UITableViewController:
#class iTanksV2ListViewController;
#protocol iTanksV2ListViewControllerDelegate
- (void) iTanksListViewController:(iTanksV2ListViewController *) sender choseTank:(tank *)tank;
#end
#interface iTanksV2ListViewController : UITableViewController
#property (weak, nonatomic) id <iTanksV2ListViewControllerDelegate> delegate;
#end
and this is what I have in the UITableViewControllers m file:
#implementation iTanksV2ListViewController
#synthesize delegate = _delegate;
- (void)viewDidLoad
{
[super viewDidLoad];
self.tankTableView.delegate = self;
self.tankTableView.dataSource = self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedTank = [self.tanks objectAtIndex:indexPath.row];
[self.delegate iTanksListViewController:self choseTank:self.selectedTank];
}
...and then here is the code I have for the delegate in the DetailViewController implementation file...
#interface tankDetailViewController () <iTanksV2ListViewControllerDelegate>
#end
-(void)iTanksListViewController:(iTanksV2ListViewController *)sender choseTank:(id)tank
{
self.tankToShow = tank;
}
All the other variables etc are declared, I have left them out in the hope it makes things clearer - the code compiles, and the segue happens but the delegate doesn't seem to do anything!!!
You mention segues so I'm assuming you're using a storyboard. If that's true, forget about delegates for this purpose. A delegate is supposed to be an object that performs some action for another but all you need is data transfer.
I suggest using the prepareForSeque: method instead in your iTanksV2ListViewController class. Keep the line that sets self.selectedTank when a row is tapped but then put something like this in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
tankDetailViewController *next = (tankDetailViewController *)[segue destinationViewController];
next.tankToShow = self.selectedTank;
}

Resources