How can I access variables from another class? - objective-c

There is probably a very simple solution for this but I can't get it working.
I have got multiple classes in my Cocoa file. In one of the classes class1 I create a variable that I need to use in another class class2 as well. Is there a simple way to import this variable in class2?

You can either make the variable public, or make it into a property. For example, to make it public:
#interface Class1
{
#public
int var;
}
// methods...
#end
// Inside a Class2 method:
Class1 *obj = ...;
obj->var = 3;
To make it a property:
#interface Class1
{
int var; // #protected by default
}
#property (readwrite, nonatomic) int var;
// methods...
#end
#implementation Class1
#synthesize var;
...
#end
// Inside a Class2 method:
Class1 *obj = ...;
obj.var = 3; // implicitly calls [obj setVar:3]
int x = obj.var; // implicitly calls x = [obj var];

You could expose the variable in class2 as a property. If class1 has a reference to class2, class1 can then see the variable. Honestly, though, it sounds like you're a beginner to both Objective-C and object oriented programming. I recommend you read up more on both.
Here is a place to start for object oriented programming with Objective-C.

try making a file that holds your variables that need to be accessed throughout the app.
extern NSString *stringVariable;
#interface GlobalVariables
#property (retain, nonatomic) NSString *stringVariable;
#end
and in the GlobalVariables.m file add
#import "GlobalVariables.h"
#implements GlobalVariables
#synthesize stringVariable;
NSString *stringVariable;
#end
And then as long as you import GlobalVariables.h into which ever .m files you need to access that variable in you can assign and access anywhere throughout your program.
EDIT
My answer that I have given above is differently not the way I would go about doing this now.
It would be more like
#interface MyClass
#property (nonatomic, strong) NSString *myVariable;
#end
then in the .m file
#implementation MyClass
#sythesize = myVariable = _myVariable; // Not that we need to do this anymore
#end
Then in another class in some method I would have
// .....
MyClass *myClass = [[MyClass alloc] init];
[myClass setMyVariable:#"My String to go in my variable"];
// .....

In "XCode" you need to make import, create object by declaring it as the property, and then use "object.variable" syntax. The file "Class2.m" would look in the following way:
#import Class2.h
#import Class1.h;
#interface Class2 ()
...
#property (nonatomic, strong) Class1 *class1;
...
#end
#implementation Class2
//accessing the variable from balloon.h
...class1.variableFromClass1...;
...
#end
Thanks! :-)

Related

Subclass of class with synthesized readonly property cannot access instance variable in Objective-C

In the superclass MyClass:
#interface MyClass : NSObject
#property (nonatomic, strong, readonly) NSString *pString;
#end
#implementation MyClass
#synthesize pString = _pString;
#end
In the subclass MySubclass
#interface MySubclass : MyClass
#end
#implementation MySubclass
- (id)init {
if (self = [super init]) {
_pString = #"Some string";
}
return self;
}
The problem is that the compiler doesn't think that _pString is a member of MySubclass, but I have no problem accessing it in MyClass.
What am I missing?
The instance variable _pString produced by #synthesize is private to MyClass. You need to make it protected in order for MySubclass to be able to access it.
Add an ivar declaration for _pString in the #protected section of MyClass, like this:
#interface MyClass : NSObject {
#protected
NSString *_pString;
}
#property (nonatomic, strong, readonly) NSString *pString;
#end
Now synthesize the accessors as usual, and your variable will become accessible to your subclass.
I am familiar with this problem. You synthesize the variable in your .m class, so it is not imported along with the header since the _pString variable will be created as part of the implementation, and not the interface. The solution is to declare _pString in your header interface and then synthesize it anyway (it will use the existing variable instead of creating a private one).
#interface MyClass : NSObject
{
NSString *_pString; //Don't worry, it will not be public
}
#property (nonatomic, strong, readonly) NSString *pString;
#end
The given answer works perfectly fine. This is an alternative answer, that apparently Apple likes a bit more.
You can define a private extension of your class, a MyClass+Protected.h file, which needs to be included in MyClass.m and MySubclass.m.
Then, in this new file, you redefine the property as readwrite.
#interface MyClass ()
#property (strong, readwrite) NSString * pString;
#end
This alternative allows you to use the accessor self.pString rather than the ivar _pString.
Note: you still need to keep the definition of pString in your MyClass.h as is.

Access private instance variable of parent class

I can't figure out why class B can access class A private instance variable.
Here is my code
A.h
#import <Foundation/Foundation.h>
#interface A : NSObject
{
#private
int x;
}
#property int x;
-(void)printX;
#end
A.m
#import "A.h"
#implementation A
#synthesize x;
-(void)printX
{
NSLog(#"%i", x);
}
#end
B.h
#import "A.h"
#interface B : A
{
}
#end
main.m
B *tr = [[B alloc] init];
tr.x = 10;
[tr printX];
Here I can access instance variable of A class x despite it is declarated as private ?
You are not accessing the private variable there, at least not directly: you are accessing a public property, which has legitimate access to the private ivar.
Your code is equivalent to this:
B *tr = [[B alloc] init];
[tr setX:10];
[tr printX];
The #synthesize statement created the getter and the setter methods for you. If you want only a getter to be available, mark your property readonly, and do all writings through an ivar in the A class.
In your implementation file do this on the top..
#interface A : NSObject
{
#private
int x;
}
#property int x;
#end
this way x will be private since it is in the implementation file. not the interface section...all classes import the interface section of A ..so it's variable are accessible to its subclasses.

Accessing variables in another class

I have integers in a class1 that i need to use in class2. I imported the .h file for class1 in the .m file of class2, but i still can't access the variable. Don't know why! :(
I even created a property for each integer in the .h file of class1 and synthesized it in the .m file.
Anyone know what the problem is?
basically, this is what i have in class1.h
//interface here
{
NSInteger row;
NSInteger section;
}
#property NSInteger row;
#property NSInteger section;
and this is the .m file for class1.
//implementation
#synthesize section = _section;
#synthesize row = _row;
and then in the implementation of class2, i have this
#import "Class2.h"
#import "Class1.h"
How do i access those integers in a method in class 2?
You need to create an instance (object) of class1 to be able to access the properties (variables).
// Create an instance of Class1
Class1 *class1Instance = [[Class1 alloc] init];
// Now, you can access properties to write
class1Instance.intProperty = 5;
class1Instance.StringProperty = #"Hello world!";
// and to read
int value1 = class1Instance.intProperty;
String *value2 = class1Instance.StringProperty;
Edit
// Create an instance of Class1
Class1 *class1Instance = [[Class1 alloc] init];
// Now, you can access properties to write
class1Instance.row = 5;
class1Instance.section = 10;
// and to read
NSInteger rowValue = class1Instance.row;
NSInteger sectionValue = class1Instance.section;
I shared the answer for the similar issue (take a look at How can I access variables from another class?). However, I could repeat it here.
In "XCode" you need to make import, create object by declaring it as the property, and then use "object.variable" syntax. The file "Class2.m" would look in the following way:
#import Class2.h
#import Class1.h;
#interface Class2 ()
...
#property (nonatomic, strong) Class1 *class1;
...
#end
#implementation Class2
//accessing the variable from balloon.h
...class1.variableFromClass1...;
...
#end

How can I assign values to other class variable in objective-c

The below coding is working and I can see the values in my second screen. But I am using the same in other classes with different variables in this format. But it dosent show me the variable if after i type the classname with a dot. I cant figure this out. Is there any way to pass values to other class.
InstallProfiler_2 *installProfiler2 = [[InstallProfiler_2 alloc] initWithNibName:#"InstallProfiler_2" bundle:nil];
installProfiler2.profilerType2 = profilerType;
[self.navigationController pushViewController:installProfiler2 animated:NO];
[installProfiler2 release];
Make sure that:
You have imported the class header.
The #property declarations are in this header and not a class extension.
#property refers to ivars so when you say
if after i type the classname with a dot
this terminology is incorrect, you probably mean after you start typing the name of the variable which has points to an instance of a class.
ClassA.h
#interface ClassA : NSObject
#property (nonatomic, weak) NSInteger myInt;
#end
ClassA.m
#implementation ClassA
#synthesize myInt = _myInt;
#end
ClassB.m
#import "ClassA.h" // <- Import the header of the class
# implementation ClassB
// .. other methods and stuff
- (void)myMethod;
{
ClassA *instanceOfClassA = [[ClassA alloc] init]; // <- Working with an instance not a class
instanceOfClassA.myInt = 1;
}
#end
UPDATE
Make sure your #property () does not have readonly between the round brackets.
Also make sure you have either #synthesize'd the ivar in the implementation or have provided both a getter and a setter for the ivar.
Failing that show some relevant code so we can actually see what your doing - we are answering pretty blindly here.
The dot syntax is only available with property/synthesize
Create a custom setter/getter:
+ (BOOL)awesomeClassVar {
return _classVar;
}
+ (void)setAwesomeClassVar:(BOOL)newVar {
_classVar = newVar;
}
then call as a method from the other class:
BOOL theOtherClassVar = [AwesomeClass awesomeClassVar];
[AwesomeClass setAwesomeClassVar:!theOtherClassVar];

Hide instance variable from header file in Objective C

I came across a library written in Objective C (I only have the header file and the .a binary).
In the header file, it is like this:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject anObject;
- (void)someMethod;
How can I achieve the same thing? If I try to declare a property without its corresponding ivar inside the interface's {}, the compiler will give me an error. Ultimately, I want to hide the internal structure of my class inside the .a, and just expose the necessary methods to the header file. How do I declare instance variables inside the .m? Categories don't allow me to add ivar, just methods.
For 64 bit applications and iPhone applications (though not in the simulator), property synthesis is also capable of synthesizing the storage for an instance variable.
I.e. this works:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject *anObject;
#end
#implementation MyClass
#synthesize anObject;
#end
If you compile for 32 bit Mac OS X or the iPhone Simulator, the compiler will give an error.
You may use of the same idiom used in Cocoa classes. If you have a look to NSString class interface in NSString.h you'll see that there is no instance variable declared. Going deeper in GNUstep source code you'll find the trick.
Consider the following code.
MyClass.h
#interface MyClass : NSObject
// Your methods here
- (void) doSomething;
#end
MyClass.m
#interface MyClassImpl : MyClass {
// Your private and hidden instance variables here
}
#end
#implementation MyClass
+ (id) allocWithZone:(NSZone *)zone
{
return NSAllocateObject([MyClassImpl class], 0, zone);
}
// Your methods here
- (void) doSomething {
// This method is considered as pure virtual and cannot be invoked
[self doesNotRecognizeSelector: _cmd];
}
#end
#implementation MyClassImpl
// Your methods here
- (void) doSomething {
// A real implementation of doSomething
}
#end
As you can see, the trick consist in overloading allocWithZone: in your class. This code is invoked by default alloc provided by NSObject, so you don't have to worry about which allocating method should be used (both are valid). In such allocWithZone:, you may use the Foundation function NSAllocateObject() to allocate memory and initialize isa for a MyClassImpl object instead of MyClass. After that, the user is dealing with a MyClassImpl object transparently.
Of course, the real implementation of your class shall be provided by MyClassImpl. The methods for MyClass shall be implemented in a way that considers a message receiving as an error.
You can use a class extension. A class extension is similar as category but without any name. On the Apple documentation they just define private methods but in fact you can also declare your internal variables.
MyClass.h
#class PublicClass;
// Public interface
#interface MyClass : NSObject
#property (nonatomic, retain) PublicClass *publicVar;
#property (nonatomic, retain) PublicClass *publicVarDiffInternal;
- (void)publicMethod;
#end
MyClass.m
#import "PublicClass.h"
#import "InternalClass.h"
// Private interface
#interface MyClass ( /* class extension */ )
{
#private
// Internal variable only used internally
NSInteger defaultSize;
// Internal variable only used internally as private property
InternalClass *internalVar;
#private
// Internal variable exposed as public property
PublicClass *publicVar;
// Internal variable exposed as public property with an other name
PublicClass *myFooVar;
}
#property (nonatomic, retain) InternalClass *internalVar;
- (void)privateMethod;
#end
// Full implementation of MyClass
#implementation MyClass
#synthesize internalVar;
#synthesize publicVar;
#synthesize publicVarDiffInternal = myFooVar
- (void)privateMethod
{
}
- (void)publicMethod
{
}
- (id)init
{
if ((self = [super init]))
{
defaultSize = 512;
self.internalVar = nil;
self.publicVar = nil;
self.publicVarDiffInternal = nil; // initialize myFooVar
}
return self;
}
#end
You can give MyClass.h to anyone with just your public API and public properties. On MyClass.m you declare your member variable private and public, and your private methods, on your class extension.
Like this it's easy to expose public interfaces and hide detail implementation. I used on my project without any troubles.
According to the documentation I've been looking at there is no problem. All you have to do to hide instance variables is to declare them at the start of the #implementation section, inside { ... }. However, I'm a relative newcomer to Objective C and there's a chance I have misunderstood something - I suspect that the language has changed. I have actually tried this system, using XCode 4.2, building code for the iPad, and it seems to work fine.
One of my sources for this idea is the Apple developer documentation at http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocDefiningClasses.html, which gives this pattern:
#implementation ClassName
{
// Instance variable declarations.
}
// Method definitions.
#end
Two possibilities:
It could be taking advantage of the modern runtime's ability to synthesize instance variables, as bbum suggested.
The property might not have an underlying instance variable in that class. Properties do not necessarily have a one-to-one mapping with instance variables.
No you can't. But you can do this if you're not using #property:
.h
#interface X : Y {
struct X_Impl* impl;
}
-(int)getValue;
#end
.m
struct X_Impl {
int value;
};
...
#implementation X
-(void)getValue {
return impl->value * impl->value;
}
#end
How about a macro trick?
Have tested code below
have tested with dylibs - worked fine
have tested subclassing - Warning! will break, I agree this makes the trick not that useful, but still I think it tells some about how ObjC works...
MyClass.h
#interface MyClass : NSObject {
#ifdef MYCLASS_CONTENT
MYCLASS_CONTENT // Nothing revealed here
#endif
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, assign) int extra;
- (id)initWithString:(NSString*)str;
#end
MyClass.m
// Define the required Class content here before the #import "MyClass.h"
#define MYCLASS_CONTENT \
NSString *_name; \
int _extra; \
int _hiddenThing;
#import "MyClass.h"
#implementation MyClass
#synthesize name=_name;
#synthesize extra=_extra;
- (id)initWithString:(NSString*)str
{
self = [super init];
if (self) {
self.name = str;
self.extra = 17;
_hiddenThing = 19;
}
return self;
}
- (void)dealloc
{
[_name release];
[super dealloc];
}
#end
DON'T do this, but I feel it should be noted that the runtime has the ability to add ivars whenever you want with class_addIvar
I was able to do the following in my library:
myLib.h:
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end
The protocol is optional of course. I believe this also makes all your instance variables private though I'm not 100% certain. For me it's just an interface to my static library so it doesn't really matter.
Anyway, I hope this helps you out. To anyone else reading this, do let me know if this is bad in general or has any unforeseen consequences. I'm pretty new to Obj-C myself so I could always use the advice of the experienced.
I don't think the following code written in another answer is working as expected.
The "SomeClass *someVars" defined in the extension class is not an instance variable of MyClass. I think it is a C global variable. If you synthesize someVars, you will get compile error. And self.someVars won't work either.
myLib.h
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end