Passing NSString from one viewController to another without IBAction - ios

I am trying to pass an NSString variable from one view controller to the other but I have only been able to find tutorials and information on doing this by the use of a button IBAction but and have not been able to pass it successfully. Are there any easy alternatives without using a button?
#import "DetailController.h"
#import "City.h"
#import "VideoController.h"
#interface DetailController ()
#end
#implementation DetailController
#synthesize city, ClubName, Price, Vip, Promo, remain,p,deal,money,camera,cam;
- (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.
UIFont *labelFont=[UIFont fontWithName:#"Deutsch Gothic" size:20.0];
UIFont *myFont=[UIFont fontWithName:#"Deutsch Gothic" size:30.0];
UIFont *titleFont=[UIFont fontWithName:#"Deutsch Gothic" size:40.0];
NSString * name= self.city.clubName;
NSString * line= self.city.clubLine;
NSString * description= self.city.promo;
NSString * price= self.city.price;
cam=self.city.camera;
remain.font=labelFont;
remain.text=#"VIP Remaining :";
p.font=labelFont;
p.text=#"Price :";
money.font=myFont;
deal.font=labelFont;
deal.text=#"Promotions :";
ClubName.font=titleFont;
ClubName.text=name;
Vip.font=myFont;
Vip.text=line;
Price.font=myFont;
Price.text=price;
Promo.font=labelFont;
Promo.text=description;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I am trying to pass cam or camera to videoController

If you are trying to Push between view controllers than you can create a property in view controller and before pushing view controller set the value.You can do this in following way:-
In View Controller2 declare a property
#property(nonatomic,strong) NSString *passedString;
in View Controller 1 do this
ViewController2 *vc2 = [ViewController2 alloc]initWithNibName:#"ViewController2" bundle:nil];
[vc setPassedString:#"Hello"];
[self.navigationController pushViewController:vc2 animated:YES];

Related

Why the String value is null?

Why the string value is getting null value. Someone please find the error?
How can i fetch the string value when the method is getting called from SecondViewController do i need a another string or someone please suggest some corrections.
I need this string to be have some value
#property (nonatomic,strong) NSString *str;
When the following method is getting called.
[view getTotal];
Label is in the first view controller.
Thanks in advance.
In ViewController.m
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController ()
{
NSInteger total;
}
#property (weak, nonatomic) IBOutlet UILabel *lbl;
#property (weak, nonatomic) IBOutlet UIButton *btn;
#property (nonatomic,strong) NSString *str;
- (id)initWithInitialNumber:(NSInteger)initialNumber;
- (void)addNumber:(NSInteger)newNumber;
- (NSInteger)getTotal;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#",_str);
self.lbl.text = _str;
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(#"viewDidAppear called");
[self viewDidLoad];
}
-(id)initWithInitialNumber:(NSInteger)initialNumber{
total = initialNumber;
return self;
}
-(void)addNumber:(NSInteger)newNumber{
total += newNumber;
}
-(NSInteger)getTotal{
NSLog(#"Number is: %ld",total);
self.str = [NSString stringWithFormat:#"%ld",total];
NSLog(#"%#",self.str);
return total;
}
- (IBAction)btnAct:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SecondViewController *SC = [sb instantiateViewControllerWithIdentifier:#"SC"];
[self presentViewController:SC animated:YES completion:nil];
}
-(NSString *)str{
return _str;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
In SecondViewController.m
#import "SecondViewController.h"
#import "ViewController.h"
#interface SecondViewController ()<Sendata>
{
NSInteger *num;
}
#end
#implementation SecondViewController
- (IBAction)backBtn:(id)sender {
ViewController *VC = [self.storyboard instantiateViewControllerWithIdentifier:#"VC"];
[self presentViewController:VC animated:YES completion:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
ViewController *view = [[ViewController alloc]initWithInitialNumber:10];
view.delegate = self;
[self Print:#"Hello"];
[view addNumber:2];
[view getTotal];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)Print:(NSString *)str{
NSLog(#"%#",str);
}
#end
What I can understand from your code is that you are presenting secondViewController from ViewController on a button click. On Second view controller you want to add two numbers and show them on Firstview controller again.
what I can see from your code , you are pushing the new instance of ViewController every time. So thevalue you are intialising in your view didLoad in diffrent object then the one your pushing again on button action of back. IF you can modify you code like this , it will work :
#interface ViewController ()
{
NSInteger total;
}
#property (weak, nonatomic) IBOutlet UILabel *lbl;
#property (weak, nonatomic) IBOutlet UIButton *btn;
#property (nonatomic,strong) NSString *str;
- (id)initWithInitialNumber:(NSInteger)initialNumber;
- (void)addNumber:(NSInteger)newNumber;
- (NSInteger)getTotal;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#",_str);
self.lbl.text = _str;
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(#"viewDidAppear called");
[self viewDidLoad];
}
-(id)initWithInitialNumber:(NSInteger)initialNumber{
total = initialNumber;
return self;
}
-(void)addNumber:(NSInteger)newNumber{
total += newNumber;
}
-(NSInteger)getTotal{
NSLog(#"Number is: %ld",total);
self.str = [NSString stringWithFormat:#"%ld",total];
NSLog(#"%#",self.str);
return total;
}
- (IBAction)btnAct:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SecondViewController *SC = [sb instantiateViewControllerWithIdentifier:#"SC"];
[self.navigationController pushViewController:SC animated:YES];
}
-(NSString *)str{
return _str;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
#interface SecondViewController ()
{
NSInteger *num;
ViewController *viewController;
}
#end
#implementation SecondViewController
- (IBAction)backBtn:(id)sender {
[self.navigationController popViewControllerAnimated:YES]
}
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *VCs = [NSMutableArray arrayWithArray: self.navigationController.viewControllers];
if ([[VCs objectAtIndex:[VCs count] - 2] isKindOfClass:[ViewController class]])
{
ViewController *view = [[VCs objectAtIndex:[VCs count] - 2]
view.delegate = self;
[self Print:#"Hello"];
[view addNumber:2];
[view getTotal];
}
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)Print:(NSString *)str{
NSLog(#"%#",str);
}
#end
I have taken the instance of ViewController already present in navigation stack , changed the values and on back I have pop out the SecondViewController.

How to pass value from subclass to super class during initialization

Suppose, I've two view controller. ViewController1 is the sub class of ViewController2. From subclass (ViewController1), I called superclass init method & passed a value by parameter & assigned that value to the superclass variable. But In superclass (ViewController2)'s viewDidLoad method, that value is always null. Why ? How can I pass that value from sub to super so that I can get that value in super class's viewDidLoad method ?
ViewController1.h
#interface ViewController : ViewController2
#end
ViewController1.m
#implementation ViewController
- (instancetype)init
{
self = [super initWithName:#"Hello"];
if (self) {
NSLog(#"1 :");
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
ViewController2.h
#interface ViewController2 : UIViewController
#property (nonatomic, strong) NSString *name;
-(instancetype)initWithName:(NSString *)name;
#end
ViewController2.m
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
self.name = name;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(#"2 : %#", self.name);
}
#end
I tired your code and it worked just fine. I suspect, that you don't instantiate your ViewController directly. Do you use storyboard in your project? If yes - you should override initWithCoder: in ViewController.
However, it is bad idea to set any properties of view controllers during init-family methods. According to Apple recommendations, all customisation should be done in -viewDidLoad or -viewWill/DidAppear methods.
If you absolutely in need to set name property from outside, it is better you assign it directly, not trough passing argument to init method.
One more thing - initWithNibName:bundle: is Designated initializer. It means, that your subclasses absolutely must in the end call it during initialisation chain.
Updated - 16-Mar-2016
Example :
ViewController1.h
#import <UIKit/UIKit.h>
#import "ViewController2.h"
#interface ViewController1 : ViewController2
#end
ViewController1.m
#import "ViewController1.h"
#interface ViewController1 ()
#end
#implementation ViewController1
-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
//self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil andUserName:#"Ramesh Annadurai"];
// we can use above init method or below method, both will work
self = [super initWithName:#"Test Name"];
if (self) {
[self.view setBackgroundColor:[UIColor brownColor]];
}
return self;
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
//self = [super initWithCoder:aDecoder];
// If you are using storyboard use this initWithCoder method.
self = [super initWithName:#"Test Name"];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
ViewController2.h
#import <UIKit/UIKit.h>
#interface ViewController2 : UIViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString *) userName;
- (instancetype)initWithName:(NSString *) userName;
#end
ViewController2.m
#import "ViewController2.h"
#interface ViewController2 ()
#property (strong, nonatomic) NSString *userName;
#end
#implementation ViewController2
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString *) userName
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.userName = userName;
}
return self;
}
- (instancetype)initWithName:(NSString *) userName
{
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.userName = userName;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"User Name : %#", self.userName);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end

Performing method on another UIViewController

I am using following code to set the text of a UILabel in SViewController, From another ViewController FViewController
SViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"SViewController"];
[vc setTextForLabel:[NSNumber numberWithInt:1];];
[self.navigationController pushViewController:vc animated:YES];
The setTextForLabel method:
-(void) setTextForLabel: (NSNumber *)text {
textLabel = [[UILabel alloc] init];
[textLabel setText:[NSString stringWithFormat:#"%#",[text stringValue]]];
NSLog(#"The text is %#", textLabel.text);
}
I have declared the property for textLabel in .h file is as follows:
#property (nonatomic, retain) IBOutlet UILabel *textLabel;
And I have also set the IBOutlet in storyboard.
Now in console I see "The text is 1", but the UI is not showing anything!
What am I doing wrong?
remove this line
textLabel = [[UILabel alloc] init];
Also, you need to link the UILabel on interface to your #property (nonatomic, retain) IBOutlet UILabel *textLabel;
Or you may add this label manually to view
textLabel = [[UILabel alloc] init];
[textLabel setText:[NSString stringWithFormat:#"%#",[text stringValue]]];
[self.view addSubView:textLabel];
First of all go put
[vc setTextForLabel:[NSNumber numberWithInt:1]];
after you push the vc.
In your xib/storyboard if your label has something written in it, remove it, leave it blank.
If that doesn't work ... leave the setText method before the push one (as you wrote it initialy) and create a NSNumber member that will hold your value and apply it in viewDidAppear like so
-(void) setTextForLabel: (NSNumber *)text{
numberValue = text; // declared in .h as NSNumber *numberValue (only make it a property if you need acces to it from outside your class)
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated]; //this is important
[textLabel setText:[NSString stringWithFormat:#"%#",[numberValue stringValue]]];
}
Your problem is linked to the view lifecycle of SViewController. When you call [.. setTextForLabel] you don't know if the controller has loaded its views (And thus your UILabel have a good chance of not being created yet)
What you should do is use a NSString property on your controller, set it with the desire text and assigned it to the UILabel in the viewDidLoad of SViewController.
in SViewController.h
#propery (strong, nonatomic) NSString *textToDisplay;
in SViewController.m
-(void)viewDidLoad
{
[super viewDidLoad];
// Here you know all Outlet are loaded and connected
textLabel.text = textToDisplay
}
I did like this
#import "FViewController.h"
#import "SViewController.h"
#interface FViewController ()
#end
#implementation FViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)do:(id)sender
{
SViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"SViewController"];
[self.navigationController pushViewController:vc animated:YES];
[vc setTextForLabel:[NSNumber numberWithInt:1]];
}
// in SViewController.h
#import <UIKit/UIKit.h>
#interface SViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *label;
-(void) setTextForLabel: (NSNumber *)text;
#end
// SViewController.m file
#import "SViewController.h"
#interface SViewController ()
#end
#implementation SViewController
#synthesize label;
- (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.
}
-(void) setTextForLabel: (NSNumber *)text{
// label.text = [text stringValue];
NSLog(#"%#",label);
[label setText:[text stringValue]];
}
#end
also check your label properties in storyboard are properly set

Sending information from a view controller to another

The question is, I have 9 buttons on viewcontroller (ViewController), and i have an outlet collection for storing all these buttons outlet.
Then i have an action method for handling click event of these buttons.
What I want is send the button image background (as an UIImage * img)of the CLICKED button, segue to another viewcontroller (vc2),
here are my code :
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardBtns;
- (IBAction)cardAction:(id)sender;
#end
#import "ViewController.h"
#import "ResultViewController.h"
#interface ViewController ()
#property(strong,nonatomic)UIImage *image;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cardAction:(id)sender {
for(UIButton *cardButton in self.cardBtns){
self.image = [cardButton currentBackgroundImage];
}
[self performSegueWithIdentifier:#"cardSegue" sender:self.image];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
//UIImage * img = [UIImage imageNamed:#"f1"];
UIImage * img = (UIImage *)sender;
ResultViewController *viewcontroller = [segue destinationViewController];
viewcontroller.img = img;
}
#end
in vc2, i have another button here, and i wish to paint this button background img with the img just sent from vc1 segue.
#interface ResultViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *cardBtn;
#property(strong,nonatomic)UIImage *img;
- (IBAction)cardDismiss:(id)sender;
#end
#import "ResultViewController.h"
#interface ResultViewController ()
#end
#implementation ResultViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.cardBtn setImage:self.img forState:UIControlStateNormal];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cardDismiss:(id)sender {
[self dismissViewControllerAnimated:NO completion:nil];
}
#end
assume my buttons is 1,2,3,4,5,6,7,8,9
for now, whatever buttons i clicked in vc1, it s always displaying as '6' in vc2...
any suggestions? thanks
The problem is this:
- (IBAction)cardAction:(id)sender {
for(UIButton *cardButton in self.cardBtns){
self.image = [cardButton currentBackgroundImage];
}
[self performSegueWithIdentifier:#"cardSegue" sender:self.image];
}
This will set self.image to the last item in self.cardBtns. You want to set self.image to sender.currentBackgroundImage (and change id in the argument type to UIButton *), and just eliminate the loop.

cannot set the text of label in DetailViewController after passing data between different viewController

pass data from FirstViewController to DetailViewController. i can not set the text of label in DetailViewController; FirstViewController is a tableview and it is good.
i use method updateRowNumber to set the rowNumber . and in DetailViewController, i can use debugger to see the rowNumber is correct. but the label's text is not showed on the view.
anyone can help me out?
in my FirstViewController
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (dvController == nil)
{
DetailViewController *aController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
self.dvController = aController;
[aController release];
}
[[self navigationController] pushViewController:dvController animated:YES];
[dvController updateRowNumber:indexPath.row];
}
in my DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
{
int rowNumber;
IBOutlet UILabel *message;
}
#property(readwrite) int rowNumber;
#property(nonatomic, retain) IBOutlet UILabel *message;
- (void) updateRowNumber:(int) theindex;
#end
in my DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#synthesize message, rowNumber;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void) updateRowNumber: (int) theindex
{
rowNumber = theindex + 1;
message.text = [NSString stringWithFormat:#"row %i was clicked", rowNumber];
}
- (void)dealloc
{
[message release];
[super dealloc];
}
- (void)viewDidLoad
{
message.text = [NSString stringWithFormat:#"row %i was clicked ", rowNumber];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Do any additional setup after loading the view from its nib.
}
- (void)viewWillAppear:(BOOL)animated
{
//message.text = [NSString stringWithFormat:#"row %i was clicked ", rowNumber];
[super viewWillAppear: animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear: animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You'll need to learn how the view is loaded, the process is well described in the documentation
What happens is that the view and all the outlets are nil until the view is loaded, you can make sure it is loaded by calling self.view; before configuring the outlet at updateRowNumber:
Please also note, you are better to call [super viewDidLoad] in the beginning of the overridden viewDidLoad, it makes sense as you need to let UIViewContorller to do it's staff before you do some customized logic, the dealloc is different as you need to do your logic before the standard NSObject -dealloc fires. Hope it's understandable.

Resources