iOS-KVC(八)常见使用

iOS-KVC(一)基本使用
iOS-KVC(二)内部赋值深层次原理
iOS-KVC(三)内部取值深层次原理
iOS-KVC(四)常见异常处理
iOS-KVC(五)容器类
iOS-KVC(六)正确性验证
iOS-KVC(七)字典相关
iOS-KVC(八)常见使用

KVC这种基于运行时的编程方式极大地提高了灵活性,简化了代码,甚至实现很多难以想像的功能,KVC也是许多iOS开发黑魔法的基础。

下面将列举iOS开发中KVC的使用场景:

动态地取值和设值

利用KVC动态的取值和设值是最基本的用途。

访问和修改私有变量
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:方法作了一些特殊的实现,比如说NSArray和NSSet这样的容器类就实现了这些方法。所以可以用KVC很方便地操作集合;

修改一些控件的内部属性

这里以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
打印结果:
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

最常用的就是个性化UITextField中的placeHolderText了。下面演示如果修改placeHolder的文字样式。这里的关键点是如果获取你要修改的样式的属性名,也就是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
image.png
实现多层的消息传递

当对容器类使用KVC时,valueForKey:将会被传递给容器中的每一个对象,而不是容器本身进行操作。结果会被添加进返回的容器中,这样,开发者可以很方便的操作集合来返回另一个集合。

#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
打印结果:
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中的每一项,这样,NSArray的每一员都会执行capitalizedString并返回一个包含结果的新的NSArray。

同样如果要执行多个方法也可以用valueForKeyPath:方法。它先会对每一个成员调用 capitalizedString方法,然后再调用length,因为lenth方法返回是一个数字,所以返回结果以NSNumber的形式保存在新数组里。

函数操作集合
  • 简单集合运算符
    简单集合运算符共有@avg, @count , @max , @min ,@sum5种。

  • 对象运算符
    比集合运算符稍微复杂,能以数组的方式返回指定的内容,一共有两种:

@distinctUnionOfObjects
@unionOfObjects

它们的返回值都是NSArray,区别是前者返回的元素都是唯一的,是去重以后的结果;后者返回的元素是全集。

  • Array和Set操作符
    @distinctUnionOfArrays:该操作会返回一个数组,这个数组包含不同的对象,不同的对象是在从关键路径到操作器右边的被指定的属性里

@unionOfArrays 该操作会返回一个数组,这个数组包含的对象是在从关键路径到操作器右边的被指定的属性里和@distinctUnionOfArrays不一样,重复的对象不会被移除

@distinctUnionOfSets 和@distinctUnionOfArrays类似。因为Set本身就不支持重复。

KVC笔记暂告一段落。继续学习,继续进步。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容