キー値符号化KVC


多くのプログラミング技術は、オブジェクト向けプログラミング分野全体を含む間接メカニズムに基づいている.この章では、Obj-C言語の特性ではなく、Cocoaが提供する特性である別の間接機構について説明します.
C#ではオブジェクトのプロパティを反射して読み書きできることを知っています.文字列でオブジェクトを動的に制御できるため、この方法は特に便利です.実はObjCの言語の特性のため、あなたはまったくいかなる操作を行う必要がなくて属性の動的な読み書きを行うことができて、このような方式はKey Value Coding(略称KVC)です.
Core DataやCocoa Bindingsなどのより高度なCocoa特性(本書では説明しない)は、基礎メカニズムにKVCが含まれています.
KVCの動作方法はNSKeyValueCodingプロトコルによって提供され、NSObjectはこのプロトコルを実現した.すなわち、ObjCのほとんどのオブジェクトがKVC動作をサポートしている.

Object-c


よく使われるKVCの操作方法


ダイナミック設定

  • - (void)setValue:(nullable id)value forKey:(NSString *)key;(単純パス用)
  • - (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;(例えばPersonにAccountタイプの属性がある場合、person.accountは複合属性である)
  • .
  • - (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues ;(辞書入力用、ビッグデータ付与用)
  • ダイナミックリード

  • - (nullable id)valueForKey:(NSString *)key;(単純パス取値)
  • - (nullable id)valueForKeyPath:(NSString *)keyPath;(複合経路取値)
  • - (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;(複数のデータを一括して抽出可能)
  • .


    モデルデータ


    Address.h
    //
    // Address.h
    // KVC
    //
    // Created by yangjun on 15/10/10.
    // Copyright © 2015   . All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    /**  */
    @interface Address : NSObject
    
    @property (nonatomic, copy) NSString *addressName;///<  
    
    @end
    

    User.h
    //
    // User.h
    // KVC
    //
    // Created by yangjun on 15/10/10.
    // Copyright © 2015   . All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import "Address.h"
    
    /**  */
    @interface User : NSObject
    
    @property (nonatomic, copy) NSString *userName; ///<  
    @property (nonatomic, strong) Address *address; ///<  
    
    @end
    

    XCTestCaseテスト

    //
    // KVCTests.m
    // KVCTests
    //
    // Created by yangjun on 15/10/10.
    // Copyright © 2015   . All rights reserved.
    //
    
    #import <XCTest/XCTest.h>
    #import "User.h"
    
    @interface KVCTests : XCTestCase
    {
        User *_user;
    }
    
    @end
    
    @implementation KVCTests
    
    - (void)setUp {
        [super setUp];
        _user = [[User alloc] init];
    }
    
    - (void)testExample {
    
        //  
        [_user setValue:@"yangjun" forKey:@"userName"];
        NSString *value = [_user valueForKey:@"userName"];
        Address *address = [[Address alloc] init];
        address.addressName = @"BeiJing";
        [_user setValue:address forKey:@"address"];
        value = [_user valueForKey:@"userName"];
        NSLog(@" :%@; :%@", _user.userName, _user.address.addressName);
    
        //  
        [_user setValue:@" " forKeyPath:@"userName"];
        [_user setValue:@" " forKeyPath:@"address.addressName"];
        value = [_user valueForKeyPath:@"address.addressName"];
        NSLog(@" :%@; :%@", _user.userName, _user.address.addressName);
    
        //  
        address = [[Address alloc] init];
        address.addressName = @" ";
        NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@" ", @"userName", address, @"address", nil];
        [_user setValuesForKeysWithDictionary:dict];//  
        dict  = [_user dictionaryWithValuesForKeys:[NSArray arrayWithObjects:@"userName", @"address", nil]];//  
        NSLog(@" :%@; :%@", _user.userName, _user.address.addressName);
        NSLog(@"%@", dict);
    
    }
    
    @end
    

    しゅつりょく

    2015-10-10 13:51:17.453 KVC[8450:699448]  :yangjun; :BeiJing
    2015-10-10 13:51:59.677 KVC[8450:699448]  : ; : 
    2015-10-10 13:51:59.677 KVC[8450:699448]  : ; : 
    2015-10-10 13:51:59.677 KVC[8450:699448] {
        address = "<Address: 0x7faf33439680>";
        userName = "\U9633";
    }

    Swift


    常用KVC操作方法


    ダイナミック設定

  • setValue(value: AnyObject?, forKey key: String)(単純パス用)
  • setValue(value: AnyObject?, forKeyPath keyPath: String)(例えばPersonにAccountタイプの属性がある場合、person.accountは複合属性である)
  • .
  • setValuesForKeysWithDictionary(keyedValues: [String : AnyObject]) ;(辞書入力用、ビッグデータ付与用)
  • ダイナミックリード

  • valueForKey(key: String) -> AnyObject?(単純パス取値)
  • valueForKeyPath(keyPath: String) -> AnyObject?(複合経路取値)
  • dictionaryWithValuesForKeys(keys: [String]) -> [String : AnyObject](複数のデータを一括して抽出可能)
  • .


    モデルデータ


    User.swift
    import Foundation
    
    ///  
    class User: NSObject {
    
        ///  
        dynamic var userName:String?
    
        override init() {
            userName = ""
        }
    
    }
    

    XCTestCaseテスト

    //
    // KVCTests.swift
    // KVCTests
    //
    // Created by yangjun on 15/10/10.
    // Copyright © 2015   . All rights reserved.
    //
    
    import XCTest
    @testable import KVC
    
    /// KVC 
    class KVCTests: XCTestCase {
    
        ///  
        var user:User!;
    
        // MARK:  
        override func setUp() {
            super.setUp()
            self.user = User()
        }
    
        func testExample() {
            //  
            self.user.setValue("yangj", forKey:"userName") //  
            var value = self.user.valueForKey("userName") as? String //  
            print("\(value)")
    
            //  
            self.user.setValue(" ", forKeyPath: "userName")
            value = self.user.valueForKeyPath("userName") as? String
            print("\(value)")
    
            //  
            let dict = ["userName":" "]
            self.user.setValuesForKeysWithDictionary(dict)
            let dictOut = self.user.dictionaryWithValuesForKeys(["userName"])
            print("\(dictOut)")
        }
    
    }
    

    しゅつりょく

    Optional("yangj")
    Optional(" ")
    ["userName":  ]