I have two view controllers called DataPass and ViewController. I want to pass a data from DataPass to ViewController. I have a label in ViewController and I have a UIButton in my ViewController which will dismiss itself and while dismissing will pass a data to label in DataPass.
I could not do it. Please help. Here is my code:
ViewController.h
#interface ViewController : UIViewController
- (IBAction)sayfaGec:(id)sender;
#property (retain, nonatomic) IBOutlet UILabel *label;
+(ViewController *)hop;
ViewController.m
+(ViewController *)hop{
static ViewController *myInstance = nil;
if (myInstance == nil){
myInstance = [[[self class]alloc]init];
myInstance.label.text = #"test";
}
return myInstance;
}
DataPass.h
- (IBAction)sayfaKapat:(id)sender;
DataPass.m
- (IBAction)sayfaKapat:(id)sender {
[ViewController hop].label.text = #"ddsg";
[self dismissModalViewControllerAnimated:YES];
}
ViewController.h
- (void)setLabelData:(NSString:)aString;
ViewController.m
- (void)setLabelData:(NSString:)aString{
[yourLabel setText:aString];
}
In your DataPass you say:
ViewController *vContr = [[ViewController aloc]init];
[vContr setLabelData: #"asta la vista baby!"];
[self.view addSubview:vContr.view];
Related
the purpose: write some html code in viewcontroller1's text field press button, the result is shown in webview in viewcontroller2
This is what i've written so far
#import <UIKit/UIkit.h>
#import <Foundation/Foundation.h>
#interface vc1 : UIViewController
#property (weak, nonatomic) IBOutlet UIButton * btn;
#property (weak, nonatomic) IBOutlet UITextField * tf;
the text field can be just a standard one, all i need to do is make sure
that when the user hits the button the vc2 comes up and in it's HTML section
is a string that i got from the textfield
the method responsible for this action is mentioned below
-(IBAction) btnAction : (id) sender;
#end
#interface vc2 : UIViewController
#property (weak, nonatomic) IBOutlet UIWebView * wv;
#end
//didn't find standard implementation for vc1
//attempted implementation for vc1
#implementation vc1
#synthesize btn, tf;
-(id) initWithNibName: (NSString *)nibName0rNil bundle: (NSBundle *)nibBundle0rNil{
self = [super initWithNibName: nibName0rNil bundle: nibBundle0rNil];
if(self){
//custom init
}
return self;
}
-(IBAction) btnAction : (id) sender {
//initialize vc2? it's a class so i can't call it.
//can i save the contents of the object as a NSString? or can i just give the Webview a textfield object to show as HTML?
}
#end
#implementation vc2
#synthesize wv;
-(id) initWithNibName: (NSString *)nibName0rNil bundle: (NSBundle *)nibBundle0rNil{
self = [super initWithNibName: nibName0rNil bundle: nibBundle0rNil];
if(self){
//custom init
}
return self;
}
-(void)viewDidLoad{
[super viewDidLoad];
this is where i am supposed to tell it to take the text from vc1 and display it as HTML
[wv loadHTMLString:#"<html><body>YOUR-TEXT-HERE</body></html>" baseURL:nil]
something of the sort but the string is replaced with what was inserted into vc1's text field
}
-(void)viewDidUnload{
[self setWebview: nil];
[super viewDidUnload];
}
-(BOOL)shouldAutorotateToTinterfaceOrientation:(UIInterfaceOrientation)interfaveOrientation{
return interfaceOrientation == UIInterfaceOrientationPortrait;
}
#end
Edit: thank you for posting, this community has been very helpful.
In Interface of vc2.h declare a property like
#property (strong, nonatomic) NSString *htmlString;
In vc1.h file or vc1.h add
#import "vc2.h"
Now in the Button Action Use the following code:
-(IBAction) btnAction : (id) sender {
//initialize vc2? it's a class so i can't call it.
//can i save the contents of the object as a NSString? or can i just give the Webview a textfield object to show as HTML?
//With Xib
vc2 *secondVC =[[vc2 alloc]initWithNibName:#"vc2" bundle:nil];
secondVC.htmlString = self.tf.text;//textField property name
[self.navigationController pushViewController:secondVC animated:YES];
}
Finally to display the WebView in vc1.m use :
NSString *myHTMLString = [[NSString alloc] initWithFormat:#"%#", self.htmlString];
[self.wv loadHTMLString:myHTMLString baseURL:nil];
Hope this helps. Please let me know in case of any specific errors.
In Swift
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
secondViewController.myStringValue = myTextField.text
self.navigationController?.pushViewController(secondViewController, animated: true)
Load the webview in the secondViewController's viewDidload method
AddBillViewController.h:
#protocol AddBillDelegate <NSObject>
- (void)addBillViewControllerDidAddOneBill;
#end
#interface AddBillViewController : UIViewController
#property (retain, nonatomic)id <AddBillDelegate> delegate;
#end
AddBillViewController.m:
- (IBAction)AddBill:(id)sender {
[self.delegate addBillViewControllerDidAddOneBill];
[self dismissViewControllerAnimated:YES completion:nil];
}
HomeViewController.m:
#interface HomeViewController () <AddBillDelegate>
#property (strong, nonatomic)AddBillViewController *abVC;
#end
#implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.abVC = [[AddBillViewController alloc] init];
self.abVC.delegate = self;
}
- (void)addBillViewControllerDidAddOneBill {
NSLog(#"Added a bill.");
}
#end
As you can see, there is button in AddBillViewController, when the button is pressed, addBill method will be called, then the delegate method addBillViewControllerDidAddOneBill in HomeViewController should be called, however in fact, it doesn't.
I think you are not getting the reference right here in this line
self.abVC = [[AddBillViewController alloc] init];
If you are performing a segue, like the AddBillViewController is your next controller, set delegate in performSegue: function
like
AddBillViewController *vc = [segue destinationViewController];
[vc setDelegate:self];
I have two storyboards and each one has its own respective view controller but I need to change the appearance of the second storyboard based on the button pressed in the first view controller.
In the first view controller I have:
// First view controller .h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface FirstViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIButton *LevelOneButton; // tag 0
#property (strong, nonatomic) IBOutlet UIButton *LevelTwoButton; // tag 1
-(IBAction)selectLevel:(UIButton *)sender; // both buttons connected to this method
#property (assign, nonatomic) int levelSelect;
#end
then in the first .m file:
//FirstViewController.m
-(IBAction)selectLevel:(UIButton *)sender {
if (sender.tag == 0) {
_levelSelect = 0;
}
if (sender.tag == 1) {
_levelSelect = 1;
}
}
This code works fine but the problem occurs in the secondViewController that I have. When I try and access the levelSelect property in the SecondViewController I get the errors "Property 'levelSelect' not found on object of type 'FirstViewController'" or "Unexpected identifier levelSelect" or something among those lines. I've tried every single thing I could think of and every question I found on StackOverflow relating to this but none have fixed the problem. Anyone know what I'm doing wrong?
You should be setting the property on the second view controller as you're pushing or segueing.
So in your first view controller it should look something like this:
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController ()
#property (strong, nonatomic) IBOutlet UIButton *levelOne;
#property (strong, nonatomic) IBOutlet UIButton *levelTwo;
#property (assign, nonatomic) int selectedLevel;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.levelOne.tag = 1;
self.levelTwo.tag = 2;
}
- (IBAction)selectLevel:(UIButton *)sender
{
if (sender.tag == 1) {
self.selectedLevel = 1;
} else {
self.selectedLevel = 2;
}
[self performSegueWithIdentifier:#"pushToSecond" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SecondViewController *dest = segue.destinationViewController;
dest.levelSelect = self.selectedLevel;
}
#end
Now, when viewDidLoad gets called on the SecondViewController that property will be set and you can use it. Like so:
#import "SecondViewController.h"
#interface SecondViewController ()
#property (strong, nonatomic) IBOutlet UILabel *levelLabel;
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.levelLabel.text = [#(self.levelSelect) stringValue];
}
#end
Quick Edit, if you're not using segues you can do the same thing by pushing manually. Would look something like:
- (IBAction)selectLevel:(UIButton *)sender
{
if (sender.tag == 1) {
self.selectedLevel = 1;
} else {
self.selectedLevel = 2;
}
SecondViewController *secondVC = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"second"];
secondVC.levelSelect = self.selectedLevel;
[self.navigationController pushViewController:secondVC animated:YES];
}
Im building an app that calls different subviews and lay them over in a main view controller (http://imgur.com/p6l9Oac)
when ever the user clicks a button on the bottom part of the screen (lets call it sliding menu!) the view behind it will disappear and new one will show up.
one of the subviews is Settings , which it have some switches to enable/disable some of the buttons.
in the SettingsViewController.
Ive set a protocol:
#protocol SettingsViewControllerDelegate <NSObject>
#required
-(void)hideCountdownView;
-(void)showCountdownView;
#end
and the interface contains:
#interface SettingsHubViewController : UIViewController
#property (weak, nonatomic) IBOutlet UISwitch *enableCountdown;
#property (nonatomic, assign) id <SettingsViewControllerDelegate> delegate;
#property (weak, nonatomic) IBOutlet UIView *mainView;
#end
and in the Implementation:
- (IBAction)switchAction:(id)sender {
if (!self.enableCountdown.on) {
NSLog(#"The view is Hidden");
[_delegate hideCountdownView];
} else if (self.enableCountdown.on) {
NSLog(#"The view is Shown");
[_delegate showCountdownView];
}
}
You can see i used _delegate to use the show and hide functions, I used NSLog to make sure that Im calling the functions correctly.
in the MainViewController
#import "SettingsHubViewController.h"
#interface MainViewController () <SettingsViewControllerDelegate>
#property (nonatomic, strong) SettingsHubViewController * settingsViewController;
and the Implementation
#implementation MainViewController
-(void)showCountdownView {
self.slidingMainMenuViewController.countdownView.hidden = NO;
NSLog(#"Showing Countdown");
}
-(void)hideCountdownView {
self.slidingMainMenuViewController.countdownView.hidden = YES;
NSLog(#"Hiding Countdown");
}
-(void)viewDidLoad {
[super viewDidLoad];
self.settingsViewController.delegate = self;
self.slidingMainMenuViewController.delegate = self;
}
the problem is that the NSLogs above is not being called at all, can any one help me ?
Thanks
UPDATE: Since i have more that 20 different views that needs to be called, i created this method
- (UIView *) getPresentedMenu:(NSString *) menuIdentifer withMenuTag:(int) menuTag withAViewController:(UIViewController*) menuViewController andMenuDelegate:(id) menuDelegate {
menuViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:Nil] instantiateViewControllerWithIdentifier:menuIdentifer];
menuViewController.view.tag = menuTag;
if (self.viewBeingCalledBySwipe == NO) {
menuViewController.view.frame = CGRectMake(0, menuViewController.view.frame.size.height, menuViewController.view.frame.size.width, menuViewController.view.frame.size.height);
} else if (self.isItRightSwipe == YES) {
menuViewController.view.frame = CGRectMake(-menuViewController.view.frame.size.width, 0, menuViewController.view.frame.size.width, menuViewController.view.frame.size.height);
} else if (self.isItRightSwipe == NO) {
menuViewController.view.frame = CGRectMake(menuViewController.view.frame.size.width, 0, menuViewController.view.frame.size.width, menuViewController.view.frame.size.height);
}
[self.view addSubview:menuViewController.view];
[self addChildViewController:menuViewController];
[menuViewController didMoveToParentViewController:self];
UIView *view = menuViewController.view;
return view;
}
So when ever i need a certain view controller, i just call this function
self.childView = [self getPresentedMenu:#"Settings" withMenuTag:SETTINGS_TAG withAViewController:self.settingsViewController andMenuDelegate:self.settingsViewController.delegate];
but this method is not assigning the delegate
If settingsViewController is an IBOutlet, you have to add IBOutlet to it's declaration and connect it using the storyboard or xib.
#property (nonatomic, strong) IBOutlet SettingsHubViewController * settingsViewController;
But if it's not an Outlet, you have to allocate it before set it's delegate.
self.settingsViewController = [[SettingsHubViewController alloc] init];
self.settingsViewController.delegate = self;
You should also verify that your - (IBAction)switchAction:(id)sender IBAction is correctly connected in the storyboard or xib.
When you initialize your SettingsViewController, make sure that you do it using the storyboard method and not [[SettingsViewController alloc] init].
First set a Storyboard ID directly in your storyboard view:
Then use this to settingsViewController:
self.settingsViewController = [[UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:NULL] instantiateViewControllerWithIdentifier:#"SettingsViewController"];
Replace MainStoryboard_iPhone with your Storyboard name.
Hope that helps!
// If u are using View controller
SettingsHubViewController *settingVC = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"yourStoryBoardIdentifier"];
settingVC.delegate = self;
// If u are using XIB load the NIB after that set the settingVC.delegate = self;
its working for me (I created OverLay view and loaded in main class)
In UINavigationController this is child controller
.h
#protocol childProtocol <NSObject>
-(void)childMethod:(NSArray*)params;
#end
#property (strong, nonatomic) id<childProtocol>childDelegate;
#property (weak, nonatomic) parentVC *pVC;
.m
if([self.childDelegate respondsToSelector:#selector(childMethod:)]) {
[self.childDelegate performSelector:#selector(childMethod:) withObject:self.arry];
}
This is my parent controller
.m
-(void)childMethod:(NSArray *)params {
// some work
}
...
childVC *cVC = [[childVC alloc]init];
cVC.pVC = self;
But childMethod: is not getting called so I searched on internet and got this post
UINavigationControllers: How to pass value to higher (parent?) controller in stack?
I tried to create a weak reference but dont know how to use to make delegate pass data from child to parent?
Try this. Check the sample project attached
ParentViewController.h
#import <UIKit/UIKit.h>
#interface ParentViewController : UIViewController
- (void)passData:(NSString *)strText;
#end
ParentViewController.m
- (IBAction)btnGoToSecondView:(id)sender {
ChildViewController *secondVC = [[ChildViewController alloc] initWithNibName:#"ChildViewController" bundle:nil];
secondVC.delegate = self;
[self presentViewController:secondVC animated:YES completion:nil];
}
- (void)passData:(NSString *)strText {
NSLog(#"Data Passed = %#",strText);
}
ChildViewController.h
#import <UIKit/UIKit.h>
#import "ParentViewController.h"
#class ParentViewController;
#interface ChildViewController : UIViewController
#property(nonatomic, assign) ParentViewController *delegate;
#end
ChildViewController.m
- (IBAction)btnPassDataBack:(id)sender {
if([self.delegate respondsToSelector:#selector(passData:)]) {
[self.delegate passData:#"Hello"];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
Sample Project
This is child controller.h
#protocol childProtocol <NSObject>
-(void)childMethod:(NSArray*)params;
#end
#property (strong, nonatomic) id<childProtocol>childDelegate;
#property (weak, nonatomic) parentVC *pVC;
.m
if([self.childDelegate respondsToSelector:#selector(childMethod:)]) {
[self.childDelegate performSelector:#selector(childMethod:) withObject:self.arry];
}
This is my parent controller.h
#import <UIKit/UIKit.h>
#import "ChildController.h"
#interface perentController : UIViewController < childProtocol >
.m
- (void)childMethod:(NSArray *)params {
// some work
}
EDITED :
And Dont Forget to add childViewOBJ.childDelegate = self; at the time of create ChildViewController's object. such like,
childVC *cVC = [[childVC alloc]init];
cVC.childDelegate = self;
cVC.pVC = self;
[self presentModalViewController:cVC animated:YES];
For More information about How to create/use of Protocol.
First of all, you are not checking for the same selector as you declared in your protocol declaration so it won't respond to that. You declared the method childMethod: whereas you are checking if your childDelegate responds to myMethod: selector which does not so it won't go into the if condition.
Also the parent view controller is missing the implementation the method childMethod: in its .m. Implement that in your parent view controller or it will crash because of not finding the exact selector definition.
Since you are using a UINavigationController, the parent view controller won't be lost till the child view controller exist so the childDelegate property must not be strong unless you intend to hold onto your delegate in child view controller for some reason.