UberBuilder提供了一系列便捷方法,用于简化构建灵活、不可变对象的任务。
- iOS 7.0+ / Mac OS X 10.10+
- Xcode 6.0
- Cocoapods 0.37.1
- 将UberBuilder作为一行添加到您的Podfile中
pod 'UberBuilder/Core', '~> 1.0'
- 运行
pod install
- 将
#import <UberBuilder/UBBuilder.h>
添加到您希望使用它的文件中。
以下我们定义一个具有只读属性的可构建的Container
类,它旨在通过[Container build:]
方法创建。
// Container.h
#import <UIKit/UIKit.h>
typedef void (^BlockType)();
@protocol Container <NSObject>
@property (nonatomic, readonly, copy) NSString *string;
@property (nonatomic, readonly) NSNumber *number;
@property (nonatomic, readonly, copy) NSArray *array;
@property (nonatomic, readonly, copy) BlockType block;
@property (nonatomic, readonly) UIEdgeInsets edgeInsets;
@end
@protocol ContainerBuilder <NSObject>
@property (nonatomic, copy) NSString *string;
@property (nonatomic) NSNumber *number;
@property (nonatomic, copy) NSArray *array;
@property (nonatomic, copy) BlockType block;
@property (nonatomic) UIEdgeInsets edgeInsets;
@end
@interface Container : NSObject <Container>
@property (nonatomic, readonly) BOOL didAwakeFromBuilder;
+ (instancetype)build:(void (^)(id <ContainerBuilder>))builder;
+ (instancetype)copy:(Container *)buildable builder:(void (^)(id <ContainerBuilder>))builder;
@end
需要注意的是,Container
类公开符合只读的Container
协议。暴露了ContainerBuilder
协议,以便在[Container build:]
和[Container copy:builder:]
方法中设置builder
属性。
Container
类的实现应包含一个扩展,该扩展符合UBBuildable
和ContainerBuilder
协议。必须合成的每个属性都必须从builder
协议中生成。
#import "Container.h"
#import <UberBuilder/UBBuilder.h>
@interface Container () <UBBuildable, ContainerBuilder>
@end
@implementation Container
@synthesize string = _string;
@synthesize number = _number;
@synthesize array = _array;
@synthesize block = _block;
@synthesize edgeInsets = _edgeInsets;
#pragma mark - Constructor
- (instancetype)init {
self = [super init];
if (self) {
// Set default values here, if desired
self.array = @[];
}
return self;
}
#pragma mark - UBBuilder
+ (instancetype)build:(void (^)(id <ContainerBuilder>))builder
{
return [UBBuilder build:self builder:builder];
}
+ (instancetype)copy:(Container *)buildable builder:(void (^)(id <ContainerBuilder>))builder
{
return [UBBuilder copy:buildable class:self builderProtocol:@protocol(ContainerBuilder) builder:builder];
}
#pragma mark - UBBuildable
- (void)ub_awakeFromBuilder
{
// Take some action post-build. For example, perform validation, ensure required parameters are set, etc...
NSParameterAssert(self.array);
}
@end
builder
方法只是将转发调用到[UBBuilder build:builder]
和[UBBuilder copy:class:builderProtocol:builder:]
方法。
在实际练习中,我们创建一个Container
实例,并可以自由分配我们选择的任何组合的组合属性。在对象创建后,没有公开的mutator,用户不能使用runtime进行更改。
- (void)testCopyBuildable
{
Container *buildable = [Container build:^(id <ContainerBuilder> builder) {
builder.string = @"Test";
builder.number = @237;
builder.block = ^{};
builder.edgeInsets = UIEdgeInsetsMake(0.0, 1.0, 2.0, 3.0);
}];
Container *buildableCopy = [Container copy:buildable builder:nil];
XCTAssertEqualObjects(buildable.string, buildableCopy.string);
XCTAssertEqualObjects(buildable.number, buildableCopy.number);
XCTAssertEqualObjects(buildable.array, buildableCopy.array);
XCTAssertEqualObjects(buildable.block, buildableCopy.block);
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(buildable.edgeInsets, buildableCopy.edgeInsets));
}