要运行示例项目,先从仓库中克隆,然后从 Example 目录运行 pod install
KSReason 通过 CocoaPods 提供。要安装它,请在您的 Podfile 添加以下行
pod "KSReason"
Backbone 是一个组件,用于实现模型和集合(受同名网络框架的启发)。
模型 可扩展,包括序列化、验证、获取器、设置器、存档和复制功能
KSModel *model = [KSModel new];
[model parse:@{ @"id": @"...", @"title": @"...", @"description": @"..." }];
[model get:@"title"];
[model get:@"description"];
集合 是有序的模型组,包括序列化、枚举、存档和复制功能
KSCollection *collection = [KSCollection new];
[collection parse:@[@{ @"id": @"...", @"title": @"...", @"description": @"..." }]];
collection.models;
事件 可以应用于模型和集合,以便轻松跟踪修改
KSModel *model = [KSModel new];
void (^callback)(KSModel *) = ^(KSModel *model) {
// ...
};
[model on:@"change" callback:callback];
[model parse:@{ @"id": @"...", @"title": @"...", @"description": @"..." }];
[model off:@"change" callback:callback];
KSCollection *collection = [KSCollection new];
void (^callback)(KSCollection *) = ^(KSCollection *collection) {
// ...
};
[collection on:@"reset" callback:callback];
[model parse:@[@{ @"id": @"...", @"title": @"...", @"description": @"..." }]];
[collection off:@"reset" callback:callback];
有状态 是一个组件,用于实现有限状态机。它支持状态、转换、守卫和回调。
配置 有限状态机是通过配置状态、转换、守卫和回调来完成的
__block typeof(self) bself = self;
KSFSM *fsm = [KSFSM new];
// States:
KSState *sleeping = [KSState named:@"sleeping"];
KSState *working = [KSState named:@"working"];
KSState *resting = [KSState named:@"resting"];
KSState *dead = [KSState named:@"dead"];
[fsm.states add:sleeping];
[fsm.states add:working];
[fsm.states add:resting];
[fsm.states add:dead];
fsm.states.initial = resting;
// Transitions:
[fsm.transitions add:[KSTransition named:@"work" from:sleeping to:working]];
[fsm.transitions add:[KSTransition named:@"rest" from:sleeping to:resting]];
[fsm.transitions add:[KSTransition named:@"sleep" from:@[working,resting] to:sleeping]];
[fsm.transitions add:[KSTransition named:@"sleep" from:@[sleeping,working,resting] to:dead]];
// Guards:
[work enterable:^BOOL {
// i.e. return bself.weekday;
}];
[rest enterable:^BOOL {
// i.e. return bself.weekend;
}];
[sleep exitable:^BOOL {
// i.e. return bself.daytime;
}];
// Callbacks:
[sleeping entered:^(KSState *state, KSTransition *transition) {
// i.e. ZZZ ZZZ ZZZ
}];
[sleeping exited:^(KSState *state, KSTransition *transition) {
// i.e. BEEP BEEP BEEP
}];
使用方法 是通过执行转换并检查错误来使用有状态对象的
NSError *error;
[fsm reset]; // Optional.
[fsm transition:@"work" error:&error].execute;
fsm.state; // working;
[fsm transition:@"sleep" error:&error].execute;
fsm.state; // sleeping;
[fsm transition:@"rest" error:&error].execute;
fsm.state; // resting;
[fsm transition:@"sleep" error:&error].execute;
fsm.state; // sleeping;
[fsm transitionable:@"sleep"]; // i.e. YES or NO
if (![fsm transition:@"sleep" error:&error].execute);
error; // <NSError @"invalid transition 'sleep' from 'sleeping' to 'sleeping">;
可枚举 为数组和字典提供了许多扩展,以支持更好的枚举
每个 对集合的每个条目执行一次代码块
集合
NSSet *collection = [NSSet setWithObjects:@"Canada", @"Greece", @"Russia", NULL];
[collection ks_each:^(NSString *object) {
// ...
}];
数组
NSArray *collection = [NSArray arrayWithObjects;@"Canada", @"Greece", @"Russia", NULL];
[collection ks_each:^(NSString *object) {
// ...
}];
字典
NSDictionary *collection = @{ @"Canada": @"Victoria", @"Russia": @"Moscow", @"Greece": @"Athens" };
[collection ks_each:^(NSString *key, NSString *value) {
// ...
}];
映射 在集合的每个元素上执行一次代码块,并返回一个同一类型的包含代码块结果的集合
集合
NSSet *collection = [NSSet setWithObjects:@"Canada", @"Greece", @"Russia", NULL];
NSSet *mapping = [collection ks_map:^NSString *(NSString *object) {
// ex: NSString *mapping = [object reverse];
return mapping;
}];
数组
NSArray *collection = [NSArray arrayWithObjects;@"Canada", @"Greece", @"Russia", NULL];
NSArray *mapping = [collection ks_map:^NSString *(NSString *object) {
// ex: NSString *mapping = [object reverse];
return mapping;
}];
字典
NSDictionary *collection = @{ @"Canada": @"Victoria", @"Russia": @"Moscow", @"Greece": @"Athens" };
NSDictionary *mapping = [collection ks_map:^NSString *(NSString *key, NSString *value) {
// ex: NSString *mapping = [value reverse];
return mapping;
}];
Reduce 对集合中的每个元素执行一次操作,并在遍历过程中返回备忘录
集合
NSSet *collection = [NSSet setWithObjects:@"Canada", @"Greece", @"Russia", NULL];
NSString *reduction = [collection ks_reduce:^NSString *(NSString *memo, NSString *object){
return [NSString stringWithFormat:@"%@ %@", memo, object];
} memo:@"reduction:"];
数组
NSArray *collection = [NSArray arrayWithObjects;@"Canada", @"Greece", @"Russia", NULL];
NSString *reduction = [collection ks_reduce:^NSString *(NSString *memo, NSString *object){
return [NSString stringWithFormat:@"%@ %@", memo, object];
} memo:@"reduction:"];
字典
NSArray *collection = [NSArray arrayWithObjects;@"Canada", @"Greece", @"Russia", NULL];
NSString *reduction = [collection ks_reduce:^NSString *(NSString *memo, NSString *key, NSString *value){
return [NSString stringWithFormat:@"%@ %@", memo, value];
} memo:@"reduction:"];
查找 遍历集合中的每个元素,并返回符合条件的那一个元素
集合
NSSet *collection = [NSSet setWithObjects:@"Canada", @"Greece", @"Russia", NULL];
NSString *element = [collection ks_find:^BOOL (NSString *object) {
return [object isEqualToString:@"..."];
}];
数组
NSArray *collection = [NSArray arrayWithObjects:@"Canada", @"Greece", @"Russia", NULL];
NSString *element = [collection ks_find:^BOOL (NSString *object) {
return [object isEqualToString:@"..."];
}];
字典
NSDictionary *collection = @{ @"Canada" : @"Victoria", @"Greece": @"Athens", @"Russia": @"Moscow" };
NSString *element = [collection ks_find:^BOOL (NSString *key, NSString *value) {
return [key isEqualToString:@"..."];
}];
任意元素 将集合中的每个元素传递给指定的操作块,并返回一个布尔值,表示操作块是否匹配任何元素
集合
NSSet *collection = [NSSet setWithObjects:@"Canada", @"Greece", @"Russia", NULL];
BOOL any = [collection ks_any:^BOOL (NSString *object) {
return [object isEqualToString:@"..."];
}];
数组
NSArray *collection = [NSArray arrayWithObjects:@"Canada", @"Greece", @"Russia", NULL];
BOOL any = [collection ks_any:^BOOL (NSString *object) {
return [object isEqualToString:@"..."];
}];
字典
NSDictionary *collection = @{ @"Canada" : @"Victoria", @"Greece": @"Athens", @"Russia": @"Moscow" };
BOOL any = [collection ks_any:^BOOL (NSString *key, NSString *value) {
return [key isEqualToString:@"..."];
}];
所有元素 将集合中的每个元素传递给指定的操作块,并返回一个布尔值,表示操作块是否一直匹配每一个元素
集合
NSSet *collection = [NSSet setWithObjects:@"Canada", @"Greece", @"Russia", NULL];
BOOL all = [collection ks_all:^BOOL (NSString *object) {
return [object isEqualToString:@"..."];
}];
数组
NSArray *collection = [NSArray arrayWithObjects:@"Canada", @"Greece", @"Russia", NULL];
BOOL all = [collection ks_all:^BOOL (NSString *object) {
return [object isEqualToString:@"..."];
}];
字典
NSDictionary *collection = @{ @"Canada" : @"Victoria", @"Greece": @"Athens", @"Russia": @"Moscow" };
BOOL all = [collection ks_all:^BOOL (NSString *key, NSString *value) {
return [key isEqualToString:@"..."];
}];
过滤 将集合中的每个元素传递给指定的操作块,并返回匹配操作块过滤后的元素
集合
NSSet *collection = [NSSet setWithObjects:@"Canada", @"Greece", @"Russia", NULL];
NSSet *filter = [collection ks_filter:^BOOL (NSString *object) {
// ex.: BOOL match = [object isEqualToString:@"..."];
return match;
}];
数组
NSArray *collection = [NSArray arrayWithObjects:@"Canada", @"Greece", @"Russia", NULL];
NSArray *filtered = [collection ks_filter:^BOOL (NSString *object) {
// ex.: BOOL match = [object isEqualToString:@"..."];
return match;
}];
字典
NSDictionary *collection = @{ @"Canada" : @"Victoria", @"Greece": @"Athens", @"Russia": @"Moscow" };
NSDictionary *filtered = [collection ks_filter:^BOOL (NSString *key, NSString *value) {
// ex.: BOOL match = [key isEqualToString:@"..."] || [value isEqualToString:@"..."];
return match;
}];
拒绝 将集合中的每个元素传递给指定的操作块,并返回不匹配操作块的过滤后的元素
集合
NSSet *collection = [NSSet setWithObjects:@"Canada", @"Greece", @"Russia", NULL];
NSSet *filter = [collection ks_reject:^BOOL (NSString *object) {
// ex.: BOOL match = [object isEqualToString:@"..."];
return match;
}];
数组
NSArray *collection = [NSArray arrayWithObjects:@"Canada", @"Greece", @"Russia", NULL];
NSArray *filtered = [collection ks_reject:^BOOL (NSString *object) {
// ex.: BOOL match = [object isEqualToString:@"..."];
return match;
}];
字典
NSDictionary *collection = @{ @"Canada" : @"Victoria", @"Greece": @"Athens", @"Russia": @"Moscow" };
NSDictionary *filtered = [collection ks_reject:^BOOL (NSString *key, NSString *value) {
// ex.: BOOL match = [key isEqualToString:@"..."] || [value isEqualToString:@"..."];
return match;
}];
并集 生成目标集合和参数集合的并集
集合
NSSet *alpha = [NSSet setWithObjects:@"A", @"B", NULL];
NSSet *omega = [NSSet setWithObjects:@"B", @"C", NULL];
[alpha ks_union:omega]; // [NSSet setWithObjects:@"A", @"B", @"C", NULL];
数组
NSArray *alpha = [NSArray arrayWithObjects:@"A", @"B", NULL];
NSArray *omega = [NSArray arrayWithObjects:@"B", @"C", NULL];
[alpha ks_union:omega]; // [NSArray arrayWithObjects:@"A", @"B", @"C", NULL];
字典
NSDictionary *alpha = @{ @"A": @"A", @"B": @"B" };
NSDictionary *omega = @{ @"B": @"B", @"C": @"C" };
[alpha ks_union:omega]; // @{ @"A": @"A", @"B": @"B", @"C": @"C" };
交集 生成目标集合和参数集合的交集
集合
NSSet *alpha = [NSSet setWithObjects:@"A", @"B", NULL];
NSSet *omega = [NSSet setWithObjects:@"B", @"C", NULL];
[alpha ks_intersection:omega]; // [NSSet setWithObjects:@"B", NULL];
数组
NSArray *alpha = [NSArray arrayWithObjects:@"A", @"B", NULL];
NSArray *omega = [NSArray arrayWithObjects:@"B", @"C", NULL];
[alpha ks_intersection:omega]; // [NSArray arrayWithObjects:@"B", NULL];
字典
NSDictionary *alpha = @{ @"A": @"A", @"B": @"B" };
NSDictionary *omega = @{ @"B": @"B", @"C": @"C" };
[alpha ks_intersection:omega]; // @{ @"B": @"B" };
差集 生成目标集合与参数集合的差集
集合
NSSet *alpha = [NSSet setWithObjects:@"A", @"B", NULL];
NSSet *omega = [NSSet setWithObjects:@"B", @"C", NULL];
[alpha ks_difference:omega]; // [NSSet setWithObjects:@"A", @"C", NULL];
数组
NSArray *alpha = [NSArray arrayWithObjects:@"A", @"B", NULL];
NSArray *omega = [NSArray arrayWithObjects:@"B", @"C", NULL];
[alpha ks_difference:omega]; // [NSArray arrayWithObjects:@"A", @"C", NULL];
字典
NSDictionary *alpha = @{ @"A": @"A", @"B": @"B" };
NSDictionary *omega = @{ @"B": @"B", @"C": @"C" };
[alpha ks_difference:omega]; // @{ @"A": @"A", @"C": @"C" };
最小值 使用 compare:
在集合中搜索以获取最小元素(元素必须实现 compare:
)
集合
NSSet *collection = [NSSet setWithObjects:@1.0, @1.25, @0.75, NULL];
collection.ks_minimum; //0.75
数组
NSArray *collection = [NSArray arrayWithObjects:@1.00, @1.25, @0.75, NULL];
collection.ks_minimum; // 0.75;
字典
NSDictionary *collection = @{ @"USD": @1.00, @"CDN": @1.25, @"EUR": @0.75 };
collection.ks_minimum; // 0.75
最大值 使用 compare:
在集合中搜索以获取最大元素(元素必须实现 compare:
)
集合
it (@"exposes the maximum in an set", ^{
NSSet *collection = [NSSet setWithObjects:@1.00, @1.25, @0.75, NULL];
collection.ks_maximum; // 1.25
数组
it (@"exposes the maximum in an array", ^{
NSArray *collection = [NSArray arrayWithObjects:@1.0, @1.25, @0.75, NULL];
collection.ks_maximum; //1.25);
字典
NSDictionary *collection = @{ @"USD": @1.0, @"CDN": @1.25, @"EUR": @0.75 };
collection.ks_maximum; //1.25
样本 从集合中随机抓取一个元素。
集合
NSSet *collection = [NSSet setWithObjects:@1.0, @1.25, @0.75, NULL];
collection.ks_sample; // (1.0 | 1.25 | 0.75)
数组
NSArray *collection = [NSArray arrayWithObjects:@1.0, @1.25, @0.75, NULL];
collection.ks_sample; // (1.0 | 1.25 | 0.75)
字典
NSDictionary *collection = @{ @"USD": @1.0, @"CDN": @1.25, @"EUR": @0.75 };
collection.ks_sample; // (1.0 | 1.25 | 0.75)
函数 提供了一些处理操作块的帮助函数
防抖 延迟执行操作块,直到经过一定的时间间隔
KSDebounce *debounce = [KSDebounce new];
__block typeof(self) bself;
[debounce debounce:0.2 block: ^{
[bself search:self.mainSearchBar.text];
}];
NSDictionary *attributes = @{ @"name": @"John Smith", @"email": @"[email protected]", @"phone": @"+1 555-555-5555" };
NSDictionary *validations = @{
@"name": @{ KSValidate.presence: @{ KSValidate.message: @"must be entered" } },
@"tagline": @{ KSValidate.length: @{ KSValidate.minimum: @20, KSValidate.maximum: @80 } },
@"email": @{ KSValidate.format: @{ KSValidate.with: KSValidateFormatEmail } },
@"phone": @{ KSValidate.format: @{ KSValidate.with: KSValidateFormatPhone } },
@"country": @{ KSValidate.inclusion: @{ KSValidate.of: @[@"Canada"] } },
@"region": @{ KSValidate.exclusion: @{ KSValidate.of: @[@"PEI"] } },
};
KSValidator *validator = [KSValidator validator:validations];
[validator validate:attributes];
validator.errors;
// ex.:
// @{
// @"tagline": @[@"must be between 20 and 80 characters", @"cannot contain inappriate language"],
// @"email": @[@"is formatted wrong"], @"phone": @[@"is formatted wrong"]
// };
validator.humanize;
// @"tagline must be between 20 and 80 characters, tagline cannot contain inapproriate language, email is formatted wrong, phone is formatted wrong and name can't be blank"
[KSValidator length:@"test" is:8]; // NO
[KSValidator length:@"test" is:4]; // YES
[KSValidator length:@"test" minimum:5]; // NO
[KSValidator length:@"test" minimum:4]; // YES
[KSValidator length:@"test" minimum:3]; // YES
[KSValidator length:@"test" maximum:3]; // NO
[KSValidator length:@"test" maximum:4]; // YES
[KSValidator length:@"test" maximum:5]; // YES
[KSValidator format:@"tester" with:KSValidationEmail]; // NO
[KSValidator format:@"[email protected]" with:KSValidationEmail]; // YES
[KSValidator format:@"tester" with:KSValidationPhone]; // NO
[KSValidator format:@"+1 555-555-5555" with:KSValidationPhone]; // YES
[KSValidator format:@"..." with:@"\\...\\"]; // NO
[KSValidator format:@"abcdefghijklmnopqrstuvwxyz" with:@"\\..\\"]; // YES
[KSValidator inclusion:@"blue" collection:@[@"blue"]]; // YES
[KSValidator inclusion:@"pink" collection:@[@"blue"]]; // NO
[KSValidator exclusion:@"blue" collection:@[@"blue"]]; // YES
[KSValidator exclusion:@"pink" collection:@[@"blue"]]; // NO
[KSValidator presence:@"Greetings!"]; // YES
[KSValidator absence:@"Greetings!"]; // NO
属性名称还可以添加到 Localizable.strings
中
消息
"is invalid": "...";
"can't be blank": "...";
"can't be present": "...";
"must be exactly %@ characters": "...";
"must be between %@ and %@ characters": "...";
"must be a minimum of %@ characters": "...";
"must be a maximum of %@ characters": "...";
属性
"ssn" = "social security number";
[@"cookie" ks_pluralize]; // "cookies"
[@"cherry" ks_pluralize]; // "cherries"
[@"potato" ks_pluralize]; // "potatoes"
[@"cookies" ks_singularize]; // "cookie"
[@"cherries" ks_singularize]; // "cherry"
[@"potatoes" ks_singularize]; // "potato"
[KSInflector.shared inflect:1 string:@"star"]; // "1 star" [KSInflector.shared inflect:2 string:@"star"]; // "2 stars" [KSInflector.shared inflect:3 string:@"star"]; // "3 stars"
[KSInflector config:^(KSInflector *inflector) {
[inflector singular:@"oxen$" replacement:@"ox"];
[inflector plural:@"ox$" replacement:@"oxen"];
}];
[NSNull null].ks_exists; // NO
[NSObject new].ks_exists; // YES
[NSSet set].ks_exists; // NO
[NSSet setWithObject:object].ks_exists; // YES
[NSArray set].ks_exists; // NO
[NSArray setWithObject:object].ks_exists; // YES
@{}.ks_exists; // NO
@{ key: value }.ks_exists; // YES
@"".ks_exists; // NO
@"Greetings!".ks_exists; // YES
Kevin Sylvestre, [email protected]
KSReason遵循MIT许可证。更多信息请参阅LICENSE文件。