Key Value Coding clarification - ios

From Apple's documentation I came across the following:
Setting values using key paths is not the same as setting them using
Objective-C properties. You cannot use property notation to set
transform values. You must use the setValue:forKeyPath: method with
the preceding key path strings.
From my understanding, we must have properties of our ivars in order to use KVC.
But from the paragraph above, it seems to say otherwise:
Setting values using key paths is not the same as setting them using
Objective-C properties. You cannot use property notation to set
transform values.
Can someone explain to me why? Perhaps I am missing something, because all along my understanding is that we must have properties to utilize KVC.

From my understanding, we must have properties of our ivars in order to use KVC.
This is incorrect. KVC will use the property generated accessor methods, or other (appropriately named) accessor methods if they exist, but they aren't required. If they don't exist KVC will attempt to directly access the instance variables.
Check this Apple ref for a description of how KVC searches for the key to update.

Related

What is get used for in Swift?

Code: https://github.com/acani/Chats/blob/master/Chats/Chats/ChatViewController.swift
The inputAccessoryView method uses get { }. Any reason why?
If I put a "println" on the line before get, it says use of unresolved identifier 'get'. I'm trying to see if the code before get is being called because the println I have inside is not being called.
What exactly is get used for here?
See Properties in the reference. Scroll down to "Computed Properties".
In addition to stored properties, classes, structures, and enumerations can define computed properties, which do not actually store a value. Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly.
So that syntax lets the value returned by a property to be caluclated on the value rather than just fetching a value. Code other than a get or set block in a property definition is not valid, which is why you get that error.

How to add a transient NSIndexPath property to NSManagedObject

I mean to add a property of type NSIndexPath to my NSManagedObject but it doesn't seem to be one of the recognized property list types. I also mean to make it transient since index paths change depending on the UI, hence I have no reason to save it in the managed document.
I'm thinking of creating two separate NSNumber properties called section and row instead but it'll be much easier if I had an NSIndexPath instead. Help?
Just make it a transformable attribute with no value transformer name. The default transformer-- NSKeyedUnarchiveFromDataTransformerName-- takes any class that conforms to the NSCoding protocol and saves it as NSData.
Works for me with NSIndexPath, NSArray, and NSDictionary. The accessors just work... I believe by setting and getting an id type, so it's not as typesafe as an NSIndexSet* property would be, but it's good enough.
[edit...]
Err, actually. I use Mogenerator, which may take care of the issue mentioned in the docs:
In principle, you don’t have to do anything else. In practice, to suppress compiler warnings you should declare a property for the attribute...
... it's Mogenerator that makes a property of type id. The Apple example creates a property of the specific type in the entity class.

Weak/Strong Annotations for Non-Synthesized Properties in Objective-C

Since Objective-C 2.0 we have properties, a nice syntax for getting and setting values for instance variables. Since Clang 3.1 all properties which are not dynamic, not readonly with an explicit getter or don't have a custom getter and setter are automatically synthesized to ivars. And since ARC we have weak/strong annotations for properties which are used by ARC to define the memory management logic of automatically synthesized properties.
The properties still can be synthesized manually e.g. for a readonly property backed by an ivar and returning a default value, for instance.
Sometimes, properties are also useful if they are not synthesized at all. I have found a few use cases when I use this sort of behavior:
A custom getter and setter which use a custom ivar for storing the actual value and which perform some additional actions.
A dynamic property, e.g. in subclasses of NSManagedObject.
A readonly property which simply passes through a property of an object stored in another property (e.g. a private one).
The Question: Does it makes sense to annotate these non-synthesized properties with weak/strong according to their actual usage or not? What is the best practice?
(https://twitter.com/kubanekl/status/427142577310408704)
I would say the answer is yes, even if only for documentation sake.
Even if you do not use any of the compiler and framework related default implementations, and implement everything by yourself, someone attempting to use these properties will be in much better position of understanding the API if he is able to get a hint on how the memory management would behave. A person does not really have to know how a setter or a getter is implemented internally, but he would might have to know, for example, if after calling a setter, the value was copied or retained or just assigned, and implement his side of things accordingly.
Yes, it does.
The property definition is a contract specification. Just because the compiler isn't fulfilling the contract doesn't mean you shouldn't respect it when manually implementing the accessor methods.

Objective C - Add property in runtime

I'd like to add an ivar to an existing objective-c class in runtime, but documentation states that an ivar cannot be an existing class, so I think property could still solve my issue.
As stated here class_addProperty(...) returns true, but when I try to access the ivar by it's name (or the property name) it always returns nil. What could be the issue causing this to happen?
You won't be able to add an ivar to the class at runtime. You can think of the class, and its ivars, as something like a C struct. It's layout is defined at compile time.
You can add properties at runtime (since these are just methods), and you can implement their getters and setters, but you'll need to come up with a different way to store any data that they represent.
Are you looking for something similar with some other programming language?
it looks like adding properties in AS3, but objc think the best would you use to store NSDictionary objects by keys.

Where's the difference between setObject:forKey: and setValue:forKey: in NSMutableDictionary?

When looking at the documentation, I hardly see any big difference. Both "value" and "object" are of type id, so can be any object. Key is once a string, and in the other case an id. One of them seems to retain the object, and the other don't. What else? Which one is for what case?
setValue:forKey: is part of the NSKeyValueCoding protocol, which among other things, lets you access object properties from the likes of Interface Builder. setValue:forKey: is implemented in classes other than NSDictionary.
setObject:forKey: is NSMutableDictionary's reason to exist. Its signature happens to be quite similar to setValue:forKey:, but is more generic (e.g. any key type). It's somewhat of a coincidence that the signatures are so similar.
What adds to the confusion is that NSMutableDictionary's implementation of setValue:forKey: is equivalent to setObject:forKey: in most cases. In other classes, setValue:forKey: changes member variables. In NSMutableDictionary, it changes dictionary entries, unless you prefix the key with a '#' character -- in which case it modifies member variables.
So, in a nutshell, use setObject:forKey: when you need to work with dictionary keys and values, and setValue:forKey: in the rarer cases where you need to tackle KVP.
EDIT: and oh, it looks like this has been asked and answered before: Difference between objectForKey and valueForKey?
Another difference is that if you give a nil value to setValue:forKey:, it removes the key from the dictionary if it exists, otherwise does nothing. But if you give a nil value to setObject:forKey:, it raises an exception.
-setValue:forKey: just send -setObject:forKey: to the receiver, unless the value is nil, in which case send -removeObjectForKey.
Dead simple.
anObject — The value for key. The object receives a retain message before being added to the NSDictionary. This value must not be nil.
aKey — The key for value. The key is copied (using copyWithZone:; keys must conform to the NSCopying protocol). The key must not be nil.
value — The value for key.
key — The key for value. Note that when using key-value coding, the key must be a string (see “Key-Value Coding Fundamentals”).

Resources