Can't access to extern variable from another class - objective-c

I've created a phonegap plugin to give a variable to native code. That works fine. Now I need to access to this value from other classes so I decided to create an extern NSString.
.h
extern NSString *lkwid;
#interface MyPlugin : CDVPlugin {
}
#property (retain, nonatomic) NSString *lkwid;
-(void) setMyValue:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
.m
#import "MyPlugin.h"
#implementation MyPlugin
#synthesize lkwid;
NSString *lkwid = #"";
-(void) setMyValue:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
NSString* callbackId = [arguments objectAtIndex:1];
lkwid = callbackId;
NSLog(#"set value %# ",lkwid);
//NSLog shows the correct value from Javascript
}
Now I want to access to lkwid from MainViewController.m (MyPlugin.h is imported) but lkwid is empty. Why?

I think that you are confusing instance variables and static (class) variables. The extern NSString *lkwid declares a globally accessible variable. #property (retain,nonatomic) NSString *lkwid declares an instance variables to your object. If you want it to set the global variable, which would then be shared by ALL the instances, then you should not synthesize the property andimplement the getter and setter yourself in the following manner:
- (NSString*) lkwid
{
return lkwid;
}
- (void) setLkwid:(NSString*)value
{
lkwid = value;
}
Make sure that you don't also declare an instance variable with the name lkwid.

Related

Can't find a appropriate property attribute for a instance variable

I'm new to this objective-c property attribute thing. Here's the code:
student.h
#import <Foundation/NSObject.h>
#interface Student: NSObject
#property int age(assign, readwrite); //I don't know what attribute it should have
#property NSString *name(retain, readwrite); //this one either
-(Student*) initWithName: (NSString *) n andAge:(int) a;
-(void) speakName;
+(void) smoke:(NSString*) thing;
#end
student.m
#import "student.h"
#implementation Student
-(Student*) initWithName:(NSString*) n andAge:(int) a {
self = [super init];
if(self) {
[self setName: n];
[self setAge: a];
}
return self;
}
-(void) speakName {
NSLog(#"MyName is %#", _name);
}
+(void) smoke:(NSString*) thing {
NSLog(#"Smoking %#", thing);
}
#end
main.m
#import <Foundation/Foundation.h>
#import "student.h"
int main(void) {
Student *student = [[Student alloc] initWithName: #"Markson" andAge: 29];
[student speakName];
[Student smoke:#"weed"];
[student release];
return 0;
}
for the the line
#property int age(assign, readwrite); //I don't know what attribute it should have
#property NSString *name(retain, readwrite); //this one either
when I don't give nothing to them, the compiler give me 4 warnings:
In file included from student.m:1:
./student.h:5:1: warning: no 'assign', 'retain', or 'copy' attribute is
specified - 'assign' is assumed [-Wobjc-property-no-attribute]
#property NSString *name;
^
./student.h:5:1: warning: default property attribute 'assign' not appropriate
for non-GC object [-Wobjc-property-no-attribute]
2 warnings generated.
In file included from main.m:2:
./student.h:5:1: warning: no 'assign', 'retain', or 'copy' attribute is
specified - 'assign' is assumed [-Wobjc-property-no-attribute]
#property NSString *name;
^
./student.h:5:1: warning: default property attribute 'assign' not appropriate
for non-GC object [-Wobjc-property-no-attribute]
2 warnings generated.
Please anyone can tell what attributes should be used for age and name properties?
#property int age(assign, readwrite); //I don't know what attribute it should have
#property NSString *name(retain, readwrite); //this one either
Short Note:
If you are creating property for primitive types like int, float, BOOL etc then use assign
If you want to retain the value then use strong or retain.
In all other situations you can go with weak.
And always go with atomic, and the syntax is like this
#property (<assign/retain/weak>, <atomic/nonatomic>, <read/readwrite>) <dataType> <propertyName>;
Change those lines to this:
#property (assign, nonatomic) int age;
#property (retain, nonatomic) NSString *name;
readwrite is the default one, so you don't need to set it.
Check this documentation:
Encapsulating data in Objective-C

Declaring instance variables in iOS - Objective-C

Ok, I've read a lot around these days about this topic and I alwyas get confused because the answers is different every search I make.
I need to know the best way to declare instance variables in iOS. So far I know I should only declare them inside .m file and leave .h clean. But I can't do it: the compiler gives me compilation erros.
Here is some code from .m only.
#interface UIDesign ()
// .m file
{
NSString *test2 = #"test2";
}
#property (nonatomic, assign) int privateInt;
#end
#implementation UIDesign
{
NSString *test1 = #"test1";
}
Both strings are declared incorrectly and I don't know why. The compiler says: expected ';' at end of declaration list.
So the question is: how can I declare instance variables? I will only need them inside the class.
You cannot initialize instance variables. They are all initialized to nil or zeroes. So compiler expect a semicolon when you are writing an equal sign.
You can initialize them in init method.
You are attempting to add an instance variable to a class extension or category which is unsupported. [EDIT 2013-05-12 06-11-08: ivars in class extension are supported, but not in categories.] As an alternative:
#interface UIDesign : NSObject
#end
#interface UIDesign ()
#property (nonatomic, assign) int privateInt;
#end
#implementation UIDesign
#synthesize privateInt = _privateInt;
- (void)someMethod {
self.privateInt = 42;
}
#end
On the other hand, if you just want to declare an instance variable inside the implementation, just do it there:
#implementation UIDesign {
int _privateInt;
}
#end
EDIT: just noticed that you're also attempting to initialize instance variables in the declaration which is also unsupported. So:
#interface UIDesign : NSObject
#end
#implementation UIDesign {
NSString *_test;
}
- (id)init {
self = [super init];
if( !self ) return nil;
_test = #"Foo";
return self;
}
#end

Objective-C Where to define initial Class Properties

just wanted to ask where I define initial class properties?
From other languages I am used to define some standard properties in the head before the content of the class starts.
For example paths to files. Settings and so on.
Where I fill these initial properties with values in Objective-C?
Thanks
Generally it's something like:
MyClass.h:
extern NSString * const staticValue1;
extern NSString * const staticValue2;
#interface MyClass : NSObject
{
NSString *_strval;
int _intval;
float _fltval;
}
#property (retain, nonatomic, readwrite) NSString *strval;
#property (assign, nonatomic, readwrite) int intval;
#property (assign, nonatomic, readwrite) float fltval;
#end
MyClass.m:
NSString * const staticValue1 = #"Something";
NSString * const staticValue2 = #"Something else";
#interface MyClass
#synthesize strval = _strval;
#synthesize intval = _intval;
#synthesize fltval = _fltval;
- (id)init
{
self = [super init];
if (self != nil)
{
[self setStrval:[NSString stringWithFormat:#"This is a %#", #"string"]];
[self setIntval:10];
[self setFltval:123.45f];
}
return self;
}
- (void)dealloc
{
[self setStrval:nil];
[super dealloc];
}
#end
This demonstrates the use of synthesized properties which are being used here to manage the memory of the instance variable _strval, which requires retaining/releasing to avoid memory leaks. Note that [self setStrval] is initialised with an autoreleased object (from [NSString stringWithFormat) and will be retained by the setter method. Alternatively these methods can be called using the following syntax, if you prefer:
self.strval = [NSString stringWithFormat:#"This is a %#", #"string"];
self.intval = 10;
self.fltval = 123.45f;
Maybe some of what you are after can be implemented with class methods.
Class methods are coded with a + (instead of the instance methods' -), and can't refer to instance variables, as they are not associated with any specific instance of the class.
This is a class method to return a default string:
+ (NSString *)myDefaultString
{
return #"Some default value";
}
You call it by simply calling it with the class name at the receiver's place. Imagine you have defined the method in a class called MyClass, the you call it like this:
NSString *str = [MyClass myDefaultString];
You'll notice that there is no alloc/init calls in this.
Public property needs to be define in .h file.
#interface MyClass {
}
#property(nonatomic, reatin) NSString *a;//Define as per needs, then synthesise in .m file
#end
For private property you need define inline category in .m file-
#interface MyClass ()
#property(nonatomic, reatin) NSString *b;//Define as per needs, then synthesise in .m file
#end
#implementation MyClass
#synthesize a = _a;
#synthesize b = _b;
- (void)viewDidLoad {
//You can initialise property here or in init method
self.a = #"Demo1";
self.b = #"Demo2";
}
//Now you can have other code for this class.
#end

In Objective-C, how do I pass a property as an argument for a function and then call the setter/getter methods?

The code is probably the best way to see what I am trying to do:
AcInfo.h:
#interface AcInfo : NSManagedObject {
#private
}
#property (nonatomic, retain) NSString *registrationNumber;
#end
AcInfo.m:
#implementation AcInfo
#dynamic registrationNumber;
#end
AnotherClass.h:
#interface AnotherClass : NSObject {
}
#property (nonatomic, retain) AcInfo *detailItem;
#property (nonatomic, retain) IBOutlet UITextField *registrationNumberTextField;
- (void)setDetailItemValueFromUIElement:(id *)uiElement forAcInfoTarget:(id *)acInfoTarget;
#end
AnotherClass.m:
#import "AcInfo.h"
#implementation AnotherClass
#synthesize detailItem, registrationNumberTextField;
- (void)viewDidLoad
{
[super viewDidLoad];
registrationNumberTextField.text = #"Test";
// I expect this to set detailItem.registrationNumber to the value of
// registrationNumberTextField.text (Test) but it doesn't change anything!
setDetailItemValueFromUIElement:registrationNumberTextField forAcInfoTarget:detailItem.registrationNumber;
}
- (void)setDetailItemValueFromUIElement:(id *)uiElement forAcInfoTarget:(id *)acInfoTarget
{
if ([(id)uiElement isKindOfClass:[UITextField class]]) {
// This doesn't do anything when it returns!
(NSString *)acInfoTarget = (UITextField *)uiElement.text
return;
}
}
#end
In short, I want acInfoTarget to call the getter [detailObject registrationNumber] and the setter [detailObject setRegistrationNumber] in the setDetailItemValueFromUIElement: function...
You can set or read properties by name using
// setter
NSString *propertyName = #"myProperty";
[object setValue:newValue forKey:propertyName];
// getter
id value = [object valueForKey:propertyName];
This is slower than using the normal dot notation, though, and it's frequently (though not always) a sign of poorly-designed code.
Also note that id is a pointer type, so you probably don't actually mean "(id*)".
Your code wants to look something like this, I think:
- (void)setDetailItemValueFromUIElement:(id)uiElement forAcInfoTarget:(NSString*)acInfoTarget {
if ([(id)uiElement isKindOfClass:[UITextField class]]) {
NSString *newValue = ((UITextField*)uiElement).text;
[self.detailItem setValue:newValue forKey:acInfoTarget];
}
}
Properties are just syntax sugar for a couple of accessor methods. They are not, in essence, variables so you shouldn't treat them as such. If you want to affect a property, then what you wanting to do is call a method. So you should pass a id and selector parameter and not pointer to a variable type.

Question about class member declarations

I`m new to the Objective-C world, so I have a couple of questions about class member declarations. Please notice the comments in the code below:
In header file I have code such
#interface MyClass : NSObject {
//what we points here ? Object or something else ?
NSString *myString;
}
// In interface we declare NSTring *myString in #property declaration is (NSString *) myString.
// What is the difference here ? Why we don`t use the same declaration as above ?
#property(nonatomic, retain) (NSString *) myString;
#end
The thing you're missing is that instance variables (defined between curly braces) are not accessed from the outside (i.e. other objects). To do that - you have to define a property for the instance var (by using #property keyword) to know how outside objects can access a value of given instance var. Also in implementation file (.m) you have to #synthesize instance variable accessor methods for it's appropriate property. Please note that #property declaration not only defines what it holds (NSString *myString), but also how it's being accessed and set. You can define property as read only (#property (readonly)...) or accessible from few threads at a time (#property (nonatomic)).
Also - if your instance var is named differently from the property it represents to other objects - you must show that in implementation file (#synthesize propertyName=instanveVariableName)
update
MyClass *myInstance = [[MyClass alloc] init];
[myInstance myString]; // returns myString property
Try running above 2 lines of code without #property and you'll see the difference.
Actually you are defining a Property of yar class.#interface MyClass : NSObject {
//public object
#public
NSString *myString;
//private object
NSString *myString2;
}
class structure for obj-c
.h file
#interface MyClass : NSObject {
//Your member variable;
// you member objects;
}
//property declarations
//function declarations
#end
so it should look like
#interface MyClass : NSObject {
NSString *str;
}
#property(nanatomic,retain) NSString *str;
-(void)method;
#end