How do I call a variable from another class? - iphone

I have a class called 'Constants' that I am storing a String variable in. This class contains a few global variables used in my app.
I want to be able to reference this class and call the variable (called profileId) in other Views of my app.
I looked around and found a few examples, but am not sure how to do this. Currently my setup is:
Constants.h
#interface Constants : UIViewController {
NSString *profileId;
}
#property (nonatomic, retain) NSString *profileId;
#end
Constants.m
#import "Constants.h"
#implementation Constants
#synthesize profileId;
- (void)dealloc {
[profileId release];
[super dealloc];
}
And I am trying to call the variable profileId in a new View via this way:
NewView.h file
#class Constants;
NewView.m file
NSLog(#"ProfileId is:", [myConstants profileId]);
Is there something I'm missing? It is coming up null, even though I am properly storing a value in it in another function via this way:
Constants *Constant;
Constant = [[Constants alloc] init];
Constant.profileId = userId;

You are missing the %# for the parameter:
NSLog(#"ProfileId is: %#", [myConstants profileId]);
As a side note, variable names should begin with a lower case letter (constant, not Constant). You also can use dot syntax with properties here: myConstants.profileId
If this doesn't work, please post the code that you use to assign your value (complete method).

Related

How to declare a variable that can be used in both class1.m and class B.m

i have "classmap.m" and annotation.m i have a value of coordinates in "classmap.m" and i need to assign a value in the other class annotation.m.
ex:
class1.m
double start_long;
i want to give pass the value in another one class (annotation.m)
annotation.m
annotation.longitude=Start_long;
how can i do that please give some examples is there.
thanks in advance
A better, more efficient, effective and cleaner way is to use Singleton Pattern. A good approach is to keep AppDelegate cleaner and avoid keeping global variables there. Always try to use Singleton classes and objects to keep global variables.
If both classmap.m and annotaion.m are inherited from NSObject then it's simple annotation:classmap . will give access to the properties of classmap
ClassMap
#interface classmap : NSObject
#property double longitude;
#end
#import "classmap.h"
#implementation classmap
#synthesize longitude;
#end
Annoataion
#interface annotation : classmap
#property double start_long;
#end
#import "annotation.h"
#implementation annotation
#synthesize start_long;
#end
Now the assigning can be done easily in annotation.longitude=Start_long the place you need
Take the variable in the Appdelegate and access it anywhere in the project .
Access it like
Assign Value
AppDelegate *app = [[UIApplication sharedApplication]delegate];
appd.start_long = -17.002// assign some value here
Read Value
AppDelegate *app = [[UIApplication sharedApplication]delegate];
double dVal = appd.start_long ;
The Singleton pattern is a weapon which should be used sparingly as it makes a concrete dependancy on the ClassMap object for everything which uses it.
While using a Singleton will achieve what you want right now which is access to a property in ClassMap but you set yourself up for future coding issues.
What happens when you have multiple ClassMap instances for example?
Singletons are better suited to things which do universal jobs. Things which are tools. e.g [NSUserDefaults standardUserDefaults] or [NSFileManager defaultManager]
A different solution is to use Dependancy Injection which creates a direct connection between the object Annotation which needs the ClassMap object.
In brief ClassMap declares a property
#property double start_long;
you pass the ClassMap object to the Annotation object when you instantiate.
Annotation.h
#interface Annotation:NSObject
-(instancetype)initWithClassMap:(ClassMap *)amap;
#end
and…
Annotation.m
#interface Annotation() {
ClassMap *_map;
}
#end
#implementation Annotation
-(instancetype)initWithClassMap:(ClassMap *)amap {
self = [super init];
if(self) {
_map = amap;
}
return self;
}
-(void)doSomething {
self.longitude = _map.start_long;
}
#end
Another method is to use delegation.In your classmap.m declare
#protocol classmapDelegate <NSObject>
-(void)didchangeCoordinateValue:(double)longitude;
#end
annotation should confirm to this protocol and when ever the value in classmap is changed, you could get the event tin Annotation class.

Using Custom Subclass of NS Object in 2 different IBActions

This is an objective-c problem. I have created a subclass person of NSObject with parameters 'height' and 'weight', with property and synthesize in a file called Person.h that contains both interface and implementation.
I want to import Person.h into my viewcontroller.m and create person objects and alter them using 2 IBActions.
-(IBAction)alterperson_1{
person *bob = [person alloc]init];
bob.height = 72;
bob.weight = 200;
}
-(IBAction)alterperson_2{
bob.height = 80;
bob.weight = 250;
}
This arrangement does not work because the method alterperson_2 can't find Bob because it is a local variable to alterperson_1. My question is how and where in viewcontroller.m do I allocate Bob as a person so that his attributes can be altered by both IBActions.
I have tried allocing in viewdidload as well as in the initwith nibname methods. It did not work. I have also tried in the implementation{ } of viewcontroller.m but that doesn't work either because Bob's allocation is not a compile time constant.
Thanks!
Update With Code
So, I have the Person.h file importing properly now (thanks Robotnik), and am able to create instances of Person throughout ViewController.m -- however, my created instance *bob does not seem to retain values for its properties (see comments by NSLog statements in the code). I think this is an initialization issue, but I have no idea where to initialize. Currently, I get a warning when initializing in viewDidLoad. How do I get bob.weight to print 200 when my IBAction is called, instead of the 0 I currently get? Thanks.
// Person.h
#import <Foundation/Foundation.h>
#interface Person : NSObject{
int weight;
int height;
}
#property int weight, height;
#end
end Person.h
//Person.m
#import "Person.h"
#implementation Person
#synthesize weight, height;
#end
end Person.m
//ViewController.h
#import <UIKit/UIKit.h>
#import "person.h"
#interface ViewController : UIViewController{
}
#property Person *bob;
-(IBAction)persontest:(id)sender;
#end
end ViewController.h
//ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize bob;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Person *bob = [[Person alloc]init]; // this causes a local declaration warning, if I remove this code, however, it still doesn't work
bob.weight = 100;
NSLog(#"viewDidLoad bob's weight, %i", bob.weight); // this will print 100, but only because I made the local initialization. The value is lost once the viewDidLoad Method ends.
}
-(IBAction)persontest:(id)sender{
bob.weight = bob.weight + 100;
NSLog(#"IBAction bob's weight %i", bob.weight); // this prints 0, probably because value is nil. How can I make it print 200?
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
end ViewController.m
You'll need to declare Bob in your ViewController.h if you want him to be accessible across multiple methods. You can then initialise him in viewDidLoad
#interface ViewController
{
Person *bob;
}
-(IBAction)alterperson_1;
-(IBAction)alterperson_2;
#end
You mentioned you wanted to instantiate multiple people. In that case you may want to keep multiple Person objects in an NSMutableArray or similar. This should still be declared in the ViewController.h in order to be accessible in multiple methods. You can then use the method addObject: to add people to the array. Here is an example of an array, storing strings.
NSMutableArray *stringArray = [[NSMutableArray alloc] init];
[stringArray addObject:#"Dog"];
[stringArray addObject:#"Cat"];
You seem to be confusing declaration of a variable with allocation of a variable. You're also not using properties properly.
Declaration of a variable is done like this:
Person *bob;
That's it. If you put this line in your #interface section, or in {braces} at the top of your implementation section, then this becomes an instance variable, any time you use bob in the rest of your class it will know that you are talking to a person. So, in your viewDidLoad, you can now do this:
bob = [[Person alloc] init];
And it knows you are referring to the instance variable. In your current code, you have Person * in front of this line, which, as the compiler is telling you, is declaring a local variable with the name bob, and therefore hiding your instance variable, so you are not changing your instance variable at all, so there is no value in it later.
Looking at the nature of this question, and your comments, I would strongly advise reading some objective-c introductory texts before proceeding much further. You can ask questions here but SO is not really the place to learn a language - most answerers will assume that you know the language basics.

Proper way to make variable accessible within entire .m file?

As you can tell, I'm new to Objective-C. I currently have a Singleton working, but I'm trying to use it throughout several methods within the same .m file.
Right now I use this to declare/instantiate the Singleton within a method:
GlobalData *globDat=[GlobalData getInstance];
Do I need to declare it within each method, or is there a way to do this at the top of the .m (or .h?) file so I can access it throughout the other methods?
Thanks...
(BTW I've tried placing the line of code shown above under my "#implementation" line, but I get an error: "Initializer element is not a compile-time constant" which I now know is because the line is not within a method.)
You can add a class extension, and store the global data in ivar, like this:
#interface MyClass() {
GlobalData *globDat;
}
#end
#implementation MyClass
-(id) init {
self = [super init];
if (self) {
globDat=[GlobalData getInstance];
}
return self;
}
#end
This will hide the globDat from the interface, and make it available throughout the methods you implement inside your implementation block of MyClass.
when u need a variable / object that is accessible to all methods in an implementation data, u need to declare it on the header file, and then synthesize it on the implementation file (note that u may need to import the GlobalData header)
so
in header (.h):
#class GlobalData;
#properties (nonatomic, strong) GlobalData *globDat;
and then at the implementation file (.m)
#import "blablabla.h"
#import "GlobalData.h"
#implementation blablabla
#synthesize globDat;
-(void)viewDidLoad
{
globDat = [GlobalData getInstance];
}
good luck

What is the point of #property and #synthesize?

I haven't been able to figure it out, and there are no websites which explain it clearly enough... what exactly are the purposes of #property and #synthesize?
Thanks in advance!
Objective-C Runtime Programming Guide: Declared Properties
#property declares the getter and the setter methods for the public property you want to implement. For example this property declaration:
#property float value;
is equivalent to:
- (float)value;
- (void)setValue:(float)newValue;
#synthesize provides default implementation for these two accessors.
Update: The above explains what these two do. It does not explain what their purpose is. :-)
#property adds a member to the public interface that acts as a data variable to your class clients, but is read and written using methods. This gives you better control over the data that is exchanged between the client and your code, for example you can do extended validation on the values your code is given.
#synthesize allows you to not explicitly write the code that will be called by the client and actually treat the property as a data variable yourself.
The "#" symbol is interpreted by the compiler as a directive. This is one of the Objective-C 'additions' to the C language. When you declare #property and then #synthesize you are instructing the compiler to create the instructions and corresponding symbols for getters and setters for you. Remember that in the C language, the "=" operator means "assign". Most of the time in the OO context that the Objective-C extensions provide, we are working with pointers (aka references) to isa data structures (Classes in Objective-C).
Prior to Objective-C 2.0, all of the getter and setter methods had to be coded by the developer for every attribute which for most cases was copy/paste code. To be completely KVC/KVO compliant requires a lot of very tedious code... willAccessValueForKey, didUpdateValueForKey statements etc. that the new compiler adds for you automatically when you use the #property/#synthesize syntax. This is a huge productivity boost for developers. The dot syntax additions to the language are a little more contentious in the community as this hides the magic the compiler is doing on you behalf to interpret the object.property = anotherObject.property; statement as [object setProperty:[anotherObject property]];
From the Apple documentation referenced in other answers
Property Declaration Attributes
You can decorate a property with attributes by using the form #property(attribute [, attribute2, ...]). Like methods, properties are scoped to their enclosing interface declaration. For property declarations that use a comma delimited list of variable names, the property attributes apply to all of the named properties.
If you use the #synthesize directive to tell the compiler to create the accessor method(s), the code it generates matches the specification given by the keywords. If you implement the accessor method(s) yourself, you should ensure that it matches the specification (for example, if you specify copy you must make sure that you do copy the input value in the setter method).
I hope this will help you.
#property and #synthesize is Use to Access Object Or Variable into Another Class.
Here is a Small Example:
This is First Class
#import <UIKit/UIKit.h>
#import "ClassB.h"
#interface ViewController : UIViewController
#property(nonatomic, retain) NSString *FirstName;
#property(nonatomic, retain) NSString *LastName;
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize FirstName, LastName;
- (void)viewDidLoad
{
[super viewDidLoad];
self.FirstName = #"Ashvin";
self.LastName = #"Ajadiya";
ClassB *ClassBOb = [[ClassB alloc] init];
ClassBOb.ViewCntrlrOb = self;
[ClassBOb CallMe];
}
#end
And This is Another Class:
#import <UIKit/UIKit.h>
#class ViewController;
#interface ClassB : UIViewController
#property(nonatomic, retain) ViewController *ViewCntrlrOb;
-(void) CallMe;
#end
#import "ClassB.h"
#import "ViewController.h"
#interface ClassB ()
#end
#implementation ClassB
#synthesize ViewCntrlrOb;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void) CallMe
{
NSLog(#"FirstName = %#",ViewCntrlrOb.FirstName);
NSLog(#"LastName = %#",ViewCntrlrOb.LastName);
}
So You can Access FirstName And LastName into ClassB.
And They Print:
2012-05-25 14:38:10.766 MyExample[8751:c07] FirstName = Ashvin
2012-05-25 14:38:10.768 MyExample[8751:c07] LastName = Ajadiya
Just a quick example of why you might not want to do just "variable = 0":
Say you have this property:
#property (nonatomic, retain) id <MyDelegate> theDelegate;
Whenever you replace that delegate with a new one, your synthesized setters and getters will handle the release/retain for you every time you set it like so:
self.theDelegate = newObject;
Really what happened was this:
[self setTheDelegate:newObject];
- (void)setTheDelegate:(id <MyDelegate>)anObject {
[theDelegate release];
theDelegate = [anObject retain];
}
(This is simplified of course)
You can do very powerful things in your own setters and getters, synthesize is for those that happen over and over like retained properties, etc. When compiling it looks at your #property and builds the methods accordingly.

Object as a data member in Objective C

From what I have experienced it seems as if objects cannot be shared data members in objective c. I know you can init a pointer and alloc the object in each method but I cannot seem to figure out how one can say define a NSMutableString as a data member and allow all of the methods to use and modify its data as in c++. Is this true or am I missing something?
To define an instance variable (member), edit your .h file:
#interface MyClass : NSObject {
// ivars go here
NSObject *member;
}
// methods go here
#end
Then, in your .m file, from any instance method (one which begins with -), you can access this variable.
- (void)doThingWithIvar {
[member doThing];
}
If you want to access the variable from outside the object itself, you'll need accessors. You can do this easily with Obj-C properties:
#interface MyClass : NSObject {
// ivars go here
NSObject *member;
}
// methods go here
#property (nonatomic, retain) NSObject *member;
#end
And in the .m:
#implementation MyClass
#synthesize member;
// ...
#end
The #synthesize line creates getter/setter methods for the ivar. Then you can use property syntax:
MyClass *thing = ...;
NSLog(#"%#", thing.member); // getting
thing.member = obj; // setting
(Note that I specified (retain) for the #property; if your member isn't an Objective-C object you won't want that. And if your property's class has a mutable counterpart, you'll want (copy) instead.)
It sounds like you want to synthesize (create getter/setter methods) a property for a member variable. I just found this cheat sheet, go down to the section called, "Properties", should give a quick overview.
Other than that Apple's documentation should give you more info.