I have a UIViewController several segues deep that when the use is finished, should unwind and take them back to the DashboardViewController.
I created the unwindToDashboard method in the Dashboard and hooked a button up to the Exit in my FinishViewController. So that when its clicked will fire the unwind action.
That works fine.
But I need to pass back data to the Dashboard from the FinishViewController.
So I created a delegate ProcessDataDelegate for the FinishViewController and made the Dashboard conform to it.
However, the delegate method in the Dashboard is NOT called.
Can anyone tell me what I have done wrong?
DashboardViewController.m
#import "FinishViewController.h"
#interface DashboardViewController () <ProcessDataDelegate>{
FinishViewController *fm;
}
#end
#implementation DashboardViewController
- (void)viewDidLoad {
[super viewDidLoad];
if(!fm){
fm = [[FinishViewController alloc] init];
}
fm.delegate = self;
}
- (IBAction)unwindToDashboard:(UIStoryboardSegue *)unwindSegue {
//empty
}
#pragma mark PROTOCOL METHODS
-(void) didFinishWithResults:(NSDictionary*) dictionary{
NSLog(#"Dashboard method called didFinishWithResults");
}
#end
FinishViewController.h
#class FinishViewController;
#protocol ProcessDataDelegate <NSObject>
#required
- (void) didFinishWithResults: (NSDictionary*)dictionary;
#end
#interface FinishViewController : UIViewController
#property (nonatomic, weak) id <ProcessDataDelegate> delegate;
#end
FinishViewController.m
#interface FinishViewController ()
#end
#implementation FinishViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(#"fired via the button to the exit--- Segue: %#", [segue identifier]);
[delegate didFinishWithResults:nil ];
}
#end
You need pass your delegate in prepareForSegue method of your DashboardViewController, there get the destinationViewController and cast to FinishViewController if the identifier is equal to your expected segue identifier
Something like this
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(#"fired via the button to the exit--- Segue: %#", [segue identifier]);
if([[segue identifier] isEqualToString:#"YourSegueIdentifier"])
{
((FinishViewController*)[segue destinationViewController]).delegate = self
}
}
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've done tutorials where I pass data through scenes with the prepareForSegue:sender: method, but right now when I try to use the passed data, it's null. I'm using a navigation controller as well.
here's the .h -
#import <UIKit/UIKit.h>
#import "TalkChatTableViewController.h"
#interface CreateChatTableViewController : UIViewController
#end
here's the .m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"idSegueMyChatsToChat"]){
TalkChatTableViewController *tctvc = [segue destinationViewController];
tctvc.chatObjectId = #"test";
NSLog(#"%#", tctvc.chatObjectId);
//succesfully logs out test
}
}
When I log in the above method, it comes out fine. But then when I go to my TalkChatTableViewController class it doesn't log out in viewDidLoad; it's null.
The header to that looks like this:
#import <UIKit/UIKit.h>
#interface TalkChatTableViewController : UITableViewController
#property (nonatomic) NSString * chatObjectId;
#end
and then finally the .m -
#import "TalkChatTableViewController.h"
#implementation TalkChatTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#", self.chatObjectId);
// logs null
}
#end
TalkChatTableViewController * tctvc = (TalkChatTableViewController *)[segue destinationViewController];
This is what winded up working.
I'm just starting to learn Objective-C and I'm not 100% on all the syntax yet, and I think that might be where I'm having trouble, then again I'm not sure. I'm trying to get one view controller to send a message to its parent/callee view controller. I have it set up like this:
//ParentViewController.h
#import "SubViewController.h"
#interface ParentViewController : UIViewController <SubViewControllerDelegate>
- (void) sendMessageToParent:(NSInteger)num;
#end
This is the implementation:
//ParentViewController.m
#implementation ParentViewController
- (void) sendMessageToParent:(NSInteger)num
{
NSLog(#"Message is %d", num);
}
- (void) buttonPushed
{
[self performSegueWithIdentifier:#"SubView" sender:sender];
}
#end
Here's the other view controller setup:
//SubViewController.h
#protocol SubViewControllerDelegate <NSObject>
- (void) sendMessageToParent:(NSInteger)num;
#end
#interface SubViewController : UIViewController
#property (nonatomic, weak) id <SubViewController> delegate;
#end
And implementation:
//SubViewController.m
#implementation SubViewController
#synthesize delegate;
- (void) something
{
[self.delegate sendMessageToParent:4];
[self.dismissViewControllerAnimated:YES completion:nil];
}
Appreciate any help, thanks.
You need to add to ParentViewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"SubView"])
{
SubViewController *vc = [segue destinationViewController];
vc.delegate = self;
}
}
You need to add handler for prepareForSegue and set .delegate properly there. I don't think your SubviewController has delegate set to the parent one.
Looks like you're not setting SubViewController's delegate to SuperViewController. You'd do this typically when you instantiate SubViewController. e.g. subViewController.delegate = self
ParentViewController.h
#interface ParentViewController : UIViewController
#end
ParentViewController.m
#implementation ParentViewController <SubViewControllerDelegate> // Better to place this in .m than .h
#pragma mark - SubViewController Delegate
- (void)sendMessageToParent:(NSInteger)num
{
NSLog(#"Message is %d", num);
}
- (void)buttonPushed
{
[self performSegueWithIdentifier:#"SubView" sender:sender];
}
#end
SubViewController.h
#protocol SubViewControllerDelegate <NSObject>
- (void)sendMessageToParent:(NSInteger)num;
#end
#interface SubViewController : UIViewController
#property (nonatomic, weak) id<SubViewController> delegate;
#end
SubViewController.m
#implementation SubViewController
// #synthesize delegate; // Not necessary, old fashioned
- (void)something
{
// Set a breakpoint here and step through, you're not setting your delegate, so this conditional is not being hit
if (self.delegate && [self.delegate respondsToSelector:#selector(sendMessageToParent:)])
{
[self.delegate sendMessageToParent:4];
}
[self.dismissViewControllerAnimated:YES completion:nil];
}
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 {
}
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;
}