Pages

Showing posts with label KVC. Show all posts
Showing posts with label KVC. Show all posts

Friday, 24 April 2015

User defined run time attributes

User defined run time attributes are one of the hidden(likely) gems of the XCode which helps you to customise/configure your UI object in the interface builder itself, without having to write code.

The "User defined run time attributes" uses the Obejctive-C's already existed concept called Key Value Coding. With the Xcode 6, this is a game changer, see here IBInspectable and IBDesignable

Key value coding is a mechanism which helps us to access the properties of an object indirectly by name (or key, which is a string) rather than directly using the accessor method.

That means, say for example you have the property text for the UILabel, you can use the user defined runtime attributes for changing its value.



Wait, who would do that? The UILabel control already have the IB properties for giving the text.
But, think of some other properties that the IB doesn't have. You can do that in the u.d.r.a (ah.,, user defined run time attributes, I am tired of typing this).

For example, here I have a custom class called CustomLabel which is a subclass of UILabel which have a property called fontName. When I give string here, my CustomLabel will use this string and updates it font. I can assign the value to this fontName in the Xib itself like this.





The fun part is you can give not only key but also the key paths. (For those who doesn't know the difference between the key and the keypath, text is a key for the UILabel whereas layer.cornerRadius is a keypath for its corner radius)

For example, if you want to change the corner radios of a UIView, you can add a u.d.r.a  with the keypath layer.cornerRadius.



Don't try to give the layer.borderColor in this way, because borderColor needs a CGColor object but you can only give UIColor with the u.d.r.a. If you want to achieve this, you can add a category for the CALayer with a UIColor property and you can write your own logic to change its borderColor.

Note:
  If you give a u.d.r.a to a UI object, that doesn't have a property with that name, you will get a warning from the debugger like this. In the previous Xcode, it will raise a invalid argument exception and crash.




Here is a list of attribute types that you can use in the u.d.r.a.




For the sake of clarity, I am adding the screenshot of my CustomLabel class here.



Monday, 9 February 2015

Key Value Coding and Key Value Observing


Key Value Coding:
Key value coding is a mechanism which helps us to access the properties of an object indirectly by name (or key, which is a string) rather than directly using the accessor method. The key value coding cannot be confused with the NSDictionary’s keys.

For e.g. the UITextField has a property called text which gives the current text displayed in it.
You normally access it by calling the following accessor method of the UITextField.
[myTextField setText:@"Hello"];
NSLog(@"%@", myTextField.text);
The above statements can be re-written by using the Key-Value coding as follows.
[myTextField setValue:@"Hello" forKey:@"text"];
NSLog(@"%@", [myTextField valueForKey:@"text"]);
The KCV can also be nested.
For e.g
[self.view setBackgroundColor:[UIColor blackColor]];
can be replaced with
[self setValue:[UIColor redColor] forKeyPath:@"view.backgroundColor"];
Key Value Observing:
Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects
For e.g. The UITextfield has delegate whenever it’s text changes, but it doesn’t have the delegates to inform about it’s colour changes. You can observe those with the “Key Value Observing”.
When you add an object as an observer for a textfield for it’s text property, whenever the text value of the textfield changes, the observer method of the object is called with the arguments.
    [myTextField addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    NSLog(@"%@ \t %@ \t %@", keyPath, object, change);
}
The KVC can be used for our custom objects by default. You don’t have to do anything separately to support the KVC i.e
[myObject setValue:@"Hello" forKey:@“foo”];
will work if the myObject have a property called foo.
But to support KVO for your custom objects you have to make use of the following methods inside object's class.
[self willChangeValueForKey: @"foo"];
[self didChangeValueForKey: @"foo"];

KVC and NSArray:
NSArray has some amusing functions with KVC's. You can see them in the following screenshot.



ScreenShot:



KVC in Xib:

     You can use the KVC directly in the Xib also. See the following screenshot. I have changed the corner radious of a view directly in the Xib itself. No coding needed. You can do the same for your own custom objects too.




Notes:
    If the object doesn't have the key you passed, the setValue:forKey: will raise an exception. 
    The keys are case sensitive.
    The KVC is little slower.

References: