Is defining a property & synthesize for a variable in a singleton class allowed? - iphone

Defining a property & synthesize for a variable in a singleton class allowed?,like below
in interface,
#property(nonatomic,assign)NSInteger value;
and in implementation file,
#synthesize value;
or we just have to declare a variable like below,
#interface SingletonDataClass : NSObject
{
NSInteger value;
}

Anything that you can do with your regular classes you can do with singletons.
There is no language concept called "singleton", it is just a common usage pattern of regular Objective C classes. What makes a class a singleton is the way you ensure its instantiation happens only once, i.e. your own supporting code.

Related

is there a way to define a variable thats accessible to some classes and not others?

In objective-c, the access to variables is limited to three types which is #public , #private , #protected (default) and #package .. these access modifiers allow us to access the variable through 4 situations in order :
1- access the variable from anywhere.
2- access the variable only inside the class.
3- access the variable from anywhere in the class and its subclasses.
4- access the variable from anywhere in the framework.
my question is: is there a way to define a variable which is accessible to some classes and not others ? (i.e. customised scope for variables)
What you're asking for is C++'s friend keyword. Friend classes in Objective-C discusses the topic.
You can use class extensions to create more flexible access control:
// MyClass.h
#interface MyClass : SomeSuperclass {
int ivar;
}
#end
// MyClass-Custom.h
#include "MyClass.h"
#interface MyClass () {
int anotherIvar;
}
#end
Now anotherIvar will be accessible only to code that #includes MyClass-Custom.h. You can create more class extensions on the same class to get additional access groups.
You would have to write your own setter and getter methods.
- (id) get_abc_value:(id)from {
if ([from isKindOfClass:[SomeRespectedClass class]]) {
return abc;
}
return nil;
}

concepts of properties with corresponding ivars

i have a general question about properties and ivars.
ive seen many different examples to use properties and it confuses me a bit.
method 1 only using a property without a corresponding ivar.
#property (...) Type *name;
#synthesize name;
method 2 using a property and an ivar
#interface{
Type *ivarName;
}
#property (...) Type *name;
#synthesize name = ivarName;
method 3 ignoring properties and working with ivars
#interface{
Type *ivarName;
}
ivar = ...;
i currently use method 1 for most things i do, it just works. but i have startet to wonder if i might be missing something here. i have read a lot of questions about ivars VS properties, but none of them seemed to really care about how they work together.
in most sample projects i've seen method 2 is used. so my question is: is there any advantage in defining a property and an ivar, and then assign the property to the ivar, than just having a property?
is the solution as simple as: only with a property can an ivar be set from 'outside'?
i have read: Must every ivar be a property? and Property vs. ivar in times of ARC but was not able to draw a final conclusion.
is the solution as simple as: only with a property can an ivar be set from 'outside'?
Essentially, yes. Ivars in Obj-C are (by default) "protected", meaning that the compiler won't allow you to access them externally to the object's own code. For example, given the following class declaration:
#interface Dunstable : NSObject
{
NSString * crunk;
}
#end
You might think you'd be able to access the ivar after creating the object, but trying results in an error:
Dunstable * d = [[Dunstable alloc] init];
d->crunk = #"Forsooth"; // Error: "Instance variable 'crunk' is protected
That's why ObjC uses accessor methods. Defining them manually was mandatory before the advent of declared properties:
#implementation Dunstable
- (NSString *)crunk {
return crunk; // implicit ivar access, i.e. self->crunk
}
- (void)setCrunk: (NSString *)newCrunk {
[newCrunk retain];
[crunk release];
crunk = newCrunk;
}
#end
Now, using the #property and #synthesize directives creates those accessor methods for you (as well as the variable itself). (The manual memory management in the setter is of course also obsolete under ARC.)
It is possible to make an ivar that's accessible from outside the object:
#interface Dunstable : NSObject
{
#public
NSNumber * nonce;
}
#end
Dunstable * d = [[Dunstable alloc] init];
d->nonce = [NSNumber numberWithInt:2]; // Works fine
but this isn't considered good Objective-C style.
The Objective-C Programming Language doc contains a "Historical Note" about this:
Note: Historically, the interface required declarations of a class’s instance variables, the data structures that are part of each instance of the class. These were declared in braces after the #interface declaration and before method declarations:
[...]
Instance variables represent an implementation detail, and should typically not be accessed outside of the class itself. Moreover, you can declare them in the implementation block or synthesize them using declared properties. Typically you should not, therefore, declare instance variables in the public interface and so you should omit the braces.
This is a pretty big change (I was actually surprised that there's no syntax given for ivars declared in #interface anymore in that doc), but it's definitely for the better. You should use declared properties; they do the right thing and make your code cleaner and safer.
When you write:
#synthesize name;
an ivar name is created, and it has the same name as the property. So you can access it with or without self.
In reality if you write
self.name = #"hello";
you are accessing the property, and if you write
name = #"hello";
you are accessing the ivar. Most people (including me) will advise you not to access your ivars directly unless it is really what you want: for example, if you are creating a custom setter or getter for the property. Otherwise always access the property with self.
In my case I always do:
#synthesize name = _name;
The advantage of this approach is that when you forget to write self instead of accessing the ivar you will get an error telling you that the ivar name doesn't exist.
You should never access ivars directly from outside of a class. That's the main function of properties--defining accessor methods for use by other objects. However, it's also good practice to use your accessors from within the same class--this way you can ensure that any appropriate side effects take place (memory management is an obvious example, if you aren't using ARC).
So, Method 3 is usually wrong. Method 1 is roughly equivalent to Method 2--that is, behind the scenes, the runtime is basically creating an ivar for you. Note also that you can set the name of that ivar even if you didn't explicitly define it:
#interface{
//No ivar here!
}
#property (...) Type *name;
#synthesize name = ivarName;
From the second link you supplied, Property vs. ivar in times of ARC, the comment by Denis Mikhaylov on the accepted answer is very telling. He points out that with your case 3, that you can access the iVar through:
classInstance->iVar = #"New value"
But this is considered bad practice. So i'd restate your point as:
Only with a property should an ivar be set from 'outside'

Creating a class whose methods can be called without an instance of an object (static class)

I'm new to objective c and i want to create a class containing certain methods that can be called in any of my other classes, mostly helper methods. im still learning the syntax and i dont know how to declare it properly
kind of like in java Integer.parseInt( );
Thanks!
Static methods in objective-c are called 'class methods' and can be declared with '+' symbol (while instance methods with '-'), e.g.:
- (void) instanceMethod;
+ (void) classMethod;
To call class method use class name:
[MyClass classMethod];
Those are called (unsurprisingly) class methods. You can declare one by using + instead of - in the method signature, e.g.
#interface MyInteger : NSObject
+ (MyInteger *)parseInt:(NSString *)str;
#end
This method is then called on the class itself, e.g. [MyInteger parseInt:#"12"].
Of course, since this is C, if your class method doesn't actually have much relation to any particular class, you could just define it as a C function instead.
NSInteger myParseInt(NSString *str);
When you see a - sign in front of a method, it's an instance method. That means you can only call that method on an instance of a class.
If you want to create a class method, all you need to do is change that - to a +.
they are called class methods. they are declared and used like this:
#interface MONClass : NSObject
+ (NSString *)convertString:(NSString *)string;
#end
in use:
NSString * converted = [MONClass convertString:string];

difference between object.variable and object->variable

What is the difference in using object.variable and object->variable? When should I use object->variable?
As Objective C is a superset of C when using '->' syntax (which is similar to (*obj).var) you are accessing the instance variable (ivar) like in C-structure (well, classes in ObjC are just fancy C-structures).
Thus using the '.' implies that you're accessing the property. Properties is the feature that was added in Objective C 2.0 and allows you access your ivars via setter/getter methods, that could be created automatically (using #synthesize) or you can provide your own implementation. BTW it is absolutely not necessary for properties to have corresponding ivar. For example in #interface you declare:
#interface Ololo : NSObject {
//NOTE: there is no ivar named someText or _someText or whatever you want
}
#property(nonatomic) NSString* someText;
#end
Then in #implementation:
#implementation Ololo
#dynamic someText; //we're using this to tell compiler that we will provide getters/setters ourselves and it doesn't need to generate them (though it is not necessary to do that)
-(NSString*) someText {
return [NSString stringWithContentsOfFile: #"some_file_path"]; //we actually get value from file
}
-(void) setSomeText:(NSString*) str {
[#"asdas" writeToFile: #"some_file_path" atomically: YES];
}
#end
Actually you can do whatever you want in those methods. So using '.' is just shortcut for [obj setSomeText: #"hello"].
If you use . you are accessing a property of the class which you defined using #property and created with #synthesize. If you use -> you just access an instance variable, but its not really something you should use a lot. And the use is very limited. So don't make it difficult for yourself and use properties with .
The indirection operator (->) is inherited from C and can be used as a shorthand for accessing fields in a structure, to which you have a pointer.
As an example...
typedef struct IPhone {
int serialId;
} IPhone;
Here I have a traditional C struct which I can instantiate as follows...
IPhone *phone = (IPhone*)malloc(sizeof(IPhone));
Now to access its fields I can either do it the long way...
*(phone).serialId = 1123432324;
Or I can use the shorthand indirection operator...
phone->serialiId = 1123432324;
At the heart of every ObjectiveC class is a C struct. So what you're doing when you use the indirection operator is to jump back to old C syntax to backdoor into the underlying representation. It works, but it's not the prescribed ObjectiveC way.
object->variable is direct access to the variable. object.variable is a method call to the getter accessor method '-(id)variable'or setter accessor method '-(void)setVariable:(id)value' depending on context. You must write the accessor methods yourself or use #synthesize to generate them in order to use dot syntax.
Good programming practice dictates you always use accessor methods to access an instance variable from another instance. ie, dont use ->

Dot notation - Does it take parameters?

Is it correct if I say that
[anIstance aMethod];
is equivalent to
anIstance.aMethod; --?
If it is the case, what about methods which take one ore more parameters?
Does the following statement
[anIstance aMethod : aParameter];
have an equivalent dot notation?
I have tried with
anIstance.aMethod : aParameter;
anIstance.aMethod(aParameter);
And they don't seem to work (compile time errors)
If there is not a way to invoke a method with parameters in dot notation what about the synthesized setter methods (which, as far as I know, by definition take an argument)?
If I have a synthesized property, does the following statement
anIstance.aProperty = anotherObject;
invoke the relative setter method? Or does it call the getter method?
The other answers convey the general idea, but I'd like to explicitly state that dot notation and properties are separate concepts. Dot notation is intended for setters (methods named setSomething: that take a single parameter) and getters, and can also be used for any method that takes no parameters (though it's very poor style to use it for an action like myObject.doSomething).
Properties are designed to declare getters and setters more easily, and even generate the code for you.
So the two concepts are related, but it's entirely possible (and not always poor style) to use dot notation with your very own getters and setters, that you wrote by hand. It's also entirely possible (and usually perfectly acceptable!) to use properties, even with getters and setters generated for you, with normal bracket syntax, and not dot notation.
But to address the original question, no, dot notation does not take parameters. It's specifically designed for use with methods that don't take parameters.
This is covered in Apple's "The Objective C Programming Language" guide:
#interface MyClass : NSObject
{
float value;
}
#property float value;
#end
You can think of a property
declaration as being equivalent to
declaring two accessor methods. Thus
#property float value;
is equivalent to:
- (float)value;
- (void)setValue:(float)newValue;
dot-notation is only valid for properties. Properties are declared with the #property declaration in Objective-C
like this:
interface MyClass {
NSString * x;
}
#property (copy) NSString *x;
implementation:
#synthesize x;
// this will generate a setter and getter method:
// - (NSString *) x {}
// - (void) setX:(NSString *)value {}
then you can use:
MyClass *obj = [[MyClass alloc] init];
obj.x = #"test";
But this only works for properties. Not for methods.
Dot notation is just syntactic sugar for properties in Objective-C, you can't use it for general method calls.