2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

KVC(Key Value Coding) with Foundation in Swift

Last updated at Posted at 2020-03-22

KVCとは

  • Key Value Codingの略
  • オブジェクトの属性値にたいしてプロパティや変数から直接アクセスするのではなく、間接的に文字列(key)を通してアクセスする手法

SwiftでKVCを行うには

  • NSObjectを継承する

  • keyの指定は、#keyPath式が使える

  • サンプルコード

foo_kvc.swift
import Foundation

class Person: NSObject {
    @objc let name: String
    @objc let age: Int
    @objc var income: Int
    init(_ name: String, _ age: Int) {
        self.name = name
        self.age = age
        self.income = 0
    }
}

let p = Person("tanaka", 27)

// keyを通しての値の取得
print(p.value(forKey: #keyPath(Person.name)) as! String)


// letプロパティを変更するとクラッシュ
// p.setValue(30, forKey: #keyPath(Person.age)) クラッシュ

// varプロパティは変更出来る
p.setValue(350, forKey: #keyPath(Person.income))

NSKeyValuCodingプロトコル

以下のメソッドが用意されている。

  • keyを使った属性へのアクセス

    • value(forKey:)
    • setValue(_: forKey:)
  • keyPathを使った属性へのアクセス = 「.」を使って、オブジェクトの属性を横断することが出来る

    • value(forKeyPath:)
    • setValue(_: forKeyPath:)
  • それぞれ動作のカスタマイズが可能 (メソッドをオーバーライドする)

keyPathテクニック

  • 配列の要素に対しても行える
配列の要素に対してKVCによる値の取得.swift
class Child: NSObject {
	@objc var value: Int
	init(_ value: Int) { self.value = value }
}

class Parent: NSObject {
	@objc var children: [Child]
	init(_ children: [Child]) { self.children = children }
}

let p = Parent(Array(1..<5).map(Child.init))
let values = p.value(forKeyPath: #keyPath(Parent.children.value)) as! NSArray // (or [Int] | [NSNumber]
  • 配列演算子も用意されている
swift_kvc_collection_operator.swift
// KVCを使って平均値を求める
let avg = p.value(forKeyPath: "children.@avg.value") as! Float

NOTE:

  • mapメソッドやfor文を使用した方が断然速い (5倍ぐらい差がありました)

KVCを使ってコードのシンプル化例

シンプル化前.m
- (id)tableView:(NSTableView *)tableview objectValueForTableColumn:(id)column row:(NSInteger)row
{
    id result = nil;
    Person *person = [self.people objectAtIndex:row];
 
    if ([[column identifier] isEqualToString:@"name"]) {
        result = [person name];
    } else if ([[column identifier] isEqualToString:@"age"]) {
        result = @([person age]);  // Wrap age, a scalar, as an NSNumber
    } else if ([[column identifier] isEqualToString:@"favoriteColor"]) {
        result = [person favoriteColor];
    } // And so on...
 
    return result;
}
シンプル化.m
- (id)tableView:(NSTableView *)tableview objectValueForTableColumn:(id)column row:(NSInteger)row
{
    return [[self.people objectAtIndex:row] valueForKey:[column identifier]];
}

KVCが使われている箇所

  • Core Data
  • Key Value Observer (KVO)
  • Cocoa binding (iOSにはない)

参照

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?