What's the difference between KVC and Properties? - objective-c

So, I've already read up on the documentation which notes
Objective-C 2.0’s dot syntax and key-value coding are orthogonal technologies. You can use key-value coding whether or not you use the dot syntax, and you can use the dot syntax whether or not you use KVC. Both, though, make use of a “dot syntax.” In the case of key-value coding, the syntax is used to delimit elements in a key path. It is important to remember that when you access a property using the dot syntax, you invoke the receiver’s standard accessor methods.
It then provided an example that supposedly showed the difference between the two. However, I still don't get, what's the difference between KVC and property accessor methods? Aren't they the same? And how do I distinguish between dots that call setValue:forKeyPath: and simple accessors?

However, I still don't get, what's the difference between KVC and property accessor methods?
KVC is a way to call property accessor methods, or otherwise access a property.
What do I mean by “otherwise access”? For KVC purposes, an instance variable with no accessor methods counts as an informal property. It'll get or set the value of the instance variable directly if no matching accessor pair can be found. (Yes, this is not worth using in modern code. Always declare an #property for anything you intend to access elsewhere, and, inversely, don't use KVC to access anything that isn't a public property.)
Property accessor methods are what KVC will call if they exist (preferred, both by KVC and by every sane programmer, over direct ivar access). An accessor may get or set an instance variable, as synthesized accessors do, or access some other storage.
Accessors are implementation, properties are interface, and KVC is one way to use them.
And how do I distinguish between dots that call setValue:forKeyPath: and simple accessors?
A key path is a string, whereas a property-access expression is an expression. The compiler evaluates a property-access expression and translates it into one or more Objective-C messages, whereas a key path is evaluated by KVC at run time.
So, when you use a key path:
[someObject setValue:theValue forKeyPath:#"foo.bar.baz"];
You know it's a key path because (1) it's a string, as indicated in this case by the string-literal syntax #"…", and (2) you're passing the key-path string to setValue:forKeyPath: for it to evaluate.
Using a key path is using KVC to access the named properties. It will send any relevant accessor messages on your behalf.
When you use a property-access expression:
someObject.foo.bar.baz = theValue;
You know it's a property access expression because you are not identifying the properties with a string. You are accessing them (sending the accessor messages) yourself, in your own code.
There isn't much reason to use KVC in any form; when you know the property at authorship/compile time, it's best to have an #property declared and to access the property yourself, whether with property-access expressions or message expressions ([[[someObject foo] bar] setBaz:theValue]). The time to use KVC is when you don't know what property you want to access until run time, which is pretty rare. It's mainly a building-block technology behind KVO, Cocoa Bindings, parts of Core Animation, etc.
Mostly, you'll only want to access properties yourself.

Key value coding allows you to set and get the value of properties through code using the string name of the property. For example, if I had a property named foo which is of type NSString:
[self setValue:#"mystring" forKey:#"foo"];
// read the value by key
NSString *s = [self valueForKey:#"foo"];
Dot syntax is compile syntax sugar. As a personal preference (as some don't agree - fine) I don't use dot syntax but I still use KVC:
[myObj setFoo: #"someString"]
equals:
myObj.foo = #"someString";
They are orthogonal, different concepts but both dealing with how you interact with properties
Finally, you mention property syntax. Yet another orthogonal concept but related to dealing with properties.
With objective-c, convention is important. Follow them. Properties are the name of the property for the get and set[Name] for the assignment:
- (NSString*)foo
{
return _foo; // defined as (NSString*)_foo in header
}
- (void) setFoo: (NSString*)foo
{
if (foo == _foo)
return;
NSString* curr = _foo;
_foo = [foo retain];
[curr release];
}
Now, who wants to write something like that every time. So, enter #property syntax:
In header:
#property (retain) NSString *foo;
Then in .m:
#synthesize foo;
That's the equivalent of the hand written property accessors. It's compiler syntax sugar which expands the property code based on how you attribute the properties.
Docs:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html

Related

what is the getter method of a simple property called

I am trying to understand the methods generated when properties are used.
Say I have the following declaration
#property int myint;
Now I know I could access this variables as such (say d was my instance of the class)
d.myint = 12; //this is equivalent to [d setMyint:12];
NSLog(#"The value is %d",d.myint); // what method is generated ?
What is the getter method called ? I was under the impression it was called getMyint however that isnt available ? Any suggestions if I might be missing something here?
As stated in the other answers, the proerty declaration gives you a getter and a setter for that instance variable for free! The notation is that you can either get [self myInt]; or self.myInt;. Both calls are 100% equivalent, i.e. they will both call the method - (int)myInt. This method is not visible (or rather, it's not explicitly implemented, see below) by default, however, you can implement it to provide some custom logic (e.g. check for specific values, error handling or lazy instantiation). If you want to override it, put this in your .m file.
- (int)myInt {
NSLog(#"getter of my int called, current value %d", _myInt);
return _myInt;
}
I only want to add to the the previous answers that in Objective-C, you have the possibility to rename your getters and setters when declaring the property, like so:
#property (getter=getMyInt) int myInt;
you can call those in the exact same way that you would use your normale getter:
int myInt = [self getMyInt];
// or
int myInt = self.getMyInt; // (will work but is not recommended since the compiler will interpret this as calling the getter of a property named `getMyInt` and only when this one is not found will actually fall back to the custom getter (thx to #NikolaiRuhe again for pointing this out))
Update:
Agreeing with most of what #NikolaiRuhe stated in his comment, here is a clarification of my answer referring to the mentioned issues:
This is indeed a typo, of course the way to use the property getter is by either calling [self myInt] or using dot notation self.myInt, and not [self getMyInt]. These calls are however 100% equivalent since they both invoke the actual getter.
About the visibility, indeed I should have been more explicit here. In OOP terms, visibility is a concept that describes the accessibility of instance variables from the outside of a particular class. I meant it exactly in the way that #NikolaiRuhe suggested, i.e. that this method is not explicitly implemented (so, it's not visible in the code by default). Sorry about this misunderstanding!
I am actually not sure about this point. For me this didn't make much of a difference in the past, I don't insist on this point. So I'd well acknowledge that the act of explicitly implementing a getter is not actually an override but rather a replacement of the synthesized method.
After explicitly renaming the getter to getMyInt like I suggested above, I don't see anything "wrong" with calling self.getMyInt. Why would this be the wrong way to access the property?
The getter method would be:
[d myInt];
Per the Apple docs :
You access or set an object’s properties via accessor methods:
NSString *firstName = [somePerson firstName];
[somePerson setFirstName:#"Johnny"]; By default, these accessor methods are synthesized automatically for you by the compiler, so you
don’t need to do anything other than declare the property using
#property in the class interface.
The synthesized methods follow specific naming conventions:
The method used to access the value (the getter method) has the same
name as the property. The getter method for a property called
firstName will also be called firstName.
The method used to set the value (the setter method) starts with the
word “set” and then uses the capitalized property name. The setter
method for a property called firstName will be called setFirstName:.
The syntax of getter method would be-
-(int)myint{
return myInt;
}
It will return myInt property of the receiver if this message i.e. d in your case.
If you are creating a property in objective-c, it creates 3 things for you.
an instance variable which you can access by using an underscore before the property name. Ex: _myint
a getter method which you can call directly by using the property name. Ex: [self myint]; / self.myint, this will actually call - (int)myint {} method.
a setter method which you can call by using a 'set' keyword before it. Ex: [self setMyint:12]; / self.myint = 12, this will actually call - (void)setMyint:(int)myint {} method.
Source
So when you write d.myint = 12; this is equivalent to writing [d setMyint:12];
And when you write NSLog(#"The value is %d",d.myint); this is equivalent to writing NSLog(#"The value is %d",[d myint]);
Custom Getters and Setters
Credits
You can also give custom names to your property Getters and Setters. This is how it is done
#property (getter=getMyInt, setter=setMyIntWithInt) int myint;
Ex:
[d setMyIntWithInt:12]; //This will set the instance variable to 12.
NSLog(#"The value is %d",[d getMyInt]);
Also, you can override these methods in your implementation(.m) file for error handling or lazy instantiation.

Key-Value-Coding with arbitrary methods, not only properties

It seems that -valueForKey: and -valueForKeyPath: work with arbitrary methods, not only with properties. This seems very convenient:
I first stumbled upon it in Interface Builder, and then made some experiments:
// Thing.h
#import <Foundation/Foundation.h>
#interface Thing : NSObject
- (BOOL) alwaysYES;
- (BOOL) alwaysNO;
#end
// Thing.m
#import "Thing.h"
#implementation Thing
- (BOOL) alwaysYES
{
return YES;
}
- (BOOL) alwaysNO
{
return NO;
}
#end
I can call these methods via -valueForKey: and -valueForKeyPath: despite the fact that they are normal methods and no properties:
Thing *aThing = [[Thing alloc] init];
id result;
result = [aThing valueForKey:#"alwaysYES"];
NSLog(#"result is: %#", result);
result = [aThing valueForKeyPath:#"alwaysNO"];
NSLog(#"result is: %#", result);
Compiles, runs and gives the correct results. Is this documented anywhere? Can I safely use it? How can i understand it?
Cocoa's key-value coding (KVC) system is older than support for explicit properties (declared with #property) in Objective-C, so KVC is defined in terms of methods, not properties.
“Default Search Pattern for valueForKey:” in the Key-Value Coding Programming Guide spells out how valueForKey: decides what to do. It starts by looking for (amongst other things) a method whose name is exactly the key you passed to valueForKey:. Here is the full search pattern, quoted from the documentation:
Searches the class of the receiver for an accessor method whose name matches the pattern get<Key>, <key>, or is<Key>, in that order. If such a method is found it is invoked. If the type of the method's result is an object pointer type the result is simply returned. If the type of the result is one of the scalar types supported by NSNumber conversion is done and an NSNumber is returned. Otherwise, conversion is done and an NSValue is returned. Results of arbitrary types are converted to NSValue objects, not just NSPoint, NSRange, NSRect, and NSSize types).
Otherwise (no simple accessor method is found), searches the class of the receiver for methods whose names match the patterns countOf<Key> and objectIn<Key>AtIndex: (corresponding to the primitive methods defined by the NSArray class) and <key>AtIndexes: (corresponding to the NSArray method objectsAtIndexes:).
If the countOf<Key> method and at least one of the other two possible methods are found, a collection proxy object that responds to all NSArray methods is returned. Each NSArray message sent to the collection proxy object will result in some combination of countOf<Key>, objectIn<Key>AtIndex:, and <key>AtIndexes: messages being sent to the original receiver of valueForKey:. If the class of the receiver also implements an optional method whose name matches the pattern get<Key>:range: that method will be used when appropriate for best performance.
Otherwise (no simple accessor method or set of array access methods is found), searches the class of the receiver for a threesome of methods whose names match the patterns countOf<Key>, enumeratorOf<Key>, and memberOf<Key>: (corresponding to the primitive methods defined by the NSSet class).
If all three methods are found, a collection proxy object that responds to all NSSet methods is returned. Each NSSet message sent to the collection proxy object will result in some combination of countOf<Key>, enumeratorOf<Key>, and memberOf<Key>: messages being sent to the original receiver of valueForKey:.
Otherwise (no simple accessor method or set of collection access methods is found), if the receiver's class method accessInstanceVariablesDirectly returns YES, the class of the receiver is searched for an instance variable whose name matches the pattern _<key>, _is<Key>, <key>, or is<Key>, in that order. If such an instance variable is found, the value of the instance variable in the receiver is returned. If the type of the result is one of the scalar types supported by NSNumber conversion is done and an NSNumber is returned. Otherwise, conversion is done and an NSValue is returned. Results of arbitrary types are converted to NSValue objects, not just NSPoint, NSRange, NSRect, and NSSize types.
If none of the above situations occurs, returns a result the default implementation invokes valueForUndefinedKey:.
This is parallel to the fact that you can call these methods using property syntax:
BOOL ok = aThing.alwaysYES
In that case and in your case, exactly the same thing happens: the first thing the runtime tries is to treat this as a getter method. What you've written is a getter method.
As for your question "can I safely use it", safely yes, but what you're doing is kind of silly, since you know (and have declared) that these methods exist. KVC is about probing to see whether methods exist. If you have a reason to specify one of these methods by string name, there are better ways to call it than using KVC.
Properties are nothing special at runtime; they generate a getter and setter (if not readonly) which conforms to KVC; for example:
#property NSString *aString;
will generate:
- (NSString)aString {
...
}
- (void)setAString(NSString *string) {
...
}
just as if you had declared those methods in the header (which itself is optional).
See the Key Value Coding Fundamentals documentation.

How to test property existence and type based on NSString typed key?

In my quest to update a Core Data model within my iOS project, I'm querying a server for JSON objects that correspond - to some extent - with the managed entities of my model. The end result I'm striving for is a reliable update solution from JSON output.
For the examples in this question, I'll name the core data managed object existingObj and the incoming JSON deserialized dictionary updateDict. The tricky part is dealing with these facts:
Not all properties of the existingObj are present in the updateDict
Not all properties of the updateDict are available in the extistingObj.
Not all types of existingObj's properties match the JSON deserialized properties. (some strings may need a custom Objective-C wrapper).
updateDict may contain values for keys that are uninitialized (nil) in existingObj.
This means that while iterating through the updated dictionaries, there has to be some testing of properties back and forth. First I have to test whether the properties of the updateDict exist in existingObj, then I set the value using KVC, like so:
// key is an NSString, e.g. #"displayName"
if ([existingObj respondsToSelector:NSSelectorFromString(key)) {
[existingObj setValue:[updateDict objectForKey:key] forKey:key];
}
Although this part works, I don't like the fact that I'm actually testing for displayName as a getter, while I'm about to call the setDisplayName: setter (indirectly via KVC). What I'd rather to is something like [existingObj hasWritablePropertyWithName:key], but something that does this I can't find.
This makes for subquestion A: How does one test for a property setter, if you only have the property's name?
The next part is where I'd like to automate the property identification based on their types. If both the updateDict and the existingObj have an NSString for key #"displayName", setting the new value is easy. However, if the updateDict contains an NSString for key #"color" that is #"niceShadeOfGreen", I'd like to transform this into the right UIColor instance. But how do I test the type of the receiving property in existingObj so I know when to convert values and when to simply assign? I was hoping for something along the lines of typeOfSelector:
if ([existingObj typeOfSelector:sel] == [[updateDict objectForKey:key] class]) {
// regular assignment
} else {
// perform custom assignment
}
Of course this is boguscode. I can't rely on testing the type of the existingObj-property's value, for it may be unitialized or nil.
Subquestion B: How does one test for the type of a property, if you only have the property's name?
I guess that's it. I figured this must be a dupe of something that's already on here, but I couldn't find it. Maybe you guys can?
Cheers, EP.
P.S. If you'd have a better way to synchronize custom Objective-C objects to deserialized JSON objects, please do share! In the end, the result is what counts.
If you want to query whether an object has a setter for a given KVC key called key which corresponds to a declared property, you need to check whether it responds to a selector method called setKey: (starts with set, capitalise the first character in key, add a trailing colon). For instance,
NSString *key = #"displayName";
NSString *setterStr = [NSString stringWithFormat:#"set%#%#:",
[[key substringToIndex:1] capitalizedString],
[key substringFromIndex:1]];
if ([obj respondsToSelector:NSSelectorFromString(setterStr)]) {
NSLog(#"found the setter!");
[obj setValue:someValue forKey:key];
}
Two remarks:
Even though properties can have setters with names that do not follow the pattern described above, they wouldn’t be KVC compliant, so it is safe to check for set<Key>: since you’re using KVC to set the corresponding value.
KVC doesn’t use the setter method only. If it doesn’t find a setter method, it checks whether the class allows direct access to instance variables and, if so, use the instance variable to set the value. Also, if no setter method or instance variable is found, it sends -setValue:forUndefinedKey: to the receiver, whose class might have overridden the standard implementation that throws an exception. This is described in the Key-Value Coding Programming Guide.That said, if you’re always using properties, checking for the setter method should be safe.
As for your second question, it is not possible to query the runtime to know the actual Objective-C class of a property. From the runtime perspective, there’s an implementation specific type encoding for properties and general types (such as method parameters/return types). This type encoding uses a single encoding (namely #) for any Objective-C object, so the type encoding of an NSString property is the same as the type encoding of a UIColor property since they’re both Objective-C classes.
If you do need this functionality, one alternative is to process your classes and add a class method that returns a dictionary with keys and corresponding types for every property (or the ones you’re interested in) declared in that class and superclasses, or maybe some sort of description language. You’d have to do this on your own and rely on information not available during runtime.

NSMutableArray with only a particular type of objects

is it possible to specify that a NSMutableArray can only contain a certain type of objects.
For example, if I want to store only this kind of objects :
#interface MyObject : NSObject {
UInt8 value;
}
In order to be able to use the instance variable like this :
- (void)myMethod:(NSMutableArray *)myArray{
for (id myObject in myArray){
[self otherMethod:myObject.value];
}
}
because I'm getting this error :
request for member 'value' in something not a structure or union
Thank you for your help
It sounds like you're coming from a Java/C# type background where limits can be imposed on collections.
Collections in Cocoa don't follow that pattern. There is no way to set a restriction on what type of objects can be inserted (unless you write a wrapper class that enforces this).
Objective-C, by design, follows the "if it walks like a duck and it quacks like a duck, then it most probably is a duck" philosophy. That is to say that rather than checking whether an object is a particular type, you should be checking whether it can do what you want it to do regardless of its type.
You can do this using respondsToSelector:.
Finally, your problem isn't actually related to the fact that the array has no restrictions. Your object doesn't appear to declare the instance variable value as a property, or expose any accessor methods for it.
This is why you're seeing the error when you try myObject.value. That syntax in Objective-C is how you access properties.
The default scope for instance variables in Objective-C is #protected, which means anything outside your class can't access them without going through an accessor method of some kind.
You need to declare and define the methods - (UInt8)value and - (void)setValue:(UInt8)aValue and use them.
Alternatively, you could declare it as a property.
You are getting that error, because for as far as Objective-C is concerned, myObject is of the non-type id, which doesn't support the value property. To make Objective-C aware of the fact it's always dealing with a MyObject in this loop, you'll have to tell it the myObject object is an instance of MyObject.
for (MyObject *myObject in myArray) {
Also, you have to make sure the value ivar is accessible using dot-notation by implementing getter and setter methods for it. You can do this yourself by implementing -value and -setValue:, or you can use #property and #synthesize to let Objective-C do this.
Objective-C doesn't work like that. You need to use [myObject value] (which will work irrespective of the kind of object, as long as it responds to -[value]. If you only want one type of objects in it, insert only that type of objects.
You would have to write a wrapper-class for the NSMutableArray, see for example this question.
Subclass NSMutableArray and override methods that mediate the addition of objects to the array. You would check the object type in these overridden methods, only calling [super addObject:xyz] if the type is accepted.
maybe you can use protocol:
#protocol Person <NSObject>
#end
#interface Person : NSObject <Person>
#end
to use:
NSArray<Person>* personArray;

Using (id) in Objective-C

I have a function that I want to operate on two different custom objects. My first thought was to accept the argument as an (id) and operate on the id object. I can't quite seem to figure out how to do that, however.
Both classes (say apples and oranges) have interface variables:
NSDecimalNumber *count;
I want to do something similar to this:
-(NSDecimalNumber*)addCount:(id)addObject{
return [count decimalNumberByAdding:addObject.count];
}
I can't seem to figure out the syntax to make that happen. Is this the proper approach, or would it be better to subclass (from say a fruit class) and operate on the parent class?
-(NSDecimalNumber*)addCount:(Fruit*)addFruit{
return [count decimalNumberByAdding:addFruit.count];
}
While you can send a message to any object (id) - property accessors require that the compiler be aware of the type you are dealing with - this is because property accessors are syntactic sugar around calling specific getter and setter methods.
You have a few of ways of working around this:
Instead of accessing the count property, call the corresponding [getCount] methods.
If the different classes have different versions of this method, you can use a runtime type check:
Provide a base class for both types so that you can pass in something more specific than (id).
Define and implement a Protocol that both objects implement that defines a count property (or method).
Example of a dynamic type check:
if( [object isKindOfClass:[Apple Class] )
// call one overload of getCount
else if( [object isKindOfClass:[Orange Class] )
// call another overload of getCount
Personally, I favor strong typing in my code because it makes it easier to understand the intent. It also allows the IDE to support your coding effort with intellisense, static analysis, and refactoring features. So, in your case, I would use either #3 or #4 as an approach - depending on whether inheritance is really appropriate for the problem.
You should try not to access instance variables from another class.
In Objective-C it's enough that the two objects respond to the same selector (say count), however that would give you a compiler warning.
There are two ways you can get rid of this warning: either by subclassing from a common Fruit class or by having your two classes conform to a protocol. I'd go with the protocol:
#protocol FruitProtocol
- (NSDecimalNumber *)count;
#end
#interface Orange : NSObject<FruitProtocol>
#end
#interface Apple : NSObject<FruitProtocol>
#end
Then your method can look like this:
-(NSDecimalNumber*)addCount:(id<FruitProtocol>)addFruit {
return [count decimalNumberByAdding:[addFruit count]];
}
Here you are saying that your addCount expects any object that conforms to the FruitProtocol protocol, and hence can respond to the count selector, so the compiler will accept it.
The fact that you are trying to access 'addFruit.count' is the problem. The dot syntax is only for properties declared with #property (or for structs). If you change it to
[addFruit count]
and add
-(NSDecimalNumber*)count
{
return [[count retain] autorelease];
}
to each class, then it would work. However, you will notice you'll get a warning saying 'id' may not respond to the 'count' message, and unless you can be absolutely sure the items sent to this method implement a 'count' method, this is a problematic approach.
I agree with pgb's approach. You should define a protocol, and declare both classes to implement that protocol. This eliminates the problem of not knowing whether the object will respond to 'count' or not, as you now have a 'contract' of sorts.
If you want to keep the dot syntax with a property, you can declare it in the protocol:
#protocol FruitProtocol
#property(readonly) NSDecimalNumber * count;
- (NSDecimalNumber *)count
#end
and then, your function would be:
-(NSDecimalNumber*)addCount:(id<FruitProtocol>)addObject{
return [count decimalNumberByAdding:addObject.count];
}
You're sending the message to count, what is count? id is a pointer to any type of object. If you expect the object to have a count property, then you should only be able to pass in an Array (or some other type restriction).
-(NSDecimalNumber*)addCount:(NSArray*) Object{
return [count decimalNumberByAdding: [Object count]];
}
As I understand it, id does not have any methods or variables associated with it because it is a generic pointer that does not refer to any specific class. This page has some good info on ids if you scroll down a bit.
anObject this will not have a count variable, which is why your first attempt won't work. Creating a base class and using that as a parameter to the method seems like the best idea to me.