How to access instance variable which is defined in class viewController.
ViewController.h
#interface ViewController : UIViewController
{
Class1* class1;
}
ViewController.m
#implementation ViewController
class1 = [[Class1 alloc]init];
#end
Class1.h
#interface Class1 : NSObject
{
NSMutableArray* variablesArray;
}
#property NSMutableArray* variablesArray;
Class1.m
#implementation Class1
#synthesize variablesArray;
#end
Now I would like to access to instance "class1" variable "variablesArray" from Class2.m. I want to add and get objects from MutableArray "variablesArray". Is it possible?
Yes it is Possible.
Make object of other class and access the variable.
In claas2 import Class1 (#import "Class1")
Class1 *objClass1= [[Class1 alloc] init];
now access like
[objClass1.variableArray addObject:#"object"];
[objClass1.variableArray objectAtIndex:0];
If you want to access same instance of array make a Singleton Class
by adding this class method in your class
+ (Class1 *)sharedInstance
{
static Class1 *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,
^{
shared = [[self alloc] init];
});
return shared;
}
and access in Class2 like
[[Class1 sharedInstance] variableAray];
Hey you can access variable in another class by Simple making property of the variable like this
#property(nonatomic, strong) NSString *str;
I gave an Answer close to this please check this link
You can access the public property of a class instance by simple using the dot-operator. Notice that there are several ways to encapsulate an instance variable by setting property attributes like (readwrite, readonly).
Class1 aClass = [[Class1 alloc] init];
aClass.varibalesArray addObject:#[ #"someObject" ];
Make sure you initialize the NSMutableArray correctly in the init method of Class1
- (id)init
{
self = [super init];
if (self) {
_variablesArray = [NSMutableArray array];
}
return self;
}
Related
I have a class (singleton class) that has three global static variables. Each of these static variables has the same type (another class that has a custom init method).
When I want to initialize the static variables, one of them has the value "nil" even if the custom init method returns a valid instance.
Please consider the above code.
//The header file of the singleton class
#import "B.h"
static B *firstVariable;
static B *secondVariable;
static B *thirdVariable;
#interface A : NSObject
//some properties and methods declarations here
#end
//The implementation file of the singleton class
#import "A.h"
#implementation A
static A *sharedInstance = nil;
+ (A *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[A alloc] init];
}
return sharedInstance;
}
...
#end
//The header file for the other class
#interface B : NSObject
#property(nonatomic, strong, readonly) NSString *path;
- (instancetype)initWithPath:(NSString *)path;
#end
//The implementation of this class
#import "B.h"
#implementation B
- (instancetype)initWithPath:(NSString *)path {
self = [super init];
if (self) {
_path = path;
}
return self;
}
#end
This is how I try to initialize those static variables
firstVariable = [[B alloc] initWithPath:#"firstPath"];
secondVariable = [[B alloc] initWithPath:#"secondPath"];
thirdVariable = [[B alloc] initWithPath:#"thirdPath"];
As I previously mentioned, even if there is a valid instance inside of the "initWithPath" method before returning, the "secondVariable" has the "nil" value.
Can anyone help me out with this?
I am working on a project that contains a Singleton instance of a class called Survey. Within that singleton instance is a property called "itemArray," which is an NSMutableArray that contains any number of instances of an Item class.
My Items class contains several NSInteger properties, but for the purposes of the application, I need to initialize all NSIntegers with a value of -1 instead of the default 0.
Now, for my Survey class (the one with the Singleton instance), I use the following method in the implementation to change the default value of a property:
-(id)init {
if (self = [super init]) {
_thingy = -1;
}
return self;
}
This works, but for some reason, the same exact syntax (with different properties) doesn't work for instances of my Item instances. For what it's worth, the following codeblock is the creation of 2 instances of Item, and their insertion into itemArray. I also tried the Item *item1 = [[Item alloc]init; method to no avail.
Item *item1;
[[[Survey sharedInstance]itemArray]insertObject:item1 atIndex:0];
Item *item2;
[[[Survey sharedInstance]itemArray]insertObject:item2 atIndex:1];
}
I would appreciate any assistance.
!!!!!UPDATE!!!!!
I entered the following conditional:
if (![[Survey sharedInstance]itemArray]){
NSLog(#"Test");
}
And the "test" logged onto the console, so it looks like the itemArray isn't being initialized. I'm not sure how to actually initialize it, though. When I try the following:
[[Survey sharedInstance]addressArray] = [[NSMutableArray alloc]init];
I'm getting an error saying "Expression is not assignable."
Survey.h:
#import <Foundation/Foundation.h>
#interface Survey : NSObject
+(instancetype)sharedInstance;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *emailAddress;
#property (nonatomic, assign) NSInteger trigger1;
#property (nonatomic, assign) NSInteger trigger2;
#property (nonatomic, assign) NSInteger trigger3;
#property (nonatomic, assign) NSInteger activeItem;
#property (nonatomic, strong) NSMutableArray *itemArray;
#end
Survey.m
#import "Survey.h"
#implementation Survey
+ (instancetype)sharedInstance {
static Survey *_instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[Survey alloc] init];
});
return _instance;
}
-(id)init {
if (self = [super init]) {
_storage = -1;
}
return self;
}
#end
Instead of
[[Survey sharedInstance]addressArray] = [[NSMutableArray alloc]init];
you need to use
[Survey sharedInstance].addressArray = [[NSMutableArray alloc]init];
or
[[Survey sharedInstance] setAddressArray:[[NSMutableArray alloc]init]];
You were trying to assign a value to the return value of a getter method, which is not possible, so the compiler was saying "Expression not assignable." You need to use the setter method or dot notation instead.
ClassA.h
...
#property (weak, nonatomic) NSString *myVariable;
- (id) setMyVariable:(NSString *)string;
- (id) getMyVariable;
ClassA.m
...
#synthezise myVariable = _myVariable;
... some inits
- (id) setMyVariable:(NSString *)string {
_myVariable = string;
NSLog(#"here nslog success return new value: ", _myVariable);
return _myVariable;
}
- (id) getMyVariable {
NSLog(#"here nslog return nil", _myVariable);
return _myVariable;
}
ClassB.m
#import ClassA.h
...
ClassA *classA = [[ClassA alloc] init];
[classA setMyVariable:#"some"];
ClassC.m
#import ClassA.h
...
ClassA *classA = [[ClassA alloc] init];
NSLog(#"here nslog returns nil: #%", [classA getMyVariable]);
Why does [ClassC getMyVariable] return nil? Same result when I try to set value directly without setter and getter. I already read other topics on StackOverflow and Google, but have not idea why it doesn't work.
Your whole code is a bit of a mess really. Why are you using a weak property? Why are you using a #synthezise since this is is automatically done by xcode for you along with the getters and setters so you don't need to create them ever.
The reason why your [classA getMyVariable]; is nil in ClassC is because you create a new instance of it on the line above. By the looks of what you are trying to do is you want to set the variable for instance of a class in one class and access that variable on the same instance in a different class. So one method of doing this is to use a singleton, these are sometimes not liked but I think they work well and don't see a reason why some (not all) developers don't like them.
So lets do some cleaning up and try implementing a singleton
ClassA.h
#interface ClassA : NSObject
#property (nonatomic, strong) NSString *myVariable;
// No need for you to create any getters or setters.
// This is the method we will call to get the shared instance of the class.
+ (id)sharedInstance;
#end
ClassA.m
#import "ClassA.h"
#implementation ClassA
// No need to add a #synthezise as this is automatically done by xcode for you.
+ (id)sharedInstance
{
static ClassA *sharedClassA = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// If there isn't already an instance created then alloc init one.
sharedClassA = [[self alloc] init];
});
// Return the sharedInstance of our class.
return sharedClassA;
}
#end
Right so we have cleaned our ClassA code up and added a method for getting a shared instance of ClassA so now to ClassB
ClassB.m
// Other code in ClassB
// Get the shared instance
ClassA *classA = [ClassA sharedInstance];
// Set the value to the property on our instance.
[classA setMyVariable:#"Some String Value"];
//........
Now that ClassB has set the variable we can go to ClassC now and look at it.
// Other code in ClassC
// We still need to have an instance of classA but we are getting the sharedInstance
// and not creating a new one.
ClassA *classA = [ClassA sharedInstance];
NSLog(#"My variable on my shared instance = %#", [classA myVariable]);
//........
Might help if you read this and this for help on understanding different design patterns
because you don't set a value after creating an object. i should be like this:
ClassA *classA = [ClassA alloc] init];
[classA setMyVariable:#"some"];
NSLog(#"not nil anymore: #%", [classA getMyVariable]);
BTW: the #property tag provides two keywords to set getter and setter methods.
#property (weak, nonatomic, getter=myVariable, setter=setMyVariable:) NSString *myVariable;
and apple avoids the word "get" in getter-methods...
I have a shared singleton classNSMutableArray [ICGlobals sharedApplianceCount](first time using this pattern so bear with me if ive done something really silly here)
.h
#import <Foundation/Foundation.h>
#interface ICGlobals : NSObject
{
NSMutableArray* applianceCount;
}
#property (nonatomic, retain) NSString *applianceCount;
+ (ICGlobals *)sharedApplianceCount;
#end
.m
#import "ICGlobals.h"
#implementation ICGlobals
static ICGlobals *sharedApplianceCount = nil;
+ (ICGlobals *)sharedUser {
if(sharedApplianceCount == nil){
sharedApplianceCount = [[super allocWithZone:NULL] init];
}
return sharedApplianceCount;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedApplianceCount];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
#end
In "another view controller" im trying to add the row count of my table view (changeable amount of rows) = self.circuits.count
Having tried this
[[ICGlobals sharedApplianceCount] addObject: self.circuits.count,nil]];
and
[[ICGlobals sharedApplianceCount] = [[NSMutableArray alloc] init];
[[ICGlobals sharedApplianceCount] addObject: self.circuits.count,Nil]];
I get no visible #interface error saying my singleton class declares the selector
same with
NSNumber* numberOfRows = [NSNumber numberWithInteger:self.circuits.count];
[[ICGlobals sharedApplianceCount]addObject:[NSMutableArray arrayWithObjects:numberOfRows, nil]];
and with
[ICGlobals sharedApplianceCount] = self.circuits.count;
I get expression assignable. Singleton class has been imported.
You have an inconsistency in your interface declaration. You declare ivar of type NSMutableArray and then a NSString property. Firstable, you don't need to declare ivar, declaring a property does it for you. So your interface should look like:
#interface ICGlobals : NSObject
#property (nonatomic, retain) NSMutableArray *applianceCount;
+ (ICGlobals *)sharedApplianceCount;
#end
Furthermore, you have a naming glitch. You should not use name applianceCount for an array. In general, naming convention of Cocoa suggests that count should be a number (int or NSUInteger). I would change this property name to applianceCounts.
Then, when you initialize your singletone, you can also initialize the array:
+ (ICGlobals *)sharedUser
{
if(sharedApplianceCount == nil)
{
sharedApplianceCount = [[super allocWithZone:NULL] init];
sharedApplianceCount.applianceCounts = [[NSMutableArray alloc] init];
}
return sharedApplianceCount;
}
Finally, here is how to add data to your singletone's applianceCounts array from view controller.
NSNumber* numberOfRows = [NSNumber numberWithInteger:self.circuits.count];
[[ICGlobals sharedApplianceCount].applianceCounts addObject:numberOfRows];
This should point you to right direction.
I don't fully get what you are trying to achieve like I don't understand why you want to have an array there, so if you need further help please let me know in the comments.
I fully recommend you reading about naming conventions. A good start is this article:
Introduction to Coding Guidelines for Cocoa.
I would recommend some refactoring to your class.
First you make the interface like this:
#interface ICGlobals : NSObject
// add the app count but make it private, because you will provide methods to access it
#property (nonatomic, readonly) NSString *applianceCount;
// return ICGlobals instance
+ (ICGlobals)sharedCounter;
- (NSInteger)count;
- (void)addObject:(id)object;
now in .m file
#implementation ICGlobals
static ICGlobals *sharedApplianceCount = nil;
// this is your method, just changed the name
+ (ICGlobals *)sharedCounter {
if(sharedApplianceCount == nil){
sharedApplianceCount = [[super allocWithZone:NULL] init];
}
return sharedApplianceCount;
}
// instance methods goes here
- (NSInteger)count
{
return _applicationCount.count;
}
- (void)addObject:(id)object
{
[_applicationCount addObject:object];
}
Now call [[ICGlobals sharedCount]addObject:object] from any viewController
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 9 years ago.
I need to make one instance of an array that can be access by multiple view controllers. It will contain objects that will be displayed in a table view and created by a modular view and then displayed in the table view. I can't figure out how to access it once I make a #property for it in the main view controller or the AppDelegate class.
You should make a singleton and the recommended way to do that in objective-c is to create a class and add a method that looks something like:
+ (YourClass *)sharedYourClass
{
static dispatch_once_t onceToken;
static YourClass *sharedInstance;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Put the array as a property in your class.
//YourClass.h
#interface YourClass : NSObject
#property(nonatomic, strong)NSArray *yourArray;
+(YourClass *)sharedYourClass;
#end
And in every class you want to use your singleton start by importing YourClass.h and then use it like:
NSArray *arr = [YourClass sharedYourClass].yourArray;
[YourArray sharedYourClass].yourArray = [[NSArray alloc] init];
etc..
What I do is put the data I want shared, in your instance the array, in the AppDelegate. Then I define a protocol that the app delegate conforms to. This lets me access the data anywhere. For example, say I have an array I want everywhere:
First define a protocol:
#protocol ApplicationState<NSObject>
#property(nonatomic, strong) NSArray* data;
#end
Then make your app delegate conform to it:
#interface AppDelegate : UIResponder <UIApplicationDelegate, ApplicationState>
#property (strong, nonatomic) UIWindow *window;
#property(nonatomic, strong) NSArray* data;
#end
Then reading and writing this shared object is simple:
id<ApplicationState> appState = (id<ApplicationState>) [UIApplication sharedApplication].delegate;
appState.data = [[NSArray alloc] init];
I am going to assume you can make the class of the array inherit from NSObject, and then pass it to the View Controller from there...
You have 2 ways to do this:
1.- Instantiate 1 arra on the main class and pass the reference to each viewcontroller what you need.
2.- Make a singleton class to hold the array an use this in your project.
First create a class like this
//GlobalDataClass.h
#interface GlobalDataClass : NSObject
#property(nonatomic,retain)NSArray *myArray;
+(GlobalDataClass*)getInstance;
#end
#import "GlobalDataClass.h"
//GlobalDataClass.m
#implementation GlobalDataClass
#synthesize myArray;
static GlobalDataClass *instance =nil;
+(GlobalDataClass *)getInstance
{
#synchronized(self)
{
if(instance==nil)
{
instance = [GlobalDataClass new];
}
}
return instance;
}
#end
Then you can use it in your viewControllers like this:
-(void)viewDidLoad{
[super viewDidLoad];
self.dataObj = [GlobalDataClass getInstance];
NSLog(#"%#",self.dataObj.myArray);
}
Hope it helps!