Chain programming thought chain programming is what
Chained programming is to connect calls to multiple methods using DOT syntax to make the code more concise and more readable
First Contact chain programming is masonry, it's really cool to use.
1 |
Make.left.right.top.equalTo (Self.view); |
4 methods are called in such a sentence
. Left invokes the Get method
. Right,. Top Call the right and top methods
. Equalto () called the Equalto method
This notation greatly simplifies the way writing constraints
Principle
The principle is that the type of the property being called or the return type of the method is the type of the original invocation property
For example, UILabel
if you call a method or property, and the resulting type is uilabel, you can continue to call Uilabel's properties or methods
How to Achieve
Looking at masonry, I found that there are two ways to achieve this.
1. Calling methods with dot syntax
Actually, I didn't find it before, and I wrote it. Calling methods with square brackets
For example, create a label that you can writeUILabel *label = [[UILabel alloc] init
You can actually write it like this.UILabel *label = UILabel.alloc.init
However, the latter method is almost useless, and Apple should not recommend this type of writing, because sometimes this is no code hint
But one drawback is that you can't call a method with parameters, so we can only write methods that don't have parameters.
To create a UIButton category
Write a two-way
1 2 |
-(UIButton *) Settexthello; -(UIButton *) settextcolorred; |
and achieve
1 2 3 4 5 6 7 8 9 10 11 |
-(UIButton *) settextcolorred { [Self Settitlecolor:[uicolor redcolor] forstate:uicontrolstatenormal]; return self; }
-(UIButton *) setimage { [Self setimage:[uiimage imagenamed:@ "Stan1"] forstate:uicontrolstatenormal]; return self; } |
And then we create a button and we can write it like this.
1 2 3 4 5 |
Create a button UIButton *button = [UIButton buttonwithtype:uibuttontypeinfolight]; Button.frame = CGRectMake (100, 100, 100, 100); button.setTextHello.setTextColorRed; [Self.view Addsubview:button]; |
Effect
However, a warning is reported because the property is called, but this property is not used
The workaround is to precede the call property (void)
, so that you can
2. Calling with attributes
Create a new category for Uilabel
If you want to pass in a parameter, return a Uilabel block that implements what you want to achieve in the block.
1 2 3 |
@property (nonatomic,copy) uilabel* (^ktext) (NSString *text); @property (nonatomic,copy) uilabel* (^kfont) (Nsuinteger fontSize); @property (nonatomic,copy) uilabel* (^ktextcolor) (Uicolor *color); |
Plus k is for easy to distinguish, can not add
Because this is the attribute in the classification, the setter and getter methods are not generated, so you have to write your own
Implemented as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st 22 23 24 25 26 27 |
-(UILabel * (^) (Nsuinteger)) Kfont { return ^ (Nsuinteger font) { [Self Setfont:[uifont systemfontofsize:font]]; return self; }; }
-(UILabel * (^) (NSString *)) Ktext { return ^ (NSString *text) { [Self settext:text]; return self; }; }
-(UILabel * (^) (Uicolor *)) Ktextcolor { return ^ (Uicolor *color) { [Self settextcolor:color]; return self; }; }
-(void) Setkfont: (UILabel * (^) (Nsuinteger)) kfont{} -(void) Setktext: (UILabel * (^) (NSString *)) ktext{} -(void) Setktextcolor: (UILabel * (^) (Uicolor *)) ktextcolor{} |
The setter method is not used and cannot be used, so the setter method is set to null
And then you can happily chain-program it.
And then I thought, if there were no parameters, I was just beginning to think that block had no parameters.
1 2 3 |
@property (nonatomic,copy) uilabel* (^atext) (); @property (nonatomic,copy) uilabel* (^afont) (); @property (nonatomic,copy) uilabel* (^atextcolor) (); |
Realize
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st 22 23 24 25 26 27 |
-(UILabel * (^) ()) Afont { return ^ () { [Self Setfont:[uifont systemfontofsize:16.0f]]; return self; }; }
-(UILabel * (^) ()) Atextcolor { return ^ () { [Self Settextcolor:[uicolor cyancolor]]; return self; }; }
-(UILabel * (^) ()) Atext { return ^ () { [Self settext:@ "This is still a label"]; return self; }; }
-(void) Setafont: (UILabel * (^) ()) afont{} -(void) Setatext: (UILabel * (^) ()) atext{} -(void) Setatextcolor: (UILabel * (^) ()) atextcolor{} |
And then I found out the call was going to be this way.
Try, the last call can remove the parentheses, the warning, can run, but no effect
So I guess why not call properties directly
1 2 3 |
@property (Nonatomic,strong) UILabel *btext; @property (Nonatomic,strong) UILabel *bfont; @property (Nonatomic,strong) UILabel *btextcolor; |
Getter && Setter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st |
-(UILabel *) Btext { [Self settext:@ "Labellabel"]; return self; }
-(UILabel *) Btextcolor { [Self Settextcolor:[uicolor purplecolor]]; return self; }
-(UILabel *) Bfont { [Self Setfont:[uifont systemfontofsize:13.0f]]; return self; }
-(void) Setbfont: (UILabel *) bfont{} -(void) Setbtext: (UILabel *) btext{} -(void) Setbtextcolor: (UILabel *) btextcolor{} |
Call
1 2 3 |
UILabel *label3 = [[UILabel alloc] Initwithframe:cgrectmake (100, 400, 200, 100)]; (void) Label3.bTextColor.bText.bFont; [Self.view Addsubview:label3]; |
If the call does not add (void) or a warning is reported
If you imagine a chain programming like masonry, you can write that.
1 2 3 |
UILabel *label3 = [[UILabel alloc] Initwithframe:cgrectmake (100, 400, 200, 100)]; Label3.bTextColor.bText.kFont (30); [Self.view Addsubview:label3]; |
So you don't report a warning, neat and clear.
Also posted on my personal blog
The idea of OBJECTIVE-C chain-type programming