I am learning how to create iPhone apps and I have seen that most of the variables we create store memory addresses (pointers) instead than holding the actual value or object. I also have found out that every time you declare a variable with the pointer char (*) you know that the variable is going to hold the address and whenever you don't use the (*) mark to declare a variable you know that it will hold the value instead than the memory location. But I don't know when to us which. for example I have:
CGFloat someVar = [image1 alpha]; // This variable does not require *
// image 1 is a: IBOutlet UIImageView
and in this other case I have to use a pointer:
UIViewController *someOtherVar = [[UIViewController alloc] init]; // this type of var requires *
It will be nice if I can know when can I use each instead of trying each until project compiles.
The function and method signatures in the headers and documentation will indicate what the type is.
For example, here is how the alpha property is declared for UIView:
#property(nonatomic) CGFloat alpha;
There is no * anywhere, so you know it returns CGFloat and not CGFloat*.
In contrast, the backgroundColor property is declared like this:
#property(nonatomic, copy) UIColor *backgroundColor;
so you know it will return UIColor* (a pointer).
Some things are declared with a type of id, which is always going to be a pointer to an object.
In general, Objective-C objects (types declared with #interface) will always be referenced as pointers, while primitive C types and structs will often (but not always) be passed and returned by value.
Oversimplifying greatly, but it depends on the data being returned.
From your examples, CGFloat is a wrapper for float, which is a primitive C data type. [image1 alpha] returns a CGFloat. UIViewController is an object type. [[UIViewController alloc] init] returns a pointer to this allocated memory, (UIViewController *). Therefore you need to use the pointer.
Pointers can be used in more cases than can be described. Generally speaking, as you are starting out, you typically use pointers for objects. But I encourage you to check the documentation to determine the exact data type. It will provide hints as to the data type returned by a specific method or property.
Related
Coming from Java et al, I'm not clear on the difference between these two declarations:
#property (nonatomic, readwrite) NSInteger score;
#property (nonatomic, strong) NSMutableArray *cards;
Why is the pointer, *, not a requirement on both property declarations?
I've seen this a lot in local variables too:
- (void)viewDidLoad
{
[super viewDidLoad];
int foo = 1;
NSString *bar = #"foo";
}
What's the difference between static allocation of primitive type int and NS types?
Objective-C objects are always allocated on the heap, so you always access them through pointers. Variables of primitive (or struct) types can be, and typically are, allocated on the stack and accessed without pointers.
If you're familiar with Java, it's basically the same semantics. Primitive types are accessed and passed around by value, objects by reference. The difference is that ObjC has (by virtue of its C lineage) syntax explicitly marking that difference.
Type names that start with an uppercase prefix in Apple frameworks aren't all ObjC classes. NSInteger is a primitive type just like int, so you can and usually do use it without pointers.
pointer is always used for referring to something at the heap but not when you referring to something on the stack.But
for some primitive types and simple structure which are accessed via the stack so you don't need to use pointer..
NSInteger is a primitive type, that means it will be stored locally on the stack. there is no need to use a pointer to access it, but if you want to use pointer then you can.
You can have a pointer to an NSInteger if you really want to with following way:
NSInteger *pointerToProcessID = &yourNsintegervar;
If you look at the definition of NSInteger you'll see that it is a typedef for a simple integer. Basically, all the non-object types are stored as simple values, while the types that are complex objects are typically pointer properties. There are a couple reasons why these more complex objects are stored as pointers:
Using the value, itself, instead of the pointer would require copying (that is, if you use a pointer, you can put the object somewhere else and you only need to copy the much shorter address rather than all of the content that happens to be in that object, and hence it is more efficient that way).
When using a non-pointer type, it is necessary to know the required storage space, which works if you know the exact type of the object, but fails in the case of inheritance (e.g. an NSMutableArray may add additional fields to NSArray, for example. If you were to use NSArray instead of NSArray*, then assigning from an NSMutableArray would be broken, because the system would only have set aside enough space for the fields in the base class and not for the derived class. When using a pointer, however, since the pointer size is the same for both the base and derived types, one can assign the pointer for a derived type to a pointer to the base type, and still have things work correctly).
Note that it is possible and safe to use a pointer type with these primitive types, as well; however, this is not done for efficiency reasons (it would create additional allocation and dereferencing where not necessary).
As the question states, I would prefer an immutable version of CGPoint, CGSize, and CGRect, although I would rather use a type which is supported by the iOS framework, to avoid converting between types.
So, is there any supported immutable version of CGPoint? If not, any recommendations?
Thanks!
You can just use constant CGPoints etc.
E.g.:
const CGSize size = (CGSize){6.0f, 4.0f};
Using CGSizeMake won't work as they are not compile time constants and you can't use variables, but this is the closest you'll get to an immutable CGSize. If that is not good enough then you'll need to use an object and convert when needed.
When a CGPoint (or any other struct - CGRect, etc.) is a property of an Objective-C object, the mechanics of getter/setter methods and the value semantics of C structs means that there is some level of protection against indirectly modifying the value of a CGPoint property of an object. For example, an expression like someObject.someCGPointProperty.x = 123 will not actually modify the x value of the CGPoint owned by someObject, because the someCGPointProperty accessor will return the CGPoint by value, which means that you are setting the x value on a copy of the CGPoint. To actually modify the CGPoint owned by that object, you would need to do something like:
CGPoint point = someObject.someCGPointProperty;
point.x = 123;
someObject.someCGPointProperty = point;
Regarding control over the number of instances you create: since CGPoint is a struct, it's passed around by value - effectively it's copied - in function arguments or Objective-C messages. So there's going to be plenty of copies of thees structs moving around anyway. However, these structs are created on the stack, not the heap, and a CGPoint is only 16 bytes (possibly smaller on 32-bit iOS devices?), so it's doubtful you need to worry about any performance implications.
Also, see #hypercrypt's more succinct answer regarding const values, as that may address your intentions well.
You can use the NSValue wrapper class. It can wrap a point, a size, a rect and more. It's immutable, so whatever you store inside it can't be changed (remember that if you store a pointer, the memory area to which points can still be changed).
Example
NSValue* value= [NSValue valueWithCGPoint: CGPointMake(x,y)];
If you try to set value.CGPointValue.x or y you get a compile error. The getter returns just a copy of the CGPoint held in the object, so there's no way to change it's value.
Sanity check. Given this:
#property (readwrite, nonatomic) NSDate *start;
Then aren't these 2 lines of code identical?
Version 1:
self.start.description
Version 2:
[self.start description]
i.e. start.description calls the description method on the start object.
Yes, they're identical, and so is [[self start] description]
Basically yes.
Around the property there is a setter and getter autosynchoronizsed. In the event that you use an #syncronize statement then you have a chance to influence how the setter, getter and property are named. If you autosynchronize the property's name is _start. The getter name is start and the setter name is setStart.
So
something = self.start
actually calls the getter and
self.start = something
calls the setter.
Equivalents are:
something = [self start];
[self setStart:something];
If you ever want to access the instance variable directly then do so by:
_start = something;
something = _start;
In the event that you just use #synthesize start; then the equivalent would be:
start = something;
something = start;
That may well be confusing but start actually addresses the instance variable while self.start uses the setter/getter. This difference comes to vast importance when you do not ARC. Depending on the property parameters (e.g. assign, copy, retain, ...) the automatically generated getter and setter does some memeory management for you while the memory management is left to you when you work directly with the instance variable.
Yes. The result will be identical in both cases; properties are (mostly) just sugar around accessor methods written in the conventional Cocoa style.
I say "mostly" because there are some minor internal differences. Properties are added as meta-data to the runtime description of the Objective C class. You can, via some reflection, find out a list of properties that have been declared as such. This list is different from a list of methods that are named in the style of getter/setters.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between self.ivar and ivar?
In Objective-C, what's the difference between [self setVariable: newStuff] and variable = newStuff?
When you have a class with a variable
#property (nonatomic) NSInteger num;
and you want to change the variable, typically you can do
[self setNum: newNum]
but you can also do
num = newNum
I know if you declare the variable readOnly, you can't use the first method to change it, but what's the concept behind it? Is it just because the second method with the setter can be called outside of its own class? Like if the class's instance was called 'sample'.
[sample setNum: newNum]
but then if you are changing the variable inside the class, either way is fine?
In Objective-C, what's the difference between [self setVariable:
newStuff] and variable = newStuff?
To be absolutely pedantic, one of them assigns the variable property the value in newStuff, whereas the other one assigns the value of newStuff to the iVar variable, but what I think you had in mind was a comparison between [self setVariable:
newStuff] and self.variable = newStuff. In that case, nothing is different, the compiler will expand case 2 out to case 1.
I know if you declare the variable readOnly, you can't use the first
method to change it, but what's the concept behind it? Is it just
because the second method with the setter can be called outside of its
own class? Like if the class's instance was called 'sample'.
readonly variables are important in cases where certain properties are private to the implementation of a class, but should be visible to other classes.
For example, if I were writing a Stack, I might want to expose the count of the number of items on the stack, but it would be a very bad idea for other classes to be able to write to the count variable. If I weren't smart and were using something like a count variable, I would want to be able to adjust the count of the semaphore internally (meaning you need it to be internally readwrite), so I declare a visibly readonly property so other classes can get it, but declare it internally readwrite so I can modify it:
//.h
#interface CFExampleStack : NSObject
#property (nonatomic, assign, readonly) int count; //readonly
#end
//.m
#interface CFExampleStack ()
#property (nonatomic, assign) int count; //readwrite
#end
Is it just because the second method with the setter can be called outside of its own class?
Well, that depends on how your instance variable is declared. By default, instance variables are #protected, i. e. they can be accessed from within the class and its subclasses only. However, if you explicitly declare an ivar as #public, then you can access it outside the class, using the C struct pointer member operator ->:
obj->publicIvar = 42;
However, this is not recommended, since it violates encapsulation.
Furthermore, if you use a custom setter method, then you have the opportunity to do custom actions when a property of an instance is updated. For example, if one changes the backgroundColor property of a UIView, it needs to redraw itself in addition to assigning the new UIColor object to its appropriate ivar, and for that, a custom setter implementation with side effects is needed.
Additionally, there are retained ("strong") and copied properties in case of instance variables that hold object. While writing a setter for a primitive type such as an integer is as simple as
- (void)setFoo:(int)newFoo
{
_foo = newFoo;
}
then, in contrast, a retained or copied property needs proper memory nanagement calls:
- (void)setBar:(Bar *)newBar
{
if (_bar != newBar) {
[_bar release];
_bar = [newBar retain]; // or copy
}
}
Without such an implementation, no reference counting would take place, so the assigned object could either be prematurely deallocated or leaked.
One more important difference...
Whenever you use self.prop KVC comes into play and you can observe the changes in the object, while _prop bypasses it.
With XCode 3 compiler, I could manage an array of objects like:
#interface myView:UIView
{
CALayer *layer[4];
}
#property (nonatomic,retain) CALayer **layer;
#end
#implementation myView
#dynamic layer;
- (CALayer **)layer { return layer; }
// I could then access elements like
- (void) example
{
self.layer[3] = NULL;
}
#end
With XCode 4 compiler the #property declaration generates an error "Property with retain must be an object type".
I guess best way to fix is to convert to NSArray, but I have 100's lines of code using the c-style array subscript (e.g., self.layer[i]). Is there some other way to fix?
Several problems with this code:
It should be MyView, not myView; classes start with capital letters.
CALayer ** is not an object type; it is a pointer to an object type, hence the compiler complaint. Simply making it assign will make it compile, but it'll still be wrong.
There is likely no reason to use a language array (MyClass foo[4]) to hold this data. Use an NSMutableArray (you can use [NSNull null] as a stand-in for "this slot is not populated".
If you really want to stick with the language array, drop the retain. Just remember that you have to explicitly manage the retain/releases of the objects within the array. The #property won't do that for you.
Also, while it may seem a pain to fix your code to be inline with typical standard patterns, it is only going to be more costly to do so as the code evolves and, someday, you'll likely be in a situation where you really need to do so....
Change it to an assign property so you don't try to retain a non-object?
You cannot use Objective-C memory management calls (i.e. retain) on a C array. You need to manage your array using standard C or C++ logic. You need to malloc and free memory on your own. If you do not need to retain the array then you can remove the retain property.