iOS-KVC(一)基本使用
iOS-KVC(二)內(nèi)部賦值深層次原理
iOS-KVC(三)內(nèi)部取值深層次原理
iOS-KVC(四)常見異常處理
iOS-KVC(五)容器類
iOS-KVC(六)正確性驗(yàn)證
iOS-KVC(七)字典相關(guān)
iOS-KVC(八)常見使用
KVC這種基于運(yùn)行時(shí)的編程方式極大地提高了靈活性,簡化了代碼,甚至實(shí)現(xiàn)很多難以想像的功能,KVC也是許多iOS開發(fā)黑魔法的基礎(chǔ)。
下面將列舉iOS開發(fā)中KVC的使用場景:
動(dòng)態(tài)地取值和設(shè)值
利用KVC動(dòng)態(tài)的取值和設(shè)值是最基本的用途。
訪問和修改私有變量
Person.m
#import "Person.h"
@interface Person()
@property (nonatomic, copy) NSString *innerProperty;
@end
@implementation Person
- (instancetype)init
{
self = [super init];
if ( self ) {
self.innerProperty = @"innerProperty";
}
return self;
}
@end
在其他的類中,通過
[xxxx valueForKey:@"innerProperty"] 可以獲取到Person的私有屬性和私有變量的值;
操作集合對象
KVC的valueForKey:方法作了一些特殊的實(shí)現(xiàn),比如說NSArray和NSSet這樣的容器類就實(shí)現(xiàn)了這些方法。所以可以用KVC很方便地操作集合;
修改一些控件的內(nèi)部屬性
這里以UITextField為示例,通過runtime獲取UITextField的成員變量名。
#import "ViewController.h"
#import <objc/runtime.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([UITextField class], &outCount);
for (int i = 0 ; i < outCount; ++i) {
Ivar ivar = ivars[i];
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
NSLog(@"%@", ivarName);
}
}
@end
打印結(jié)果:
2019-06-23 17:37:21.951965+0800 study[13019:192606] _borderStyle
2019-06-23 17:37:21.952126+0800 study[13019:192606] _minimumFontSize
2019-06-23 17:37:21.952230+0800 study[13019:192606] _delegate
2019-06-23 17:37:21.952331+0800 study[13019:192606] _background
2019-06-23 17:37:21.952447+0800 study[13019:192606] _disabledBackground
2019-06-23 17:37:21.952542+0800 study[13019:192606] _clearButtonMode
2019-06-23 17:37:21.952681+0800 study[13019:192606] _leftView
2019-06-23 17:37:21.952775+0800 study[13019:192606] _leftViewMode
2019-06-23 17:37:21.952872+0800 study[13019:192606] _rightView
2019-06-23 17:37:21.952966+0800 study[13019:192606] _rightViewMode
2019-06-23 17:37:21.953054+0800 study[13019:192606] _contentCoverView
2019-06-23 17:37:21.953251+0800 study[13019:192606] _contentCoverViewMode
2019-06-23 17:37:21.953533+0800 study[13019:192606] _backgroundCoverView
2019-06-23 17:37:21.953813+0800 study[13019:192606] _backgroundCoverViewMode
2019-06-23 17:37:21.954153+0800 study[13019:192606] _traits
2019-06-23 17:37:21.954423+0800 study[13019:192606] _nonAtomTraits
2019-06-23 17:37:21.954729+0800 study[13019:192606] _fullFontSize
2019-06-23 17:37:21.955079+0800 study[13019:192606] _padding
2019-06-23 17:37:21.955341+0800 study[13019:192606] _progress
2019-06-23 17:37:21.955728+0800 study[13019:192606] _clearButton
2019-06-23 17:37:21.957196+0800 study[13019:192606] _clearButtonOffset
2019-06-23 17:37:21.957315+0800 study[13019:192606] _leftViewOffset
2019-06-23 17:37:21.957415+0800 study[13019:192606] _rightViewOffset
2019-06-23 17:37:21.957504+0800 study[13019:192606] _backgroundView
2019-06-23 17:37:21.957589+0800 study[13019:192606] _disabledBackgroundView
2019-06-23 17:37:21.957678+0800 study[13019:192606] _systemBackgroundView
2019-06-23 17:37:21.957795+0800 study[13019:192606] _textContentView
2019-06-23 17:37:21.957911+0800 study[13019:192606] _floatingContentView
2019-06-23 17:37:21.958001+0800 study[13019:192606] _contentBackdropView
2019-06-23 17:37:21.958245+0800 study[13019:192606] _fieldEditorBackgroundView
2019-06-23 17:37:21.958559+0800 study[13019:192606] _fieldEditorEffectView
2019-06-23 17:37:21.958869+0800 study[13019:192606] _placeholderLabel
2019-06-23 17:37:21.959139+0800 study[13019:192606] _suffixLabel
2019-06-23 17:37:21.959453+0800 study[13019:192606] _prefixLabel
2019-06-23 17:37:21.959710+0800 study[13019:192606] _iconView
2019-06-23 17:37:21.960013+0800 study[13019:192606] _label
2019-06-23 17:37:21.960278+0800 study[13019:192606] _labelOffset
2019-06-23 17:37:21.960581+0800 study[13019:192606] _overriddenPlaceholder
2019-06-23 17:37:21.960853+0800 study[13019:192606] _overriddenPlaceholderAlignment
2019-06-23 17:37:21.961147+0800 study[13019:192606] _interactionAssistant
2019-06-23 17:37:21.961413+0800 study[13019:192606] _selectGestureRecognizer
2019-06-23 17:37:21.961660+0800 study[13019:192606] _fieldEditor
2019-06-23 17:37:21.961934+0800 study[13019:192606] __textContainer
2019-06-23 17:37:21.962323+0800 study[13019:192606] __layoutManager
2019-06-23 17:37:21.962529+0800 study[13019:192606] _textStorage
2019-06-23 17:37:21.962854+0800 study[13019:192606] _pasteController
2019-06-23 17:37:21.963259+0800 study[13019:192606] _inputView
2019-06-23 17:37:21.963590+0800 study[13019:192606] _inputAccessoryView
2019-06-23 17:37:21.964307+0800 study[13019:192606] _recentsAccessoryView
2019-06-23 17:37:21.964645+0800 study[13019:192606] _systemInputViewController
2019-06-23 17:37:21.965105+0800 study[13019:192606] _atomBackgroundView
2019-06-23 17:37:21.965361+0800 study[13019:192606] _textDragDropSupport
2019-06-23 17:37:21.965661+0800 study[13019:192606] _textFieldFlags
2019-06-23 17:37:21.966017+0800 study[13019:192606] _deferringBecomeFirstResponder
2019-06-23 17:37:21.966374+0800 study[13019:192606] _animateNextHighlightChange
2019-06-23 17:37:21.966638+0800 study[13019:192606] _cuiCatalog
2019-06-23 17:37:21.966982+0800 study[13019:192606] _cuiStyleEffectConfiguration
2019-06-23 17:37:21.967281+0800 study[13019:192606] _roundedRectBackgroundCornerRadius
2019-06-23 17:37:21.967577+0800 study[13019:192606] _overriddenAttributesForEditing
2019-06-23 17:37:21.967862+0800 study[13019:192606] _adjustsFontForContentSizeCategory
2019-06-23 17:37:21.968136+0800 study[13019:192606] _tvUseVibrancy
2019-06-23 17:37:21.968439+0800 study[13019:192606] _disableTextColorUpdateOnTraitCollectionChange
2019-06-23 17:37:21.968746+0800 study[13019:192606] _pasteDelegate
2019-06-23 17:37:21.969034+0800 study[13019:192606] _baselineLayoutConstraint
2019-06-23 17:37:21.969317+0800 study[13019:192606] _baselineLayoutLabel
2019-06-23 17:37:21.969629+0800 study[13019:192606] _tvCustomTextColor
2019-06-23 17:37:21.969933+0800 study[13019:192606] _tvCustomFocusedTextColor
2019-06-23 17:37:21.970251+0800 study[13019:192606] _textDragOptions
2019-06-23 17:37:21.970541+0800 study[13019:192606] _textDragDelegate
2019-06-23 17:37:21.970839+0800 study[13019:192606] _textDropDelegate
2019-06-23 17:37:21.971160+0800 study[13019:192606] _visualStyle
最常用的就是個(gè)性化UITextField中的placeHolderText了。下面演示如果修改placeHolder的文字樣式。這里的關(guān)鍵點(diǎn)是如果獲取你要修改的樣式的屬性名,也就是key或者keyPath名。
#import "ViewController.h"
#import <objc/runtime.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *textField;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.textField setValue:[UIColor blueColor] forKeyPath:@"_placeholderLabel.textColor"];
[self.textField setValue:[UIFont systemFontOfSize:14] forKeyPath:@"_placeholderLabel.font"];
[self.textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.backgroundColor"];
}
@end

實(shí)現(xiàn)多層的消息傳遞
當(dāng)對容器類使用KVC時(shí),valueForKey:將會(huì)被傳遞給容器中的每一個(gè)對象,而不是容器本身進(jìn)行操作。結(jié)果會(huì)被添加進(jìn)返回的容器中,這樣,開發(fā)者可以很方便的操作集合來返回另一個(gè)集合。
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *arr = @[@"apple", @"orange", @"pear", @"grape"];
NSArray *capitalizedStringArr = [arr valueForKey:@"capitalizedString"];
NSLog(@"capitalizedStringArr = %@", capitalizedStringArr);
NSArray *capitalizedStringLengthArr = [arr valueForKeyPath:@"capitalizedString.length"];
NSLog(@"capitalizedStringLengthArr = %@", capitalizedStringLengthArr);
}
@end
打印結(jié)果:
2019-06-23 17:54:29.889966+0800 study[13554:201678] capitalizedStringArr = (
Apple,
Orange,
Pear,
Grape
)
2019-06-23 17:54:29.890241+0800 study[13554:201678] capitalizedStringLengthArr = (
5,
6,
4,
5
)
方法capitalizedString被傳遞到NSArray中的每一項(xiàng),這樣,NSArray的每一員都會(huì)執(zhí)行capitalizedString并返回一個(gè)包含結(jié)果的新的NSArray。
同樣如果要執(zhí)行多個(gè)方法也可以用valueForKeyPath:方法。它先會(huì)對每一個(gè)成員調(diào)用 capitalizedString方法,然后再調(diào)用length,因?yàn)閘enth方法返回是一個(gè)數(shù)字,所以返回結(jié)果以NSNumber的形式保存在新數(shù)組里。
函數(shù)操作集合
簡單集合運(yùn)算符
簡單集合運(yùn)算符共有@avg, @count , @max , @min ,@sum5種。對象運(yùn)算符
比集合運(yùn)算符稍微復(fù)雜,能以數(shù)組的方式返回指定的內(nèi)容,一共有兩種:
@distinctUnionOfObjects
@unionOfObjects
它們的返回值都是NSArray,區(qū)別是前者返回的元素都是唯一的,是去重以后的結(jié)果;后者返回的元素是全集。
- Array和Set操作符
@distinctUnionOfArrays:該操作會(huì)返回一個(gè)數(shù)組,這個(gè)數(shù)組包含不同的對象,不同的對象是在從關(guān)鍵路徑到操作器右邊的被指定的屬性里
@unionOfArrays 該操作會(huì)返回一個(gè)數(shù)組,這個(gè)數(shù)組包含的對象是在從關(guān)鍵路徑到操作器右邊的被指定的屬性里和@distinctUnionOfArrays不一樣,重復(fù)的對象不會(huì)被移除
@distinctUnionOfSets 和@distinctUnionOfArrays類似。因?yàn)镾et本身就不支持重復(fù)。
KVC筆記暫告一段落。繼續(xù)學(xué)習(xí),繼續(xù)進(jìn)步。