I am trying to send string from Second VC to First VC. I have assigned delegate to first VC and given protocol in second VC but I don't see the method in First VC is being called when Second VC sends some data.
Code
First VC
FirstViewController.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface FirstViewController : UIViewController <cellDelegate>
#end
FirstViewController.m
- (void)printString:(NSString *)string{
NSLog(#"Received string: %#",string);
}
SecondViewController.h
#protocol cellDelegate <NSObject>
- (void)printString:(NSString *)string{
#end
#interface SecondViewController : UIViewController
#property (nonatomic, weak) id <cellDelegate> delegate;
#end
SecondViewController.m
- (IBAction)buttonPressed:(id)sender {
if ([self.delegate respondsToSelector:#selector(printString:)]) {
[self.delegate printString:#"arrow"]];
}
}
Any help is greatly appreciated.
You forgot to do
SecondViewcontroller *vc;
vc.delegate=self;
On first view controller
Maybe you just forgot to assign your secondViewController.delegate to self.
1- In first viewController, before pushing secondViewController, with that SecondViewController instance do:
secondViewController.delegate = self;
I can not comment, so if this does not work out just let me know or share more code.
When you navigate from one VC to Second VC you can set the delegate.
SecondViewcontroller *secondVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewcontroller"];
secondVC.delegate = self;
[self.navigationController pushViewController:secondVC animated:YES];
This code writes on FirstViewController. Hope it helps you.
Related
I have two view controllers in my project ViewController and SecondViewController and my ViewController has a button which performs a popover segue to SecondViewController then in my SecondViewController I have a button which I would like to use to a call a method from ViewController and I assumed it was possible using [self presentingViewController] but that pointer is set to nil so I'm not quite sure how to call a method in the first ViewController inside the SecondViewController after a popover segue.
This is the code for my ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
- (IBAction)dosegue:(id)sender;
-(void)tobecalledfromseguepopover;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
}
-(void)tobecalledfromseguepopover{
NSLog(#"Called from segue popover");
}
- (IBAction)dosegue:(id)sender {
[self performSegueWithIdentifier:#"segueforpopup" sender:self];
}
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface SecondViewController : UIViewController
- (IBAction)returntocaller:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController()
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)returntocaller:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
ViewController* caller = (ViewController*)[self presentingViewController];
if(caller!=nil){
[caller tobecalledfromseguepopover];
}else{
NSLog(#"nil");
}
}];
}
#end
My UI
So any ideas on how I can call tobecalledfromseguepopover inside SecondViewController after the segue? Also is there a way for SecondViewCOntroller to know it's being called from a segue popover?
The usual thing is a delegate architecture. Give the popover a delegate property and set it to self in your prepareForSegue. Now the popover knows where to find the first view controller.
This is often combined with a protocol so that the popover knows the name of the method to be called without worrying about the class of the first view controller, but that part isn’t crucial, especially in Objective C.
I am a newbie to Swift. I have started a new project with Swift. I am trying to add SecondViewcontroller view as a subview to the FirstViewController. What i am looking is to declare the SecondViewController property for the FirstViewController. Can anyone please suggest the Swift version of the below code
FirstViewController.h
#interface FirstViewController : UIViewController {
IBOutlet UIView *listContainerView;
}
#property (nonatomic, strong) SecondViewController *secondVC;
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self.secondVC = (SecondViewController *)[mainStoryBoard instantiateViewControllerWithIdentifier:#"SecondViewController"];
if (![self.secondVC.view isDescendantOfView:self.view]) {
[self addChildViewController:self.secondVC];
self.secondVC.view.frame = CGRectMake(0, 0, listContainerView.frame.size.width, listContainerView.frame.size.height);
[listContainerView addSubview:self.secondVC.view];
[self.secondVC didMoveToParentViewController:self];
}
}
#end
What you should do is to make a subview, instead of making a new UIViewController. In only very special cases would you ever put one UIViewController inside another. Basically every 'screen' should have one UIViewController, but you shouldn't put one inside another.
I have a simple application with the following structure:
'A': Standalone view controller with a WebView
'B': Navigation controller
'C': Root View Controller in 'B', a TableView of all stores
When the URL of the WebView in 'A' becomes something specific (http://www.mysite.com/store), I need to:
Push to 'C'
Send a string to be used in 'C'
How can I achieve this?
Here you can do with delegate methods
// This is your root ViewController to call delegate methods
#import "ThirdViewController.h"
#import "SecondViewController.h"
#interface ViewController ()<ThirdViewControllerDelegate>
#end
#implementation ViewController
#pragma mark -
#pragma mark ThirdViewController Delegate Method
// Implementation of delegate methods in your Root ViewController
-(void)didSelectValue:(NSString *)value{
NSLog(#"%#",value);
}
// Pass the last Vc delegate to the next ViewController
-(void)gotoSeconddVc{
SecondViewController *vc2=[[SecondViewController alloc]init];
vc2.lastDelegate=self;
[self.navigationController pushViewController:vc2 animated:YES];
}
#import "ThirdViewController.h"
#interface SecondViewController : UIViewController
#property(nonatomic,retain) id <ThirdViewControllerDelegate> lastDelegate;
#end
-(void)gotoThirdVc{
ThirdViewController *vc3=[[ThirdViewController alloc]init];
vc3.delegate=self.lastDelegate;
[self.navigationController pushViewController:vc3 animated:YES];
}
Implementation of last viewcontroller
#implementation ThirdViewController
-(void)btnDoneClicked{
[self.navigationController popToRootViewControllerAnimated:YES];
[self.delegate didSelectValue:strValue]; //call delegate methods here
}
Using a storyboard I've set up two different view controllers (A&B) where one of them (B) have a UITextView.
How can I access and change the text in the textview from View Controller A?
The code below doesn't give any errors but the text isn't set, even though the function is called correctly.
If I run [self.desc setText:text]; inside viewDidLoad in ViewControllerB it works.
ViewControllerA.h
#interface ViewControllerA : UIViewController
{
}
#end
ViewControllerA.m
#import "ViewControllerA.h"
#import "ViewControllerB.h"
#interface ViewControllerA ()
#end
#implementation ViewControllerA
- (void)viewDidLoad
{
[super viewDidLoad];
ViewControllerB *bInstance = [[ViewControllerB alloc] init];
[bInstance setDescription:#"this is some new text";
}
#end
ViewControllerB.h
#interface ViewControllerB : UIViewController
{
UITextView *desc;
}
- (void)setDescription:(NSString *) text;
#property (nonatomic, retain) IBOutlet UITextView *desc;
#end
ViewControllerB.m
#import "ViewControllerB.h"
#interface ViewControllerB ()
#end
#implementation ViewControllerB
#synthesize desc;
- (void)setDescription:(NSString *)text{
NSLog(#"called!");
[self.desc setText:text];
}
#end
You should not manipulate another view controller's views, ever. It is bad design in general, and often doesn't work at all (as you've discovered.)
Instead, set up a string property in your second view controller. Set that (in prepareForSegue, if you're using storyboards.)
Then, in your second view controller's viewWillAppear, put the string into the text field.
Do the following:
#interface ViewControllerA : UIViewController
{
UITextView *desc;
#public
ViewControllerB objB;
}
When you launch:
ObjectOfAToLaunch.objB = ObjectOfBToLaunch;
In view did load
- (void)viewDidLoad
{
[super viewDidLoad];
[Objb setDescription:#"this is some new text"];
}
Good Luck.
You can implement prepareForSegue method in the controller that launch A and B.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
UIViewController *vc = [segue destinationViewController];
if ([vc isKindOfClass:ViewControllerB])
{
ObjB = vc; // ObjB is a public member you must declare in interface
if (ObjA!=nil)vc->ObjA = ObjB;
}
if ([vc isKindOfClass:ViewControllerA])
{
ObjA = vc; // ObjA is a public member you must declare in interface
if (ObjB!=nil)vc->ObjA = ObjB;
}
}
}
Good Luck.
bInstance is another instance of the class. not the same one.
In a view, let's call it firstView I created a secondView as follows and pushed it if certain thing happened in the firstView:
SecondViewController *secondVC = [[secondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:secondVC animated:YES];
[secondVC release];
Now when I'm in the secondView if let say a button is pressed I want to go back to firstView and also pass back a value from secondView to the firstView (let say an integer value of a textfield from secondView to the firstView).
Here is what I tried:
#protocol SecondViewControllerDelegate;
#import <UIKit/UIKit.h>
#import "firstViewController.h"
#interface SecondViewController : UIViewController <UITextFieldDelegate>
{
UITextField *xInput;
id <SecondViewControllerDelegate> delegate;
}
- (IBAction)useXPressed:(UIButton *)sender;
#property (assign) id <SecondViewControllerDelegate> delegate;
#property (retain) IBOutlet UITextField *xInput;
#end
#protocol SecondViewControllerDelegate
- (void)secondViewController:(SecondViewController *)sender xValue:(int)value;
#end
And in the m file
- (IBAction)useXPressed:(UIButton *)sender
{
[self.delegate secondViewController:self xValue:1234]; // 1234 is just for test
}
And then in the firstView I did:
#import "SecondViewController.h"
#interface FirstViewController : UITableViewController <SecondViewControllerDelegate> {
}
#end
And implemented:
- (void) secondViewController:(SecondViewController *)sender xValue:(int)value
{
[self.navigationController popViewControllerAnimated:YES];
}
Now, the problem is for one in FirstViewController I get the warning that "No definition of protocol "SecondViewControllerDelegate" is found, and for two the delegate method (last piece of code above) does not get invoked at all. Can somebody please tell me what's wrong?
After this line
SecondViewController *secondVC = [[secondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
Add
secondVC.delegate = self;
Also instead of
- (void) secondViewController:(SecondViewController *)sender xValue:(int)value
{
[self.navigationController popViewControllerAnimated:YES];
}
You should use
- (void) secondViewController:(SecondViewController *)sender xValue:(int)value
{
[sender popViewControllerAnimated:YES];
}
In FirstViewController .h file :
#import "SecondViewController.h"
#interface FirstViewController : UITableViewController <SecondViewControllerDelegate> {
SecondViewController *secondViewController;
}
#end
In implementation file , where you init SecondViewController instance next line assign self to delegate property :
secondViewController.delegate = self;
Next define delegate method :
- (void)secondViewController:(SecondViewController *)sender xValue:(int)value
{
NSLog ("This is a Second View Controller with value %i",value)
}
For problem 1: The #protocol definition for SecondViewControllerDelegate looks like it's in secondViewController.h; are you sure this file is imported in firstViewController.h? Otherwise it won't know about the protocol.
Problem 2: It might be totally unrelated to problem 1. Are you sure the action is hooked up properly? Can you put a NSLog() call in your useXPressed: to make sure that method is actually getting called when you expect it to?