I try to get a static variable from a class so I do this
in file Login.h
+ (instancetype)setToken:(NSString *)aToken;
In file Login.m I do this
static NSString* token;
.......
+(instancetype)setToken:(NSString *)aToken
{
token = [aToken copy];
return aToken;
}
so I can get value
[Login setToken:token]
But I don't know how to get this value in another class
You have to provide a class getter method as well:
+ (void)setToken:(NSString *)token;
+ (NSString *)token;
However using a singleton is the preferred way of doing this, allowing you to use a #property.
Create a getter method for that. This method will return that static variable value.
Add signature of that method to Login.h file.
+ (NSString *) getUniqueToken;
Relevant method in Login.m class.
+ (NSString *) getUniqueToken {
return token;
}
As it is a class method you can direclty access with out creating object of login class.
Call above method in other controller class, It will return token string.
[Login getToken];
Related
I'm trying to use class property following this example. But I'm getting the following error:"Use of undecleared identifier '_myProperty'".
Here is my implementation:
#interface myClass()
#property (class,strong,nonatomic) NSString *myProperty;
#end
+ (NSString*)myProperty
{
if (!_myProperty) {
}
return [NSString new];
}
Why I'm getting this error? or any of you knows a work around this?
I'll really appreciate your help
Class properties don't get synthesized in Objective-C. You have to provide your own backing variable and your own getter/setter:
static NSString *_myProperty = nil;
+ (NSString *)myProperty {
if (!_myProperty) {
_myProperty = [NSString new];
}
return _myProperty;
}
+ (void)setMyProperty:(NSString *)myProperty {
_myProperty = myProperty;
}
Class properties and never auto-synthesised, the getter and/or setter must be implemented, and no backing variable is automatically created for them.
If your property needs a variable you must declare one, use a static global in the implementation file - that is effectively a "class variable" in Objective-C. Alternatively if you only require a getter you can declare a static variable local to the getter itself, further reducing its visibility and keeping the getter and variable together as a package.
HTH
In fact, class property is not a member of a class. So it will be created at once and all instances will use this one. So there is nothing to synthesize.
I have a very specific issue where, if I have a swift class which inherits from an objective-c class, and it has a dynamic property.
Now, on the +initialize, I am injecting getter and setters into the swift(:NSObject) class, and these work no problem, except for a slight issue when setting values from an init overload.
So, my swift class looks like this:
class TestClass: BaseClass {
dynamic var testStringProperty: String?
init(initialValue: String) {
super.init()
self.testStringProperty = initialValue;
// does not trigger the get/set methods
// a po self.testStringProperty will output 'nil'
let xyz = self.testStringProperty;
// xyz is actually set to the value of initialValue, but it does not trigger the getter.
}
}
And the objective-c class that bases the swift is as follows:
static id storedVar;
#implementation BaseClass
+ (void)initialize {
// we are going to exchange getter/setter methods for a property on a SwiftClass, crude but demonstrates the point
if(![[self description] isEqualToString:#"BaseClass"]) {
IMP reader = (IMP)getPropertyIMP;
IMP writer = (IMP)setPropertyIMP;
const char* type = "#";
NSString* propertyName = #"testStringProperty";
IMP oldMethod = class_replaceMethod([self class], NSSelectorFromString(propertyName), reader, [[NSString stringWithFormat:#"%s#:", type] UTF8String]);
NSString* setMethod = [NSString stringWithFormat:#"set%#%#:", [[propertyName substringToIndex:1] uppercaseString], [propertyName substringFromIndex:1]];
oldMethod = class_replaceMethod([self class], NSSelectorFromString(setMethod), writer, [[NSString stringWithFormat:#"v#:%s",type] UTF8String]);
}
}
static id getPropertyIMP(id self, SEL _cmd) {
return storedVar;
}
static void setPropertyIMP(id self, SEL _cmd, id aValue) {
storedVar = aValue;
}
#end
Long story short, whilst in the call to init(initialValue: String), the getters and setters are not triggered, but immediately after the call to init has completed they work.
This is despite the call to initialize completing successfully and the methods being replaced.
But outside of the init function, the get/set behave as expected.
Here is where it get's called.
let test = TestClass(initialValue: "hello");
test.testStringProperty = "hello"
A po test.testStringProperty after the creation of the object, will output nil. But the subsequent assignment, triggers all the correct methods.
It only fails when assigning within the init. Everywhere else it works like a charm.
I would like to get this to work within the initializer if possible, i'm not sure if there is another way to work around it.
Here is a link to the sample app that replicates the issue:
https://www.dropbox.com/s/5jymj581yps799d/swiftTest.zip?dl=0
If I want to access a variable that is declared in Class A and I
want to use that variable in Class B .
I don't want to use Property.
How Can I do ?
It is bad practice to declare a public variable without making it a property.
You may also use KVC to access(both read and write) ivar, even if it is readonly.
[instanceOfMyClass valueForKey:#"myIvar"];
I hope someone finds my first stackOverflow answer helpful :)
#interface Class1
{
#public
int var; // if you not declare it public by default it'll be protected
}
// methods...
#end
// Inside a Class2 method:
Class1 *obj = ...;
obj->var = 3;
But property approach is far better.
Well, you can declare variable as public and access it with selector operator, but this is not recommended:
#interface A:NSObject{
#public
int x;
}
#end
...
//Somewhere inside class B
A *a = [[A alloc] init];
a->x;
However it's hard to imagine why it can be better that to use a property.
The 4 possibles cases that I can think to access a variable are:
1 Declare the variable in class A as public
#public
BOOL _test;
Totally not recommended. If you need a public variable you use a property.
2 Use a property.
#property (readonly, getter = myMehtodName) id myVariable;
3 Use a custom method. In practice it acts the same as a property with readonly attribute. Also you can access it with the dot notation.
4 Use KVC to access the variable.
This can be useful when you don't know the name of the property / variable in compilation time.
A little example:
NSString *myKey = [self obtainKey];
id myVariable = [self valueForKey:myKey];
if ([myVariable isKindOfClass:[NSString class]]) {
//Do something
}else {
//Do another thing
}
Note that key can be either a method name or a variable.
Very new to Objective c. My interface and implementation looks like this:
// MyAuth.h
// #interface
+ (instancetype)sharedToken;
// MyAuth.m
//#implementation
+ (instancetype)sharedToken {
static MyAuth *_sharedToken = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedToken = [[NSUserDefaults standardUserDefaults] valueForKey:#"token"];
});
return _sharedToken;
}
Now I'm trying to get the length of the sharedToken but am stuck here. What I've tried
[MyAuth sharedToken].length // doesn't work
How can I get the length of `sharedToken
You want a string pulled from NSUserDefaults to be accessible everywhere in your app, via this method.
The return type of the method needs to be the type of the object you're actually returning:
+ (NSString *)sharedToken;
instancetype says that the method returns an instance of the class which runs the method.
The pointer you use for the string should also have the correct type:
static NSString *_sharedToken = nil;
Now the compiler will let you send length to the result of the method call.
Is is possible to create getters and setters for constants? I want to refer to a constant directly, and have it instantiate itself if it's value is nil. A constant declared like this:
// Prefs.h
extern MyClass * const kThing;
// Prefs.m
MyClass * const kThing = nil;
and the getter/setter would look like:
// getter
+ (MyClass *)kThing
{
_kThing = _kThing ? : [MyClass new];
return _kThing;
}
// setter
+ (void)setKThing:(MyClass *)myClass
{
_kThing = myClass
}
And then I could use it like:
[kThing doSomething];
Is this possible?
edit edited the methods to class methods
What you describe are not constants, they are global variables. You cannot define getters and setters for them, but you can use their values to back class methods, which is precisely what you have done.
However, when you send message like this
[kThing doSomething];
the global variable is used directly, bypassing your getter. If you want to go through a getter, you can write
[[MyClass kThing] doSomething];
or inside methods of MyClass you can write
[[[self class] kThing] doSomething];
Another note is that when yo implement accessor methods like that, you should make the backing variables static, rather than extern. This will ensure that other modules cannot access these variables bypassing your getters.
Global variable declaration in other file is very dangerous in objective C. Ideally we use sharedInstance. Try like this:
In MyGame.h
#interface MyGame : NSObject
{
int mScore;
}
#property(nonatomic,assign) int score;
+(MyGame*)sharedObject;
-(void)someFunction;
#end
In MyGame.m
static MyGame *gGame = nil;
#implementation MyGame
#synthesize score = mScore;
+(MyGame*)sharedObject
{
if(!gGame)
{
gGame = [[MyGame alloc] init];
}
return gGame;
}
-(void)someFunction
{
}
#end
To access anywhere in project:
#import "MyGame.h"
[MyGame sharedObject].score;
[MyGame sharedObject] someFunction];
The short answer is that this is not possible.
MyClass * const kThing = nil;
means that kThing is a constant pointer, which means that the address in memory that it points to cannot be changed. So once it's set to nil, it can't later be set to a new object.