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;
}
Related
On a button press, I am trying to send data from Collection View Controller to my View Controller. Here is what I have so far:
CollectionViewController.h
#import <UIKit/UIKit.h>
#class CollectionViewController;
#protocol CollectionViewDelegate <NSObject>
-(void) sendTest;
#end
#interface CollectionViewController : UICollectionViewController
#property (nonatomic, weak) id<CollectionViewDelegate> deligate;
#end
CollectionViewController.m
-(void) viewDidLoad {
[super viewDidLoad];
}
...
NSLog(#"check");
[self.deligate sendTest];
NSLog(#"called");
FooViewController.m
#import "CollectionViewController.h"
#interface FooViewController () <CollectionViewDelegate> {}
#end
#implementation FooViewController
- (void)viewDidLoad {
[super viewDidLoad];
CollectionViewController *controler = [[CollectionViewController alloc] init];
controler.deligate = self;
}
- (void) sendTest {
NSLog(#"Delegates are great!");
}
Unfortunaly when I call [self.deligate sendTest]; nothing happens. I know it is called, because I get the check, called logs.
The main wrong thing is that you are creating a CollectionViewController yourself, but you shouldn't. The CollectionViewController that you want is instantiated automagically by the Storyboard. How to find this view controller?
1 - Catch it during the segue in FooViewController:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
CollectionViewController *collectionViewController =(CollectionViewController *) segue.destinationViewController;
collectionViewController.deligate = self;
}
2 - Find it in within the child view controllers in FooViewController
self.childViewControllers
Does it help you?
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.
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.
For a project I need to be able to send a status back from "secondTableViewController" to "firstTableViewController". I followed some tutorials on delegates but I don't seem to get it to work. When I want to call the method in firstTableViewController from the secondTableViewController I do a check to see if "delegate" property is empty, and every time it is..
This is my code:
SecondTableViewController.h
#protocol SendStatusDelegate <NSObject>
#required
-(void)didStatusChanged;
#end // eof delegate protocol
#interface SecondTableViewController : UITableViewController
#property (nonatomic, assign) id<SendStatusDelegate> delegate;
#end
SecondTableViewController.m
// Status is changed on row click
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.delegate) { // This is never called because delegate looks to remain empty
[self.delegate didStatusChanged];
}
}
FirstTableViewController.h
#interface FirstTableViewController : UITableViewController <SendStatusDelegate>
#end
FirstTableViewController.m
The only thing that goes on here is implementing the -(void)didStatusChanged method.
First You need to set the delegate to self in FirstTableViewController when you init the SecondTableViewController. say on didSelectRowAtIndexPath: you are calling the SecondTableViewController in that case,
FirstTableViewController.m
// Status is changed on row click
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SecondTableViewController *secondTableVC = [SecondTableViewController alloc] init];
secondTableVC.delegate = self;
}
In the FirstTableViewController where you create the SecondTableViewController instance you should assign the delegate of the created instance to FirstTableViewController
ie
secondTableViewControllerInstance.delegate = self;
in FirstTableViewController
Your FirstTableViewController Class should conform the SendStatusDelegate Like
#interface FirstTableViewController : UITableViewController <SendStatusDelegate>
And then then assign the delegate of SecondViewController instance by self Like
SecondTableViewControllerInstance.delegate = self;
In my second controller when user select a row and after clicked on the back button
I would like to update a UILabel with the text choice.
I have added a UILabel on the first controller and connected to h. file but I don't know how go on
I would like to replicate the GENERAL/AUTO-LOCK function in iPhone/iPad Settings.
You should use delegates for this.
SecondViewController.h:
#protocol SecondViewControllerDelegate;
#interface
...
#property (nonatomic, assign) id <SecondViewControllerDelegate> delegate;
...
#end
#protocol SecondViewControllerDelegate <NSObject>
- (void)secondViewController:(SecondViewController *)vc didTapRowWithText:(NSString *)text;
#end
SecondViewController.m:
#implementation
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self.delegate secondViewController:self didTapRowWithText:cell.yourLabel.text];
}
...
#end
whoever created and pushed SecondViewController (and maybe/hopefully also 1st one):
// put this after secondViewController initialization
secondViewController.delegate = self;
- (void)secondViewController:(SecondViewController *)vc didTapRowWithText:(NSString *)text
{
firstViewController.yourLabel.text = text;
}