KeyPathExtension 1.0.6

KeyPathExtension 1.0.6

Novo维护。



  • 作者:
  • Meterwhite

LogoKeyPathExtension

  • Objective C运行时中KVC的KeyPath扩展。

  • 用更少的代码描述复杂的逻辑,减少程序员的工作量。

    1. 在KeyPath中直接访问结构体值。
    2. 在KeyPath中使用谓词。
    3. 实现自定义函数或@NSKeyValueOperator(@avg, @count, ...)。
    4. 在KeyPath中直接执行类型安全检查。
    5. 小步快跑。
  • 用较少的代码描述复杂的逻辑,减少工作量。

    1. 在KVC中直接访问结构体成员。
    2. 在KVC中使用谓词。
    3. 实现自定义函数或@NSKeyValueOperator(@avg, @count, ...)
    4. 在KVC中直接进行类型安全检查。
    5. 随手点赞,好运连连。
  • 关键词:KeyPath Extension KVC Extension 按Path排序

导入

  • KeyPathExtension目录下的所有源文件拖到您的项目中。
#import "KeyPathExtension.h"
  • 或者使用CocoaPods
pod 'KeyPathExtension'
  • iOS & macOS

概述

示例

[... kpe_setValue:@(100) forExtensionPath:@"....frame->size->width"];

[... kpe_setValue:@(YES) forExtensionPath:@"...dogs.@:age<1!.smallDog"];

[... kpe_valueForExtensionPath:@"view.subviews.@:hidden == YES!.@removeFromSuperview"];

///myStarts is outlet collections
myStarts
.akvcSetValueForExtensionPath(@(NO), @"seleced")
.akvcSetValueForExtensionPathWithFormat(@(YES), @"@:tag <= %ld!.seleced", sender.tag);

///Get the path in a different way.
@akvcGetPath(object, a.b.c.d).akvcPathAppend(@"e.f.g.h").akvcPathAppendCode(h.i.j.k);

内容


扩展路径

全部功能

Name                   Representation
-------------------------------------
StructPath         :   NSKeyPath->StructKey
Indexer            :   @[...]
PathFunction       :   @PathFunction
Subkey             :   <...>
Regkey             :   <$...$>
SELInspector       :   SEL(...)?
ClassInspector     :   Class(...)?
KeysAccessor       :   {KeyPath,KeyPath, ...}
PredicateFilter    :   @:...!
PredicateEvaluate  :   @:...?
-------------------------------------

结构路径

StructPath可以访问结构。

  • 使用访问器 -> 访问结构中的属性。结构体访问符
@"...NSKeyPath->StructKey->StructKey";

索引器

提供了一种简单的方式来访问键路径中的数组元素。

Provides a simple way to access array elements in key path.
@[0] ; @[0,1] ;

Use the index symbol 'i' to find elements within the array range.
@[i <= 3 , i > 5];

Use the index symbol '!' You can exclude elements from an array.
@[!0,!1] ; @[i != 0 , i != 1] ; @[i<5 , 9] ; @[i<5 , !3] ;

Confirm elements and deny elements cannot exist at the same time.真假不能同时存在!
It's wrong : @[0,!1] ;

PathFunction

PathFunction 是一个自定义的 NSKeyValueOperator。自定义路径函数

[... kpe_valueForExtensionPath:@"...friendList.@sortFriends..."];

Regist PathFunction

[KeyPathExtension registFunction:@"sortFriends" withBlock:^id(id  _Nullable target) {

    //... ...
    //return result;
}];

Default PathFunction 默认路径函数

name
--------------------
@nslog
@isNSNull
@isAllEqual
@lastObject
@firstObject
@isAllDifferent
--------------------

默认行为

  • 当调用未注册的方法时,函数名称将以选择器名称的方式调用。如果有返回值,则返回;如果没有返回,则返回目标本身。
id viewThatRemoved = [... kpe_valueForExtensionPath:@"view.@removeFromSuperview"];
  • 可以使用带有参数的方法,但不推荐这样做。所有参数都是默认值。
id mulArraySelf = [mulArray kpe_valueForExtensionPath:@"@removeObjectAtIndex:.@removeObjectAtIndex:"];

Equivalent ==> 

[mulArray removeObjectAtIndex:0];
[mulArray removeObjectAtIndex:0];
id mulArraySelf = mulArray;

子键

属性键的子字符串。

  • 表达式:<...>
`time` can match 'createTime' and 'modifyTime'.

[... kpe_valueForExtensionPath:@"...<time>.@isAllEqual"];

注册密钥

属性键的表达式。

  • 表达式:<$...$>
`button\\d+` can match 'button0','button1', ...

[... kpe_setValue:@(YES) forExtensionPath:@"...<button\\d+>.hidden"];

SELInspector

如果 iSELInspector 是最后一个组件,则它等价于 - respondsToSelector: .

  • 表达式:SEL(...)?
NSNumber *value = [... kpe_valueForExtensionPath:@"...SEL(addObject:)?"];

如果 SELInspector 不是最后一个组件,则它是执行下一路径的条件。

[... kpe_setValue:@"Trump" forExtensionPath:@"...friend.SEL(setNickName:)?.nickName"];

类检查器

如果类检查器是最后一个组件,它等同于 isKindOfClass: .

  • 表达式:Class(...)?
[... kpe_valueForExtensionPath:@"...Class(NSArray)?"];

如果类检查器不是最后一个组件,它是在执行下一个路径的条件。

[... kpe_setValue:@"Trump" forExtensionPath:@"...friend.Class(AkvcPerson)?.nickName"];

KeysAccessor

使用Keysaccessor可以同时访问多个路径。返回结果按顺序放置在数组中。多键访问,返回按顺的数组

  • 讨论:在KeysAccessor中,谓词(Predicate)、子键(Subkey)、注册键(Regkey)被禁用!另外,nil值将替换为NSNull。
  • 表达式:{...}
[... kpe_valueForExtensionPath:@"{Breakfast.name, lunch.name, dinner.name}.@isAllEqual"];

谓词过滤器

PredicateFilter 等于 - filteredArrayUsingPredicate

  • 表达式:@:PredicateString!
  • 讨论:符号 !.?. 不应使用,但 ?!. 可用。
[... kpe_valueForExtensionPath:@"...users.@:age>18 && sex == 0!"];

在 ExtensionPath 中为 predicate 组件使用占位符

  • 讨论:参数列表只接受装箱参数。使用 AkvcBoxValue(...) 拼接标量。
[... kpe_valueForExtensionPathWithPredicateFormat:@"...@:@K == %@!...@:SELF == %@?", object0, object1, object2];

PredicateEvaluate

PredicateEvaluate 等于 - evaluateWithObject: . 参考 PredicateFilter

  • 表达式:@:PredicateString?

Component ...?

  • Class(...)?(ClassInspector), SEL(...)?(SELInspector),@:...? (PredicateEvaluate)
    这些组件都具有此特性:如果不是最后一个组件,将作为一个条件来确定是否执行下一个路径。如果为 false,则返回 nil 或不执行任何操作,否则执行下一个路径。
    • 在路径中这类组件表示执行条件,false 时返回 nil 或不进行任何操作,true 时继续执行。

注册自定义结构体

  • 注册自定义结构体需要2个方法:+ registStruct:getterMap:+ registStruct:setterMap:
    • getter map 或 setter map 的键是结构体成员名称
    • getter map 的值是一个类似以下块的代码:__kindof NSValue*(^GetBlockType)(NSValue* value)
@{
    @"size"   :   ^(NSValue* value){
    
        return [NSValue valueWithCGSize:[value CGRectValue].size];
    } ,
    ... ...
}
  • setter map 的值是一个类似以下块的代码:__kindof NSValue*(^SetBlockType)(NSValue* value , id newValue)
@{
    @"size"   :   ^(NSValue* value , id newValue){

        CGRect rect = [value CGRectValue];
        rect.size = [newValue CGSizeValue];
        return [NSValue valueWithCGRect:rect];
    } ,
    ... ...
}

清除缓存

[KeyPathExtension cleanCache];

链式编程

  • NSObject+KeyPathExtensionChain.h 定义了链式编程的 API,所有 setter 的返回值都是目标本身。
_NonnullObject.akvcSetValueForExtensionPath(...)akvcSetValueForExtensionPath(...)...

需要扩展 KeyPathExtension