I want to print out vc1.string1 from vc2.
Currently console's showing:
vc1.string1 (null)
When I was not using storyboard I accessed vc1 variable like this:
AppDelegate *appDelegate = [(AppDelegate *)[UIApplication sharedApplication]delegate];
NSLog(#"vc1.string1 %#", appDelegate.viewController.string1);
But I don't know how to access vc1.string when I'm using storyboard.
Help please thanks.
P.S.
Here's the link of my project: http://dl.dropbox.com/u/12439052/AccessDiffClass.zip
//ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
NSString *string1;
}
#property (nonatomic, strong) NSString *string1;
#end
#import "ViewController.h"
#implementation ViewController
#synthesize string1;
-(void)viewDidLoad {
string1 = #"String One";
NSLog(#"string1 %#", string1);
}
#end
VC2:
//ViewController2.h
#import <UIKit/UIKit.h>
#class ViewController;
#interface ViewController2 : UIViewController {
ViewController *vc1;
}
#property (nonatomic, strong) ViewController *vc1;
#end
#import "ViewController2.h"
#import "ViewController.h"
#implementation ViewController2
#synthesize vc1;
-(void)viewDidLoad {
NSLog(#"vc1.string1 %#", vc1.string1);
}
#end
I downloaded your project and added this bit of code to your ViewController.m file:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog( #"preparing for segue" );
ViewController2 * vc2 = [segue destinationViewController];
vc2.vc1 = self;
}
And this got things appearing as you were hoping for in my simulator console.
Now, this is definitely not the best thing to do here. In the ARC world, I don't know if vc1 is retained or if we're leaking or whatever. It would be much smarter for you to give your ViewController2 class a NSString * property that gets set in the prepareForSegue method. And also give an identifier to your segue.
Here is another StackOverflow question that talks about prepareForSegue a bit more (and somewhat more detailed).
made a mistake last time try this.
Key Code:
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
vc1 = appDelegate.viewController;
NSLog(#"string1 %#", vc1.string1);
http://dl.dropbox.com/u/12439052/passingValue.zip
Related
I have a navigation controller residing inside a tab bar controller and whenever I try to access a class from a class within the navigation controller all my values return (null).
This is how I'm trying to do it.
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate> {
NSString *searchQueryA;
}
#property (strong, nonatomic) NSString *searchQueryA;
ThirdViewController.h
#import "MasterViewController.h"
#import "AppDelegate.h"
#class MasterViewController;
#interface ThirdViewController : UIViewController {
code
}
#property (strong, retain) MasterViewController *masterViewController;
ThirdViewController.m
- (IBAction)showDetail:(id)sender {
AppDelegate *appDelegate = [[AppDelegate alloc] init];
appDelegate.searchQueryA = _searchField.text;
masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[self.navigationController pushViewController:masterViewController animated:YES];
}
MasterViewController.h
#import "AppDelegate.h"
#interface MasterViewController : UITableViewController
{
NSString *searchQueryM;
}
#property (nonatomic, strong) NSString *searchQueryM;
MasterViewController.m
AppDelegate *appDelegate = [[AppDelegate alloc] init];
searchQueryM = appDelegate.searchQueryA;
NSLog(#"%#", searchQueryM);
And in the log I can see that searchQueryM is (null). If I try to access the variable in AppDelegate from another class, that isn't involved with navigation controller, then it shows perfectly fine. What am I missing?
If you need to see more code I'd be happy to provide it.
EDIT:
For legibility I'll post code changes here:
I have the delegate in my AppDelegate.h
As Leonardo pointed out I only alloc'd and init'd my AppDelegate. I changed that snippet to this:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
searchQueryM = appDelegate.searchQueryA;
but still no go as searchQueryM still is (null).
This is what I do with searchQueryM
MasterViewController.h
#interface MasterViewController : UITableViewController
{
NSString *searchQueryM;
}
#property (nonatomic, strong) NSString *searchQueryM;
MasterViewController.m
#synthesize searchQueryM;
I'm fairly new to Objective-C (as well as OO-programming) and should probably read a book on it, but it seems to me like there isn't a lot more to it than that. Do correct me if I'm wrong.
EDIT 2
ThirdViewController.h
#interface ThirdViewController : UIViewController {
UITextField *_searchField;
}
#property (nonatomic, strong) IBOutlet UITextField *searchField;
ThirdViewController.m
#synthesize searchField = _searchField;
...
- (IBAction)showDetail:(id)sender {
_code_
NSLog(#"%#", searchField.text);
_code_
If i type in "asd" in the searchField textfield and output it with the log I get "asd".
}
Why are you alloc init your AppDelegate ?
The AppDelegate should be accessed with:
[[UIApplication sharedApplication] delegate]
We should see how you normally initialize searchQueryM, you are getting null, probably because the AppDelegate get only allocated and init, but the logic that initialize its properties never gets called.
I'm trying to assign SecondViewController as a delegate object of FirstViewController (if I understand correctly). However FirstViewController doesn't send any messages to SecondViewController.
Am I allowed to pretend as though SecondViewController did get a message from FirstViewController and respond to the FirstViewController? (Note: My SecondViewController is in charge of a view that has a button. When I press the button on my SecondViewController's view I want it to tell the FirstViewController to update its view)
FirstViewController.h
#import <UIKit/UIKit.h>
#protocol FirstViewControllerDelegate <NSObject>
#optional
- (void) setAnotherLabel;
#end
#interface FirstViewController : UIViewController {
IBOutlet UILabel *label;
id <FirstViewControllerDelegate> delegate;
}
#property (nonatomic, retain) IBOutlet UILabel *label;
#property (nonatomic, assign) id <FirstViewControllerDelegate> delegate;
- (void) pretendLabel;
- (void) realLabel;
#end
FirstViewController.m
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize label;
#synthesize delegate;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void) setAnotherLabel;
{
label.text =#"Real";
[self.view setNeedsDisplay];
}
- (void) pretendLabel;
{
label.text =#"Pretend";
[self.view setNeedsDisplay];
}
- (void) realLabel;
{
[self setAnotherLabel];
}
- (void)viewDidLoad
{
[super viewDidLoad];
label.text=#"Load";
[self pretendLabel];
}
...
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "FirstViewController.h"
#interface SecondViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, FirstViewControllerDelegate>
{
UIImage *image;
IBOutlet UIImageView *imageView;
}
- (IBAction) sendPressed:(UIButton *)sender;
- (IBAction) cancelPressed:(UIButton *)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#implementation SecondViewController
- (IBAction) sendPressed:(UIButton *)sender
{
FirstViewController *fvc = [[FirstViewController alloc] init];
[fvc setDelegate:self];
//how do I find out if I'm actually the delegate for FirstViewController at this point?
[fvc realLabel];
self.tabBarController.selectedIndex = 0;//switch over to the first view to see if it worked
}
There are a few issues with this and what appears to be a bit of confusion.
I assume that FirstViewController and SecondViewController are in separate tabs in the tab bar controller.
In the sendPressed: method, you're creating a new instance of FirstViewController - this is not the same FirstViewController that is in your tab bar controller and why calling realLabel has no effect.
The second point is that you appear to misunderstand how delegation works - there is no reason for a delegate in the code you posted.
Good read for getting to grips with delegates: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/CommunicateWithObjects.html
As for a solution to your problem there are a few options:
Post a notification from SecondViewController that FirstViewController is observing (lots of information available on the net regarding notifications).
Get the specific instance of FirstViewController within the self.tabBarController.viewControllers array and call the method from there. Something like...
- (IBAction) sendPressed:(UIButton *)sender
{
for(UIViewController *controller in self.tabBarController.viewControllers)
{
if([controller isKindOfClass:[FirstViewController class]])
{
FirstViewController *firstViewController = (FirstViewController *)controller;
[firstViewController realLabel];
}
}
self.tabBarController.selectedIndex = 0;//switch over to the first view to see if it worked
}
There are more options available than this, but the above will give you a good start into researching the best approach for your need.
Hope this helps.
I have created a tab based application having 4 tabs and 4 views respective to these tabs.
I have a string in first view and when I printing this string in second view it printing null.
In first view.h
NSString *dateString;
#property(nonatomic,retain) NSString *dateString;
In first view.m
#synthesize dateString;
dateString=button6.titleLabel.text;
NSLog(#"dateString:%#",dateString);
In second view.h
NSString *dateString;
#property(nonatomic,retain) NSString *dateString;
In second view.m
#synthesize dateString;
- (void)viewDidLoad { [super viewDidLoad];
NSLog(#"dateString:%#",self.dateString);
}
Add your view controllers as properties for the application delegate (if the app is a relatively simple design).
Then you can reference the properties of the second view controller from the first view controller, by way of the app delegate. (One such property could be the string you want the second VC to copy or retain.)
Create NSString variable in Application delegate class and set the Property and make synthesize that variable.
And set the #"" (blank) value in applicationDidFinishLaunching method.
For Example - my variable name is str, then initialize str in applicationDidFinishLaunching like self.str = [NSString stringWithFormat:#""];
And now you can use it in any tab *view* and set the value as per your require.
More code
AppDelegate.h
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
NSString *baseURL;
}
#property (nonatomic, retain) NSString *baseURL;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window;
#synthesize baseURL;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
self.baseURL = [NSString stringWithFormat:#""];
}
- (void)dealloc
{
[baseURL release];
[window release];
[super dealloc];
}
#end
ViewController1.h
#class AppDelegate;
#interface ViewController1 : UIViewController <UITextFieldDelegate>
{
AppDelegate *appDelegate;
}
#end
ViewController1.m
#import "AppDelegate.h"
#import "ViewController1.h"
#implementation ViewController1
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSLog(#"value - %#",appDelegate.baseURL); // Here you can set or get the value.
}
it may not be the best answer.but creating a string variable in the appdelgate and passing the variable to this from the first view and fetching it from the second view works for me
Really, did we lose focus of MVC and the most awesome of abilities that is easy to do in iPhone Development?
How about a delegate?
#protocol ViewOneDelegate
- (void)getStringVariable;
#end
#interface ViewOneModel : NSObject
{
NSString* _stringVariable;
id<ViewOneDelegate> _theDelegate;
}
#property (nonatomic, retain) id<ViewOneDelegate> theDelegate;
#end
Assign a controller to be the delegate for the ViewOneModel.
Here is a simple solution, but not the best one, Create a global variable, and just use that.
Header
extern NSString *GlobalString;
#interface GlobalVariables : NSObject {
}
#end
implementation
#import "GlobalVariables.h"
#implementation GlobalVariables
NSString *GlobalString;
#end
And now to have access to the variable just import the header in the file you want to use.
You'll probably want to check if it's initiated before you use it.
Hello i'm trying to make a simple ios app with tabs and navigation .
in the delegate i have the following type:
BlogRss * _currentlySelectedBlogItem;
with this property:
#property (readwrite,retain) BlogRss * currentlySelectedBlogItem;
and i'm trying to get his data with two other classes, one is a table view with the data and the other will show the data;
in both classes i have declared the following:
#class NewsAppDelegate;
NewsAppDelegate * _appDelegate;
#property (nonatomic, retain) IBOutlet _NewsAppDelegate * appDelegate;
#synthesize appDelegate = _appDelegate;
ofter "touching" the cell in the table view i wrote this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[self appDelegate] setCurrentlySelectedBlogItem:[[[self rssParser]rssItems]objectAtIndex:indexPath.row]];
// Navigation logic may go here. Create and push another view controller.
// [[self appDelegate] loadNewsDetails];
NewsDetailViewController *detailViewController = [[NewsDetailViewController alloc] initWithNibName:#"NewsDetailViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
when i'm writing in the other class:
NSLog(#"%#",self.appDelegate.currentlySelectedBlogItem);
i'm getting null.
clearly i'm doing something wrong, but i don't know what...
The problem is likely that this line is returning null:
[[[self rssParser]rssItems]objectAtIndex:indexPath.row]
Code is easier to debug when you don't nest so many sentences.
You can access your delegate from anywhere because UIApplication is a singleton, you don't need to keep a reference as you do with self.appDelegate. Example:
(NewsAppDelegate *)[[UIApplication sharedApplication] delegate];
Or just do as Jennis suggest, who is a faster typer than me, and remove the IBOutlet. :P
When you do
NewsAppDelegate * _appDelegate;
#property (nonatomic, retain) IBOutlet _NewsAppDelegate * appDelegate;
#synthesize appDelegate = _appDelegate;
The result is the same if you skip the first line, because the runtime creates it for you.
See Question about #synthesize. And I guess _NewsAppDelegate is really NewsAppDelegate (no underscore).
Please do as follow.
//Your Header File
#import "YourAppDelegate.h"
#interface YourViewController : UIViewController
{
YourAppDelegate *appDelegate;
}
#property(nonatomic,retain) YourAppDelegate *appDelegate;
#end
//Your Implementation file
#implementation YourViewController
#synthesize appDelegate
- (void)viewDidLoad {
self.appDelegate = (YourAppDelegate*) [[UIApplication sharedApplication] delegate];
}
#end
After declaring as above you will have access of appDelegate anywhere in your view controller.
Hope it helps.
I have an App Delegate and a 3 view controllers in my project. I have a variable(a NSMutable Array) in my App Delegate which I want to access from my view controllers. So I decided to create a pointer to my App Delegate and access the variables.
Here is my code:
iSolveMathAppDelegate.h
#import <UIKit/UIKit.h>
#interface iSolveMathAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
NSMutableArray *tmpArray;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) NSMutableArray *tmpArray; // variable I want to access
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
iSolveMathAppDelegate.m
#import "iSolveMathAppDelegate.h"
#implementation iSolveMathAppDelegate
#synthesize window;
#synthesize tabBarController;
#synthesize tmpArray;
...
- (void)dealloc {
[tabBarController release];
[window release];
[tmpArray release];
[super dealloc];
}
#end
The view controller class from which I want to access the tmpArray.
referenceViewController.h
#import <UIKit/UIKit.h>
#class iSolveMathAppDelegate;
#interface referenceViewController : UITableViewController {
NSMutableArray *equationTypes;
iSolveMathAppDelegate *data;
}
#property(nonatomic, retain) NSMutableArray *equationTypes;
#property(nonatomic, retain) iSolveMathAppDelegate *data;
#end
And finally referenceViewController.m
#import "referenceViewController.h"
#implementation referenceViewController
#synthesize equationTypes, data;
data = (iSolveMathAppDelegate *)[[UIApplication sharedApplication] delegate];
//says that initializer element is not constant...ERROR!
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"equationTemplates"ofType:#"plist"];
data.tmpArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
self.equationTypes = data.tmpArray;
[data.tmpArray release]; // obviously none of these work, as data is not set.
}
- (void)dealloc {
[super dealloc];
[equationTypes release];
[data release];
}
#end
So anyway at the line data = (iSolveMathAppDelegate *)[[UIApplication sharedApplication] delegate]; the compiler says that the initializer element is not constant.
I have scrouged the web for answers, and for all it seems to work...but no dice for me :( Can you please advice me on where I have gone wrong? I am using XCode 3.2 and iOS SDK 3....maybe the SDK is the problem.
Thank You
That line of code isn't in a method or function, so the compiler is treating it as the definition of a compile-time constant or static/global variable. Those need constant values for initialization.
You should put the assignment of data within a method. A good place would be -viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
data = (iSolveMathAppDelegate *)[[UIApplication sharedApplication] delegate];
...
}
I figured out the struct and union problem. All I had to do was change #class iSolveAppDelegate to #import "iSolveAppDelegate.h" in my referenceViewController.h file. Thanks Jonathan for your help!