KVC和KVO
今天在這里給大家詳解一下KVC和KVO的用法, 在這里首先給大家介紹一下KVC的用法,雖然他倆看似只差一個字母但,但其實兩種放法的機制相差很大,千萬不要被表象所蒙騙哦, 下面分別介紹了兩種機制的使用方式, 理解之后你就明白, 他倆一毛錢關(guān)系也沒有哦 ^- -^
KVC
KVC(鍵值編碼,是KeyValue Coding
的簡稱),它是一種可以直接通過字符串的名字(key)來訪問類屬性的機制.使用該機制不需要調(diào)取實例變量就可以訪問對象屬性,并對屬性進行賦值.在iOS開發(fā)中, KVC經(jīng)常會被使用,在給Model類進行賦值時,你會經(jīng)常用到KVC, 如果你還不知道Model,請自行補習(xí).下面的實例清單會涉及Model類.
實例清單1.1 KVC的最基礎(chǔ)用法(setValue:forKey:):
//Person類.h文件內(nèi)容
#import <Foundation/Foundation.h>
@class Student;
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@end
//VC中.m內(nèi)容
Person *per = [[Person alloc] init];
[per setValue:@"火星人" forKey:@"name"];
NSLog(@"%@", per.name);
實例清單1.2 KVC的第二種用法(setValuesForKeysWithDictionary:):
#import <Foundation/Foundation.h>
@interface Person : NSObject
// 自定義Model(Person)類.h文件內(nèi)容/此.m文件無內(nèi)容(在真正的開發(fā)中.m中是有內(nèi)容, 在這里為了減少我的工作量,我lazy一下)
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *phoneNumber;
@property (nonatomic, strong) NSString *address;
@end
// VC中的.m文件中內(nèi)容
// 定義一個字典, 在這里請注意,字典中Key值要和Model類中屬性名一致,不然會出現(xiàn)問題,把出錯的話,就復(fù)制粘貼吧! (^-#-^)
NSDictionary *personDic = @{@"name" :@"你是誰", @"phoneNumber" :@"1314512521", @"address" :@"國際空間站"};
Person *per = [[Person alloc] init];
//注意:這只是KVC中的一種用法(下面會把中的用法都介紹一下)
[per setValuesForKeysWithDictionary:personDic];
實例清單1.3 KVC的第三種用法(可能會失效,原因未知, 有待讀者研究)(setValue:forKeyPath:):
// Person.h類文件
#import <Foundation/Foundation.h>
@class Student;
@interface Person : NSObject
@property (nonatomic, strong) Student *stu;
@end
// Student.h類文件
#import <Foundation/Foundation.h>
@interface Student : NSObject
@property (nonatomic, strong) NSString *sex;
@end
//vc.m文件
#import "ViewController.h"
#import "Person.h"
#import "student.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *per = [[Person alloc] init];
//關(guān)鍵路徑賦值
[per setValue:@"male" forKeyPath:@"stu.sex"];
Student *stu = [[Student alloc] init];
NSLog(@"%@", stu);
}
KVO
重點來了,KVO的時間到了,KVO的全稱叫(Key-value observing),在我理解看來,就是一種監(jiān)聽機制,能夠?qū)崟r的監(jiān)聽關(guān)鍵Key值得變化,現(xiàn)在你可能不明白這個Key到底是神魔玩意, 先不要著急,繼續(xù)讀下去,在這我先舉幾個例子,比如:UIscrollView中屬性contentOffset, 自定義的BOOL屬性, UIView及子類的backgroundColor屬性等等都可以作為Key,即觀察的對象.廢話不多說了,實例才能證明一切.
聲明:如果想實現(xiàn)下列清單中的案例請粘貼到工程中就可以了,具體的實現(xiàn)可能使你更加的了解KVO -%-
實例清單如下:
//自定義的TitleView(網(wǎng)易新聞的文字橫條)
//TitleView.h文件
#import <UIKit/UIKit.h>
@interface TitleView : UIView
@property (nonatomic, retain) NSArray *titles;
@end
//TitleView.m文件
#import "TitleView.h"
@interface TitleView ()
@end
@implementation TitleView
#pragma mark - override
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self createSubviews];
}
return self;
}
- (void)setTitles:(NSArray *)titles {
for (int i = 0; i < 5; i++) {
[self.subviews[i] setTitle:titles[i] forState:UIControlStateNormal];
}
}
- (void)createSubviews {
for (int i = 0; i < 5; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
button.frame = CGRectMake(CGRectGetWidth(self.bounds) / 5 * i, 0, CGRectGetWidth(self.bounds) / 5, CGRectGetHeight(self.bounds));
[self addSubview:button];
}
}
// 當(dāng)然自定義TitleView不是重點啦, 重點來啦
@interface ViewController () <UICollectionViewDelegate, UICollectionViewDataSource,
UIScrollViewDelegate>
@property (nonatomic, retain) UIView *viewOfRedline;
@property (nonatomic, retain) UICollectionView *collectionView;
@property (nonatomic, retain) TitleView *viewOfTitle;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self createViewOfRedLine];
[self createCollectionView];
[self createTitleView];
}
//不是重點哦
- (void)createViewOfRedLine {
self.viewOfRedline = [[UIView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds) / 5, 2)];
[self.view addSubview:self.viewOfRedline];
self.viewOfRedline.backgroundColor = [UIColor redColor];
}
// 不是重點哦
- (void)createCollectionView {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.itemSize = CGSizeMake(CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 66);
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 0;
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 66, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 66) collectionViewLayout:layout];
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
[self.view addSubview:self.collectionView];
// 注冊cell
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"pool"];
self.collectionView.pagingEnabled = YES;
// KVO 觀察collectionView的offset //注意:次步是重點
[self.collectionView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}
// 不是重點
- (void)createTitleView {
self.viewOfTitle = [[TitleView alloc] initWithFrame:CGRectMake(0, 32, CGRectGetWidth(self.view.bounds), 32)];
self.viewOfTitle.titles = @[@"頭條", @"熱點", @"財經(jīng)", @"新聞", @"汽車"];
[self.view addSubview:self.viewOfTitle];
}
// KOV的實現(xiàn),事件處理都在這里進行處理, 這是重點哦, 好好理解一下吧
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
//objectForKey:@"new" 中的只能寫@"new"(新的值, 監(jiān)聽的Key的變化的值) 或者寫 @"old"(舊的值, 監(jiān)聽Key變化之前的值)
// 在這里我們獲取新值(變化后的值)
CGFloat x = [[change objectForKey:@"new"] CGPointValue].x / 5.0f;
self.viewOfRedline.frame = CGRectMake(x, 64, CGRectGetWidth(self.view.bounds) / 5, 2);
}
// UIScrollView的協(xié)議方法之一
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 5;
}
// UIScrollView的協(xié)議方法之一
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"pool" forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithRed:arc4random() % (256) / 255.0f green:arc4random() % (256) / 255.0f blue:arc4random() % (256) / 255.0f alpha:1];
return cell;
}
// 改變標(biāo)題的顏色
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSInteger index = scrollView.contentOffset.x / 5.0f / (CGRectGetWidth(self.view.bounds) / 5);
for (UIButton *button in self.viewOfTitle.subviews) {
[button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
}
[self.viewOfTitle.subviews[index] setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
}