I am new to iPhone. I have small doubt. I have three strings in class BiblePlayerViewController and I want to pass those 3 strings to appdelegate from this class. How to do that?
create a property NSDictionary in BiblePlayerViewController and add your three strings to the dictionary,so you can read that dictionary where ever you want
NSDictionary *FileDict = [[NSDictionary alloc] initWithObjectsAndKeys:str1,#"key1",str2,#"key2",str3,#"key3",nil];
Create a static reference of Appdelegate and declare NSStrings as class variables in Appdelegate
Put this is appdelegate
+(Appdelegate*)getAppdelegate{
return self
}
and then in your viewcontroller
do appdelegate.string1 = string1 and so on ..
you can also encapsulate these objects in an Array and pass them to appdelegate .
The idea is to get a static reference of Appdelegate.
Create a variable of type NSString in appdelegate.h
NSString *test;
import appdelegate.h in BiblePlayerViewController.m
Now get a reference to appdelegate class using
Appdelegate *ad; //init with some object
//now access the NSString var u just created
ad.test=#"your string";
I think you can use the shared object of the appdelegate class for the similar cases.
in the appdelegate class declare global object as
#define UIAppDelegate ((MyAppDelegateClass *)[UIApplication sharedApplication].delegate)
By declaring this, from any class that imports your AppDelegate class can use this shared object of AppDelegate class.
Then is you have three property declared in AppDelegate as
#interface MyAppDelegateClass : NSObject <UIApplicationDelegate>
{
NSString *string1;
NSString *string2;
NSString *string3;
}
#property (nonatomic,retain) NSString string1;
#property (nonatomic,retain) NSString string2;
#property (nonatomic,retain) NSString string3;
#end
Then in the AppDelegate Implementation
#implementation MyAppDelegateClass
#synthesize string1;
#synthesize string2;
#synthesize string3;
#end
In the class from where you need to send the strings to AppDelegate use like below
You need to import AppDelegate class first
#import "MyAppDelegateClass.h"
#interface MyCustomSenderClass : UIViewController
#end
And in the implementation
#implementation MyCustomSenderClass
- (void) sendStringsToAppDelegate
{
UIAppDelegate.string1 = myString1;
UIAppDelegate.string2 = myString2;
UIAppDelegate.string3 = myString3;
}
#end
Thus you can directly set a value to the AppDelegate from any class imports your AppDelegate class.
I think this helps you.
Related
I want to use global variables and objects for the iphone project.
I have created NSobject class and defined like below:
.h File:
#import <Foundation/Foundation.h>
#interface GlobelClass : NSObject
extern NSString *mystr;
extern NSMutableArray *Arrdata;
#end
.m File:
#import "GlobelClass.h"
#implementation GlobelClass
NSString *mystr;
NSMutableArray *Arrdata;
#end
What is the best way Or should I use singleton pattern like below link answer:
Using global variables in Objective-C
Please share thoughts?
One of the way to use global variable in the application is:
You can use App Delegate class itself :
.h file:
AppDelegate: UIResponder <UIApplicationDelegate> {
}
#property(nonatomic,strong) NSString* strUserID;
.m file:
#synthesize strUserID;
Now you can access strUserID as global variable in your UIViewController as:
ABCProjectAppDelegate *appDelegate = (ABCProjectAppDelegate*) [[UIApplication sharedApplication] delegate];
You can set value:
appDelegate.strUserID = #"Test";
Get Value:
NSString *strId = appDelegate.strUserID;
:)
I'm setting a string in a view controller called ViewController and trying to access it somewhere else. This is the code:
ViewController.h
NSString *string;
...
#property (retain) NSString *string;
ViewController.m
#synthesize string;
...
-(void)viewDidLoad {
...
string = #"Test";
}
OtherViewController.m
#import "ViewController.h"
...
-(void)viewDidLoad {
ViewController *vc;
vc = [[ViewController alloc] init];
NSLog(#"String: %#", vc.string);
}
However, the log is showing: String: (null). What am I doing incorrectly? Thanks.
The viewDidLoad of ViewController is only called when the view is loaded. The view is lazily loaded when required e.g. when a call to vc.view is made.
I'm not sure what you are trying to achieve but this certainly seems like a code smell to me.
As #Fscheidl points out you are creating a new instance and not accessing an existing instance so this may add to your problem. I still believe your main issue is that you assume viewDidLoad is being called just by creating the viewController, which is not the case
edit : it doesn't necessarily need to be an NSObject class, if you want to, you could also do this on your viewController class, just be sure to also include
-(id)init
on your header
---- end of edit
if you're trying to make a class that's accessible to another view controller, why not try NSObject instead of view controller (considering you only need to take that string value)
for instance, lets call that viewController class "global" class
so at global.h, you put up
#import <Foundation/Foundation.h>
#interface GlobalVar : NSObject
#property (nonatomic, strong) NSString *myString;
-(id)init;
#end
and then, at global.m you put up
#import "GlobalVar.h"
#implementation GlobalVar
#synthesize myString;
-(id)init
{
self = [super init];
if(self)
{
myString = [[NSString alloc]initWithFormat:#"the String"];
}
return self;
}
#end
after this, everytime you need to access the "myString" object that contained in global class, you could put up
at header :
#import "GlobalVar.h"
...
...
#property (nonatomic, strong) GlobalVar *globalVar;
at implementation file :
#synthesize globalVar;
...
...
self.globalVar = [[GlobalVar alloc]init];
NSString *theString = globalVar.myString;
NSLog(#"content of my string is : %#",theString);
there you go ;)
You do create a new instance of ViewController by calling [[ViewController alloc] init]; This instance hasn't had string even set. You have to access that exact instance of ViewController.
If you create the instance of OtherViewController directly from ViewController, you can add the following to OtherViewController.h:
#import "ViewController.h"
#property (nonatomic, retain) ViewController *previousViewController
When creating the OtherViewController, you can then set:
//alloc and init instance of OtherViewController
myOtherViewController.previousViewController = self;
In your viewDidLoad: method, you can then access your string as follows:
NSLog(#"String: %#", previousViewController.string);
this is something I have always had confusion about
I never can seem to find a good explanation, i understand inheritance, but from what i learned that is between the master class and the sublasses of them...What if i want to pass a NSString to another class thats not a subclass of the other
Heres a example:
class1.h
#interface class1 : UIViewController{
NSString *string
}
#property (nonatomic, retain) NSString *string
#end
class1.m
#implementation class1
#synthesize string;
-(void)viewDidLoad{
string = #"IM A STRING AHHH";
}
Now lets say i want to pass that string with what its equal to to another class
class2.h
#import "class1.h"
#interface class2 : UIViewController{
}
#end
class2.m
#implementation class2
//i want to use the NSString in here, how do i do that?
Thanks,
Jacob
First of all use [string retain]; in class 1.
Then, in class 2, import class1. make object of class 1 say cls1. and you can access it by cls1.string;
Smiriti's answer is right...
what else you can do is..
overrirde the init method and pass your NSString as a parameter and use it.
You can create an instance of class1 and then you can access string simply calling
[instance string];
or
instance.string
If you don't want to create an instance of class1 you may define a method such as
+(NSString*)getString;
and then call it from class2
[class1 getString];
If class 2 is loading from class 1 you can send the value as parameters.
-(id)initwithParameters:(NSString *)parameter
{
if(self == [super init])
{
// access the paramenter and store in yo u avariable
}
return self;
}
In class 1
[[class 2 alloc]initwithParameters: ]
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.
My application is a tab bar application, with a separate view controller for each tab.
I have an object in my first view controller (A) which contains all my stored application data (Please ignore NSUserDefaults for this) which needs to be accessed by the second view controller (B) when I press a button on it. How can I achieve this in the best way?
One option you have is to declare your date model as instance variables of your app delegate (as mentioned by other commenters).
Instead of referencing the app delegate as suggested by nevan an alternative is to add a property to your view controller classes (A and B) for your data model.
Say you wanted to share a data model object between your view controllers you can add a property to each:
#interface AViewController : UIViewController {
MyDataModel *model;
}
#property (nonatomic, retain) MyDataModel *model;
#end
#interface BViewController : UIViewController {
MyDataModel *model;
}
#property (nonatomic, retain) MyDataModel *model;
#end
When you initialise your view controller you can then set this property to the object context initialised previously.
You have mentioned a tab bar controller. If your view controllers are wired through IB all you have to do is to set these parameters in your application delegate applicationDidFinishLaunching: method, before the tab bar controller is displayed:
#interface MyAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>
{
MyDataModel *model;
AViewController *aViewController;
BViewController *bViewController;
...
}
#property (retain) IBOutlet AViewController *aViewController;
#property (retain) IBOutlet BViewController *aViewController;
#end
#implementation MyAppDelegate
...
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
...
aViewController.model = model;
bViewController.model = model;
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
Don't forget to release the model in your view controller's dealloc method.
The alternative is to use a singleton object. An simple singleton example:
#interface MyDataModel : NSObject
{
}
+ (MyDataModel *) sharedDataModel;
#end
#implementation MyDataModel
static MyDataModel *sharedDataModel = nil;
+ (MyDataModel *) sharedDataModel
{
#synchronized(self)
{
if (sharedDataModel == nil)
{
sharedDataModel = [[MyDataModel alloc] init];
}
}
return sharedDataModel;
}
#end
You can access this data model from all your view controllers with something similar to the following:
MyDataModel *model = [MyDataModel sharedDataModel];
See also this stack overflow discussion about singletons.
The most common way I've seen this is to set up the thing you want to access in the app delegate and reference it in other places like this:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
myStuff = appDelegate.stuff;
In the app delegate, set up a stuff variable and use #property and #synthesize as usual.
Some people say that it's not a good approach, since it's the same as using global variables, but it's very common.
I like to create a top level Model class that is a singleton and contains all the elements I might need.
It's helpful to also give it a top level load method that populates objects with just the db keys, using the hydrate/dehydrate pattern common in the Apple examples.
Typical usage in the app delegate would be simply,
[[MyModel sharedModel] load];
And then in a view controller:
NSArray *myThing1s = [[MyModel sharedModel] thing1s];
NSArray *myThing2s = [[MyModel sharedModel] thing2s];
You can then iterate over your thing1s and thing2s and when you need details, you can just call
[myThing1 hydrate];
which will populate the object.
Of course, you probably want to use CoreData to manage the persistence from 3.0 onwards.
I always create a special object called DataModel and use it's singleton sharedInstance.
And this object then holds all the app-related-data. No need for accessing the dreaded appDelegate.
DataModel.h
#import <Foundation/Foundation.h>
#class MyClass1, MyClass2;
#interface DataModel : NSObject
#property (copy, nonatomic) NSString *aString;
#property (assign) BOOL aBool;
#property (strong) MyClass1 *myObject1;
#property (strong) MyClass2 *myObject2;
+ (DataModel *)sharedModel;
#end
DataModel.m
#import "DataModel.h"
#import "Class1.h"
#import "Class2.h"
#implementation DataModel
- (id) init
{
self = [super init];
if (self)
{
_myObject1 = [[MyClass1 alloc] init];
_myObject2 = [[MyClass2 alloc] init];
aBool = NO;
aString = nil;
}
return self;
}
+ (DataModel *)sharedModel
{
static DataModel *_sharedModel = nil;
static dispatch_once_t onceSecurePredicate;
dispatch_once(&onceSecurePredicate,^
{
_sharedModel = [[self alloc] init];
});
return _sharedModel;
}
#end
And (bacause I'm lazy) i put DataModel.h in application-prefix.pch.
That way i can access my data from anywhere in the application simply by calling
[DataModel sharedModel]
Both view controllers should reference a third object (C) as their dataSource; this object (C) containing all the stored application data.
C would be, in this case, the M in the MVC.
Add to each of your ViewControllers the following declarations:
// SomeViewController.h
// Before #interface
#class MyDataSource;
// In the interface
IBOutlet MyDataSource *datasource;
#property(retain) IBOutlet MyDataSource *datasource;