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?
Related
I've got a singleton class named MyManager which holds multiple of properties. One of these properties is a custom class I've made that inherits from NSObject and also holds multiple properties.
One of my ViewControllers changes one of the properties in the MyManager class but for some reason, it also changes a property (with the same name), but inside the custom object.
To explain:
MyManager:
Custom object
objectThatGetsSet (inside custom object)
objectThatGetsSet
Once I set the objectThatGetsSet in MyManager, it also get's set inside the custom object. Why is this and how can I avoid it?
Here's the MyManager header file:
#import <Foundation/Foundation.h>
#import "myClass.h"
#interface MyManager : NSObject
#property (nonatomic, strong) NSDate *objectThatGetsSet;
#property (nonatmoc, strong) myClass *customObject;
+(id)sharedManager;
#end
And here's the implementation file:
#import "MyManager.h"
#implementation MyManager
#synthesize objectThatGetsSet, customObject;
#pragma mark Singleton Methods;
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
-(id)init {
if (self == [super init]) {
}
return self;
}
#end
Here's the custom class header file:
#import <Foundation/Foundation.h>
#interface myClass : NSObject
#property (nonatomic, strong) myClass objectThatGetsSet;
#end
And the implementation file:
#import "WorkLocationModel.h"
#implementation WorkLocationModel
-(id)init {
// Init self
self = [super init];
if (self)
{
// Setup
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.objectThatGetsSet forKey:#"objectThatGetsSet"];
}
-(instancetype)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self)
self.objectThatGetsSet = [coder decodeObjectForKey:#"objectThatGetsSet"];
return self;
}
#end
Please help me with this, thanks a lot!
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...
So I was having issues where I had circular dependencies and so I am trying to implement forward declaration. I have three classes (logger, api, helpers), all of which are singleton objects. I have one controller class (globalclass), that has properties linking to the three classes.
Here is my code:
includes.h:
#import "globalclass.h"
#import "logger.h"
#import "api.h"
#import "helpers.h"
globalclass.h:
#class logger
#class api
#class helpers
#interface globalclass : NSObject
+ (id) sharedGlobal;
- (id) init;
...
#property (nonatomic, strong) logger *log;
#property (nonatomic, strong) api *remote;
#property (nonatmoic, strong) helpers *utils;
...
logger/api/helpers.h templates:
#class globalclass
#interface logger : NSObject
+ (id) sharedLogger;
- (id) init;
...
#property (nonatomic, strong) globalclass *gc;
...
globalclass.m:
#import "includes.h"
#implementation globalclass
/*
* Singleton Class
*/
+ (id) sharedGlobal
{
static globalclass *sharedGlobalClass = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedGlobalClass = [[self alloc] init];
});
return sharedGlobalClass;
}
/*
* Init
*/
- (id) init
{
self = [super init];
if (!self) return nil;
// Logging
self.logger = [logger sharedLogger];
...
return self;
}
logger/api/helpers.m template:
#import "includes.h"
#implementation logger
/*
* Singleton Class
*/
+ (id) sharedLogger
{
static logger *sharedLog = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedLog = [[self alloc] init];
});
return sharedLog;
}
/*
* Init
*/
- (id) init
{
self = [super init];
if (!self) return nil;
// Global Class
self.gc = [GlobalClass sharedGlobal];
...
return self;
}
Then, in my AppDelegate, I have a property to the global class and am doing this:
self.gc = [GlobalClass sharedGlobal];
However, it seems that everytime I boot up my app, it stalls and is automatically terminated because it takes too long to boot up.
Am I thinking about forward globals incorrectly?
The app builds fine.
Any help would be appreciated.
Thanks.
You have a deadlock, because the dispatch_once block in sharedGlobal is (via the global class init) invoking sharedLogger, which itself is invoking sharedGlobal (via the logger class init).
Since everything is singletons, there are a few approaches you could take to avoid this issue. Here are two:
A. Replace any self.log usages in the global class with [logger sharedLogger], and replace any self.gc usages in the logger class with [globalclass sharedGlobal]. You can get rid of these properties entirely. dispatch_once is very fast after the first invocation, so performance is not a reason to store reference to singletons as properties (though you could conceivably have other reasons)
B. Keep the log and gc properties, but make them readonly properties with custom getters:
#property (nonatomic, readonly) globalclass *gc;
// implementation:
- (globalclass *)gc
{
return [globalclass sharedGlobal];
}
#property (nonatomic, readonly) logger *log;
// implementation:
- (logger *)log
{
return [logger sharedLogger];
}
Personally I would choose A.
Both of these alternatives eliminate any references to the singleton accessors from the init methods, which gets rid of the deadlock.
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;
}
Newbie to objective C...
NOTE: This is a conceptual problem, as I'm trying to translate "public and private" from what I know about other languages.
How can I access the "stringB" ivar through the "public" method?
myClass.h
#interface myClass : UIViewController {
}
#property (nonatomic, retain) NSString *stringA;
#property (nonatomic, retain) NSString *stringB;
- (void)dealWithStringA;
+ (void)dealWithStringB;
myClass.m
#import "myClass.h"
#interface myClass () {
}
#end
#implementation myClass
// My "private" function
- (void)dealWithStringA
{
return _stringA;
}
// My "public" function
+ (void)dealWithStringB
{
// Errors with: Instance variable "stringB" accessed in class method
return _stringB;
}
The method starting with a + is called a class method in objective C where a method starting with - is an instance method. An instance method can be performed on an instance of that class only.
Also the return type for your method would be an NSString since you are expecting to get a string object from that method.
For a class method, you'll need to create an autoreleasing instance of that class and then perform operations on that instance.
For eg.
+ (NSString*)dealWithStringB
{
MyClass *myClass = [[[MyClass alloc] init] autorelease];
myClass.stringB = #"Its String B";//It's an absurd example
return myClass.stringB;
}
You are wrong with understanding "+", "-" - it's not about private / public.
To have a private function you should implement that in your .m file:
#interface YourClass ()
- (id) privateMethod;
#end
Everything you declare in .h file will be public:
#interface YourClass : NSObject
- (id)someMethod //public
#end
"+" is used for static functions so you can call them without having an instance of a class.
For example in your case:
[myClass dealWithStringB];
and for "-" function you need instance.
[[[myClass alloc] init] dealWithStringA];
The static functions can be used when you don't need any properties from a class or to they are pretty often used to create instances of classes.
The "+" prefix means class method, not public. A "-" stands for instance method, not private.
Both public and private methods can access the private state of the class or instance.
myClass.h (Similar to yours)
#interface myClass : UIViewController
{
}
#property (nonatomic, retain) NSString *stringA;
#property (nonatomic, retain) NSString *stringB;
- (void)dealWithStringA;
+ (void)dealWithStringB;
#end
myClass.m
#implementation myClass
#synthesize stringA ;
#synthesize stringB ;
static myClass* instance = nil;
+(void) dealWithStringB
{
if(instance==nil)
{
instance=[myClass alloc]init];
}
else
{
//Access the field this way
printf("#"The string content is %#",instance.stringB);
}
}
Hope its Clear!!!