Global NSString - objective-c

I need to create an NSString, so I can set its value in one class and get it in another. How can I do it?

if you write:
NSString *globalString = #"someString";
anywhere outside a method, class definition, function, etc... it will be able to be referenced anywhere. (it is global!)
The file that accesses it will declare it as external
extern NSString *globalString;
This declaration signifies that it is being accessed from another file.

Make it a global variable.
In one file in global scope:
NSMutableString *myString = #"some funny string";
In the other file:
extern NSMutableString *myString;

Global NSString Variable for Complete iPhone Project/Apps
For Declare/Define/Use a global variable follow these easy steps:-
Create a NSObject File with named "GlobalVars.h and .m" or as u wish
Declare your global variable in GlobalVars.h file after #import and before #implementation like-
extern NSString *Var_name;
initialize it in GlobalVars.m file after #import and before #implementation like-
NSString *Var_name = #"";
Define its property in AppDelegate.h File
#property (nonatomic, retain) NSString *Var_name;
synthesize it in AppDelegate.m File like-
#synthesize Var_name;
Now where you want to use this variable (in .m file) just import/inclue GlobalVars.h file in that all .h files, and you can access easily this variable as Globally.
Carefully follow these Steps and it'll work Surely.

If you're creating a global NSString variable, you should use probably use a class method.
In MyClass.h:
#interface MyClass : NSObject {}
+ (NSString *)myGlobalVariable;
+ (void)setMyGlobalVariable:(NSString *)val;
#end
In MyClass.m:
#implementation MyClass
NSString *myGlobalVariable = #"default value";
+ (NSString *)myGlobalVariable {
return myGlobalVariable;
}
+ (void)setMyGlobalVariable:(NSString *)val {
myGlobalVariable = val;
}
#end

Remember that you should keep memory allocation and freeing in mind. This is not the same thing as a global int value - you need to manage the memory with any NSObject.
Repeatedly just setting the global to new strings will leak. Accessing through threads will create all manner of issues. Then there is shutdown where the last string will still be around.

I think you should use a singleton. A good article that discusses this is Singletons, AppDelegates and top-level data.
Additional information on a singleton class is at MVC on the iPhone: The Model

Related

Objective-C propreties and private variable

I'm a debutant to objective-c and I don't understand something.
I practiced c++ so some practices are not instinctif ..
1)
#implementation Car {
// Private instance variables
double _odometer;
}
Why a private attribute is in the .m file ?
2)
#interface Car : NSObject {
// Protected instance variables (not recommended)
}
#property (copy) NSString *model;
-(void)drive
a)It seems model is declared like an attribute, but why it's not recommended to do it in the #interface ?
b) why the drive method is not in the interface ?
3)
What if i'm not use function allocation for exemple for a NString and initialise it directly with #"..." ?
4)
I don't understand the difference between + and - before method declaration too..
Thanks in advance
1.>Why a private attribute is in the .m file
Why not? Everything that is declared inside *.m is private because *.m file could not be imported (included) somewhere. In objective C you can declare instance variables in both files - *.h and *.m
2.a Recommended way is to use accessors (#properties in Objective C). For each property setter, getter and instance variable are generated. Default names for
#property (copy)NSString *str;
are:
- (void)setStr:(NSString*)obj; // setter
- (NSString*)str; //getter
NSString *_str; //instance variable
You can modify accessors names
#property (copy, setter = NewSetterName, getter = NewGetterName )NSString *str;
and instance variable name (should be done #implementation section)
#synthesize str = _newStingInstanceVariable;
Ofcource you can rewrite setters and getters that are generated by default.
2.b Interface is everything between #implementation and #end. {} area after #interface - is a place were you can declare instance variables.
3.It is ok for NSStrings
NSString *str = #"some text";
but for most classes it will not work as you expect:
NSMutableString *str = #"some text";
// You will receive warning here! And str will be NSString, not NSMutableString
4."+" - class methods (static in C++), "-" - instance methods.
There's a general principle in programming that you should make the smallest possible amount of information available to the outside. Anything that's in the .h file, anyone in the world can see, access, and mess up. If there's something wrong with an _odometer and it is in the header file, you have to go through all of your source code to find if something is using it wrong. If it's only in the .m file, you know that if there's a problem, it is in the .m file.
The other reason to not make things public is that you are free to change them if nobody knows about them. For some reason, you decide next month that having _odometer wasn't a good idea in the first place. By now three programmers have changed a dozen files to use _odometer because it was there. So removing that _odometer is now a lot, lot of work. If it was never in the .h file, nobody is using it so you only need to change your own .m file.

How to use #property correctly (Setters) within another class

another question i'm trying to use a setter within another class but I seem to get this odd error here is the code below:
AppDataSorting.h
#import <Foundation/Foundation.h>
#interface AppDataSorting : NSObject{
NSString *createNewFood;
NSNumber *createNewFoodCarbCount;
}
#property (readwrite) NSString *createNewFood;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
- (IBAction)saveData:(id)sender {
NSLog(#"%#", self.foodName.stringValue);
self.createNewFood = self.foodName.stringValue;
NSLog(#"%.1f", self.carbAmount.floatValue);
}
#end
I get the error message in AppDelegate.m which is: Property 'createNewFood' not found on object of type 'AppDelegate *'
Could someone please explain the issue here?
You declare this property:
#property (readwrite) NSString *createNewFood;
In AppDataSorting.h so you can access it like self.createNewFood in AppDataSorting.m file not AppDelegate.m. If you want to call it as you do in AppDelegate.m you have move this line:
#property (readwrite) NSString *createNewFood;
to AppDelegate.h file.
Or if you want to use property from AppDataSorting class in AppDelegate you have to create object and call it on that object:
- (IBAction)saveData:(id)sender {
NSLog(#"%#", self.foodName.stringValue);
AppDataSorting *dSorting = [[AppDataSorting alloc] init];
dSorting.createNewFood = self.foodName.stringValue;
NSLog(#"%.1f", self.carbAmount.floatValue);
}
In -saveData:, self refers to an instance of NSAppDelegate. The createNewFood property is defined on instances of the class AppDataSorting.
Also note that Cocoa/CF naming conventions give special meaning to methods that start with "init", "new" and (to a lesser degree) "create". You probably want to avoid such things in your property names. Details here.
In general, properties should represent conceptual "properties" of an object. So if you had a Person class, it might have a name property, but it wouldn't have a createNewOutfit property.
You need to access createNewFood on an instance of AppDataSorting - but you're trying to access the property on the AppDelegate-class which clearly doesn't implement it.
So you would need to create an instance of AppDataSorting and then access the property like so:
AppDataSorting *instance = [[AppDataSorting alloc] init];
instance.createNewFood = self.foodName.stringValue;
Final notes:
The docs provide a good base of information
If you don't need atomicity you should always declare properties with the nonatomic attribute
createNewFood is not a good name for a property since it suggests a method which creates new food - yet it's only meant to store data (in this case an NSString instance)

Do I need to declare a property in the instance variables section, too? What do I gain?

I read some tutorials here about properties ,but i still have some doubts to clarify, is there a difference between
#interface MyClass : NSObject {
}
#property(nonatomic,retain) NSString *temp;
#end
AND
#interface MyClass : NSObject {
NSString *temp;
}
#property(nonatomic,retain) NSString *temp;
#end
The difference is that in the first version, the compiler will automatically create an instance variable (IIRC, it will be named _temp but I don't know for sure). This is only supported on iOS and Mac 64 bit.
In the second example, you provide the variable.
There's actually a way to tell the compiler which variable to use for the property, which I use a lot:
#interface MyClass : NSObject {
NSString *temp_;
}
#property(nonatomic,retain) NSString *temp;
#end
#implementation MyClass
#synthesize temp = temp_;
#end
This way the variable and the property have different names and you can't confuse them (e.g. by forgetting to prefix self.).
Minor side-note: it's often desirable to use copy instead of retain for NSString *, since you might assign an NSMutableString * to the property. Now if you would change that mutable string unexpected things might happen.
Does the first one even work? If there is no instance variable its a bit hard to have a property to access it.
#properties are meant for you, so you can be lazy, they write the following 2 methods for you ( if not set to readonly ):
- (void)setYourVariable:(id)new;
- (id)yourVariable;
it also allows you to use "someClass.itsVariable;" instead of "[someClass itsVariable];"
Another thing, when you create your header files make sure that the biggest variables ( like pointers ) are on the top and the smallest on the bottom, this saves ram.
thus:
NSObject *someObject;
NSObject *someOtherObject;
int anInt;
short aShort;
BOOL fakeBool;
instead of:
BOOL fakeBool;
NSObject *someObject;
short aShort;
NSObject *someOtherObject;
int anInt;
This has to do with the compiler, you can check this by using sizeof()
In the modern runtime (Objective-C 2.0) it is the same because the compiler will generate the variable for you. See Question about #synthesize
Quoting The Objective-C Programming Language > Declared Properties > Property Implementation Directives:
There are differences in the behavior of accessor synthesis that
depend on the runtime:
For the legacy runtimes, instance variables must already be declared in the #interface block of the current class. If an instance
variable of the same name as the property exists, and if its type is
compatible with the property’s type, it is used—otherwise, you get a
compiler error.
For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is
used.
The practical difference that I've found is that the debugger doesn't appear to show you the value of properties, just instance variables.
Therefore, your first example, which (assuming you use the #synthesize directive to create your getter/setter) automatically creates the ivar, will not have a value that you can easily retrieve during debug. You'll end up having to send a lot of NSLog messages, rather than just looking at the values while stepping through your code.
As an aside, which seems to relate to this topic, I typically prepend my ivars with "iv" and change my color settings in XCode preferences so that I'm never unsure whether I'm accessing a property or an ivar.
Example
#interface MyClass : NSObject {
NSString *ivName;
NSString *ivTitle;
}
#property (nonatomic, copy) NSString *Name;
#property (nonatomic, copy) NSString *Title;
#end
Now, this then requires a small trick (to tie the two together) when synthesizing the properties, which I show below:
#implementation MyClass
#synthesize Name = ivName;
#synthesize Title = ivTitle;
This way, it's always very easy for me to know exactly what's going on at a glance. Yes, context can also tell you whether you're accessing an ivar/property, but why not make it easier?

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

Is there a difference between an "instance variable" and a "property" in Objective-c?

Is there a difference between an "instance variable" and a "property" in Objective-c?
I'm not very sure about this. I think that an "property" is an instance variable that has accessor methods, but I might think wrong.
A property is a more abstract concept. An instance variable is literally just a storage slot, like a slot in a struct. Normally other objects are never supposed to access them directly. A property, on the other hand, is an attribute of your object that can be accessed (it sounds vague and it's supposed to). Usually a property will return or set an instance variable, but it could use data from several or none at all. For example:
#interface Person : NSObject {
NSString *name;
}
#property(copy) NSString *name;
#property(copy) NSString *firstName;
#property(copy) NSString *lastName;
#end
#implementation Person
#synthesize name;
- (NSString *)firstName {
[[name componentsSeparatedByString:#" "] objectAtIndex:0];
}
- (NSString *)lastName {
[[name componentsSeparatedByString:#" "] lastObject];
}
- (NSString *)setFirstName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:#" "];
NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
self.name = [newNameArray componentsJoinedByString:#" "];
}
- (NSString *)setLastName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:#" "];
NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
self.name = [newNameArray componentsJoinedByString:#" "];
}
#end
(Note: The above code is buggy in that it assumes the name already exists and has at least two components (e.g. "Bill Gates" rather than just "Gates"). I felt that fixing those assumptions would make the actual point of the code less clear, so I'm just pointing it out here so nobody innocently repeats those mistakes.)
A property is a friendly way of implementing a getter/setter for some value, with additional useful features and syntax. A property can be backed by an instance variable, but you can also define the getter/setter to do something a bit more dynamic, e.g. you might define a lowerCase property on a string which dynamically creates the result rather than returning the value of some member variable.
Here's an example:
// === In your .h ===
#interface MyObject {
NSString *propertyName;
}
// ...
#property (nonatomic, retain) NSString *propertyName;
// === In your .m #implementation ===
#synthesize propertyName /* = otherVarName */;
The #property line defines a property called propertyName of type NSString *. This can be get/set using the following syntax:
myObject.propertyName = #"Hello World!";
NSLog("Value: %#", myObject.propertyName);
When you assign to or read from myObject.propertyName you are really calling setter/getter methods on the object.
The #synthesize line tells the compiler to generate these getter/setters for you, using the member variable with the same name of the property to store the value (or otherVarName if you use the syntax in comments).
Along with #synthesize you can still override one of the getter/setters by defining your own. The naming convention for these methods is setPropertyName: for the setter and propertyName (or getPropertyName, not standard) for the getter. The other will still be generated for you.
In your #property line you can define a number of attributes in parens for the property that can automate things like thread-safety and memory management. By default a property is atomic meaning the compiler will wrap #synthesized get/set calls with appropriate locks to prevent concurrency issues. You can specify the nonatomic attribute to disable this (for example on the iPhone you want to default most properties to nonatomic).
There are 3 attribute values that control memory management for any #synthesized setters. The first is retain which will automatically send release to old values of the property, and retain to the new values. This is very useful.
The second is copy which will make a copy of any values passed in rather than retaining them. It is good practice to use copy for NSString because a caller could pass in an NSMutableString and change it out from under you. copy will make a new copy of the input which only you have access to.
The third is assign which does a straight pointer assign without calling retain/release on the old or new object.
Lastly you can also use the readonly attribute to disable the setter for the property.
I use properties for the interface part - where the object interfaces with other objects
and instance variables are stuff that you need inside your class - nobody but you is supposed to see and manipulate those.
By default, a readwrite property will be backed by an instance variable, which will again be synthesized automatically by the compiler.
An instance variable is a variable that exists and holds its value for the life of the object. The memory used for instance variables is allocated when the object is first created (through alloc), and freed when the object is deallocated.
Unless you specify otherwise, the synthesized instance variable has the same name as the property, but with an underscore prefix. For a property called firstName, for example, the synthesized instance variable will be called _firstName.
Previously people use properties publicly and ivars for private usage, but since several years ago, you can also define properties in #implementation to use them privately. But I'd still use ivars when possible, since there are less letters to type, and it runs faster according to this article. It makes sense since properties are mean to be "heavy": they are supposed to be accessed from either generated getters/setters or the ones manually written.
However, in recent codes from Apple, ivars are not used anymore. I guess because it's more like objc rather than C/C++, plus it's easier to use properties with assign, nullable, etc.
Objective-C Property vs Instance variable (iVar)
[Swift variable, property...]
Instance variable
#interface SomeClass: NSObject
NSString *someVariable;
#end
Property
#interface SomeClass: NSObject
#property (nonatomic, strong) NSString *someVariable;
#end
Property uses Instance variable inside. property = variable + bounded getter/setter. It is a method call with variable syntax and access
#property generates getter and setter methods(accessor methods) which uses backing ivar(aka backing field) which you can use via underscore _<var_name> (_someVariable).
Since it calls a method - method dispatch mechanism is used that is why KVO[About] can be applied
When you override accessor methods backing iVar is not generated that is why you can declare a new property explicitly or use #synthesize[About] to generate a new one or link with existing
#import "SomeClass.h"
#interface SomeClass()
#property (nonatomic, strong) NSString *someVariable;
#end
#implementation SomeClass
- (void) foo {
//property getter method
NSString *a1 = self.someVariable; //NSString *a1 = [self someVariable];
//property setter method
self.someVariable = #"set someVariable"; //[self setSomeVariable:#"set someVariable"];
//iVar read
NSString *a2 = _someVariable;
//iVar write
_someVariable = #"set iVar";
}
//if you overriding someVariable getter and setter the iVar(_someVariable) is not generated, that is why you can:
//1. create some variable explicitly
NSString *_someVariable;
//or
//2. use #synthesize
#synthesize someVariable = _someVariable;
//overriding
- (NSString*) someVariable {
return _someVariable;
}
- (void)setSomeVariable: (NSString*) updatedSomeVariable {
_someVariable = updatedSomeVariable;
}
#end
[property attributes]