Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to learn about KVC with swift 4.2

Tags:

swift

kvc

I'm using Xcode 10.0 with swift 4.2 to learn about Key Value Coding from "Cocoa programming for OSX"

I'm asked to create a simple class, which is a subclass of NSObject. The codes below:

import Cocoa

class Student: NSObject {
    var name: String = ""
    var gradeLevel: Int = 0
}

let student1 = Student()


student1.setValue("Benny", forKeyPath: "name")

student1.setValue("Benny", forKeyPath: "name")

Generates the following error message:

Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).

I've looked online and seem some issues regarding KVC such as : https://bugs.swift.org/browse/SR-5139

What am I doing wrong? The book was published in 2015.

like image 999
hoboBob Avatar asked Oct 03 '18 20:10

hoboBob


People also ask

What is KVC in swift example?

According to Apple: Key-value coding is a mechanism for accessing an object's properties indirectly, using strings to identify properties, rather than through invocation of an accessor method or accessing them directly through instance variables.

Can we use KVC in structure Swift?

Structures and enumerations don't support inheritance, which means the runtime doesn't have to figure out which implementation it needs to use. So to use KVC & KVO in swift, for the properties we want to observe in KVO we need to declare them with @objc dynamic keyword.

What is the use of KVC?

KVC is a mechanism that allows you to access properties without directly invoking accessor methods or instance variables. KVC uses a string, referred to as the key, to identify an attribute or property for a given object. Ruby developers may find KVC similar to the send method and other metaprogramming techniques.

What is KVC and KVO in Swift?

KVO and KVC or Key-Value Observing and Key-Value Coding are mechanisms originally built and provided by Objective-C that allows us to locate and interact with the underlying properties of a class that inherits NSObject at runtime.


1 Answers

In Swift 4 exposing code to the Objective-C runtime is no longer inferred for performance reasons.
To avoid the crash you have to add the @objc attribute explicitly.

@objc var name: String = ""

But from the strong type perspective of Swift there are two better ways to get values with KVC:

  1. The #keyPath directive which uses the ObjC runtime, too, but checks the key path at compile time

    let keyPath = #keyPath(Student.name)
    student1.setValue("Benny", forKeyPath: keyPath)
    

    In this case you get a very descriptive compiler warning

    Argument of '#keyPath' refers to property 'name' in 'Student' that depends on '@objc' inference deprecated in Swift 4

  2. The (recommended) native way: Swift 4+ provides its own KVC pattern where subclassing NSObject is not required.
    Key paths are indicated by a leading backslash followed by the type and the property (or properties):

    class Student {
        var name: String = ""
        var gradeLevel: Int = 0
    }
    
    let student1 = Student()
    student1[keyPath: \Student.name] = "Benny"
    
like image 199
vadian Avatar answered Sep 21 '22 10:09

vadian