iOS KVC

一、簡介

KVC 的全稱是 Key-Value Coding(鍵值編碼)蝙泼,是由 NSKeyValueCoding 非正式協(xié)議啟用的一種機(jī)制,對(duì)象采用這種機(jī)制來提供對(duì)其屬性的間接訪問脚猾,可以通過字符串來訪問一個(gè)對(duì)象的成員變量或其關(guān)聯(lián)的存取方法(getter or setter)贸伐。

通常,我們可以直接通過存取方法或變量名來訪問對(duì)象的屬性觅赊。我們也可以使用 KVC 間接訪問對(duì)象的屬性桶唐,并且 KVC 還可以訪問私有變量。某些情況下 KVC 還可以幫助簡化代碼茉兰。

二、使用

1.訪問對(duì)象屬性
(1)常用 API
- (nullable id)valueForKey:(NSString *)key;         // 通過 key 來取值
- (nullable id)valueForKeyPath:(NSString *)keyPath; // 通過 keyPath 來取值

- (void)setValue:(nullable id)value forKey:(NSString *)key;         // 通過 key 來賦值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath; // 通過 keyPath 來賦值
(2)基礎(chǔ)操作
#import <Foundation/Foundation.h>
#import "DJTestModelOne.h"
@interface DJTestModel : NSObject

@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *test;
@property (nonatomic,strong) DJTestModelOne *one;

@end
#import <Foundation/Foundation.h>

@interface DJTestModelOne : NSObject
@property (nonatomic,copy)NSString *oneName;
@end
#import "ViewController.h"
#import "DJTestModel.h"
#import "DJTestModelOne.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor orangeColor];
    
    DJTestModel *model = [[DJTestModel alloc]init];

    //直接賦值
    [model setName:@"dj"];
    
    //使用 KVC 賦值
    [model setValue:@"dj" forKey:@"name"];
    
    DJTestModelOne *oneModel = [[DJTestModelOne alloc]init];
    model.one = oneModel;
    
    //使用 KVC 的 keyPath 賦值
    [model setValue:@"djOne" forKeyPath:@"one.oneName"];
    
    //使用 KVC 取值
    NSString *name = [model valueForKey:@"name"];
    
    //使用 KVC 的 keyPath 取值
    NSString *oneName = [model valueForKeyPath:@"one.oneName"];
    
    
}

@end

KVC 還支持多級(jí)訪問欣簇,KeyPath 用法跟點(diǎn)語法相同规脸。

(3)多值操作

給定一組 Key,獲得一組 value熊咽,以字典的形式返回莫鸭。該方法為數(shù)組中的每個(gè) Key 調(diào)用 valueForKey: 方法。

[model setValuesForKeysWithDictionary:@{@"name":@"djValue",@"test":@"testValue"}];

將指定字典中的值設(shè)置到消息接收者的屬性中横殴,使用字典的 Key 標(biāo)識(shí)屬性被因。默認(rèn)實(shí)現(xiàn)是為每個(gè)鍵值對(duì)調(diào)用 setValue:forKey: 方法 ,會(huì)根據(jù)需要用 nil 替換 NSNull 對(duì)象衫仑。

NSDictionary *dict = [model dictionaryWithValuesForKeys:@[@"name",@"test"]];
2.訪問集合屬性

我們可以像訪問其它對(duì)象一樣使用 valueForKey:setValue:forKey: 方法來獲取或設(shè)置集合對(duì)象(主要指 NSArrayNSSet)梨与。但是,當(dāng)我們要操作集合對(duì)象的內(nèi)容文狱,比如添加或者刪除元素時(shí)粥鞋,通過 KVC 的可變代理方法獲取集合代理對(duì)象是最有效的。
【擴(kuò)展:根據(jù) KVO 的實(shí)現(xiàn)原理瞄崇,是在運(yùn)行時(shí)動(dòng)態(tài)生成子類并重寫 setter 方法來達(dá)到可以通知所有觀察者對(duì)象的目的呻粹,因此我們對(duì)集合對(duì)象進(jìn)行操作是不會(huì)觸發(fā) KVO 的。當(dāng)我們要使用 KVO 監(jiān)聽集合對(duì)象變化時(shí)苏研,需要通過 KVC 的可變代理方法獲取集合代理對(duì)象等浊,然后對(duì)代理對(duì)象進(jìn)行操作。當(dāng)代理對(duì)象的內(nèi)部對(duì)象發(fā)生改變時(shí)摹蘑,會(huì)觸發(fā) KVO 的監(jiān)聽方法筹燕。】

KVC 提供了三種不同的代理對(duì)象訪問的代理方法衅鹿,每種都有 Key 和 KeyPath 兩種方法庄萎。

  • mutableArrayValueForKey:mutableArrayValueForKeyPath: 返回 NSMutableArray 對(duì)象的代理對(duì)象。
  • mutableSetValueForKey:mutableSetValueForKeyPath: 返回 NSMutableSet 對(duì)象的代理對(duì)象塘安。
  • mutableOrderedSetValueForKey:mutableOrderedSetValueForKeyPath: 返回 NSMutableOrderedSet 對(duì)象的代理對(duì)象糠涛。
3.使用集合運(yùn)算符

KVC 的 valueForKeyPath: 方法除了可以取出屬性值以外,還可以在 KeyPath 中嵌套集合運(yùn)算符兼犯,來對(duì)集合對(duì)象進(jìn)行操作忍捡。

以下是KeyPath集合運(yùn)算符的格式集漾,主要分為 3 個(gè)部分:

  • Left key path:左鍵路徑,要操作的集合對(duì)象砸脊,如果消息接收者就是集合對(duì)象具篇,則可以省略 Left 部分;
  • Collection operator:集合運(yùn)算符凌埂;
  • Right key path:右鍵路徑驱显,要進(jìn)行運(yùn)算的集合中的屬性。

集合運(yùn)算符主要分為三類:

  • 聚合運(yùn)算符:以某種方式合并集合中的對(duì)象瞳抓,并返回右鍵路徑中指定的屬性的數(shù)據(jù)類型匹配的一個(gè)對(duì)象埃疫,一般返回 NSNumber 實(shí)例。
  • 數(shù)組運(yùn)算符:根據(jù)運(yùn)算符的條件孩哑,將符合條件的對(duì)象以一個(gè) NSArray 實(shí)例返回栓霜。
  • 嵌套運(yùn)算符:處理集合對(duì)象中嵌套其他集合對(duì)象的情況,并根據(jù)運(yùn)算符返回一個(gè) NSArrayNSSet 實(shí)例横蜒。

示例:

#import <Foundation/Foundation.h>
#import "DJTestModelOne.h"
@interface DJTestModel : NSObject
@property (nonatomic,strong) NSArray <DJTestModelOne *> *oneArray;
@end
#import <Foundation/Foundation.h>

@interface DJTestModelOne : NSObject
@property (nonatomic,assign)NSInteger num;
@property (nonatomic,copy)NSString * type;
@end
(1)使用聚合運(yùn)算符
#import "ViewController.h"
#import "DJTestModel.h"
#import "DJTestModelOne.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor orangeColor];
    
    DJTestModel *model = [[DJTestModel alloc]init];

    DJTestModelOne *one1 = [[DJTestModelOne alloc]init];
    one1.num = 1;
    
    DJTestModelOne *one2 = [[DJTestModelOne alloc]init];
    one2.num = 2;
    
    DJTestModelOne *one3 = [[DJTestModelOne alloc]init];
    one3.num = 3;
    
    DJTestModelOne *one4 = [[DJTestModelOne alloc]init];
    one4.num = 4;
    
    model.oneArray = @[one1,one2,one3,one4];
    
    NSNumber *avg = [model.oneArray valueForKeyPath:@"@avg.num"];
    
    NSNumber *conunt = [model.oneArray valueForKeyPath:@"@count"];
    
    NSNumber *sum = [model.oneArray valueForKeyPath:@"@sum.num"];
    
    NSNumber *max = [model.oneArray valueForKeyPath:@"@max.num"];
    NSNumber *min = [model.oneArray valueForKeyPath:@"@min.num"];
    
}

@end
(2)使用數(shù)組運(yùn)算符
#import "ViewController.h"
#import "DJTestModel.h"
#import "DJTestModelOne.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor orangeColor];
    
    DJTestModel *model = [[DJTestModel alloc]init];

    DJTestModelOne *one1 = [[DJTestModelOne alloc]init];
    one1.type = @"one1";
    
    DJTestModelOne *one2 = [[DJTestModelOne alloc]init];
    one2.type = @"one2";
    
    DJTestModelOne *one3 = [[DJTestModelOne alloc]init];
    one3.type = @"one2";
    
    DJTestModelOne *one4 = [[DJTestModelOne alloc]init];
    one4.type = @"one4";
    
    model.oneArray = @[one1,one2,one3,one4];
    
    //獲取集合中的所有 type 對(duì)象
    NSArray *types = [model.oneArray valueForKeyPath:@"@unionOfObjects.type"];
    
    // 獲取集合中的所有不同的 type 對(duì)象
    NSArray *disTypes = [model.oneArray valueForKeyPath:@"@distinctUnionOfObjects.type"];
    
}

在使用數(shù)組運(yùn)算符時(shí)胳蛮,如果有任何操作的對(duì)象為 nil,則 valueForKeyPath: 方法將引發(fā)異常丛晌。

(3)使用嵌套運(yùn)算符

處理集合對(duì)象中嵌套其他集合對(duì)象的情況仅炊,并根據(jù)運(yùn)算符返回一個(gè)NSArray或NSSet實(shí)例。

NSArray *arrayOfArrays = @[model.oneArray,model.oneArray];
    
    NSArray *arrayTypes = [arrayOfArrays valueForKeyPath:@"@unionOfArrays.type"];
    
    NSArray *distinctTypes = [arrayOfArrays valueForKeyPath:@"@distinctUnionOfArrays.type"];
  • 在使用嵌套運(yùn)算符時(shí)澎蛛,valueForKeyPath: 內(nèi)部會(huì)根據(jù)運(yùn)算符創(chuàng)建一個(gè) NSMutableArrayNSMutableSet 對(duì)象茂洒,將集合中的 array 和 set 添加進(jìn)去再進(jìn)行操作。如果集合中有非集合元素瓶竭,會(huì)導(dǎo)致 Crash督勺。
  • 使用 unionOfArraysdistinctUnionOfArrays 運(yùn)算符,消息接收者應(yīng)該是 arrayOfArrays 類型斤贰,即 NSArray< NSArray* >* arrayOfArrays; 使用 distinctUnionOfSets 運(yùn)算符智哀,消息接收者應(yīng)該是 setOfSets 或者 arrayOfSets 類型。否則會(huì)發(fā)生異常荧恍。
  • 在使用嵌套運(yùn)算符時(shí)瓷叫,如果有任何操作的對(duì)象為 nil, 則 valueForKeyPath: 方法將引發(fā)異常送巡。
(4)拓展

如果集合中的對(duì)象都是 NSNumber摹菠,右鍵路徑可以用 self

    NSArray *array = @[@1, @2, @3, @4, @5];
    NSNumber *sum = [array valueForKeyPath:@"@sum.self"];
    NSLog(@"%d",[sum intValue]); 
4.非對(duì)象值處理

KVC 支持基礎(chǔ)數(shù)據(jù)類型和結(jié)構(gòu)體骗爆,在使用 KVC 進(jìn)行賦值或取值的時(shí)候次氨,會(huì)自動(dòng)在非對(duì)象值和對(duì)象值之間進(jìn)行轉(zhuǎn)換。

  • 當(dāng)進(jìn)行取值如 valueForKey: 時(shí)摘投,如果返回值非對(duì)象煮寡,會(huì)使用該值初始化一個(gè) NSNumber(用于基礎(chǔ)數(shù)據(jù)類型)或 NSValue(用于結(jié)構(gòu)體)實(shí)例虹蓄,然后返回該實(shí)例。
  • 當(dāng)進(jìn)行賦值如 setValue:forKey: 時(shí)幸撕,如果 key 的數(shù)據(jù)類型非對(duì)象薇组,則會(huì)發(fā)送一條 <type>Value 消息給 value 對(duì)象以提取基礎(chǔ)數(shù)據(jù),然后賦值給 key坐儿。

注意:因?yàn)镾wift 中的所有屬性都是對(duì)象律胀,所以這里僅適用于 Objective-C 屬性。
當(dāng)進(jìn)行賦值如 setValue:forKey: 時(shí)貌矿,如果 key 的數(shù)據(jù)類型是非對(duì)象類型炭菌,則 value 就禁止傳 nil。否則會(huì)調(diào)用 setNilValueForKey: 方法站叼,該方法的默認(rèn)實(shí)現(xiàn)拋出異常 NSInvalidArgumentException,并導(dǎo)致程序 Crash菇民。

5.屬性驗(yàn)證

KVC 提供了屬性驗(yàn)證的方法尽楔,如下。我們可以在使用 KVC 賦值前驗(yàn)證能否為這個(gè) key 賦值指定 value第练。
validateValue 方法的默認(rèn)實(shí)現(xiàn)是查看消息接收者類中是否實(shí)現(xiàn)了遵循命名規(guī)則為 validate<Key>:error: 的方法阔馋,如果有的話就返回調(diào)用該方法的結(jié)果;如果沒有的話娇掏,則默認(rèn)驗(yàn)證成功并返回 YES呕寝。我們可以在消息接收者類中實(shí)現(xiàn) validate<Key>:error: 的方法來自定義邏輯返回 YES 或 NO。

#import <Foundation/Foundation.h>
#import "DJTestModelOne.h"
@interface DJTestModel : NSObject
@property (nonatomic,strong) NSArray <DJTestModelOne *> *oneArray;
@property (nonatomic,copy)NSString *name;
@end


#import "DJTestModel.h"

@implementation DJTestModel

-(BOOL)validateValue:(inout id  _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError *__autoreleasing  _Nullable *)outError{
    NSString *name = *ioValue;
        BOOL result = NO;
        if ([name isEqualToString:@"dj"]) {
            result = YES;
        }
        return result;
}

@end
DJTestModel *model = [[DJTestModel alloc]init];

    NSString *value = @"dj";
    NSString *key = @"name";
    NSError  *error;
    BOOL result = [model validateValue:&value forKey:key error:&error];
       
   if (error) {
       NSLog(@"error = %@", error);
   }

三婴梧、原理

1.搜索規(guī)則

除了了解 KVC 的使用下梢,了解 KVC 取值和賦值過程的工作原理也是很有必要的。

(1)基本的 Getter 搜索模式

以下是 valueForKey: 方法的默認(rèn)實(shí)現(xiàn)塞蹭,給定一個(gè) key 作為輸入?yún)?shù)孽江,在消息接收者類中操作,執(zhí)行以下過程番电。

  • 第一步:按照 get<Key>岗屏、<key>is<Key>漱办、_<key> 順序查找方法这刷。如果找到就調(diào)用取值并執(zhí)行第五步,否則執(zhí)行第二步娩井;
  • 第二步:查找 countOf<Key>暇屋、objectIn<Key>AtIndex:<key>AtIndexes: 命名的方法洞辣。如果找到第一個(gè)和后面兩個(gè)中的至少一個(gè)率碾,則創(chuàng)建一個(gè)能夠響應(yīng)所有 NSArray 的方法的集合代理對(duì)象(類型為 NSKeyValueArray叔营,繼承自 NSArray),并返回該對(duì)象所宰。否則執(zhí)行第三步绒尊;
    代理對(duì)象隨后將其接收到的任何 NSArray 消息轉(zhuǎn)換為 countOf<Key>objectIn<Key>AtIndex:仔粥、<Key>AtIndexes: 消息的組合婴谱,并將其發(fā)送給 KVC 調(diào)用方。如果原始對(duì)象還實(shí)現(xiàn)了一個(gè)名為 get<Key>:range: 的可選方法躯泰,則代理對(duì)象也會(huì)在適當(dāng)時(shí)使用該方法谭羔。
    當(dāng) KVC 調(diào)用方與代理對(duì)象一起工作時(shí),允許底層屬性的行為如同 NSArray 一樣麦向,即使它不是 NSArray瘟裸。
  • 第三步:查找 countOf<Key>enumeratorOf<Key>诵竭、memberOf<Key>: 命名的方法话告。如果三個(gè)方法都找到,則創(chuàng)建一個(gè)能夠響應(yīng)所有 NSSet 的方法的集合代理對(duì)象(類型為 NSKeyValueSet卵慰,繼承自 NSSet)沙郭,并返回該對(duì)象。否則執(zhí)行第四步裳朋;
    代理對(duì)象隨后將其接收到的任何 NSSet 消息轉(zhuǎn)換為 countOf<Key>病线、enumeratorOf<Key>memberOf<Key>: 消息的組合鲤嫡,并將其發(fā)送給 KVC 調(diào)用方送挑。
    當(dāng) KVC 調(diào)用方與代理對(duì)象一起工作時(shí),允許底層屬性的行為如同 NSSet 一樣暖眼,即使它不是 NSSet让虐。
  • 第四步:查看消息接收者類的 +accessInstanceVariablesDirectly 方法的返回值(默認(rèn)返回 YES)。如果返回 YES罢荡,就按照 _<key>赡突、_is<Key><key>区赵、is<Key> 順序查找成員變量惭缰。如果找到就直接取值并執(zhí)行第五步,否則執(zhí)行第六步笼才。如果 +accessInstanceVariablesDirectly 方法返回 NO 也執(zhí)行第六步漱受。
  • 第五步:如果取到的值是一個(gè)對(duì)象指針,即獲取的是對(duì)象,則直接將對(duì)象返回昂羡。如果取到的值是一個(gè)NSNumber 支持的數(shù)據(jù)類型絮记,則將其存儲(chǔ)在 NSNumber 實(shí)例并返回。如果取到的值不是一個(gè) NSNumber 支持的數(shù)據(jù)類型虐先,則轉(zhuǎn)換為 NSValue 對(duì)象, 然后返回怨愤。
  • 第六步:調(diào)用 valueForUndefinedKey: 方法,該方法拋出異常 NSUnknownKeyException蛹批,并導(dǎo)致程序 Crash撰洗。這是默認(rèn)實(shí)現(xiàn),我們可以重寫該方法根據(jù)特定 key 做一些特殊處理腐芍。
(2)基本的 Setter 搜索模式

以下是 setValue:forKey: 方法的默認(rèn)實(shí)現(xiàn)差导,給定 key 和 value 作為輸入?yún)?shù),嘗試將 KVC 調(diào)用方的屬性名為 ke y的值設(shè)置為 value猪勇,執(zhí)行以下過程设褐。

  • 第一步:按照 set<Key>:_set<Key>: 順序查找方法泣刹。如果找到就調(diào)用并將 value 傳進(jìn)去(根據(jù)需要進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換)助析,否則執(zhí)行第二步。
  • 第二步:查看消息接收者類的 +accessInstanceVariablesDirectly 方法的返回值(默認(rèn)返回 YES)项玛。如果返回 YES貌笨,就按照 _<key>弱判、_is<Key>襟沮、<key>is<Key> 順序查找成員變量(同基本的 Getter 搜索模式)昌腰。如果找到就將 value 賦值給它(根據(jù)需要進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換)开伏,否則執(zhí)行第三步。如果 +accessInstanceVariablesDirectly 方法返回 NO 也執(zhí)行第三步遭商。
  • 第三步:調(diào)用 setValue:forUndefinedKey: 方法固灵,該方法拋出異常 NSUnknownKeyException,并導(dǎo)致程序 Crash劫流。這是默認(rèn)實(shí)現(xiàn)巫玻,我們可以重寫該方法根據(jù)特定 key 做一些特殊處理。
2.異常處理

根據(jù) KVC 搜索規(guī)則祠汇,當(dāng)沒有搜索到對(duì)應(yīng)的 key 或者 keyPath 相關(guān)方法或者變量時(shí)仍秤,會(huì)調(diào)用對(duì)應(yīng)的異常方法 valueForUndefinedKey:setValue:forUndefinedKey:,這兩個(gè)方法的默認(rèn)實(shí)現(xiàn)是拋出異常 NSUnknownKeyException可很,并導(dǎo)致程序 Crash诗力。我們可以重寫這兩個(gè)方法來處理異常。

- (nullable id)valueForUndefinedKey:(NSString *)key;
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;

當(dāng)進(jìn)行賦值如 setValue:forKey: 時(shí)我抠,如果 key 的數(shù)據(jù)類型是非對(duì)象類型苇本,則 value 就禁止傳 nil袜茧。否則會(huì)調(diào)用 setNilValueForKey: 方法,該方法的默認(rèn)實(shí)現(xiàn)是拋出異常 NSInvalidArgumentException瓣窄,并導(dǎo)致程序 Crash笛厦。我們可以重寫這個(gè)方法來處理異常。

- (void)setNilValueForKey:(NSString *)key
{
    if ([key isEqualToString:@"hidden"]) {
        [self setValue:@(NO) forKey:@”hidden”];
    } else {
        [super setNilValueForKey:key];
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末康栈,一起剝皮案震驚了整個(gè)濱河市递递,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啥么,老刑警劉巖登舞,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異悬荣,居然都是意外死亡菠秒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門氯迂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來践叠,“玉大人,你說我怎么就攤上這事嚼蚀〗疲” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵轿曙,是天一觀的道長弄捕。 經(jīng)常有香客問我,道長导帝,這世上最難降的妖魔是什么守谓? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮您单,結(jié)果婚禮上斋荞,老公的妹妹穿的比我還像新娘。我一直安慰自己虐秦,他們只是感情好平酿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悦陋,像睡著了一般蜈彼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叨恨,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天柳刮,我揣著相機(jī)與錄音,去河邊找鬼。 笑死秉颗,一個(gè)胖子當(dāng)著我的面吹牛痢毒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蚕甥,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼哪替,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了菇怀?” 一聲冷哼從身側(cè)響起凭舶,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎爱沟,沒想到半個(gè)月后帅霜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呼伸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年身冀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片括享。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡搂根,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出铃辖,到底是詐尸還是另有隱情剩愧,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布娇斩,位于F島的核電站仁卷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏成洗。R本人自食惡果不足惜五督,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一藏否、第九天 我趴在偏房一處隱蔽的房頂上張望瓶殃。 院中可真熱鬧,春花似錦副签、人聲如沸遥椿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冠场。三九已至,卻和暖如春本砰,著一層夾襖步出監(jiān)牢的瞬間碴裙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舔株,地道東北人莺琳。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像载慈,于是被迫代替她去往敵國和親惭等。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • KVC 簡介 KVC全稱是Key Value Coding(鍵值編碼)办铡,是一個(gè)基于NSKeyValueCoding...
    rightmost閱讀 821評(píng)論 0 0
  • KVC KVC定義 KVC(Key-value coding)鍵值編碼辞做,就是指iOS的開發(fā)中,可以允許開發(fā)者通過K...
    jackyshan閱讀 51,897評(píng)論 9 200
  • 前言: 本文基本不講KVC/KVO的用法寡具,只結(jié)合網(wǎng)上的資料說說對(duì)這種技術(shù)的理解秤茅。 由于KVO內(nèi)容較少,而且是以KV...
    土b蘭博王閱讀 3,063評(píng)論 0 33
  • 一童叠、基本介紹 KVC官網(wǎng)地址 KVC全稱為key value coding嫂伞,簡稱鍵值編碼,它是一種機(jī)制拯钻,使用NSK...
    默默_David閱讀 284評(píng)論 0 2
  • KVC定義 KVC(Key-value coding)鍵值編碼帖努,就是指iOS的開發(fā)中,可以允許開發(fā)者通過Key名直...
    SheIsMySin_72e7閱讀 380評(píng)論 0 0