So I have 3 views as follows: viewController >> viewController2 >> viewController3.
In viewController3 I have created a Delegate Protocol. The protocol method is a simple method that prints out an NSLog.
When I call the delegates from ViewController3, only its parent (viewController2 ) responds not the (first) viewController. There are no errors.I think problem has got something to do with [v2 setDelegate:self]; in the viewController.m file.
Nevertheless,[self.v3 setDelegate:self]; works fine in ViewController2.m file.
Why does the (first) viewController delegate not respond ? Do delegates only work with its immediate child ??
> **ViewController.h**
#import <UIKit/UIKit.h>
#import "ViewController2.h"
#import "ViewController2.h"
#interface ViewController : UIViewController <PassData>{
ViewController2 *v2;
}
#property (strong, nonatomic) ViewController2 *v2;
> Blockquote
- (IBAction)button:(id)sender;
#end
> **ViewController.M**
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize v2;
- (IBAction)button:(id)sender {
v2 = [[ViewController2 alloc]initWithNibName:#"ViewController2" bundle:nil];
[v2 setDelegate:self];
[self.view addSubview:v2.view];
}
-(void)print: (BOOL)success;{
if (success == YES) {
NSLog(#"ViewController called");
}
}
#end
> > ViewController2.h
#import <UIKit/UIKit.h>
#import "ViewController3.h"
#interface ViewController2 : UIViewController <PassData> {
ViewController3 *v3;
}
#property (strong, nonatomic)ViewController3 *v3;
#property (retain) id delegate;
- (IBAction)button:(id)sender;
#end
ViewController2.m
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
#synthesize v3,delegate;
- (IBAction)button:(id)sender {
v3 = [[ViewController3 alloc]initWithNibName:#"ViewController3" bundle:nil];
[self.v3 setDelegate:self];
[self.view addSubview:v3.view];
}
-(void)print: (BOOL)success;{
if (success == YES) {
NSLog(#"ViewController2 called");
}
}
#end
> ViewController3.h
#import <UIKit/UIKit.h>
#protocol PassData <NSObject>
#required
-(void)print:(BOOL)success;
#end
#interface ViewController3 : UIViewController {
id<PassData> delegate;
}
#property (retain) id delegate;
- (IBAction)callButton:(id)sender;
#end
ViewController3.m
#import "ViewController3.h"
#interface ViewController3 ()
#end
#implementation ViewController3
#synthesize delegate;
- (IBAction)callButton:(id)sender {
// call all delegates
[[self delegate]print:YES];
}
#end
v2 doesn't have a method "print", that's a protocol method of v3 -- you can't chain delegate messages like this. If you want multiple controllers to respond to something in another controller, then you should use an NSNotification -- any number of objects can register to receive a notification.
Related
I know there are tons of questions out there about passing messages between different view controllers. I've checked them all but I can't get it working.
I've followed this tutorial: http://www.youtube.com/watch?v=XZWT0IV8FrI replacing the storyboard with a navigation controller but I run across the following issue over and over again: 'Cannot find protocol declaration for...'
Here is the code:
FirstViewController.h
#import "SecondViewController.h"
#interface FirstViewController : UIViewController <SecondViewControllerDelegate>{
//In this line above is where I get the error 'Cannot find protocol declaration for SecondViewControllerDelegate'
IBOutlet UITextField *userNameTextField;
}
#property (nonatomic, strong) UITextField *userNameTextField;
-(IBAction)goNext:(id)sender;
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize userNameTextField;
-(void)goNext:(id)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
secondVC.delegate = self;
[self.navigationController pushViewController:secondVC animated:YES];
}
-(void)done:(NSString*)name{
NSLog(#"BACK in firstVC");
userNameTextField.text = name;
}
#end
SecondViewController.h
#import "FirstViewController.h"
#protocol SecondViewControllerDelegate <NSObject>
-(void)done:(NSString*)someText;
#end
#interface SecondViewController : UIViewController{
IBOutlet UITextField *someText;
IBOutlet UIButton *returnButton;
id delegate;
}
#property (assign, nonatomic) id <SecondViewControllerDelegate> delegate;
#property (strong, nonatomic) UITextField *someText;
-(IBAction)goBack:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize someText;
#synthesize delegate = _delegate;
-(void)goBack:(id)sender{
[self.delegate done:someText.text];
FirstViewController *firstVC = [[FirstViewController alloc]init];
[self.navigationController pushViewController:firstVC animated:YES];
}
#end
In your SecondViewController goBack implementation you are creating a new FirstViewController rather than popping your navigation controller, code should read...
-(void)goBack:(id)sender{
[self.delegate done:someText.text];
[self.navigationController popViewControllerAnimated:YES];
}
And also in your SecondViewController.h remover this #import "FirstViewController.h" as it is no longer needed and could be confusing the compiler
Your protocol name is EYSSecondViewControllerDelegate:
#protocol EYSSecondViewControllerDelegate <NSObject>
but you call it SecondViewControllerDelegate in two places:
#interface EYSFirstViewController : UIViewController <SecondViewControllerDelegate>{...
#property (assign, nonatomic) id <SecondViewControllerDelegate> delegate;...
Make sure that the name match and it should works fine.
In SecondViewController.h
remove line id delegate;
In SecondViewController.m
Update code -> [delegate done:someText.text];
'self.' remove
Try it
Hi in this code the protocol RefreshLibraryDropBoxDelegate doesn't work, doesn't call the method refreshLibrary in the WVdALibraryDocumentViewController. Why?
WVdADropboxViewController.h:
#import <UIKit/UIKit.h>
#import <DropboxSDK/DropboxSDK.h>
#protocol RefreshLibraryDropBoxDelegate <NSObject>
#optional
-(void)refreshLibrary;
#end
#interface WVdADropboxViewController : UIViewController <DBRestClientDelegate, UITableViewDataSource, UITableViewDelegate>
{
id <RefreshLibraryDropBoxDelegate> delegate;
}
//delegate
#property (assign) id <RefreshLibraryDropBoxDelegate> delegate;
WVdADropboxViewController.m:
- (void)restClient:(DBRestClient *)client loadedFile:(NSString *)destPath
{
NSLog(#"upload complete");
[self.delegate refreshLibrary];
[[self navigationController] popViewControllerAnimated:YES];
}
WVdALibraryDocumentViewController.h:
#import <UIKit/UIKit.h>
#import "WVdACustomCell.h"
#import "WVdAViewController.h"
#import <QuartzCore/QuartzCore.h>
#import "WVdADropboxViewController.h"
#interface WVdALibraryDocumentViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate, RefreshLibraryDropBoxDelegate>
-(void)refreshLibrary;
WVdALibraryDocumentViewController.m:
// REFRESH LIBRARY //
-(void)refreshLibrary
{
NSLog(#"refresh");
[self getDataArrayDocumentFiles];
}
You do not need this line
{
id <RefreshLibraryDropBoxDelegate> delegate;
}
Then, in WVdALibraryDocumentViewController
you need to set in viewDidLoad, or somewhere else
WVdADropboxViewController *myCoolController = [WVdADropboxViewController new];
myCoolController.delegate = self;
It should work!
I guess you for get to set the delegate inside your WVdALibraryDocumentViewController.m.
In your viewDidLoad in WVdALibraryDocumentViewController:
wVdADropboxViewController.delegate = self;
I am trying to set up a system of ViewControllers and navigate between them. I am trying to navigate between DefaultViewController and CreateViewController. I am new to iOS programming, so I am having a hard time figuring this out. I have mainly been trying to use code from the Utility App template. It would be great if someone could spot my mistake!
The log CreateViewController: cancel is reached when I click on my Cancel-button, but DefaultViewController: createViewControllerDidFinish is not.
This is the relevant code:
DefaultViewController.h
#import <UIKit/UIKit.h>
#import <Social/Social.h>
#import "CreateViewController.h"
#interface DefaultViewController : UIViewController <CreateViewControllerDelegate, UIWebViewDelegate> {
...
}
#property (strong, nonatomic) UIWebView *webView;
- (IBAction)create:(id)sender;
#end
CreateViewController.h
#import <UIKit/UIKit.h>
#import <Social/Social.h>
#class CreateViewController;
#protocol CreateViewControllerDelegate
- (void)createViewControllerDidFinish:(CreateViewController *)controller;
#end
#interface CreateViewController : UIViewController <UIWebViewDelegate> {
...
}
#property (weak, nonatomic) id <CreateViewControllerDelegate> delegate;
- (IBAction)cancel:(id)sender;
- (IBAction)submit:(id)sender;
#end
DefaultViewController.m
#import "AppDelegate.h"
#import "DefaultViewController.h"
...
#implementation DefaultViewController
...
#pragma mark - CreateViewController
- (void)createViewControllerDidFinish:(CreateViewController *)controller {
NSLog(#"DefaultViewController: createViewControllerDidFinish");
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)create:(id)sender {
CreateViewController *vc2 = [[CreateViewController alloc] init];
[self.navigationController pushViewController:vc2 animated:YES];
}
#end
CreateViewController.m
#import "AppDelegate.h"
#import "CreateViewController.h"
...
#implementation CreateViewController
...
#pragma mark - Actions
- (IBAction)cancel:(id)sender {
NSLog(#"CreateViewController: cancel");
[self.delegate createViewControllerDidFinish:self];
}
- (IBAction)submit:(id)sender {
[webView stringByEvaluatingJavaScriptFromString:#"EntryCreate.submit();"];
}
#end
Using Navigation Controller,when you push a view controller you have to pop to dismiss
- (IBAction)cancel:(id)sender {
NSLog(#"CreateViewController: cancel");
[self.navigationController popViewControllerAnimated:YES];
}
No need for the controller instance Nav Controller is basically a stack and when you pop it removes from the top of the stack and move to the previous viewcontroller from where it is pushed.
I'm trying to access some things from another viewcontroller (iOS).
I have my ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITextFieldDelegate> {
...
}
#end
ViewController.m:
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
ViewController2.someVar = #"cakes"; // this is where I'm trying to set something in vc2
}
ViewController2.h:
#import <UIKit/UIKit.h>
#interface ViewController2 : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate>
{
...
}
#property (nonatomic, copy) NSString *someVar;
#end
ViewController2.m:
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
#synthesize someVar;
etc.
But at the line where I try to access this var, it gives me the following error:
Property 'someVar' not found on object of type 'ViewController2'.
In what way would I achieve accessing this other view controller?
You have to create a ViewControlle2 object in your Viewcontroller.m.
ViewController2 *myVC2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
myVC2.someVar = #"cakes";
Another way to do this is by using delegates. If you created ViewController1 in AppDelegate, you should also create ViewController2 in AppDelegate, or where ever you create your ViewControllers. Then you ViewController1 would send a message to AppDelegate to get the data from ViewController2 and vice versa. This makes ViewController1 and ViewController2 no longer dependent on each other.
So in AppDelegate.h we'd have something like this
#interface AppDelegate : NSObject <MyViewControllerDelegate>
#property (nonatomic) ViewController1 *viewController1;
#property (nonatomic) ViewController2 *viewController2;
#end
Then in both view controllers you can add this line in the .h
#property (nonatomic) id<MyViewControllerDelegate> delegate;
This just gives us a variable to use to refer to the delegate from within the ViewController's .m
You also need to create the MyViewControllerDelegate protocol, so in a file called MyViewControllerDelegate.h
#protocol MyViewControllerDelegate
- (ViewController1 *) viewController1;
- (ViewControlelr2 *) viewController2;
#end
Then when you create the ViewControllers in AppDelegate.m, you should also set AppDelegate as the ViewController's delegate.
self.viewController1 = [[ViewController1 alloc] init];
self.viewController1.delegate = self;
self.viewController2 = [[ViewController2 alloc] init];
self.viewController2.delegate = self;
So with all of this delegate set up done, you should be able to access viewController2.someVar from viewController1 through the delegate by using:
self.delegate.viewController2.someVar = #"Cakes";
Hope this isn't too long winded.
i try a simple Delegate but the method won't fire. Here is my code:
The view with the protocol and a button which should trigger the delegate:
ViewController.h
#import <UIKit/UIKit.h>
#protocol InitStackDelegate <NSObject>
#required
-(void)initstack:(NSInteger)amount;
#end
#interface ViewController : UIViewController{
IBOutlet UITextField *amountTextField;
__unsafe_unretained id<InitStackDelegate> delegate;
}
- (IBAction)init:(id)sender;
#property (nonatomic,assign)id delegate;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize delegate;
- (IBAction)init:(id)sender {
//send the delegate
[delegate initstack:[amountTextField.text intValue]];
}
AppDelegate.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate,InitStackDelegate> {
}
#property (strong, nonatomic) UIWindow *window;
#property (strong,nonatomic) ViewController *myView;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window;
#synthesize myView;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
// Override point for customization after application launch.
//..... push second controller into navigation stack
myView.delegate = self;
return YES;
}
...
#pragma mark Delegate Method
-(void)initstack:(NSInteger)amount{
NSInteger test;
}
#end
When i hit the button i get to (IBAction) init but then the delegate do nothing. I set a breakpoint in AppDelegate.m but it is never reached. Any help?
thx
Mario
In you App Delegate, when you set myView.delegate=self myView doesn't actually point to anything!
You need to set myView to point to your ViewController.
Use this in didFinishLaunchingWithOptions
myView = (ViewController *)self.window.rootViewController;
myView.delegate = self;