/**
testLoadPersonAsync 异步加载测试:
苹果的单元测试的特点:早期的单元测试并不好用!
1.是串行的:
1.1 先 setUp --->
然后 test1
再 test2
再 test3 ......
后 tearDown 知道真相的我眼泪掉下来.
*/
#pragma mark - testLoadPersonAsync 异步加载测试
- (void)testLoadPersonAsync {
//Xcode6.0之后进行了改进:
//创建一个"预期"expectation:
XCTestExpectation *expectation = [self expectationWithDescription:@"异步加载 Person"] ;
[Person loadPersonAsync:^(Person *person) {
NSLog(@"-_- --> %@ <-- -_-" , person.name) ;
//标注预期达成:
[expectation fulfill] ;
}] ;
//等待预期达成:
//1.0f'之内预期达成我都认为是合理的:
[self waitForExpectationsWithTimeout:1.0f handler:^(NSError * _Nullable error) {
NSLog(@"哈哈哈 --> error = %@ <-- 哈哈哈" , error) ;
}] ;
}
@end
  Person.h 文件
#import <Foundation/Foundation.h>
@interface Person : NSObject
//name:
@property (nonatomic, copy) NSString *name ;
//age:
@property (nonatomic) NSInteger age ;
//工厂方法:
+ (instancetype)personWithDictionary:(NSDictionary *)dictionary ;
//异步加载个人记录:异步加载数据回调传值都是用的 block!
//手写 block一定要注意格式: void (^) (Person *person)completion ;
+ (void)loadPersonAsync:(void (^) (Person *person))completion ;
@end
  Person.m 文件
#import "Person.h"
@implementation Person
+ (instancetype)personWithDictionary:(NSDictionary *)dictionary {
//[[self alloc] init] ;这里用 self 是方便子类继承这个方法,在搞一个 person 的子类我不用在写这个方法了!
Person *obj = [[self alloc] init] ;
//KVC 方法:
[obj setValuesForKeysWithDictionary:dictionary] ;
//为了防止单元测试时年龄非法:
if (obj.age <= 0 || obj.age > 100) {
obj.age = 0 ;
}
return obj ;
}
//写一个空方法:解决多一个 title : boss 的键值对的问题:
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
}
+ (void)loadPersonAsync:(void (^)(Person *))completion {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:1.0f] ;
Person *person = [Person personWithDictionary:@{@"name":@"lisi" , @"age":@20}] ;
dispatch_async(dispatch_get_main_queue(), ^{
//在 OC 中写块代码回调的时候一定要写块代码是否存在的判断条件,否则一出问题会闪退:
if (completion != nil) {
//回调回来person 这个对象给我:
completion(person) ;
}
}) ;
}) ;
}
@end