Is UIColor's CGColor accessor a property or method? - objective-c

I found a curious bit of code near the bottom of UIColor.h (lines 69-71 in my SDK):
// Access the underlying CGColor or CIColor.
#property(nonatomic,readonly) CGColorRef CGColor;
- (CGColorRef)CGColor NS_RETURNS_INNER_POINTER CF_RETURNS_NOT_RETAINED;
Why is CGColor defined as both a property and a method? Is it truly a property but just defined as a method so they use the two annotations?

the method is the synthesized getter method of the property, which needs to be declared to be able to assign the return annotations

Related

Objective-C: which getter method should I implement for read-only BOOL properties?

I am writing a subclass for the UITextRange class, which has the following property:
#property(nonatomic, readonly, getter=isEmpty) BOOL empty
Should I write an implementation for the empty or the isEmpty method in my subclasss? Should I write implementations for both?
getter=isEmpty means that the getter method named - (BOOL)isEmpty is called when you write someVariable = obj.empty. So you should implement the isEmpty method.

Easy iOS Line of Code Explanation

I am doing the 'Your Second App' tutorial and it has me add the line of code below that is a setter for the masterBirdSightingList property. I just have a basic questions on it:
Is this line the same as if I were to synthesize it? If not, what makes it different?
- (void)setMasterBirdSightingList:(NSMutableArray *)newList
{
if (_masterBirdSightingList != newList) {
_masterBirdSightingList = [newList mutableCopy];
}
}
If the property is defined as:
#property (nonatomic, copy) NSMutableArray *masterBirdSightingList;
then implementing this method is not the same as simply using #synthensize masterBirdSightingList;.
Defining a property with copy semantics for a mutable container type doesn't actually work as expected using the default synthesized setter.
Without the explicit method, you actually end up with the property referencing an immutable copy of the array.
By using the code you posted, instead of relying on the synthesized method, you get the proper and expected behavior of having a mutable copy of the original array.
Another way to look at this is that calling copy on an NSMutableArray returns an NSArray, not an NSMutableArray. This is why the default synthesized property setter doesn't work as expected (when dealing with a mutable container property). So you must implement the setter yourself and call mutableCopy on the parameter.

Accessing member variable in objective c

What is the difference between the code:
[[self label] setText:#"Hello"];
[label setText:#"Hello"];
Is it correct that they are basically the same if I call them from inside the class?
So if I call it from another class it will be:
[[someclass label] setText:#"Hello"];
someclass.label.text = #"Hello";
Is this correct? This self is disorientating me.
self is a pointer to the object that's had the method called on it.
[label setText:] would presumably access the instance variable directly. The other ways all go through the accessor method.
Self is only the way to show you that Label or anything you taking is belong to the current class. self will just tell you the entity belong to the same current class where you are declaring it or assigning some value to it.
And if you assigning that label to other class is a different thing.
Yes both way are correct. in
someclass.label.text = #"Hello";
You are directly accessing the property
while in
[[someclass label] setText:#"Hello"];
You are using setter method to set value of text property which is created by objective C for you.
But I prefer set method more. but there is nothing wrong in using property.
The confusion stems from that #synthesize by default generates an iVar with the same name as the property.
The [[self label] setText:#"Hello"]; line will access the property label and call setText on that.
The [label setText:#"Hello"]; will access the iVar label and call setText on that.
The difference is that when you use the iVar, any settings you set on the property (atomic, copy, retain etc.) will not be respected.
It's usually better to just use the property if you don't have any particular reason not to. You can make this easier to remember by synthesizing the iVar with another name using;
#synthesize label = _label;

Objective-C Command Line Equivalent of ViewDidLoad

I was just wondering where I should set the values of variables for use in all my methods.
For example, let's say in my .h I say:
#property NSString *name; and then synthesize it in the .m. Where do I assign it a value so in my functions, say -(NSString *)changeUsername:(NSString *) changes and -(void)deleteUsername, I can access that data?
main() is the first thing that gets called in a command line program. Wouldn't you do it there (or somewhere called from main())?
Since you're talking about properties, you must have a class that you're instantiating. That class's designated initializer (-init or similar) is the right place to set up your properties and/or instance variables.
The only reason that Cocoa Touch apps defer some initialization tags to -viewDidLoad is that view controllers don't load their views when they're initialized and some properties or ivars are related to the view(s) that will be loaded. Those things clearly can't be set up until the view is loaded (or created), so -viewDidLoad becomes the best place for setting up those sorts of things.
Well you COULD do so in an initializer for your class and indeed, this would be the approach in C++ or maybe Java. In objective-c, you usually use lazy instantiation, and the best place to do that is in the getter for that property.
If someone assigns a value to the property the setter is called and everything is fine.
If someone asks FOR the value and it has not been set yet (is nil) you can create the object and/or assign a default value in the getter.
// Override accessor for name
- (NSString*)name
{
if (!_name) {
_name = #"unknown";
}
return _name;
}
The accessor methods are the only place you should be accessing instance variables directly.

Objective-C struct property pointer cannot be made via self.prop?

I've just encountered a little surprise whilst writing NSCoder support into a class. I have a class A which contains an exposed 'color' property of an rgb struct type. I have another class B which extends A.
To encode the color property within class B's encodeWithCoder method I've first wrapped it into an NSValue like so:
[NSValue value:&(self.color)]
However using this code causes the following compilation error:
Lvalue required as unary '&' operand.
It's easy enough to get around by simply copying self.color to a method-scope value before wrapping with NSValue, but I'd like to understand the rule for when this will happen, and why it occurs. Will this happen with any #synthesize property due to there being no need for a true class field of that property name to exist, hence no guaranteed object to point to?
You cannot get the address of something returned by a function (or method). You need to get the address of the color ivar directly (i.e. &color). In your case though, I recommend using the approach you proposed yourself (id tempCol = self.color; [NSValue value:&tempCol];).
Note that a method is invoked when using dot notation.
self.color
// is equal to
[self color]
&([self color]) is also impossible because & is resolved at compile-time, not at runtime. The return value of [self color] and self.color (which are equal) aren't yet known at compile-time (even when using #synthesize, since you can change a method's implementation in Objective-C at runtime (e.g. with method swizzling or using categories)).
It seems that you don't fully understand what #synthesize does, so I'll explain. :)
Basically what #synthesize does is this: the compiler generates methods and their implementations from the given property names.
For example, this property:
#property(nonatomic, retain) NSColor *color;
Together with this synthesization:
#synthesize color;
Will insert this code for you in the #implementation:
- (NSColor *)color {
return color;
}
- (void)setColor:(NSColor *)newColor {
if (color == newColor) { return; }
NSColor *theOldColor = color;
color = [newColor retain];
[theOldColor release];
}
When you like to use your own setter or getter, you simply define these in the #implementation by using the same method names. You could, for example, return a default color if none is set yet:
- (NSColor *)color {
if (color) { return color; }
return [NSColor whiteColor];
}
Now the compiler will generate the setter, but not the getter: it will use the getter you provided, you can still use it with self.color.
You may want to take a look at Apple's guide on properties.
The rule is simple enough. The compiler turns a property access:
self.color
into a method call*
[self color]
which means that &(self.color) turns into &([self color]). Then the compiler complains, because you can't take the address of a method call.
*If you were assigning to the property, the assignment would be transformed into a call to the setter: self.color = aColor; -> [self setColor:aColor];.