how to save a variable and use it from two different classes Objective C - objective-c

I have one Class called "System" it contains some variables and two arrays and I need to access this from two other classes which should be able to read and write that variables
Im a total Beginner so its pretty possible that i already did some mistakes.
System.h
#interface System : UIViewController{
float length_of_one_hour;
float length_of_first_break;
float length_of_second_break;
float length_of_lunch_break;
float length_of_shortned_hour;
float school_begin;
int school_end[5];
float school_length[5];
}
About_now.m
- (void)read_school_end_monday{
school_end_label.text=[NSString stringWithFormat:#"%i", school_end[0]];
}
Settings.m
- (IBAction)set_school_end_monday{
school_end[0]= [school_end_on_mondays_textfield.text intValue];
}
But i don't know what to write in System.h and About_now.m that the variables are saved in System class and can be accessed from anywhere. And Yes I already tried #public and extern.
BTW I need to have an array for the school_end because I'll calculate it (in use of length of an hour and when school actually starts etc.) with a function which already works but i need to access the variables from the About_now class afterwards.
Hope there is someone who can help me. Thanks

A common way to share data across classes in iOS apps is by following the singleton pattern.
SystemModel.h
#import <Foundation/Foundation.h>
#interface SystemModel : NSObject {
#public
float length_of_one_hour;
float length_of_first_break;
float length_of_second_break;
float length_of_lunch_break;
float length_of_shortned_hour;
float school_begin;
int school_end[5];
float school_length[5];
}
+(SystemModel*)instance;
#end
SystemModel.m
#implementation SystemModel
static SystemModel* _instance= nil;
+(SystemModel*)instance {
#synchronized([SystemModel class]) {
if (!_instance)
[[self alloc] init];
return _instance;
}
return nil;
}
+(id)alloc {
#synchronized([SystemModel class]) {
return (_instance = [super alloc]);
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// your init code
}
return self;
}
#end
Now you can use your instance like this:
float tmp = [SystemModel instance]->length_of_one_hour;
You could also convert instance variables to properties, and use the dot syntax. It does not matter for floats and arrays, but for id-based objects using properties is preferred.

You need a pointer to an instance of System. So to access the member variable:
System* system = GetSystem();
system->school_end[0] = whatever();
This is exactly the same as accessing a member via a struct pointer.
But saying that, it is good practice to hide access via methods:
- (int)getSchoolEndAtIndex:(int)index
{
return school_end[index];
}

You have many design options for doing that:
create a global System object;
make the System class a Singleton;
define the System class interface so that it offers accessors methods for its "properties" at the class level (vs. object level).
instantiate System as it is now and pass it as a initialization parameter to the other two classes.
Now, in more detail:
(1) declare:
extern System* globalSystemObject;
in System.h; then define:
static System* globalSystemObject = nil;
in System.m. Don't forget to initialize globalSystemObject somewhere in your code:
globalSystemObject = [[System alloc] init];
Doing like that, you can use globalSystemObject from any file which imports System.h.
(2) have a look here for details about implementing a singleton class. Keep in mind that many people suggest against using Singleton (if it is only a way to "hide" a global variable). In this specific case, considering the semantics of a class called System, I would say a Singleton is the best option for you.
(3) your class might look like this:
#interface System : UIViewController{
}
+(float)length_of_one_hour;
+(void)set_length_of_one_hour:(float)length;
+(float)length_of_first_break;
+(void)length_of_first_break:(float)length;
...
#end
You would implement those variable in the .m file by means of static variables like in 1.
(4) this is pretty straightforward. The only thing is that you have to create the System instance and those of the other two classes in the same scope:
System* system = [[System alloc] init];
about_now* anow = [[about_now alloc] initWithSystemInstance:system];
...
The system parameter would be stored inside an ivar (or property) of about_now.
Doing like that you avoid altogether the use of global variables (even those hidden behind the Singleton mask).

You could expose the system instance variables via getters/setters (#property / #synthesize) and pass a reference to other classes instances.
#interface System : UIViewController{
float length_of_one_hour;
//...
#property (nonatomic,assign);
..
#end
OtherClass other = [[OtherClass alloc] initWithSystem:sys];
or with a setter
[other setSystem:sys];

Related

making a class variable global in throught the application

In my application there are lot of view controller in some view controller some variables are there which i want to use in other classes .my variable is not present in application delegate file so i can i make it global to use every where in my application?
In my opinion, how about using singleton pattern? So when you want to use the variables of that class, just get instance and then use the variables.
#interface MySingletonViewController : UIViewController
{
//here your variables
int globalVariables;
}
#property (nonatomic, assign) int globalVariables;
+ (MySingletonViewController *)sharedSingleton;
#end
#implementation MySingletonViewController
#synthesize globalVariables;
static MySingletonViewController *sharedSingleton = nil;
+ (MySingletonViewController *)sharedSingleton
{
#synchronized(self)
{
if (sharedSingleton == nil)
sharedSingleton = [[MySingleton alloc] init];
return sharedSingleton;
}
}
#end
UIViewController is class actually, so we can do this way : ) Hope this helpful.
Sure you can, but using global variables through entire app is definitely broken architecture design.
As Objective-C based on C, you can define variable (in you case - pointer to class) in any *.m file outside implementation part as:
MyVeryOwnClass *g_MyVeryOwnClassPointer = nil;
And access it as:
extern MyVeryOwnClass *g_MyVeryOwnClassPointer;
/* do some operations with your pointer here*/
Or move extern declaration to header file.
PS: You can use singletons. They are not the best solution, but better then using raw variable.

Is this a new way to define private instance variables in Objective-C?

I've recently updated to Xcode 4.3.2 and found that I can now declare private instance variables inside #implementation block like so:
#interface TestClass : NSObject
#property (nonatomic, copy) NSString *testProp;
#end
#implementation TestClass {
NSString *_testPropStore;
}
- (NSString *)testProp { return _testPropStore; }
- (void)setTestProp:(NSString *)testProp { _testPropStore = [testProp copy]; }
- (id)init {
if (self = [super init]) {
_testPropStore = nil;
}
return self;
}
#end
Notice the NSString *_testPropStore line inside #implementation brace block.
I've also tested with the following code:
TestClass *c1 = [[TestClass alloc] init];
TestClass *c2 = [[TestClass alloc] init];
c1.testProp = #"Hello";
c2.testProp = #"World";
NSAssert(c1.testProp == c2.testProp, #"It's working!");
Which seems to work fine. (That is, the app crashes with the "It's working" message at the NSAssert line.)
So is this a new feature of Objective-C for declaring private instance variables? Since I discovered this by accident, I would love to know if it is just for declaring private instance variables or will there be any side effects that I'm not aware of?
I couldn't find any relevant document since most questions of such type with the word private just ended up with answers on how to declare them on a private extension category which is different.
It's for real, it's the new way,* it's great, and, yes, it's in the docs. The Objective-C Programming Language, which is as close as we get to having an actual spec for the language, has the following to say:
The definition of a class is structured very much like its declaration. It begins with an #implementation directive and ends with the #end directive. In addition, the class may declare instance variables in braces after the #implementation directive:
#implementation ClassName
{
// Instance variable declarations.
}
// Method definitions.
#end
There's also a historical note a little ways back from that link, addressing the fact that we used to have to declare ivars in the interface block:
Historically, the interface required declarations of a class’s instance variables, the data structures that are part of each instance of the class. ... Instance variables represent an implementation detail, and should typically not be accessed outside of the class itself. Moreover, you can declare them in the implementation block or synthesize them using declared properties. Typically you should not, therefore, declare instance variables in the public interface and so you should omit the braces.
For the question of privacy, yes, these variables are truly private -- they act like ivars declared in the interface with the #private directive. This means that subclasses can't access them, by default. Their visibility can be changed, however, using either #protected or (if necessary for some bizarre reason) #public:
#interface Stuper : NSObject
#end
#implementation Stuper
{
#protected
NSString * sangfroid;
}
#end
#interface Stub : Stuper
- (void)setSangfroid: (NSString *)newSangfroid;
#end
#implementation Stub
- (void)setSangfroid: (NSString *)newSangfroid {
sangfroid = [newSangfroid copy];
}
*You have to use clang > 3.0, I believe, so that's just a few months ago as of this posting. GCC won't do it.
It's pretty new and it's valid as long as any compiler you need supports it.
It's great for minimizing your dependencies -- the includes and forwards may largely be in the implementation file. For this reason, and if all the compilers you use support it, then it's a better place for your ivars than in the #interface block.
A final caveat is that our current (may.2.2012) debuggers do not support this.

Singleton or Class methods [duplicate]

This question already has answers here:
What does #synchronized() do as a singleton method in objective C?
(6 answers)
Closed 3 years ago.
After reading the responses to a question about singletons in Objective C it appears that each solution makes some tradeoff in regards to threading in the instance accessor. i.e.
#synchronized(self)
{
if (sharedInstance == nil)
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
This essentially single-threads access to the singleton, and if it's something that's used frequently in an operation, seems like something that could cause threads to unnecessarily contend.
What's the downside to simply using the class object as the singleton instance, and exposing functionality via class methods, i.e.
#interface MySingleton : NSObject {
}
+ (void)doSomething;
#end
#implementation MySingleton
+ (void)initialize {
//do some setup if necessary
}
+ (void)doSomething {
//do something
}
#end
In this way we avoid doing the lock + check every time we want to reference the singleton object and we can also eliminate having to store it in a local or method ivar.
This approach also lets the runtime guarantee that only one instance (the Class object) exists in the system at any given time.
EDIT
There's more here than just threading, with a traditional singleton you usually write code like this:
MySingleton *instance = [MySingleton getSharedInstance];
NSObject *someResult = [instance getResult];
//or
if (instance.someProperty) {
//do something
}
However if your singleton is a class instance, you essentially eliminate the need call getSharedInstance all the time. Consider this code:
NSObject *someResult = [MySingleton getResult];
//or
if ([MySingleton someProperty]) {
//do something
}
I hear the point that you have to store your data in file local static variables, or in global variables (yuck). But it's really not all that different from a traditional singleton with the exception that you lose Objective-C 2.0 properties (instead you have to use traditional accessor methods).
Here's one key tradeoff for me that seems like a win. In a traditional singleton you end up overriding -copyWithZone, +allocWithZone, -retain, -retainCount, -release and -autorelease if you really want to get things right.
This seems like an awful lot of work to do every time you want to write a simple Singleton object (they happen to be pretty useful). So why not simply just replace it with this:
#implementation MySingleton
+ (void)initialize {
//do your setup
}
- (id)init {
NSAssert(NO, #"You should read the documentation on singletons.");
}
#end
It's a lot lighter in terms of code, and unless your consumers are really sneaky they won't ever create two instances.
Get to the point already
My question is really this:
Is there any drawback to using the Class object as the instance of your singleton?
It seems like you can take all the same steps in terms of threadsafety, memory efficiency etc. without having to remember to override so many methods and accessors or litter your code with instance checks.
With iOS 4.0 or later, by far the best solution is to just use dispatch_once, as in
+ (id)sharedInstance {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedInstance = [[MyClass alloc] init];
});
return sharedInstance;
}
You may also want to consider using a single dispatch_queue to serialize access to the internals of a class. If all your public methods just run a block on the same dispatch_queue then you won't have to worry about concurrency issues.
This is my first post on Stack Overflow... (so prepare for stupidity)
I think there is a hybrid solution that might be useful.
I want to set and get (global) values out of a singleton class without having calling "getSharedInstance". I'd want the code to look like this...
frameRate = Singleton.frameRate;
Singleton.frameRate = 42;
To achieve this, each variable we need to store in the singleton has a getter and setter class method. The class method then goes to an instance to store the data in an ivar. The instance isn't directly accessed by the main program.
The getter looks like this:
+ (int) frameRate
{
return [[Singleton instance] ivarFrameRate];
}
The (ugly) instance call is hidden inside the class code.
By calling the instance method here, the class method will automatically instantiate an object when first used. Once the singleton is instantiated, the instance stores ivars conventionally. Here, I am prefixing with "ivar" make the ivar explicit.
#property int ivarFrameRate;
and
#synthesize ivarFrameRate;
This automatically creates conventional getter (and setter) methods to access the ivar.
(edit - here is a complete example)
// Singleton.h
#import <Foundation/Foundation.h>
#interface Singleton : NSObject
{
float ivarFrameRate
}
#property float ivarFrameRate;
- (id) init;
+ (Singleton *) instance;
+ (float) frameRate;
+ (void) setFrameRate:(float)fr;
#end
and
// Singleton.m
#import "Singleton.h"
#implementation Singleton
#synthesize ivarFrameRate;
static Singleton* gInstance = NULL;
+ (Singleton*)instance
{
#synchronized(self)
{
if (gInstance == NULL)
gInstance = [[self alloc] init];
}
return(gInstance);
}
- (id)init
{
self = [super init];
return self;
}
+ (float) frameRate
{
return [[Singleton instance] ivarFrameRate];
}
+ (void) setFrameRate:(float)fr;
{
[[Singleton instance] setIvarFrameRate:fr];
}
This is fine, but still just changes your circumstances rather than fixes your problems. Unless you don't have any actual data tied to your singleton, in which case this will work just fine. Anytime you access central data you will need to properly make it thread-safe.
Additionally, without some kind of iVar I don't know of a way to store data (that is intended) directly in a class.
In the example above I would code it in this way, getting the same result as you are proposing and only taking the performance hit if we are creating/re-creating the singleton:
if (sharedInstance)
return sharedInstance;
#synchronized(self)
{
if (sharedInstance == nil)
sharedInstance = [[MySingleton alloc] init];
}
return sharedInstance;
Keep in mind that either way, if you are accessing data that is potentially changing on different threads then you'll have to make that code thread-safe anyway, either with very careful planning or using code to ensure there are no problems. I'd recommend a mix, but when in doubt the latter when at all possible. =)
If you use a class as your singleton, the only way to store data would be to use static file variables and global variables. If you are going to go so far that you make a class you don't plan to instantiate, you might as well just use standard C functions:
void doSomething(void);
void doSomething() {
//do something
}

Class variable defined at #implementation rather than #interface?

I'm new to Objective-C, but I am curious about something that I haven't really seen addressed anywhere else.
Could anyone tell me what is the difference between a private variable that is declared at the #interface block versus a variable that is declared within the #implementation block outside of the class methods, i.e:
#interface Someclass : NSObject {
NSString *forExample;
}
#end
vs.
#implementation Someclass
NSString *anotherExample;
-(void)methodsAndSuch {}
#end
It seems both variables ( forExample, anotherExample ) are equally accessible throughout the class and I can't really find a difference in their behaviour. Is the second form also called an instance variable?
The latter is not defining an instance variable. Rather, it is defining a global variable in the .m file. Such a variable is not unique to or part of any object instance.
Such globals have their uses (roughly equivalent C++ static members; e.g. storing a singleton instance), but normally you would define them at the top of the file before the #implementation directive.
They're very different! The one in #implementation is a global variable not unique to each instance. Imagine there were accessors for both variables, written in the obvious way. Then the difference in behavior is shown here:
Someclass* firstObject = [[Someclass alloc] init];
Someclass* secondObject = [[Someclass alloc] init];
//forExample is an instance variable, and is unique to each instance.
[firstObject setForExample:#"One"];
[secondObject setForExample:#"Two"];
NSLog(#"%#",[firstObject forExample]); //Result: "One"
NSLog(#"%#",[secondObject forExample]); //Result: "Two"
//anotherExample is a global variable, and is NOT unique to each instance.
[firstObject setAnotherExample:#"One"];
[secondObject setAnotherExample:#"Two"];
NSLog(#"%#",[firstObject anotherExample]); //Result: "Two" (!)
NSLog(#"%#",[secondObject anotherExample]); //Result: "Two"
//Both instances return "Two" because there is only ONE variable this time.
//When secondObject set it, it replaced the value that firstObject set.
If you are looking for this sort of behavior, you might be better off using a class variable, like this:
static NSString* yetAnotherExample = nil;
Then you can use class methods to interact with the variable, and it's clearly class-specific (as opposed to instance-specific or global).
If you declare a variable inside the #implementation section, you're actually creating a global variable, visible everywhere (in every method in your application).
Member variables can only be declared in the #interface section. They are only accessible in the class itself.
The private block declared inside the #implementation block is kind of dangerous, seems to me, comparing with other OOP concept e.g. Java. Its look like member variable but kinda static.
Novice programmer can easily fooled with it. I write a test program and surprised with the behaviour.
#interface SomeClass : NSObject
{
NSString *forExample;
}
- (void) set:(NSString *)one another:(NSString *)another;
- (void)print;
#end
Implementation:
#import "SomeClass.h"
#implementation SomeClass
NSString *anotherExample;
- (void) set:(NSString *)one another:(NSString *)another
{
forExample = one;
anotherExample = another;
}
- (void)print{
NSLog(#"One = %#, another = %#", forExample, anotherExample);
}
#end
Test:
- (void)testClass {
SomeClass * s1 = [SomeClass new];
[s1 set:#"one one" another:#"one another"];
SomeClass *s2 = [SomeClass new];
[s2 set:#"two one" another:#"two another"];
[s1 print];
[s2 print];
}
And the output is,
One = one one, another = two another
One = two one, another = two another
Use a code snippet to tell the difference between a member variable and a global variable:
#implementation MyClass {
// It is an ivar, or called member variable
// Can NOT be initialized when defined.
// Can be accessed with `self->_i`
int _i;
}
- (instancetype)init {
if (self = [super init]) {
_i = 2; // should be initialized before being used.
}
return self;
}
int i = 9; // Global variable, and can be initialized when defined.
- (void)myFun {
NSLog(#"%i, %i", self->_i, i);
}
#end
// Another file
extern int i;
NSLog(#"%i", i);
Just to be clear, never ever ever declare an IBOutlet as a global var (in the implementation) if you are using it for localized nibs/xibs.
I spent a few hours figuring why the outlet is connectable only in one of the localized nibs at any given time.
Thanks for this question and the answers!

Objective-C Static Class Level variables

I have a class Film, each of which stores a unique ID. In C#, Java etc I can define a static int currentID and each time i set the ID i can increase the currentID and the change occurs at the class level not object level. Can this be done in Objective-C? I've found it very hard to find an answer for this.
Issue Description:
You want your ClassA to have a ClassB class variable.
You are using Objective-C as programming language.
Objective-C does not support class variables as C++ does.
One Alternative:
Simulate a class variable behavior using Objective-C features
Declare/Define an static variable within the classA.m so it will be only accessible for the classA methods (and everything you put inside classA.m).
Overwrite the NSObject initialize class method to initialize just once the static variable with an instance of ClassB.
You will be wondering, why should I overwrite the NSObject initialize method. Apple documentation about this method has the answer: "The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.)".
Feel free to use the static variable within any ClassA class/instance method.
Code sample:
file: classA.m
static ClassB *classVariableName = nil;
#implementation ClassA
...
+(void) initialize
{
if (! classVariableName)
classVariableName = [[ClassB alloc] init];
}
+(void) classMethodName
{
[classVariableName doSomething];
}
-(void) instanceMethodName
{
[classVariableName doSomething];
}
...
#end
References:
Class variables explained comparing Objective-C and C++ approaches
As of Xcode 8, you can define class properties in Obj-C. This has been added to interoperate with Swift's static properties.
Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: #property (class) NSString *someStringProperty;. They are never synthesized. (23891898)
Here is an example
#interface YourClass : NSObject
#property (class, nonatomic, assign) NSInteger currentId;
#end
#implementation YourClass
static NSInteger _currentId = 0;
+ (NSInteger)currentId {
return _currentId;
}
+ (void)setCurrentId:(NSInteger)newValue {
_currentId = newValue;
}
#end
Then you can access it like this:
YourClass.currentId = 1;
val = YourClass.currentId;
Here is a very interesting explanatory post I used as a reference to edit this old answer.
2011 Answer: (don't use this, it's terrible)
If you really really don't want to declare a global variable, there another option, maybe not very orthodox :-), but works... You can declare a "get&set" method like this, with an static variable inside:
+ (NSString*)testHolder:(NSString*)_test {
static NSString *test;
if(_test != nil) {
if(test != nil)
[test release];
test = [_test retain];
}
// if(test == nil)
// test = #"Initialize the var here if you need to";
return test;
}
So, if you need to get the value, just call:
NSString *testVal = [MyClass testHolder:nil]
And then, when you want to set it:
[MyClass testHolder:testVal]
In the case you want to be able to set this pseudo-static-var to nil, you can declare testHolder as this:
+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
static NSString *test;
if(shouldSet) {
if(test != nil)
[test release];
test = [_test retain];
}
return test;
}
And two handy methods:
+ (NSString*)test {
return [MyClass testHolderSet:NO newValue:nil];
}
+ (void)setTest:(NSString*)_test {
[MyClass testHolderSet:YES newValue:_test];
}
Hope it helps! Good luck.
On your .m file, you can declare a variable as static:
static ClassName *variableName = nil;
Then you can initialize it on your +(void)initialize method.
Please note that this is a plain C static variable and is not static in the sense Java or C# consider it, but will yield similar results.
In your .m file, declare a file global variable:
static int currentID = 1;
then in your init routine, refernce that:
- (id) init
{
self = [super init];
if (self != nil) {
_myID = currentID++; // not thread safe
}
return self;
}
or if it needs to change at some other time (eg in your openConnection method), then increment it there. Remember it is not thread safe as is, you'll need to do syncronization (or better yet, use an atomic add) if there may be any threading issues.
As pgb said, there are no "class variables," only "instance variables." The objective-c way of doing class variables is a static global variable inside the .m file of the class. The "static" ensures that the variable can not be used outside of that file (i.e. it can't be extern).
Here would be an option:
+(int)getId{
static int id;
//Do anything you need to update the ID here
return id;
}
Note that this method will be the only method to access id, so you will have to update it somehow in this code.
(Strictly speaking not an answer to the question, but in my experience likely to be useful when looking for class variables)
A class method can often play many of the roles a class variable would in other languages (e.g. changed configuration during tests):
#interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
#end
#implementation
+ (NSString*)theNameThing { return #"Something general"; }
- (void)doTheThing {
[SomeResource changeSomething:[self.class theNameThing]];
}
#end
#interface MySpecialCase: MyCls
#end
#implementation
+ (NSString*)theNameThing { return #"Something specific"; }
#end
Now, an object of class MyCls calls Resource:changeSomething: with the string #"Something general" upon a call to doTheThing:, but an object derived from MySpecialCase with the string #"Something specific".
u can rename the class as classA.mm and add C++ features in it.
Another possibility would be to have a little NSNumber subclass singleton.