├── .gitignore ├── DYKit ├── Category │ ├── DGCategory.h │ ├── DGTextField.h │ ├── DGTextField.m │ ├── DYKit.h │ ├── DYRefreshHeader.h │ ├── DYRefreshHeader.m │ ├── NSString+CommonString.h │ ├── NSString+CommonString.m │ ├── NSString+DY.h │ ├── NSString+DY.m │ ├── NSString+DY_Size.h │ ├── NSString+DY_Size.m │ ├── UIBarButtonItem+Extension.h │ ├── UIBarButtonItem+Extension.m │ ├── UIButton+ImageAlignment.h │ ├── UIButton+ImageAlignment.m │ ├── UIColor+DY_Extension.h │ ├── UIColor+DY_Extension.m │ ├── UIImage+Extension.h │ ├── UIImage+Extension.m │ ├── UIImage+GIF.h │ ├── UIImage+GIF.m │ ├── UIImageView+CornerRadius.h │ ├── UIImageView+CornerRadius.m │ ├── UILabel+DY_Extension.h │ ├── UILabel+DY_Extension.m │ ├── UILabel+YBAttributeTextTapAction.h │ ├── UILabel+YBAttributeTextTapAction.m │ ├── UIScrollView+DGRefresh.h │ ├── UIScrollView+DGRefresh.m │ ├── UITabBar+dy_badge.h │ ├── UITabBar+dy_badge.m │ ├── UITextField+indexPath.h │ ├── UITextField+indexPath.m │ ├── UIView+Extension.h │ ├── UIView+Extension.m │ ├── UIView+HUD.h │ ├── UIView+HUD.m │ ├── UIView+dy_CornerRadius.h │ ├── UIView+dy_CornerRadius.m │ ├── UIViewController+BackButtonHandler.h │ └── UIViewController+BackButtonHandler.m ├── DYKit.h ├── DYNetWorking │ ├── DYCacheManager.h │ ├── DYCacheManager.m │ ├── DYImageScaleTools.h │ ├── DYImageScaleTools.m │ ├── DYNetworking.h │ ├── DYRequestConfig.h │ ├── DYRequestConfig.m │ ├── DYRequestConst.h │ ├── DYRequestManager.h │ ├── DYRequestManager.m │ ├── DYRequestTool.h │ ├── DYRequestTool.m │ ├── NSString+DYUTF8Encoding.h │ └── NSString+DYUTF8Encoding.m ├── DY_const.h └── class │ ├── DYAuthorizationTool.h │ ├── DYAuthorizationTool.m │ ├── DYChineseInclude.h │ ├── DYChineseInclude.m │ ├── DYCopyLable.h │ ├── DYCopyLable.m │ ├── DYCustomTabBarLb.h │ ├── DYCustomTabBarLb.m │ ├── DYHiddenView.h │ ├── DYHiddenView.m │ ├── DYLabel.h │ ├── DYLabel.m │ ├── DataMD5.h │ ├── DataMD5.m │ ├── JKCopyField.h │ ├── JKCopyField.m │ ├── JKCustomButton.h │ ├── JKCustomButton.m │ ├── KTDropdownMenuView.h │ ├── KTDropdownMenuView.m │ ├── Sparkle1.png │ ├── Sparkle2.png │ ├── Sparkle3.png │ ├── WEmitterButton.h │ ├── WEmitterButton.m │ └── class.h ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DYKit/Category/DGCategory.h: -------------------------------------------------------------------------------- 1 | // 2 | // DGCategory.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/9. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #ifndef DGCategory_h 10 | #define DGCategory_h 11 | 12 | #import "DataMD5.h" 13 | 14 | 15 | 16 | #import "DGTextField.h" 17 | #import "NSString+CommonString.h" 18 | #import "UIBarButtonItem+Extension.h" 19 | 20 | #import "UIImage+GIF.h" 21 | #import "UIButton+ImageAlignment.h" 22 | #import "UIImage+Extension.h" 23 | 24 | #import "UIScrollView+DGRefresh.h" 25 | #import "UIView+Extension.h" 26 | 27 | #import "UILabel+DY_Extension.h" 28 | 29 | #import "UIColor+DY_Extension.h" 30 | 31 | #import "UIImageView+CornerRadius.h" 32 | 33 | #import "UIView+HUD.h" 34 | 35 | #import "UIScrollView+DGRefresh.h" 36 | 37 | #import "NSObject+parse.h" 38 | 39 | #import "NSString+DY.h" 40 | #import "NSString+DY_Size.h" 41 | #import "UIImageView+CornerRadius.h" 42 | #import "UITextField+indexPath.h" 43 | 44 | #endif /* DGCategory_h */ 45 | -------------------------------------------------------------------------------- /DYKit/Category/DGTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // DGTextField.h 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/22. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DGTextField : UITextField 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/Category/DGTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // DGTextField.m 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/22. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import "DGTextField.h" 10 | 11 | @implementation DGTextField 12 | 13 | 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /DYKit/Category/DYKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYKit.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/13. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #ifndef DYKit_h 10 | #define DYKit_h 11 | //分类 12 | 13 | #import "DGCategory.h" 14 | #import "class.h" 15 | 16 | 17 | #endif /* DYKit_h */ 18 | -------------------------------------------------------------------------------- /DYKit/Category/DYRefreshHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYRefreshHeader.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/5/22. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DYRefreshHeader : MJRefreshGifHeader 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/Category/DYRefreshHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYRefreshHeader.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/5/22. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYRefreshHeader.h" 10 | 11 | @implementation DYRefreshHeader 12 | - (void)prepare { 13 | [super prepare]; 14 | 15 | // 设置普通状态的动画图片 16 | NSMutableArray *idleImages = [NSMutableArray array]; 17 | for (NSUInteger i = 1; i<=60; i++) { 18 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_anim__000%zd", i]]; 19 | [idleImages addObject:image]; 20 | } 21 | [self setImages:idleImages forState:MJRefreshStateIdle]; 22 | 23 | // 设置即将刷新状态的动画图片(一松开就会刷新的状态) 24 | NSMutableArray *refreshingImages = [NSMutableArray array]; 25 | for (NSUInteger i = 1; i<=3; i++) { 26 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_loading_0%zd", i]]; 27 | [refreshingImages addObject:image]; 28 | } 29 | [self setImages:refreshingImages forState:MJRefreshStatePulling]; 30 | 31 | // 设置正在刷新状态的动画图片 32 | [self setImages:refreshingImages forState:MJRefreshStateRefreshing]; 33 | 34 | } 35 | @end 36 | -------------------------------------------------------------------------------- /DYKit/Category/NSString+CommonString.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+CommonString.h 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/20. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @interface NSString (CommonString) 12 | 13 | 14 | - (NSURL *)DY_URL; 15 | - (NSURL *)DG_URL; 16 | 17 | #pragma mark 匹配手机号码 18 | +(BOOL)isMatch:(NSString *)str; 19 | 20 | #pragma 正则匹配用户身份证号15或18位 21 | + (BOOL)checkUserIdCard: (NSString *) idCard; 22 | /** 23 | * 秒数时间转换 24 | */ 25 | + (NSString *)distanceTimeWithBeforeTime:(double)time; 26 | //时间戳转换时间 27 | + (NSString *)distanceFormatterWithTime:(double)time; 28 | 29 | //时间戳转换时间 年月日时分 30 | + (NSString *)distanceFormatterWithHHSSTime:(double)time; 31 | //时间戳转换时间 年月日时分 秒 32 | + (NSString *)distanceFormatterWithHHMMSSTime:(double)time; 33 | //获取当前时间戳 34 | +(NSString *)currentTimeStr; 35 | 36 | 37 | /** 38 | * 过滤HTML标签 39 | */ 40 | + (NSString *)removeStringIntheHTML:(NSString *)html; 41 | 42 | /** 43 | * 随机验证码字符串 44 | */ 45 | + (NSString *)RandomString:(double)number; 46 | 47 | /** 48 | * 判断用户输入是否含有emoji 49 | */ 50 | + (BOOL)stringContainsEmoji:(NSString *)string; 51 | 52 | /** 53 | * 过滤emoji 54 | */ 55 | + (NSString *)removeStringIntheEmoji:(NSString *)string; 56 | 57 | /** 58 | * 查看当前版本号 59 | */ 60 | + (NSString *)getAppVersion; 61 | 62 | /** 63 | * 获取App的build版本 64 | */ 65 | + (NSString *)getappBuildVersion; 66 | 67 | /** 68 | * 获取App名称 69 | */ 70 | + (NSString *)getappName; 71 | 72 | /** 73 | * 判断是否为手机号码 74 | */ 75 | + (BOOL)isValidPhoneWithString:(NSString *)phoneString; 76 | 77 | /** 78 | * 判断字符串是否包含空格 79 | */ 80 | + (BOOL)isBlank:(NSString *)str; 81 | 82 | /** 83 | * 判断字符串中是否含有非法字符 84 | */ 85 | + (BOOL)isContainErrorCharacter:(NSString *)content; 86 | 87 | /** 88 | * 判断字符串中包含空格换行 89 | */ 90 | + (BOOL)isEmpty:(NSString* )string; 91 | 92 | /** 93 | * 截取字符串中的数字 94 | */ 95 | + (NSString *)getPhoneNumberFomat:(NSString *)number; 96 | //UIimage装base64的字符串 97 | +(NSString*)UIImageToBase64Str:(UIImage*)image; 98 | //通过富文本去掉标签 99 | //将HTML字符串转化为NSAttributedString富文本字符串 100 | + (NSAttributedString *)attributedStringWithHTMLString:(NSString *)htmlString; 101 | 102 | 103 | //拼接USER_ 104 | + (NSString *)addString:(NSString *)str; 105 | //截取USER_ 106 | + (NSString *)deleteString:(NSString *)str; 107 | //设置行间距 和字符间距 108 | - (NSAttributedString *)getAttributedStringWithLineSpace:(CGFloat)lineSpace kern:(CGFloat)kern; 109 | @end 110 | -------------------------------------------------------------------------------- /DYKit/Category/NSString+CommonString.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+CommonString.m 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/20. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import "NSString+CommonString.h" 10 | 11 | @implementation NSString (CommonString) 12 | - (NSURL *)DG_URL{ 13 | return [NSURL URLWithString:self]; 14 | } 15 | 16 | - (NSURL *)DY_URL{ 17 | return [NSURL URLWithString:self]; 18 | } 19 | 20 | 21 | +(BOOL)isMatch:(NSString *)str{ 22 | //正则表达式匹配11位手机号码 23 | // NSString *regex = @"^((13[0-9])|(15[^4,\\D])|(18[0,0-9]))\\d{8}$"; 24 | 25 | NSString *pattern = @"^1+[3578]+\\d{9}"; 26 | NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern]; 27 | BOOL isMatch = [pred evaluateWithObject:str]; 28 | return isMatch; 29 | } 30 | + (NSString *)distanceFormatterWithTime:(double)time{ 31 | NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; 32 | [formatter setDateStyle:NSDateFormatterMediumStyle]; 33 | [formatter setTimeStyle:NSDateFormatterShortStyle]; 34 | [formatter setDateFormat:@"yyyy年MM月dd日"];// 35 | NSDate* date = [NSDate dateWithTimeIntervalSince1970:time]; 36 | NSString* dateString = [formatter stringFromDate:date]; 37 | 38 | return dateString; 39 | } 40 | //时间戳转换时间 年月日时分 41 | + (NSString *)distanceFormatterWithHHSSTime:(double)time{ 42 | NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; 43 | [formatter setDateStyle:NSDateFormatterMediumStyle]; 44 | [formatter setTimeStyle:NSDateFormatterShortStyle]; 45 | [formatter setDateFormat:@"yyyy年MM月dd日HH时mm分"];// 46 | NSDate* date = [NSDate dateWithTimeIntervalSince1970:time]; 47 | NSString* dateString = [formatter stringFromDate:date]; 48 | return dateString; 49 | } 50 | 51 | + (NSString *)distanceFormatterWithHHMMSSTime:(double)time{ 52 | NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; 53 | [formatter setDateStyle:NSDateFormatterMediumStyle]; 54 | [formatter setTimeStyle:NSDateFormatterShortStyle]; 55 | [formatter setDateFormat:@"yyyy-MM-dd HH-mm-ss"];// 56 | NSDate* date = [NSDate dateWithTimeIntervalSince1970:time]; 57 | NSString* dateString = [formatter stringFromDate:date]; 58 | 59 | return dateString; 60 | 61 | } 62 | 63 | 64 | #pragma 正则匹配用户身份证号15或18位 65 | + (BOOL)checkUserIdCard: (NSString *) idCard 66 | { 67 | NSString *pattern = @"(^[0-9]{15}$)|([0-9]{17}([0-9]|X)$)"; 68 | NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern]; 69 | BOOL isMatch = [pred evaluateWithObject:idCard]; 70 | return isMatch; 71 | } 72 | // 秒数时间转换 73 | + (NSString *)distanceTimeWithBeforeTime:(double)time { 74 | 75 | NSTimeInterval now = [[NSDate date]timeIntervalSince1970]; 76 | double distanceTime = now - time; 77 | NSString * distanceStr; 78 | 79 | NSDate * beDate = [NSDate dateWithTimeIntervalSince1970:time]; 80 | NSDateFormatter * df = [[NSDateFormatter alloc]init]; 81 | [df setDateFormat:@"HH:mm"]; 82 | NSString * timeStr = [df stringFromDate:beDate]; 83 | 84 | [df setDateFormat:@"dd"]; 85 | NSString * nowDay = [df stringFromDate:[NSDate date]]; 86 | NSString * lastDay = [df stringFromDate:beDate]; 87 | 88 | if (distanceTime < 60) { 89 | //小于一分钟 90 | distanceStr = @"刚刚"; 91 | } else if (distanceTime <60*60) { 92 | //时间小于一个小时 93 | distanceStr = [NSString stringWithFormat:@"%ld分钟前",(long)distanceTime/60]; 94 | } else if (distanceTime <24*60*60 && [nowDay integerValue] == [lastDay integerValue]) { 95 | //时间小于一天 96 | distanceStr = [NSString stringWithFormat:@"今天 %@",timeStr]; 97 | } else if (distanceTime<24*60*60*2 && [nowDay integerValue] != [lastDay integerValue]){ 98 | 99 | if ([nowDay integerValue] - [lastDay integerValue] ==1 || ([lastDay integerValue] - [nowDay integerValue] > 10 && [nowDay integerValue] == 1)) { 100 | distanceStr = [NSString stringWithFormat:@"昨天 %@",timeStr]; 101 | } else { 102 | [df setDateFormat:@"MM-dd HH:mm"]; 103 | distanceStr = [df stringFromDate:beDate]; 104 | } 105 | 106 | } else if (distanceTime <24*60*60*365) { 107 | [df setDateFormat:@"MM-dd HH:mm"]; 108 | distanceStr = [df stringFromDate:beDate]; 109 | } else { 110 | [df setDateFormat:@"yyyy-MM-dd HH:mm"]; 111 | distanceStr = [df stringFromDate:beDate]; 112 | } 113 | return distanceStr; 114 | } 115 | 116 | // 过滤 HTML 标签 117 | + (NSString *)removeStringIntheHTML:(NSString *)html { 118 | NSScanner *theScanner; 119 | NSString *text = nil; 120 | theScanner = [NSScanner scannerWithString:html]; 121 | while ([theScanner isAtEnd] == NO) { 122 | [theScanner scanUpToString:@"<" intoString:NULL] ; 123 | [theScanner scanUpToString:@">" intoString:&text] ; 124 | html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>", text]withString:@""]; 125 | } 126 | 127 | NSString *str1 = [html stringByReplacingOccurrencesOfString:@" " withString:@" "]; 128 | NSString *str2 = [str1 stringByReplacingOccurrencesOfString:@"—" withString:@"—"]; 129 | NSString *str3 = [str2 stringByReplacingOccurrencesOfString:@"“" withString:@"“"]; 130 | NSString *str4 = [str3 stringByReplacingOccurrencesOfString:@"…" withString:@"…"]; 131 | NSString *str5 = [str4 stringByReplacingOccurrencesOfString:@"”" withString:@"”"]; 132 | NSString *str6 = [str5 stringByReplacingOccurrencesOfString:@"•" withString:@"•"]; 133 | NSString *str7 = [str6 stringByReplacingOccurrencesOfString:@"ω" withString:@"Ω"]; 134 | 135 | return str7; 136 | } 137 | 138 | // 随机字符串 139 | + (NSString *)RandomString:(double)number { 140 | NSString *string = [[NSString alloc]init]; 141 | for (int i = 0; i < number; i++) { 142 | int number = arc4random() % 36; 143 | if (number < 10) { 144 | int figure = arc4random() % 10; 145 | NSString *tempString = [NSString stringWithFormat:@"%d", figure]; 146 | string = [string stringByAppendingString:tempString]; 147 | 148 | } else { 149 | int figure = (arc4random() % 26) + 97; 150 | char character = figure; 151 | NSString *tempString = [NSString stringWithFormat:@"%c", character]; 152 | string = [string stringByAppendingString:tempString]; 153 | } 154 | } 155 | return string; 156 | } 157 | 158 | // 判断用户输入是否含有emoji 159 | + (BOOL)stringContainsEmoji:(NSString *)string { 160 | __block BOOL returnValue = NO; 161 | [string enumerateSubstringsInRange:NSMakeRange(0, [string length]) 162 | options:NSStringEnumerationByComposedCharacterSequences 163 | usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { 164 | const unichar hs = [substring characterAtIndex:0]; 165 | if (0xd800 <= hs && hs <= 0xdbff) { 166 | if (substring.length > 1) { 167 | const unichar ls = [substring characterAtIndex:1]; 168 | const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000; 169 | if (0x1d000 <= uc && uc <= 0x1f77f) { 170 | returnValue = YES; 171 | } 172 | } 173 | } else if (substring.length > 1) { 174 | const unichar ls = [substring characterAtIndex:1]; 175 | if (ls == 0x20e3) { 176 | returnValue = YES; 177 | } 178 | } else { 179 | if (0x2100 <= hs && hs <= 0x27ff) { 180 | returnValue = YES; 181 | } else if (0x2B05 <= hs && hs <= 0x2b07) { 182 | returnValue = YES; 183 | } else if (0x2934 <= hs && hs <= 0x2935) { 184 | returnValue = YES; 185 | } else if (0x3297 <= hs && hs <= 0x3299) { 186 | returnValue = YES; 187 | } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) { 188 | returnValue = YES; 189 | } 190 | } 191 | }]; 192 | return returnValue; 193 | } 194 | 195 | // 过滤emoji 196 | + (NSString *)removeStringIntheEmoji:(NSString *)string { 197 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]" options:NSRegularExpressionCaseInsensitive error:nil]; 198 | NSString *modifiedString = [regex stringByReplacingMatchesInString:string 199 | options:0 200 | range:NSMakeRange(0, [string length]) 201 | withTemplate:@""]; 202 | return modifiedString; 203 | } 204 | 205 | // 查看App的当前版本号 206 | + (NSString *)getAppVersion { 207 | NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary]; 208 | NSString *appVersion = [infoDic objectForKey:@"CFBundleShortVersionString"]; 209 | return appVersion; 210 | } 211 | 212 | // 获取App的build版本 213 | + (NSString *)getappBuildVersion { 214 | NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary]; 215 | NSString *appBuildVersion = [infoDic objectForKey:@"CFBundleVersion"]; 216 | return appBuildVersion; 217 | } 218 | 219 | // 获取App名称 220 | + (NSString *)getappName { 221 | NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary]; 222 | NSString *appName = [infoDic objectForKey:@"CFBundleDisplayName"]; 223 | return appName; 224 | } 225 | 226 | // 判断是否为手机号 227 | + (BOOL)isValidPhoneWithString:(NSString *)phoneString 228 | { 229 | 230 | /** 231 | * 手机号码 232 | * 移动:134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188 233 | * 联通:130,131,132,152,155,156,185,186 234 | * 电信:133,1349,153,180,189 235 | */ 236 | NSString * MOBILE = @"^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$"; 237 | /** 238 | 10 * 中国移动:China Mobile 239 | 11 * 134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188 240 | 12 */ 241 | NSString * CM = @"^((13[4-9])|(147)|(15[0-2,7-9])|(178)|(18[2-4,7-8]))\\d{8}|(1705)\\d{7}$"; 242 | /** 243 | 15 * 中国联通:China Unicom 244 | 16 * 130,131,132,152,155,156,185,186 245 | 17 */ 246 | NSString * CU = @"^((13[0-2])|(145)|(15[5-6])|(176)|(18[5,6]))\\d{8}|(1709)\\d{7}$"; 247 | /** 248 | * 中国电信:China Telecom 249 | * 133,1349,153,180,189,177,181(增加) 250 | */ 251 | NSString * CT = @"^((133)|(153)|(177)|(18[0,1,9]))\\d{8}$"; 252 | /** 253 | 25 * 大陆地区固话及小灵通 254 | 26 * 区号:010,020,021,022,023,024,025,027,028,029 255 | 27 * 号码:七位或八位 256 | 28 */ 257 | 258 | // NSString * PHS = @"^0(10|2[0-5789]|\\d{3})\\d{7,8}$"; 259 | 260 | NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE]; 261 | NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM]; 262 | NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU]; 263 | NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT]; 264 | 265 | if (([regextestmobile evaluateWithObject:phoneString] == YES) 266 | || ([regextestcm evaluateWithObject:phoneString] == YES) 267 | || ([regextestct evaluateWithObject:phoneString] == YES) 268 | || ([regextestcu evaluateWithObject:phoneString] == YES)) 269 | { 270 | return YES; 271 | } 272 | else 273 | { 274 | return NO; 275 | } 276 | } 277 | 278 | 279 | // 判断字符串是否包含空格 280 | + (BOOL)isBlank:(NSString *)str { 281 | NSRange _range = [str rangeOfString:@" "]; 282 | if (_range.location != NSNotFound) { 283 | return YES; 284 | } 285 | else { 286 | return NO; 287 | } 288 | } 289 | 290 | // 判断字符串中是否含有非法字符 291 | + (BOOL)isContainErrorCharacter:(NSString *)content { 292 | NSString *str =@"^[A-Za-z0-9\\u4e00-\u9fa5]+$"; 293 | NSPredicate* emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", str]; 294 | if (![emailTest evaluateWithObject:content]) { 295 | return YES; 296 | } 297 | return NO; 298 | } 299 | 300 | // 判断字符串中包含空格换行 301 | + (BOOL)isEmpty:(NSString* )string { 302 | if (!string) { 303 | return true; 304 | } 305 | else { 306 | NSCharacterSet *chara = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 307 | NSString* str =[string stringByTrimmingCharactersInSet:chara]; 308 | if (str.length ==0) { 309 | return true; 310 | } 311 | else{ 312 | return false; 313 | } 314 | } 315 | } 316 | 317 | // 截取字符串中的数字 318 | + (NSString *)getPhoneNumberFomat:(NSString *)number { 319 | NSMutableArray *characters = [NSMutableArray array]; 320 | NSMutableString *mutStr = [NSMutableString string]; 321 | // 分离出字符串中的所有字符,并存储到数组characters中 322 | for (int i = 0; i < number.length; i ++) { 323 | NSString *subString = [number substringToIndex:i + 1]; 324 | 325 | subString = [subString substringFromIndex:i]; 326 | 327 | [characters addObject:subString]; 328 | } 329 | // 利用正则表达式,匹配数组中的每个元素,判断是否是数字,将数字拼接在可变字符串mutStr中 330 | for (NSString *b in characters) { 331 | NSString *regex = @"^[0-9]*$"; 332 | NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];// 谓词 333 | BOOL isShu = [pre evaluateWithObject:b];// 对b进行谓词运算 334 | if (isShu) { 335 | [mutStr appendString:b]; 336 | } 337 | } 338 | return mutStr; 339 | } 340 | 341 | 342 | +(NSString*)UIImageToBase64Str:(UIImage*)image 343 | { 344 | NSData *data = UIImageJPEGRepresentation(image, 1.0f); 345 | NSString *encodedImageStr = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; 346 | return encodedImageStr; 347 | } 348 | + (NSAttributedString *)attributedStringWithHTMLString:(NSString *)htmlString 349 | { 350 | NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType, 351 | NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding) }; 352 | 353 | NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding]; 354 | 355 | return [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil]; 356 | } 357 | 358 | 359 | //拼接USER_ 360 | + (NSString *)addString:(NSString *)str{ 361 | return [NSString stringWithFormat:@"USER_%@",str]; 362 | } 363 | //截取USER_ 364 | + (NSString *)deleteString:(NSString *)str{ 365 | return [str substringFromIndex:5]; 366 | } 367 | 368 | 369 | 370 | //获取当前时间戳 371 | +(NSString *)currentTimeStr{ 372 | NSDate* date = [NSDate dateWithTimeIntervalSinceNow:0];//获取当前时间0秒后的时间 373 | NSTimeInterval time=[date timeIntervalSince1970];// *1000 是精确到毫秒,不乘就是精确到秒 374 | NSString *timeString = [NSString stringWithFormat:@"%.0f", time]; 375 | return timeString; 376 | } 377 | 378 | - (NSAttributedString *)getAttributedStringWithLineSpace:(CGFloat)lineSpace kern:(CGFloat)kern{ 379 | NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; 380 | paragraphStyle.lineSpacing = lineSpace; 381 | NSDictionary *attriDict = @{NSParagraphStyleAttributeName:paragraphStyle,NSKernAttributeName:@(kern)}; 382 | NSMutableAttributedString *attributeSting = [[NSMutableAttributedString alloc] initWithString:self attributes:attriDict]; 383 | return attributeSting; 384 | } 385 | @end 386 | -------------------------------------------------------------------------------- /DYKit/Category/NSString+DY.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DY.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/4/18. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (DY) 12 | - (NSURL *)DY_URL; 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/Category/NSString+DY.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DY.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/4/18. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "NSString+DY.h" 10 | 11 | @implementation NSString (DY) 12 | - (NSURL *)DY_URL{ 13 | return [NSURL URLWithString:self]; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /DYKit/Category/NSString+DY_Size.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DY_Size.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/14. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (DY_Size) 12 | 13 | /** 14 | * 计算文字高度,可以处理计算带行间距的等属性 15 | */ 16 | - (CGSize)boundingRectWithSize:(CGSize)size paragraphStyle:(NSMutableParagraphStyle *)paragraphStyle font:(UIFont*)font; 17 | ///** 18 | // * 计算文字高度,可以处理计算带行间距的 19 | // */ 20 | //- (CGSize)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing; 21 | ///** 22 | // * 计算最大行数文字高度,可以处理计算带行间距的 23 | // */ 24 | //- (CGFloat)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing maxLines:(NSInteger)maxLines; 25 | - (CGSize)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing; 26 | /** 27 | * 计算是否超过一行 28 | */ 29 | - (BOOL)isMoreThanOneLineWithSize:(CGSize)size font:(UIFont *)font lineSpaceing:(CGFloat)lineSpacing; 30 | @end 31 | -------------------------------------------------------------------------------- /DYKit/Category/NSString+DY_Size.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DY_Size.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/14. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "NSString+DY_Size.h" 10 | 11 | @implementation NSString (DY_Size) 12 | /** 13 | * 计算文字高度,可以处理计算带字符间距的 14 | */ 15 | - (CGSize)boundingRectWithSize:(CGSize)size paragraphStyle:(NSMutableParagraphStyle *)paragraphStyle font:(UIFont*)font 16 | { 17 | NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:self]; 18 | [attributeString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, self.length)]; 19 | [attributeString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, self.length)]; 20 | NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading; 21 | CGRect rect = [attributeString boundingRectWithSize:size options:options context:nil]; 22 | 23 | // NSLog(@"size:%@", NSStringFromCGSize(rect.size)); 24 | 25 | //文本的高度减去字体高度小于等于行间距,判断为当前只有1行 26 | if ((rect.size.height - font.lineHeight) <= paragraphStyle.lineSpacing) { 27 | if ([self containChinese:self]) { //如果包含中文 28 | rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height-paragraphStyle.lineSpacing); 29 | } 30 | } 31 | 32 | 33 | return rect.size; 34 | } 35 | 36 | 37 | 38 | /** 39 | * 计算文字高度,可以处理计算带行间距的 40 | */ 41 | - (CGSize)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing 42 | { 43 | NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:self]; 44 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 45 | paragraphStyle.lineSpacing = lineSpacing; 46 | [attributeString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, self.length)]; 47 | [attributeString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, self.length)]; 48 | NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading; 49 | CGRect rect = [attributeString boundingRectWithSize:size options:options context:nil]; 50 | 51 | // NSLog(@"size:%@", NSStringFromCGSize(rect.size)); 52 | 53 | //文本的高度减去字体高度小于等于行间距,判断为当前只有1行 54 | if ((rect.size.height - font.lineHeight) <= paragraphStyle.lineSpacing) { 55 | if ([self containChinese:self]) { //如果包含中文 56 | rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height-paragraphStyle.lineSpacing); 57 | } 58 | } 59 | 60 | 61 | return rect.size; 62 | } 63 | 64 | 65 | 66 | /** 67 | * 计算最大行数文字高度,可以处理计算带行间距的 68 | */ 69 | - (CGFloat)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing maxLines:(NSInteger)maxLines{ 70 | 71 | if (maxLines <= 0) { 72 | return 0; 73 | } 74 | 75 | CGFloat maxHeight = font.lineHeight * maxLines + lineSpacing * (maxLines - 1); 76 | 77 | CGSize orginalSize = [self boundingRectWithSize:size font:font lineSpacing:lineSpacing]; 78 | 79 | if ( orginalSize.height >= maxHeight ) { 80 | return maxHeight; 81 | }else{ 82 | return orginalSize.height; 83 | } 84 | } 85 | 86 | /** 87 | * 计算是否超过一行 88 | */ 89 | - (BOOL)isMoreThanOneLineWithSize:(CGSize)size font:(UIFont *)font lineSpaceing:(CGFloat)lineSpacing{ 90 | 91 | if ( [self boundingRectWithSize:size font:font lineSpacing:lineSpacing].height > font.lineHeight ) { 92 | return YES; 93 | }else{ 94 | return NO; 95 | } 96 | } 97 | 98 | //判断是否包含中文 99 | - (BOOL)containChinese:(NSString *)str { 100 | for(int i=0; i< [str length];i++){ 101 | int a = [str characterAtIndex:i]; 102 | if( a > 0x4e00 && a < 0x9fff){ 103 | return YES; 104 | } 105 | } 106 | return NO; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /DYKit/Category/UIBarButtonItem+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIBarButtonItem+Extension.h 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/21. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIBarButtonItem (Extension) 12 | + (instancetype) initWithImage:(NSString *)image highImage:(NSString *)highImage target:(id)target action:(SEL)action; 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/Category/UIBarButtonItem+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIBarButtonItem+Extension.m 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/21. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import "UIBarButtonItem+Extension.h" 10 | #import "UIView+Extension.h" 11 | @implementation UIBarButtonItem (Extension) 12 | 13 | 14 | + (instancetype)initWithImage:(NSString *)image highImage:(NSString *)highImage target:(id)target action:(SEL)action{ 15 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 16 | [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal]; 17 | [btn setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateSelected]; 18 | btn.size = CGSizeMake(15, 15); 19 | btn.contentMode = UIViewContentModeScaleAspectFill; 20 | [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; 21 | return [[self alloc] initWithCustomView:btn]; 22 | 23 | } 24 | @end 25 | -------------------------------------------------------------------------------- /DYKit/Category/UIButton+ImageAlignment.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+ImageAlignment.h 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/20. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, DYImageAlignment){ 12 | 13 | DYButtonEdgeInsetsStyleTop, // image在上,label在下 14 | DYButtonEdgeInsetsStyleLeft, // image在左,label在右 15 | DYButtonEdgeInsetsStyleBottom, // image在下,label在上 16 | DYButtonEdgeInsetsStyleRight // image在右,label在左 17 | }; 18 | @interface UIButton (ImageAlignment) 19 | @property (nonatomic, assign) NSTimeInterval custom_acceptEventInterval;//可以用这个给重复点击加间隔 20 | 21 | /** 22 | * 设置Button文字和图片的方向和距离 23 | * 24 | * @param type 图片所在的方向(上、下、左、右) 25 | * @param range 图片和文字的距离 26 | /** 27 | * 设置button的titleLabel和imageView的布局样式,及间距 28 | * 29 | * @param style titleLabel和imageView的布局样式 30 | * @param space titleLabel和imageView的间距 31 | */ 32 | - (void)layoutButtonWithEdgeInsetsStyle:(DYImageAlignment)style 33 | imageTitleSpace:(CGFloat)space; 34 | 35 | /* 36 | * 设置Button文字和图片的方向和距离 37 | * 38 | * @param type 图片所在的方向(上、下、左、右) 39 | * @param range 图片和文字的距离 40 | /** 41 | * 设置button的titleLabel和imageView的布局样式,及间距 42 | * 43 | * @param style titleLabel和imageView的布局样式 44 | * @param space titleLabel和imageView的间距 45 | 46 | imageTopEdg 图片拒上距离 (主要是为了调整,button里面图片小的情况下使用) 47 | imageBottomSpace 图片拒下距离 48 | */ 49 | - (void)layoutButtonSizeWithEdgeInsetsStyle:(DYImageAlignment)style imageTitleSpace:(CGFloat)space imageTopEdg:(CGFloat)imageTopSpace imageBottomEdg:(CGFloat)imageBottomSpace; 50 | /** 51 | * 设置带图片的 Button (带方法) 52 | * 53 | * @param title 文字 54 | * @param normalTitleColor 默认文字颜色 55 | * @param highTitleColor 高亮文字颜色 56 | * @param normalImage 默认图片 57 | * @param selectedImage 高亮图片 58 | * @param selected 点击后做的事情 59 | */ 60 | + (instancetype)initWithTitle:(NSString *)title normalTitleColor:(UIColor*)normalTitleColor highTitleColor:(UIColor *)highTitleColor normalImage:(NSString *)normalImage selectedImage:(NSString *)selectedImage target:(id)target selected:(SEL)selected; 61 | 62 | + (instancetype)initWithTitle:(NSString *)title image:(NSString *)image target:(id)target action:(SEL)action frame:(CGRect)frame; 63 | +(instancetype)initWithTitle:(NSString *)title image:(NSString *)image target:(id)target action:(SEL)action; 64 | /** 65 | 16进制文本颜色 自适应字体大小 66 | 67 | @param title <#title description#> 68 | @param font <#font description#> 69 | @param norHexeColor <#norHexeColor description#> 70 | @param seletedHexColor <#seletedHexColor description#> 71 | @param target <#target description#> 72 | @param action <#action description#> 73 | @return <#return value description#> 74 | */ 75 | + (instancetype)hexWithTitle:(NSString *)title font:(CGFloat)font norHexColor:(NSString*)norHexeColor seletedHexColor:(NSString *) seletedHexColor target:(id)target action:(SEL)action; 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /DYKit/Category/UIButton+ImageAlignment.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+ImageAlignment.m 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/20. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import "UIButton+ImageAlignment.h" 10 | #import 11 | 12 | @interface UIButton() 13 | @property (nonatomic, assign) NSTimeInterval custom_acceptEventTime; 14 | @end 15 | @implementation UIButton (ImageAlignment) 16 | 17 | + (void)load{ 18 | Method systemMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:)); 19 | SEL sysSEL = @selector(sendAction:to:forEvent:); 20 | Method customMethod = class_getInstanceMethod(self, @selector(custom_sendAction:to:forEvent:)); 21 | 22 | SEL customSEL = @selector(custom_sendAction:to:forEvent:); 23 | 24 | //添加方法 语法:BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) 若添加成功则返回No 25 | // cls:被添加方法的类 name:被添加方法方法名 imp:被添加方法的实现函数 types:被添加方法的实现函数的返回值类型和参数类型的字符串 26 | 27 | BOOL didAddMethod = class_addMethod(self, sysSEL, method_getImplementation(customMethod),method_getTypeEncoding(customMethod)); 28 | //如果系统中改方法已经存在了,则替换系统的方法,语法 IMP class_replaceMethod(Class cls, SEL name, IMP imp,const char *types) 29 | if (didAddMethod) { 30 | class_replaceMethod(self, customSEL, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod)); 31 | }else{ 32 | method_exchangeImplementations(systemMethod, customMethod); 33 | } 34 | } 35 | 36 | 37 | - (NSTimeInterval)custom_acceptEventInterval{ 38 | return [objc_getAssociatedObject(self, "UIControl_acceptEventInterval")doubleValue]; 39 | } 40 | - (void)setCustom_acceptEventInterval:(NSTimeInterval)custom_acceptEventInterval{ 41 | objc_setAssociatedObject(self, "UIControl_acceptEventInterval", @(custom_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 42 | } 43 | 44 | - (NSTimeInterval)custom_acceptEventTime{ 45 | return [objc_getAssociatedObject(self, "UIControl_acceptEventTime")doubleValue]; 46 | } 47 | - (void)setCustom_acceptEventTime:(NSTimeInterval)custom_acceptEventTime{ 48 | objc_setAssociatedObject(self, "UIControl_acceptEventTime", @(custom_acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 49 | } 50 | 51 | 52 | - (void)custom_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{ 53 | 54 | // 如果想要设置统一的间隔时间,可以在此处加上以下几句 55 | // 值得提醒一下:如果这里设置了统一的时间间隔,会影响UISwitch,如果想统一设置,又不想影响UISwitch,建议将UIControl分类,改成UIButton分类,实现方法是一样的 56 | // if (self.custom_acceptEventInterval <= 0) { 57 | // // 如果没有自定义时间间隔,则默认为2秒 58 | // self.custom_acceptEventInterval = 2; 59 | // } 60 | 61 | // 是否小于设定的时间间隔 62 | BOOL needSendAction = (NSDate.date.timeIntervalSince1970 - self.custom_acceptEventTime >= self.custom_acceptEventInterval); 63 | 64 | // 更新上一次点击时间戳 65 | if (self.custom_acceptEventInterval > 0) { 66 | self.custom_acceptEventTime = NSDate.date.timeIntervalSince1970; 67 | } 68 | // 两次点击的时间间隔小于设定的时间间隔时,才执行响应事件 69 | if (needSendAction) { 70 | [self custom_sendAction:action to:target forEvent:event]; 71 | } 72 | } 73 | - (void)layoutButtonWithEdgeInsetsStyle:(DYImageAlignment)style 74 | imageTitleSpace:(CGFloat)space 75 | { 76 | // self.backgroundColor = [UIColor cyanColor]; 77 | 78 | /** 79 | * 前置知识点:titleEdgeInsets是title相对于其上下左右的inset,跟tableView的contentInset是类似的, 80 | * 如果只有title,那它上下左右都是相对于button的,image也是一样; 81 | * 如果同时有image和label,那这时候image的上左下是相对于button,右边是相对于label的;title的上右下是相对于button,左边是相对于image的。 82 | */ 83 | 84 | 85 | // 1. 得到imageView和titleLabel的宽、高 86 | CGFloat imageWith = self.imageView.frame.size.width ; 87 | CGFloat imageHeight = self.imageView.frame.size.height ; 88 | 89 | CGFloat labelWidth = 0.0; 90 | CGFloat labelHeight = 0.0; 91 | if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { 92 | // 由于iOS8中titleLabel的size为0,用下面的这种设置 93 | labelWidth = self.titleLabel.intrinsicContentSize.width; 94 | labelHeight = self.titleLabel.intrinsicContentSize.height; 95 | } else { 96 | labelWidth = self.titleLabel.frame.size.width; 97 | labelHeight = self.titleLabel.frame.size.height; 98 | } 99 | 100 | // 2. 声明全局的imageEdgeInsets和labelEdgeInsets 101 | UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero; 102 | UIEdgeInsets labelEdgeInsets = UIEdgeInsetsZero; 103 | 104 | // 3. 根据style和space得到imageEdgeInsets和labelEdgeInsets的值 105 | switch (style) { 106 | case DYButtonEdgeInsetsStyleTop: 107 | { 108 | imageEdgeInsets = UIEdgeInsetsMake(-labelHeight-space/2.0, 0, 0, -labelWidth); 109 | labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith, -imageHeight-space/2.0, 0); 110 | } 111 | break; 112 | case DYButtonEdgeInsetsStyleLeft: 113 | { 114 | imageEdgeInsets = UIEdgeInsetsMake(0, -space/2.0, 0, space/2.0); 115 | labelEdgeInsets = UIEdgeInsetsMake(0, space/2.0, 0, -space/2.0); 116 | } 117 | break; 118 | case DYButtonEdgeInsetsStyleBottom: 119 | { 120 | imageEdgeInsets = UIEdgeInsetsMake(0, 0, -labelHeight-space/2.0, -labelWidth); 121 | labelEdgeInsets = UIEdgeInsetsMake(-imageHeight-space/2.0, -imageWith, 0, 0); 122 | } 123 | break; 124 | case DYButtonEdgeInsetsStyleRight: 125 | { 126 | imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth+space/2.0, 0, -labelWidth-space/2.0); 127 | labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith-space/2.0, 0, imageWith+space/2.0); 128 | } 129 | break; 130 | default: 131 | break; 132 | } 133 | 134 | // 4. 赋值 135 | self.titleEdgeInsets = labelEdgeInsets; 136 | self.imageEdgeInsets = imageEdgeInsets; 137 | } 138 | - (void)layoutButtonSizeWithEdgeInsetsStyle:(DYImageAlignment)style imageTitleSpace:(CGFloat)space imageTopEdg:(CGFloat)imageTopSpace imageBottomEdg:(CGFloat)imageBottomSpace 139 | { 140 | // self.backgroundColor = [UIColor cyanColor]; 141 | 142 | /** 143 | * 前置知识点:titleEdgeInsets是title相对于其上下左右的inset,跟tableView的contentInset是类似的, 144 | * 如果只有title,那它上下左右都是相对于button的,image也是一样; 145 | * 如果同时有image和label,那这时候image的上左下是相对于button,右边是相对于label的;title的上右下是相对于button,左边是相对于image的。 146 | */ 147 | 148 | CGFloat imageWith = self.imageView.frame.size.width ; 149 | CGFloat imageHeight = self.imageView.frame.size.height ; 150 | 151 | CGFloat labelWidth = 0.0; 152 | CGFloat labelHeight = 0.0; 153 | if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { 154 | // 由于iOS8中titleLabel的size为0,用下面的这种设置 155 | labelWidth = self.titleLabel.intrinsicContentSize.width; 156 | labelHeight = self.titleLabel.intrinsicContentSize.height; 157 | } else { 158 | labelWidth = self.titleLabel.frame.size.width; 159 | labelHeight = self.titleLabel.frame.size.height; 160 | } 161 | 162 | // 2. 声明全局的imageEdgeInsets和labelEdgeInsets 163 | UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero; 164 | UIEdgeInsets labelEdgeInsets = UIEdgeInsetsZero; 165 | 166 | // 3. 根据style和space得到imageEdgeInsets和labelEdgeInsets的值 167 | switch (style) { 168 | case DYButtonEdgeInsetsStyleTop: 169 | { 170 | imageEdgeInsets = UIEdgeInsetsMake(-labelHeight-space/2.0, 0, 0, -labelWidth); 171 | labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith, -imageHeight-space/2.0, 0); 172 | } 173 | break; 174 | case DYButtonEdgeInsetsStyleLeft: 175 | { 176 | imageEdgeInsets = UIEdgeInsetsMake(imageTopSpace, -space/2.0, imageBottomSpace, space/2.0); 177 | labelEdgeInsets = UIEdgeInsetsMake(0, space/2.0, 0, -space/2.0); 178 | } 179 | break; 180 | case DYButtonEdgeInsetsStyleBottom: 181 | { 182 | imageEdgeInsets = UIEdgeInsetsMake(0, 0, -labelHeight-space/2.0, -labelWidth); 183 | labelEdgeInsets = UIEdgeInsetsMake(-imageHeight-space/2.0, -imageWith, 0, 0); 184 | } 185 | break; 186 | case DYButtonEdgeInsetsStyleRight: 187 | { 188 | imageEdgeInsets = UIEdgeInsetsMake(imageTopSpace, labelWidth+space/2.0, imageBottomSpace, -labelWidth-space/2.0); 189 | labelEdgeInsets = UIEdgeInsetsMake(0, -imageWith-space/2.0, 0, imageWith+space/2.0); 190 | } 191 | break; 192 | default: 193 | break; 194 | } 195 | 196 | // 4. 赋值 197 | self.titleEdgeInsets = labelEdgeInsets; 198 | self.imageEdgeInsets = imageEdgeInsets; 199 | } 200 | 201 | 202 | 203 | + (instancetype)initWithTitle:(NSString *)title normalTitleColor:(UIColor *)normalTitleColor highTitleColor:(UIColor *)highTitleColor normalImage:(NSString *)normalImage selectedImage:(NSString *)selectedImage target:(id)target selected:(SEL)selected{ 204 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 205 | [btn setTitle:title forState:UIControlStateNormal]; 206 | [btn setTitleColor:normalTitleColor forState:UIControlStateNormal]; 207 | [btn setTitleColor:highTitleColor forState:UIControlStateSelected]; 208 | [btn setImage:[UIImage imageNamed:normalImage] forState:UIControlStateNormal]; 209 | [btn setImage:[UIImage imageNamed:selectedImage] forState:UIControlStateSelected]; 210 | [btn addTarget:target action:selected forControlEvents:UIControlEventTouchUpInside]; 211 | return btn; 212 | } 213 | 214 | +(instancetype)initWithTitle:(NSString *)title image:(NSString *)image target:(id)target action:(SEL)action{ 215 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 216 | [btn setTitle:title forState:UIControlStateNormal]; 217 | [btn setImage:[UIImage imageNamed:image] forState:UIControlStateNormal]; 218 | 219 | btn.imageView.contentMode = UIViewContentModeScaleAspectFit; 220 | [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; 221 | 222 | 223 | return btn; 224 | } 225 | 226 | + (instancetype)initWithTitle:(NSString *)title image:(NSString *)image target:(id)target action:(SEL)action frame:(CGRect)frame{ 227 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 228 | [btn setTitle:title forState:UIControlStateNormal]; 229 | // [btn setImage:[UIImage imageNamed:image] forState:UIControlStateNormal]; 230 | [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal]; 231 | // [btn sizeToFit]; 232 | [btn setFrame:frame]; 233 | // btn.imageView.contentMode = UIViewContentModeScaleAspectFit; 234 | [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; 235 | // btn.frame = frame; 236 | return btn; 237 | } 238 | + (instancetype)hexWithTitle:(NSString *)title font:(CGFloat)font norHexColor:(NSString*)norHexeColor seletedHexColor:(NSString *) seletedHexColor target:(id)target action:(SEL)action{ 239 | 240 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 241 | 242 | [btn setTitle:title forState:UIControlStateNormal]; 243 | 244 | [btn setTitleColor:[UIColor DY_colorWithHexString:norHexeColor] forState:UIControlStateNormal]; 245 | 246 | [btn setTitleColor:[UIColor DY_colorWithHexString:seletedHexColor] forState:UIControlStateSelected]; 247 | 248 | btn.titleLabel.font = [UIFont systemFontOfSize:FontSize(font)]; 249 | [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; 250 | return btn; 251 | 252 | } 253 | @end 254 | -------------------------------------------------------------------------------- /DYKit/Category/UIColor+DY_Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+DY_Extension.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/14. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (DY_Extension) 12 | // 透明度固定为1,以0x开头的十六进制转换成的颜色 13 | + (UIColor *)DY_colorWithHex:(long)hexColor; 14 | // 0x开头的十六进制转换成的颜色,透明度可调整 15 | + (UIColor *)DY_colorWithHex:(long)hexColor alpha:(float)opacity; 16 | // 颜色转换三:iOS中十六进制的颜色(以#开头)转换为UIColor 17 | + (UIColor *) DY_colorWithHexString: (NSString *)color; 18 | 19 | + (UIColor *)DY_colorWithR255Red:(CGFloat)r green:(CGFloat)g blue:(CGFloat)r alpha:(CGFloat)a; 20 | + (UIColor *)DY_colorWithRed:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b ; 21 | @end 22 | -------------------------------------------------------------------------------- /DYKit/Category/UIColor+DY_Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+DY_Extension.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/14. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "UIColor+DY_Extension.h" 10 | 11 | @implementation UIColor (DY_Extension) 12 | 13 | 14 | // 透明度固定为1,以0x开头的十六进制转换成的颜色 15 | + (UIColor*) DY_colorWithHex:(long)hexColor; 16 | { 17 | return [UIColor DY_colorWithHex:hexColor alpha:1.]; 18 | } 19 | // 0x开头的十六进制转换成的颜色,透明度可调整 20 | + (UIColor *)DY_colorWithHex:(long)hexColor alpha:(float)opacity 21 | { 22 | float red = ((float)((hexColor & 0xFF0000) >> 16))/255.0; 23 | float green = ((float)((hexColor & 0xFF00) >> 8))/255.0; 24 | float blue = ((float)(hexColor & 0xFF))/255.0; 25 | return [UIColor colorWithRed:red green:green blue:blue alpha:opacity]; 26 | } 27 | // 颜色转换三:iOS中十六进制的颜色(以#开头)转换为UIColor 28 | + (UIColor *) DY_colorWithHexString: (NSString *)color 29 | { 30 | NSString *cString = [[color stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 31 | 32 | // String should be 6 or 8 characters 33 | if ([cString length] < 6) { 34 | return [UIColor clearColor]; 35 | } 36 | 37 | // 判断前缀并剪切掉 38 | if ([cString hasPrefix:@"0X"]) 39 | cString = [cString substringFromIndex:2]; 40 | if ([cString hasPrefix:@"#"]) 41 | cString = [cString substringFromIndex:1]; 42 | if ([cString length] != 6) 43 | return [UIColor clearColor]; 44 | 45 | // 从六位数值中找到RGB对应的位数并转换 46 | NSRange range; 47 | range.location = 0; 48 | range.length = 2; 49 | 50 | //R、G、B 51 | NSString *rString = [cString substringWithRange:range]; 52 | 53 | range.location = 2; 54 | NSString *gString = [cString substringWithRange:range]; 55 | 56 | range.location = 4; 57 | NSString *bString = [cString substringWithRange:range]; 58 | 59 | // Scan values 60 | unsigned int r, g, b; 61 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 62 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 63 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 64 | 65 | return [UIColor colorWithRed:((float) r / 255.0f) green:((float) g / 255.0f) blue:((float) b / 255.0f) alpha:1.0f]; 66 | } 67 | 68 | + (UIColor *)DY_colorWithR255Red:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b alpha:(CGFloat)a{ 69 | return [UIColor colorWithRed:r / 255.0f green:g / 255.0f blue:b / 255.0f alpha:a]; 70 | } 71 | 72 | 73 | + (UIColor *)DY_colorWithRed:(CGFloat)r green:(CGFloat)g blue:(CGFloat)b{ 74 | return [UIColor colorWithRed:r / 255.0f green:g / 255.0f blue:b / 255.0f alpha:1.0f]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /DYKit/Category/UIImage+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Extension.h 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/20. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @interface UIImage (Extension) 12 | 13 | 14 | //字符串转图片 15 | +(UIImage*)Base64StrToUIImage:(NSString*)encodedImageStr; 16 | 17 | 18 | - (void)dy_imageWithSize:(CGSize)size fillColor:(UIColor *)fillColor completion:(void(^)(UIImage *image))completion; 19 | 20 | - (void)dy_imageWithSize:(CGSize)size fillColor:(UIColor *)fillColor completion:(void (^)(UIImage *))completion; 21 | /** 22 | *根据尺寸 和颜色 绘制图片 23 | */ 24 | + (UIImage*)dy_imageWithColor:(UIColor*)color size:(CGSize)size; 25 | 26 | 27 | /** 28 | * 尺寸 文字 颜色 字体 绘制头像 例:钉钉通讯录头像 默认为15号字体 29 | **/ 30 | + (UIImage *)dy_circleImageWithText:(NSString *)text setColor:(UIColor *)setColor size:(CGSize)size fontSize:(NSInteger)fontSize textColor:(UIColor *)textColor; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /DYKit/Category/UIImage+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Extension.m 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/20. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import "UIImage+Extension.h" 10 | 11 | @implementation UIImage (Extension) 12 | 13 | - (void)dy_imageWithSize:(CGSize)size fillColor:(UIColor *)fillColor completion:(void (^)(UIImage *))completion{ 14 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 15 | //开始时间 16 | NSTimeInterval start = CACurrentMediaTime(); 17 | //利用绘图,建立上下文 18 | UIGraphicsBeginImageContextWithOptions(size, YES, 0); 19 | //利用贝塞尔曲线路径裁切效果 20 | CGRect rect = CGRectMake(0, 0, size.width, size.height); 21 | //填充颜色 22 | [fillColor setFill]; 23 | UIRectFill(rect); 24 | UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect]; 25 | //裁切 26 | [path addClip]; 27 | //3绘制图像 28 | [self drawInRect:rect]; 29 | //4取得结果 30 | UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); 31 | //关闭上下文 32 | UIGraphicsEndImageContext(); 33 | NSLog(@"%f",CACurrentMediaTime() - start); 34 | dispatch_async(dispatch_get_main_queue(), ^{ 35 | if (completion != nil) { 36 | completion(result); 37 | } 38 | }); 39 | }); 40 | } 41 | - (void)dy_imageWithSize:(CGSize)size fillColor:(UIColor *)fillColor completion:(void (^)(UIImage *))completion{ 42 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 43 | //开始时间 44 | NSTimeInterval start = CACurrentMediaTime(); 45 | //利用绘图,建立上下文 46 | UIGraphicsBeginImageContextWithOptions(size, YES, 0); 47 | //利用贝塞尔路径裁切效果 48 | CGRect rect = CGRectMake(0, 0, size.width, size.height); 49 | //填充颜色 50 | [fillColor setFill]; 51 | UIRectFill(rect); 52 | UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect]; 53 | //裁切 54 | [path addClip]; 55 | //3绘制图像 56 | [self drawInRect:rect]; 57 | //4取得结果 58 | UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); 59 | //关闭上下文 60 | UIGraphicsEndImageContext(); 61 | NSLog(@"%f",CACurrentMediaTime() - start); 62 | //7完成回调 63 | dispatch_async(dispatch_get_main_queue(), ^{ 64 | if (completion != nil) { 65 | completion(result); 66 | } 67 | }); 68 | }); 69 | 70 | 71 | } 72 | 73 | 74 | 75 | +(UIImage*)Base64StrToUIImage:(NSString*)encodedImageStr 76 | { 77 | NSData *decodedImageData = [[NSData alloc] 78 | initWithBase64EncodedString:encodedImageStr options:NSDataBase64DecodingIgnoreUnknownCharacters]; 79 | UIImage *decodedImage = [UIImage imageWithData:decodedImageData]; 80 | return decodedImage; 81 | } 82 | 83 | 84 | 85 | + (UIImage*)dy_imageWithColor:(UIColor*)color size:(CGSize)size { 86 | 87 | if(!color || size.width<=0|| size.height<=0)return nil; 88 | CGRect rect =CGRectMake(0.0f,0.0f, size.width, size.height); 89 | UIGraphicsBeginImageContextWithOptions(rect.size,NO, 0); 90 | CGContextRef context = UIGraphicsGetCurrentContext(); 91 | CGContextSetFillColorWithColor(context, color.CGColor); 92 | CGContextFillRect(context, rect); 93 | UIImage *image =UIGraphicsGetImageFromCurrentImageContext(); 94 | UIGraphicsEndImageContext(); 95 | 96 | return image; 97 | } 98 | 99 | 100 | + (UIImage *)dy_circleImageWithText:(NSString *)text setColor:(UIColor *)setColor size:(CGSize)size fontSize:(NSInteger)fontSize textColor:(UIColor *)textColor{ 101 | 102 | 103 | NSDictionary *fontAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize:fontSize?fontSize:15], NSForegroundColorAttributeName: textColor}; 104 | CGSize textSize = [text sizeWithAttributes:fontAttributes]; 105 | CGPoint drawPoint = CGPointMake((size.width - textSize.width)/2, (size.height - textSize.height)/2); 106 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); 107 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 108 | UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, size.width, size.height)]; 109 | CGContextSetFillColorWithColor(ctx, setColor.CGColor); 110 | [path fill]; 111 | [text drawAtPoint:drawPoint withAttributes:fontAttributes]; 112 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 113 | UIGraphicsEndImageContext(); 114 | 115 | 116 | } 117 | 118 | @end 119 | -------------------------------------------------------------------------------- /DYKit/Category/UIImage+GIF.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+GIF.h 3 | // 富文本 4 | // 5 | // Created by Dainty on 17/6/28. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | typedef void (^GIFimageBlock)(UIImage *GIFImage); 11 | @interface UIImage (GIF) 12 | 13 | /** 根据本地GIF图片名 获得GIF image对象 */ 14 | + (UIImage *)imageWithGIFNamed:(NSString *)name; 15 | 16 | /** 根据一个GIF图片的data数据 获得GIF image对象 */ 17 | + (UIImage *)imageWithGIFData:(NSData *)data; 18 | 19 | /** 根据一个GIF图片的URL 获得GIF image对象 */ 20 | + (void)imageWithGIFUrl:(NSString *)url and:(GIFimageBlock)gifImageBlock; 21 | @end 22 | -------------------------------------------------------------------------------- /DYKit/Category/UIImage+GIF.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+GIF.m 3 | // 富文本 4 | // 5 | // Created by Dainty on 17/6/28. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "UIImage+GIF.h" 10 | #import 11 | @implementation UIImage (GIF) 12 | + (UIImage *)imageWithGIFData:(NSData *)data 13 | { 14 | if (!data) return nil; 15 | 16 | CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); 17 | 18 | size_t count = CGImageSourceGetCount(source); 19 | 20 | UIImage *animatedImage; 21 | 22 | if (count <= 1) { 23 | animatedImage = [[UIImage alloc] initWithData:data]; 24 | } else { 25 | 26 | NSMutableArray *images = [NSMutableArray array]; 27 | NSTimeInterval duration = 0.0f; 28 | 29 | for (size_t i = 0; i < count; i++) { 30 | 31 | // 拿出了Gif的每一帧图片 32 | CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); 33 | 34 | //Learning... 设置动画时长 算出每一帧显示的时长(帧时长) 35 | NSTimeInterval frameDuration = [UIImage sd_frameDurationAtIndex:i source:source]; 36 | duration += frameDuration; 37 | 38 | // 将每帧图片添加到数组中 39 | [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]]; 40 | 41 | // 释放真图片对象 42 | CFRelease(image); 43 | } 44 | 45 | // 设置动画时长 46 | if (!duration) { 47 | duration = (1.0f / 10.0f) * count; 48 | } 49 | 50 | animatedImage = [UIImage animatedImageWithImages:images duration:duration]; 51 | } 52 | 53 | // 释放源Gif图片 54 | CFRelease(source); 55 | 56 | return animatedImage; 57 | } 58 | 59 | + (UIImage *)imageWithGIFNamed:(NSString *)name 60 | { 61 | NSUInteger scale = (NSUInteger)[UIScreen mainScreen].scale; 62 | return [self GIFName:name scale:scale]; 63 | } 64 | 65 | + (UIImage *)GIFName:(NSString *)name scale:(NSUInteger)scale 66 | { 67 | 68 | NSString *imagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@@%zdx", name, scale] ofType:@"gif"]; 69 | 70 | if (!imagePath) { 71 | 72 | (scale + 1 > 3) ? (scale -= 1) : (scale += 1); 73 | imagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@@%zdx", name, scale] ofType:@"gif"]; 74 | } 75 | 76 | if (imagePath) { 77 | 78 | // 传入图片名(不包含@Nx) 79 | NSData *imageData = [NSData dataWithContentsOfFile:imagePath]; 80 | return [UIImage imageWithGIFData:imageData]; 81 | 82 | } else { 83 | 84 | imagePath = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; 85 | if (imagePath) { 86 | 87 | // 传入的图片名已包含@Nx or 传入图片只有一张 不分@Nx 88 | NSData *imageData = [NSData dataWithContentsOfFile:imagePath]; 89 | return [UIImage imageWithGIFData:imageData]; 90 | } else { 91 | 92 | // 不是一张GIF图片(后缀不是gif) 93 | return [UIImage imageNamed:name]; 94 | } 95 | } 96 | } 97 | 98 | + (void)imageWithGIFUrl:(NSString *)url and:(GIFimageBlock)gifImageBlock 99 | { 100 | NSURL *GIFUrl = [NSURL URLWithString:url]; 101 | 102 | if (!GIFUrl) return; 103 | 104 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 105 | 106 | NSData *CIFData = [NSData dataWithContentsOfURL:GIFUrl]; 107 | 108 | // 刷新UI在主线程 109 | dispatch_async(dispatch_get_main_queue(), ^{ 110 | 111 | gifImageBlock([UIImage imageWithGIFData:CIFData]); 112 | }); 113 | }); 114 | 115 | } 116 | 117 | #pragma mark - <关于GIF图片帧时长(Learning...)> 118 | 119 | + (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source { 120 | 121 | float frameDuration = 0.1f; 122 | CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil); 123 | NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties; 124 | NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary]; 125 | 126 | NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime]; 127 | if (delayTimeUnclampedProp) { 128 | frameDuration = [delayTimeUnclampedProp floatValue]; 129 | } 130 | else { 131 | 132 | NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime]; 133 | if (delayTimeProp) { 134 | frameDuration = [delayTimeProp floatValue]; 135 | } 136 | } 137 | 138 | // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. 139 | // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify 140 | // a duration of <= 10 ms. See and 141 | // for more information. 142 | 143 | if (frameDuration < 0.011f) { 144 | frameDuration = 0.100f; 145 | } 146 | 147 | CFRelease(cfFrameProperties); 148 | return frameDuration; 149 | } 150 | @end 151 | -------------------------------------------------------------------------------- /DYKit/Category/UIImageView+CornerRadius.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+CornerRadius.h 3 | // MyPractise 4 | // 5 | // Created by lzy on 16/3/1. 6 | // Copyright © 2016年 lzy. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface UIImageView (CornerRadius) 13 | 14 | //初始化设置圆角 15 | - (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType; 16 | 17 | - (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType; 18 | 19 | - (instancetype)initWithRoundingRectImageView; 20 | 21 | - (void)zy_cornerRadiusRoundingRect; 22 | 23 | - (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DYKit/Category/UIImageView+CornerRadius.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+CornerRadius.m 3 | // MyPractise 4 | // 5 | // Created by lzy on 16/3/1. 6 | // Copyright © 2016年 lzy. All rights reserved. 7 | // 8 | 9 | #import "UIImageView+CornerRadius.h" 10 | #import 11 | 12 | const char kProcessedImage; 13 | 14 | @interface UIImageView () 15 | 16 | @property (assign, nonatomic) CGFloat zyRadius; 17 | @property (assign, nonatomic) UIRectCorner roundingCorners; 18 | @property (assign, nonatomic) CGFloat zyBorderWidth; 19 | @property (strong, nonatomic) UIColor *zyBorderColor; 20 | @property (assign, nonatomic) BOOL zyHadAddObserver; 21 | @property (assign, nonatomic) BOOL zyIsRounding; 22 | 23 | @end 24 | 25 | 26 | 27 | 28 | 29 | @implementation UIImageView (CornerRadius) 30 | /** 31 | * @brief init the Rounding UIImageView, no off-screen-rendered 32 | */ 33 | - (instancetype)initWithRoundingRectImageView { 34 | self = [super init]; 35 | if (self) { 36 | [self zy_cornerRadiusRoundingRect]; 37 | } 38 | return self; 39 | } 40 | 41 | /** 42 | * @brief init the UIImageView with cornerRadius, no off-screen-rendered 43 | */ 44 | - (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType { 45 | self = [super init]; 46 | if (self) { 47 | [self zy_cornerRadiusAdvance:cornerRadius rectCornerType:rectCornerType]; 48 | } 49 | return self; 50 | } 51 | 52 | /** 53 | * @brief attach border for UIImageView with width & color 54 | */ 55 | - (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color { 56 | self.zyBorderWidth = width; 57 | self.zyBorderColor = color; 58 | } 59 | 60 | #pragma mark - Kernel 61 | /** 62 | * @brief clip the cornerRadius with image, UIImageView must be setFrame before, no off-screen-rendered 63 | */ 64 | - (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType { 65 | CGSize size = self.bounds.size; 66 | CGFloat scale = [UIScreen mainScreen].scale; 67 | CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius); 68 | 69 | UIGraphicsBeginImageContextWithOptions(size, NO, scale); 70 | CGContextRef currentContext = UIGraphicsGetCurrentContext(); 71 | if (nil == currentContext) { 72 | return; 73 | } 74 | UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii]; 75 | [cornerPath addClip]; 76 | [self.layer renderInContext:currentContext]; 77 | [self drawBorder:cornerPath]; 78 | UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext(); 79 | UIGraphicsEndImageContext(); 80 | if (processedImage) { 81 | objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 82 | } 83 | self.image = processedImage; 84 | } 85 | 86 | /** 87 | * @brief clip the cornerRadius with image, draw the backgroundColor you want, UIImageView must be setFrame before, no off-screen-rendered, no Color Blended layers 88 | */ 89 | - (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType backgroundColor:(UIColor *)backgroundColor { 90 | CGSize size = self.bounds.size; 91 | CGFloat scale = [UIScreen mainScreen].scale; 92 | CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius); 93 | 94 | UIGraphicsBeginImageContextWithOptions(size, YES, scale); 95 | CGContextRef currentContext = UIGraphicsGetCurrentContext(); 96 | if (nil == currentContext) { 97 | return; 98 | } 99 | UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii]; 100 | UIBezierPath *backgroundRect = [UIBezierPath bezierPathWithRect:self.bounds]; 101 | [backgroundColor setFill]; 102 | [backgroundRect fill]; 103 | [cornerPath addClip]; 104 | [self.layer renderInContext:currentContext]; 105 | [self drawBorder:cornerPath]; 106 | UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext(); 107 | UIGraphicsEndImageContext(); 108 | if (processedImage) { 109 | objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 110 | } 111 | self.image = processedImage; 112 | } 113 | 114 | /** 115 | * @brief set cornerRadius for UIImageView, no off-screen-rendered 116 | */ 117 | - (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType { 118 | self.zyRadius = cornerRadius; 119 | self.roundingCorners = rectCornerType; 120 | self.zyIsRounding = NO; 121 | if (!self.zyHadAddObserver) { 122 | [[self class] swizzleDealloc]; 123 | [self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil]; 124 | self.zyHadAddObserver = YES; 125 | } 126 | //Xcode 8 xib 删除了控件的Frame信息,需要主动创造 127 | [self layoutIfNeeded]; 128 | } 129 | 130 | /** 131 | * @brief become Rounding UIImageView, no off-screen-rendered 132 | */ 133 | - (void)zy_cornerRadiusRoundingRect { 134 | self.zyIsRounding = YES; 135 | if (!self.zyHadAddObserver) { 136 | [[self class] swizzleDealloc]; 137 | [self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil]; 138 | self.zyHadAddObserver = YES; 139 | } 140 | //Xcode 8 xib 删除了控件的Frame信息,需要主动创造 141 | [self layoutIfNeeded]; 142 | } 143 | 144 | #pragma mark - Private 145 | - (void)drawBorder:(UIBezierPath *)path { 146 | if (0 != self.zyBorderWidth && nil != self.zyBorderColor) { 147 | [path setLineWidth:2 * self.zyBorderWidth]; 148 | [self.zyBorderColor setStroke]; 149 | [path stroke]; 150 | } 151 | } 152 | 153 | - (void)zy_dealloc { 154 | if (self.zyHadAddObserver) { 155 | [self removeObserver:self forKeyPath:@"image"]; 156 | } 157 | [self zy_dealloc]; 158 | } 159 | 160 | - (void)validateFrame { 161 | if (self.frame.size.width == 0) { 162 | [self.class swizzleLayoutSubviews]; 163 | } 164 | } 165 | 166 | + (void)swizzleMethod:(SEL)oneSel anotherMethod:(SEL)anotherSel { 167 | Method oneMethod = class_getInstanceMethod(self, oneSel); 168 | Method anotherMethod = class_getInstanceMethod(self, anotherSel); 169 | method_exchangeImplementations(oneMethod, anotherMethod); 170 | } 171 | 172 | + (void)swizzleDealloc { 173 | static dispatch_once_t onceToken; 174 | dispatch_once(&onceToken, ^{ 175 | [self swizzleMethod:NSSelectorFromString(@"dealloc") anotherMethod:@selector(zy_dealloc)]; 176 | }); 177 | } 178 | 179 | + (void)swizzleLayoutSubviews { 180 | static dispatch_once_t onceToken; 181 | dispatch_once(&onceToken, ^{ 182 | [self swizzleMethod:@selector(layoutSubviews) anotherMethod:@selector(zy_LayoutSubviews)]; 183 | }); 184 | } 185 | 186 | - (void)zy_LayoutSubviews { 187 | [self zy_LayoutSubviews]; 188 | if (self.zyIsRounding) { 189 | [self zy_cornerRadiusWithImage:self.image cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners]; 190 | } else if (0 != self.zyRadius && 0 != self.roundingCorners && nil != self.image) { 191 | [self zy_cornerRadiusWithImage:self.image cornerRadius:self.zyRadius rectCornerType:self.roundingCorners]; 192 | } 193 | } 194 | 195 | #pragma mark - KVO for .image 196 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 197 | if ([keyPath isEqualToString:@"image"]) { 198 | UIImage *newImage = change[NSKeyValueChangeNewKey]; 199 | if ([newImage isMemberOfClass:[NSNull class]]) { 200 | return; 201 | } else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) { 202 | return; 203 | } 204 | [self validateFrame]; 205 | if (self.zyIsRounding) { 206 | [self zy_cornerRadiusWithImage:newImage cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners]; 207 | } else if (0 != self.zyRadius && 0 != self.roundingCorners && nil != self.image) { 208 | [self zy_cornerRadiusWithImage:newImage cornerRadius:self.zyRadius rectCornerType:self.roundingCorners]; 209 | } 210 | } 211 | } 212 | 213 | #pragma mark property 214 | - (CGFloat)zyBorderWidth { 215 | return [objc_getAssociatedObject(self, _cmd) floatValue]; 216 | } 217 | 218 | - (void)setZyBorderWidth:(CGFloat)zyBorderWidth { 219 | objc_setAssociatedObject(self, @selector(zyBorderWidth), @(zyBorderWidth), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 220 | } 221 | 222 | - (UIColor *)zyBorderColor { 223 | return objc_getAssociatedObject(self, _cmd); 224 | } 225 | 226 | - (void)setZyBorderColor:(UIColor *)zyBorderColor { 227 | objc_setAssociatedObject(self, @selector(zyBorderColor), zyBorderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 228 | } 229 | 230 | - (BOOL)zyHadAddObserver { 231 | return [objc_getAssociatedObject(self, _cmd) boolValue]; 232 | } 233 | 234 | - (void)setZyHadAddObserver:(BOOL)zyHadAddObserver { 235 | objc_setAssociatedObject(self, @selector(zyHadAddObserver), @(zyHadAddObserver), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 236 | } 237 | 238 | - (BOOL)zyIsRounding { 239 | return [objc_getAssociatedObject(self, _cmd) boolValue]; 240 | } 241 | 242 | - (void)setZyIsRounding:(BOOL)zyIsRounding { 243 | objc_setAssociatedObject(self, @selector(zyIsRounding), @(zyIsRounding), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 244 | } 245 | 246 | - (UIRectCorner)roundingCorners { 247 | return [objc_getAssociatedObject(self, _cmd) unsignedLongValue]; 248 | } 249 | 250 | - (void)setRoundingCorners:(UIRectCorner)roundingCorners { 251 | objc_setAssociatedObject(self, @selector(roundingCorners), @(roundingCorners), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 252 | } 253 | 254 | - (CGFloat)zyRadius { 255 | return [objc_getAssociatedObject(self, _cmd) floatValue]; 256 | } 257 | 258 | - (void)setZyRadius:(CGFloat)zyRadius { 259 | objc_setAssociatedObject(self, @selector(zyRadius), @(zyRadius), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 260 | } 261 | 262 | 263 | @end 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | //ZYCornerRadius is available under the MIT license. 273 | //Please visit https://github.com/liuzhiyi1992/ZYCornerRadius for details. 274 | -------------------------------------------------------------------------------- /DYKit/Category/UILabel+DY_Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+DY_Extension.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/13. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UILabel (DY_Extension) 12 | 13 | 14 | /** 15 | * 功能:UILabel 字体设置 16 | 17 | label.font = [UIFont fontWithName:@"Helvetica-Bold" size:20];//加粗 18 | label.font = [UIFont fontWithName:@"Helvetica-Oblique" size:20];//加斜 19 | label.font = [UIFont fontWithName:@"Helvetica-BoldOblique" size:20];//又粗又斜 20 | + (instancetype)initWithFontSize:(CGFloat)fontSize numberOfLines: (NSInteger)numberOfLines; 21 | */ 22 | 23 | + (instancetype)initWithFontSize:(CGFloat)fontSize numberOfLines: (NSInteger)numberOfLines textColor:(NSString *)hex; 24 | //是否首行缩进 多少字符 25 | 26 | /** 27 | @param fontSize 字体像数大小 28 | @param numberOfLines 行数 29 | @param hexY 16进制字符串 30 | @param paraStyleSize 缩进像数大小 31 | @return label 32 | */ 33 | + (instancetype)paraStyleWithFontSize:(CGFloat)fontSize numberOfLines: (NSInteger)numberOfLines textColor:(NSString *)hexY paraStyleSize:(CGFloat)paraStyleSize; 34 | 35 | 36 | /** 37 | 截取最后一行字符串 38 | */ 39 | - (void)setLineBreakByTruncatingLastLineMiddle; 40 | - (NSArray *)getSeparatedLinesFromLabel; 41 | - (NSArray *)getSeparatedLinesArray; 42 | //图片在后 43 | - (void)setText:(NSString *)text frontImages:(NSArray *)images imageSpan:(CGFloat)span; 44 | - (void)setText:(NSString *)text 45 | imageSize:(CGFloat)imageSize frontImages:(NSArray *)images imageSpan:(CGFloat)span; 46 | - (void)leftPicSetText:(NSString *)text frontImages:(NSArray *)images imageSpan:(CGFloat)span; 47 | //图片在左 设置图片大小 48 | - (void)leftPicWithText:(NSString *)text imageSize:(CGFloat)imageSize frontImages:(NSArray *)images imageSpan:(CGFloat)span; 49 | @end 50 | -------------------------------------------------------------------------------- /DYKit/Category/UILabel+DY_Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+DY_Extension.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/13. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "UILabel+DY_Extension.h" 10 | #import "UIColor+DY_Extension.h" 11 | @implementation UILabel (DY_Extension) 12 | 13 | + (instancetype)initWithFontSize: (CGFloat)fontSize numberOfLines: (NSInteger)numberOfLines{ 14 | 15 | UILabel *lb = [[UILabel alloc] init]; 16 | 17 | 18 | lb.font = [UIFont systemFontOfSize:FontSize(fontSize)]; 19 | 20 | lb.numberOfLines = numberOfLines; 21 | return lb; 22 | } 23 | 24 | + (instancetype)initWithFontSize:(CGFloat)fontSize numberOfLines:(NSInteger)numberOfLines textColor:(NSString *)hex{ 25 | 26 | UILabel *lb = [[UILabel alloc] init]; 27 | lb.font = [UIFont systemFontOfSize:FontSize(fontSize)]; 28 | lb.numberOfLines = numberOfLines; 29 | lb.textColor = [UIColor colorWithHexString:hex]; 30 | return lb; 31 | 32 | } 33 | 34 | + (instancetype)paraStyleWithFontSize:(CGFloat)fontSize numberOfLines: (NSInteger)numberOfLines textColor:(NSString *)hexY paraStyleSize:(CGFloat)paraStyleSize { 35 | UILabel *lb = [[UILabel alloc] init]; 36 | lb.font = [UIFont systemFontOfSize:FontSize(fontSize)]; 37 | lb.numberOfLines = numberOfLines; 38 | lb.textColor = [UIColor colorWithHexString:hexY]; 39 | NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init]; 40 | paraStyle.alignment = NSTextAlignmentLeft; 41 | // CGFloat p = 12 * 2; 42 | CGFloat p = 12 * 2; 43 | paraStyle.firstLineHeadIndent = p; 44 | NSAttributedString *string = [[NSAttributedString alloc] initWithString:lb.text attributes:@{NSParagraphStyleAttributeName: paraStyle}]; 45 | lb.attributedText = string; 46 | return lb; 47 | 48 | } 49 | 50 | 51 | // 52 | //- (void)setLineBreakByTruncatingLastLineMiddle{ 53 | // 54 | // if ( self.numberOfLines <= 0 ) { 55 | // return; 56 | // } 57 | // NSArray *separatedLines = [self getSeparatedLinesFromLabel]; 58 | // 59 | // NSMutableString *limitedText = [NSMutableString string]; 60 | // if ( separatedLines.count >= self.numberOfLines ) { 61 | // 62 | // for (int i = 0 ; i < self.numberOfLines; i++) { 63 | // if ( i == self.numberOfLines - 1) { 64 | // UILabel *lastLineLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, MAXFLOAT)]; 65 | // lastLineLabel.text = separatedLines[self.numberOfLines - 1]; 66 | // 67 | // NSArray *subSeparatedLines = [lastLineLabel getSeparatedLinesFromLabel]; 68 | // NSString *lastLineText = [subSeparatedLines firstObject]; 69 | // NSInteger lastLineTextCount = lastLineText.length; 70 | // [limitedText appendString:[NSString stringWithFormat:@"%@......",[lastLineText substringToIndex:lastLineTextCount]]]; 71 | // }else{ 72 | // [limitedText appendString:separatedLines[i]]; 73 | // } 74 | // } 75 | // 76 | // 77 | // }else{ 78 | // [limitedText appendString:self.text]; 79 | // } 80 | // 81 | // self.text = limitedText; 82 | // 83 | //} 84 | - (void)setLineBreakByTruncatingLastLineMiddle{ 85 | if ( self.numberOfLines <= 0 ) { 86 | return; 87 | } 88 | 89 | DYLog(@"%ld",(long)self.numberOfLines); 90 | NSArray *separatedLines = [self getSeparatedLinesArray]; 91 | 92 | NSMutableString *limitedText = [NSMutableString string]; 93 | if ( separatedLines.count >= self.numberOfLines ) { 94 | 95 | for (int i = 0 ; i < self.numberOfLines; i++) { 96 | if ( i == self.numberOfLines - 1) { 97 | UILabel *lastLineLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width/2, MAXFLOAT)]; 98 | lastLineLabel.text = separatedLines[self.numberOfLines - 1]; 99 | 100 | NSArray *subSeparatedLines = [lastLineLabel getSeparatedLinesArray]; 101 | NSString *lastLineText = [subSeparatedLines firstObject]; 102 | NSInteger lastLineTextCount = lastLineText.length; 103 | [limitedText appendString:[NSString stringWithFormat:@"%@...",[lastLineText substringToIndex:lastLineTextCount]]]; 104 | }else{ 105 | [limitedText appendString:separatedLines[i]]; 106 | } 107 | } 108 | 109 | 110 | }else{ 111 | [limitedText appendString:self.text]; 112 | } 113 | 114 | self.text = limitedText; 115 | 116 | } 117 | 118 | //获取每行的字符串.,改为UIlabel分类 119 | //+(NSArray)getSeparatedLinesFromLabel:(UILabel *)lable; 120 | - (NSArray *)getSeparatedLinesFromLabel 121 | { 122 | NSString *text = [self text]; 123 | UIFont *font = [self font]; 124 | CGRect rect = [self frame]; 125 | 126 | CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL); 127 | NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text]; 128 | [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)]; 129 | 130 | CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr); 131 | 132 | CGMutablePathRef path = CGPathCreateMutable(); 133 | CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000)); 134 | 135 | CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL); 136 | 137 | NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame); 138 | NSMutableArray *linesArray = [[NSMutableArray alloc]init]; 139 | 140 | for (id line in lines) 141 | { 142 | CTLineRef lineRef = (__bridge CTLineRef )line; 143 | CFRange lineRange = CTLineGetStringRange(lineRef); 144 | NSRange range = NSMakeRange(lineRange.location, lineRange.length); 145 | 146 | NSString *lineString = [text substringWithRange:range]; 147 | [linesArray addObject:lineString]; 148 | } 149 | 150 | NSLog( @" %@",linesArray); 151 | return (NSArray *)linesArray; 152 | 153 | 154 | } 155 | 156 | 157 | - (NSArray *)getSeparatedLinesArray 158 | { 159 | NSString *text = [self text]; 160 | UIFont *font = [self font]; 161 | CGRect rect = [self frame]; 162 | 163 | CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL); 164 | NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text]; 165 | [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)]; 166 | 167 | CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr); 168 | 169 | CGMutablePathRef path = CGPathCreateMutable(); 170 | //rect.size.width 171 | CGPathAddRect(path, NULL, CGRectMake(0,0,KScreenW - 80,100000)); 172 | 173 | CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL); 174 | 175 | NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame); 176 | NSMutableArray *linesArray = [[NSMutableArray alloc]init]; 177 | 178 | for (id line in lines) 179 | { 180 | CTLineRef lineRef = (__bridge CTLineRef )line; 181 | CFRange lineRange = CTLineGetStringRange(lineRef); 182 | NSRange range = NSMakeRange(lineRange.location, lineRange.length); 183 | 184 | NSString *lineString = [text substringWithRange:range]; 185 | [linesArray addObject:lineString]; 186 | } 187 | 188 | NSLog(@"%@",linesArray); 189 | return (NSArray *)linesArray; 190 | } 191 | 192 | /** 193 | 为UILabel首部设置图片标签 194 | 195 | @param text 文本 196 | @param images 标签数组 197 | @param span 标签间距 198 | */ 199 | -(void)setText:(NSString *)text frontImages:(NSArray *)images imageSpan:(CGFloat)span 200 | { 201 | NSMutableAttributedString *textAttrStr = [[NSMutableAttributedString alloc] init]; 202 | //设置显示文本 203 | [textAttrStr appendAttributedString:[[NSAttributedString alloc]initWithString:text]]; 204 | 205 | [textAttrStr appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]]; 206 | for (UIImage *img in images) {//遍历添加标签 207 | NSTextAttachment *attach = [[NSTextAttachment alloc] init]; 208 | attach.image = img; 209 | //计算图片大小,与文字同高,按比例设置宽度 210 | CGFloat imgH = self.font.pointSize; 211 | // DYLog( @"%f",img.size.width); 212 | CGFloat imgW = (img.size.width / img.size.height) * imgH; 213 | 214 | 215 | attach.bounds = CGRectMake(0, -2 ,imgW , imgH); 216 | 217 | NSAttributedString *imgStr = [NSAttributedString attributedStringWithAttachment:attach]; 218 | [textAttrStr appendAttributedString:imgStr]; 219 | //标签后添加空格 220 | [textAttrStr appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]]; 221 | } 222 | 223 | 224 | //设置间距 225 | if (span != 0) { 226 | // [textAttrStr addAttribute:NSKernAttributeName value:@(span) 227 | // range:NSMakeRange(10, images.count * 2/*由于图片也会占用一个单位长度,所以带上空格数量,需要 *2 */)]; 228 | 229 | [textAttrStr addAttribute:NSKernAttributeName value:@(span) range:NSMakeRange(0, images.count * 2)]; 230 | } 231 | 232 | self.attributedText = textAttrStr; 233 | 234 | 235 | 236 | 237 | } 238 | 239 | 240 | - (void)setText:(NSString *)text 241 | imageSize:(CGFloat)imageSize frontImages:(NSArray *)images imageSpan:(CGFloat)span{ 242 | NSMutableAttributedString *textAttrStr = [[NSMutableAttributedString alloc] init]; 243 | //设置显示文本 244 | [textAttrStr appendAttributedString:[[NSAttributedString alloc]initWithString:text]]; 245 | 246 | [textAttrStr appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]]; 247 | for (UIImage *img in images) {//遍历添加标签 248 | NSTextAttachment *attach = [[NSTextAttachment alloc] init]; 249 | attach.image = img; 250 | //计算图片大小,与文字同高,按比例设置宽度 251 | if (!imageSize) { 252 | imageSize = 1; 253 | } 254 | CGFloat imgH = self.font.pointSize * imageSize; 255 | // DYLog( @"%f",img.size.width); 256 | CGFloat imgW = (img.size.width / img.size.height) * imgH; 257 | 258 | 259 | attach.bounds = CGRectMake(0, 0 ,imgW , imgH); 260 | 261 | NSAttributedString *imgStr = [NSAttributedString attributedStringWithAttachment:attach]; 262 | [textAttrStr appendAttributedString:imgStr]; 263 | //标签后添加空格 264 | [textAttrStr appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]]; 265 | } 266 | 267 | 268 | //设置间距 269 | if (span != 0) { 270 | // [textAttrStr addAttribute:NSKernAttributeName value:@(span) 271 | // range:NSMakeRange(10, images.count * 2/*由于图片也会占用一个单位长度,所以带上空格数量,需要 *2 */)]; 272 | 273 | [textAttrStr addAttribute:NSKernAttributeName value:@(span) range:NSMakeRange(0, images.count * 2)]; 274 | } 275 | 276 | self.attributedText = textAttrStr; 277 | 278 | 279 | } 280 | - (void)leftPicSetText:(NSString *)text frontImages:(NSArray *)images imageSpan:(CGFloat)span{ 281 | NSMutableAttributedString *textAttrStr = [[NSMutableAttributedString alloc] init]; 282 | //设置显示文本 283 | for (UIImage *img in images) {//遍历添加标签 284 | NSTextAttachment *attach = [[NSTextAttachment alloc] init]; 285 | attach.image = img; 286 | //计算图片大小,与文字同高,按比例设置宽度 287 | CGFloat imgH = self.font.pointSize; 288 | // DYLog( @"%f",img.size.width); 289 | CGFloat imgW = (img.size.width / img.size.height) * imgH; 290 | attach.bounds = CGRectMake(0, -2 ,imgW , imgH); 291 | NSAttributedString *imgStr = [NSAttributedString attributedStringWithAttachment:attach]; 292 | [textAttrStr appendAttributedString:imgStr]; 293 | //标签后添加空格 294 | [textAttrStr appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]]; 295 | } 296 | 297 | 298 | [textAttrStr appendAttributedString:[[NSMutableAttributedString alloc]initWithString:text]]; 299 | 300 | 301 | //设置间距 302 | if (span != 0) { 303 | [textAttrStr addAttribute:NSKernAttributeName value:@(span) 304 | range:NSMakeRange(0, images.count * 2/*由于图片也会占用一个单位长度,所以带上空格数量,需要 *2 */)]; 305 | } 306 | 307 | self.attributedText = textAttrStr; 308 | } 309 | 310 | - (void)leftPicWithText:(NSString *)text imageSize:(CGFloat)imageSize frontImages:(NSArray *)images imageSpan:(CGFloat)span{ 311 | NSMutableAttributedString *textAttrStr = [[NSMutableAttributedString alloc] init]; 312 | //设置显示文本 313 | for (UIImage *img in images) {//遍历添加标签 314 | NSTextAttachment *attach = [[NSTextAttachment alloc] init]; 315 | attach.image = img; 316 | //计算图片大小,与文字同高,按比例设置宽度 317 | CGFloat imgH = self.font.pointSize *imageSize; 318 | // DYLog( @"%f",img.size.width); 319 | CGFloat imgW = (img.size.width / img.size.height) * imgH; 320 | attach.bounds = CGRectMake(0, -2 ,imgW , imgH); 321 | NSAttributedString *imgStr = [NSAttributedString attributedStringWithAttachment:attach]; 322 | [textAttrStr appendAttributedString:imgStr]; 323 | //标签后添加空格 324 | [textAttrStr appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]]; 325 | } 326 | 327 | 328 | [textAttrStr appendAttributedString:[[NSMutableAttributedString alloc]initWithString:text]]; 329 | 330 | 331 | //设置间距 332 | if (span != 0) { 333 | [textAttrStr addAttribute:NSKernAttributeName value:@(span) 334 | range:NSMakeRange(0, images.count * 2/*由于图片也会占用一个单位长度,所以带上空格数量,需要 *2 */)]; 335 | } 336 | 337 | self.attributedText = textAttrStr; 338 | } 339 | 340 | @end 341 | -------------------------------------------------------------------------------- /DYKit/Category/UILabel+YBAttributeTextTapAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+YBAttributeTextTapAction.h 3 | // 4 | // Created by LYB on 16/7/1. 5 | // Copyright © 2016年 LYB. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @protocol YBAttributeTapActionDelegate 11 | @optional 12 | /** 13 | * YBAttributeTapActionDelegate 14 | * 15 | * @param string 点击的字符串 16 | * @param range 点击的字符串range 17 | * @param index 点击的字符在数组中的index 18 | */ 19 | - (void)yb_attributeTapReturnString:(NSString *)string 20 | range:(NSRange)range 21 | index:(NSInteger)index; 22 | 23 | 24 | 25 | @end 26 | 27 | @interface YBAttributeModel : NSObject 28 | 29 | @property (nonatomic, copy) NSString *str; 30 | 31 | @property (nonatomic, assign) NSRange range; 32 | 33 | @end 34 | 35 | 36 | 37 | 38 | 39 | @interface UILabel (YBAttributeTextTapAction) 40 | 41 | /** 42 | * 给文本添加点击事件Block回调 43 | * 44 | * @param strings 需要添加的字符串数组 45 | * @param tapClick 点击事件回调 46 | */ 47 | - (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings 48 | tapClicked:(void (^) (NSString *string , NSRange range , NSInteger index))tapClick; 49 | 50 | /** 51 | * 给文本添加点击事件delegate回调 52 | * 53 | * @param strings 需要添加的字符串数组 54 | * @param delegate delegate 55 | */ 56 | - (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings 57 | delegate:(id )delegate; 58 | 59 | @end 60 | 61 | -------------------------------------------------------------------------------- /DYKit/Category/UILabel+YBAttributeTextTapAction.m: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+YBAttributeTextTapAction.m 3 | // 4 | // Created by LYB on 16/7/1. 5 | // Copyright © 2016年 LYB. All rights reserved. 6 | // 7 | 8 | #import "UILabel+YBAttributeTextTapAction.h" 9 | #import 10 | #import 11 | #import 12 | 13 | @implementation YBAttributeModel 14 | 15 | @end 16 | 17 | @implementation UILabel (YBAttributeTextTapAction) 18 | 19 | #pragma mark - AssociatedObjects 20 | 21 | - (NSMutableArray *)attributeStrings 22 | { 23 | return objc_getAssociatedObject(self, _cmd); 24 | } 25 | 26 | - (void)setAttributeStrings:(NSMutableArray *)attributeStrings 27 | { 28 | objc_setAssociatedObject(self, @selector(attributeStrings), attributeStrings, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 29 | } 30 | 31 | - (void (^)(NSString *, NSRange, NSInteger))tapBlock 32 | { 33 | return objc_getAssociatedObject(self, _cmd); 34 | } 35 | 36 | - (void)setTapBlock:(void (^)(NSString *, NSRange, NSInteger))tapBlock 37 | { 38 | objc_setAssociatedObject(self, @selector(tapBlock), tapBlock, OBJC_ASSOCIATION_COPY_NONATOMIC); 39 | } 40 | 41 | - (id)delegate 42 | { 43 | return objc_getAssociatedObject(self, _cmd); 44 | } 45 | 46 | - (void)setDelegate:(id)delegate 47 | { 48 | objc_setAssociatedObject(self, @selector(delegate), delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 49 | } 50 | 51 | #pragma mark - mainFunction 52 | - (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings tapClicked:(void (^) (NSString *string , NSRange range , NSInteger index))tapClick 53 | { 54 | [self yb_getRangesWithStrings:strings]; 55 | 56 | if (self.tapBlock != tapClick) { 57 | self.tapBlock = tapClick; 58 | } 59 | } 60 | 61 | - (void)yb_addAttributeTapActionWithStrings:(NSArray *)strings 62 | delegate:(id )delegate 63 | { 64 | [self yb_getRangesWithStrings:strings]; 65 | 66 | if (self.delegate != delegate) { 67 | self.delegate = delegate; 68 | } 69 | } 70 | 71 | #pragma mark - touchAction 72 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 73 | { 74 | UITouch *touch = [touches anyObject]; 75 | 76 | CGPoint point = [touch locationInView:self]; 77 | 78 | __weak typeof(self) weakSelf = self; 79 | 80 | [self yb_getTapFrameWithTouchPoint:point result:^(NSString *string, NSRange range, NSInteger index) { 81 | 82 | if (weakSelf.tapBlock) { 83 | weakSelf.tapBlock (string , range , index); 84 | } 85 | 86 | if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(yb_attributeTapReturnString:range:index:)]) { 87 | [weakSelf.delegate yb_attributeTapReturnString:string range:range index:index]; 88 | } 89 | 90 | }]; 91 | } 92 | 93 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 94 | if ([self yb_getTapFrameWithTouchPoint:point result:nil]) { 95 | return self; 96 | } 97 | return nil; 98 | } 99 | 100 | #pragma mark - getTapFrame 101 | - (BOOL)yb_getTapFrameWithTouchPoint:(CGPoint)point result:(void (^) (NSString *string , NSRange range , NSInteger index))resultBlock 102 | { 103 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attributedText); 104 | 105 | CGMutablePathRef Path = CGPathCreateMutable(); 106 | 107 | CGPathAddRect(Path, NULL, self.bounds); 108 | 109 | CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL); 110 | 111 | CFArrayRef lines = CTFrameGetLines(frame); 112 | 113 | if (!lines) { 114 | return NO; 115 | } 116 | 117 | CFIndex count = CFArrayGetCount(lines); 118 | 119 | CGPoint origins[count]; 120 | 121 | CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins); 122 | 123 | CGAffineTransform transform = [self yb_transformForCoreText]; 124 | 125 | CGFloat verticalOffset = 0; 126 | 127 | for (CFIndex i = 0; i < count; i++) { 128 | CGPoint linePoint = origins[i]; 129 | 130 | CTLineRef line = CFArrayGetValueAtIndex(lines, i); 131 | 132 | CGRect flippedRect = [self yb_getLineBounds:line point:linePoint]; 133 | 134 | CGRect rect = CGRectApplyAffineTransform(flippedRect, transform); 135 | 136 | rect = CGRectInset(rect, 0, 0); 137 | 138 | rect = CGRectOffset(rect, 0, verticalOffset); 139 | 140 | if (CGRectContainsPoint(rect, point)) { 141 | 142 | CGPoint relativePoint = CGPointMake(point.x - CGRectGetMinX(rect), point.y - CGRectGetMinY(rect)); 143 | 144 | CFIndex index = CTLineGetStringIndexForPosition(line, relativePoint); 145 | 146 | CGFloat offset; 147 | 148 | CTLineGetOffsetForStringIndex(line, index, &offset); 149 | 150 | if (offset > relativePoint.x) { 151 | index = index - 1; 152 | } 153 | 154 | NSInteger link_count = self.attributeStrings.count; 155 | 156 | for (int j = 0; j < link_count; j++) { 157 | 158 | YBAttributeModel *model = self.attributeStrings[j]; 159 | 160 | NSRange link_range = model.range; 161 | if (NSLocationInRange(index, link_range)) { 162 | if (resultBlock) { 163 | resultBlock (model.str , model.range , (NSInteger)j); 164 | } 165 | return YES; 166 | } 167 | } 168 | } 169 | } 170 | return NO; 171 | } 172 | 173 | - (CGAffineTransform)yb_transformForCoreText 174 | { 175 | return CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f); 176 | } 177 | 178 | - (CGRect)yb_getLineBounds:(CTLineRef)line point:(CGPoint)point 179 | { 180 | CGFloat ascent = 0.0f; 181 | CGFloat descent = 0.0f; 182 | CGFloat leading = 0.0f; 183 | CGFloat width = (CGFloat)CTLineGetTypographicBounds(line, &ascent, &descent, &leading); 184 | CGFloat height = ascent + descent; 185 | 186 | return CGRectMake(point.x, point.y - descent, width, height); 187 | } 188 | 189 | #pragma mark - getRange 190 | - (void)yb_getRangesWithStrings:(NSArray *)strings 191 | { 192 | __block NSString *totalStr = self.attributedText.string; 193 | 194 | self.attributeStrings = [NSMutableArray array]; 195 | 196 | __weak typeof(self) weakSelf = self; 197 | 198 | [strings enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 199 | 200 | NSRange range = [totalStr rangeOfString:obj]; 201 | 202 | if (range.length != 0) { 203 | YBAttributeModel *model = [YBAttributeModel new]; 204 | model.range = range; 205 | model.str = obj; 206 | [weakSelf.attributeStrings addObject:model]; 207 | 208 | totalStr = [totalStr stringByReplacingCharactersInRange:range withString:[weakSelf yb_getStringWithRange:range]]; 209 | } 210 | }]; 211 | } 212 | 213 | - (NSString *)yb_getStringWithRange:(NSRange)range 214 | { 215 | NSMutableString *string = [NSMutableString string]; 216 | for (int i = 0; i < range.length ; i++) { 217 | [string appendString:@" "]; 218 | } 219 | return string; 220 | } 221 | 222 | @end 223 | -------------------------------------------------------------------------------- /DYKit/Category/UIScrollView+DGRefresh.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+DGRefresh.h 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/24. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import 10 | @interface UIScrollView (DGRefresh) 11 | 12 | - (void)addHeaderRefresh:(void(^)())handler ; 13 | - (void)addFooterRefresh:(void(^)())handler ; 14 | - (void)beginHeaderRefresh; 15 | -(void)endHeaderRefresh; 16 | - (void)endFooterRefresh; 17 | -(void)beginFooterRefresh; 18 | 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /DYKit/Category/UIScrollView+DGRefresh.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+DGRefresh.m 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/24. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import "UIScrollView+DGRefresh.h" 10 | 11 | //#import 12 | @implementation UIScrollView (DGRefresh) 13 | 14 | - (void)addHeaderRefresh:(void (^)())handler{ 15 | self.mj_header = [DYRefreshHeader headerWithRefreshingBlock:handler]; 16 | //取消之前的所有请求 17 | // [[DYHTTPTool sharedInstance].tasks makeObjectsPerformSelector:@selector(cancel)]; 18 | 19 | } 20 | - (void)beginHeaderRefresh{ 21 | [self.mj_header beginRefreshing]; 22 | } 23 | - (void)endHeaderRefresh{ 24 | [self.mj_header endRefreshing]; 25 | } 26 | - (void)addFooterRefresh:(void (^)())handler{ 27 | self.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:handler ]; 28 | 29 | //取消之前的所有请求 30 | // [[DYHTTPTool sharedInstance].tasks makeObjectsPerformSelector:@selector(cancel)]; 31 | } 32 | - (void)beginFooterRefresh{ 33 | [self.mj_footer beginRefreshing]; 34 | } 35 | - (void)endFooterRefresh{ 36 | [self.mj_footer endRefreshing]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /DYKit/Category/UITabBar+dy_badge.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITabBar+dy_badge.h 3 | // uuyu 4 | // 5 | // Created by Dainty on 2019/2/27. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | 13 | @interface UITabBar (dy_badge) 14 | //重写是为了修改badge小红点儿的颜色 15 | - (void)dy_showBadgeOnItemIndex:(int)index; //显示小红点 16 | 17 | - (void)dy_showBadgeOnItemIndex:(int)index badgeValue:(int)badgeValue; //显示带badge的红点 18 | 19 | - (void)dy_showBadgeOnItemIndex:(int)index badgeValue:(int)badgeValue smallValue:(BOOL)smallValue; //默认不显示带小红点; 20 | 21 | - (void)dy_hideBadgeOnItemIndex:(int)index; //隐藏小红点 22 | 23 | @end 24 | 25 | 26 | -------------------------------------------------------------------------------- /DYKit/Category/UITabBar+dy_badge.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITabBar+dy_badge.m 3 | // uuyu 4 | // 5 | // Created by Dainty on 2019/2/27. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "UITabBar+dy_badge.h" 10 | #import "DYCustomTabBarLb.h" 11 | 12 | #define TabbarItemNums 5.0 13 | @implementation UITabBar (dy_badge) 14 | 15 | - (void)dy_showBadgeOnItemIndex:(int)index{ 16 | [self dy_showBadgeOnItemIndex:index]; 17 | //新建小红点 18 | UIView *badgeView = [UIView new]; 19 | badgeView.tag = 666 + index; 20 | badgeView.layer.cornerRadius = 5.0f; 21 | badgeView.backgroundColor = [UIColor redColor]; 22 | CGRect tabFrame = self.frame; 23 | 24 | //确定小红点的位置 25 | 26 | float percentX = (index + 0.5) / TabbarItemNums; 27 | CGFloat x = ceil((percentX * tabFrame.size.width)); 28 | CGFloat y = ceil((0.1 * tabFrame.size.height)); 29 | badgeView.frame = CGRectMake(x, y, 10, 10);// 图形大小为10 30 | [self addSubview:badgeView]; 31 | } 32 | 33 | 34 | - (void)dy_hideBadgeOnItemIndex:(int)index{ 35 | [self dy_removeBadgeOnItemIndex:index]; 36 | } 37 | 38 | 39 | - (void)dy_removeBadgeOnItemIndex:(int)index{ 40 | for (UIView *subView in self.subviews) { 41 | if (subView.tag == 666 + index) { 42 | [((DYCustomTabBarLb *)subView).shapeLayer removeFromSuperlayer]; 43 | [subView removeFromSuperview]; 44 | } 45 | } 46 | 47 | } 48 | 49 | - (void)initUnreadCountLb:(CGRect)frame tag:(NSInteger)tag badgeValue:(int)baderValue{ 50 | DYCustomTabBarLb *lb =[[DYCustomTabBarLb alloc] initWithFrame:frame]; 51 | [self addSubview:lb]; 52 | lb.tag = tag; 53 | lb.layer.cornerRadius = frame.size.height / 2; // 图形 54 | if (baderValue != 0) { 55 | lb.text = [NSString stringWithFormat:@"%d",baderValue]; 56 | } 57 | 58 | } 59 | 60 | - (void)dy_showBadgeOnItemIndex:(int)index badgeValue:(int)badgeValue{ 61 | [self dy_removeBadgeOnItemIndex:index]; 62 | // 新建小红点 63 | 64 | 65 | CGRect tabFrame = self.frame; 66 | //确定小红点的位置 67 | 68 | float percentX = (index + 0.5) / TabbarItemNums; 69 | CGFloat x = ceil(percentX * tabFrame.size.width) + 5; 70 | CGFloat y = ceil(0.1 * tabFrame.size.height) - 2; 71 | if (badgeValue < 10) { 72 | [self initUnreadCountLb:CGRectMake(x, y, 14, 14) tag:666 + index badgeValue:badgeValue]; 73 | } 74 | if (badgeValue >= 10 && badgeValue < 100) { 75 | [self initUnreadCountLb:CGRectMake(x, y, 17, 14) tag:666 + index badgeValue:badgeValue]; 76 | } 77 | if (badgeValue >= 100) { 78 | DYCustomTabBarLb *lb = [[DYCustomTabBarLb alloc] initWithFrame:CGRectMake(x, y, 20, 14)]; 79 | lb.text = @"99+"; 80 | [self addSubview:lb]; 81 | lb.tag = 666 + index; 82 | } 83 | 84 | 85 | 86 | 87 | } 88 | 89 | - (void)dy_showBadgeOnItemIndex:(int)index badgeValue:(int)badgeValue smallValue:(BOOL)smallValue{ 90 | 91 | //移除之前的小红点 92 | 93 | [self dy_removeBadgeOnItemIndex:index]; 94 | 95 | //新建小红点 96 | CGRect tabFrame = self.frame; 97 | //确定小红点的位置 98 | float percentX = (index + 0.5) / TabbarItemNums; 99 | CGFloat x = ceilf(percentX * tabFrame.size.width)+5; 100 | CGFloat y = ceilf(0.1 * tabFrame.size.height); 101 | if (smallValue == YES) { 102 | [self initUnreadCountLb:CGRectMake(x, y, 10, 10) tag:888 + index badgeValue:badgeValue]; 103 | }else{ 104 | 105 | if (badgeValue < 10) { 106 | [self initUnreadCountLb:CGRectMake(x, y, 14, 14) tag:888 + index badgeValue:badgeValue]; 107 | 108 | [self initUnreadCountLb:CGRectMake(x, y, 14, 14) tag:666 + index badgeValue:badgeValue]; 109 | 110 | } 111 | if (badgeValue >= 10 && badgeValue < 100) { 112 | [self initUnreadCountLb:CGRectMake(x, y, 17, 14) tag:666 + index badgeValue:badgeValue]; 113 | } 114 | if (badgeValue >= 100) { 115 | DYCustomTabBarLb *lb = [[DYCustomTabBarLb alloc] initWithFrame:CGRectMake(x, y, 20, 14)]; 116 | 117 | lb.text = @"99+"; 118 | [self addSubview:lb]; 119 | lb.tag = 888 + index; 120 | 121 | } 122 | } 123 | 124 | } 125 | @end 126 | -------------------------------------------------------------------------------- /DYKit/Category/UITextField+indexPath.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField+indexPath.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/5/3. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UITextField (indexPath) 12 | @property (nonatomic, strong) NSIndexPath *indexPath; 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/Category/UITextField+indexPath.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField+indexPath.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/5/3. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "UITextField+indexPath.h" 10 | #import 11 | 12 | static char indexPathKey; 13 | @implementation UITextField (indexPath) 14 | - (NSIndexPath *)indexPath{ 15 | return objc_getAssociatedObject(self, &indexPathKey); 16 | } 17 | - (void)setIndexPath:(NSIndexPath *)indexPath{ 18 | objc_setAssociatedObject(self, &indexPathKey, indexPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /DYKit/Category/UIView+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.h 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/20. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Extension) 12 | 13 | @property(nonatomic, assign) IBInspectable CGFloat borderWidth; 14 | @property(nonatomic, assign) IBInspectable UIColor *borderColor; 15 | @property(nonatomic, assign) IBInspectable CGFloat cornerRadius; 16 | /** 起点x坐标 */ 17 | @property (nonatomic, assign) CGFloat x; 18 | /** 起点y坐标 */ 19 | @property (nonatomic, assign) CGFloat y; 20 | /** 中心点x坐标 */ 21 | @property (nonatomic, assign) CGFloat centerX; 22 | /** 中心点y坐标 */ 23 | @property (nonatomic, assign) CGFloat centerY; 24 | /** 宽度 */ 25 | @property (nonatomic, assign) CGFloat width; 26 | /** 高度 */ 27 | @property (nonatomic, assign) CGFloat height; 28 | /** 顶部 */ 29 | @property (nonatomic, assign) CGFloat top; 30 | /** 底部 */ 31 | @property (nonatomic, assign) CGFloat bottom; 32 | /** 左边 */ 33 | @property (nonatomic, assign) CGFloat left; 34 | /** 右边 */ 35 | @property (nonatomic, assign) CGFloat right; 36 | /** size */ 37 | @property (nonatomic, assign) CGSize size; 38 | /** origin */ 39 | @property (nonatomic, assign) CGPoint origin; 40 | 41 | 42 | /** 设置圆角 */ 43 | - (void)rounded:(CGFloat)cornerRadius; 44 | 45 | /** 设置圆角和边框 */ 46 | - (void)rounded:(CGFloat)cornerRadius width:(CGFloat)borderWidth color:(UIColor *)borderColor; 47 | 48 | /** 设置边框 */ 49 | - (void)border:(CGFloat)borderWidth color:(UIColor *)borderColor; 50 | 51 | /** 给哪几个角设置圆角 */ 52 | -(void)round:(CGFloat)cornerRadius RectCorners:(UIRectCorner)rectCorner; 53 | 54 | /** 设置阴影 */ 55 | -(void)shadow:(UIColor *)shadowColor opacity:(CGFloat)opacity radius:(CGFloat)radius offset:(CGSize)offset; 56 | 57 | - (UIViewController *)viewController; 58 | 59 | + (CGFloat)getLabelHeightByWidth:(CGFloat)width Title:(NSString *)title font:(UIFont *)font; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /DYKit/Category/UIView+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.m 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/20. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import "UIView+Extension.h" 10 | 11 | @implementation UIView (Extension) 12 | 13 | - (void)setWidth:(CGFloat)width{ 14 | CGRect frame = self.frame; 15 | frame.size.width = width; 16 | self.frame = frame; 17 | } 18 | - (CGFloat)width{ 19 | return self.frame.size.width; 20 | } 21 | - (void)setSize:(CGSize)size{ 22 | CGRect frame = self.frame; 23 | frame.size = size; 24 | self.frame = frame; 25 | } 26 | - (CGSize)size{ 27 | return self.frame.size; 28 | } 29 | - (void)setHeight:(CGFloat)height 30 | { 31 | CGRect frame = self.frame; 32 | frame.size.height = height; 33 | self.frame = frame; 34 | } 35 | - (CGFloat)height{ 36 | return self.frame.size.height; 37 | } 38 | - (void)setX:(CGFloat)x{ 39 | CGRect frame = self.frame; 40 | frame.origin.x = x; 41 | self.frame = frame; 42 | } 43 | - (CGFloat)x{ 44 | return self.frame.origin.x; 45 | } 46 | - (void)setY:(CGFloat)y{ 47 | CGRect frame = self.frame; 48 | frame.origin.y = y ; 49 | self.frame = frame; 50 | } 51 | - (CGFloat)y{ 52 | return self.frame.origin.y; 53 | } 54 | 55 | - (void)setCenterX:(CGFloat)centerX { 56 | 57 | CGPoint center = self.center; 58 | center.x = centerX; 59 | self.center = center; 60 | 61 | } 62 | 63 | - (CGFloat)centerX { 64 | return self.center.x; 65 | } 66 | 67 | - (void)setCenterY:(CGFloat)centerY{ 68 | CGPoint center = self.center; 69 | center.y = centerY; 70 | self.center = center; 71 | } 72 | 73 | - (CGFloat)centerY { 74 | return self.center.y; 75 | } 76 | 77 | 78 | - (void)setOrigin:(CGPoint)origin { 79 | CGRect frame = self.frame; 80 | frame.origin = origin; 81 | self.frame = frame; 82 | } 83 | 84 | - (CGPoint)origin { 85 | return self.frame.origin; 86 | } 87 | - (CGFloat)top { 88 | return self.frame.origin.y; 89 | } 90 | 91 | - (void)setTop:(CGFloat)top { 92 | CGRect frame = self.frame; 93 | frame.origin.y = top; 94 | self.frame = frame; 95 | } 96 | 97 | - (CGFloat)left { 98 | return self.frame.origin.x; 99 | } 100 | 101 | - (void)setLeft:(CGFloat)left { 102 | CGRect frame = self.frame; 103 | frame.origin.x = left; 104 | self.frame = frame; 105 | } 106 | 107 | 108 | - (CGFloat)bottom { 109 | return self.frame.size.height + self.frame.origin.y; 110 | } 111 | 112 | - (void)setBottom:(CGFloat)bottom { 113 | CGRect frame = self.frame; 114 | frame.origin.y = bottom - frame.size.height; 115 | self.frame = frame; 116 | } 117 | 118 | - (CGFloat)right { 119 | return self.frame.size.width + self.frame.origin.x; 120 | } 121 | 122 | - (void)setRight:(CGFloat)right { 123 | CGRect frame = self.frame; 124 | frame.origin.x = right - frame.size.width; 125 | self.frame = frame; 126 | } 127 | 128 | #pragma mark - layer 129 | - (void)rounded:(CGFloat)cornerRadius { 130 | [self rounded:cornerRadius width:0 color:nil]; 131 | } 132 | 133 | - (void)border:(CGFloat)borderWidth color:(UIColor *)borderColor { 134 | [self rounded:0 width:borderWidth color:borderColor]; 135 | } 136 | 137 | - (void)rounded:(CGFloat)cornerRadius width:(CGFloat)borderWidth color:(UIColor *)borderColor { 138 | self.layer.cornerRadius = cornerRadius; 139 | self.layer.borderWidth = borderWidth; 140 | self.layer.borderColor = [borderColor CGColor]; 141 | self.layer.masksToBounds = YES; 142 | } 143 | 144 | 145 | -(void)round:(CGFloat)cornerRadius RectCorners:(UIRectCorner)rectCorner { 146 | 147 | UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCorner cornerRadii:CGSizeMake(cornerRadius, cornerRadius)]; 148 | CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; 149 | maskLayer.frame = self.bounds; 150 | maskLayer.path = maskPath.CGPath; 151 | self.layer.mask = maskLayer; 152 | } 153 | 154 | 155 | -(void)shadow:(UIColor *)shadowColor opacity:(CGFloat)opacity radius:(CGFloat)radius offset:(CGSize)offset { 156 | //给Cell设置阴影效果 157 | self.layer.masksToBounds = NO; 158 | self.layer.shadowColor = shadowColor.CGColor; 159 | self.layer.shadowOpacity = opacity; 160 | self.layer.shadowRadius = radius; 161 | self.layer.shadowOffset = offset; 162 | } 163 | 164 | 165 | #pragma mark - base 166 | - (UIViewController *)viewController { 167 | 168 | id nextResponder = [self nextResponder]; 169 | while (nextResponder != nil) { 170 | if ([nextResponder isKindOfClass:[UIViewController class]]) { 171 | UIViewController *vc = (UIViewController *)nextResponder; 172 | return vc; 173 | } 174 | nextResponder = [nextResponder nextResponder]; 175 | } 176 | return nil; 177 | } 178 | 179 | + (CGFloat)getLabelHeightByWidth:(CGFloat)width Title:(NSString *)title font:(UIFont *)font { 180 | 181 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 0)]; 182 | label.text = title; 183 | label.font = font; 184 | label.numberOfLines = 0; 185 | [label sizeToFit]; 186 | CGFloat height = label.frame.size.height; 187 | return height; 188 | } 189 | - (void)setBorderWidth:(CGFloat)borderWidth{ 190 | if (borderWidth < 0) { 191 | return; 192 | } 193 | self.layer.borderWidth = borderWidth; 194 | } 195 | - (void)setBorderColor:(UIColor *)borderColor{ 196 | self.layer.borderColor = borderColor.CGColor; 197 | } 198 | - (void)setCornerRadius:(CGFloat)cornerRadius{ 199 | self.layer.cornerRadius = cornerRadius; 200 | self.layer.masksToBounds = YES; 201 | } 202 | - (CGFloat)borderWidth 203 | { 204 | return self.borderWidth; 205 | } 206 | 207 | - (UIColor *)borderColor 208 | { 209 | return self.borderColor; 210 | 211 | } 212 | 213 | - (CGFloat)cornerRadius 214 | { 215 | return self.cornerRadius; 216 | } 217 | @end 218 | -------------------------------------------------------------------------------- /DYKit/Category/UIView+HUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+HUD.h 3 | // HiddView 4 | // 5 | // Created by Dainty on 17/3/31. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SVProgressHUD.h" 11 | @interface UIView (HUD) 12 | 13 | /** 14 | 普通的显示 15 | */ 16 | - (void)show; 17 | //旋转时下方显示内容 18 | - (void)showWithStr:(NSString *)str; 19 | /** 20 | 消失 21 | */ 22 | - (void)dismiss; 23 | 24 | /** 25 | 进度条 26 | */ 27 | - (void)showWithProgress; 28 | //⚠️ 29 | - (void)showInfoWithStr; 30 | //加载成功 31 | - (void)showSuccessWithStr:(NSString *)str; 32 | //加载失败 33 | - (void)showErrorWithStr:(NSString *)str; 34 | //自定义SV的帧动画 35 | - (void)showImageStatus:(NSString *)status; 36 | /** 37 | 当无数据时或有其他情况隐藏HUD 38 | 39 | @param timer 时间(s) 40 | */ 41 | - (void)afterDismissTimer:(NSTimeInterval)timer; 42 | @end 43 | -------------------------------------------------------------------------------- /DYKit/Category/UIView+HUD.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+HUD.m 3 | // HiddView 4 | // 5 | // Created by Dainty on 17/3/31. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "UIView+HUD.h" 10 | 11 | @implementation UIView (HUD) 12 | //- (void)show{ 13 | // /* 14 | // Style指的是背景颜色,背景色与前景色相反。 15 | // 16 | // typedef NS_ENUM(NSInteger, SVProgressHUDStyle) { 17 | // SVProgressHUDStyleLight, // default style, white HUD with black text, HUD background will be blurred on iOS 8 and above 18 | // SVProgressHUDStyleDark, // black HUD and white text, HUD background will be blurred on iOS 8 and above 19 | // SVProgressHUDStyleCustom // uses the fore- and background color properties 20 | // };*/ 21 | // [SVProgressHUD setDefaultStyle:SVProgressHUDStyleCustom]; 22 | // /*AnimationType指的是动画类型,只对 "show" 和 "showWithStatus" 有效 23 | // 24 | // typedef NS_ENUM(NSUInteger, SVProgressHUDAnimationType) { 25 | // SVProgressHUDAnimationTypeFlat, // default animation type, custom flat animation (indefinite animated ring) 26 | // SVProgressHUDAnimationTypeNative // iOS native UIActivityIndicatorView 27 | // }; 28 | // */ 29 | // [SVProgressHUD setDefaultAnimationType:SVProgressHUDAnimationTypeNative]; 30 | // [SVProgressHUD show]; 31 | //} 32 | //-(void)showWithStr:(NSString *)str{ 33 | // 34 | // 35 | // [SVProgressHUD showWithStatus:str]; 36 | // 37 | // //[self afterDismissTimer:2]; 38 | // 39 | //} 40 | - (void)dismiss{ 41 | [SVProgressHUD dismiss]; 42 | } 43 | static float progress = 0.0f; 44 | - (void)showWithProgress{ 45 | progress = 0.0f; 46 | [SVProgressHUD showProgress:0 status:@"DY"]; 47 | [self performSelector:@selector(increaseProgress) withObject:nil afterDelay:0.1f]; 48 | } 49 | - (void)increaseProgress{ 50 | 51 | progress += 0.1f; 52 | [SVProgressHUD showProgress:progress status:@"DY"]; 53 | if (progress < 1.0f) { 54 | [self performSelector:@selector(increaseProgress) withObject:nil afterDelay:0.3f]; 55 | }else{ 56 | [self performSelector:@selector(dismiss) withObject:nil afterDelay:0.4f]; 57 | } 58 | } 59 | - (void)afterDismissTimer:(NSTimeInterval)timer{ 60 | dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, timer * NSEC_PER_SEC); 61 | dispatch_after(time, dispatch_get_main_queue(), ^{ 62 | [self dismiss]; 63 | }); 64 | } 65 | - (void)showSuccessWithStr:(NSString *)str{ 66 | [SVProgressHUD showSuccessWithStatus:str]; 67 | [self afterDismissTimer:2]; 68 | } 69 | - (void)showErrorWithStr:(NSString *)str{ 70 | [SVProgressHUD showErrorWithStatus:str]; 71 | 72 | [self afterDismissTimer:2]; 73 | } 74 | - (void)showInfoWithStr:(NSString *)str{ 75 | [SVProgressHUD showInfoWithStatus:str]; 76 | } 77 | - (void)showImageStatus:(NSString *)status{ 78 | 79 | [SVProgressHUD setMinimumDismissTimeInterval:30]; 80 | 81 | [SVProgressHUD setBackgroundColor:[UIColor DY_colorWithR255Red:1.0f green:1.0f blue:1.0f alpha:0.5f]]; 82 | // 83 | // [SVProgressHUD setBackgroundColor:[UIColor blackColor]]; 84 | [SVProgressHUD showImage:[UIImage imageWithGIFNamed:@"loading"] status:nil]; 85 | 86 | 87 | // [self afterDismissTimer:2]; 88 | } 89 | @end 90 | -------------------------------------------------------------------------------- /DYKit/Category/UIView+dy_CornerRadius.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+dy_CornerRadius.h 3 | // UITableView 4 | // 5 | // Created by Dainty on 2018/9/13. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | 10 | 11 | 12 | #import 13 | 14 | @interface UIView (CornerRadius) 15 | 16 | /** 17 | 绘制一个圆角的view 18 | 19 | @param radius 圆角大小 20 | @param size view大小 21 | */ 22 | - (void)dy_addRounderCornerWithRadius:(CGFloat)radius size:(CGSize)size; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /DYKit/Category/UIView+dy_CornerRadius.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+dy_CornerRadius.m 3 | // UITableView 4 | // 5 | // Created by Dainty on 2018/9/13. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "UIView+dy_CornerRadius.h" 10 | 11 | @implementation UIView (CornerRadius) 12 | - (void)dy_addRounderCornerWithRadius:(CGFloat)radius size:(CGSize)size 13 | { 14 | UIGraphicsBeginImageContextWithOptions(size, NO, 0); 15 | CGContextRef cxt = UIGraphicsGetCurrentContext(); 16 | 17 | CGContextSetFillColorWithColor(cxt, [UIColor redColor].CGColor); 18 | CGContextSetStrokeColorWithColor(cxt, [UIColor redColor].CGColor); 19 | 20 | CGContextMoveToPoint(cxt, size.width, size.height-radius); 21 | CGContextAddArcToPoint(cxt, size.width, size.height, size.width-radius, size.height, radius);//右下角 22 | CGContextAddArcToPoint(cxt, 0, size.height, 0, size.height-radius, radius);//左下角 23 | CGContextAddArcToPoint(cxt, 0, 0, radius, 0, radius);//左上角 24 | CGContextAddArcToPoint(cxt, size.width, 0, size.width, radius, radius);//右上角 25 | CGContextClosePath(cxt); 26 | CGContextDrawPath(cxt, kCGPathFillStroke); 27 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 28 | UIGraphicsEndImageContext(); 29 | 30 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)]; 31 | [imageView setImage:image]; 32 | [self insertSubview:imageView atIndex:0]; 33 | } 34 | 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /DYKit/Category/UIViewController+BackButtonHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+BackButtonHandler.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/8/24. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | @protocol BackButtonHandlerProtocol 11 | 12 | @optional 13 | // 重写下面的方法以拦截导航栏返回按钮点击事件,返回 YES 则 pop,NO 则不 pop 14 | - (BOOL)navigationShouldPopOnBackButton; 15 | @end 16 | @interface UIViewController (BackButtonHandler) 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /DYKit/Category/UIViewController+BackButtonHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+BackButtonHandler.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/8/24. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "UIViewController+BackButtonHandler.h" 10 | 11 | @implementation UIViewController (BackButtonHandler) 12 | 13 | @end 14 | @implementation UINavigationController(ShouldPopOnBackButton) 15 | 16 | 17 | - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item { 18 | 19 | if([self.viewControllers count] < [navigationBar.items count]) { 20 | return YES; 21 | } 22 | 23 | BOOL shouldPop = YES; 24 | UIViewController* vc = [self topViewController]; 25 | if([vc respondsToSelector:@selector(navigationShouldPopOnBackButton)]) { 26 | shouldPop = [vc navigationShouldPopOnBackButton]; 27 | } 28 | 29 | if(shouldPop) { 30 | dispatch_async(dispatch_get_main_queue(), ^{ 31 | [self popViewControllerAnimated:YES]; 32 | }); 33 | } else { 34 | // 取消 pop 后,复原返回按钮的状态 35 | for(UIView *subview in [navigationBar subviews]) { 36 | if(0. < subview.alpha && subview.alpha < 1.) { 37 | [UIView animateWithDuration:.25 animations:^{ 38 | subview.alpha = 1.; 39 | }]; 40 | } 41 | } 42 | } 43 | return NO; 44 | } 45 | 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /DYKit/DYKit.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // DYKit.h 4 | // DYKit 5 | // 6 | // Created by Dainty on 2018/8/14. 7 | // Copyright © 2018年 DAINTY. All rights reserved. 8 | 9 | 10 | #ifndef DYKit_h 11 | #define DYKit_h 12 | #import "DGCategory.h" 13 | #import "class.h" 14 | #import "DY_const.h" 15 | #import "DYNetworking.h" 16 | #endif /* DYKit_h */ 17 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYCacheManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYCacheManager.h 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/28. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /**缓存是否存储成功的block*/ 12 | typedef void(^DYCacheIsSuccessBlock)(BOOL isSuccess); 13 | /**得到缓存的block*/ 14 | typedef void(^DYCacheBlock)(NSData *data , NSString *filePath); 15 | 16 | /**缓存完成的后续操作block*/ 17 | typedef void(^DYCacheCompletedBlock)(void); 18 | 19 | @interface DYCacheManager : NSObject 20 | 21 | + (DYCacheManager *)shareInstance; 22 | 23 | /** 24 | 获取沙盒tmp的文件目录 25 | 26 | @return tmp路径 27 | */ 28 | - (NSString *)tmpPath; 29 | 30 | /** 31 | 判断沙盒是否对应的值 32 | 33 | @param key url 34 | 35 | @return YES/NO 36 | */ 37 | - (BOOL)diskCacheExistsWithKey:(NSString *)key; 38 | /** 39 | 判断沙盒是否对应的值 40 | 41 | @param key url 42 | @param path 沙盒路径 43 | @return YES/NO 44 | */ 45 | - (BOOL)diskCacheExistsWithKey:(NSString *)key path:(NSString *)path; 46 | 47 | /** 48 | * 返回数据及路径 49 | * @param key 存储的文件的url 50 | * @param value 返回在本地的数据及存储文件路径 51 | */ 52 | - (void)getCacheDataForKey:(NSString *)key value:(DYCacheBlock)value; 53 | 54 | /** 55 | 把内容,存储到文件 56 | 57 | @param content 数据 58 | @param key url 59 | @param isSuccess 是否存储成功 60 | */ 61 | - (void)storeContent:(NSObject *)content forKey:(NSString *)key isSuccess:(DYCacheIsSuccessBlock)isSuccess; 62 | - (void)clearDiskWithpath:(NSString *)path completion:(DYCacheCompletedBlock)completion; 63 | @end 64 | 65 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYCacheManager.m: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // DYCacheManager.m 4 | // DYNetWorkingDemo 5 | // 6 | // Created by Dainty on 2019/3/28. 7 | // Copyright © 2019年 DAINTY. All rights reserved. 8 | // 9 | 10 | #import "DYCacheManager.h" 11 | #import 12 | #import 13 | NSString *const PathSpace =@"DYKit"; 14 | NSString *const defaultCachePath =@"AppCache"; 15 | static const NSInteger defaultCacheMaxAge = 60 * 60 * 24 * 7; 16 | 17 | @interface DYCacheManager () 18 | /** 磁盘缓存路径*/ 19 | 20 | @property (nonatomic ,copy)NSString *diskCachePath; 21 | @property (nonatomic, strong) dispatch_queue_t patchQueue; 22 | 23 | @end 24 | @implementation DYCacheManager 25 | 26 | + (DYCacheManager *)shareInstance{ 27 | static dispatch_once_t onceToken; 28 | 29 | static DYCacheManager *instance; 30 | dispatch_once(&onceToken, ^{ 31 | instance = [self new]; 32 | }); 33 | return instance; 34 | } 35 | 36 | 37 | - (void)dealloc{ 38 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 39 | } 40 | - (instancetype)init{ 41 | if (self = [super init]) { 42 | //创建一个串行队列 43 | _patchQueue = dispatch_queue_create("com.dispatch.DYCacheManager", DISPATCH_QUEUE_SERIAL); 44 | [self initCachesfileWithName:defaultCachePath]; 45 | /**前台清除*/ 46 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deleteOldFiles) name:UIApplicationWillTerminateNotification object:nil]; 47 | /**h后台清除缓存*/ 48 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backgroundDeleteOldFiles) name:UIApplicationDidEnterBackgroundNotification object:nil]; 49 | 50 | 51 | }return self; 52 | } 53 | 54 | 55 | #pragma mark - 创建存储文件夹 56 | - (void)initCachesfileWithName:(NSString *)name{ 57 | self.diskCachePath = [[self DYKitPath] stringByAppendingPathComponent:name]; 58 | [self createDirectoryAtPath:self.diskCachePath]; 59 | } 60 | 61 | 62 | 63 | - (void)createDirectoryAtPath:(NSString *)path{ 64 | if (![[NSFileManager defaultManager]fileExistsAtPath:path]) { 65 | [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:NULL]; 66 | }else{ 67 | 68 | } 69 | } 70 | 71 | - (void)deleteOldFiles{ 72 | [self clearCacheWithTime:60 * 60 * 24 * 7 completion:nil]; 73 | } 74 | 75 | 76 | - (void)clearCacheWithTime:(NSTimeInterval)time completion:(DYCacheCompletedBlock)completion{ 77 | [self clearCacheWithTime:time path:self.diskCachePath completion:nil]; 78 | } 79 | 80 | - (void)clearCacheWithTime:(NSTimeInterval)time path:(NSString *)path completion:(DYCacheCompletedBlock)completion{ 81 | 82 | if (!time|| !path) return; 83 | dispatch_async(self.patchQueue, ^{ 84 | NSDate *finalDate = [NSDate dateWithTimeIntervalSinceNow:-time]; 85 | NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:path]; 86 | for (NSString *fileName in fileEnumerator) { 87 | NSString *filePath = [path stringByAppendingPathComponent:fileName]; 88 | NSDictionary *info = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; 89 | NSDate *current = [info objectForKey:NSFileModificationDate]; 90 | if ([[current laterDate:finalDate] isEqualToDate:finalDate]) { 91 | [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; 92 | } 93 | } 94 | if (completion) { 95 | dispatch_async(dispatch_get_main_queue(), ^{ 96 | completion(); 97 | }); 98 | } 99 | }); 100 | 101 | 102 | 103 | } 104 | 105 | - (void)backgroundDeleteOldFiles{ 106 | [self backgroundDeleteOldFilesWith:self.diskCachePath]; 107 | } 108 | - (void)backgroundDeleteOldFilesWith:(NSString *)path { 109 | Class UIApplicationClass = NSClassFromString(@"UIApplication"); 110 | if(!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) { 111 | return; 112 | } 113 | UIApplication *application = [UIApplication performSelector:@selector(sharedApplication)]; 114 | __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ 115 | // Clean up any unfinished task business by marking where you 116 | // stopped or ending the task outright. 117 | [application endBackgroundTask:bgTask]; 118 | bgTask = UIBackgroundTaskInvalid; 119 | }]; 120 | 121 | // Start the long-running task and return immediately. 122 | 123 | 124 | [self clearCacheWithTime:defaultCacheMaxAge path:path completion:^{ 125 | [application endBackgroundTask:bgTask]; 126 | bgTask = UIBackgroundTaskInvalid; 127 | }]; 128 | 129 | } 130 | 131 | 132 | #pragma mark - 清除单个缓存文件 133 | - (void)clearCacheForkey:(NSString *)key{ 134 | [self clearCacheForkey:key completion:nil]; 135 | } 136 | 137 | 138 | - (void)clearCacheForkey:(NSString *)key completion:(DYCacheCompletedBlock)completion{ 139 | 140 | [self clearCacheForkey:key path:self.diskCachePath completion:completion]; 141 | 142 | } 143 | 144 | 145 | - (void)clearCacheForkey:(NSString *)key path:(NSString *)path completion:(DYCacheCompletedBlock)completion{ 146 | 147 | if (!key||!path) return; 148 | dispatch_async(self.patchQueue, ^{ 149 | NSString *filePath = [[self getDiskCacheWithCodingForKey:key path:path] stringByDeletingPathExtension]; 150 | [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; 151 | if (completion) { 152 | dispatch_async(dispatch_get_main_queue(), ^{ 153 | completion(); 154 | }); 155 | } 156 | }); 157 | 158 | 159 | 160 | } 161 | 162 | #pragma mark MD5编码 163 | - (NSString *)getDiskCacheWithCodingForKey:(NSString *)key{ 164 | NSString *path = [self getDiskCacheWithCodingForKey:key path:self.diskCachePath]; 165 | return path; 166 | } 167 | - (NSString *)getDiskCacheWithCodingForKey:(NSString *)key path:(NSString *)path{ 168 | NSString *filename = [self MD5StringForKey:key]; 169 | return [path stringByAppendingPathComponent:filename]; 170 | } 171 | 172 | - (NSString *)MD5StringForKey:(NSString *)key{ 173 | const char *str = [key UTF8String]; 174 | if (str == NULL) { 175 | str = ""; 176 | } 177 | unsigned char r[CC_MD5_DIGEST_LENGTH]; 178 | CC_MD5(str,(CC_LONG)strlen(str), r); 179 | NSString *filename = [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%@",r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],r[8],r[9],r[10],r[11],r[12],r[13],r[14],r[15],[[key pathExtension] isEqualToString:@""] ? @"": [NSString stringWithFormat:@".%@",[key pathExtension]]]; 180 | return filename; 181 | } 182 | #pragma mark - 获取沙盒目录 183 | - (NSString *)homePath{ 184 | 185 | return NSHomeDirectory(); 186 | 187 | } 188 | - (NSString *)documentPath{ 189 | return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 190 | 191 | } 192 | - (NSString *)libraryPath{ 193 | return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject]; 194 | } 195 | 196 | - (NSString *)cachesPath{ 197 | return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 198 | } 199 | 200 | /**存放临时文件*/ 201 | - (NSString *)tmpPath{ 202 | return NSTemporaryDirectory(); 203 | } 204 | 205 | - (NSString *)DYKitPath{ 206 | return [[self cachesPath] stringByAppendingPathComponent:PathSpace]; 207 | } 208 | 209 | - (BOOL)diskCacheExistsWithKey:(NSString *)key{ 210 | return [self diskCacheExistsWithKey:key path:self.diskCachePath]; 211 | } 212 | 213 | - (BOOL)diskCacheExistsWithKey:(NSString *)key path:(NSString *)path{ 214 | NSString *isExists = [[self getDiskCacheWithCodingForKey:key path:path] stringByDeletingPathExtension]; 215 | return [[NSFileManager defaultManager] fileExistsAtPath:isExists]; 216 | } 217 | 218 | #pragma mark - 获取存储数据 219 | - (void)getCacheDataForKey:(NSString *)key value:(DYCacheBlock)value{ 220 | [self getCacheDataForKey:key path:self.diskCachePath value:value]; 221 | } 222 | 223 | 224 | 225 | - (void)getCacheDataForKey:(NSString *)key path:(NSString *)path value:(DYCacheBlock)value{ 226 | if (!key) return; 227 | dispatch_async(self.patchQueue, ^{ 228 | @autoreleasepool { 229 | NSString *filePath = [[self getDiskCacheWithCodingForKey:key path:path]stringByDeletingPathExtension]; 230 | NSData *diskData = [NSData dataWithContentsOfFile:filePath]; 231 | if (value) { 232 | dispatch_async(dispatch_get_main_queue(), ^{ 233 | value(diskData,filePath); 234 | }); 235 | } 236 | } 237 | }); 238 | 239 | 240 | } 241 | 242 | 243 | #pragma mark 存储 244 | - (void)storeContent:(NSObject *)content forKey:(NSString *)key isSuccess:(DYCacheIsSuccessBlock)isSuccess{ 245 | [self storeContent:content forKey:key path:self.diskCachePath isSuccess:isSuccess]; 246 | } 247 | 248 | 249 | 250 | 251 | 252 | - (void)storeContent:(NSObject *)content forKey:(NSString *)key path:(NSString *)path isSuccess:(DYCacheIsSuccessBlock)isSuccess{ 253 | dispatch_async(self.patchQueue,^{ 254 | NSString *codingPath =[[self getDiskCacheWithCodingForKey:key path:path]stringByDeletingPathExtension]; 255 | BOOL result=[self setContent:content writeToFile:codingPath]; 256 | if (isSuccess) { 257 | dispatch_async(dispatch_get_main_queue(), ^{ 258 | isSuccess(result); 259 | }); 260 | } 261 | }); 262 | } 263 | 264 | 265 | - (BOOL)setContent:(NSObject *)content writeToFile:(NSString *)path{ 266 | if (!content||!path){ 267 | return NO; 268 | } 269 | if ([content isKindOfClass:[NSMutableArray class]]) { 270 | return [(NSMutableArray *)content writeToFile:path atomically:YES]; 271 | }else if ([content isKindOfClass:[NSArray class]]) { 272 | return [(NSArray *)content writeToFile:path atomically:YES]; 273 | }else if ([content isKindOfClass:[NSMutableData class]]) { 274 | return [(NSMutableData *)content writeToFile:path atomically:YES]; 275 | }else if ([content isKindOfClass:[NSData class]]) { 276 | return [(NSData *)content writeToFile:path atomically:YES]; 277 | }else if ([content isKindOfClass:[NSMutableDictionary class]]) { 278 | [(NSMutableDictionary *)content writeToFile:path atomically:YES]; 279 | }else if ([content isKindOfClass:[NSDictionary class]]) { 280 | return [(NSDictionary *)content writeToFile:path atomically:YES]; 281 | }else if ([content isKindOfClass:[NSJSONSerialization class]]) { 282 | return [(NSDictionary *)content writeToFile:path atomically:YES]; 283 | }else if ([content isKindOfClass:[NSMutableString class]]) { 284 | return [[((NSString *)content) dataUsingEncoding:NSUTF8StringEncoding] writeToFile:path atomically:YES]; 285 | }else if ([content isKindOfClass:[NSString class]]) { 286 | return [[((NSString *)content) dataUsingEncoding:NSUTF8StringEncoding] writeToFile:path atomically:YES]; 287 | }else if ([content isKindOfClass:[UIImage class]]) { 288 | return [UIImageJPEGRepresentation((UIImage *)content,(CGFloat)0.9) writeToFile:path atomically:YES]; 289 | }else if ([content conformsToProtocol:@protocol(NSCoding)]) { 290 | return [NSKeyedArchiver archiveRootObject:content toFile:path]; 291 | }else { 292 | [NSException raise:@"非法的文件内容" format:@"文件类型%@异常。", NSStringFromClass([content class])]; 293 | return NO; 294 | } 295 | return NO; 296 | } 297 | 298 | #pragma mark - 清除默认路径缓存 299 | - (void)clearCache{ 300 | [self clearCacheOnCompletion:nil]; 301 | } 302 | 303 | - (void)clearCacheOnCompletion:(DYCacheCompletedBlock)completion{ 304 | 305 | dispatch_async(self.patchQueue, ^{ 306 | //[self clearDiskWithpath:self.diskCachePath]; 307 | [[NSFileManager defaultManager] removeItemAtPath:self.diskCachePath error:nil]; 308 | [self createDirectoryAtPath:self.diskCachePath]; 309 | if (completion) { 310 | dispatch_async(dispatch_get_main_queue(),^{ 311 | completion(); 312 | }); 313 | } 314 | }); 315 | } 316 | #pragma mark - 清除自定义路径缓存 317 | - (void)clearDiskWithpath:(NSString *)path{ 318 | [self clearDiskWithpath:path completion:nil]; 319 | } 320 | 321 | - (void)clearDiskWithpath:(NSString *)path completion:(DYCacheCompletedBlock)completion{ 322 | if (!path)return; 323 | dispatch_async(self.patchQueue, ^{ 324 | 325 | NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:path]; 326 | for (NSString *fileName in fileEnumerator) 327 | { 328 | NSString *filePath = [path stringByAppendingPathComponent:fileName]; 329 | 330 | [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; 331 | } 332 | if (completion) { 333 | dispatch_async(dispatch_get_main_queue(),^{ 334 | completion(); 335 | }); 336 | } 337 | }); 338 | } 339 | 340 | 341 | 342 | @end 343 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYImageScaleTools.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYImageScaleTools.h 3 | // DYImageScaleTool 4 | // 5 | // Created by Dainty on 2019/2/13. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DYImageScaleTools : NSObject 14 | + (instancetype)shareInstance; 15 | 16 | //仿微信压缩图像 17 | + (NSData *)reduceOfImageWithWeiChate:(UIImage *)source_Imaga maxByte:(NSInteger)maxByte; 18 | +(NSData *)reduceOfImageWithTwoPoint:(UIImage *)souce_image maxByte:(NSInteger)maxByte; 19 | /** 20 | 等比例缩小图像压缩 21 | 22 | @param source_Imaga 目标image 23 | @param maxByte 最大图片字节 24 | @return 二进制图片 25 | */ 26 | + (NSData *)reduceOfImageWithEqualProportion:(UIImage *)source_Imaga maxByte:(NSInteger)maxByte; 27 | 28 | @end 29 | 30 | NS_ASSUME_NONNULL_END 31 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYImageScaleTools.m: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // DYImageScaleTools.m 4 | // DYImageScaleTool 5 | // 6 | // Created by Dainty on 2019/2/13. 7 | // Copyright © 2019年 DAINTY. All rights reserved. 8 | // 9 | 10 | #import "DYImageScaleTools.h" 11 | /** 计算图像压缩所需时间 */ 12 | #import 13 | 14 | @implementation DYImageScaleTools 15 | double MachTimeToScale(uint64_t time) 16 | { 17 | mach_timebase_info_data_t timebase; 18 | mach_timebase_info(&timebase); 19 | return (double)time * (double)timebase.numer / (double)timebase.denom / 1e9; 20 | } 21 | 22 | 23 | 24 | + (instancetype)shareInstance{ 25 | 26 | static DYImageScaleTools *instance; 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | instance = [[DYImageScaleTools alloc] init]; 30 | }); 31 | 32 | return instance; 33 | } 34 | 35 | 36 | 37 | #pragma mark ============ Public Method 38 | 39 | //仿微信压缩图像 40 | + (NSData *)reduceOfImageWithWeiChate:(UIImage *)source_Imaga maxByte:(NSInteger)maxByte{ 41 | 42 | 43 | CGFloat compression = 1.0f; 44 | CGFloat minCompression = 0.5f; 45 | 46 | NSData *imageData = UIImageJPEGRepresentation(source_Imaga, compression); 47 | CGFloat imageFileSize = imageData.length / 1024; 48 | 49 | CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); 50 | NSLog(@"原图大小:%lu kb",imageData.length / 1024); 51 | DYImageScaleTools *tool = [DYImageScaleTools shareInstance]; 52 | UIImage *newImage = [tool CompresImage:source_Imaga]; 53 | //每次减少的比例 54 | float scale = 0.05; 55 | //循环条件:没到最小压缩比例,且没压缩到目标大小 56 | while ((compression > minCompression)&&(imageFileSize > maxByte)) { 57 | compression -= scale; 58 | imageData = UIImageJPEGRepresentation(newImage, compression); 59 | } 60 | CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime); 61 | NSLog(@"压缩时间: %.4lf s, 压缩后图片大小: %lu Kb", linkTime, (unsigned long)imageData.length/1024); 62 | return imageData; 63 | 64 | } 65 | 66 | +(NSData *)reduceOfImageWithTwoPoint:(UIImage *)souce_image maxByte:(NSInteger)maxByte{ 67 | //先判断当前质量是否满足要求,不满足在进行压缩 68 | 69 | __block NSData *finallImageData = UIImageJPEGRepresentation(souce_image, 1.0); 70 | NSUInteger sizeOrigin = finallImageData.length; 71 | NSUInteger sizeOriginKB = sizeOrigin/ 1024; 72 | if (sizeOriginKB <= maxByte) { 73 | return finallImageData; 74 | } 75 | DYImageScaleTools *tool = [DYImageScaleTools shareInstance]; 76 | uint64_t begin = mach_absolute_time(); 77 | NSLog(@"原图大小 = %lu kb",(unsigned long)finallImageData.length /1024); 78 | //先调整分辨率 79 | CGSize defaultSize = CGSizeMake(1024 , 1024); 80 | UIImage *newImage = [tool newSizeImage:defaultSize image:souce_image]; 81 | finallImageData = UIImageJPEGRepresentation(newImage, 1.0); 82 | //保存压缩系数 83 | NSMutableArray *reduceQualityArr = [NSMutableArray array]; 84 | CGFloat avg = 1.0 / 250; 85 | CGFloat value = avg; 86 | for (int i = 250 ; i >= 1; i--) { 87 | value = i * avg; 88 | [reduceQualityArr addObject:@(value)]; 89 | } 90 | /**调整大小 压缩s系数数组是从大到小存储*/ 91 | finallImageData = [tool halfFuntion:reduceQualityArr image:newImage sourceData:finallImageData maxSize:maxByte]; 92 | //如果还是未能压缩到指定大小,则降分辨率 93 | while (finallImageData.length == 0) { 94 | //每次降100分辨率 95 | if (defaultSize.width - 100 <= 0 || defaultSize.height - 100<=0) { 96 | break; 97 | } 98 | defaultSize = CGSizeMake(defaultSize.width - 100, defaultSize.height - 100); 99 | UIImage *image = [tool newSizeImage:defaultSize image:[UIImage imageWithData:UIImageJPEGRepresentation(newImage, [[reduceQualityArr lastObject] floatValue])]]; 100 | finallImageData = [tool halfFuntion:reduceQualityArr image:image sourceData:UIImageJPEGRepresentation(image, 1.0) maxSize:maxByte]; 101 | } 102 | 103 | uint64_t end = mach_absolute_time(); 104 | NSLog(@"压缩时间 = %g s, 压缩后图片大小 = %lu Kb", MachTimeToScale(end - begin), (unsigned long)finallImageData.length/1024); 105 | 106 | return finallImageData; 107 | } 108 | 109 | 110 | /** 二分法压缩 */ 111 | 112 | - (NSData *)halfFuntion:(NSArray *)arr image:(UIImage *)image sourceData:(NSData *)finallImageData maxSize:(NSInteger)maxSize { 113 | NSData *tempData = [NSData data]; 114 | NSUInteger start = 0; 115 | NSUInteger end = arr.count - 1; 116 | NSUInteger index = 0; 117 | 118 | NSUInteger difference = NSIntegerMax; 119 | while(start <= end) { 120 | index = start + (end - start)/2; 121 | 122 | finallImageData = UIImageJPEGRepresentation(image,[arr[index] floatValue]); 123 | 124 | NSUInteger sizeOrigin = finallImageData.length; 125 | NSUInteger sizeOriginKB = sizeOrigin / 1024; 126 | 127 | // NSLog(@"当前降到的质量 -> %ld 压缩系数 -> %lg", (unsigned long)sizeOriginKB, [arr[index] floatValue]); 128 | 129 | 130 | if (sizeOriginKB > maxSize) { 131 | start = index + 1; 132 | } else if (sizeOriginKB < maxSize) { 133 | if (maxSize-sizeOriginKB < difference) { 134 | difference = maxSize-sizeOriginKB; 135 | tempData = finallImageData; 136 | } 137 | if (index<=0) { 138 | break; 139 | } 140 | end = index - 1; 141 | } else { 142 | break; 143 | } 144 | } 145 | return tempData; 146 | } 147 | 148 | 149 | 150 | /** 151 | 等比例缩小图像压缩 152 | 153 | @param source_Imaga <#source_Imaga description#> 154 | @param maxByte <#maxByte description#> 155 | @return <#return value description#> 156 | */ 157 | + (NSData *)reduceOfImageWithEqualProportion:(UIImage *)source_Imaga maxByte:(NSInteger)maxByte{ 158 | 159 | CGFloat compression = 1.0f; 160 | CGFloat minCompression = 0.5f; 161 | NSData *imageData = UIImageJPEGRepresentation(source_Imaga, compression); 162 | NSLog(@"原图大小 = %lu kb",(unsigned long)imageData.length / 1024); 163 | CGFloat imageFileSize = imageData.length / 1024; 164 | DYImageScaleTools *tool = [DYImageScaleTools shareInstance]; 165 | UIImage *newImage = [tool scaleToWidth:1242 scaleImage:source_Imaga]; 166 | uint64_t begin = mach_absolute_time(); 167 | //每次减少的比例 168 | float scale = 0.05; 169 | while ((compression > minCompression) && imageFileSize > maxByte) { 170 | compression -= scale; 171 | imageData = UIImageJPEGRepresentation(newImage, compression); 172 | } 173 | uint64_t end = mach_absolute_time(); 174 | NSLog(@"压缩时间 = %g s, 压缩后图片大小 = %lu Kb", MachTimeToScale(end - begin), (unsigned long)imageData.length/1024); 175 | return imageData; 176 | 177 | } 178 | 179 | /** 在原有基础上图像等比例缩放 */ 180 | 181 | - (UIImage *)scaleToWidth:(CGFloat)width scaleImage:(UIImage *)image 182 | { 183 | if (width > image.size.width) { 184 | return image; 185 | } 186 | CGFloat height = (width / image.size.width) * image.size.height; 187 | CGRect rect = CGRectMake(0, 0, width, height); 188 | UIGraphicsBeginImageContext(rect.size); 189 | [image drawInRect:rect]; 190 | UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext(); 191 | UIGraphicsEndImageContext(); 192 | return newImage; 193 | } 194 | 195 | 196 | 197 | 198 | - (UIImage *)CompresImage:(UIImage *)image{ 199 | CGSize size = [self compressSizeImage:image]; 200 | UIImage *reImage = [self resizedImage:size image:image]; 201 | return reImage; 202 | } 203 | 204 | 205 | 206 | - (UIImage *)resizedImage:(CGSize)newSize image:(UIImage *)image{ 207 | CGRect newRect = CGRectMake(0, 0, newSize.width, newSize.height); 208 | UIGraphicsBeginImageContext(newRect.size); 209 | 210 | UIImage *newImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:1 orientation:image.imageOrientation]; 211 | [newImage drawInRect:newRect]; 212 | newImage = UIGraphicsGetImageFromCurrentImageContext(); 213 | UIGraphicsEndImageContext(); 214 | return newImage; 215 | } 216 | - (CGSize)compressSizeImage:(UIImage *)image{ 217 | CGFloat width = image.size.width; 218 | CGFloat height = image.size.height; 219 | CGFloat boundary = 1280; 220 | if (width < boundary && height < boundary) { 221 | return CGSizeMake(width, height); 222 | } 223 | CGFloat ratio = MAX(width, height) / MIN(width, height); 224 | if (ratio <= 2) { 225 | CGFloat x = MAX(width, height) / boundary; 226 | if (width > height) { 227 | width = boundary; 228 | height = height / x; 229 | }else{ 230 | height = boundary; 231 | width = width / x; 232 | } 233 | }else{ 234 | if (MIN(width, height) >= boundary) { 235 | CGFloat x = MIN(width, height) / boundary; 236 | if (width < height) { 237 | width = boundary; 238 | height = height / x; 239 | }else{ 240 | height = boundary; 241 | width = width / x; 242 | } 243 | } 244 | } 245 | return CGSizeMake(width, height); 246 | 247 | 248 | } 249 | - (UIImage *)newSizeImage:(CGSize)size image:(UIImage *)source_image{ 250 | CGSize newSize = CGSizeMake(source_image.size.width, source_image.size.height); 251 | 252 | CGFloat tempHeight = newSize.height / size.height; 253 | 254 | CGFloat tempWidth = newSize.width / size.width; 255 | 256 | if (tempWidth > 1.0 && tempWidth > tempHeight) { 257 | newSize = CGSizeMake(source_image.size.width / tempWidth, source_image.size.height / tempWidth); 258 | }else if (tempHeight > 1.0 && tempWidth < tempHeight){ 259 | newSize = CGSizeMake(source_image.size.width / tempHeight, source_image.size.height / tempHeight); 260 | } 261 | UIGraphicsBeginImageContext(newSize); 262 | [source_image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; 263 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 264 | UIGraphicsEndImageContext(); 265 | return newImage; 266 | } 267 | @end 268 | 269 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYNetworking.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYNetworking.h 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | /** 9 | 参考至ZBNetWorking 10 | */ 11 | #ifndef DYNetworking_h 12 | #define DYNetworking_h 13 | 14 | #import "DYRequestConst.h" 15 | #import "DYRequestConfig.h" 16 | #import "DYRequestManager.h" 17 | 18 | #import "NSString+DYUTF8Encoding.h" 19 | #import "DYRequestTool.h" 20 | #import "DYCacheManager.h" 21 | #endif /* DYNetworking_h */ 22 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYRequestConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYRequestConfig.h 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DYRequestConst.h" 11 | #import 12 | @class DYUploadData; 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface DYRequestConfig : NSObject 16 | 17 | /** 18 | 缓存方式 19 | */ 20 | @property (nonatomic, assign) RequestType requestType; 21 | 22 | /** 23 | 图片压缩策略 24 | */ 25 | @property (nonatomic, assign) DYUploadCompressType compressType; 26 | 27 | /** 28 | 请求方式 29 | */ 30 | @property (nonatomic, assign) MethodType methodType; 31 | 32 | /** 33 | 请求参数的格式.默认是HTTP 34 | */ 35 | @property (nonatomic, assign) RequestSerializerType requsetSerializer; 36 | 37 | /** 38 | 返回响应数据的格式.默认是JSON 39 | */ 40 | @property (nonatomic, assign) ResponseSerializerType responseSerializer; 41 | 42 | 43 | /** 44 | 接口请求地址 45 | */ 46 | @property (nonatomic, copy,nonnull) NSString * urlString; 47 | 48 | 49 | /** 50 | 提供外部参数配置 51 | */ 52 | @property (nullable,nonatomic, strong) id parameters; 53 | 54 | /** 55 | 自定义缓存key,在urlString不作为缓存key时使用 56 | */ 57 | @property (nonatomic, copy) NSString *customCacheKey; 58 | 59 | /** 60 | 过滤parameters 里的随机参数 61 | */ 62 | @property (nonatomic,strong) NSArray *parametersfiltrationCacheKey; 63 | 64 | /** 65 | 设置超时时间,默认为30s 66 | */ 67 | @property (nonatomic, assign) NSTimeInterval timeoutInterval; 68 | 69 | 70 | /** 71 | 请求头对象 72 | */ 73 | @property (nonatomic, strong,nonnull) NSMutableDictionary * mutableHTTPRequestHeader; 74 | 75 | /** 76 | 为上传请求提供数据 77 | */ 78 | @property (nonatomic, strong,nullable) NSMutableArray *uploadDatas; 79 | 80 | /** 81 | * 存储路径 只有下载文件方法有用 默认是 NSTemporaryDirectory(); 82 | */ 83 | @property (nonatomic, copy) NSString *downloadSavePath; 84 | 85 | /** 86 | 添加请求头 87 | 88 | @param value value 89 | @param key key 90 | */ 91 | - (void)setValue:(NSString * _Nonnull)value forHeaderKey:(NSString *)key; 92 | 93 | - (void)removeHeaderForkey:(NSString * _Nonnull)key; 94 | 95 | 96 | 97 | //============================================================ 98 | - (void)addFormDataWithName:(NSString *_Nonnull)name fileData:(NSData *_Nonnull)fileData; 99 | - (void)addFormDataWithName:(NSString *_Nonnull)name fileName:(NSString *_Nonnull)fileName mimeType:(NSString *_Nonnull)mimeType fileData:(NSData *_Nonnull)fileData; 100 | - (void)addFormDataWithName:(NSString *_Nonnull)name fileURL:(NSURL *_Nonnull)fileURL; 101 | - (void)addFormDataWithName:(NSString *_Nonnull)name fileName:(NSString *_Nonnull)fileName mimeType:(NSString *_Nonnull)mimeType fileURL:(NSURL *_Nonnull)fileURL; 102 | @end 103 | 104 | 105 | @interface DYUploadData : NSObject 106 | 107 | 108 | /** 109 | 文件对应服务器上的字段 110 | */ 111 | @property (nonatomic, copy) NSString * _Nonnull name; 112 | /** 113 | 文件名 114 | */ 115 | @property (nonatomic, copy,nullable) NSString *fileName; 116 | 117 | /** 118 | png。jpeg 119 | */ 120 | @property (nonatomic, copy,nullable) NSString *mimeType; 121 | 122 | /** 123 | 传入的若是图片,内部做图片压缩处理 124 | */ 125 | @property (nonatomic, strong,nullable) UIImage *uploadImage; 126 | @property (nonatomic, strong,nullable) NSData *fileData; 127 | @property (nonatomic, strong,nullable) NSURL *fileURL; 128 | 129 | //注意:“fileData”和“fileURL”中的任何一个都不应该是“nil”,“fileName”和“mimeType”都必须是“nil”,或者同时被分配, 130 | 131 | 132 | 133 | + (instancetype _Nonnull )formDataWithName:(NSString *_Nonnull)name fileData:(NSData *_Nonnull)fileData; 134 | + (instancetype _Nonnull )formDataWithName:(NSString *_Nonnull)name fileName:(NSString *_Nonnull)fileName mimeType:(NSString *_Nonnull)mimeType fileData:(NSData *_Nonnull)fileData; 135 | + (instancetype _Nonnull )formDataWithName:(NSString *_Nonnull)name fileURL:(NSURL *_Nonnull)fileURL; 136 | + (instancetype _Nonnull )formDataWithName:(NSString *_Nonnull)name fileName:(NSString *_Nonnull)fileName mimeType:(NSString *_Nonnull)mimeType fileURL:(NSURL *_Nonnull)fileURL; 137 | 138 | @end 139 | NS_ASSUME_NONNULL_END 140 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYRequestConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYRequestConfig.m 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYRequestConfig.h" 10 | #import "DYCacheManager.h" 11 | @implementation DYRequestConfig 12 | 13 | - (void)setValue:(NSString *)value forHeaderKey:(NSString *)key{ 14 | if (value) { 15 | [self.mutableHTTPRequestHeader setValue:value forKey:key]; 16 | }else { 17 | [self removeHeaderForkey:key]; 18 | } 19 | } 20 | 21 | //- (void)setDownloadSavePath:(NSString *)downloadSavePath{ 22 | // downloadSavePath = downloadSavePath; 23 | //} 24 | 25 | - (void)setDownloadSavePath:(NSString *)downloadSavePath{ 26 | _downloadSavePath = downloadSavePath; 27 | } 28 | 29 | - (void)removeHeaderForkey:(NSString *)key{ 30 | if (!key) return; 31 | [self.mutableHTTPRequestHeader removeObjectForKey:key]; 32 | 33 | } 34 | 35 | - (NSMutableDictionary *)mutableHTTPRequestHeader{ 36 | if (!_mutableHTTPRequestHeader) { 37 | _mutableHTTPRequestHeader = [[NSMutableDictionary alloc] init]; 38 | } 39 | return _mutableHTTPRequestHeader; 40 | } 41 | - (NSMutableArray *)uploadDatas{ 42 | if (!_uploadDatas) { 43 | _uploadDatas = [NSMutableArray new]; 44 | }return _uploadDatas; 45 | } 46 | 47 | 48 | #pragma mark - 上传请求参数 49 | - (void)addFormDataWithName:(NSString *)name fileData:(NSData *)fileData { 50 | DYUploadData *formData = [DYUploadData formDataWithName:name fileData:fileData]; 51 | [self.uploadDatas addObject:formData]; 52 | } 53 | 54 | - (void)addFormDataWithName:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType fileData:(NSData *)fileData { 55 | DYUploadData *formData = [DYUploadData formDataWithName:name fileName:fileName mimeType:mimeType fileData:fileData]; 56 | [self.uploadDatas addObject:formData]; 57 | } 58 | 59 | - (void)addFormDataWithName:(NSString *)name fileURL:(NSURL *)fileURL { 60 | DYUploadData *formData = [DYUploadData formDataWithName:name fileURL:fileURL]; 61 | [self.uploadDatas addObject:formData]; 62 | } 63 | 64 | - (void)addFormDataWithName:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType fileURL:(NSURL *)fileURL { 65 | DYUploadData *formData = [DYUploadData formDataWithName:name fileName:fileName mimeType:mimeType fileURL:fileURL]; 66 | [self.uploadDatas addObject:formData]; 67 | } 68 | 69 | 70 | @end 71 | @implementation DYUploadData 72 | 73 | + (instancetype)formDataWithName:(NSString *)name fileURL:(NSURL *)fileURL{ 74 | DYUploadData *formData = [DYUploadData new]; 75 | formData.name = name; 76 | formData.fileURL = fileURL; 77 | return formData; 78 | } 79 | 80 | + (instancetype)formDataWithName:(NSString *)name fileData:(NSData *)fileData{ 81 | DYUploadData *formData = [DYUploadData new]; 82 | formData.name = name; 83 | formData.fileData = fileData; 84 | return formData; 85 | } 86 | 87 | 88 | + (instancetype)formDataWithName:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType fileData:(NSData *)fileData{ 89 | DYUploadData *formData = [DYUploadData new]; 90 | formData.name = name; 91 | formData.fileName = fileName; 92 | formData.mimeType = mimeType; 93 | formData.fileData = fileData; 94 | return formData; 95 | } 96 | 97 | 98 | + (instancetype)formDataWithName:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType fileURL:(NSURL *)fileURL{ 99 | 100 | DYUploadData *formData = [DYUploadData new]; 101 | formData.name = name; 102 | formData.fileName = fileName; 103 | formData.mimeType = mimeType; 104 | formData.fileURL = fileURL; 105 | return formData; 106 | 107 | } 108 | @end 109 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYRequestConst.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // DYRequestConst.h 4 | // DYNetWorkingDemo 5 | // 6 | // Created by Dainty on 2019/3/29. 7 | // Copyright © 2019年 DAINTY. All rights reserved. 8 | // 9 | 10 | #ifndef DYRequestConst_h 11 | #define DYRequestConst_h 12 | @class DYRequestConfig; 13 | typedef NS_ENUM(NSInteger, RequestType) { 14 | /**重新请求,不读去缓存,*/ 15 | DYReuestTypeRefresh, 16 | /**优先缓存,无缓存,重新请求*/ 17 | DYReuestTypeCache, 18 | /**加载更多,不读取缓存*/ 19 | DYReuestTypeRefreshMore, 20 | /**加载更多,有缓存,读取缓存,无缓存重新请求*/ 21 | DYReuestTypeReCacheMore, 22 | /**详情页面:有缓存,读取缓存,无缓存,重新请求*/ 23 | DYReuestTypeDetailCache, 24 | /**自定义项: 有缓存,读取缓存--无缓存,重新请求*/ 25 | DYReuestTypeCustomCache 26 | }; 27 | 28 | 29 | /** 30 | HTTP请求类型 31 | */ 32 | typedef NS_ENUM(NSInteger,MethodType){ 33 | DYMethodTypeGET, 34 | 35 | DYMethodTypePOST, 36 | 37 | DYMethodTypeUpload, 38 | 39 | DYMethodTypeDownLoad, 40 | 41 | DYMethodTypePUT, 42 | 43 | DYMethodTypePATCH, 44 | 45 | DYMethodTypeDELETE, 46 | /** 可以在config里面配置使用 DYMethodTypeUploadImage 也可以直接调用 requestUploadImageWithConfig方法*/ 47 | DYMethodTypeUploadImage 48 | 49 | } ; 50 | 51 | /** 52 | 请求参数的格式.默认是HTTP 53 | */ 54 | typedef NS_ENUM(NSUInteger, RequestSerializerType) { 55 | /** 设置请求参数为二进制格式*/ 56 | DYHTTPRequestSerializer, 57 | /** 设置请求参数为JSON格式*/ 58 | DYJSONRequestSerializer 59 | }; 60 | 61 | 62 | 63 | /** 64 | 返回响应数据的格式.默认是JSON 65 | */ 66 | typedef NS_ENUM(NSUInteger, ResponseSerializerType) { 67 | /** 设置响应数据为JSON格式*/ 68 | DYJSONResponseSerializer, 69 | /** 设置响应数据为二进制格式*/ 70 | DYHTTPResponseSerializer 71 | }; 72 | 73 | 74 | 75 | /** 76 | 图片压缩策略 默认使用DYUploadCompressWeiChat; 77 | */ 78 | typedef NS_ENUM(NSUInteger, DYUploadCompressType) { 79 | 80 | DYUploadCompressWeiChat = 40000, // 仿照微信压缩 (仿照微信的压缩比例) 81 | DYUploadCompressEqualProportion, // 图像等比例缩小压缩 (宽度参照 1242 进行等比例缩小) 82 | DYUploadCompressTwoPoints // 采用二分法压缩 (最接近压缩比例) 83 | }; 84 | 85 | 86 | 87 | 88 | /**请求配置的block*/ 89 | typedef void(^requestConfig)(DYRequestConfig *config); 90 | /**请求成功的block*/ 91 | typedef void(^requestSuccess)(id responseObject,RequestType type ,BOOL isCache); 92 | /**请求失败的Block*/ 93 | typedef void (^requestFailure)(NSError *error); 94 | /**请求进度block*/ 95 | typedef void(^progressBlock)(NSProgress *progress); 96 | /**请求取消的block*/ 97 | typedef void(^cancelBlock)(BOOL result ,NSString *urlString); 98 | 99 | 100 | #endif /* DYRequestConst_h */ 101 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYRequestManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYRequestManager.h 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DYRequestConst.h" 11 | #import "DYRequestConfig.h" 12 | 13 | @interface DYRequestManager : NSObject 14 | 15 | 16 | 17 | /** 18 | 请求方法 GET/POST/PUT/PATCH/DELETE 19 | 20 | @param config 请求b配置block 21 | @param success 请求成功block 22 | @param failure 请求失败block 23 | */ 24 | +(void)requestWithConfig:(requestConfig)config success:(requestSuccess)success failure:(requestFailure)failure; 25 | /** 26 | * 请求方法 GET/POST/PUT/PATCH/DELETE/Upload/DownLoad 27 | * 28 | * @param config 请求配置 Block 29 | * @param progress 请求进度 Block 30 | * @param success 请求成功的 Block 31 | * @param failure 请求失败的 Block 32 | */ 33 | + (void)requestWithConfig:(requestConfig)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure; 34 | /** 35 | * 请求方法 仅适用上传图片 36 | * 37 | * @param config 请求配置 Block 38 | * @param progress 请求进度 Block 39 | * @param success 请求成功的 Block 40 | * @param failure 请求失败的 Block 41 | */ 42 | + (void)requestUploadImageWithConfig:(requestConfig)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure; 43 | @end 44 | 45 | 46 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYRequestManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYRequestManager.m 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYRequestManager.h" 10 | 11 | #import "NSString+DYUTF8Encoding.h" 12 | #import "DYRequestTool.h" 13 | #import "DYCacheManager.h" 14 | @implementation DYRequestManager 15 | 16 | 17 | + (void)requestWithConfig:(requestConfig)config success:(requestSuccess)success failure:(requestFailure)failure{ 18 | [self requestWithConfig:config progress:nil success:success failure:failure]; 19 | } 20 | 21 | 22 | + (void)requestWithConfig:(requestConfig)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure { 23 | DYRequestConfig *request=[[DYRequestConfig alloc]init]; 24 | config ? config(request) : nil; 25 | [self sendRequest:request progress:progress success:success failure:failure]; 26 | } 27 | 28 | 29 | + (void)requestUploadImageWithConfig:(requestConfig)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure { 30 | DYRequestConfig *request=[[DYRequestConfig alloc]init]; 31 | config ? config(request) : nil; 32 | if ([request.urlString isEqualToString:@""]||request.urlString == nil) return; 33 | [self sendUploadImageRequest:request progress:progress success:success failure:failure]; 34 | } 35 | 36 | 37 | 38 | +(void)sendRequest:(DYRequestConfig *)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure{ 39 | if ([config.urlString isEqualToString:@""]||config.urlString == nil) return; 40 | if (config.methodType == DYMethodTypeUpload) { 41 | [self sendUploadRequest:config progress:progress success:success failure:failure]; 42 | }else if (config.methodType == DYMethodTypeDownLoad){ 43 | [self sendDownLoadRequest:config progress:progress success:success failure:failure]; 44 | }else if (config.methodType == DYMethodTypeUploadImage){ 45 | [self sendUploadImageRequest:config progress:progress success:success failure:failure]; 46 | } 47 | else{ 48 | [self sendHTTPRequest:config progress:progress success:success failure:failure]; 49 | } 50 | 51 | } 52 | 53 | + (void)sendUploadRequest:(DYRequestConfig *)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure{ 54 | [[DYRequestTool defaultTool] uploadWithRequest:config progress:progress success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { 55 | success ? success(responseObject,0,NO):nil; 56 | } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) { 57 | failure ? failure(error) : nil; 58 | }]; 59 | 60 | } 61 | 62 | + (void)sendUploadImageRequest:(DYRequestConfig *)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure{ 63 | [[DYRequestTool defaultTool] uploadImgWithRequest:config progress:progress success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { 64 | success ? success(responseObject,0,NO):nil; 65 | } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) { 66 | failure ? failure(error) : nil; 67 | }]; 68 | 69 | } 70 | 71 | 72 | 73 | + (void)sendDownLoadRequest:(DYRequestConfig *)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure{ 74 | [[DYRequestTool defaultTool] downloadWithRequest:config downloadProgress:progress completionHandler:^(NSURLResponse * response, NSURL * filePath, NSError * error) { 75 | failure ? failure(error) : nil; 76 | success ? success([filePath path],config.requestType,NO) : nil; 77 | }]; 78 | 79 | } 80 | 81 | + (void)sendHTTPRequest:(DYRequestConfig *)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure{ 82 | NSString *key = [self keyWithParameters:config]; 83 | if ([[DYCacheManager shareInstance] diskCacheExistsWithKey:key] && config.requestType != DYReuestTypeRefresh && config.requestType != DYReuestTypeRefreshMore) { 84 | [[DYCacheManager shareInstance] getCacheDataForKey:key value:^(NSData *data, NSString *filePath) { 85 | id result = [self responseSerializerConfig:config responseObject:data]; 86 | success ? success(result,config.requestType,YES) : nil; 87 | }]; 88 | }else{ 89 | [self dataTaskWithHTTPRequest:config progress:progress success:success failure:failure]; 90 | } 91 | 92 | 93 | } 94 | #pragma mark 发起HTTP请求 95 | + (void)dataTaskWithHTTPRequest:(DYRequestConfig *)config progress:(progressBlock)progress success:(requestSuccess)success failure:(requestFailure)failure{ 96 | [[DYRequestTool defaultTool] dataTaskWithMethod:config progress:^(NSProgress * _Nonnull dy_progress) { 97 | progress ? progress(dy_progress) : nil; 98 | } success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) { 99 | [self storeObject:responseObject request:config]; 100 | id result = [self responseSerializerConfig:config responseObject:responseObject]; 101 | success ? success(result,config.requestType,NO) : nil ; 102 | 103 | } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) { 104 | failure ? failure(error) : nil; 105 | }]; 106 | } 107 | 108 | 109 | + (void)storeObject:(NSObject *)object request:(DYRequestConfig *)config{ 110 | NSString * key= [self keyWithParameters:config]; 111 | [[DYCacheManager shareInstance] storeContent:object forKey:key isSuccess:^(BOOL isSuccess) { 112 | if (isSuccess) { 113 | NSLog(@"store successful"); 114 | }else{ 115 | NSLog(@"store failure"); 116 | } 117 | }]; 118 | } 119 | 120 | 121 | 122 | /** 123 | 数据转换 124 | 125 | @param config 126 | @param responseObject 127 | @return 返回二进制数据 128 | */ 129 | +(id)responseSerializerConfig:(DYRequestConfig *)config responseObject:(id)responseObject{ 130 | if (config.responseSerializer == DYHTTPResponseSerializer) { 131 | return responseObject; 132 | }else{ 133 | NSError *serializationError = nil; 134 | NSData *data = (NSData *)responseObject; 135 | 136 | BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]]; 137 | if (data.length > 0 && !isSpace) { 138 | id result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&serializationError]; 139 | return result; 140 | }else{ 141 | return nil; 142 | } 143 | } 144 | 145 | 146 | } 147 | 148 | +(NSString *)keyWithParameters:(DYRequestConfig *)config{ 149 | if (config.parametersfiltrationCacheKey.count>0) { 150 | NSMutableDictionary *mutableParameters = [NSMutableDictionary dictionaryWithDictionary:config.parameters]; 151 | [mutableParameters removeObjectForKey:config.parametersfiltrationCacheKey]; 152 | config.parameters = [mutableParameters copy]; 153 | } 154 | NSString *urlStringCacheKey; 155 | if (config.customCacheKey) { 156 | urlStringCacheKey = config.customCacheKey; 157 | }else{ 158 | urlStringCacheKey = config.urlString; 159 | } 160 | return [NSString dy_stringUTF8Encoding:[NSString dy_urlString:urlStringCacheKey appendingParameters:config.parameters]]; 161 | } 162 | @end 163 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYRequestTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYRequestTool.h 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "AFHTTPSessionManager.h" 10 | #import "DYRequestConfig.h" 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DYRequestTool : AFHTTPSessionManager 14 | + (instancetype)defaultTool; 15 | 16 | 17 | /** 18 | 发起请求 19 | 20 | @param config DYRequestConfig 21 | @param progress 进度 22 | @param success 成功回调 23 | @param failure 失败回调 24 | @return task 25 | */ 26 | - (NSURLSessionDataTask *)dataTaskWithMethod:(DYRequestConfig *)config 27 | progress:(void(^)(NSProgress * _Nonnull))progress 28 | success:(void(^)(NSURLSessionDataTask *task , id responseObject))success 29 | failure:(void(^)(NSURLSessionDataTask *task,NSError *error))failure; 30 | 31 | /** 32 | 上传文件 33 | 34 | @param config DYRequestConfig 35 | @param progress 进度 36 | @param success 成功回调 37 | @param failure 失败回调 38 | @return task 39 | */ 40 | - (NSURLSessionDataTask *)uploadWithRequest:(DYRequestConfig *)config 41 | progress:(void(^)(NSProgress * _Nonnull))progress 42 | success:(void(^)(NSURLSessionDataTask *task , id responseObject))success 43 | failure:(void(^)(NSURLSessionDataTask *task,NSError *error))failure; 44 | 45 | 46 | /** 47 | 上传图片,内部处理了图片压缩 48 | 49 | @param config DYRequestConfig 50 | @param progress 进度 51 | @param success 成功回调 52 | @param failure 失败回调 53 | @return task 54 | */ 55 | - (NSURLSessionDataTask *)uploadImgWithRequest:(DYRequestConfig *)config 56 | progress:(void(^)(NSProgress * _Nonnull))progress 57 | success:(void(^)(NSURLSessionDataTask *task , id responseObject))success 58 | failure:(void(^)(NSURLSessionDataTask *task,NSError *error))failure; 59 | 60 | 61 | 62 | /** 63 | 下载文件 64 | 65 | @param config DYRequestConfig 66 | @param downloadProgressBlock 进度 67 | @param completionHandler 回调 68 | @return task 69 | */ 70 | - (NSURLSessionDownloadTask *)downloadWithRequest:(DYRequestConfig *)config 71 | downloadProgress:(void (^)(NSProgress * _Nonnull progress))downloadProgressBlock completionHandler:(void (^)(NSURLResponse * _Nonnull, NSURL * _Nonnull, NSError * _Nonnull))completionHandler; 72 | 73 | /** 74 | 取消请求 75 | 76 | @param urlString 请求地址 77 | @param completion 回调 78 | */ 79 | - (void)cancelRequest:(NSString *)urlString completion:(cancelBlock)completion; 80 | @end 81 | 82 | NS_ASSUME_NONNULL_END 83 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/DYRequestTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYRequestTool.m 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYRequestTool.h" 10 | #import 11 | 12 | #import "NSString+DYUTF8Encoding.h" 13 | #import "DYImageScaleTools.h" 14 | #import "DYCacheManager.h" 15 | @implementation DYRequestTool 16 | + (instancetype)defaultTool{ 17 | 18 | static DYRequestTool *instance; 19 | static dispatch_once_t onceToken; 20 | dispatch_once(&onceToken, ^{ 21 | instance = [[DYRequestTool alloc] init]; 22 | }); 23 | return instance; 24 | } 25 | 26 | - (instancetype)init{ 27 | 28 | if (self = [super init]) { 29 | //无条件地信任服务器端返回的证书。 30 | self.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone]; 31 | self.securityPolicy = [AFSecurityPolicy defaultPolicy]; 32 | self.securityPolicy.allowInvalidCertificates = YES; 33 | self.securityPolicy.validatesDomainName = NO; 34 | /*因为与缓存互通 服务器返回的数据 必须是二进制*/ 35 | self.responseSerializer = [AFHTTPResponseSerializer serializer]; 36 | 37 | self.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", 38 | @"application/json", 39 | @"text/json", 40 | @"text/plain", 41 | @"text/javascript", 42 | @"text/xml", 43 | @"image/*",nil]; 44 | [AFNetworkActivityIndicatorManager sharedManager].enabled = YES; 45 | } 46 | return self; 47 | 48 | } 49 | 50 | - (void)dealloc{ 51 | [self invalidateSessionCancelingTasks:YES]; 52 | } 53 | 54 | 55 | - (NSURLSessionDataTask *)dataTaskWithMethod:(DYRequestConfig *)config 56 | progress:(void(^)(NSProgress * _Nonnull))progress 57 | success:(void(^)(NSURLSessionDataTask *task , id responseObject))success 58 | failure:(void(^)(NSURLSessionDataTask *task,NSError *error))failure{ 59 | 60 | self.requestSerializer = config.requsetSerializer == DYJSONRequestSerializer ? [AFJSONRequestSerializer serializer]:[AFHTTPRequestSerializer serializer]; 61 | self.requestSerializer.timeoutInterval = config.timeoutInterval?config.timeoutInterval:30; 62 | if ([[config mutableHTTPRequestHeader] allKeys].count > 0) { 63 | [[config mutableHTTPRequestHeader] enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { 64 | [self.requestSerializer setValue:obj forHTTPHeaderField:key]; 65 | }]; 66 | } 67 | NSString *urlString = [NSString dy_stringUTF8Encoding:config.urlString]; 68 | if (config.methodType == DYMethodTypePOST) { 69 | return [self POST:urlString parameters:config.parameters progress:progress success:success failure:failure]; 70 | }else if (config.methodType == DYMethodTypePUT){ 71 | return [self PUT:urlString parameters:config.parameters success:success failure:failure]; 72 | }else if (config.methodType == DYMethodTypePATCH){ 73 | return [self PATCH:urlString parameters:config.parameters success:success failure:failure]; 74 | }else if (config.methodType == DYMethodTypeDELETE){ 75 | return [self DELETE:urlString parameters:config.parameters success:success failure:failure]; 76 | }else{ 77 | return [self GET:urlString parameters:config.parameters progress:progress success:success failure:failure]; 78 | } 79 | 80 | 81 | } 82 | 83 | 84 | - (NSURLSessionDataTask *)uploadWithRequest:(DYRequestConfig *)config 85 | progress:(void (^)(NSProgress * _Nonnull))progress 86 | success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nonnull))success 87 | failure:(void (^)(NSURLSessionDataTask * _Nonnull, NSError * _Nonnull))failure{ 88 | NSURLSessionDataTask *uploadTask = [self POST:[NSString dy_stringUTF8Encoding:config.urlString] parameters:config.parameters constructingBodyWithBlock:^(id _Nonnull formData) { 89 | 90 | [config.uploadDatas enumerateObjectsUsingBlock:^(DYUploadData * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 91 | if (obj.fileData) { 92 | if (obj.fileName && obj.mimeType) { 93 | [formData appendPartWithFileData:obj.fileData name:obj.name fileName:obj.fileName mimeType:obj.mimeType]; 94 | }else{ 95 | [formData appendPartWithFormData:obj.fileData name:obj.name]; 96 | } 97 | }else if (obj.fileURL){ 98 | if (obj.fileName && obj.mimeType) { 99 | [formData appendPartWithFileURL:obj.fileURL name:obj.name fileName:obj.fileName mimeType:obj.mimeType error:nil]; 100 | } 101 | } 102 | }]; 103 | } progress:^(NSProgress * _Nonnull uploadProgress) { 104 | dispatch_sync(dispatch_get_main_queue(), ^{ 105 | progress?progress(uploadProgress):nil; 106 | }); 107 | } success:success failure:failure]; 108 | 109 | return uploadTask; 110 | } 111 | 112 | 113 | 114 | 115 | 116 | 117 | /** 118 | 上传图片,内部处理了图片压缩 119 | 120 | @param config DYRequestConfig 121 | @param progress 进度 122 | @param success 成功回调 123 | @param failure 失败回调 124 | @return task 125 | */ 126 | - (NSURLSessionDataTask *)uploadImgWithRequest:(DYRequestConfig *)config 127 | progress:(void(^)(NSProgress * _Nonnull))progress 128 | success:(void(^)(NSURLSessionDataTask *task , id responseObject))success 129 | failure:(void(^)(NSURLSessionDataTask *task,NSError *error))failure{ 130 | NSURLSessionDataTask *uploadTask = [self POST:[NSString dy_stringUTF8Encoding:config.urlString] parameters:config.parameters constructingBodyWithBlock:^(id _Nonnull formData) { 131 | 132 | [config.uploadDatas enumerateObjectsUsingBlock:^(DYUploadData * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 133 | if (obj.uploadImage) { 134 | if (obj.fileName && obj.mimeType) { 135 | dispatch_sync(dispatch_get_global_queue(0, 0), ^{ 136 | if (config.compressType == DYUploadCompressEqualProportion) { 137 | obj.fileData = [DYImageScaleTools reduceOfImageWithEqualProportion:obj.uploadImage maxByte:50]; 138 | 139 | }else if (config.compressType == DYUploadCompressTwoPoints){ 140 | obj.fileData = [DYImageScaleTools reduceOfImageWithTwoPoint:obj.uploadImage maxByte:50]; 141 | 142 | }else{ 143 | obj.fileData = [DYImageScaleTools reduceOfImageWithWeiChate:obj.uploadImage maxByte:50]; 144 | } 145 | 146 | [formData appendPartWithFileData:obj.fileData name:obj.name fileName:obj.fileName mimeType:obj.mimeType]; 147 | }); 148 | 149 | }else{ 150 | //[formData appendPartWithFormData:obj.fileData name:obj.name]; 151 | } 152 | }else if (obj.fileURL){ 153 | if (obj.fileName && obj.mimeType) { 154 | [formData appendPartWithFileURL:obj.fileURL name:obj.name fileName:obj.fileName mimeType:obj.mimeType error:nil]; 155 | } 156 | } 157 | }]; 158 | } progress:^(NSProgress * _Nonnull uploadProgress) { 159 | dispatch_sync(dispatch_get_main_queue(), ^{ 160 | progress?progress(uploadProgress):nil; 161 | }); 162 | } success:success failure:failure]; 163 | 164 | return uploadTask; 165 | } 166 | 167 | 168 | - (NSURLSessionDownloadTask *)downloadWithRequest:(DYRequestConfig *)config 169 | downloadProgress:(void (^)(NSProgress * progress))downloadProgressBlock completionHandler:(void (^)(NSURLResponse * _Nonnull, NSURL * _Nonnull, NSError * _Nonnull))completionHandler{ 170 | 171 | NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString dy_stringUTF8Encoding:config.urlString]]]; 172 | 173 | self.requestSerializer.timeoutInterval = config.timeoutInterval?config.timeoutInterval:30; 174 | if ([[config mutableHTTPRequestHeader] allKeys].count > 0) { 175 | [[config mutableHTTPRequestHeader] enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { 176 | [self.requestSerializer setValue:obj forHTTPHeaderField:key]; 177 | }]; 178 | } 179 | 180 | NSURL *downloadFileSavePath; 181 | config.downloadSavePath = config.downloadSavePath ? config.downloadSavePath : [DYCacheManager shareInstance].tmpPath; 182 | BOOL isDircetory; 183 | if (![[NSFileManager defaultManager] fileExistsAtPath:config.downloadSavePath isDirectory:&isDircetory]) { 184 | isDircetory = NO; 185 | } 186 | if (isDircetory) { 187 | NSString *fileName = [urlRequest.URL lastPathComponent]; 188 | downloadFileSavePath = [NSURL fileURLWithPath:[NSString pathWithComponents:@[config.downloadSavePath,fileName]] isDirectory:NO]; 189 | }else{ 190 | downloadFileSavePath = [NSURL fileURLWithPath:config.downloadSavePath isDirectory:NO]; 191 | } 192 | 193 | 194 | NSURLSessionDownloadTask *dataTask = [self downloadTaskWithRequest:urlRequest progress:^(NSProgress * _Nonnull downloadProgress) { 195 | dispatch_async(dispatch_get_main_queue(), ^{ 196 | downloadProgressBlock ? downloadProgressBlock(downloadProgress) : nil; 197 | }); 198 | 199 | } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { 200 | return downloadFileSavePath; 201 | } completionHandler:completionHandler]; 202 | [dataTask resume]; 203 | return dataTask; 204 | } 205 | - (void)cancelRequest:(NSString *)urlString completion:(cancelBlock)completion{ 206 | __block NSString *currentUrlString = nil; 207 | BOOL results; 208 | @synchronized (self.tasks) { 209 | [self.tasks enumerateObjectsUsingBlock:^(NSURLSessionTask * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 210 | if ([[[obj.currentRequest URL] absoluteString] isEqualToString:[NSString dy_stringUTF8Encoding:urlString]]) { 211 | currentUrlString = [[obj.currentRequest URL] absoluteString]; 212 | [obj cancel]; 213 | *stop = YES; 214 | } 215 | }]; 216 | } 217 | if (currentUrlString == nil) { 218 | results = NO; 219 | }else{ 220 | results = YES; 221 | } 222 | completion ? completion(results,currentUrlString) : nil; 223 | } 224 | @end 225 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/NSString+DYUTF8Encoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DYUTF8Encoding.h 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSString (DYUTF8Encoding) 14 | 15 | /** 16 | UTF8 17 | 18 | @param urlString 编码前的url字符串 19 | @return 返回 编码后的url字符串 20 | */ 21 | + (NSString *)dy_stringUTF8Encoding:(NSString *)urlString; 22 | 23 | /** 24 | url字符串与parameters参数的的拼接 25 | 26 | @param urlString url字符串 27 | @param parameters parameters参数 28 | @return 返回拼接后的url字符串 29 | */ 30 | + (NSString *)dy_urlString:(NSString *)urlString appendingParameters:(id)parameters; 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | -------------------------------------------------------------------------------- /DYKit/DYNetWorking/NSString+DYUTF8Encoding.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DYUTF8Encoding.m 3 | // DYNetWorkingDemo 4 | // 5 | // Created by Dainty on 2019/3/29. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "NSString+DYUTF8Encoding.h" 10 | #import 11 | @implementation NSString (DYUTF8Encoding) 12 | + (NSString *)dy_stringUTF8Encoding:(NSString *)urlString{ 13 | if ([[UIDevice currentDevice] systemVersion].floatValue >= 9.0) { 14 | return [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; 15 | }else{ 16 | return [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 17 | } 18 | } 19 | 20 | + (NSString *)dy_urlString:(NSString *)urlString appendingParameters:(id)parameters{ 21 | if (parameters == nil) { 22 | return urlString; 23 | }else{ 24 | NSMutableArray *array = [[NSMutableArray alloc] init]; 25 | for (NSString *key in parameters) { 26 | id obj = [parameters objectForKey:key]; 27 | NSString *str = [NSString stringWithFormat:@"%@=%@",key,obj]; 28 | [array addObject:str]; 29 | } 30 | NSString *parameterString = [array componentsJoinedByString:@"&"]; 31 | return [urlString stringByAppendingString:[NSString stringWithFormat:@"?%@",parameterString]]; 32 | } 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /DYKit/DY_const.h: -------------------------------------------------------------------------------- 1 | // 2 | // DY_const.h 3 | // DYKit 4 | // 5 | // Created by Dainty on 2018/8/14. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #ifndef DY_const_h 10 | #define DY_const_h 11 | 12 | #define kDevice [[UIDevice currentDevice].systemVersion doubleValue] 13 | //当前导航 的高度 14 | #define KnaviBarHeight self.navigationController.navigationBar.height 15 | #define DYISiPhoneX [[UIScreen mainScreen] bounds].size.width >=375.0f && [[UIScreen mainScreen] bounds].size.height >=812.0f 16 | //当前view 的宽度 17 | #define KviewWidth self.view.width 18 | 19 | #define KstatusHeight [[UIScreen mainScreen] bounds].size.width >=375.0f && [[UIScreen mainScreen] bounds].size.height >=812.0f ? 40:20 20 | //当前view 的高度 21 | #define kviewHeight self.view.height 22 | //判断当前是否是X 23 | #define bottomHeight [[UIScreen mainScreen] bounds].size.width >=375.0f && [[UIScreen mainScreen] bounds].size.height >=812.0f ? 88 :49 24 | //当前屏幕 的宽度 25 | #define KScreenW [UIScreen mainScreen].bounds.size.width 26 | //当前屏幕 的高度 27 | #define KScreenH [UIScreen mainScreen].bounds.size.height 28 | 29 | //当前tabBar 的高度 30 | #define KTabBarH self.tabBarController.tabBar.height 31 | 32 | /** 33 | * 相对4.0寸屏幕宽的自动布局 34 | */ 35 | #define KFiveWidth(value) (long)((value)/320.0f * [UIScreen mainScreen].bounds.size.width) 36 | 37 | 38 | /** 39 | * 相对4.0寸屏幕高的比例进行屏幕适配 40 | */ 41 | #define KFiveHeight(value) (long)((value)/568.0f * [UIScreen mainScreen].bounds.size.height) 42 | 43 | 44 | /** 45 | * 相对4.7寸屏幕宽的比例进行屏幕适配 46 | */ 47 | #define KSixWidth(value) (long)((value)/375.0f * [UIScreen mainScreen].bounds.size.width) 48 | 49 | 50 | /** 51 | * 相对4.7寸屏幕高的比例进行屏幕适配 52 | */ 53 | #define KSixHeight(value) (long)((value)/667.0f * [UIScreen mainScreen].bounds.size.height) 54 | 55 | 56 | /** 57 | * 相对5.5寸屏幕宽的比例进行屏幕适配 58 | */ 59 | #define KSixPWidth(value) (long)((value)/414.0f * [UIScreen mainScreen].bounds.size.width) 60 | 61 | 62 | /** 63 | * 相对5.5寸屏幕高的比例进行屏幕适配 64 | */ 65 | #define KSixPHeight(value) (long)((value)/736.0f * [UIScreen mainScreen].bounds.size.height) 66 | 67 | 68 | #define FontSize(size) ((KScreenW / 375.0f) > 1 ? size * 1.07 : size) 69 | 70 | #define KviewBackColor [UIColor DY_colorWithRed:243 green:245 blue:246] 71 | 72 | #define kChatToolBarHeight 49 73 | #endif /* DY_const_h */ 74 | -------------------------------------------------------------------------------- /DYKit/class/DYAuthorizationTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYAuthorizationTool.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/4/6. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | typedef NS_ENUM(NSInteger, DYAuthorizationStatus) { 11 | DYAuthorizationStatusAuthorized = 0, //已授权 12 | DYAuthorizationStatusDenied, //已拒绝 13 | DYAuthorizationStatusRestricted, //应用没有相关权限,且当前用户无法改变这个权限 14 | DYAuthorizationStatusNotDetermined , //未授权 15 | DYAuthorizationStatusNotSupport //硬件不支持,(该处是自己加的) 16 | }; 17 | @interface DYAuthorizationTool : NSObject 18 | 19 | /** 20 | 请求访问相册 21 | 22 | @param callback <#callback description#> 23 | */ 24 | +(void)requestImagePickerAuthorization:(void (^)(DYAuthorizationStatus status))callback; 25 | @end 26 | -------------------------------------------------------------------------------- /DYKit/class/DYAuthorizationTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYAuthorizationTool.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/4/6. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYAuthorizationTool.h" 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | #import 17 | @implementation DYAuthorizationTool 18 | + (void)requestImagePickerAuthorization:(void (^)(DYAuthorizationStatus))callback{ 19 | if ([UIImagePickerController isSourceTypeAvailable: 20 | UIImagePickerControllerSourceTypePhotoLibrary] || [UIImagePickerController isSourceTypeAvailable: 21 | UIImagePickerControllerSourceTypeCamera]){ 22 | if ([UIDevice currentDevice].systemVersion.floatValue > 9.0) { 23 | PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus]; 24 | if (authStatus == PHAuthorizationStatusNotDetermined) { 25 | [self operationCallback:callback status:DYAuthorizationStatusAuthorized]; 26 | }else{ 27 | [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 28 | if (status == PHAuthorizationStatusAuthorized){ 29 | //授权 30 | [self operationCallback:callback status:DYAuthorizationStatusAuthorized]; 31 | }else if (status == PHAuthorizationStatusDenied){ 32 | //已拒绝 33 | [self operationCallback:callback status:DYAuthorizationStatusDenied]; 34 | }else if(status == PHAuthorizationStatusRestricted){ 35 | //应用没有相关权限 如家长控制 36 | [self operationCallback:callback status:DYAuthorizationStatusRestricted]; 37 | 38 | } 39 | }]; 40 | 41 | } 42 | }else{ 43 | ALAuthorizationStatus authStatus = [ALAssetsLibrary authorizationStatus]; 44 | //未授权 45 | if (authStatus == ALAuthorizationStatusNotDetermined) { 46 | if ([UIDevice currentDevice].systemVersion.floatValue > 8.0){ 47 | [self operationCallback:callback status:DYAuthorizationStatusAuthorized]; 48 | }else{ 49 | [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 50 | if (status == PHAuthorizationStatusAuthorized){ 51 | //授权 52 | [self operationCallback:callback status:DYAuthorizationStatusAuthorized]; 53 | }else if (status == PHAuthorizationStatusDenied){ 54 | //已拒绝 55 | [self operationCallback:callback status:DYAuthorizationStatusDenied]; 56 | }else if(status == PHAuthorizationStatusRestricted){ 57 | //应用没有相关权限 如家长控制 58 | [self operationCallback:callback status:DYAuthorizationStatusRestricted]; 59 | } 60 | }]; 61 | } 62 | }else if (authStatus == PHAuthorizationStatusAuthorized){ 63 | //授权 64 | [self operationCallback:callback status:DYAuthorizationStatusAuthorized]; 65 | }else if (authStatus == PHAuthorizationStatusDenied){ 66 | //已拒绝 67 | [self operationCallback:callback status:DYAuthorizationStatusDenied]; 68 | }else if(authStatus == PHAuthorizationStatusRestricted){ 69 | //应用没有相关权限 如家长控制 70 | [self operationCallback:callback status:DYAuthorizationStatusRestricted]; 71 | 72 | } 73 | } 74 | } 75 | else{ 76 | [self operationCallback:callback status:DYAuthorizationStatusNotSupport]; 77 | } 78 | 79 | 80 | } 81 | //执行时 82 | + (void)operationCallback:(void (^)(DYAuthorizationStatus))callback status:(DYAuthorizationStatus)status{ 83 | dispatch_async(dispatch_get_main_queue(), ^{ 84 | if (callback) { 85 | callback(status); 86 | } 87 | }); 88 | } 89 | @end 90 | -------------------------------------------------------------------------------- /DYKit/class/DYChineseInclude.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYChineseInclude.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/5/23. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DYChineseInclude : NSObject 12 | + (BOOL)isIncludeChineseInString:(NSString *)str; 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/class/DYChineseInclude.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYChineseInclude.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/5/23. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYChineseInclude.h" 10 | 11 | @implementation DYChineseInclude 12 | + (BOOL)isIncludeChineseInString:(NSString*)str { 13 | for (int i=0; i 10 | 11 | @interface DYCopyLable : UILabel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/class/DYCopyLable.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYCopyLable.m 3 | // HYBS 4 | // 5 | // Created by Dainty on 2018/3/28. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYCopyLable.h" 10 | 11 | @implementation DYCopyLable 12 | 13 | //为了能接收到事件(能成为第一响应者),我们需要覆盖一个方法: 14 | 15 | -(BOOL)canBecomeFirstResponder 16 | { 17 | return YES; 18 | } 19 | 20 | 21 | //还需要针对复制的操作覆盖两个方法: 22 | 23 | // 可以响应的方法 24 | -(BOOL)canPerformAction:(SEL)action withSender:(id)sender 25 | { 26 | return (action == @selector(copy:)); 27 | } 28 | 29 | 30 | 31 | 32 | //针对于响应方法的实现 33 | -(void)copy:(id)sender 34 | { 35 | UIPasteboard *pboard = [UIPasteboard generalPasteboard]; 36 | pboard.string = self.text; 37 | } 38 | @end 39 | -------------------------------------------------------------------------------- /DYKit/class/DYCustomTabBarLb.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYCustomTabBarLb.h 3 | // uuyu 4 | // 5 | // Created by Dainty on 2019/2/27. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | 13 | @interface DYCustomTabBarLb : UILabel 14 | /** 大圆脱离小圆的最大距离 */ 15 | @property(nonatomic, assign) CGFloat maxDistance; 16 | 17 | /** 小圆 */ 18 | @property(nonatomic, strong) UIView *samllCircleView; 19 | 20 | /** 按钮消失的动画图片组 */ 21 | @property(nonatomic, strong) NSMutableArray *images; 22 | 23 | /** 未读数 */ 24 | @property(nonatomic, strong) NSString *unreadCount; 25 | 26 | @property(nonatomic, strong) UIImage *unreadCountImage; 27 | 28 | /** 绘制不规则图形 */ 29 | @property(nonatomic, strong) CAShapeLayer *shapeLayer; 30 | @end 31 | 32 | 33 | -------------------------------------------------------------------------------- /DYKit/class/DYCustomTabBarLb.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYCustomTabBarLb.m 3 | // uuyu 4 | // 5 | // Created by Dainty on 2019/2/27. 6 | // Copyright © 2019年 DAINTY. All rights reserved. 7 | // 8 | #define kLbWidth self.bounds.size.width 9 | #define kLbHeight self.bounds.size.height 10 | #import "DYCustomTabBarLb.h" 11 | @interface DYCustomTabBarLb () 12 | 13 | @property(nonatomic, strong) NSString *tabBarIndex; 14 | @end 15 | @implementation DYCustomTabBarLb 16 | 17 | 18 | - (instancetype)initWithFrame:(CGRect)frame{ 19 | if (self = [super initWithFrame:frame]) { 20 | 21 | [self setUp]; 22 | [[NSNotificationCenter defaultCenter] addObserver:self 23 | selector:@selector(setTabBarIndexStr:) 24 | name:@"NotifyTabBarIndex" 25 | object:nil]; 26 | self.tabBarIndex = 0; 27 | }return self; 28 | } 29 | 30 | - (NSMutableArray *)images{ 31 | if (!_images) { 32 | _images = [NSMutableArray array]; 33 | for (int i = 1; i < 9; i++) { 34 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%d",i]]; 35 | [_images addObject:image]; 36 | } 37 | 38 | }return _images; 39 | } 40 | 41 | 42 | 43 | - (CAShapeLayer *)shapeLayer{ 44 | if (!_shapeLayer) { 45 | _shapeLayer = [CAShapeLayer layer]; 46 | _shapeLayer.fillColor = [self.backgroundColor CGColor]; 47 | [self.superview.layer insertSublayer:_shapeLayer above:self.layer]; 48 | 49 | 50 | }return _shapeLayer; 51 | } 52 | 53 | 54 | - (UIView *)samllCircleView{ 55 | if (!_samllCircleView) { 56 | _samllCircleView = [UIView new]; 57 | _samllCircleView.backgroundColor = self.backgroundColor; 58 | 59 | 60 | [self.superview insertSubview:_samllCircleView belowSubview:self]; 61 | 62 | }return _samllCircleView; 63 | } 64 | 65 | - (void)setUp{ 66 | CGFloat cornerRadius = (kLbHeight > kLbWidth ? kLbWidth / 2.0 : kLbHeight / 2.0); 67 | self.backgroundColor = [UIColor redColor]; 68 | self.textColor = [UIColor whiteColor]; 69 | self.font = [UIFont boldSystemFontOfSize:9]; 70 | self.textAlignment = NSTextAlignmentCenter; 71 | _maxDistance = cornerRadius * 5; 72 | self.layer.cornerRadius = cornerRadius; 73 | self.layer.masksToBounds = YES; 74 | 75 | CGRect smallCireleRect = CGRectMake(0, 0, cornerRadius * (2 - 0.5), cornerRadius * (2 - - 0.5)); 76 | self.samllCircleView.bounds = smallCireleRect; 77 | _samllCircleView.center = self.center; 78 | _samllCircleView.layer.cornerRadius = _samllCircleView.bounds.size.width / 2; 79 | } 80 | 81 | - (void)setTabBarIndexStr:(NSNotification *)notify { 82 | if (notify != nil) { 83 | self.tabBarIndex = notify.object; 84 | } 85 | } 86 | 87 | - (void)dealloc { 88 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /DYKit/class/DYHiddenView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYHiddenView.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/30. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DYHiddenView : UIView 12 | 13 | /** 14 | 弹出框中间 15 | 16 | @param message 文本内容 17 | @param time 几秒后隐藏 18 | */ 19 | + (void)showCenterMessage:( NSString *)message time:(NSTimeInterval)time; 20 | 21 | 22 | /** 23 | 弹出框 中有图片 24 | 25 | 26 | */ 27 | 28 | 29 | + (void)showCenterWithMessage:(NSString *)message time:(NSTimeInterval)time imageStr:(NSString*)imageStr; 30 | @end 31 | -------------------------------------------------------------------------------- /DYKit/class/DYHiddenView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYHiddenView.m 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/3/30. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYHiddenView.h" 10 | #define HiddenImageH 50.0f 11 | #define HiddenImageW 50.0f 12 | #import "DY_const.h" 13 | @implementation DYHiddenView 14 | 15 | 16 | + (void)showCenterMessage:(NSString *)message time:(NSTimeInterval)time{ 17 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 18 | UIView *showView = [[UIView alloc] init]; 19 | showView.frame = CGRectMake(1,1,1, 1); 20 | showView.backgroundColor = [UIColor blackColor]; 21 | showView.alpha = 1.0f; 22 | showView.layer.cornerRadius = 5.0f; 23 | showView.layer.masksToBounds = YES; 24 | [window addSubview:showView]; 25 | UILabel *lb = [[UILabel alloc] init]; 26 | CGSize szie = CGSizeMake(MAXFLOAT,0); 27 | lb.text = message; 28 | NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:FontSize(16)]}; 29 | CGSize lableSize = [message boundingRectWithSize:szie options: NSStringDrawingUsesFontLeading |NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size; 30 | lb.frame = CGRectMake(FontSize(10), FontSize(5), lableSize.width , lableSize.height); 31 | lb.textColor =[ UIColor whiteColor]; 32 | [lb sizeToFit]; 33 | [showView addSubview:lb]; 34 | showView.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - lableSize.width - FontSize(20) ) / 2, ([UIScreen mainScreen].bounds.size.height - lableSize.height - FontSize(10)) / 2, lb.frame.size.width + FontSize(20) , lb.frame.size.height + FontSize(10)); 35 | [UIView animateWithDuration:time animations:^{ 36 | showView.alpha = 0; 37 | } completion:^(BOOL finished) { 38 | [showView removeFromSuperview]; 39 | }]; 40 | 41 | } 42 | 43 | + (void)showCenterWithMessage:(NSString *)message time:(NSTimeInterval)time imageStr:(NSString *)imageStr{ 44 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 45 | UIView *showView = [[UIView alloc] init]; 46 | showView.frame = CGRectMake(1,1,1, 1); 47 | showView.backgroundColor = [UIColor blackColor]; 48 | showView.alpha = 1.0f; 49 | showView.layer.cornerRadius = 5.0f; 50 | showView.layer.masksToBounds = YES; 51 | [window addSubview:showView]; 52 | 53 | UIImageView *iv = [[UIImageView alloc] init]; 54 | iv.image = [UIImage imageNamed:imageStr]; 55 | iv.frame = CGRectMake(0,0,HiddenImageW, HiddenImageH); 56 | iv.contentMode = UIViewContentModeScaleAspectFit; 57 | [showView addSubview:iv]; 58 | UILabel *lb = [[UILabel alloc] init]; 59 | CGSize szie = CGSizeMake(MAXFLOAT,0); 60 | lb.text = message; 61 | NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:FontSize(16)]}; 62 | CGSize lableSize = [message boundingRectWithSize:szie options: NSStringDrawingUsesFontLeading |NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size; 63 | 64 | CGFloat w; 65 | if (lableSize.width + FontSize(20)> HiddenImageW) { 66 | w = lableSize.width + FontSize(20); 67 | }else{ 68 | w = HiddenImageW; 69 | } 70 | 71 | lb.frame = CGRectMake(FontSize(10), FontSize(5) + HiddenImageH, w , lableSize.height); 72 | lb.textColor =[ UIColor whiteColor]; 73 | lb.textAlignment = NSTextAlignmentCenter; 74 | [lb sizeToFit]; 75 | [showView addSubview:lb]; 76 | 77 | showView.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - w ) / 2, ([UIScreen mainScreen].bounds.size.height - lableSize.height - FontSize(10)) / 2, w+ FontSize(10) , lb.frame.size.height + FontSize(10 )+ HiddenImageH); 78 | 79 | iv.centerX = (w / 2); 80 | [UIView animateWithDuration:time animations:^{ 81 | showView.alpha = 0; 82 | } completion:^(BOOL finished) { 83 | [showView removeFromSuperview]; 84 | }]; 85 | 86 | } 87 | @end 88 | -------------------------------------------------------------------------------- /DYKit/class/DYLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYLabel.h 3 | // DYKit 4 | // 5 | // Created by Dainty on 2018/8/14. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DYLabel : UILabel 12 | //继承该类,解决当文字右对齐时,若文字最后是为空或者为@“”,则会忽略 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/class/DYLabel.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYLabel.m 3 | // DYKit 4 | // 5 | // Created by Dainty on 2018/8/14. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "DYLabel.h" 10 | 11 | @implementation DYLabel 12 | 13 | -(void) drawTextInRect:(CGRect)rect { 14 | //从将文本的绘制Rect宽度缩短半个字体宽度 15 | //self.font.pointSize / 2 16 | return [super drawTextInRect:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width - self.font.pointSize / 2, rect.size.height)]; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /DYKit/class/DataMD5.h: -------------------------------------------------------------------------------- 1 | // 2 | // DataMD5.h 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/21. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #pragma mark - 需要配置的参数 12 | 13 | 14 | // 开放平台登录https://open.weixin.qq.com的开发者中心获取APPID 15 | #define WX_APPID @"wxd21d890******" 16 | // 开放平台登录https://open.weixin.qq.com的开发者中心获取AppSecret。 17 | #define WX_APPSecret @"fc32dfae9******edc5eb5f77dddd4ea5" 18 | // 微信支付商户号 19 | #define MCH_ID @"1353******02" 20 | // 安全校验码(MD5)密钥,商户平台登录账户和密码登录http://pay.weixin.qq.com 21 | // 平台设置的“API密钥”,为了安全,请设置为以数字和字母组成的32字符串。 22 | #define WX_PartnerKey @"B6246A6D******30EEA0F78D3B461" 23 | 24 | #pragma mark - 统一下单请求参数键值 25 | 26 | // 应用id 27 | #define WXAPPID @"appid" 28 | // 商户号 29 | #define WXMCHID @"mch_id" 30 | // 随机字符串 31 | #define WXNONCESTR @"nonce_str" 32 | // 签名 33 | #define WXSIGN @"sign" 34 | // 商品描述 35 | #define WXBODY @"body" 36 | // 商户订单号 37 | #define WXOUTTRADENO @"out_trade_no" 38 | // 总金额 39 | #define WXTOTALFEE @"total_fee" 40 | // 终端IP 41 | #define WXEQUIPMENTIP @"spbill_create_ip" 42 | // 通知地址 43 | #define WXNOTIFYURL @"notify_url" 44 | // 交易类型 45 | #define WXTRADETYPE @"trade_type" 46 | // 预支付交易会话 47 | #define WXPREPAYID @"prepay_id" 48 | 49 | 50 | 51 | #pragma mark - 微信下单接口 52 | 53 | // 微信统一下单接口连接 54 | #define WXUNIFIEDORDERURL @"https://api.mch.weixin.qq.com/pay/unifiedorder" 55 | 56 | @interface DataMD5 : NSObject 57 | 58 | 59 | 60 | @property (nonatomic,strong) NSMutableDictionary *dic; 61 | 62 | - (instancetype)initWithAppid:(NSString *)appid_key 63 | mch_id:(NSString *)mch_id_key 64 | nonce_str:(NSString *)noce_str_key 65 | partner_id:(NSString *)partner_id 66 | body:(NSString *)body_key 67 | out_trade_no :(NSString *)out_trade_no_key 68 | total_fee:(NSString *)total_fee_key 69 | spbill_create_ip:(NSString *)spbill_create_ip_key 70 | notify_url:(NSString *)notify_url_key 71 | trade_type:(NSString *)trade_type_key; 72 | 73 | ///创建发起支付时的SIGN签名(二次签名) 74 | - (NSString *)createMD5SingForPay:(NSString *)appid_key partnerid:(NSString *)partnerid_key prepayid:(NSString *)prepayid_key package:(NSString *)package_key noncestr:(NSString *)noncestr_key timestamp:(UInt32)timestamp_key; 75 | /*MD5加密,传入需要加密的字符串,不可逆 76 | *@param str 需要加密的字符串 77 | *@return 加密后的字符串 78 | */ 79 | - (NSString*)md5:(NSString *)str; 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /DYKit/class/DataMD5.m: -------------------------------------------------------------------------------- 1 | // 2 | // DataMD5.m 3 | // DaintyKit 4 | // 5 | // Created by Dainty on 17/2/21. 6 | // Copyright © 2017年 Edward. All rights reserved. 7 | // 8 | 9 | #import "DataMD5.h" 10 | 11 | #import 12 | 13 | 14 | @interface DataMD5() 15 | @property (nonatomic,strong) NSString *appid; 16 | @property (nonatomic,strong) NSString *mch_id; 17 | @property (nonatomic,strong) NSString *nonce_str; 18 | @property (nonatomic,strong) NSString *partnerkey; 19 | @property (nonatomic,strong) NSString *body; 20 | @property (nonatomic,strong) NSString *out_trade_no; 21 | @property (nonatomic,strong) NSString *total_fee; 22 | @property (nonatomic,strong) NSString *spbill_create_ip; 23 | @property (nonatomic,strong) NSString *notify_url; 24 | @property (nonatomic,strong) NSString *trade_type; 25 | 26 | 27 | @end 28 | @implementation DataMD5 29 | 30 | #pragma makr - 懒加载 31 | 32 | - (NSMutableDictionary *)dic 33 | { 34 | if (!_dic) { 35 | _dic = [NSMutableDictionary dictionary]; 36 | } 37 | return _dic; 38 | } 39 | - (instancetype)initWithAppid:(NSString *)appid_key 40 | mch_id:(NSString *)mch_id_key 41 | nonce_str:(NSString *)noce_str_key 42 | partner_id:(NSString *)partner_id 43 | body:(NSString *)body_key 44 | out_trade_no:(NSString *)out_trade_no_key 45 | total_fee:(NSString *)total_fee_key 46 | spbill_create_ip:(NSString *)spbill_create_ip_key 47 | notify_url:(NSString *)notify_url_key 48 | trade_type:(NSString *)trade_type_key{ 49 | if (self = [super init]) { 50 | _appid = appid_key; 51 | _mch_id = mch_id_key; 52 | _nonce_str = noce_str_key; 53 | _partnerkey = partner_id; 54 | _body = body_key; 55 | _out_trade_no = out_trade_no_key; 56 | _total_fee = total_fee_key; 57 | _spbill_create_ip = spbill_create_ip_key; 58 | _notify_url = notify_url_key; 59 | _trade_type = trade_type_key; 60 | 61 | [self.dic setValue:_appid forKey:WXAPPID]; 62 | [self.dic setValue:_mch_id forKey:WXMCHID]; 63 | [self.dic setValue:_nonce_str forKey:WXNONCESTR]; 64 | [self.dic setValue:_body forKey:WXBODY]; 65 | [self.dic setValue:_out_trade_no forKey:WXOUTTRADENO]; 66 | [self.dic setValue:_total_fee forKey:WXTOTALFEE]; 67 | [self.dic setValue:_spbill_create_ip forKey:WXEQUIPMENTIP]; 68 | [self.dic setValue:_notify_url forKey:WXNOTIFYURL]; 69 | [self.dic setValue:_trade_type forKey:WXTRADETYPE]; 70 | [self createMd5Sign:_dic]; 71 | } 72 | return self; 73 | } 74 | 75 | 76 | 77 | //创建签名 78 | //签名算法 79 | //签名生成的通用步骤如下: 80 | //第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。 81 | //特别注意以下重要规则: 82 | //◆ 参数名ASCII码从小到大排序(字典序); 83 | //◆ 如果参数的值为空不参与签名; 84 | //◆ 参数名区分大小写; 85 | //◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。 86 | //◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段 87 | //第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。 88 | //key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 89 | 90 | -(void)createMd5Sign:(NSMutableDictionary*)dict 91 | { 92 | NSMutableString *contentString =[NSMutableString string]; 93 | 94 | NSArray *keys = [dict allKeys]; 95 | 96 | //按字母顺序排序 97 | NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 98 | return [obj1 compare:obj2 options:NSNumericSearch]; 99 | }]; 100 | 101 | //拼接字符串 102 | for (NSString *categoryId in sortedArray) { 103 | 104 | if ( ![[dict objectForKey:categoryId] isEqualToString:@""] 105 | && ![[dict objectForKey:categoryId] isEqualToString:@"sign"] 106 | && ![[dict objectForKey:categoryId] isEqualToString:@"key"] 107 | ) 108 | { 109 | [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]]; 110 | } 111 | } 112 | //添加商户密钥key字段 113 | [contentString appendFormat:@"key=%@",_partnerkey]; 114 | 115 | //MD5 获取Sign签名 116 | NSString *md5Sign =[self md5:contentString]; 117 | 118 | // 119 | [self.dic setValue:md5Sign forKey:@"sign"]; 120 | 121 | } 122 | 123 | 124 | //创建发起支付时的sign签名 125 | 126 | -(NSString *)createMD5SingForPay:(NSString *)appid_key partnerid:(NSString *)partnerid_key prepayid:(NSString *)prepayid_key package:(NSString *)package_key noncestr:(NSString *)noncestr_key timestamp:(UInt32)timestamp_key{ 127 | NSMutableDictionary *signParams = [NSMutableDictionary dictionary]; 128 | [signParams setObject:appid_key forKey:WXAPPID]; 129 | [signParams setObject:noncestr_key forKey:@"noncestr"]; 130 | [signParams setObject:package_key forKey:@"package"]; 131 | [signParams setObject:partnerid_key forKey:@"partnerid"]; 132 | [signParams setObject:prepayid_key forKey:@"prepayid"]; 133 | [signParams setObject:[NSString stringWithFormat:@"%u",(unsigned int)timestamp_key] forKey:@"timestamp"]; 134 | 135 | NSMutableString *contentString =[NSMutableString string]; 136 | NSArray *keys = [signParams allKeys]; 137 | //按字母顺序排序 138 | NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 139 | return [obj1 compare:obj2 options:NSNumericSearch]; 140 | }]; 141 | //拼接字符串 142 | for (NSString *categoryId in sortedArray) { 143 | if ( ![[signParams objectForKey:categoryId] isEqualToString:@""] 144 | && ![[signParams objectForKey:categoryId] isEqualToString:WXSIGN] 145 | && ![[signParams objectForKey:categoryId] isEqualToString:@"key"] 146 | ) 147 | { 148 | [contentString appendFormat:@"%@=%@&", categoryId, [signParams objectForKey:categoryId]]; 149 | } 150 | } 151 | 152 | 153 | //添加商户密钥key字段 154 | #warning 注意此处一定要添加上商户密钥 155 | [contentString appendFormat:@"key=%@", WX_PartnerKey]; 156 | 157 | NSString *result = [self md5:contentString]; 158 | 159 | return result; 160 | } 161 | 162 | - (NSString *)md5:(NSString *)str{ 163 | const char *cStr = [str UTF8String]; 164 | //加密规则 微信没有出微信支付demo,这里加密规则是参照安装demo来做的 165 | unsigned char result[16] ;//= @"012345678abcdef"; 166 | CC_MD5(cStr, (CC_LONG)strlen(cStr), result); 167 | //这里的x是小写则产生的md5也是小写,x是大写则md5也是大写 168 | return [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 169 | result[0],result[1],result[2],result[3],result[4],result[5],result[6],result[7],result[8],result[9],result[10],result[11],result[12],result[13],result[14],result[15] 170 | ]; 171 | 172 | } 173 | @end 174 | -------------------------------------------------------------------------------- /DYKit/class/JKCopyField.h: -------------------------------------------------------------------------------- 1 | // 2 | // JKCopyField.h 3 | // HYBS 4 | // 5 | // Created by Dainty on 2018/3/28. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JKCopyField : UITextField 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/class/JKCopyField.m: -------------------------------------------------------------------------------- 1 | // 2 | // JKCopyField.m 3 | // HYBS 4 | // 5 | // Created by Dainty on 2018/3/28. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "JKCopyField.h" 10 | 11 | @implementation JKCopyField 12 | 13 | - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { 14 | 15 | NSLog(@"%@",NSStringFromSelector(action)); 16 | 17 | if (action == @selector(cut:) || action == @selector(copy:)) { 18 | return NO; 19 | } 20 | 21 | return YES; 22 | } 23 | 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DYKit/class/JKCustomButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // JKCustomButton.h 3 | // HYBS 4 | // 5 | // Created by Dainty on 2018/3/21. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JKCustomButton : UIButton 12 | //- (void)setRightspacing:(CGFloat)spacing; 13 | @end 14 | -------------------------------------------------------------------------------- /DYKit/class/JKCustomButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // JKCustomButton.m 3 | // HYBS 4 | // 5 | // Created by Dainty on 2018/3/21. 6 | // Copyright © 2018年 DAINTY. All rights reserved. 7 | // 8 | 9 | #import "JKCustomButton.h" 10 | 11 | @implementation JKCustomButton 12 | 13 | - (void)setRightspacing:(CGFloat)spacing 14 | { 15 | CGFloat space = spacing; 16 | CGFloat titleW = CGRectGetWidth(self.titleLabel.bounds); 17 | CGFloat titleH = CGRectGetHeight(self.titleLabel.bounds); 18 | 19 | CGFloat imageW = CGRectGetWidth(self.imageView.bounds); 20 | CGFloat imageH = CGRectGetHeight(self.imageView.bounds); 21 | 22 | CGFloat btnCenterX = CGRectGetWidth(self.bounds)/2; 23 | CGFloat imageCenterX = btnCenterX - titleW/2; 24 | CGFloat titleCenterX = btnCenterX + imageW/2; 25 | 26 | self.titleEdgeInsets = UIEdgeInsetsMake(imageH/2+ space/2, -(titleCenterX-btnCenterX), -(imageH/2 + space/2), titleCenterX-btnCenterX); 27 | self.imageEdgeInsets = UIEdgeInsetsMake(-(titleH/2 + space/2), btnCenterX-imageCenterX, titleH/2+ space/2, -(btnCenterX-imageCenterX)); 28 | } 29 | 30 | - (void)layoutSubviews 31 | { 32 | [super layoutSubviews]; 33 | [self setRightspacing:3]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /DYKit/class/KTDropdownMenuView.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTDropdownMenuView.h 3 | // KTDropdownMenuViewDemo 4 | // 5 | // Created by tujinqiu on 15/10/12. 6 | // Copyright © 2015年 tujinqiu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTDropdownMenuView : UIView 12 | 13 | // width the table width, default 0.0, which indicates that the table width is equal to 14 | // the window width, width less than 80 is two small and will be set to window width as 15 | // well 16 | @property (nonatomic, assign) CGFloat width; 17 | 18 | // cell color default [UIColor colorWithRed:0.296 green:0.613 blue:1.000 alpha:1.000] 19 | @property (nonatomic, strong) UIColor *cellColor; 20 | 21 | // cell seprator color default whiteColor 22 | @property (nonatomic, strong) UIColor *cellSeparatorColor; 23 | 24 | // cell accessory check mark color default whiteColor 25 | @property (nonatomic, strong) UIColor *cellAccessoryCheckmarkColor; 26 | 27 | // cell height default 44 28 | @property (nonatomic, assign) CGFloat cellHeight; 29 | 30 | // animation duration default 0.4 31 | @property (nonatomic, assign) CGFloat animationDuration; 32 | @property (nonatomic, assign) NSUInteger selectedIndex; 33 | 34 | // text color default whiteColor 35 | @property (nonatomic, strong) UIColor *textColor; 36 | 37 | // text font default system 17 38 | @property (nonatomic, strong) UIFont *textFont; 39 | 40 | // background opacity default 0.3 41 | @property (nonatomic, assign) CGFloat backgroundAlpha; 42 | 43 | // callback block 44 | @property (nonatomic, copy) void (^selectedAtIndex)(int index); 45 | @property (nonatomic, assign) CGSize intrinsicContentSize; 46 | - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray*)titles; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /DYKit/class/Sparkle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daintly/DYKit/1d0535a992a4dabcce19223207b671b984970468/DYKit/class/Sparkle1.png -------------------------------------------------------------------------------- /DYKit/class/Sparkle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daintly/DYKit/1d0535a992a4dabcce19223207b671b984970468/DYKit/class/Sparkle2.png -------------------------------------------------------------------------------- /DYKit/class/Sparkle3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Daintly/DYKit/1d0535a992a4dabcce19223207b671b984970468/DYKit/class/Sparkle3.png -------------------------------------------------------------------------------- /DYKit/class/WEmitterButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // WEmitterButton.h 3 | // WEmitterButton 4 | // 5 | // Created by 王王亚 on 16/12/1. 6 | // Copyright © 2016年 王亚. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIView+Extension.h" 11 | typedef NS_ENUM(NSInteger, WButtonType) { 12 | WButtonTypeImageUp = 0, // 图片在上 13 | WButtonTypeImageDown = 1, // 图片在下 14 | BWButtonTypeImageLeft = 2, // 图片在左边 15 | WButtonTypeImageRight = 3, // 图片在右边 16 | WButtonTypeDefault = BWButtonTypeImageLeft, 17 | }; 18 | 19 | @interface WEmitterButton : UIButton 20 | 21 | /** 22 | * 初始化方法 23 | * 24 | * @param type 类型 25 | * @param spacing 间距 26 | * 27 | * @return 实例对象 28 | */ 29 | - (instancetype)initWithType:(WButtonType)type spacing:(CGFloat)spacing; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /DYKit/class/WEmitterButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // WEmitterButton.m 3 | // WEmitterButton 4 | // 5 | // Created by 王王亚 on 16/12/1. 6 | // Copyright © 2016年 王亚. All rights reserved. 7 | // 8 | 9 | #import "WEmitterButton.h" 10 | 11 | @interface WEmitterButton () 12 | 13 | /** weak类型 粒子发射器图层 */ 14 | @property (nonatomic, weak) CAEmitterLayer *emitterLayer; 15 | 16 | @property (nonatomic, assign) WButtonType type; 17 | 18 | @property (nonatomic, assign) CGFloat spacing; 19 | 20 | 21 | @end 22 | 23 | @implementation WEmitterButton 24 | 25 | /** 26 | * 初始化方法 27 | * 28 | * @param type 类型 29 | * 30 | * @return 实例对象 31 | */ 32 | - (instancetype)initWithType:(WButtonType)type spacing:(CGFloat)spacing{ 33 | 34 | if (self = [super init]) { 35 | _type = type; 36 | _spacing = spacing; 37 | } 38 | return self; 39 | } 40 | 41 | - (instancetype)initWithFrame:(CGRect)frame { 42 | self = [super initWithFrame:frame]; 43 | if (self) { 44 | [self setup]; 45 | } 46 | return self; 47 | } 48 | 49 | - (void)setSelected:(BOOL)selected { 50 | [super setSelected:selected]; 51 | [self animation]; 52 | } 53 | 54 | /** 55 | * 重写selected 方法 56 | * 57 | * @param selected 系统参数 58 | */ 59 | - (void)setHighlighted:(BOOL)highlighted{ 60 | 61 | } 62 | 63 | 64 | - (void)setup { 65 | 66 | CAEmitterCell *emitterCell = [CAEmitterCell emitterCell]; 67 | emitterCell.name = @"emitterCell"; 68 | emitterCell.alphaRange = 0.10; 69 | emitterCell.alphaSpeed = -1.0; 70 | emitterCell.lifetime = 0.7; 71 | emitterCell.lifetimeRange = 0.3; 72 | emitterCell.velocity = 30.00; 73 | emitterCell.velocityRange = 4.00; 74 | emitterCell.scale = 0.1; 75 | emitterCell.scaleRange = 0.02; 76 | emitterCell.contents = (id)[UIImage imageNamed:@"Sparkle3"].CGImage; 77 | 78 | 79 | CAEmitterCell *emitterCell3 = [CAEmitterCell emitterCell]; 80 | emitterCell3.name = @"emitterCell3"; 81 | emitterCell3.alphaRange = 0.10; 82 | emitterCell3.alphaSpeed = -1.0; 83 | emitterCell3.lifetime = 0.7; 84 | emitterCell3.lifetimeRange = 0.3; 85 | emitterCell3.velocity = 30.00; 86 | emitterCell3.velocityRange = 4.00; 87 | emitterCell3.scale = 0.1; 88 | emitterCell3.scaleRange = 0.02; 89 | emitterCell3.contents = (id)[UIImage imageNamed:@"Sparkle1"].CGImage; 90 | 91 | 92 | CAEmitterLayer *layer = [CAEmitterLayer layer]; 93 | layer.name = @"emitterLayer"; 94 | layer.emitterShape = kCAEmitterLayerCircle; 95 | layer.emitterMode = kCAEmitterLayerOutline; 96 | layer.emitterCells = @[emitterCell, emitterCell3]; 97 | layer.renderMode = kCAEmitterLayerOldestFirst; 98 | layer.masksToBounds = NO; 99 | layer.zPosition = -1; 100 | 101 | [self.layer addSublayer:layer]; 102 | _emitterLayer = layer; 103 | } 104 | 105 | 106 | /** 107 | * 点赞效果动画 108 | */ 109 | - (void)animation { 110 | 111 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; 112 | if (self.selected) { 113 | animation.values = @[@1.5 ,@0.8, @1.0,@1.2,@1.0]; 114 | animation.duration = 0.5; 115 | // 粒子发射器 发射 116 | [self startFire]; 117 | }else 118 | { 119 | animation.values = @[@0.8, @1.0]; 120 | animation.duration = 0.4; 121 | } 122 | animation.calculationMode = kCAAnimationCubic; 123 | [self.imageView.layer addAnimation:animation forKey:@"transform.scale"]; 124 | } 125 | 126 | - (void)startFire{ 127 | 128 | // 每秒喷射的80个 129 | [self.emitterLayer setValue:@1000 forKeyPath:@"emitterCells.emitterCell.birthRate"]; 130 | [self.emitterLayer setValue:@1000 forKeyPath:@"emitterCells.emitterCell3.birthRate"]; 131 | // 开始 132 | self.emitterLayer.beginTime = CACurrentMediaTime(); 133 | // 执行停止 134 | [self performSelector:@selector(stopFire) withObject:nil afterDelay:0.1]; 135 | 136 | } 137 | 138 | - (void)stopFire { 139 | 140 | //每秒喷射的个数0个 141 | [self.emitterLayer setValue:@0 forKeyPath:@"emitterCells.emitterCell.birthRate"]; 142 | [self.emitterLayer setValue:@0 forKeyPath:@"emitterCells.emitterCell3.birthRate"]; 143 | 144 | } 145 | 146 | 147 | - (void)layoutSubviews{ 148 | [super layoutSubviews]; 149 | 150 | 151 | 152 | switch (_type) { 153 | 154 | case WButtonTypeImageDown: 155 | 156 | self.titleLabel.centerX = CGRectGetMidX(self.bounds); 157 | self.titleLabel.y = 0; 158 | 159 | self.imageView.centerX = CGRectGetMidX(self.bounds); 160 | self.imageView.y = CGRectGetMaxY(self.titleLabel.frame) + _spacing; 161 | 162 | 163 | break; 164 | 165 | case WButtonTypeImageUp: 166 | 167 | self.imageView.centerX = CGRectGetMidX(self.bounds); 168 | self.imageView.y = 0; 169 | 170 | self.titleLabel.centerX = CGRectGetMidX(self.bounds); 171 | self.titleLabel.y = CGRectGetMaxY(self.imageView.frame) + _spacing; 172 | 173 | break; 174 | 175 | default: 176 | break; 177 | } 178 | 179 | /// 设置粒子发射器的锚点 180 | _emitterLayer.position = self.imageView.center; 181 | 182 | 183 | } 184 | 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /DYKit/class/class.h: -------------------------------------------------------------------------------- 1 | // 2 | // class.h 3 | // HSQ 4 | // 5 | // Created by Dainty on 17/4/6. 6 | // Copyright © 2017年 DAINTY. All rights reserved. 7 | // 8 | 9 | #ifndef class_h 10 | #define class_h 11 | 12 | #import "DYHiddenView.h" 13 | #import "DYAuthorizationTool.h" 14 | #import "DY_FMHelper.h" 15 | #import "DYHTTPTool.h" 16 | #import "DYRefreshHeader.h" 17 | #import "DYPinYinSearch.h" 18 | #import "WYAlertView.h" 19 | #endif /* class_h */ 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Daintly 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DYKit --------------------------------------------------------------------------------