├── .gitignore ├── Classes ├── STMAssembleMaker.h ├── STMAssembleMaker.m ├── STMAssembleView.h ├── STMAssembleView.m ├── STMPartMaker.h ├── STMPartMaker.m ├── STMPartView.h └── STMPartView.m ├── LICENSE ├── Podfile ├── README.md ├── STMAssembleView.podspec ├── STMAssembleView.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── STMAssembleView ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json ├── Contents.json ├── avatar.imageset │ ├── 1-1.jpeg │ ├── 1-2.jpeg │ ├── 1.jpeg │ └── Contents.json └── starmingicon.imageset │ ├── 64height-1.png │ ├── 64height-2.png │ ├── 64height.png │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m ├── as.png ├── asExample.asv ├── center.png ├── des.png ├── followBt.png ├── main.m └── mid.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | Pods/ 38 | STMAssembleView.xcworkspace/ 39 | Podfile.lock 40 | 41 | # Carthage 42 | # 43 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 44 | # Carthage/Checkouts 45 | 46 | Carthage/Build 47 | 48 | # fastlane 49 | # 50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 51 | # screenshots whenever they are needed. 52 | # For more information about the recommended setup visit: 53 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 54 | 55 | fastlane/report.xml 56 | fastlane/screenshots 57 | 58 | #Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /Classes/STMAssembleMaker.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMAssembleMaker.h 3 | // HomePageTest 4 | // 5 | // Created by DaiMing on 16/5/31. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "STMPartView.h" 11 | 12 | @class STMAssembleView; 13 | 14 | typedef NS_ENUM(NSUInteger, STMAssembleAlignment) { 15 | STMAssembleAlignmentCenter, 16 | STMAssembleAlignmentLeft, 17 | STMAssembleAlignmentRight, 18 | STMAssembleAlignmentTop, 19 | STMAssembleAlignmentBottom 20 | }; 21 | typedef NS_ENUM(NSUInteger, STMAssembleArrange) { 22 | STMAssembleArrangeHorizontal, 23 | STMAssembleArrangeVertical 24 | }; 25 | 26 | typedef void(^ParsingFormatStringCompleteBlock)(STMAssembleView *asView); 27 | 28 | @interface STMAssembleMaker : NSObject 29 | //属性 30 | @property (nonatomic, strong) NSMutableArray *subViews; //存放所有子视图 31 | @property (nonatomic) CGFloat padding; //间隔距离 32 | @property (nonatomic) STMAssembleAlignment alignment; //对齐 33 | @property (nonatomic) STMAssembleArrange arrange; //水平还是垂直排列 34 | @property (nonatomic) NSUInteger extendWith; //由第几个PartView来撑开AssembleView的大小 35 | @property (nonatomic, copy) ParsingFormatStringCompleteBlock parsingCompletion; 36 | 37 | 38 | //方法 39 | - (STMAssembleMaker *(^)(STMAssembleView *))addAssembleView; 40 | - (STMAssembleMaker *(^)(STMPartView *))addPartView; 41 | - (STMAssembleMaker *(^)(UIView *))addView; 42 | 43 | - (STMAssembleMaker *(^)(CGFloat))paddingEqualTo; 44 | - (STMAssembleMaker *(^)(STMAssembleAlignment))alignmentEqualTo; 45 | - (STMAssembleMaker *(^)(STMAssembleArrange))arrangeEqualTo; 46 | - (STMAssembleMaker *(^)(NSUInteger))extendWithEqualTo; 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Classes/STMAssembleMaker.m: -------------------------------------------------------------------------------- 1 | // 2 | // STMAssembleMaker.m 3 | // HomePageTest 4 | // 5 | // Created by DaiMing on 16/5/31. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import "STMAssembleMaker.h" 10 | 11 | #import "STMAssembleView.h" 12 | 13 | @implementation STMAssembleMaker 14 | 15 | - (STMAssembleMaker *(^)(STMAssembleView *))addAssembleView { 16 | return ^STMAssembleMaker *(STMAssembleView *view) { 17 | [self.subViews addObject:view]; 18 | return self; 19 | }; 20 | } 21 | - (STMAssembleMaker *(^)(STMPartView *))addPartView { 22 | return ^STMAssembleMaker *(STMPartView *view) { 23 | [self.subViews addObject:view]; 24 | return self; 25 | }; 26 | } 27 | - (STMAssembleMaker *(^)(UIView *))addView { 28 | return ^STMAssembleMaker *(UIView *view) { 29 | [self.subViews addObject:view]; 30 | return self; 31 | }; 32 | } 33 | - (STMAssembleMaker *(^)(CGFloat))paddingEqualTo { 34 | return ^STMAssembleMaker *(CGFloat value) { 35 | self.padding = value; 36 | return self; 37 | }; 38 | } 39 | - (STMAssembleMaker *(^)(STMAssembleAlignment))alignmentEqualTo { 40 | return ^STMAssembleMaker *(STMAssembleAlignment alignment) { 41 | self.alignment = alignment; 42 | return self; 43 | }; 44 | } 45 | - (STMAssembleMaker *(^)(STMAssembleArrange))arrangeEqualTo { 46 | return ^STMAssembleMaker *(STMAssembleArrange arrange) { 47 | self.arrange = arrange; 48 | return self; 49 | }; 50 | } 51 | - (STMAssembleMaker *(^)(NSUInteger))extendWithEqualTo { 52 | return ^STMAssembleMaker *(NSUInteger num) { 53 | self.extendWith = num; 54 | return self; 55 | }; 56 | } 57 | 58 | 59 | #pragma mark - Getter 60 | - (NSMutableArray *)subViews { 61 | if (!_subViews) { 62 | _subViews = [NSMutableArray array]; 63 | } 64 | return _subViews; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Classes/STMAssembleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMAssembleView.h 3 | // HomePageTest 4 | // 5 | // Created by DaiMing on 16/4/15. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "STMAssembleMaker.h" 11 | @class STMPartView; 12 | 13 | @interface STMAssembleView : UIView 14 | 15 | @property (nonatomic, strong, readonly) STMAssembleMaker *maker; 16 | 17 | + (STMAssembleView *)createView:(void(^)(STMAssembleMaker *make))assembleMaker; 18 | 19 | //主线程使用格式化字符串创建AssembleView 20 | + (STMAssembleView *)fs:(NSString *)string objects:(NSDictionary *)objs; 21 | //异步线程格式化字符串,内部实现异步处理,外部需要父视图或类持有string和objs,如果在方法栈里设置的话string和objs在异步还没开始执行前出栈时会被释放。 22 | + (void)fsAsync:(NSString *)string objects:(NSDictionary *)objs completion:(ParsingFormatStringCompleteBlock)completeBlock; 23 | //提供可异步操作回调主线程block,内部没实现异步处理,需要在外部进行。 24 | + (STMAssembleView *)createViewWithFormatString:(NSString *)string objects:(NSDictionary *)objs completion:(ParsingFormatStringCompleteBlock)completeBlock; 25 | 26 | //简化NSString的format 27 | FOUNDATION_EXPORT NSString *ASS(NSString *format, ...) NS_FORMAT_FUNCTION(1,2); 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Classes/STMAssembleView.m: -------------------------------------------------------------------------------- 1 | // 2 | // STMAssembleView.m 3 | // HomePageTest 4 | // 5 | // Created by DaiMing on 16/4/15. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import "STMAssembleView.h" 10 | 11 | #import "Masonry.h" 12 | #import "STMPartView.h" 13 | #import 14 | @interface STMAssembleView() 15 | 16 | @property (nonatomic, strong) STMAssembleMaker *maker; 17 | 18 | @end 19 | 20 | @implementation STMAssembleView 21 | 22 | 23 | /*-------------创建Assemble View------------*/ 24 | + (STMAssembleView *)createView:(void(^)(STMAssembleMaker *))assembleMaker { 25 | STMAssembleView *assembleView = [[self alloc] init]; 26 | assembleView.maker = [[STMAssembleMaker alloc] init]; 27 | assembleMaker(assembleView.maker); 28 | assembleView = [assembleView buildAssembleView]; 29 | return assembleView; 30 | } 31 | - (STMAssembleView *)buildAssembleView{ 32 | STMAssembleMaker *assembleMaker = self.maker; 33 | if (!(assembleMaker.subViews.count > 0)) { 34 | return self; 35 | } 36 | 37 | UIView __block *lastView = nil; 38 | NSUInteger i = 0; 39 | NSUInteger count = assembleMaker.subViews.count; 40 | for (id x in assembleMaker.subViews) { 41 | UIView *xView = nil; 42 | STMPartView *partView = nil; 43 | if ([x isKindOfClass:[STMPartView class]]) { 44 | partView = (STMPartView *)x; 45 | xView = partView.maker.view; 46 | } else { 47 | xView = (UIView *)x; 48 | } 49 | [self addSubview:xView]; 50 | //设置权重 51 | if (partView.maker.CRpriority != STMPriorityDefault) { 52 | switch (partView.maker.CRpriority) { 53 | case STMPriorityFittingSizeLevel: 54 | [xView setContentCompressionResistancePriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal]; 55 | break; 56 | case STMPriorityDefaultLow: 57 | [xView setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal]; 58 | break; 59 | case STMPriorityDefaultHigh: 60 | [xView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; 61 | break; 62 | case STMPriorityRequired: 63 | [xView setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; 64 | break; 65 | default: 66 | break; 67 | } 68 | } 69 | 70 | //设置布局约束 71 | [xView mas_makeConstraints:^(MASConstraintMaker *make) { 72 | //通用情况处理 73 | CGFloat xViewPadding = assembleMaker.padding; 74 | if ([x isKindOfClass:[STMAssembleView class]]) { 75 | // 76 | } else if([x isKindOfClass:[STMPartView class]]) { 77 | //大小 78 | if (partView.maker.size.width > 0) { 79 | make.width.mas_equalTo(partView.maker.size.width); 80 | } 81 | if (partView.maker.size.height > 0) { 82 | make.height.mas_equalTo(partView.maker.size.height); 83 | } 84 | //根据排列方式是否填充满,如果设置填充,对应的宽高需要设置为0 85 | if (partView.maker.isFill) { 86 | if (assembleMaker.arrange == STMAssembleArrangeHorizontal) { 87 | make.height.equalTo(self); 88 | } else if (assembleMaker.arrange == STMAssembleArrangeVertical) { 89 | make.width.equalTo(self); 90 | } 91 | } 92 | //间隔Padding的设置 93 | if (partView.maker.padding != 0) { 94 | xViewPadding = partView.maker.padding; 95 | } 96 | } 97 | 98 | CGFloat partViewMarginOffset = 0; //对齐时的partView设置的间距 99 | if (partView.maker.alignmentMargin > 0) { 100 | partViewMarginOffset = partView.maker.alignmentMargin; 101 | } 102 | //排序设置 103 | if (assembleMaker.arrange == STMAssembleArrangeHorizontal) { 104 | BOOL hNeedAsAlignment = YES; //是否需要assemble配置 105 | //水平情况 106 | if (partView.maker.partAlignment != STMPartAlignmentDefault) { 107 | //如果有PartView自定义布局的情况 108 | hNeedAsAlignment = NO; 109 | if (partView.maker.partAlignment == STMPartAlignmentCenter) { 110 | make.centerY.equalTo(self).offset(partViewMarginOffset); 111 | } else if (partView.maker.partAlignment == STMPartAlignmentTop) { 112 | make.top.equalTo(self).offset(partViewMarginOffset); 113 | } else if (partView.maker.partAlignment == STMPartAlignmentBottom) { 114 | make.bottom.equalTo(self).offset(partViewMarginOffset); 115 | } else if (partView.maker.partAlignment == STMPartAlignmentLeft) { 116 | //在只有一个视图,或者这一个part视图是assemble的情况 117 | make.left.equalTo(self).offset(partViewMarginOffset); 118 | hNeedAsAlignment = YES; 119 | } else if (partView.maker.partAlignment == STMPartAlignmentRight) { 120 | //在只有一个视图,或者这一个part视图是assemble的情况 121 | hNeedAsAlignment = YES; 122 | make.right.equalTo(self).offset(partViewMarginOffset); 123 | } 124 | } 125 | if (hNeedAsAlignment) { 126 | //需要按照assemble maker来配置的情况 127 | if (assembleMaker.alignment == STMAssembleAlignmentCenter) { 128 | make.centerY.equalTo(self); 129 | } else if (assembleMaker.alignment == STMAssembleAlignmentTop) { 130 | make.top.equalTo(self); 131 | } else if (assembleMaker.alignment == STMAssembleAlignmentBottom) { 132 | make.bottom.equalTo(self); 133 | } 134 | } 135 | //由内部撑大AssembleView 136 | if (assembleMaker.extendWith == i + 1) { 137 | make.top.equalTo(self); 138 | make.bottom.equalTo(self); 139 | } 140 | 141 | if (partView.maker.ignoreAlignment == STMPartAlignmentLeft) { 142 | //如果设置忽略左约束就不设置左约束 143 | } else { 144 | make.left.equalTo(lastView ? lastView.mas_right : self.mas_left).offset(lastView ? xViewPadding : 0); 145 | } 146 | //最后一个元素 147 | if (i == count - 1) { 148 | make.right.equalTo(self.mas_right); 149 | } 150 | //lessThanOrEqualTo和greaterThanOrEqualTo的设置 151 | if (partView.maker.minWidth > 0) { 152 | make.width.greaterThanOrEqualTo(@(partView.maker.minWidth)); 153 | } 154 | if (partView.maker.maxWidth > 0) { 155 | make.width.lessThanOrEqualTo(@(partView.maker.maxWidth)); 156 | } 157 | 158 | } else if (assembleMaker.arrange == STMAssembleArrangeVertical) { 159 | //垂直情况 160 | if (partView.maker.partAlignment != STMPartAlignmentDefault) { 161 | //如果有PartView自定义布局的情况 162 | if (partView.maker.partAlignment == STMPartAlignmentCenter) { 163 | make.centerX.equalTo(self).offset(partViewMarginOffset); 164 | } else if (partView.maker.partAlignment == STMPartAlignmentLeft) { 165 | make.left.equalTo(self).offset(partViewMarginOffset); 166 | } else if (partView.maker.partAlignment == STMPartAlignmentRight) { 167 | make.right.equalTo(self).offset(partViewMarginOffset); 168 | } else if (partView.maker.partAlignment == STMPartAlignmentTop) { 169 | make.top.equalTo(self).offset(partViewMarginOffset); 170 | } else if (partView.maker.partAlignment == STMPartAlignmentBottom) { 171 | make.bottom.equalTo(self).offset(partViewMarginOffset); 172 | } 173 | } else { 174 | //按Assemble View的maker设置来 175 | if (assembleMaker.alignment == STMAssembleAlignmentCenter) { 176 | make.centerX.equalTo(self); 177 | } else if (assembleMaker.alignment == STMAssembleAlignmentLeft) { 178 | make.left.equalTo(self); 179 | } else if (assembleMaker.alignment == STMAssembleAlignmentRight) { 180 | make.right.equalTo(self); 181 | } 182 | } 183 | //由内部撑大AssembleView 184 | if (assembleMaker.extendWith == i + 1) { 185 | make.left.equalTo(self); 186 | make.right.equalTo(self); 187 | } 188 | 189 | make.right.lessThanOrEqualTo(self); 190 | 191 | if (partView.maker.ignoreAlignment == STMPartAlignmentTop) { 192 | //如果设置忽略上约束就不设置上约束 193 | } else { 194 | make.top.equalTo(lastView ? lastView.mas_bottom : self.mas_top).offset(lastView ? xViewPadding : 0); 195 | } 196 | 197 | if (i == count - 1) { 198 | make.bottom.equalTo(self.mas_bottom); 199 | } 200 | } 201 | 202 | 203 | }]; 204 | 205 | lastView = xView; 206 | i++; 207 | } 208 | if (assembleMaker.parsingCompletion) { 209 | assembleMaker.parsingCompletion(self); 210 | } 211 | return self; 212 | } 213 | 214 | /*-------------格式化字符串创建Part View----------------*/ 215 | + (STMAssembleView *)fs:(NSString *)string objects:(NSDictionary *)objs { 216 | return [STMAssembleView createViewWithFormatString:string objects:objs completion:nil]; 217 | } 218 | 219 | + (void)fsAsync:(NSString *)string objects:(NSDictionary *)objs completion:(ParsingFormatStringCompleteBlock)completeBlock{ 220 | __weak __typeof(string) weakString = string; 221 | __weak __typeof(objs) weakObjs = objs; 222 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 223 | __strong __typeof(weakString) strongString = weakString; 224 | __strong __typeof(weakObjs) strongObjs = weakObjs; 225 | if (strongString) { 226 | [STMAssembleView createViewWithFormatString:strongString objects:strongObjs completion:completeBlock]; 227 | } 228 | }); 229 | } 230 | 231 | + (STMAssembleView *)createViewWithFormatString:(NSString *)string objects:(NSDictionary *)objs completion:(ParsingFormatStringCompleteBlock)completeBlock { 232 | //根据格式化字符串来 233 | NSScanner *scanner = [NSScanner scannerWithString:string]; 234 | scanner.charactersToBeSkipped = [NSCharacterSet whitespaceAndNewlineCharacterSet]; //跳过换行和空格 235 | NSMutableArray *tokens = [NSMutableArray array]; 236 | NSMutableCharacterSet *mCSet = [NSMutableCharacterSet alphanumericCharacterSet]; 237 | [mCSet addCharactersInString:@"./|?!$%#-+_&:“”。,《》!"]; 238 | //下一步需要做个特殊字符串映射对应关系,比如说属性的值里需要“:”这个符号和关键符号冲突了就需要通过映射表来处理 239 | while (!scanner.isAtEnd) { 240 | for (NSString *operator in @[@"(",@")",@":",@",",@"[",@"]",@"{",@"}",@"<",@">"]) { 241 | if ([scanner scanString:operator intoString:NULL]) { 242 | [tokens addObject:operator]; 243 | } 244 | NSString *result = nil; 245 | if ([scanner scanCharactersFromSet:mCSet intoString:&result]) { 246 | [tokens addObject:result]; 247 | } 248 | } 249 | } 250 | if (completeBlock) { 251 | dispatch_async(dispatch_get_main_queue(),^{ 252 | NSArray *strongTokens = tokens; 253 | NSDictionary *strongObjs = objs; 254 | if ([strongTokens isKindOfClass:[NSArray class]]) { 255 | if (strongTokens.count > 0) { 256 | [STMAssembleView createViewWithFormatArray:strongTokens objects:strongObjs completion:completeBlock]; 257 | } 258 | } 259 | }); 260 | return [[STMAssembleView alloc] init]; 261 | } else { 262 | return [STMAssembleView createViewWithFormatArray:tokens objects:objs completion:completeBlock]; 263 | } 264 | 265 | 266 | } 267 | 268 | + (STMAssembleView *)createViewWithFormatArray:(NSArray *)array objects:(NSDictionary *)objs completion:(ParsingFormatStringCompleteBlock)completeBlock { 269 | STMAssembleView *asView = [STMAssembleView createView:^(STMAssembleMaker *make) { 270 | if (completeBlock) { 271 | make.parsingCompletion = completeBlock; 272 | } else { 273 | make.parsingCompletion = nil; 274 | } 275 | 276 | NSMutableArray *asPropertyArray = [NSMutableArray array]; //asView的属性array 277 | NSMutableArray *partsArray = [NSMutableArray array]; //用来装所有partView的array的array,二级array 278 | NSMutableArray *partArray = [NSMutableArray array]; //单个partView的array 279 | 280 | BOOL isParsingAssembleProperty = NO; //正在处理assemble的属性 281 | BOOL isParsingPart = NO; //正在处理part view 282 | BOOL isParsingPartContainAssemble = NO; //正在处理part view里包含assemble的情况 283 | NSInteger PCAcount = 0; //part view里包含assemble对层级的计数,当为0时判断为解析结束 284 | NSUInteger i = 0; 285 | for (NSString *token in array) { 286 | //校验是否是合适的assemble view字符串 287 | if (i == 0) { 288 | if ([token isEqualToString:@"{"]) { 289 | i++; 290 | continue; 291 | } else { 292 | break; 293 | } 294 | } 295 | //处理排序方向和对齐方向 296 | if (i == 1 && token.length == 2) { 297 | NSString *arrangeStr = [token substringWithRange:NSMakeRange(0, 1)]; 298 | NSString *alignmentStr = [token substringWithRange:NSMakeRange(1, 1)]; 299 | if ([arrangeStr isEqualToString:@"v"]) { 300 | make.arrangeEqualTo(STMAssembleArrangeVertical); 301 | } 302 | if ([arrangeStr isEqualToString:@"h"]) { 303 | make.arrangeEqualTo(STMAssembleArrangeHorizontal); 304 | } 305 | if ([alignmentStr isEqualToString:@"c"]) { 306 | make.alignmentEqualTo(STMAssembleAlignmentCenter); 307 | } 308 | if ([alignmentStr isEqualToString:@"l"]) { 309 | make.alignmentEqualTo(STMAssembleAlignmentLeft); 310 | } 311 | if ([alignmentStr isEqualToString:@"r"]) { 312 | make.alignmentEqualTo(STMAssembleAlignmentRight); 313 | } 314 | if ([alignmentStr isEqualToString:@"t"]) { 315 | make.alignmentEqualTo(STMAssembleAlignmentTop); 316 | } 317 | if ([alignmentStr isEqualToString:@"b"]) { 318 | make.alignmentEqualTo(STMAssembleAlignmentBottom); 319 | } 320 | } 321 | //--------处理assemble view的属性--------- 322 | if (i == 2 && [token isEqualToString:@"("]) { 323 | isParsingAssembleProperty = YES; 324 | } 325 | //灌数组 326 | if (isParsingAssembleProperty) { 327 | if ([token isEqualToString:@"("] || [token isEqualToString:@")"]) { 328 | //对应的()符号不用灌 329 | } else { 330 | [asPropertyArray addObject:token]; 331 | } 332 | } 333 | //结束处理assemble view的属性 334 | if (isParsingAssembleProperty && [token isEqualToString:@")"]) { 335 | isParsingAssembleProperty = NO; 336 | } 337 | 338 | //--------处理part view--------- 339 | if ([token isEqualToString:@"["]) { 340 | isParsingPart = YES; 341 | } 342 | //灌数组 343 | if (isParsingPart) { 344 | if ([token isEqualToString:@"{"]) { 345 | isParsingPartContainAssemble = YES; 346 | PCAcount += 1; 347 | } 348 | if ([token isEqualToString:@"}"]) { 349 | PCAcount -= 1; 350 | if (PCAcount == 0) { 351 | //这时assemble view的灌结束 352 | isParsingPartContainAssemble = NO; 353 | } 354 | } 355 | 356 | if (([token isEqualToString:@"["] || [token isEqualToString:@"]"]) && !isParsingPartContainAssemble) { 357 | //对应的[]符号不用灌 358 | } else { 359 | [partArray addObject:token]; 360 | } 361 | } 362 | //结束处理part view 363 | if (isParsingPart && [token isEqualToString:@"]"] && !isParsingPartContainAssemble) { 364 | [partsArray addObject:partArray]; 365 | partArray = [NSMutableArray array]; 366 | isParsingPart = NO; 367 | } 368 | 369 | i++; 370 | } 371 | 372 | //遍历解析到的assemble view的属性 373 | NSMutableDictionary *keyValueProperty = [STMAssembleView parsingPropertyFormatArray:asPropertyArray objects:objs]; 374 | NSArray *keys = [keyValueProperty allKeys]; 375 | for (NSString *key in keys) { 376 | if ([key isEqualToString:@"padding"]) { 377 | make.paddingEqualTo([keyValueProperty[key] floatValue]); 378 | } 379 | if ([key isEqualToString:@"extendWith"]) { 380 | make.extendWithEqualTo([keyValueProperty[key] floatValue]); 381 | } 382 | } 383 | 384 | //part view解析 385 | for (NSMutableArray *part in partsArray) { 386 | make.addPartView([STMAssembleView createPartViewWithFormatArray:part objects:objs]); 387 | } 388 | 389 | 390 | }]; 391 | return asView; 392 | } 393 | /*-------------格式化字符串创建Part View----------------*/ 394 | + (STMPartView *)createPartViewWithFormatArray:(NSMutableArray *)array objects:(NSDictionary *)objs { 395 | return [STMPartView createView:^(STMPartMaker *make) { 396 | NSArray *allObjKeys = objs.allKeys; 397 | 398 | NSMutableArray *propertyArray = [NSMutableArray array]; //属性 399 | NSMutableArray *asArray = [NSMutableArray array]; //assemble view 400 | 401 | BOOL isParsingProperty = NO; //正在处理属性 402 | BOOL isParsingAssemble = NO; //正在处理assemble view数组 403 | NSInteger PCAcount = 0; //part view里包含assemble对层级的计数,当为0时判断为解析结束 404 | 405 | NSUInteger i = 0; 406 | 407 | for (NSString *token in array) { 408 | //处理assemble view 409 | if ([token isEqualToString:@"{"]) { 410 | isParsingAssemble = YES; 411 | PCAcount += 1; 412 | } 413 | if (isParsingAssemble) { 414 | [asArray addObject:token]; 415 | } 416 | if ([token isEqualToString:@"}"]) { 417 | PCAcount -= 1; 418 | if (PCAcount == 0) { 419 | //as的处理结束 420 | isParsingAssemble = NO; 421 | } 422 | } 423 | 424 | //处理property 425 | if ([token isEqualToString:@"("] && !isParsingAssemble) { 426 | isParsingProperty = YES; 427 | } 428 | if (isParsingProperty) { 429 | if ([token isEqualToString:@"("] || [token isEqualToString:@")"]) { 430 | //这里就不用记录这两个符号了 431 | } else { 432 | [propertyArray addObject:token]; 433 | } 434 | } 435 | if ([token isEqualToString:@")"] && !isParsingAssemble) { 436 | isParsingProperty = NO; 437 | } 438 | 439 | //处理自定义视图 440 | if (!isParsingProperty && !isParsingAssemble) { 441 | for (NSString *objKey in allObjKeys) { 442 | if ([objKey isEqualToString:token]) { 443 | make.customViewEqualTo(objs[objKey]); 444 | } 445 | } 446 | } 447 | 448 | i++; 449 | } 450 | 451 | //assemble view的情况就用递归完成 452 | if (asArray.count > 0) { 453 | make.customViewEqualTo([STMAssembleView createViewWithFormatArray:asArray objects:objs completion:nil]); 454 | } 455 | 456 | //开始设置Part属性 457 | if (propertyArray.count > 0) { 458 | NSMutableDictionary *dic = [STMAssembleView parsingPropertyFormatArray:propertyArray objects:objs]; 459 | NSArray *keys = [dic allKeys]; 460 | CGFloat width = 0; 461 | CGFloat height = 0; 462 | for (NSString *key in keys) { 463 | //设置布局 464 | if ([key isEqualToString:@"width"]) { 465 | width = [dic[key] floatValue]; 466 | } 467 | if ([key isEqualToString:@"height"]) { 468 | height = [dic[key] floatValue]; 469 | } 470 | if ([key isEqualToString:@"isFill"]) { 471 | if ([dic[key] integerValue] > 0) { 472 | make.isFillEqualTo(YES); 473 | } else { 474 | make.isFillEqualTo(NO); 475 | } 476 | } 477 | if ([key isEqualToString:@"padding"]) { 478 | make.paddingEqualTo([dic[key] floatValue]); 479 | } 480 | if ([key isEqualToString:@"partAlignment"]) { 481 | if ([dic[key] isEqualToString:@"center"]) { 482 | make.partAlignmentEqualTo(STMPartAlignmentCenter); 483 | } 484 | if ([dic[key] isEqualToString:@"left"]) { 485 | make.partAlignmentEqualTo(STMPartAlignmentLeft); 486 | } 487 | if ([dic[key] isEqualToString:@"right"]) { 488 | make.partAlignmentEqualTo(STMPartAlignmentRight); 489 | } 490 | if ([dic[key] isEqualToString:@"top"]) { 491 | make.partAlignmentEqualTo(STMPartAlignmentTop); 492 | } 493 | if ([dic[key] isEqualToString:@"bottom"]) { 494 | make.partAlignmentEqualTo(STMPartAlignmentBottom); 495 | } 496 | } 497 | if ([key isEqualToString:@"ignoreAlignment"]) { 498 | if ([dic[key] isEqualToString:@"center"]) { 499 | make.ignoreAlignmentEqualTo(STMPartAlignmentCenter); 500 | } 501 | if ([dic[key] isEqualToString:@"left"]) { 502 | make.ignoreAlignmentEqualTo(STMPartAlignmentLeft); 503 | } 504 | if ([dic[key] isEqualToString:@"right"]) { 505 | make.ignoreAlignmentEqualTo(STMPartAlignmentRight); 506 | } 507 | if ([dic[key] isEqualToString:@"top"]) { 508 | make.ignoreAlignmentEqualTo(STMPartAlignmentTop); 509 | } 510 | if ([dic[key] isEqualToString:@"bottom"]) { 511 | make.ignoreAlignmentEqualTo(STMPartAlignmentBottom); 512 | } 513 | } 514 | if ([key isEqualToString:@"alignmentMargin"]) { 515 | make.alignmentMarginEqualTo([dic[key] floatValue]); 516 | } 517 | //设置权重 518 | if ([key isEqualToString:@"crp"]) { 519 | if ([dic[key] isEqualToString:@"fit"]) { 520 | make.CRpriorityEqualTo(STMPriorityFittingSizeLevel); 521 | } 522 | if ([dic[key] isEqualToString:@"low"]) { 523 | make.CRpriorityEqualTo(STMPriorityDefaultLow); 524 | } 525 | if ([dic[key] isEqualToString:@"high"]) { 526 | make.CRpriorityEqualTo(STMPriorityDefaultHigh); 527 | } 528 | if ([dic[key] isEqualToString:@"required"]) { 529 | make.CRpriorityEqualTo(STMPriorityRequired); 530 | } 531 | } 532 | //设置最大,最小宽 533 | if ([key isEqualToString:@"minWidth"]) { 534 | make.minWidthEqualTo([dic[key] floatValue]); 535 | } 536 | if ([key isEqualToString:@"maxWidth"]) { 537 | make.maxWidthEqualTo([dic[key] floatValue]); 538 | } 539 | //设置控件通用 540 | if ([key isEqualToString:@"backColor"]) { 541 | if ([dic[key] isKindOfClass:[UIColor class]]) { 542 | UIColor *pColor = (UIColor *)dic[key]; 543 | make.backColorIs(pColor); 544 | } else { 545 | make.backColorHexStringIs(dic[key]); 546 | } 547 | } 548 | if ([key isEqualToString:@"backColorHexString"]) { 549 | make.backColorHexStringIs(dic[key]); 550 | } 551 | if ([key isEqualToString:@"backPaddingHorizontal"]) { 552 | make.backPaddingHorizontalIs([dic[key] floatValue]); 553 | } 554 | if ([key isEqualToString:@"backPaddingVertical"]) { 555 | make.backPaddingVerticalIs([dic[key] floatValue]); 556 | } 557 | if ([key isEqualToString:@"backBorderColor"]) { 558 | if ([dic[key] isKindOfClass:[UIColor class]]) { 559 | UIColor *pColor = (UIColor *)dic[key]; 560 | make.backBorderColorIs(pColor); 561 | } else { 562 | make.backBorderColorHexStringIs(dic[key]); 563 | } 564 | } 565 | if ([key isEqualToString:@"backBorderColorHexString"]) { 566 | make.backBorderColorHexStringIs(dic[key]); 567 | } 568 | if ([key isEqualToString:@"backBorderWidth"]) { 569 | make.backBorderWidthIs([dic[key] floatValue]); 570 | } 571 | if ([key isEqualToString:@"backBorderRadius"] || [key isEqualToString:@"radius"]) { 572 | make.backBorderRadiusIs([dic[key] floatValue]); 573 | } 574 | if ([key isEqualToString:@"button"]) { 575 | make.buttonIs(dic[key]); 576 | } 577 | if ([key isEqualToString:@"buttonHighlightColor"]) { 578 | if ([dic[key] isKindOfClass:[UIColor class]]) { 579 | make.buttonHighlightColorIs(dic[key]); 580 | } 581 | } 582 | //设置控件属性 583 | if ([key isEqualToString:@"text"]) { 584 | make.textIs(dic[key]); 585 | } 586 | if ([key isEqualToString:@"fontSize"]) { 587 | make.fontSizeIs([dic[key] floatValue]); 588 | } 589 | if ([key isEqualToString:@"font"]) { 590 | if ([dic[key] isKindOfClass:[UIFont class]]) { 591 | UIFont *pFont = (UIFont *)dic[key]; 592 | make.fontIs(pFont); 593 | } else { 594 | make.fontSizeIs([dic[key] floatValue]); 595 | } 596 | } 597 | if ([key isEqualToString:@"color"]) { 598 | if ([dic[key] isKindOfClass:[UIColor class]]) { 599 | UIColor *pColor = (UIColor *)dic[key]; 600 | make.colorIs(pColor); 601 | } else { 602 | make.colorHexStringIs(dic[key]); 603 | } 604 | } 605 | if ([key isEqualToString:@"colorHexString"]) { 606 | make.colorHexStringIs(dic[key]); 607 | } 608 | if ([key isEqualToString:@"imageName"]) { 609 | make.imageNameIs(dic[key]); 610 | } 611 | if ([key isEqualToString:@"image"]) { 612 | if ([dic[key] isKindOfClass:[UIImage class]]) { 613 | make.imageIs(dic[key]); 614 | } 615 | } 616 | if ([key isEqualToString:@"imageUrl"]) { 617 | make.imageUrlIs(dic[key]); 618 | } 619 | 620 | } 621 | //处理多个值需要组合的情况 622 | if (width > 0 || height > 0) { 623 | make.sizeEqualTo(CGSizeMake(width, height)); 624 | } 625 | } 626 | 627 | }]; 628 | } 629 | /*-------------辅助方法--------------------*/ 630 | //将属性数组转成键值对应的字典 631 | + (NSMutableDictionary *)parsingPropertyFormatArray:(NSMutableArray *)array objects:(NSDictionary *)objs{ 632 | NSArray *allObjKeys = objs.allKeys; 633 | //遍历解析到的assemble view的属性 634 | [array addObject:@","];//处理最后一个没添加,的情况 635 | BOOL isParsingOneProperty = NO; 636 | NSString *parsingKey = @""; 637 | BOOL isParsingObj = NO; 638 | NSMutableDictionary *keyValuePropertys = [NSMutableDictionary dictionary]; 639 | for (NSString *proStr in array) { 640 | //属性 641 | if (!isParsingOneProperty) { 642 | isParsingOneProperty = YES; 643 | parsingKey = proStr; 644 | } else if ([proStr isEqualToString:@":"]) { 645 | //直接略过 646 | } else if ([proStr isEqualToString:@","]){ 647 | //需要结束 648 | isParsingOneProperty = NO; 649 | } else if (isParsingOneProperty) { 650 | if ([proStr isEqualToString:@"<"]) { 651 | isParsingObj = YES; 652 | } else if ([proStr isEqualToString:@">"]) { 653 | isParsingObj = NO; 654 | } else if (isParsingObj) { 655 | //处理obj传入的属性 656 | // keyValuePropertys[parsingKey] = 657 | for (NSString *objKey in allObjKeys) { 658 | if ([objKey isEqualToString:proStr]) { 659 | keyValuePropertys[parsingKey] = objs[objKey]; 660 | } 661 | } 662 | } else { 663 | keyValuePropertys[parsingKey] = proStr; 664 | } 665 | 666 | } 667 | 668 | } 669 | return keyValuePropertys; 670 | } 671 | 672 | //宏 673 | NSString *ASS(NSString *format, ...) { 674 | va_list args; 675 | if (format) { 676 | va_start(args, format); 677 | 678 | NSString *str = [[NSString alloc] initWithFormat:format arguments:args]; 679 | va_end(args); 680 | return str; 681 | } 682 | return @""; 683 | } 684 | 685 | @end 686 | -------------------------------------------------------------------------------- /Classes/STMPartMaker.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMPartMaker.h 3 | // HomePageTest 4 | // 5 | // Created by DaiMing on 16/6/2. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, STMPartAlignment) { 12 | STMPartAlignmentDefault, 13 | STMPartAlignmentCenter, 14 | STMPartAlignmentLeft, 15 | STMPartAlignmentRight, 16 | STMPartAlignmentTop, 17 | STMPartAlignmentBottom 18 | }; 19 | typedef NS_ENUM(NSUInteger, STMPartColorType) { 20 | STMPartColorWhite, 21 | STMPartColorBlack, 22 | STMpartColorGray, 23 | STMpartColorLightGray, 24 | STMpartColorDarkGray, 25 | STMpartColorOrange, 26 | STMpartColorRed 27 | }; 28 | //权重 29 | typedef NS_ENUM(NSUInteger, STMPartPriority) { 30 | STMPriorityDefault, //不设置,按照默认来 31 | STMPriorityFittingSizeLevel, //50 32 | STMPriorityDefaultLow, //250 33 | STMPriorityDefaultHigh, //750 34 | STMPriorityRequired, //1000 35 | }; 36 | 37 | @interface STMPartMaker : NSObject 38 | 39 | //----------------属性---------------- 40 | //布局 41 | @property (nonatomic) CGSize size; 42 | @property (nonatomic) CGFloat padding; 43 | @property (nonatomic, strong) UIView *view; 44 | @property (nonatomic) BOOL isFill; //如果设置填充,对应的宽高需要设置为0 45 | 46 | @property (nonatomic) STMPartAlignment partAlignment; //不设置就按照assembleView的设置来 47 | @property (nonatomic) CGFloat alignmentMargin; //对齐方向和assembleView的间距 48 | @property (nonatomic) STMPartAlignment ignoreAlignment; //需要忽略的约束方向 49 | @property (nonatomic) STMPartPriority CRpriority; //CompressionResistancePriority 50 | 51 | @property (nonatomic) CGFloat minWidth; //最小宽 52 | @property (nonatomic) CGFloat maxWidth; //最大宽 53 | 54 | //控件属性 55 | //通用部分 56 | //底部 57 | @property (nonatomic, strong) UIColor *backColor; //底部设置的颜色 58 | @property (nonatomic, strong) UIColor *backBorderColor; //边线的颜色 59 | @property (nonatomic) CGFloat backBorderWidth; //边线的大小 60 | @property (nonatomic) CGFloat backBorderRadius; //边线半径 61 | @property (nonatomic) CGFloat backPaddingHorizontal; //左右的间隔 62 | @property (nonatomic) CGFloat backPaddingVertical; //上下的间隔 63 | @property (nonatomic, strong) UIImage *backImage; //待实现 64 | //按钮 65 | @property (nonatomic, strong) UIButton *button; 66 | @property (nonatomic, strong) UIColor *buttonHighlightColor; 67 | 68 | //Label 69 | @property (nonatomic, copy) NSString *text; 70 | @property (nonatomic, strong) UIFont *font; 71 | @property (nonatomic, strong) UIColor *color; 72 | 73 | //ImageView 74 | @property (nonatomic, strong) UIImage *image; 75 | @property (nonatomic, strong) NSString *imageUrl; 76 | @property (nonatomic, strong) UIImage *imagePlaceholder; 77 | 78 | //----------------方法-------------- 79 | //布局 80 | - (STMPartMaker *(^)(UIView *))customViewEqualTo; 81 | - (STMPartMaker *(^)(CGSize))sizeEqualTo; 82 | - (STMPartMaker *(^)(BOOL))isFillEqualTo; 83 | - (STMPartMaker *(^)(CGFloat))paddingEqualTo; 84 | - (STMPartMaker *(^)(STMPartAlignment))partAlignmentEqualTo; 85 | - (STMPartMaker *(^)(CGFloat))alignmentMarginEqualTo; 86 | - (STMPartMaker *(^)(STMPartAlignment))ignoreAlignmentEqualTo; 87 | - (STMPartMaker *(^)(STMPartPriority))CRpriorityEqualTo; 88 | - (STMPartMaker *(^)(CGFloat))minWidthEqualTo; 89 | - (STMPartMaker *(^)(CGFloat))maxWidthEqualTo; 90 | 91 | //控件属性 92 | //通用 93 | - (STMPartMaker *(^)(UIColor *))backColorIs; 94 | - (STMPartMaker *(^)(NSString *))backColorHexStringIs; 95 | - (STMPartMaker *(^)(UIColor *))backBorderColorIs; 96 | - (STMPartMaker *(^)(NSString *))backBorderColorHexStringIs; 97 | - (STMPartMaker *(^)(CGFloat))backBorderWidthIs; 98 | - (STMPartMaker *(^)(CGFloat))backBorderRadiusIs; 99 | - (STMPartMaker *(^)(CGFloat))backPaddingHorizontalIs; 100 | - (STMPartMaker *(^)(CGFloat))backPaddingVerticalIs; 101 | - (STMPartMaker *(^)(UIButton *))buttonIs; 102 | - (STMPartMaker *(^)(UIColor *))buttonHighlightColorIs; 103 | 104 | //Label 105 | - (STMPartMaker *(^)(NSString *))textIs; 106 | - (STMPartMaker *(^)(UIFont *))fontIs; 107 | - (STMPartMaker *(^)(CGFloat))fontSizeIs; 108 | - (STMPartMaker *(^)(UIColor *))colorIs; 109 | - (STMPartMaker *(^)(NSString *))colorHexStringIs; //十六进制颜色 110 | - (STMPartMaker *(^)(STMPartColorType))colorTypeIs;//颜色类型 111 | 112 | //ImageView 113 | - (STMPartMaker *(^)(UIImage *))imageIs; 114 | - (STMPartMaker *(^)(NSString *))imageNameIs; 115 | - (STMPartMaker *(^)(NSString *))imageUrlIs; 116 | - (STMPartMaker *(^)(UIImage *))imagePlaceholderIs; 117 | - (STMPartMaker *(^)(NSString *))imagePlaceholderNameIs; 118 | 119 | /*-----辅助方法-----*/ 120 | + (UIColor *)colorWithHexString:(NSString *)hexString; 121 | @end 122 | -------------------------------------------------------------------------------- /Classes/STMPartMaker.m: -------------------------------------------------------------------------------- 1 | // 2 | // STMPartMaker.m 3 | // HomePageTest 4 | // 5 | // Created by DaiMing on 16/6/2. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import "STMPartMaker.h" 10 | 11 | 12 | typedef NS_ENUM(NSUInteger, STMPartType) { 13 | STMPartTypeCustom, 14 | STMPartTypeUILabel, 15 | STMPartTypeUIImageView 16 | }; 17 | 18 | @implementation STMPartMaker 19 | 20 | - (STMPartMaker *(^)(CGSize))sizeEqualTo { 21 | return ^STMPartMaker *(CGSize size) { 22 | self.size = size; 23 | return self; 24 | }; 25 | } 26 | - (STMPartMaker *(^)(UIView *))customViewEqualTo { 27 | return ^STMPartMaker *(UIView *customView) { 28 | self.view = customView; 29 | return self; 30 | }; 31 | } 32 | - (STMPartMaker *(^)(BOOL))isFillEqualTo { 33 | return ^STMPartMaker *(BOOL isFill) { 34 | self.isFill = isFill; 35 | return self; 36 | }; 37 | } 38 | - (STMPartMaker *(^)(CGFloat))paddingEqualTo { 39 | return ^STMPartMaker *(CGFloat padding) { 40 | self.padding = padding; 41 | return self; 42 | }; 43 | } 44 | - (STMPartMaker *(^)(STMPartAlignment))partAlignmentEqualTo { 45 | return ^STMPartMaker *(STMPartAlignment alignment) { 46 | self.partAlignment = alignment; 47 | return self; 48 | }; 49 | } 50 | - (STMPartMaker *(^)(CGFloat))alignmentMarginEqualTo { 51 | return ^STMPartMaker *(CGFloat margin) { 52 | self.alignmentMargin = margin; 53 | return self; 54 | }; 55 | } 56 | - (STMPartMaker *(^)(STMPartAlignment))ignoreAlignmentEqualTo { 57 | return ^STMPartMaker *(STMPartAlignment alignment) { 58 | self.ignoreAlignment = alignment; 59 | return self; 60 | }; 61 | } 62 | - (STMPartMaker *(^)(STMPartPriority))CRpriorityEqualTo { 63 | return ^STMPartMaker *(STMPartPriority priority) { 64 | self.CRpriority = priority; 65 | return self; 66 | }; 67 | } 68 | - (STMPartMaker *(^)(CGFloat))minWidthEqualTo { 69 | return ^STMPartMaker *(CGFloat width) { 70 | self.minWidth = width; 71 | return self; 72 | }; 73 | } 74 | - (STMPartMaker *(^)(CGFloat))maxWidthEqualTo { 75 | return ^STMPartMaker *(CGFloat width) { 76 | self.maxWidth = width; 77 | return self; 78 | }; 79 | } 80 | 81 | //控件 82 | //通用 83 | - (STMPartMaker *(^)(UIColor *))backColorIs { 84 | return ^STMPartMaker *(UIColor *color) { 85 | self.backColor = color; 86 | return self; 87 | }; 88 | } 89 | - (STMPartMaker *(^)(NSString *))backColorHexStringIs { 90 | return ^STMPartMaker *(NSString *str) { 91 | self.backColor = [STMPartMaker colorWithHexString:str]; 92 | return self; 93 | }; 94 | } 95 | - (STMPartMaker *(^)(UIColor *))backBorderColorIs { 96 | return ^STMPartMaker *(UIColor *color) { 97 | self.backBorderColor = color; 98 | return self; 99 | }; 100 | } 101 | - (STMPartMaker *(^)(NSString *))backBorderColorHexStringIs { 102 | return ^STMPartMaker *(NSString *str) { 103 | self.backBorderColor = [STMPartMaker colorWithHexString:str]; 104 | return self; 105 | }; 106 | } 107 | - (STMPartMaker *(^)(CGFloat))backBorderWidthIs { 108 | return ^STMPartMaker *(CGFloat size) { 109 | self.backBorderWidth = size; 110 | return self; 111 | }; 112 | } 113 | - (STMPartMaker *(^)(CGFloat))backBorderRadiusIs { 114 | return ^STMPartMaker *(CGFloat rd) { 115 | self.backBorderRadius = rd; 116 | return self; 117 | }; 118 | } 119 | - (STMPartMaker *(^)(CGFloat))backPaddingHorizontalIs { 120 | return ^STMPartMaker *(CGFloat padding) { 121 | self.backPaddingHorizontal = padding; 122 | return self; 123 | }; 124 | } 125 | - (STMPartMaker *(^)(CGFloat))backPaddingVerticalIs { 126 | return ^STMPartMaker *(CGFloat padding) { 127 | self.backPaddingVertical = padding; 128 | return self; 129 | }; 130 | } 131 | - (STMPartMaker *(^)(UIButton *))buttonIs { 132 | return ^STMPartMaker *(UIButton *bt) { 133 | self.button = bt; 134 | return self; 135 | }; 136 | } 137 | - (STMPartMaker *(^)(UIColor *))buttonHighlightColorIs { 138 | return ^STMPartMaker *(UIColor *color) { 139 | self.buttonHighlightColor = color; 140 | return self; 141 | }; 142 | } 143 | //label 144 | - (STMPartMaker *(^)(NSString *))textIs { 145 | return ^STMPartMaker *(NSString *text) { 146 | self.text = text; 147 | return self; 148 | }; 149 | } 150 | - (STMPartMaker *(^)(UIFont *))fontIs { 151 | return ^STMPartMaker *(UIFont *font) { 152 | self.font = font; 153 | return self; 154 | }; 155 | } 156 | - (STMPartMaker *(^)(CGFloat))fontSizeIs { 157 | return ^STMPartMaker *(CGFloat size) { 158 | self.font = [UIFont systemFontOfSize:size]; 159 | return self; 160 | }; 161 | } 162 | - (STMPartMaker *(^)(UIColor *))colorIs { 163 | return ^STMPartMaker *(UIColor *color) { 164 | self.color = color; 165 | return self; 166 | }; 167 | } 168 | - (STMPartMaker *(^)(NSString *))colorHexStringIs { 169 | return ^STMPartMaker *(NSString *string) { 170 | self.color = [STMPartMaker colorWithHexString:string]; 171 | return self; 172 | }; 173 | } 174 | - (STMPartMaker *(^)(STMPartColorType))colorTypeIs { 175 | return ^STMPartMaker *(STMPartColorType type) { 176 | switch (type) { 177 | case STMPartColorWhite: 178 | self.color = [UIColor whiteColor]; 179 | break; 180 | case STMPartColorBlack: 181 | self.color = [UIColor blueColor]; 182 | break; 183 | case STMpartColorRed: 184 | self.color = [UIColor redColor]; 185 | break; 186 | case STMpartColorGray: 187 | self.color = [UIColor grayColor]; 188 | break; 189 | case STMpartColorLightGray: 190 | self.color = [UIColor lightGrayColor]; 191 | break; 192 | case STMpartColorDarkGray: 193 | self.color = [UIColor darkGrayColor]; 194 | break; 195 | case STMpartColorOrange: 196 | self.color = [UIColor orangeColor]; 197 | break; 198 | } 199 | return self; 200 | }; 201 | } 202 | 203 | //Image View 204 | - (STMPartMaker *(^)(UIImage *))imageIs { 205 | return ^STMPartMaker *(UIImage *image) { 206 | self.image = image; 207 | return self; 208 | }; 209 | } 210 | - (STMPartMaker *(^)(NSString *))imageNameIs { 211 | return ^STMPartMaker *(NSString *name) { 212 | self.image = [UIImage imageNamed:name]; //这里需要根据情况 213 | return self; 214 | }; 215 | } 216 | - (STMPartMaker *(^)(NSString *))imageUrlIs { 217 | return ^STMPartMaker *(NSString *url) { 218 | self.imageUrl = url; 219 | return self; 220 | }; 221 | } 222 | - (STMPartMaker *(^)(UIImage *))imagePlaceholderIs { 223 | return ^STMPartMaker *(UIImage *image) { 224 | self.imagePlaceholder = image; 225 | return self; 226 | }; 227 | } 228 | - (STMPartMaker *(^)(NSString *))imagePlaceholderNameIs { 229 | return ^STMPartMaker *(NSString *name) { 230 | self.imagePlaceholder = [UIImage imageNamed:name]; 231 | return self; 232 | }; 233 | } 234 | 235 | 236 | //辅助方法 237 | + (UIColor *)colorWithRGBHex:(UInt32)hex { 238 | int r = (hex >> 16) & 0xFF; 239 | int g = (hex >> 8) & 0xFF; 240 | int b = (hex) & 0xFF; 241 | 242 | return [UIColor colorWithRed:r / 255.0f 243 | green:g / 255.0f 244 | blue:b / 255.0f 245 | alpha:1.0f]; 246 | } 247 | 248 | + (UIColor *)colorWithHexString:(NSString *)hexString { 249 | NSString *stringToConvert = [[hexString stringByReplacingOccurrencesOfString:@"#" withString:@""] uppercaseString]; 250 | 251 | NSScanner *scanner = [NSScanner scannerWithString:stringToConvert]; 252 | unsigned hexNum; 253 | if (![scanner scanHexInt:&hexNum]) return nil; 254 | return [STMPartMaker colorWithRGBHex:hexNum]; 255 | } 256 | 257 | @end 258 | 259 | -------------------------------------------------------------------------------- /Classes/STMPartView.h: -------------------------------------------------------------------------------- 1 | // 2 | // STMPartView.h 3 | // HomePageTest 4 | // 5 | // Created by DaiMing on 16/5/31. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "STMPartMaker.h" 11 | 12 | @interface STMPartView : NSObject 13 | 14 | @property (nonatomic, strong) STMPartMaker *maker; 15 | 16 | + (STMPartView *)createView:(void(^)(STMPartMaker *make))partMaker; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/STMPartView.m: -------------------------------------------------------------------------------- 1 | // 2 | // STMPartView.m 3 | // HomePageTest 4 | // 5 | // Created by DaiMing on 16/5/31. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import "STMPartView.h" 10 | #import "UIImageView+WebCache.h" 11 | #import "Masonry.h" 12 | 13 | @implementation STMPartView 14 | 15 | + (STMPartView *)createView:(void(^)(STMPartMaker *))partMaker { 16 | STMPartView *partView = [[self alloc] init]; 17 | partView.maker = [[STMPartMaker alloc] init]; 18 | partMaker(partView.maker); 19 | [partView buildPartView]; 20 | return partView; 21 | } 22 | 23 | - (STMPartView *)buildPartView { 24 | if (self.maker.image) { 25 | 26 | if (self.maker.view) { 27 | if ([self.maker.view isKindOfClass:[UIImageView class]]) { 28 | UIImageView *fiv = (UIImageView *)self.maker.view; 29 | [self updateImageView:fiv]; 30 | } 31 | } else { 32 | UIImageView *iv = [[UIImageView alloc] init]; 33 | [self updateImageView:iv]; 34 | self.maker.view = iv; 35 | } 36 | 37 | } else if (self.maker.text.length > 0 || self.maker.font) { 38 | 39 | if (self.maker.view) { 40 | if ([self.maker.view isKindOfClass:[UILabel class]]) { 41 | UILabel *fLb = (UILabel *)self.maker.view; 42 | [self updateLabel:fLb]; 43 | } 44 | } else { 45 | UILabel *lb = [[UILabel alloc] init]; 46 | [self updateLabel:lb]; 47 | self.maker.view = lb; 48 | } 49 | 50 | } 51 | 52 | //处理有背景的情况 53 | if (self.maker.backColor || self.maker.backPaddingVertical || self.maker.backPaddingHorizontal) { 54 | UIView *backView = [[UIView alloc] init]; 55 | if (self.maker.backColor) { 56 | backView.backgroundColor = self.maker.backColor; 57 | } else { 58 | backView.backgroundColor = [UIColor clearColor]; 59 | } 60 | 61 | UIView *oView = self.maker.view; 62 | CGFloat paddingV = self.maker.backPaddingVertical; 63 | CGFloat paddingH = self.maker.backPaddingHorizontal; 64 | 65 | [backView addSubview:oView]; 66 | if (paddingH > 0 || paddingV > 0) { 67 | [oView mas_makeConstraints:^(MASConstraintMaker *make) { 68 | make.left.equalTo(backView).offset(paddingH); 69 | make.right.equalTo(backView).offset(-paddingH); 70 | make.top.equalTo(backView).offset(paddingV); 71 | make.bottom.equalTo(backView).offset(-paddingV); 72 | }]; 73 | } else { 74 | [oView mas_makeConstraints:^(MASConstraintMaker *make) { 75 | make.center.equalTo(backView); 76 | }]; 77 | } 78 | 79 | 80 | //设置边线 81 | if (self.maker.backBorderColor) { 82 | backView.layer.borderColor = self.maker.backBorderColor.CGColor; 83 | } 84 | if (self.maker.backBorderWidth > 0) { 85 | backView.layer.borderWidth = self.maker.backBorderWidth; 86 | } 87 | if (self.maker.backBorderRadius > 0) { 88 | backView.layer.cornerRadius = self.maker.backBorderRadius; 89 | } 90 | 91 | self.maker.view = backView; 92 | } 93 | 94 | //处理有button的情况 95 | if (self.maker.button) { 96 | [self.maker.view addSubview:self.maker.button]; 97 | if (self.maker.buttonHighlightColor) { 98 | //点击效果 99 | [self.maker.button setBackgroundImage:[self imageWithColor:self.maker.buttonHighlightColor] forState:UIControlStateHighlighted]; 100 | } else { 101 | [self.maker.button setBackgroundImage:[self imageWithColor:[[STMPartMaker colorWithHexString:@"000000"] colorWithAlphaComponent:0.05]] forState:UIControlStateHighlighted]; 102 | } 103 | [self.maker.button mas_makeConstraints:^(MASConstraintMaker *make) { 104 | make.left.right.top.bottom.equalTo(self.maker.view); 105 | }]; 106 | } 107 | 108 | 109 | return self; 110 | } 111 | 112 | - (void)updateLabel:(UILabel *)label { 113 | label.text = self.maker.text; 114 | label.textColor = self.maker.color; 115 | label.font = self.maker.font; 116 | } 117 | - (void)updateImageView:(UIImageView *)imageView { 118 | if(self.maker.imageUrl.length > 0) { 119 | [imageView sd_setImageWithURL:[NSURL URLWithString:self.maker.imageUrl] placeholderImage:self.maker.imagePlaceholder]; 120 | } else { 121 | [imageView setImage:self.maker.image]; 122 | } 123 | } 124 | 125 | #pragma mark - helper 126 | //辅助方法 127 | - (UIImage *)imageWithColor:(UIColor *)color 128 | { 129 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 130 | UIGraphicsBeginImageContext(rect.size); 131 | CGContextRef context = UIGraphicsGetCurrentContext(); 132 | 133 | CGContextSetFillColorWithColor(context, [color CGColor]); 134 | CGContextFillRect(context, rect); 135 | 136 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 137 | UIGraphicsEndImageContext(); 138 | 139 | return image; 140 | } 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 戴铭 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # platform :ios, '7.0' 2 | use_frameworks! 3 | target 'STMAssembleView' do 4 | 5 | pod 'SDWebImage' 6 | pod 'Masonry' 7 | pod 'Reveal-iOS-SDK', :configurations => ['Debug'] 8 | 9 | end 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 在项目中总是希望页面上各处的文字,颜色,字体大小甚至各个视图控件布局都能够在发版之后能够修改以弥补一些前期考虑不周,或者根据统计数据能够随时进行调整,当然是各个版本都能够统一变化。看到这样的要求后,第一反应是这样的页面只能改成H5,或者尝试使用React Native来应对这种要求。 2 | 3 | 既然UIStackView已经提供了一种既先进又简洁的布局思路,为何不通过制作一个类似VFL这样的DSL语言来处理布局。这样不就能够通过下发一串DSL字符串的方式来进行内容样式甚至布局的更换,不用跟版,还能使多版本统一。同时在端内直接用这样的DSL语言来写界面不光能够减少代码量易于维护,还能够很直观方便的看出整个界面布局结构。 4 | 5 | # AssembleView(组装视图)和PartView(零件视图) 6 | 在设计格式化语言之前需要对布局做个统一思想进行管理,在看了WWDC里关于UIStackView的介绍后感觉任何复杂的布局都能够通过这样一种组合排布再组合排布的思路特别适合用格式化语言来描述。于是我想出两个视图概念。 7 | 8 | 一个是AssembleView组合视图,专门用于对其PartView子视图进行排列,比如说是水平排列还是垂直排列,PartView是按照居中对齐还是居左等对齐方式,各个PartView之间间隔是多少。 9 | 10 | PartView决定自己视图类型,内容,无固定大小的可以设置大小,同时AssembleView可以作为PartView被加入另一个AssembleView里进行排列,这样各种设计图都可以在初期通过拆解分成不同的AssembleView和PartView进行组合套组合布局出来。 11 | 12 | # 格式化语言 13 | 接下来是如何通过格式化语言来描述AssembleView和PartView。“{}”符号里包含的是AssembleView的设置,“[]”符号里是PartView的设置,“()”里是他们的属性设置,“<>”可以将对象带入到设置里。下面举几个例子说明下。完整Demo放到了Github上: 14 | 15 | ## 三个星星水平对齐居中排列 16 | h表示水平排列horizontal,c表示居中center,“[]”PartView会根据顺序依次添加排列,imageName属性能够指定本地图片 17 | ![三个星星水平对齐居中排列](https://github.com/ming1016/STMAssembleView/blob/master/STMAssembleView/center.png?raw=true 18 | ) 19 | ``` 20 | { 21 | hc(padding:30) 22 | [(imageName:starmingicon)] 23 | [(imageName:starmingicon)] 24 | [(imageName:starmingicon)] 25 | } 26 | ``` 27 | 28 | ## AssembleView里套作为PartView的AssembleView的复杂情况 29 | color可以指定文字颜色,font指定文字大小 30 | ![AssembleView里套作为PartView的AssembleView的复杂情况](https://github.com/ming1016/STMAssembleView/blob/master/STMAssembleView/mid.png?raw=true 31 | ) 32 | ``` 33 | { 34 | ht(padding:10) 35 | [avatarImageView(imageName:avatar)] 36 | [ 37 | { 38 | vl(padding:10) 39 | [(text:戴铭,color:AAA0A3)] 40 | [(text:Starming站长,color:E3DEE0,font:13)] 41 | [(text:喜欢画画编程和写小说,color:E3DEE0,font:13)] 42 | } 43 | (width:210,backColor:FAF8F9,backPaddingHorizontal:10,backPaddingVertical:10,radius:8) 44 | ] 45 | } 46 | ``` 47 | 48 | ## 给PartView设置背景色和按钮 49 | 设置背景色使用backColor,背景距离设置的PartView的内容间距通过backPaddingHorizontal属性设置水平间距,backPaddingVertical设置垂直间距,“<>”符号带入的button通过button属性设置。 50 | ![给PartView设置背景色和按钮](https://github.com/ming1016/STMAssembleView/blob/master/STMAssembleView/followBt.png?raw=true 51 | ) 52 | ``` 53 | [ 54 | { 55 | hc(padding:4) 56 | [(imageName:starmingicon,width:14,height:10)] 57 | [(text:关注,font:16,color:FFFFFF)] 58 | } 59 | (height:36,backColor:AAA0A3,radius:8,backBorderWidth:1,backBorderColor:E3DEE0,backPaddingHorizontal:80,backPaddingVertical:10,button:) 60 | ] 61 | ``` 62 | 63 | ## AssembleView设置忽略约束的方法 64 | 水平排列时,通过ignoreAlignment属性设置忽略left约束,如果是垂直排列设置top忽略。 65 | ![AssembleView设置忽略约束的方法](https://github.com/ming1016/STMAssembleView/blob/master/STMAssembleView/des.png?raw=true 66 | ) 67 | ``` 68 | { 69 | hc(padding:5) 70 | [(text:STMAssembleView演示,color:E3DEE0,font:13)] 71 | [(imageName:starmingicon,width:14,height:10,ignoreAlignment:left)] 72 | [(text:Starming星光社,color:E3DEE0,font:13)] 73 | } 74 | ``` 75 | 76 | ## 将前面的视图组合成一个AssembleView 77 | ![将前面的视图组合成一个AssembleView](https://github.com/ming1016/STMAssembleView/blob/master/STMAssembleView/as.png?raw=true 78 | ) 79 | ``` 80 | ASS(@"{ 81 | vc(padding:20) 82 | [%@(height:90)] 83 | [%@(height:36,backColor:AAA0A3,radius:8,backBorderWidth:1,backBorderColor:E3DEE0,backPaddingHorizontal:80,backPaddingVertical:10,button:)] 84 | [%@(height:25)] 85 | [%@(ignoreAlignment:top,isFill:1,height:16)] 86 | }",midStr,followBtStr,centerStr,desStr) 87 | ``` 88 | 89 | ## AssembleView的属性 90 | * 当在“{}”里面第一个字母是v表示垂直排列vertical,是h表示水平排列horizontal 91 | * 第二个字母是c表示所有PartView居中对齐center,l表示居左对齐left,r表示居右对齐right,t表示居上对齐top,b表示居下对齐bottom。 92 | * padding:默认各个PartView的间距。 93 | * extendWithEqualTo:由第几个PartView来撑开AssembleView的大小。 94 | 95 | ## PartView的属性 96 | 如果不希望通过属性生成视图,可以通过在[后直接填入带入对象对应的key,然后再在()里设置属性。 97 | 98 | ### PartView布局相关属性 99 | * width:UILabel和UIImage这样有固定大小的可以不用设置,会按照固定大小的来。 100 | * height:有固定大小的可以不用设置。 101 | * isFill:垂直排列时会将宽设置为父AssembleView的宽,水平排列时会将高设置为父AssembleView的高。 102 | * padding:设置后会忽略父AssembleView里设置的padding,达到自定义间距的效果。 103 | * partAlignment:可以自定义对齐方向,设置后会忽略父AssembleView里设置的对齐。值可填center,left,right,top,bottom。 104 | * alignmentMargin:对齐方向和assembleView的间距 105 | * ignoreAlignment:设置忽略的约束方向,在父AssembleView不需要由子PartView决定大小的情况下,可以通过打断某个方向约束来实现拆开排列的效果。值可填center,left,right,top,bottom。 106 | 107 | ### PartView权重相关属性 108 | * crp:Compression Resistance Priority的设置,根据权重由低到高值可以设置为fit,low,high,required。对应的UILayoutPriority的分别是UILayoutPriorityFittingSizeLevel,UILayoutPriorityDefaultLow,UILayoutPriorityDefaultHigh,UILayoutPriorityRequired。 109 | * minWidth:对应NSLayoutRelationGreaterThanOrEqual,设置一个最小的宽 110 | * maxWidth:对应NSLayoutRelationLessThanOrEqual,设置一个最大的宽 111 | 112 | ### PartView视图控件相关设置 113 | 通过以下属性即可生成对应的UILabel,UIImageView或者UIButton等控件视图,而不用特别指出需要生成哪种控件视图 114 | * text:设置文字内容 115 | * font:设置字体,可以带入一个UIFont,也可以直接设置一个字体大小,解析时会判断类型。 116 | * color:设置颜色,可以带入一个UIColor,也可以直接设置一个十六进制颜色,解析时会判断类型。 117 | * imageName:设置本地图片,值是本地图片名称。 118 | * image:带入一个UIImage。 119 | * imageUrl:设置一个网络图片的url地址,ps:目前需要通过<>来带入一个字符串。 120 | 121 | ### PartView的通用设置 122 | 可以为PartView创建一个底部视图,并设置其样式。也可以添加一个UIButton设置UIControlStateHighlighted时的样式。 123 | * backColor:设置底部视图的颜色,可以带入一个UIColor,也可以直接设置一个十六进制颜色,解析时会判断类型。 124 | * backPaddingHorizontal:设置当前PartView视图距离底部视图top和bottom的间距。 125 | * backPaddingVertical:设置当前PartView视图距离底部视图left和right的间距。 126 | * backBorderColor:设置底部视图边框的颜色,可以带入一个UIColor,也可以直接设置一个十六进制颜色,解析时会判断类型。 127 | * backBorderWidth:设置底部视图边框宽。 128 | * radius:设置底部视图的圆角半径。 129 | * button:带入一个button。 130 | * buttonHighlightColor:设置button在UIControlStateHighlighted时的颜色,默认是透明度0.05的黑色。 131 | 132 | # 解析格式化语言 133 | 解析过程的第一步采用扫描scanner程序将字符串按照分析符号表将字符流序列收集到有意义的单元中。 134 | 135 | 第二步将这些单元逐个归类到对应的类别中。比如解析到“()”里内容时就将其归类到对应的AssembleView的属性或者PartView的属性类别中。在归类过程中会出现PartView是AssembleView,这个Assemble里面又有这样作为PartView的AssembleView这样层层套的情况,所以需要采用类似引用计数方式保证在最后一个“}”符号结束时能将整个Assemble递归进行解析。 136 | 137 | 第三步将各个类别集合转换成对应原生代码从而生成对应的视图布局。 138 | 139 | 具体实现可以查看STMAssembleView.m文件。Github地址: 140 | 141 | # 如何生成页面 142 | 生成页面需要实现格式化语言对应的原生代码,所有PartView的属性都会存放在STMPartMaker里,包括带入的自定义视图还有用于生成视图控件的属性等。PartView属性设置完成后会在STMPartView这个类中先决定对应的视图控件,并将STMPartMaker里的属性都设置上。实现代码可以查看STMPartView.m里的- (STMPartView *)buildPartView方法。 143 | 144 | 接下来STMAssembleView会在buildAssembleView时进行布局,具体实现代码可以查看STMAssembleView.m里的- (STMAssembleView *)buildAssembleView方法。 145 | -------------------------------------------------------------------------------- /STMAssembleView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "STMAssembleView" 3 | s.version = "1.1" 4 | s.summary = "制作一个类似苹果VFL(Visual Format Language)的格式化语言来描述类似UIStackView那种布局思路,并解析生成页面" 5 | s.homepage = "https://github.com/ming1016/STMAssembleView" 6 | 7 | s.license = "MIT" 8 | 9 | s.author = { "ming1016" => "ming1016@foxmail.com" } 10 | s.ios.deployment_target = "9.0" 11 | s.source = { :git => "https://github.com/ming1016/STMAssembleView.git", :tag => "1.2" } 12 | s.source_files = "Classes/**/*.{h,m}" 13 | s.requires_arc = true 14 | end 15 | -------------------------------------------------------------------------------- /STMAssembleView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0A1C0B741DD4B17D00465005 /* STMAssembleMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A1C0B6D1DD4B17D00465005 /* STMAssembleMaker.m */; }; 11 | 0A1C0B751DD4B17D00465005 /* STMAssembleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A1C0B6F1DD4B17D00465005 /* STMAssembleView.m */; }; 12 | 0A1C0B761DD4B17D00465005 /* STMPartMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A1C0B711DD4B17D00465005 /* STMPartMaker.m */; }; 13 | 0A1C0B771DD4B17D00465005 /* STMPartView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A1C0B731DD4B17D00465005 /* STMPartView.m */; }; 14 | 0A2FD1601D4074A900B2E6C4 /* as.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2FD15B1D4074A900B2E6C4 /* as.png */; }; 15 | 0A2FD1611D4074A900B2E6C4 /* center.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2FD15C1D4074A900B2E6C4 /* center.png */; }; 16 | 0A2FD1621D4074A900B2E6C4 /* des.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2FD15D1D4074A900B2E6C4 /* des.png */; }; 17 | 0A2FD1631D4074A900B2E6C4 /* followBt.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2FD15E1D4074A900B2E6C4 /* followBt.png */; }; 18 | 0A2FD1641D4074A900B2E6C4 /* mid.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2FD15F1D4074A900B2E6C4 /* mid.png */; }; 19 | 0A6B81471D3F951700D71B72 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A6B81461D3F951700D71B72 /* main.m */; }; 20 | 0A6B814A1D3F951700D71B72 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A6B81491D3F951700D71B72 /* AppDelegate.m */; }; 21 | 0A6B814D1D3F951700D71B72 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A6B814C1D3F951700D71B72 /* ViewController.m */; }; 22 | 0A6B81501D3F951700D71B72 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0A6B814E1D3F951700D71B72 /* Main.storyboard */; }; 23 | 0A6B81521D3F951700D71B72 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0A6B81511D3F951700D71B72 /* Assets.xcassets */; }; 24 | 0A6B81551D3F951700D71B72 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0A6B81531D3F951700D71B72 /* LaunchScreen.storyboard */; }; 25 | 0A7E4DCF1DAA4F4D0049713F /* asExample.asv in Resources */ = {isa = PBXBuildFile; fileRef = 0A7E4DCE1DAA4F4D0049713F /* asExample.asv */; }; 26 | C0E20BD7F7BE87B0F8DDB204 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D7A3506E929B33F2BB3AF5F3 /* libPods.a */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 0A1C0B6C1DD4B17D00465005 /* STMAssembleMaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STMAssembleMaker.h; sourceTree = ""; }; 31 | 0A1C0B6D1DD4B17D00465005 /* STMAssembleMaker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STMAssembleMaker.m; sourceTree = ""; }; 32 | 0A1C0B6E1DD4B17D00465005 /* STMAssembleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STMAssembleView.h; sourceTree = ""; }; 33 | 0A1C0B6F1DD4B17D00465005 /* STMAssembleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STMAssembleView.m; sourceTree = ""; }; 34 | 0A1C0B701DD4B17D00465005 /* STMPartMaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STMPartMaker.h; sourceTree = ""; }; 35 | 0A1C0B711DD4B17D00465005 /* STMPartMaker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STMPartMaker.m; sourceTree = ""; }; 36 | 0A1C0B721DD4B17D00465005 /* STMPartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STMPartView.h; sourceTree = ""; }; 37 | 0A1C0B731DD4B17D00465005 /* STMPartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STMPartView.m; sourceTree = ""; }; 38 | 0A2FD15B1D4074A900B2E6C4 /* as.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = as.png; sourceTree = ""; }; 39 | 0A2FD15C1D4074A900B2E6C4 /* center.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = center.png; sourceTree = ""; }; 40 | 0A2FD15D1D4074A900B2E6C4 /* des.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = des.png; sourceTree = ""; }; 41 | 0A2FD15E1D4074A900B2E6C4 /* followBt.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = followBt.png; sourceTree = ""; }; 42 | 0A2FD15F1D4074A900B2E6C4 /* mid.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mid.png; sourceTree = ""; }; 43 | 0A6B81421D3F951700D71B72 /* STMAssembleView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = STMAssembleView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 0A6B81461D3F951700D71B72 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | 0A6B81481D3F951700D71B72 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 46 | 0A6B81491D3F951700D71B72 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 47 | 0A6B814B1D3F951700D71B72 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 48 | 0A6B814C1D3F951700D71B72 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 49 | 0A6B814F1D3F951700D71B72 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 50 | 0A6B81511D3F951700D71B72 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 0A6B81541D3F951700D71B72 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52 | 0A6B81561D3F951700D71B72 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 0A7E4DCE1DAA4F4D0049713F /* asExample.asv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = asExample.asv; sourceTree = ""; }; 54 | 31D84A63D1A76D3603A060A1 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 55 | A3452471D6A996A0F18B5691 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 56 | D7A3506E929B33F2BB3AF5F3 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | 0A6B813F1D3F951700D71B72 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | C0E20BD7F7BE87B0F8DDB204 /* libPods.a in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | 0A1C0B5F1DD4A85400465005 /* Classes */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 0A1C0B6C1DD4B17D00465005 /* STMAssembleMaker.h */, 75 | 0A1C0B6D1DD4B17D00465005 /* STMAssembleMaker.m */, 76 | 0A1C0B6E1DD4B17D00465005 /* STMAssembleView.h */, 77 | 0A1C0B6F1DD4B17D00465005 /* STMAssembleView.m */, 78 | 0A1C0B701DD4B17D00465005 /* STMPartMaker.h */, 79 | 0A1C0B711DD4B17D00465005 /* STMPartMaker.m */, 80 | 0A1C0B721DD4B17D00465005 /* STMPartView.h */, 81 | 0A1C0B731DD4B17D00465005 /* STMPartView.m */, 82 | ); 83 | name = Classes; 84 | path = ../Classes; 85 | sourceTree = ""; 86 | }; 87 | 0A2FD15A1D40748600B2E6C4 /* ScreenShots */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 0A2FD15B1D4074A900B2E6C4 /* as.png */, 91 | 0A2FD15C1D4074A900B2E6C4 /* center.png */, 92 | 0A2FD15D1D4074A900B2E6C4 /* des.png */, 93 | 0A2FD15E1D4074A900B2E6C4 /* followBt.png */, 94 | 0A2FD15F1D4074A900B2E6C4 /* mid.png */, 95 | ); 96 | name = ScreenShots; 97 | sourceTree = ""; 98 | }; 99 | 0A6B81391D3F951700D71B72 = { 100 | isa = PBXGroup; 101 | children = ( 102 | 0A6B81441D3F951700D71B72 /* STMAssembleView */, 103 | 0A6B81431D3F951700D71B72 /* Products */, 104 | FA16D0B8C8E68FFA944D5D45 /* Pods */, 105 | F6E3E429198F40B5E35EB972 /* Frameworks */, 106 | ); 107 | sourceTree = ""; 108 | }; 109 | 0A6B81431D3F951700D71B72 /* Products */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 0A6B81421D3F951700D71B72 /* STMAssembleView.app */, 113 | ); 114 | name = Products; 115 | sourceTree = ""; 116 | }; 117 | 0A6B81441D3F951700D71B72 /* STMAssembleView */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 0A1C0B5F1DD4A85400465005 /* Classes */, 121 | 0A6B81481D3F951700D71B72 /* AppDelegate.h */, 122 | 0A6B81491D3F951700D71B72 /* AppDelegate.m */, 123 | 0A6B814B1D3F951700D71B72 /* ViewController.h */, 124 | 0A6B814C1D3F951700D71B72 /* ViewController.m */, 125 | 0A6B814E1D3F951700D71B72 /* Main.storyboard */, 126 | 0A6B81511D3F951700D71B72 /* Assets.xcassets */, 127 | 0A6B81531D3F951700D71B72 /* LaunchScreen.storyboard */, 128 | 0A6B81561D3F951700D71B72 /* Info.plist */, 129 | 0A2FD15A1D40748600B2E6C4 /* ScreenShots */, 130 | 0A6B81451D3F951700D71B72 /* Supporting Files */, 131 | ); 132 | path = STMAssembleView; 133 | sourceTree = ""; 134 | }; 135 | 0A6B81451D3F951700D71B72 /* Supporting Files */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 0A7E4DCE1DAA4F4D0049713F /* asExample.asv */, 139 | 0A6B81461D3F951700D71B72 /* main.m */, 140 | ); 141 | name = "Supporting Files"; 142 | sourceTree = ""; 143 | }; 144 | F6E3E429198F40B5E35EB972 /* Frameworks */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | D7A3506E929B33F2BB3AF5F3 /* libPods.a */, 148 | ); 149 | name = Frameworks; 150 | sourceTree = ""; 151 | }; 152 | FA16D0B8C8E68FFA944D5D45 /* Pods */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | A3452471D6A996A0F18B5691 /* Pods.debug.xcconfig */, 156 | 31D84A63D1A76D3603A060A1 /* Pods.release.xcconfig */, 157 | ); 158 | name = Pods; 159 | sourceTree = ""; 160 | }; 161 | /* End PBXGroup section */ 162 | 163 | /* Begin PBXNativeTarget section */ 164 | 0A6B81411D3F951700D71B72 /* STMAssembleView */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = 0A6B81591D3F951700D71B72 /* Build configuration list for PBXNativeTarget "STMAssembleView" */; 167 | buildPhases = ( 168 | 337BE6BECA72B41961083872 /* Check Pods Manifest.lock */, 169 | 0A6B813E1D3F951700D71B72 /* Sources */, 170 | 0A6B813F1D3F951700D71B72 /* Frameworks */, 171 | 0A6B81401D3F951700D71B72 /* Resources */, 172 | 64FFAF4C86C3F1A4D6551325 /* Embed Pods Frameworks */, 173 | A7CBE67B96AB36A1003ECD92 /* Copy Pods Resources */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = STMAssembleView; 180 | productName = STMAssembleView; 181 | productReference = 0A6B81421D3F951700D71B72 /* STMAssembleView.app */; 182 | productType = "com.apple.product-type.application"; 183 | }; 184 | /* End PBXNativeTarget section */ 185 | 186 | /* Begin PBXProject section */ 187 | 0A6B813A1D3F951700D71B72 /* Project object */ = { 188 | isa = PBXProject; 189 | attributes = { 190 | LastUpgradeCheck = 0730; 191 | ORGANIZATIONNAME = Starming; 192 | TargetAttributes = { 193 | 0A6B81411D3F951700D71B72 = { 194 | CreatedOnToolsVersion = 7.3.1; 195 | }; 196 | }; 197 | }; 198 | buildConfigurationList = 0A6B813D1D3F951700D71B72 /* Build configuration list for PBXProject "STMAssembleView" */; 199 | compatibilityVersion = "Xcode 3.2"; 200 | developmentRegion = English; 201 | hasScannedForEncodings = 0; 202 | knownRegions = ( 203 | en, 204 | Base, 205 | ); 206 | mainGroup = 0A6B81391D3F951700D71B72; 207 | productRefGroup = 0A6B81431D3F951700D71B72 /* Products */; 208 | projectDirPath = ""; 209 | projectRoot = ""; 210 | targets = ( 211 | 0A6B81411D3F951700D71B72 /* STMAssembleView */, 212 | ); 213 | }; 214 | /* End PBXProject section */ 215 | 216 | /* Begin PBXResourcesBuildPhase section */ 217 | 0A6B81401D3F951700D71B72 /* Resources */ = { 218 | isa = PBXResourcesBuildPhase; 219 | buildActionMask = 2147483647; 220 | files = ( 221 | 0A2FD1621D4074A900B2E6C4 /* des.png in Resources */, 222 | 0A2FD1631D4074A900B2E6C4 /* followBt.png in Resources */, 223 | 0A6B81551D3F951700D71B72 /* LaunchScreen.storyboard in Resources */, 224 | 0A2FD1601D4074A900B2E6C4 /* as.png in Resources */, 225 | 0A7E4DCF1DAA4F4D0049713F /* asExample.asv in Resources */, 226 | 0A2FD1641D4074A900B2E6C4 /* mid.png in Resources */, 227 | 0A6B81521D3F951700D71B72 /* Assets.xcassets in Resources */, 228 | 0A2FD1611D4074A900B2E6C4 /* center.png in Resources */, 229 | 0A6B81501D3F951700D71B72 /* Main.storyboard in Resources */, 230 | ); 231 | runOnlyForDeploymentPostprocessing = 0; 232 | }; 233 | /* End PBXResourcesBuildPhase section */ 234 | 235 | /* Begin PBXShellScriptBuildPhase section */ 236 | 337BE6BECA72B41961083872 /* Check Pods Manifest.lock */ = { 237 | isa = PBXShellScriptBuildPhase; 238 | buildActionMask = 2147483647; 239 | files = ( 240 | ); 241 | inputPaths = ( 242 | ); 243 | name = "Check Pods Manifest.lock"; 244 | outputPaths = ( 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | shellPath = /bin/sh; 248 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 249 | showEnvVarsInLog = 0; 250 | }; 251 | 64FFAF4C86C3F1A4D6551325 /* Embed Pods Frameworks */ = { 252 | isa = PBXShellScriptBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | ); 256 | inputPaths = ( 257 | ); 258 | name = "Embed Pods Frameworks"; 259 | outputPaths = ( 260 | ); 261 | runOnlyForDeploymentPostprocessing = 0; 262 | shellPath = /bin/sh; 263 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; 264 | showEnvVarsInLog = 0; 265 | }; 266 | A7CBE67B96AB36A1003ECD92 /* Copy Pods Resources */ = { 267 | isa = PBXShellScriptBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | ); 271 | inputPaths = ( 272 | ); 273 | name = "Copy Pods Resources"; 274 | outputPaths = ( 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | shellPath = /bin/sh; 278 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 279 | showEnvVarsInLog = 0; 280 | }; 281 | /* End PBXShellScriptBuildPhase section */ 282 | 283 | /* Begin PBXSourcesBuildPhase section */ 284 | 0A6B813E1D3F951700D71B72 /* Sources */ = { 285 | isa = PBXSourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | 0A1C0B771DD4B17D00465005 /* STMPartView.m in Sources */, 289 | 0A1C0B761DD4B17D00465005 /* STMPartMaker.m in Sources */, 290 | 0A6B814D1D3F951700D71B72 /* ViewController.m in Sources */, 291 | 0A1C0B741DD4B17D00465005 /* STMAssembleMaker.m in Sources */, 292 | 0A1C0B751DD4B17D00465005 /* STMAssembleView.m in Sources */, 293 | 0A6B814A1D3F951700D71B72 /* AppDelegate.m in Sources */, 294 | 0A6B81471D3F951700D71B72 /* main.m in Sources */, 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | }; 298 | /* End PBXSourcesBuildPhase section */ 299 | 300 | /* Begin PBXVariantGroup section */ 301 | 0A6B814E1D3F951700D71B72 /* Main.storyboard */ = { 302 | isa = PBXVariantGroup; 303 | children = ( 304 | 0A6B814F1D3F951700D71B72 /* Base */, 305 | ); 306 | name = Main.storyboard; 307 | sourceTree = ""; 308 | }; 309 | 0A6B81531D3F951700D71B72 /* LaunchScreen.storyboard */ = { 310 | isa = PBXVariantGroup; 311 | children = ( 312 | 0A6B81541D3F951700D71B72 /* Base */, 313 | ); 314 | name = LaunchScreen.storyboard; 315 | sourceTree = ""; 316 | }; 317 | /* End PBXVariantGroup section */ 318 | 319 | /* Begin XCBuildConfiguration section */ 320 | 0A6B81571D3F951700D71B72 /* Debug */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | ALWAYS_SEARCH_USER_PATHS = NO; 324 | CLANG_ANALYZER_NONNULL = YES; 325 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 326 | CLANG_CXX_LIBRARY = "libc++"; 327 | CLANG_ENABLE_MODULES = YES; 328 | CLANG_ENABLE_OBJC_ARC = YES; 329 | CLANG_WARN_BOOL_CONVERSION = YES; 330 | CLANG_WARN_CONSTANT_CONVERSION = YES; 331 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 332 | CLANG_WARN_EMPTY_BODY = YES; 333 | CLANG_WARN_ENUM_CONVERSION = YES; 334 | CLANG_WARN_INT_CONVERSION = YES; 335 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 336 | CLANG_WARN_UNREACHABLE_CODE = YES; 337 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 339 | COPY_PHASE_STRIP = NO; 340 | DEBUG_INFORMATION_FORMAT = dwarf; 341 | ENABLE_STRICT_OBJC_MSGSEND = YES; 342 | ENABLE_TESTABILITY = YES; 343 | GCC_C_LANGUAGE_STANDARD = gnu99; 344 | GCC_DYNAMIC_NO_PIC = NO; 345 | GCC_NO_COMMON_BLOCKS = YES; 346 | GCC_OPTIMIZATION_LEVEL = 0; 347 | GCC_PREPROCESSOR_DEFINITIONS = ( 348 | "DEBUG=1", 349 | "$(inherited)", 350 | ); 351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 353 | GCC_WARN_UNDECLARED_SELECTOR = YES; 354 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 355 | GCC_WARN_UNUSED_FUNCTION = YES; 356 | GCC_WARN_UNUSED_VARIABLE = YES; 357 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 358 | MTL_ENABLE_DEBUG_INFO = YES; 359 | ONLY_ACTIVE_ARCH = YES; 360 | SDKROOT = iphoneos; 361 | TARGETED_DEVICE_FAMILY = "1,2"; 362 | }; 363 | name = Debug; 364 | }; 365 | 0A6B81581D3F951700D71B72 /* Release */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | ALWAYS_SEARCH_USER_PATHS = NO; 369 | CLANG_ANALYZER_NONNULL = YES; 370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 371 | CLANG_CXX_LIBRARY = "libc++"; 372 | CLANG_ENABLE_MODULES = YES; 373 | CLANG_ENABLE_OBJC_ARC = YES; 374 | CLANG_WARN_BOOL_CONVERSION = YES; 375 | CLANG_WARN_CONSTANT_CONVERSION = YES; 376 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 377 | CLANG_WARN_EMPTY_BODY = YES; 378 | CLANG_WARN_ENUM_CONVERSION = YES; 379 | CLANG_WARN_INT_CONVERSION = YES; 380 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 381 | CLANG_WARN_UNREACHABLE_CODE = YES; 382 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 383 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 384 | COPY_PHASE_STRIP = NO; 385 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 386 | ENABLE_NS_ASSERTIONS = NO; 387 | ENABLE_STRICT_OBJC_MSGSEND = YES; 388 | GCC_C_LANGUAGE_STANDARD = gnu99; 389 | GCC_NO_COMMON_BLOCKS = YES; 390 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 391 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 392 | GCC_WARN_UNDECLARED_SELECTOR = YES; 393 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 394 | GCC_WARN_UNUSED_FUNCTION = YES; 395 | GCC_WARN_UNUSED_VARIABLE = YES; 396 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 397 | MTL_ENABLE_DEBUG_INFO = NO; 398 | SDKROOT = iphoneos; 399 | TARGETED_DEVICE_FAMILY = "1,2"; 400 | VALIDATE_PRODUCT = YES; 401 | }; 402 | name = Release; 403 | }; 404 | 0A6B815A1D3F951700D71B72 /* Debug */ = { 405 | isa = XCBuildConfiguration; 406 | baseConfigurationReference = A3452471D6A996A0F18B5691 /* Pods.debug.xcconfig */; 407 | buildSettings = { 408 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 409 | INFOPLIST_FILE = STMAssembleView/Info.plist; 410 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 411 | PRODUCT_BUNDLE_IDENTIFIER = com.starming.STMAssembleView; 412 | PRODUCT_NAME = "$(TARGET_NAME)"; 413 | }; 414 | name = Debug; 415 | }; 416 | 0A6B815B1D3F951700D71B72 /* Release */ = { 417 | isa = XCBuildConfiguration; 418 | baseConfigurationReference = 31D84A63D1A76D3603A060A1 /* Pods.release.xcconfig */; 419 | buildSettings = { 420 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 421 | INFOPLIST_FILE = STMAssembleView/Info.plist; 422 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 423 | PRODUCT_BUNDLE_IDENTIFIER = com.starming.STMAssembleView; 424 | PRODUCT_NAME = "$(TARGET_NAME)"; 425 | }; 426 | name = Release; 427 | }; 428 | /* End XCBuildConfiguration section */ 429 | 430 | /* Begin XCConfigurationList section */ 431 | 0A6B813D1D3F951700D71B72 /* Build configuration list for PBXProject "STMAssembleView" */ = { 432 | isa = XCConfigurationList; 433 | buildConfigurations = ( 434 | 0A6B81571D3F951700D71B72 /* Debug */, 435 | 0A6B81581D3F951700D71B72 /* Release */, 436 | ); 437 | defaultConfigurationIsVisible = 0; 438 | defaultConfigurationName = Release; 439 | }; 440 | 0A6B81591D3F951700D71B72 /* Build configuration list for PBXNativeTarget "STMAssembleView" */ = { 441 | isa = XCConfigurationList; 442 | buildConfigurations = ( 443 | 0A6B815A1D3F951700D71B72 /* Debug */, 444 | 0A6B815B1D3F951700D71B72 /* Release */, 445 | ); 446 | defaultConfigurationIsVisible = 0; 447 | defaultConfigurationName = Release; 448 | }; 449 | /* End XCConfigurationList section */ 450 | }; 451 | rootObject = 0A6B813A1D3F951700D71B72 /* Project object */; 452 | } 453 | -------------------------------------------------------------------------------- /STMAssembleView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /STMAssembleView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // STMAssembleView 4 | // 5 | // Created by Daiming on 16/7/20. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /STMAssembleView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // STMAssembleView 4 | // 5 | // Created by Daiming on 16/7/20. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/avatar.imageset/1-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/Assets.xcassets/avatar.imageset/1-1.jpeg -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/avatar.imageset/1-2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/Assets.xcassets/avatar.imageset/1-2.jpeg -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/avatar.imageset/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/Assets.xcassets/avatar.imageset/1.jpeg -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/avatar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "1.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "1-1.jpeg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "1-2.jpeg", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/starmingicon.imageset/64height-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/Assets.xcassets/starmingicon.imageset/64height-1.png -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/starmingicon.imageset/64height-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/Assets.xcassets/starmingicon.imageset/64height-2.png -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/starmingicon.imageset/64height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/Assets.xcassets/starmingicon.imageset/64height.png -------------------------------------------------------------------------------- /STMAssembleView/Assets.xcassets/starmingicon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "64height.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "64height-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "64height-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /STMAssembleView/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /STMAssembleView/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /STMAssembleView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /STMAssembleView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // STMAssembleView 4 | // 5 | // Created by Daiming on 16/7/20. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /STMAssembleView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // STMAssembleView 4 | // 5 | // Created by Daiming on 16/7/20. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "Masonry.h" 11 | #import "STMAssembleView.h" 12 | 13 | @interface ViewController () 14 | 15 | @property (nonatomic, strong) STMAssembleView *asView; 16 | 17 | @property (nonatomic, copy) NSString *asStr; 18 | @property (nonatomic, strong) NSDictionary *asDic; 19 | @property (nonatomic, strong) UIImageView *avatarImageView; 20 | @property (nonatomic, strong) UIButton *clickBt; 21 | 22 | @end 23 | 24 | @implementation ViewController 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | self.avatarImageView = [UIImageView new]; 29 | self.avatarImageView.clipsToBounds = YES; 30 | self.avatarImageView.layer.cornerRadius = 35/2; 31 | self.clickBt = [UIButton new]; 32 | 33 | [self asyncMake]; 34 | 35 | return; 36 | 37 | NSString *sentence = @"今天上班了,下午去喝咖啡。喝咖啡真是非常幸福的事情风和曰丽"; 38 | 39 | CFStringRef string = (__bridge CFStringRef)sentence; 40 | CFRange stringRange = CFRangeMake(0, [(__bridge NSString *)string length]) ; 41 | CFStringTokenizerRef tokenizerRef = CFStringTokenizerCreate(NULL, //アロケーター 42 | string, //解析的文字 43 | stringRange, //解析的范围 44 | //kCFStringTokenizerUnitWord, // 45 | kCFStringTokenizerUnitWordBoundary, 46 | //kCFStringTokenizerUnitWord,// 47 | //kCFStringTokenizerUnitSentence,// 48 | //kCFStringTokenizerAttributeLanguage, 49 | //kCFStringTokenizerUnitWord, 50 | //kCFStringTokenizerUnitParagraph 51 | CFLocaleCopyCurrent() 52 | ); 53 | CFStringTokenizerAdvanceToNextToken(tokenizerRef); 54 | //NSMutableDictionary 55 | //遍历 56 | while (1) { 57 | CFRange r = CFStringTokenizerGetCurrentTokenRange(tokenizerRef); 58 | if (r.location == kCFNotFound && r.length == 0){break;} 59 | 60 | NSString *token = [NSString stringWithString: 61 | [(__bridge NSString *)string substringWithRange: NSMakeRange(r.location, r.length)]]; 62 | if (token.length < 2) { 63 | CFStringTokenizerAdvanceToNextToken(tokenizerRef); 64 | continue; 65 | } 66 | //得到拼音 67 | CFMutableStringRef mSpell = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (__bridge CFStringRef)token); 68 | CFStringTransform(mSpell, nil, kCFStringTransformMandarinLatin, false); 69 | CFStringTransform(mSpell, nil, kCFStringTransformStripDiacritics, false); 70 | 71 | // NSLog(@"(%@) 拼音 = %@",token,(__bridge NSString *)mSpell); 72 | CFStringTokenizerAdvanceToNextToken(tokenizerRef); 73 | 74 | } 75 | 76 | CFRelease(tokenizerRef); 77 | 78 | 79 | 80 | } 81 | 82 | //- (NSArray *) 83 | 84 | - (void)asyncMake { 85 | self.asDic = @{ 86 | @"avatarImageView":self.avatarImageView, 87 | @"clickBt":self.clickBt 88 | }; 89 | //排列居中 90 | NSString *sizeStr = @"width:25,height:18"; 91 | NSString *centerStr = ASS(@"{hc(padding:30,extendWith:1)[(imageName:starmingicon,%@)][(imageName:starmingicon,%@)][(imageName:starmingicon,%@)]}",sizeStr,sizeStr,sizeStr); 92 | //嵌套组合布局 93 | NSString *midStr = @"{ht(padding:10,extendWith:2)[avatarImageView(imageName:avatar)][{vl(padding:10)[(text:戴铭,color:AAA0A3)][(text:Starming站长,color:E3DEE0,font:13)][(text:喜欢画画编程和写小说,color:E3DEE0,font:13)]}(width:210,backColor:FAF8F9,backPaddingHorizontal:10,backPaddingVertical:10,radius:8)]}"; 94 | //按钮 95 | NSString *followBtStr = @"{hc(padding:4,extendWith:1)[(imageName:starmingicon,width:14,height:10)][(text:关注,font:16,color:FFFFFF)]}"; 96 | //说明区域 97 | NSString *desStr = @"{hc(padding:5.5,extendWith:1)[(text:STMAssembleView.演示,color:E3DEE0,font:13)][(imageName:starmingicon,width:14,height:10,ignoreAlignment:left)][(text:www.starming.com星光社,color:E3DEE0,font:13)]}"; 98 | //整体组装 99 | self.asStr = ASS(@"{vc(padding:20)[%@][%@(backColor:AAA0A3,radius:8,backBorderWidth:1,backBorderColor:E3DEE0,backPaddingHorizontal:80,backPaddingVertical:20,button:)][%@][%@(ignoreAlignment:top,isFill:1)]}",midStr,followBtStr,centerStr,desStr); 100 | 101 | __weak typeof(self) weakSelf = self; 102 | [STMAssembleView fsAsync:self.asStr objects:self.asDic completion:^(STMAssembleView *asView) { 103 | [weakSelf.view addSubview:asView]; 104 | [asView mas_makeConstraints:^(MASConstraintMaker *make) { 105 | make.top.equalTo(weakSelf.view).offset(30); 106 | make.left.equalTo(weakSelf.view).offset(20); 107 | make.right.equalTo(weakSelf.view).offset(-20); 108 | make.bottom.equalTo(weakSelf.view).offset(-20); 109 | }]; 110 | }]; 111 | } 112 | 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /STMAssembleView/as.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/as.png -------------------------------------------------------------------------------- /STMAssembleView/asExample.asv: -------------------------------------------------------------------------------- 1 | { 2 | vc(padding:10) 3 | [(text:打开端口打开)] 4 | [(text:打开端口打开1)] 5 | } 6 | -------------------------------------------------------------------------------- /STMAssembleView/center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/center.png -------------------------------------------------------------------------------- /STMAssembleView/des.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/des.png -------------------------------------------------------------------------------- /STMAssembleView/followBt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/followBt.png -------------------------------------------------------------------------------- /STMAssembleView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // STMAssembleView 4 | // 5 | // Created by didi on 16/7/20. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /STMAssembleView/mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/STMAssembleView/af7c4c8b393be5be90bb1c634834c101dfcf3a66/STMAssembleView/mid.png --------------------------------------------------------------------------------