DRYUI 1.4.0

DRYUI 1.4.0

测试已测试
Lang语言 SwiftSwift
许可协议 MIT
发布上次发布2019年5月
SPM支持 SPM

Griffin Schneider 维护。



DRYUI 1.4.0

  • 来自
  • Griffin Schneider

DRYUI Version Build Status

DRYUI 是一个小型库,提供更好地构建和代码中样式化视图层级结构的API。DRYUI使用Masonry进行自动布局,并支持iOS和OSX。

安装

DRYUI可通过CocoaPods使用。要安装它,只需将以下行添加到您的Podfile中

pod 'DRYUI'

##层次结构构建

为了展示,让我们构建一个简单的视图层次结构,其中2个视图嵌套在self.view中。

通常构建层次结构

UIView *view1 = [UIView new];
view1.backgroundColor = [UIColor redColor];
[self.view addSubview:view1]
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(view1.superview);
}];

UIView *view2 = [UIView new];
view2.backgroundColor = [UIColor blueColor];
[view1 addSubview:view2];
[view2 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(view1);
}];

使用DRYUI构建层次结构

build_subviews(self.view) {
    UIView *add_subview(view1) {
        _.backgroundColor = [UIColor redColor];
        make.edges.equalTo(superview);
        UIView *add_subview(view2) {
            _.backgroundColor = [UIColor blueColor];
            make.edges.equalTo(superview);
        };
    };
};

####优势

  • 代码的层次结构与创建的视图层次结构相匹配 - 嵌套块直接对应嵌套子视图。
  • 减少了重复的模板 - 再也不会忘记将视图作为子视图添加。
  • 减少了复制粘贴错误的机会 - 由于_superview始终绑定到当前视图,将行从一端移动到另一端将自动使其影响它们移动到的块所在的视图。
  • 视图为你初始化 - 如果你将子视图声明为UIView,DRYUI将自动[[UIView alloc] init]它。

##样式

####基础你可以定义一个样式如下

.h文件中

dryui_public_style(RedView);

和在.m

dryui_style(RedView) {
    _.backgroundColor = [UIColor redColor];
};

现在你有一个名为RedView的样式可以应用在add_subview中的视图,如下所示

build_subviews(self.view) {
    UIView *add_subview(thisViewIsRed, RedView) {
        // thisViewIsRed is now red.
    };
};

你可以以这种方式向视图添加任意数量的样式,并将它们按添加的顺序应用。主要块在add_subview之后运行,因此可以覆盖应用过的样式。

如果你希望你的样式仅对.m文件私有,则省略dryui_public_style并在.m中使用dryui_private_style

dryui_private_style(RedView) {
    _.backgroundColor = [UIColor redColor];
};

####为特定类样式化默认情况下,样式块假定它们正在应用于UIViews。如果您想为一个UIView的子类进行样式化,只需将类名作为dryui_styledryui_public_styledryui_private_style的第二个参数添加即可。

dryui_style(RedButton, UIButton) {
    // _ is now a UIButton *
};

尝试将此样式应用于不正确的类型视图将触发编译器警告,然后是运行时异常。

####样式继承样式还支持这种简单的继承。

dryui_style(RedView) {
    _.backgroundColor = [UIColor redColor];
};
dryui_style(RedAndWhiteLabel, UILabel) {
    dryui_parent_style(RedView);
    _.textColor = [UIColor whiteColor];
};
// Now, applying the RedAndWhiteLabel style to a UILabel will give it a red background and white text.

####动态样式您可以声明具有参数的样式,您在应用样式时传递参数。语法如下

dryui_style(ColorView, UIView, (UIColor *)colorArgument) {
    _.backgroundColor = colorArgument;
};

然后,通过以下方式应用带有参数的样式

build_subviews(self.view) {
    UIView *add_subview(thisViewIsBlue, ColorView([UIColor blueColor])) {
        // thisViewIsBlue is now blue.
    };
};

请注意,即使它适用于UIView,也必须包含样式适用的类。

传递参数的方式与添加父样式或样式使用的任何地方相似

dryui_style(TextAndBackgroundColor, UILabel, (UIColor *)textColor, (UIColor *)backgroundColor) {
    dryui_parent_style(ColorView(backgroundColor));
    _.textColor = textColor;
};

####无需build_subviews的样式要在build_subviews/add_subview的上下文之外应用样式,只需调用带有要应用的视图和样式的dryui_apply_styledryui_apply_styles即可。

UIView *view = [UIView new];
dryui_apply_style(view, RedView);
UIView *view = [UIView new];
dryui_apply_styles(view, RedView, ColorView([UIColor redColor]));

##add_subview的进阶使用

add_subview接受一个变量名作为第一个参数。如果一个变量已声明,add_subview将初始化一个新的该类型对象并将其分配给该变量。如果没有声明,则在add_subview之前放置您想要的变量类型,并add_subview将声明该变量并将其分配。

add_subview可以可选地接受一个UIView的实例作为第二个参数。如果这样调用add_subview,则将那只实例分配给变量,而不是默认的[[<变量类型> alloc] init]

在第一个(可选的第二个)参数之后,可以向add_subview传递一个样式列表,以将所有给定的样式应用于该视图。

以下是一些示例

__block UIButton *secondButton, *thirdButton;
build_subviews(self) {
    UIButton *add_subview(firstButton) {};
    // The above line is equivalent to:
    //     UIButton *firstButton = [[UIButton alloc] init]; 
    //     [_ addSubview:firstButton];
    
    add_subview(secondButton) {};
    // secondButton has already been declared, to this is equivalent to:
    //     secondButton = [[UIButton alloc] init];
    //     [_ addSubview:secondButton];
    
    thirdButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    add_subview(thirdButton) {};
    // thirdButton has already been assigned, so this just does:
    //    [_ addSubview:thirdButton];
    
    UIButton *add_subview(fourthButton, [UIButton buttonWithType:UIButtonTypeSystem]) {};
    // The second argument to add_subview is a view instance, so we'll use it for assignment
    // instead of the default alloc init:
    //     UIButton *fourthButton = [UIButton buttonWithType:UIButtonTypeSystem];
    //     [_ addSubview:fourthButton];
    
    UIButton *add_subview(fifthButton, RedView, RedButton) {};
    // Simple style application - this will create a new button named fifthButton and
    // apply the RedView and RedButton styles to it.
    
    UIButton *add_subview(sixthButton, [UIButton buttonWithType:UIButtonTypeSystem], RedView, RedButton) {};
    // Style application with a custom view instance - add_subview can detect that its second argument
    // is a custom view instance instead of a style, so this will do:
    //     UIButton *sixthButton = [UIButton buttonWithType:UIButtonTypeSystem];
    //     [_ addSubview:sixthButton];
    // and then add the RedView and RedButton styles to sixthButton.
};

add_subview 的每次调用都会将指定的视图作为子视图添加到 build_subviewsadd_subview 的最近嵌套调用传递的视图中。视图顺序将根据它们的 add_subview 调用顺序确定。

add_subview 的调用必须在 build_subviews 的调用内部进行。build_subviews 不会将给定的视图作为子视图添加到任何其他地方。

add_subview 宏后的块中,_ 指的是给定的视图,而 superview 指的是该视图的父视图。make 被设置为给定视图的 MASConstraintMaker,类似于传递给 Masonry 的 mas_makeConstraints: 方法传入的块。