UberBuilder 1.0.1

UberBuilder 1.0.1

Patrick HoganUberAlan Zeino维护。



  • Uber iOS团队

UberBuilder

什么是UberBuilder?

UberBuilder提供了一系列便捷方法,用于简化构建灵活、不可变对象的任务。

要求

  • iOS 7.0+ / Mac OS X 10.10+
  • Xcode 6.0
  • Cocoapods 0.37.1

Cocoapods安装

  1. 将UberBuilder作为一行添加到您的Podfile中 pod 'UberBuilder/Core', '~> 1.0'
  2. 运行pod install
  3. #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类的实现应包含一个扩展,该扩展符合UBBuildableContainerBuilder协议。必须合成的每个属性都必须从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));
}