iOS interview questions 2018

KVC & KVO , iOS interview questions, cracking iOS interview 2018, iOS 2018 interview questions
I'm going to explain the concepts behind bindings from the ground up; first explaining Key-Value Coding (KVC), then Key-Value Observing (KVO). Keys and key paths are frequently used for key-value…

iOS 2018 series — Cracking iOS interview or Become iOS expert (2)

Chapter 2: KVC & KVO

I’m going to explain the concepts behind bindings from the ground up; first explaining Key-Value Coding (KVC), then Key-Value Observing (KVO).

Keys and key paths are frequently used for key-value coding (KVC), a mechanism for indirectly accessing an object’s attributes and relationships using string identifiers. Keys and key paths are also used for key-value observing (KVO), a mechanism that enables an object to be notified directly when a property of another object changes.

Key-Value-Coding (KVC) means accessing a property or value using a string.

id someValue = [myObject valueForKeyPath:@"foo.bar.baz"];

Which could be the same as:

id someValue = [[[myObject foo] bar] baz];

Key-Value-Observing (KVO) allows you to observe changes to a property or value.

To observe a property using KVO you would identify to property with a string; i.e., using KVC. Therefore, the observable object must be KVC compliant.

[myObject addObserver:self forKeyPath:@"foo.bar.baz" options:0 context:NULL];

Lets dive into some details:

Key-Value Coding (KVC)

Actually, any property you want to observe for changes must be Key-Value Coding compliant, An object is key-value coding compliant when it adopts the NSKeyValueCoding protocol. An object that inherits from NSObject, which provides a default implementation of the protocol’s essential methods, automatically adopts this protocol with certain default behaviors. Lets start with an example to understand it.

@interface BankAccount : NSObject

@property (nonatomic) NSNumber* currentBalance; // An attribute

@property (nonatomic) Person* owner; // A to-one relation

@property (nonatomic) NSArray< Transaction* >* transactions; // A to-many relation

@end

In order to maintain encapsulation, an object typically provides accessor methods for the properties on its interface. The object’s author may write these methods explicitly or may rely on the compiler to synthesize them automatically. Either way, the author of code using one of these accessors must write the property name into the code before compiling it. The name of the accessor method becomes a static part of the code that is using it. For example, given the bank account object declared above, the compiler synthesizes a setter that you can invoke for the myAccount instance:

[myAccount setCurrentBalance:@(100.0)]; //NORMAL

[myAccount setValue:@(100.0) forKey:@”currentBalance”]; //KVC

This is direct, but lacks flexibility. A key-value coding compliant object, on the other hand, offers a more general mechanism to access an object’s properties using string identifiers.

Keys

A key is a string that identifies a specific property.

BankAccount class is key-value coding compliant, it recognizes the keys owner, currentBalance, and transactions, which are the names of its properties. Instead of calling the setCurrentBalance: method, you can set the value by its key:

[myAccount setValue:@(100.0) forKey:@”currentBalance”];

In fact, you can set all the properties of the myAccount object with the same method, using different key parameters.

Key Paths

A key path is a string of dot-separated keys used to specify a sequence of object properties to traverse. For example, the key path owner.address.street applied to a bank account instance refers to the value of the street string that is stored in the address of the bank account’s owner, assuming the Person and Address classes are also key-value coding compliant.

In Swift, you can use a key-path expression to create key paths for accessing properties.

let balanceAccessor = \BankAccount.currentBalance

myAccount.value(forKeyPath:balanceAccessor) //Type 1

myAccount.value(forKeyPath: #keyPath(BankAccount.currentBalance)//Type 2

Note: In Swift, instead of using a string to indicate a key or key path, you can use a #keyPath expression. This offers the advantage of a compile time check, as described in the Keys and Key Paths

Key-Value Observing (KVO)

Key-Value Observing (KVO) is built on top of KVC. It allows you to observe (i.e. watch) a KVC key path on an object to see when the value changes. For example, let’s write some code that watches to see if a person’s address changes. There are three methods of interest in the following code:

  • watchPersonForChangeOfAddress: begins the observing
    //this begins the observing
    [p addObserver:self forKeyPath:@”address” options:0 context:KVO_CONTEXT_ADDRESS_CHANGED];
  • observeValueForKeyPath:ofObject:change:context: is called every time there is a change in the value of the observed key path
    //whenever an observed key path changes, this method will be called — (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; {
    }
  • dealloc stops the observing
    //must stop observing everything before this object is //deallocated, otherwise it will cause crashes
    [p removeObserver:self forKeyPath:@”address”]

To be observable, it has to inherit from NSObject and it has to have dynamic properties. Being dynamic means that a property can be dynamically dispatched at runtime.

I have attached KVO demo video for reference, let’s say I have a WKWebView object and that I want to observe one of its properties, estimatedProgress.

Bonus time: What’s new in Swift 4

1. String will be treated as collection- SE-0163

let message = "Message!"
message.count // no need of message.characters.count
for character in message {  // no need of message.characters
print(character)
}

2. MutableCollection.swapAt-SE-0173

New swap function now takes indices of elements which are to be swapped.

var names = [“Vipul”,”Vinay”,”Vishal”,”Akshay”]
names.swapAt(2,3)

3. Dictionary and Set enhancements — SE-0165
a. Now you can create a dictionary using array elements.

b. Provide default value if value for key does not exist. In following statement if there is no value for key 10 found then it will print default value.

print(friendsDictionary[10, default: “No Friends Exist yet!”])

c. Partition array in different buckets

let mates = [“Akshay”, “Anil”, “Vishal”, “Vinay”, “Ankit”]
let buckets = Dictionary(grouping: mates, by: { $0.first! })

4. Swift Archival & Serialization — SE-0166

Good News! Swift 4 comes with built in encoders and decoders for JSON. JSON <-> Model conversion is comes built in ( Although you can customize that behavior if required ).

5. Smart KeyPaths: Key-Value Coding — SE-0161

This is one of my favorite feature in Swift 4. You can grab root object name and drill down upto any property name to get its value.

References:-