├── .gitignore ├── HDAlertView.podspec ├── HDAlertView ├── HDAlertView.h ├── HDAlertView.m ├── HDMacro.h ├── NSString+HDExtension.h ├── NSString+HDExtension.m ├── UIImage+HDExtension.h ├── UIImage+HDExtension.m ├── UIView+HDExtension.h └── UIView+HDExtension.m ├── HDAlertViewDemo ├── HDAlertViewDemo.xcodeproj │ └── project.pbxproj └── HDAlertViewDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── HDAlertView │ ├── HDAlertView.h │ ├── HDAlertView.m │ ├── HDMacro.h │ ├── NSString+HDExtension.h │ ├── NSString+HDExtension.m │ ├── UIImage+HDExtension.h │ ├── UIImage+HDExtension.m │ ├── UIView+HDExtension.h │ └── UIView+HDExtension.m │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── Images └── HDAlertViewDemo.gif ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Xcode 3 | # 4 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 5 | 6 | ## Build generated 7 | build/ 8 | DerivedData/ 9 | 10 | ## Various settings 11 | *.pbxuser 12 | !default.pbxuser 13 | *.mode1v3 14 | !default.mode1v3 15 | *.mode2v3 16 | !default.mode2v3 17 | *.perspectivev3 18 | !default.perspectivev3 19 | xcuserdata/ 20 | *.xcworkspace 21 | UserInterfaceState.xcuserstate 22 | .DS_Store 23 | ._.DS_Store 24 | .pyc 25 | 26 | ## Other 27 | *.moved-aside 28 | *.xcuserstate 29 | 30 | ## Obj-C/Swift specific 31 | *.hmap 32 | *.ipa 33 | *.dSYM.zip 34 | *.dSYM 35 | 36 | # CocoaPods 37 | # 38 | # We recommend against adding the Pods directory to your .gitignore. However 39 | # you should judge for yourself, the pros and cons are mentioned at: 40 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 41 | # 42 | # Pods/ 43 | 44 | # Carthage 45 | # 46 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 47 | # Carthage/Checkouts 48 | 49 | Carthage/Build 50 | 51 | # fastlane 52 | # 53 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 54 | # screenshots whenever they are needed. 55 | # For more information about the recommended setup visit: 56 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 57 | 58 | fastlane/report.xml 59 | fastlane/screenshots 60 | 61 | # Code Injection 62 | # 63 | # After new code Injection tools there's a generated folder /iOSInjectionProject 64 | # https://github.com/johnno1962/injectionforxcode 65 | 66 | iOSInjectionProject/ -------------------------------------------------------------------------------- /HDAlertView.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = "HDAlertView" 4 | s.version = "3.0" 5 | s.summary = "A similar system alertView" 6 | s.homepage = "https://github.com/Bruce-7/HDAlertView" 7 | s.license = "MIT" 8 | s.author = { "HeDong" => "57008939@qq.com" } 9 | s.source = { :git => "https://github.com/Bruce-7/HDAlertView.git", :tag => s.version } 10 | s.platform = :ios, "7.0" 11 | s.requires_arc = true 12 | s.source_files = "HDAlertView" 13 | 14 | end -------------------------------------------------------------------------------- /HDAlertView/HDAlertView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HDAlertView.h 3 | // Seven 4 | // 5 | // Created by HeDong on 16/9/1. 6 | // Copyright © 2016年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "HDMacro.h" 11 | 12 | HD_EXTERN NSString *const HDAlertViewWillShowNotification; 13 | HD_EXTERN NSString *const HDAlertViewDidShowNotification; 14 | HD_EXTERN NSString *const HDAlertViewWillDismissNotification; 15 | HD_EXTERN NSString *const HDAlertViewDidDismissNotification; 16 | 17 | typedef NS_ENUM(NSInteger, HDAlertViewStyle) { 18 | HDAlertViewStyleAlert = 0, // 默认 19 | HDAlertViewStyleActionSheet 20 | }; 21 | 22 | typedef NS_ENUM(NSInteger, HDAlertViewButtonType) { 23 | HDAlertViewButtonTypeDefault = 0, // 字体默认蓝色 24 | HDAlertViewButtonTypeDestructive, // 字体默认红色 25 | HDAlertViewButtonTypeCancel // 字体默认绿色 26 | }; 27 | 28 | typedef NS_ENUM(NSInteger, HDAlertViewBackgroundStyle) { 29 | HDAlertViewBackgroundStyleSolid = 0, // 平面的 30 | HDAlertViewBackgroundStyleGradient // 聚光的 31 | }; 32 | 33 | typedef NS_ENUM(NSInteger, HDAlertViewButtonsListStyle) { 34 | HDAlertViewButtonsListStyleNormal = 0, 35 | HDAlertViewButtonsListStyleRows // 每个按钮都是一行 36 | }; 37 | 38 | typedef NS_ENUM(NSInteger, HDAlertViewTransitionStyle) { 39 | HDAlertViewTransitionStyleFade = 0, // 渐退 40 | HDAlertViewTransitionStyleSlideFromTop, // 从顶部滑入滑出 41 | HDAlertViewTransitionStyleSlideFromBottom, // 从底部滑入滑出 42 | HDAlertViewTransitionStyleBounce, // 弹窗效果 43 | HDAlertViewTransitionStyleDropDown // 顶部滑入底部滑出 44 | }; 45 | 46 | @class HDAlertView; 47 | typedef void(^HDAlertViewHandler)(HDAlertView *alertView); 48 | 49 | @interface HDAlertView : UIView 50 | 51 | /** 是否支持旋转 */ 52 | @property (nonatomic, assign) BOOL isSupportRotating; 53 | 54 | /** 图标的名字 */ 55 | @property (nonatomic, copy) NSString *imageName; 56 | 57 | @property (nonatomic, copy) NSString *title; // ActionSheet模式最多2行 58 | @property (nonatomic, copy) NSString *message; 59 | @property (nonatomic, assign) NSTextAlignment titleTextAlignment; 60 | @property (nonatomic, assign) NSTextAlignment messageTextAlignment; 61 | 62 | 63 | @property (nonatomic, assign) HDAlertViewStyle alertViewStyle; // 默认是HDAlertViewStyleAlert 64 | @property (nonatomic, assign) HDAlertViewTransitionStyle transitionStyle; // 默认是 HDAlertViewTransitionStyleFade 65 | @property (nonatomic, assign) HDAlertViewBackgroundStyle backgroundStyle; // 默认是 HDAlertViewBackgroundStyleSolid 66 | @property (nonatomic, assign) HDAlertViewButtonsListStyle buttonsListStyle; // 默认是 HDAlertViewButtonsListStyleNormal 67 | 68 | @property (nonatomic, copy) HDAlertViewHandler willShowHandler; 69 | @property (nonatomic, copy) HDAlertViewHandler didShowHandler; 70 | @property (nonatomic, copy) HDAlertViewHandler willDismissHandler; 71 | @property (nonatomic, copy) HDAlertViewHandler didDismissHandler; 72 | 73 | @property (nonatomic, strong) UIColor *viewBackgroundColor UI_APPEARANCE_SELECTOR; // 默认是clearColor 74 | @property (nonatomic, strong) UIColor *titleColor UI_APPEARANCE_SELECTOR; // 默认是blackColor 75 | @property (nonatomic, strong) UIColor *messageColor UI_APPEARANCE_SELECTOR; // 默认是darkGrayColor 76 | @property (nonatomic, strong) UIColor *defaultButtonTitleColor UI_APPEARANCE_SELECTOR; // 默认是blueColor 77 | @property (nonatomic, strong) UIColor *cancelButtonTitleColor UI_APPEARANCE_SELECTOR; // 默认是greenColor 78 | @property (nonatomic, strong) UIColor *destructiveButtonTitleColor UI_APPEARANCE_SELECTOR; // 默认是redColor 79 | @property (nonatomic, strong) UIFont *titleFont UI_APPEARANCE_SELECTOR; // 默认是bold 18.0 80 | @property (nonatomic, strong) UIFont *messageFont UI_APPEARANCE_SELECTOR; // 默认是system 16.0 81 | @property (nonatomic, strong) UIFont *buttonFont UI_APPEARANCE_SELECTOR; // 默认是bold buttonFontSize 82 | @property (nonatomic, assign) CGFloat cornerRadius UI_APPEARANCE_SELECTOR; // 默认是10.0 83 | 84 | 85 | /** 86 | * 设置默认按钮图片和状态 87 | */ 88 | - (void)setDefaultButtonImage:(UIImage *)defaultButtonImage forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 89 | 90 | /** 91 | * 设置取消按钮图片和状态 92 | */ 93 | - (void)setCancelButtonImage:(UIImage *)cancelButtonImage forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 94 | 95 | /** 96 | * 设置毁灭性按钮图片和状态 97 | */ 98 | - (void)setDestructiveButtonImage:(UIImage *)destructiveButtonImage forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 99 | 100 | /** 101 | * 初始化一个弹窗提示 102 | */ 103 | - (instancetype)initWithTitle:(NSString *)title andMessage:(NSString *)message; 104 | + (instancetype)alertViewWithTitle:(NSString *)title andMessage:(NSString *)message; 105 | 106 | /** 107 | * 添加按钮点击时候和处理 108 | * 109 | * @param title 按钮名字 110 | * @param type 按钮类型 111 | * @param handler 点击按钮处理事件 112 | */ 113 | - (void)addButtonWithTitle:(NSString *)title type:(HDAlertViewButtonType)type handler:(HDAlertViewHandler)handler; 114 | 115 | /** 116 | * 显示弹窗提示 117 | */ 118 | - (void)show; 119 | 120 | /** 121 | * 移除视图 122 | */ 123 | - (void)removeAlertView; 124 | 125 | /** 126 | 快速弹窗 127 | 128 | @param title 标题 129 | @param message 消息体 130 | @param cancelButtonTitle 取消按钮文字 131 | @param otherButtonTitles 其他按钮 132 | @param block 回调 133 | @return 返回HDAlertView对象 134 | */ 135 | + (HDAlertView *)showAlertViewWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles handler:(void (^)(HDAlertView *alertView, NSInteger buttonIndex))block; 136 | 137 | /** 138 | ActionSheet样式弹窗 139 | 140 | @param title 标题 141 | @return 返回HBAlertView对象 142 | */ 143 | + (HDAlertView *)showActionSheetWithTitle:(NSString *)title; 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /HDAlertView/HDMacro.h: -------------------------------------------------------------------------------- 1 | // 2 | // HDMacro.h 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/03/20. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | //// 判断是真机还是模拟器 10 | //#if TARGET_OS_IPHONE 11 | //// iPhone Device 12 | //#endif 13 | // 14 | //#if TARGET_IPHONE_SIMULATOR 15 | //// iPhone Simulator 16 | //#endif 17 | 18 | 19 | #ifdef __cplusplus 20 | #define HD_EXTERN extern "C" __attribute__((visibility ("default"))) 21 | #else 22 | #define HD_EXTERN extern __attribute__((visibility ("default"))) 23 | #endif 24 | 25 | 26 | #define weakSelf(weakSelf) __weak typeof(self)weakSelf = self; 27 | #define strongSelf(strongSelf) __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf) return; 28 | 29 | 30 | // 由角度获取弧度 31 | #define HDDegreesToRadian(x) (M_PI * (x) / 180.0) 32 | // 由弧度获取角度 33 | #define HDRadianToDegrees(radian) (radian * 180.0) / (M_PI) 34 | 35 | 36 | #define HDNotificationCenter [NSNotificationCenter defaultCenter] 37 | #define HDUserDefaults [NSUserDefaults standardUserDefaults] 38 | #define HDFirstWindow [UIApplication sharedApplication].windows.firstObject 39 | #define HDRootViewController HDFirstWindow.rootViewController 40 | 41 | 42 | /******* 效验对象是否是空 *******/ 43 | #define HDStringIsEmpty(str) ([str isKindOfClass:[NSNull class]] || str == nil || [str length] < 1 ? YES : NO ) 44 | #define HDArrayIsEmpty(array) (array == nil || [array isKindOfClass:[NSNull class]] || array.count == 0) 45 | #define HDDictionaryIsEmpty(dic) (dic == nil || [dic isKindOfClass:[NSNull class]] || dic.allKeys == 0) 46 | #define HDObjectIsEmpty(_object) (_object == nil \ 47 | || [_object isKindOfClass:[NSNull class]] \ 48 | || ([_object respondsToSelector:@selector(length)] && [(NSData *)_object length] == 0) \ 49 | || ([_object respondsToSelector:@selector(count)] && [(NSArray *)_object count] == 0)) 50 | /******* 效验对象是否是空 *******/ 51 | 52 | 53 | /******* APP_INFO *******/ 54 | /** APP版本号 */ 55 | #define HDAppVersion [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] 56 | /** APP BUILD 版本号 */ 57 | #define HDAppBuildVersion [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] 58 | /** APP名字 */ 59 | #define HDAppDisplayName [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] 60 | /** 当前语言 */ 61 | #define HDLocalLanguage [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] 62 | /** 当前国家 */ 63 | #define HDLocalCountry [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode] 64 | /******* APP_INFO *******/ 65 | 66 | 67 | /******* 回到主线程 *******/ 68 | #define dispatch_main_sync_safe(block)\ 69 | if ([NSThread isMainThread]) {\ 70 | block();\ 71 | } else {\ 72 | dispatch_sync(dispatch_get_main_queue(), block);\ 73 | } 74 | 75 | #define dispatch_main_async_safe(block) \ 76 | if ([NSThread isMainThread]) { \ 77 | block(); \ 78 | } else { \ 79 | dispatch_async(dispatch_get_main_queue(), block); \ 80 | } 81 | /******* 回到主线程 *******/ 82 | 83 | 84 | /******* RGB颜色 *******/ 85 | #define HDColorAlpha(r, g, b, a) [UIColor colorWithRed:(r) / 255.0 green:(g) / 255.0 blue:(b) / 255.0 alpha:a] 86 | #define HDColor(r, g, b) HDColorAlpha(r, g, b, 1.0) 87 | 88 | #define HDColorFromHexAlpha(rgbValue, a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16)) / 255.0 green:((float)((rgbValue & 0xFF00) >> 8)) / 255.0 blue:((float)(rgbValue & 0xFF)) / 255.0 alpha:a] 89 | #define HDColorFromHex(rgbValue) HDColorFromHexAlpha(rgbValue, 1.0) 90 | /******* RGB颜色 *******/ 91 | 92 | 93 | /******* 屏幕尺寸 *******/ 94 | #define HDMainScreenWidth [UIScreen mainScreen].bounds.size.width 95 | #define HDMainScreenHeight [UIScreen mainScreen].bounds.size.height 96 | #define HDMainScreenBounds [UIScreen mainScreen].bounds 97 | /******* 屏幕尺寸 *******/ 98 | 99 | 100 | /******* 屏幕系数 *******/ 101 | #define HDiPhone6WidthCoefficient(width) (width / 375.0) // 以苹果6为准的系数 102 | #define HDiPhone6HeightCoefficient(height) (height / 667.0) // 以苹果6为准的系数 103 | #define HDiPhone6ScaleWidth(width) (HDiPhone6WidthCoefficient(width) * HDMainScreenWidth) // 以苹果6为准的系数得到的宽 104 | #define HDiPhone6ScaleHeight(height) (HDiPhone6HeightCoefficient(height) * HDMainScreenHeight) // 以苹果6为准的系数得到的高 105 | /******* 屏幕系数 *******/ 106 | 107 | 108 | /******* 设备型号和系统 *******/ 109 | /** 检查系统版本 */ 110 | #define HDSYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) 111 | #define HDSYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) 112 | #define HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 113 | #define HDSYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) 114 | #define HDSYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) 115 | 116 | #define iOS5_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.0") 117 | #define iOS6_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0") 118 | #define iOS7_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0") 119 | #define iOS8_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0") 120 | #define iOS9_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9.0") 121 | #define iOS10_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0") 122 | 123 | /** 系统和版本号 */ 124 | #define HDDevice [UIDevice currentDevice] 125 | #define HDDeviceName HDDevice.name // 设备名称 126 | #define HDDeviceModel HDDevice.model // 设备类型 127 | #define HDDeviceLocalizedModel HDDevice.localizedModel // 本地化模式 128 | #define HDDeviceSystemName HDDevice.systemName // 系统名字 129 | #define HDDeviceSystemVersion HDDevice.systemVersion // 系统版本 130 | #define HDDeviceOrientation HDDevice.orientation // 设备朝向 131 | //#define HDDeviceUUID HDDevice.identifierForVendor.UUIDString // UUID // 使用苹果不让上传App Store!!! 132 | #define HDiOS8 ([HDDeviceSystemVersion floatValue] >= 8.0) // iOS8以上 133 | #define HDiPhone ([HDDeviceModel rangeOfString:@"iPhone"].length > 0) 134 | #define HDiPod ([HDDeviceModel rangeOfString:@"iPod"].length > 0) 135 | #define HDiPad (HDDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) 136 | /******* 设备型号和系统 *******/ 137 | 138 | 139 | /******* 日志打印替换 *******/ 140 | //#import 141 | #ifdef DEBUG 142 | 143 | //#define HDLog(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagVerbose, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 144 | // 145 | //#define HDLogError(frmt, ...) LOG_MAYBE(NO, LOG_LEVEL_DEF, DDLogFlagError, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 146 | // 147 | //#define HDLogWarn(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagWarning, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 148 | // 149 | //#define HDLogInfo(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagInfo, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 150 | // 151 | //#define HDLogDebug(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagDebug, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 152 | // 153 | //#define HDLogVerbose(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagVerbose, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 154 | 155 | 156 | #define HDAssert(...) NSAssert(__VA_ARGS__) 157 | #define HDParameterAssert(condition) NSAssert((condition), @"Invalid parameter not satisfying: %@", @#condition) 158 | 159 | //static const int ddLogLevel = LOG_LEVEL_VERBOSE; 160 | 161 | #else 162 | 163 | #define HDLog(...) 164 | #define HDLogError(frmt, ...) 165 | #define HDLogWarn(frmt, ...) 166 | #define HDLogInfo(frmt, ...) 167 | #define HDLogDebug(frmt, ...) 168 | 169 | #define HDAssert(...) 170 | #define HDParameterAssert(condition) 171 | //static const int ddLogLevel = LOG_LEVEL_OFF; 172 | 173 | #endif 174 | /******* 日志打印替换 *******/ 175 | 176 | 177 | /******* 归档解档 *******/ 178 | #define HDCodingImplementation \ 179 | - (void)encodeWithCoder:(NSCoder *)aCoder { \ 180 | unsigned int count = 0; \ 181 | Ivar *ivars = class_copyIvarList([self class], &count); \ 182 | for (int i = 0; i < count; i++) { \ 183 | Ivar ivar = ivars[i]; \ 184 | const char *name = ivar_getName(ivar); \ 185 | NSString *key = [NSString stringWithUTF8String:name]; \ 186 | id value = [self valueForKey:key]; \ 187 | [aCoder encodeObject:value forKey:key]; \ 188 | } \ 189 | free(ivars); \ 190 | } \ 191 | \ 192 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { \ 193 | if (self = [super init]) { \ 194 | unsigned int count = 0; \ 195 | Ivar *ivars = class_copyIvarList([self class], &count); \ 196 | for (int i = 0; i < count; i++) { \ 197 | Ivar ivar = ivars[i]; \ 198 | const char *name = ivar_getName(ivar); \ 199 | NSString *key = [NSString stringWithUTF8String:name]; \ 200 | id value = [aDecoder decodeObjectForKey:key]; \ 201 | [self setValue:value forKey:key]; \ 202 | } \ 203 | free(ivars); \ 204 | } \ 205 | return self; \ 206 | } 207 | /******* 归档解档 *******/ 208 | -------------------------------------------------------------------------------- /HDAlertView/NSString+HDExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+HDExtension.h 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/5/10. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "HDMacro.h" 11 | 12 | @interface NSString (HDExtension) 13 | 14 | #pragma mark - 散列函数 15 | /** 16 | * 计算MD5散列结果 17 | * 18 | * 终端测试命令: 19 | * @code 20 | * md5 -s "string" 21 | * @endcode 22 | * 23 | *

提示:随着 MD5 碰撞生成器的出现,MD5 算法不应被用于任何软件完整性检查或代码签名的用途。

24 | * 25 | * @return 32个字符的MD5散列字符串 26 | */ 27 | - (instancetype)hd_md5String; 28 | 29 | /** 30 | * 计算SHA1散列结果 31 | * 32 | * 终端测试命令: 33 | * @code 34 | * echo -n "string" | openssl sha -sha1 35 | * @endcode 36 | * 37 | * @return 40个字符的SHA1散列字符串 38 | */ 39 | - (instancetype)hd_sha1String; 40 | 41 | /** 42 | * 计算SHA224散列结果 43 | * 44 | * 终端测试命令: 45 | * @code 46 | * echo -n "string" | openssl sha -sha224 47 | * @endcode 48 | * 49 | * @return 56个字符的SHA224散列字符串 50 | */ 51 | - (instancetype)hd_sha224String; 52 | 53 | /** 54 | * 计算SHA256散列结果 55 | * 56 | * 终端测试命令: 57 | * @code 58 | * echo -n "string" | openssl sha -sha256 59 | * @endcode 60 | * 61 | * @return 64个字符的SHA256散列字符串 62 | */ 63 | - (instancetype)hd_sha256String; 64 | 65 | /** 66 | * 计算SHA 384散列结果 67 | * 68 | * 终端测试命令: 69 | * @code 70 | * echo -n "string" | openssl sha -sha384 71 | * @endcode 72 | * 73 | * @return 96个字符的SHA 384散列字符串 74 | */ 75 | - (instancetype)hd_sha384String; 76 | 77 | /** 78 | * 计算SHA 512散列结果 79 | * 80 | * 终端测试命令: 81 | * @code 82 | * echo -n "string" | openssl sha -sha512 83 | * @endcode 84 | * 85 | * @return 128个字符的SHA 512散列字符串 86 | */ 87 | - (instancetype)hd_sha512String; 88 | 89 | #pragma mark - HMAC 散列函数 90 | /** 91 | * 计算HMAC MD5散列结果 92 | * 93 | * 终端测试命令: 94 | * @code 95 | * echo -n "string" | openssl dgst -md5 -hmac "key" 96 | * @endcode 97 | * 98 | * @return 32个字符的HMAC MD5散列字符串 99 | */ 100 | - (instancetype)hd_hmacMD5StringWithKey:(NSString *)key; 101 | 102 | /** 103 | * 计算HMAC SHA1散列结果 104 | * 105 | * 终端测试命令: 106 | * @code 107 | * echo -n "string" | openssl sha -sha1 -hmac "key" 108 | * @endcode 109 | * 110 | * @return 40个字符的HMAC SHA1散列字符串 111 | */ 112 | - (instancetype)hd_hmacSHA1StringWithKey:(NSString *)key; 113 | 114 | /** 115 | * 计算HMAC SHA256散列结果 116 | * 117 | * 终端测试命令: 118 | * @code 119 | * echo -n "string" | openssl sha -sha256 -hmac "key" 120 | * @endcode 121 | * 122 | * @return 64个字符的HMAC SHA256散列字符串 123 | */ 124 | - (instancetype)hd_hmacSHA256StringWithKey:(NSString *)key; 125 | 126 | /** 127 | * 计算HMAC SHA512散列结果 128 | * 129 | * 终端测试命令: 130 | * @code 131 | * echo -n "string" | openssl sha -sha512 -hmac "key" 132 | * @endcode 133 | * 134 | * @return 128个字符的HMAC SHA512散列字符串 135 | */ 136 | - (instancetype)hd_hmacSHA512StringWithKey:(NSString *)key; 137 | 138 | #pragma mark - 文件散列函数 139 | /** 140 | * 计算文件的MD5散列结果 141 | * 142 | * 终端测试命令: 143 | * @code 144 | * md5 file.dat 145 | * @endcode 146 | * 147 | * @return 32个字符的MD5散列字符串 148 | */ 149 | - (instancetype)hd_fileMD5Hash; 150 | 151 | /** 152 | * 计算文件的SHA1散列结果 153 | * 154 | * 终端测试命令: 155 | * @code 156 | * openssl sha -sha1 file.dat 157 | * @endcode 158 | * 159 | * @return 40个字符的SHA1散列字符串 160 | */ 161 | - (instancetype)hd_fileSHA1Hash; 162 | 163 | /** 164 | * 计算文件的SHA256散列结果 165 | * 166 | * 终端测试命令: 167 | * @code 168 | * openssl sha -sha256 file.dat 169 | * @endcode 170 | * 171 | * @return 64个字符的SHA256散列字符串 172 | */ 173 | - (instancetype)hd_fileSHA256Hash; 174 | 175 | /** 176 | * 计算文件的SHA512散列结果 177 | * 178 | * 终端测试命令: 179 | * @code 180 | * openssl sha -sha512 file.dat 181 | * @endcode 182 | * 183 | * @return 128个字符的SHA512散列字符串 184 | */ 185 | - (instancetype)hd_fileSHA512Hash; 186 | 187 | #pragma mark - Base64编码 188 | /** 189 | * 返回Base64遍码后的字符串 190 | */ 191 | - (instancetype)hd_base64Encode; 192 | 193 | /** 194 | * 返回Base64解码后的字符串 195 | */ 196 | - (instancetype)hd_base64Decode; 197 | 198 | #pragma mark - 路径方法 199 | /** 200 | * 快速返回沙盒中,Documents文件的路径 201 | * 202 | * @return Documents文件的路径 203 | */ 204 | + (instancetype)hd_pathForDocuments; 205 | 206 | /** 207 | * 快速返回沙盒中,Documents文件中某个子文件的路径 208 | * 209 | * @param fileName 子文件名称 210 | * 211 | * @return 快速返回Documents文件中某个子文件的路径 212 | */ 213 | + (instancetype)hd_filePathAtDocumentsWithFileName:(NSString *)fileName; 214 | 215 | /** 216 | * 快速返回沙盒中,Library下Caches文件的路径 217 | * 218 | * @return 快速返回沙盒中Library下Caches文件的路径 219 | */ 220 | + (instancetype)hd_pathForCaches; 221 | 222 | /** 223 | * 快速返回沙盒中,Library下Caches文件中某个子文件的路径 224 | * 225 | * @param fileName 子文件名称 226 | * 227 | * @return 快速返回Caches文件中某个子文件的路径 228 | */ 229 | + (instancetype)hd_filePathAtCachesWithFileName:(NSString *)fileName; 230 | 231 | /** 232 | * 快速返回沙盒中,MainBundle(资源捆绑包的)的路径 233 | * 234 | * @return 快速返回MainBundle(资源捆绑包的)的路径 235 | */ 236 | + (instancetype)hd_pathForMainBundle; 237 | 238 | /** 239 | * 快速返回沙盒中,MainBundle(资源捆绑包的)中某个子文件的路径 240 | * 241 | * @param fileName 子文件名称 242 | * 243 | * @return 快速返回MainBundle(资源捆绑包的)中某个子文件的路径 244 | */ 245 | + (instancetype)hd_filePathAtMainBundleWithFileName:(NSString *)fileName; 246 | 247 | /** 248 | * 快速返回沙盒中,tmp(临时文件)文件的路径 249 | * 250 | * @return 快速返回沙盒中tmp文件的路径 251 | */ 252 | + (instancetype)hd_pathForTemp; 253 | 254 | /** 255 | * 快速返回沙盒中,temp文件中某个子文件的路径 256 | * 257 | * @param fileName 子文件名 258 | * 259 | * @return 快速返回temp文件中某个子文件的路径 260 | */ 261 | + (instancetype)hd_filePathAtTempWithFileName:(NSString *)fileName; 262 | 263 | /** 264 | * 快速返回沙盒中,Library下Preferences文件的路径 265 | * 266 | * @return 快速返回沙盒中Library下Caches文件的路径 267 | */ 268 | + (instancetype)hd_pathForPreferences; 269 | 270 | /** 271 | * 快速返回沙盒中,Library下Preferences文件中某个子文件的路径 272 | * 273 | * @param fileName 子文件名称 274 | * 275 | * @return 快速返回Preferences文件中某个子文件的路径 276 | */ 277 | + (instancetype)hd_filePathAtPreferencesWithFileName:(NSString *)fileName; 278 | 279 | /** 280 | * 快速返回沙盒中,你指定的系统文件的路径。tmp文件除外,tmp用系统的NSTemporaryDirectory()函数更加便捷 281 | * 282 | * @param directory NSSearchPathDirectory枚举 283 | * 284 | * @return 快速你指定的系统文件的路径 285 | */ 286 | + (instancetype)hd_pathForSystemFile:(NSSearchPathDirectory)directory; 287 | 288 | /** 289 | * 快速返回沙盒中,你指定的系统文件的中某个子文件的路径。tmp文件除外,请使用filePathAtTempWithFileName 290 | * 291 | * @param directory 你指的的系统文件 292 | * @param fileName 子文件名 293 | * 294 | * @return 快速返回沙盒中,你指定的系统文件的中某个子文件的路径 295 | */ 296 | + (instancetype)hd_filePathForSystemFile:(NSSearchPathDirectory)directory withFileName:(NSString *)fileName; 297 | 298 | #pragma mark - 文本计算方法 299 | /** 300 | * 计算文字大小 301 | * 302 | * @param font 字体 303 | * @param size 计算范围的大小 304 | * @param mode 段落样式 305 | * 306 | * @return 计算出来的大小 307 | */ 308 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode; 309 | 310 | /** 311 | 计算字符串高度 312 | 313 | @param font 字体 314 | @param size 限制大小 315 | @param mode 计算的换行模型 316 | @param numberOfLine 限制计算高度的行数 317 | @return 返回计算大小 318 | */ 319 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode numberOfLine:(NSInteger)numberOfLine; 320 | 321 | /** 322 | * 计算文字大小 323 | * 324 | * @param font 字体 325 | * @param size 计算范围的大小 326 | * 327 | * @return 计算出来的大小 328 | */ 329 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size; 330 | 331 | /** 332 | * 计算文字大小 333 | * 334 | * @param text 文字 335 | * @param font 字体 336 | * @param size 计算范围的大小 337 | * 338 | * @return 计算出来的大小 339 | */ 340 | + (CGSize)hd_sizeWithText:(NSString *)text systemFont:(UIFont *)font constrainedToSize:(CGSize)size; 341 | 342 | /** 343 | 计算粗体文字大小 344 | 345 | @param font 字体 346 | @param size 计算范围的大小 347 | @param mode 计算的换行模型 348 | @return 计算出来的大小 349 | */ 350 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode; 351 | 352 | /** 353 | 计算粗体文字大小 354 | 355 | @param font 字体 356 | @param size 计算范围的大小 357 | @return 计算出来的大小 358 | */ 359 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size; 360 | 361 | /** 362 | 计算粗体文字大小 363 | 364 | @param font 字体 365 | @param size 计算范围的大小 366 | @param mode 计算的换行模型 367 | @param numberOfLine 限制计算高度的行数 368 | @return 计算出来的大小 369 | */ 370 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode numberOfLine:(NSInteger)numberOfLine; 371 | 372 | 373 | #pragma mark - 富文本相关 374 | /** 375 | 转变成富文本 376 | 377 | @param lineSpacing 行间距 378 | @param kern 文字间的间距 379 | @param lineBreakMode 换行方式 380 | @param alignment 文字对齐格式 381 | @return 转变后的富文本 382 | */ 383 | - (NSAttributedString *)hd_conversionToAttributedStringWithLineSpeace:(CGFloat)lineSpacing kern:(CGFloat)kern lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment; 384 | 385 | /** 386 | 计算富文本字体大小 387 | 388 | @param lineSpeace 行间距 389 | @param kern 文字间的间距 390 | @param font 字体 391 | @param size 计算范围 392 | @param lineBreakMode 换行方式 393 | @param alignment 文字对齐格式 394 | @return 计算后的字体大小 395 | */ 396 | - (CGSize)hd_sizeWithAttributedStringLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment; 397 | 398 | /** 399 | 计算富文本字体大小 400 | 401 | @param lineSpeace 行间距 402 | @param kern 文字间的间距 403 | @param font 字体 404 | @param size 计算范围 405 | @param lineBreakMode 换行方式 406 | @param alignment 文字对齐格式 407 | @param numberOfLine 限制计算行数 408 | @return 计算后的字体大小 409 | */ 410 | - (CGSize)hd_sizeWithAttributedStringLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment numberOfLine:(NSInteger)numberOfLine; 411 | 412 | /** 413 | 是否是一行高度 414 | 415 | @param lineSpeace 行间距 416 | @param kern 文字间的间距 417 | @param font 字体 418 | @param size 计算范围 419 | @param lineBreakMode 换行方式 420 | @param alignment 文字对齐格式 421 | @return 返回YES代表1行, NO代表多行 422 | */ 423 | - (BOOL)hd_numberOfLineWithLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment; 424 | 425 | #pragma mark - 设备相关 426 | /** 427 | * 设备版本 428 | */ 429 | + (instancetype)hd_deviceVersion; 430 | 431 | /** 432 | * 设备类型(用于区分iPhone屏幕大小) 433 | */ 434 | HD_EXTERN NSString *const iPhone6_6s_7_8; 435 | HD_EXTERN NSString *const iPhone6_6s_7_8Plus; 436 | HD_EXTERN NSString *const iPhone_X; 437 | + (instancetype)hd_deviceType; 438 | 439 | 440 | #pragma mark - 效验相关 441 | /** 442 | * 判断是否是邮箱 443 | */ 444 | - (BOOL)hd_isValidEmail; 445 | 446 | /** 447 | * 判断是否是中文 448 | */ 449 | - (BOOL)hd_isChinese; 450 | 451 | /** 452 | * 判断是不是url地址 453 | */ 454 | - (BOOL)hd_isValidUrl; 455 | 456 | /** 457 | * 验证是否是手机号 458 | */ 459 | - (BOOL)hd_isValidateMobile; 460 | 461 | 462 | #pragma mark - 限制相关 463 | /** 464 | 限制字符串长度 465 | 466 | @param length 限制的长度 467 | */ 468 | - (instancetype)hd_limitLength:(NSInteger)length; 469 | 470 | /** 471 | 字符串长度 472 | 473 | @return 返回字符串长度 474 | */ 475 | - (NSUInteger)hd_length; 476 | 477 | /** 478 | 字符串截串 479 | 480 | @param maxLength 最大长度 481 | @return 返回截取到最大长度的字符串 482 | */ 483 | - (instancetype)hd_substringMaxLength:(NSUInteger)maxLength; 484 | 485 | @end 486 | -------------------------------------------------------------------------------- /HDAlertView/NSString+HDExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+HDExtension.m 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/5/10. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | #import "NSString+HDExtension.h" 10 | #import "sys/utsname.h" 11 | #import 12 | 13 | @implementation NSString (HDExtension) 14 | 15 | 16 | #pragma mark - 散列函数 17 | - (instancetype)hd_md5String { 18 | const char *str = self.UTF8String; 19 | uint8_t buffer[CC_MD5_DIGEST_LENGTH]; 20 | 21 | CC_MD5(str, (CC_LONG)strlen(str), buffer); 22 | 23 | return [self hd_stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; 24 | } 25 | 26 | - (instancetype)hd_sha1String { 27 | const char *str = self.UTF8String; 28 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; 29 | 30 | CC_SHA1(str, (CC_LONG)strlen(str), buffer); 31 | 32 | return [self hd_stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; 33 | } 34 | 35 | - (instancetype)hd_sha224String { 36 | const char *str = self.UTF8String; 37 | uint8_t buffer[CC_SHA224_DIGEST_LENGTH]; 38 | 39 | CC_SHA224(str, (CC_LONG)strlen(str), buffer); 40 | 41 | return [self hd_stringFromBytes:buffer length:CC_SHA224_DIGEST_LENGTH]; 42 | } 43 | 44 | - (instancetype)hd_sha256String { 45 | const char *str = self.UTF8String; 46 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; 47 | 48 | CC_SHA256(str, (CC_LONG)strlen(str), buffer); 49 | 50 | return [self hd_stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; 51 | } 52 | 53 | - (instancetype)hd_sha384String { 54 | const char *str = self.UTF8String; 55 | uint8_t buffer[CC_SHA384_DIGEST_LENGTH]; 56 | 57 | CC_SHA384(str, (CC_LONG)strlen(str), buffer); 58 | 59 | return [self hd_stringFromBytes:buffer length:CC_SHA384_DIGEST_LENGTH]; 60 | } 61 | 62 | - (instancetype)hd_sha512String { 63 | const char *str = self.UTF8String; 64 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; 65 | 66 | CC_SHA512(str, (CC_LONG)strlen(str), buffer); 67 | 68 | return [self hd_stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; 69 | } 70 | 71 | 72 | #pragma mark - HMAC 散列函数 73 | - (instancetype)hd_hmacMD5StringWithKey:(NSString *)key { 74 | const char *keyData = key.UTF8String; 75 | const char *strData = self.UTF8String; 76 | uint8_t buffer[CC_MD5_DIGEST_LENGTH]; 77 | 78 | CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer); 79 | 80 | return [self hd_stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; 81 | } 82 | 83 | - (instancetype)hd_hmacSHA1StringWithKey:(NSString *)key { 84 | const char *keyData = key.UTF8String; 85 | const char *strData = self.UTF8String; 86 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; 87 | 88 | CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer); 89 | 90 | return [self hd_stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; 91 | } 92 | 93 | - (instancetype)hd_hmacSHA256StringWithKey:(NSString *)key { 94 | const char *keyData = key.UTF8String; 95 | const char *strData = self.UTF8String; 96 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; 97 | 98 | CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer); 99 | 100 | return [self hd_stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; 101 | } 102 | 103 | - (instancetype)hd_hmacSHA512StringWithKey:(NSString *)key { 104 | const char *keyData = key.UTF8String; 105 | const char *strData = self.UTF8String; 106 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; 107 | 108 | CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer); 109 | 110 | return [self hd_stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; 111 | } 112 | 113 | 114 | #pragma mark - 文件散列函数 115 | #define FileHashDefaultChunkSizeForReadingData 4096 116 | - (instancetype)hd_fileMD5Hash { 117 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; 118 | if (fp == nil) return nil; 119 | 120 | CC_MD5_CTX hashCtx; 121 | CC_MD5_Init(&hashCtx); 122 | 123 | while (YES) { 124 | @autoreleasepool { 125 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; 126 | 127 | CC_MD5_Update(&hashCtx, data.bytes, (CC_LONG)data.length); 128 | 129 | if (data.length == 0) break; 130 | } 131 | } 132 | [fp closeFile]; 133 | 134 | uint8_t buffer[CC_MD5_DIGEST_LENGTH]; 135 | CC_MD5_Final(buffer, &hashCtx); 136 | 137 | return [self hd_stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; 138 | } 139 | 140 | - (instancetype)hd_fileSHA1Hash { 141 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; 142 | if (fp == nil) return nil; 143 | 144 | CC_SHA1_CTX hashCtx; 145 | CC_SHA1_Init(&hashCtx); 146 | 147 | while (YES) { 148 | @autoreleasepool { 149 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; 150 | 151 | CC_SHA1_Update(&hashCtx, data.bytes, (CC_LONG)data.length); 152 | 153 | if (data.length == 0) break; 154 | } 155 | } 156 | [fp closeFile]; 157 | 158 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; 159 | CC_SHA1_Final(buffer, &hashCtx); 160 | 161 | return [self hd_stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; 162 | } 163 | 164 | - (instancetype)hd_fileSHA256Hash { 165 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; 166 | if (fp == nil) return nil; 167 | 168 | CC_SHA256_CTX hashCtx; 169 | CC_SHA256_Init(&hashCtx); 170 | 171 | while (YES) { 172 | @autoreleasepool { 173 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; 174 | 175 | CC_SHA256_Update(&hashCtx, data.bytes, (CC_LONG)data.length); 176 | 177 | if (data.length == 0) break; 178 | } 179 | } 180 | [fp closeFile]; 181 | 182 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; 183 | CC_SHA256_Final(buffer, &hashCtx); 184 | 185 | return [self hd_stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; 186 | } 187 | 188 | - (instancetype)hd_fileSHA512Hash { 189 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; 190 | if (fp == nil) return nil; 191 | 192 | CC_SHA512_CTX hashCtx; 193 | CC_SHA512_Init(&hashCtx); 194 | 195 | while (YES) { 196 | @autoreleasepool { 197 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; 198 | 199 | CC_SHA512_Update(&hashCtx, data.bytes, (CC_LONG)data.length); 200 | 201 | if (data.length == 0) break; 202 | } 203 | } 204 | [fp closeFile]; 205 | 206 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; 207 | CC_SHA512_Final(buffer, &hashCtx); 208 | 209 | return [self hd_stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; 210 | } 211 | 212 | 213 | #pragma mark - Base64编码 214 | - (instancetype)hd_base64Encode { 215 | NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; 216 | 217 | return [data base64EncodedStringWithOptions:0]; 218 | } 219 | 220 | - (instancetype)hd_base64Decode { 221 | NSData *data = [[NSData alloc] initWithBase64EncodedString:self options:0]; 222 | 223 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 224 | } 225 | 226 | 227 | #pragma mark - 路径方法 228 | + (instancetype)hd_pathForDocuments { 229 | return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 230 | } 231 | 232 | + (instancetype)hd_filePathAtDocumentsWithFileName:(NSString *)fileName { 233 | return [[self hd_pathForDocuments] stringByAppendingPathComponent:fileName]; 234 | } 235 | 236 | + (instancetype)hd_pathForCaches { 237 | return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 238 | } 239 | 240 | + (instancetype)hd_filePathAtCachesWithFileName:(NSString *)fileName { 241 | return [[self hd_pathForCaches] stringByAppendingPathComponent:fileName]; 242 | } 243 | 244 | + (instancetype)hd_pathForMainBundle { 245 | return [NSBundle mainBundle].bundlePath; 246 | } 247 | 248 | + (instancetype)hd_filePathAtMainBundleWithFileName:(NSString *)fileName { 249 | return [[self hd_pathForMainBundle] stringByAppendingPathComponent:fileName]; 250 | } 251 | 252 | + (instancetype)hd_pathForTemp { 253 | return NSTemporaryDirectory(); 254 | } 255 | 256 | + (instancetype)hd_filePathAtTempWithFileName:(NSString *)fileName { 257 | return [[self hd_pathForTemp] stringByAppendingPathComponent:fileName]; 258 | } 259 | 260 | + (instancetype)hd_pathForPreferences { 261 | return [NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES) lastObject]; 262 | } 263 | 264 | + (instancetype)hd_filePathAtPreferencesWithFileName:(NSString *)fileName { 265 | return [[self hd_pathForPreferences] stringByAppendingPathComponent:fileName]; 266 | } 267 | 268 | + (instancetype)hd_pathForSystemFile:(NSSearchPathDirectory)directory { 269 | return [NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES) lastObject]; 270 | } 271 | 272 | + (instancetype)hd_filePathForSystemFile:(NSSearchPathDirectory)directory withFileName:(NSString *)fileName { 273 | return [[self hd_pathForSystemFile:directory] stringByAppendingPathComponent:fileName]; 274 | } 275 | 276 | 277 | #pragma mark - 文本计算方法 278 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode { 279 | NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; 280 | paragraphStyle.lineBreakMode = mode; 281 | paragraphStyle.alignment = NSTextAlignmentLeft; 282 | 283 | NSDictionary *attributes = @{NSFontAttributeName : font, 284 | NSParagraphStyleAttributeName : paragraphStyle}; 285 | CGRect rect = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil]; 286 | return CGSizeMake(ceil(rect.size.width), ceil(rect.size.height)); 287 | } 288 | 289 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode numberOfLine:(NSInteger)numberOfLine { 290 | CGSize maxSize = [self hd_sizeWithSystemFont:font constrainedToSize:size lineBreakMode:mode]; 291 | CGFloat oneLineHeight = [self hd_sizeWithSystemFont:font constrainedToSize:CGSizeMake(size.width, font.lineHeight) lineBreakMode:NSLineBreakByTruncatingTail].height; 292 | CGFloat height = 0; 293 | CGFloat limitHeight = oneLineHeight * numberOfLine; 294 | 295 | if (maxSize.height > limitHeight) { 296 | height = limitHeight; 297 | } else { 298 | height = maxSize.height; 299 | } 300 | 301 | return CGSizeMake(maxSize.width, height); 302 | } 303 | 304 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size { 305 | return [self hd_sizeWithSystemFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping]; 306 | } 307 | 308 | + (CGSize)hd_sizeWithText:(NSString *)text systemFont:(UIFont *)font constrainedToSize:(CGSize)size { 309 | return [text hd_sizeWithSystemFont:font constrainedToSize:size]; 310 | } 311 | 312 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode { 313 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 314 | paragraphStyle.lineBreakMode = mode; 315 | paragraphStyle.alignment = NSTextAlignmentLeft; 316 | NSDictionary *attributes = @{NSFontAttributeName: font, 317 | NSParagraphStyleAttributeName: paragraphStyle}; 318 | 319 | CGRect rect = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil]; 320 | return CGSizeMake(ceil(rect.size.width), ceil(rect.size.height)); 321 | } 322 | 323 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size { 324 | return [self hd_sizeWithBoldFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping]; 325 | } 326 | 327 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode numberOfLine:(NSInteger)numberOfLine { 328 | CGSize maxSize = [self hd_sizeWithBoldFont:font constrainedToSize:size lineBreakMode:mode]; 329 | CGFloat oneLineHeight = [self hd_sizeWithBoldFont:font constrainedToSize:CGSizeMake(size.width, font.lineHeight) lineBreakMode:NSLineBreakByTruncatingTail].height; 330 | CGFloat height = 0; 331 | CGFloat limitHeight = oneLineHeight * numberOfLine; 332 | 333 | if (maxSize.height > limitHeight) { 334 | height = limitHeight; 335 | } else { 336 | height = maxSize.height; 337 | } 338 | 339 | return CGSizeMake(maxSize.width, height); 340 | } 341 | 342 | 343 | #pragma mark - 富文本相关 344 | - (NSAttributedString *)hd_conversionToAttributedStringWithLineSpeace:(CGFloat)lineSpacing kern:(CGFloat)kern lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment { 345 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 346 | paragraphStyle.lineSpacing = lineSpacing; 347 | paragraphStyle.lineBreakMode = lineBreakMode; 348 | paragraphStyle.alignment = alignment; 349 | 350 | NSDictionary *attributes = @{NSParagraphStyleAttributeName:paragraphStyle, 351 | NSKernAttributeName:@(kern)}; 352 | 353 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self attributes:attributes]; 354 | 355 | return attributedString; 356 | } 357 | 358 | - (CGSize)hd_sizeWithAttributedStringLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment { 359 | if (font == nil) { 360 | HDAssert(!HDObjectIsEmpty(font), @"font不能为空"); 361 | return CGSizeMake(0, 0); 362 | } 363 | 364 | NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init]; 365 | paraStyle.lineSpacing = lineSpeace; 366 | paraStyle.lineBreakMode = lineBreakMode; 367 | paraStyle.alignment = alignment; 368 | 369 | NSDictionary *dic = @{NSFontAttributeName:font, 370 | NSParagraphStyleAttributeName:paraStyle, 371 | NSKernAttributeName:@(kern)}; 372 | CGRect rect = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil]; 373 | return CGSizeMake(ceil(rect.size.width), ceil(rect.size.height)); 374 | } 375 | 376 | - (CGSize)hd_sizeWithAttributedStringLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment numberOfLine:(NSInteger)numberOfLine { 377 | CGSize maxSize = [self hd_sizeWithAttributedStringLineSpeace:lineSpeace kern:kern font:font size:size lineBreakMode:lineBreakMode alignment:alignment]; 378 | CGFloat oneLineHeight = [self hd_sizeWithAttributedStringLineSpeace:lineSpeace kern:kern font:font size:CGSizeMake(size.width, font.lineHeight) lineBreakMode:NSLineBreakByTruncatingTail alignment:alignment].height; 379 | CGFloat height = 0; 380 | CGFloat limitHeight = oneLineHeight * numberOfLine; 381 | 382 | if (maxSize.height > limitHeight) { 383 | height = limitHeight; 384 | } else { 385 | height = maxSize.height; 386 | } 387 | 388 | return CGSizeMake(maxSize.width, height); 389 | } 390 | 391 | - (BOOL)hd_numberOfLineWithLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment { 392 | CGFloat oneHeight = [self hd_sizeWithAttributedStringLineSpeace:lineSpeace kern:kern font:font size:CGSizeMake(size.width, font.lineHeight) lineBreakMode:NSLineBreakByTruncatingTail alignment:alignment].height; 393 | CGFloat maxHeight = [self hd_sizeWithAttributedStringLineSpeace:lineSpeace kern:kern font:font size:size lineBreakMode:lineBreakMode alignment:alignment].height; 394 | 395 | if (maxHeight > oneHeight) { 396 | return NO; 397 | } 398 | 399 | return YES; 400 | } 401 | 402 | 403 | #pragma mark - 设备相关 404 | /** 405 | * 设备版本 406 | */ 407 | + (instancetype)hd_deviceVersion { 408 | // 需要#import "sys/utsname.h" 409 | struct utsname systemInfo; 410 | uname(&systemInfo); 411 | NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; 412 | 413 | // iPhone 414 | if ([deviceString isEqualToString:@"iPhone1,1"]) return @"iPhone 1G"; 415 | if ([deviceString isEqualToString:@"iPhone1,2"]) return @"iPhone 3G"; 416 | if ([deviceString isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS"; 417 | if ([deviceString isEqualToString:@"iPhone3,1"]) return @"iPhone 4"; 418 | if ([deviceString isEqualToString:@"iPhone3,2"]) return @"Verizon iPhone 4"; 419 | if ([deviceString isEqualToString:@"iPhone4,1"]) return @"iPhone 4S"; 420 | if ([deviceString isEqualToString:@"iPhone5,1"]) return @"iPhone 5"; 421 | if ([deviceString isEqualToString:@"iPhone5,2"]) return @"iPhone 5"; 422 | if ([deviceString isEqualToString:@"iPhone5,3"]) return @"iPhone 5C"; 423 | if ([deviceString isEqualToString:@"iPhone5,4"]) return @"iPhone 5C"; 424 | if ([deviceString isEqualToString:@"iPhone6,1"]) return @"iPhone 5S"; 425 | if ([deviceString isEqualToString:@"iPhone6,2"]) return @"iPhone 5S"; 426 | if ([deviceString isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus"; 427 | if ([deviceString isEqualToString:@"iPhone7,2"]) return @"iPhone 6"; 428 | if ([deviceString isEqualToString:@"iPhone8,1"]) return @"iPhone 6s"; 429 | if ([deviceString isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus"; 430 | if ([deviceString isEqualToString:@"iPhone9,1"]) return @"iPhone 7"; 431 | if ([deviceString isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus"; 432 | if ([deviceString isEqualToString:@"iPhone9,3"]) return @"iPhone 7"; 433 | if ([deviceString isEqualToString:@"iPhone9,4"]) return @"iPhone 7 Plus"; 434 | 435 | // iPod 436 | if ([deviceString isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G"; 437 | if ([deviceString isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G"; 438 | if ([deviceString isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G"; 439 | if ([deviceString isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G"; 440 | if ([deviceString isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G"; 441 | 442 | // iPad 443 | if ([deviceString isEqualToString:@"iPad1,1"]) return @"iPad"; 444 | if ([deviceString isEqualToString:@"iPad2,1"]) return @"iPad 2 (WiFi)"; 445 | if ([deviceString isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)"; 446 | if ([deviceString isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)"; 447 | if ([deviceString isEqualToString:@"iPad2,4"]) return @"iPad 2 (32nm)"; 448 | if ([deviceString isEqualToString:@"iPad2,5"]) return @"iPad mini (WiFi)"; 449 | if ([deviceString isEqualToString:@"iPad2,6"]) return @"iPad mini (GSM)"; 450 | if ([deviceString isEqualToString:@"iPad2,7"]) return @"iPad mini (CDMA)"; 451 | 452 | if ([deviceString isEqualToString:@"iPad3,1"]) return @"iPad 3(WiFi)"; 453 | if ([deviceString isEqualToString:@"iPad3,2"]) return @"iPad 3(CDMA)"; 454 | if ([deviceString isEqualToString:@"iPad3,3"]) return @"iPad 3(4G)"; 455 | if ([deviceString isEqualToString:@"iPad3,4"]) return @"iPad 4 (WiFi)"; 456 | if ([deviceString isEqualToString:@"iPad3,5"]) return @"iPad 4 (4G)"; 457 | if ([deviceString isEqualToString:@"iPad3,6"]) return @"iPad 4 (CDMA)"; 458 | 459 | if ([deviceString isEqualToString:@"iPad4,1"]) return @"iPad Air"; 460 | if ([deviceString isEqualToString:@"iPad4,2"]) return @"iPad Air"; 461 | if ([deviceString isEqualToString:@"iPad4,3"]) return @"iPad Air"; 462 | if ([deviceString isEqualToString:@"iPad5,3"]) return @"iPad Air 2"; 463 | if ([deviceString isEqualToString:@"iPad5,4"]) return @"iPad Air 2"; 464 | if ([deviceString isEqualToString:@"i386"]) return @"Simulator"; 465 | if ([deviceString isEqualToString:@"x86_64"]) return @"Simulator"; 466 | 467 | if ([deviceString isEqualToString:@"iPad4,4"] 468 | ||[deviceString isEqualToString:@"iPad4,5"] 469 | ||[deviceString isEqualToString:@"iPad4,6"]) return @"iPad mini 2"; 470 | 471 | if ([deviceString isEqualToString:@"iPad4,7"] 472 | ||[deviceString isEqualToString:@"iPad4,8"] 473 | ||[deviceString isEqualToString:@"iPad4,9"]) return @"iPad mini 3"; 474 | 475 | return deviceString; 476 | } 477 | 478 | 479 | NSString *const iPhone6_6s_7_8 = @"iPhone6_6s_7_8"; 480 | NSString *const iPhone6_6s_7_8Plus = @"iPhone6_6s_7_8Plus"; 481 | NSString *const iPhone_X = @"iPhone_X"; 482 | 483 | + (instancetype)hd_deviceType { 484 | struct utsname systemInfo; 485 | uname(&systemInfo); 486 | NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; 487 | 488 | // iPhone 489 | if ([deviceString isEqualToString:@"iPhone7,1"]) return iPhone6_6s_7_8Plus; 490 | if ([deviceString isEqualToString:@"iPhone7,2"]) return iPhone6_6s_7_8; 491 | if ([deviceString isEqualToString:@"iPhone8,1"]) return iPhone6_6s_7_8; 492 | if ([deviceString isEqualToString:@"iPhone8,2"]) return iPhone6_6s_7_8Plus; 493 | if ([deviceString isEqualToString:@"iPhone9,1"]) return iPhone6_6s_7_8; 494 | if ([deviceString isEqualToString:@"iPhone9,2"]) return iPhone6_6s_7_8Plus; 495 | if ([deviceString isEqualToString:@"iPhone9,3"]) return iPhone6_6s_7_8; 496 | if ([deviceString isEqualToString:@"iPhone9,4"]) return iPhone6_6s_7_8Plus; 497 | if ([deviceString isEqualToString:@"iPhone10,1"]) return iPhone6_6s_7_8; 498 | if ([deviceString isEqualToString:@"iPhone10,4"]) return iPhone6_6s_7_8; 499 | if ([deviceString isEqualToString:@"iPhone10,2"]) return iPhone6_6s_7_8Plus; 500 | if ([deviceString isEqualToString:@"iPhone10,5"]) return iPhone6_6s_7_8Plus; 501 | if ([deviceString isEqualToString:@"iPhone10,3"]) return iPhone_X; 502 | if ([deviceString isEqualToString:@"iPhone10,6"]) return iPhone_X; 503 | 504 | return deviceString; 505 | } 506 | 507 | 508 | #pragma mark - 效验相关 509 | - (BOOL)hd_isValidEmail { 510 | NSString *emailRegex = @"((?]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^;&*+?:_/=<>]*)?)"; 525 | NSPredicate *urlTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; 526 | return [urlTest evaluateWithObject:self]; 527 | } 528 | 529 | - (BOOL)hd_isValidateMobile { 530 | if (self.length < 1) { 531 | return NO; 532 | } 533 | 534 | return YES; // 现在新增手机号段很多_国际别的手机不一定11位_手机号其实没必要限制死! 535 | } 536 | 537 | 538 | #pragma mark - 限制相关 539 | - (instancetype)hd_limitLength:(NSInteger)length { 540 | NSString *str = self; 541 | if (str.length > length) { 542 | str = [str substringToIndex:length]; 543 | } 544 | 545 | return str; 546 | } 547 | 548 | - (NSUInteger)hd_length { 549 | float number = 0.0; 550 | 551 | for (int i = 0; i < self.length; i++) { 552 | NSString *character = [self substringWithRange:NSMakeRange(i, 1)]; 553 | 554 | if ([character lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 3) { 555 | number++; 556 | } else { 557 | number = number + 0.5; 558 | } 559 | } 560 | 561 | return ceil(number); 562 | } 563 | 564 | - (instancetype)hd_substringMaxLength:(NSUInteger)maxLength { 565 | NSMutableString *ret = [[NSMutableString alloc] init]; 566 | float number = 0.0; 567 | 568 | for (int i = 0; i < self.length; i++) { 569 | NSString *character = [self substringWithRange:NSMakeRange(i, 1)]; 570 | 571 | if ([character lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 3) { 572 | number++; 573 | } else { 574 | number = number + 0.5; 575 | } 576 | 577 | if (number <= maxLength) { 578 | [ret appendString:character]; 579 | } else { 580 | break; 581 | } 582 | } 583 | 584 | return [ret copy]; 585 | } 586 | 587 | 588 | #pragma mark - 其他 589 | /** 590 | * 返回二进制 Bytes 流的字符串表示形式 591 | * 592 | * @param bytes 二进制 Bytes 数组 593 | * @param length 数组长度 594 | * 595 | * @return 字符串表示形式 596 | */ 597 | - (instancetype)hd_stringFromBytes:(uint8_t *)bytes length:(int)length { 598 | NSMutableString *strM = [NSMutableString string]; 599 | 600 | for (int i = 0; i < length; i++) { 601 | [strM appendFormat:@"%02x", bytes[i]]; 602 | } 603 | 604 | return [strM copy]; 605 | } 606 | 607 | @end 608 | -------------------------------------------------------------------------------- /HDAlertView/UIImage+HDExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+HDExtension.h 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/1/17. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (HDExtension) 12 | 13 | /** 14 | * 拉伸图片 15 | * 16 | * @param name 图片名字 17 | * 18 | * @return 拉伸好的图片 19 | */ 20 | + (instancetype)hd_resizedImageWithImageName:(NSString *)name; 21 | 22 | /** 23 | * 拉伸图片 24 | * 25 | * @param image 要拉伸的图片 26 | * 27 | * @return 拉伸好的图片 28 | */ 29 | + (instancetype)hd_resizedImageWithImage:(UIImage *)image; 30 | 31 | /** 32 | * 返回一个缩放好的图片 33 | * 34 | * @param image 要切割的图片 35 | * @param imageSize 边框的宽度 36 | * 37 | * @return 切割好的图片 38 | */ 39 | + (instancetype)hd_cutImage:(UIImage*)image andSize:(CGSize)imageSize; 40 | 41 | /** 42 | * 返回一个下边有半个红圈的原型头像 43 | * 44 | * @param image 要切割的图片 45 | * 46 | * @return 切割好的头像 47 | */ 48 | + (instancetype)hd_captureCircleImage:(UIImage*)image; 49 | 50 | /** 51 | * 根据url返回一个圆形的头像 52 | * 53 | * @param iconUrl 头像的URL 54 | * @param border 边框的宽度 55 | * @param color 边框的颜色 56 | * 57 | * @return 切割好的头像 58 | */ 59 | + (instancetype)hd_captureCircleImageWithURL:(NSString *)iconUrl andBorderWith:(CGFloat)border andBorderColor:(UIColor *)color; 60 | 61 | /** 62 | * 根据iamge返回一个圆形的头像 63 | * 64 | * @param iconImage 要切割的头像 65 | * @param border 边框的宽度 66 | * @param color 边框的颜色 67 | * 68 | * @return 切割好的头像 69 | */ 70 | + (instancetype)hd_captureCircleImageWithImage:(UIImage *)iconImage andBorderWith:(CGFloat)border andBorderColor:(UIColor *)color; 71 | 72 | /** 73 | * 生成毛玻璃效果的图片 74 | * 75 | * @param image 要模糊化的图片 76 | * @param blurAmount 模糊化指数 77 | * 78 | * @return 返回模糊化之后的图片 79 | */ 80 | + (instancetype)hd_blurredImageWithImage:(UIImage *)image andBlurAmount:(CGFloat)blurAmount; 81 | 82 | /** 83 | * 截取对应的view生成一张图片 84 | * 85 | * @param view 要截的view 86 | * 87 | * @return 生成的图片 88 | */ 89 | + (instancetype)hd_viewShotWithView:(UIView *)view; 90 | 91 | /** 92 | * 截屏 93 | * 94 | * @return 返回截屏的图片 95 | */ 96 | + (instancetype)hd_screenShot; 97 | 98 | /** 99 | * 给图片添加水印 100 | * 101 | * @param bgName 原图的名字 102 | * @param waterImageName 水印的名字 103 | * 104 | * @return 添加完水印的图片 105 | */ 106 | + (instancetype)hd_waterImageWithBgImageName:(NSString *)bgName andWaterImageName:(NSString *)waterImageName ; 107 | 108 | /** 109 | * 图片进行压缩 110 | * 111 | * @param image 要压缩的图片 112 | * @param percent 要压缩的比例(建议在0.3以上) 113 | * 114 | * @return 压缩之后的图片 115 | * 116 | * @exception 压缩之后为image/jpeg 格式 117 | */ 118 | + (instancetype)hd_reduceImage:(UIImage *)image percent:(CGFloat)percent; 119 | 120 | /** 121 | * 对图片进行压缩 122 | * 123 | * @param image 要压缩的图片 124 | * @param newSize 压缩后的图片的像素尺寸 125 | * 126 | * @return 压缩好的图片 127 | */ 128 | + (instancetype)hd_imageWithImageSimple:(UIImage *)image scaledToSize:(CGSize)newSize; 129 | 130 | /** 131 | * 对图片进行压缩 132 | * 133 | * @param image 要压缩的图片 134 | * @param newSize 压缩后的图片的像素尺寸 135 | * 136 | * @return 压缩好的图片 137 | */ 138 | + (instancetype)hd_imageWithDataSimple:(NSData *)imageData scaledToSize:(CGSize)newSize; 139 | 140 | /** 141 | * 生成了一个毛玻璃效果的图片 142 | * 143 | * @return 返回模糊化好的图片 144 | */ 145 | - (instancetype)hd_blurredImage:(CGFloat)blurAmount; 146 | 147 | /** 148 | * 生成一个毛玻璃效果的图片 149 | * 150 | * @param blurLevel 毛玻璃的模糊程度 151 | * 152 | * @return 毛玻璃好的图片 153 | */ 154 | - (instancetype)hd_blearImageWithBlurLevel:(CGFloat)blurLevel; 155 | 156 | /** 157 | * 根据颜色返回图片 158 | * 159 | * @param color 颜色 160 | * 161 | * @return 图片 162 | */ 163 | + (instancetype)hd_imageWithColor:(UIColor *)color; 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /HDAlertView/UIImage+HDExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+HDExtension.m 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/1/17. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | #import "UIImage+HDExtension.h" 10 | #import 11 | #import 12 | 13 | @implementation UIImage (HDExtension) 14 | 15 | + (instancetype)hd_resizedImageWithImageName:(NSString *)name { 16 | return [self hd_resizedImageWithImage:[UIImage imageNamed:name]]; 17 | } 18 | 19 | + (instancetype)hd_resizedImageWithImage:(UIImage *)image { 20 | return [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5]; 21 | } 22 | 23 | + (instancetype)hd_cutImage:(UIImage*)image andSize:(CGSize)newImageSize { 24 | UIGraphicsBeginImageContextWithOptions(newImageSize, NO, 0.0); 25 | [image drawInRect:CGRectMake(0, 0, newImageSize.width, newImageSize.height)]; 26 | // 从上下文中取出图片 27 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 28 | UIGraphicsEndImageContext(); 29 | 30 | return newImage; 31 | } 32 | 33 | + (instancetype)hd_captureCircleImage:(UIImage *)image { 34 | CGFloat imageW = image.size.width; 35 | CGFloat imageH = image.size.height; 36 | imageW = MIN(imageH, imageW); 37 | imageH = imageW; 38 | 39 | CGFloat border = imageW / 100 * 2; 40 | CGSize imageSize = CGSizeMake(imageW, imageH); 41 | CGFloat radius = imageSize.width * 0.5; 42 | 43 | CGSize graphicSize = CGSizeMake(imageSize.width + 2 * border, imageSize.height + 2 * border); 44 | UIGraphicsBeginImageContextWithOptions(graphicSize, NO, 0.0); 45 | 46 | // 灰色边框 47 | [[UIColor darkGrayColor] setFill]; 48 | CGContextRef context=UIGraphicsGetCurrentContext(); 49 | CGContextAddArc(context,graphicSize.width * 0.5, graphicSize.height * 0.5, radius+border, -M_PI, M_PI, 0); 50 | CGContextFillPath(context); 51 | 52 | // 红色边框 53 | [[UIColor colorWithRed:247 / 255.0 green:98 / 255.0 blue:46 / 255.0 alpha:1.0] setFill]; 54 | CGContextAddArc(context, graphicSize.width * 0.5, graphicSize.height * 0.5, radius + border, -M_PI * 1.35, M_PI * 0.35, 1); 55 | CGContextFillPath(context); 56 | 57 | UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(graphicSize.width * 0.5, graphicSize.height * 0.5) radius:radius startAngle:-M_PI endAngle:M_PI clockwise:YES]; 58 | [path addClip]; 59 | 60 | CGRect imageFrame = CGRectMake(border, border, imageSize.width, imageSize.height); 61 | [image drawInRect:imageFrame]; 62 | UIImage *finishImage = UIGraphicsGetImageFromCurrentImageContext(); 63 | UIGraphicsEndImageContext(); 64 | 65 | return finishImage; 66 | } 67 | 68 | + (instancetype)hd_captureCircleImageWithURL:(NSString *)iconUrl andBorderWith:(CGFloat)border andBorderColor:(UIColor *)color { 69 | return [self hd_captureCircleImageWithImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:iconUrl]]] andBorderWith:border andBorderColor:color]; 70 | } 71 | 72 | + (instancetype)hd_captureCircleImageWithImage:(UIImage *)iconImage andBorderWith:(CGFloat)border andBorderColor:(UIColor *)color { 73 | CGFloat imageW = iconImage.size.width + border * 2; 74 | CGFloat imageH = iconImage.size.height + border * 2; 75 | imageW = MIN(imageH, imageW); 76 | imageH = imageW; 77 | CGSize imageSize = CGSizeMake(imageW, imageH); 78 | // 新建一个图形上下文 79 | UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0); 80 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 81 | [color set]; 82 | // 画大圆 83 | CGFloat bigRadius = imageW * 0.5; 84 | CGFloat centerX = imageW * 0.5; 85 | CGFloat centerY = imageH * 0.5; 86 | CGContextAddArc(ctx, centerX, centerY, bigRadius, 0, M_PI * 2, 0); 87 | CGContextFillPath(ctx); 88 | // 画小圆 89 | CGFloat smallRadius = bigRadius - border; 90 | CGContextAddArc(ctx , centerX , centerY , smallRadius ,0, M_PI * 2, 0); 91 | // 切割 92 | CGContextClip(ctx); 93 | // 画图片 94 | [iconImage drawInRect:CGRectMake(border, border, iconImage.size.width, iconImage.size.height)]; 95 | //从上下文中取出图片 96 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 97 | UIGraphicsEndImageContext(); 98 | 99 | return newImage; 100 | } 101 | 102 | + (instancetype)hd_blurredImageWithImage:(UIImage *)image andBlurAmount:(CGFloat)blurAmount { 103 | return [image hd_blurredImage:blurAmount]; 104 | } 105 | 106 | + (instancetype)hd_viewShotWithView:(UIView *)view { 107 | UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0); 108 | [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 109 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 110 | UIGraphicsEndImageContext(); 111 | 112 | return newImage; 113 | } 114 | 115 | + (instancetype)hd_screenShot { 116 | CGSize imageSize = [[UIScreen mainScreen] bounds].size; 117 | // 开启图形上下文 118 | UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); 119 | CGContextRef context = UIGraphicsGetCurrentContext(); 120 | for (UIWindow *window in [[UIApplication sharedApplication] windows]) { 121 | if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen]) { 122 | CGContextSaveGState(context); 123 | CGContextTranslateCTM(context, [window center].x, [window center].y); 124 | CGContextConcatCTM(context, [window transform]); 125 | CGContextTranslateCTM(context, 126 | -[window bounds].size.width * [[window layer] anchorPoint].x, 127 | -[window bounds].size.height * [[window layer] anchorPoint].y); 128 | [[window layer] renderInContext:context]; 129 | 130 | CGContextRestoreGState(context); 131 | } 132 | } 133 | 134 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 135 | UIGraphicsEndImageContext(); 136 | 137 | return image; 138 | } 139 | 140 | + (instancetype)hd_waterImageWithBgImageName:(NSString *)bgName andWaterImageName:(NSString *)waterImageName { 141 | UIImage *bgImage = [UIImage imageNamed:bgName]; 142 | CGSize imageViewSize = bgImage.size; 143 | 144 | UIGraphicsBeginImageContextWithOptions(imageViewSize, NO, 0.0); 145 | [bgImage drawInRect:CGRectMake(0, 0, imageViewSize.width, imageViewSize.height)]; 146 | 147 | UIImage *waterImage = [UIImage imageNamed:waterImageName]; 148 | CGFloat scale = 0.2; 149 | CGFloat margin = 5; 150 | CGFloat waterW = imageViewSize.width * scale; 151 | CGFloat waterH = imageViewSize.height * scale; 152 | CGFloat waterX = imageViewSize.width - waterW - margin; 153 | CGFloat waterY = imageViewSize.height - waterH - margin; 154 | 155 | [waterImage drawInRect:CGRectMake(waterX, waterY, waterW, waterH)]; 156 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 157 | UIGraphicsEndImageContext(); 158 | 159 | return newImage; 160 | } 161 | 162 | + (instancetype)hd_reduceImage:(UIImage *)image percent:(CGFloat)percent { 163 | NSData *imageData = UIImageJPEGRepresentation(image, percent); 164 | UIImage *newImage = [UIImage imageWithData:imageData]; 165 | 166 | return newImage; 167 | } 168 | 169 | + (instancetype)hd_imageWithImageSimple:(UIImage*)image scaledToSize:(CGSize)newSize { 170 | UIGraphicsBeginImageContext(newSize); 171 | [image drawInRect:CGRectMake(0, 0, newSize.width,newSize.height)]; 172 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 173 | UIGraphicsEndImageContext(); 174 | 175 | return newImage; 176 | } 177 | 178 | + (instancetype)hd_imageWithDataSimple:(NSData *)imageData scaledToSize:(CGSize)newSize { 179 | return [self hd_imageWithImageSimple:[UIImage imageWithData:imageData] scaledToSize:newSize]; 180 | } 181 | 182 | - (instancetype)hd_blurredImage:(CGFloat)blurAmount { 183 | if (blurAmount < 0.0 || blurAmount > 2.0) { 184 | blurAmount = 0.5; 185 | } 186 | 187 | CGImageRef img = self.CGImage; 188 | 189 | vImage_Buffer inBuffer, outBuffer; 190 | vImage_Error error; 191 | 192 | void *pixelBuffer; 193 | 194 | CGDataProviderRef inProvider = CGImageGetDataProvider(img); 195 | CFDataRef inBitmapData = CGDataProviderCopyData(inProvider); 196 | 197 | inBuffer.width = CGImageGetWidth(img); 198 | inBuffer.height = CGImageGetHeight(img); 199 | inBuffer.rowBytes = CGImageGetBytesPerRow(img); 200 | 201 | inBuffer.data = (void *)CFDataGetBytePtr(inBitmapData); 202 | 203 | pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img)); 204 | 205 | outBuffer.data = pixelBuffer; 206 | outBuffer.width = CGImageGetWidth(img); 207 | outBuffer.height = CGImageGetHeight(img); 208 | outBuffer.rowBytes = CGImageGetBytesPerRow(img); 209 | int boxSize = blurAmount * 40; 210 | boxSize = boxSize - (boxSize % 2) + 1; 211 | error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 212 | if (!error) 213 | { 214 | error = vImageBoxConvolve_ARGB8888(&outBuffer, &inBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 215 | } 216 | 217 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 218 | 219 | CGContextRef ctx = CGBitmapContextCreate(outBuffer.data, 220 | outBuffer.width, 221 | outBuffer.height, 222 | 8, 223 | outBuffer.rowBytes, 224 | colorSpace, 225 | (CGBitmapInfo)kCGImageAlphaNoneSkipLast); 226 | 227 | CGImageRef imageRef = CGBitmapContextCreateImage(ctx); 228 | 229 | UIImage *returnImage = [UIImage imageWithCGImage:imageRef]; 230 | 231 | CGContextRelease(ctx); 232 | CGColorSpaceRelease(colorSpace); 233 | 234 | free(pixelBuffer); 235 | CFRelease(inBitmapData); 236 | CGImageRelease(imageRef); 237 | 238 | return returnImage; 239 | } 240 | 241 | - (instancetype)hd_blearImageWithBlurLevel:(CGFloat)blurLevel { 242 | CIContext *context = [CIContext contextWithOptions:nil]; 243 | CIImage *inputImage = [[CIImage alloc] initWithImage:self]; 244 | CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; 245 | [blurFilter setDefaults]; 246 | [blurFilter setValue:inputImage forKey:@"inputImage"]; 247 | // 设值模糊的级别 248 | [blurFilter setValue:[NSNumber numberWithFloat:blurLevel] forKey:@"inputRadius"]; 249 | CIImage *outputImage = [blurFilter valueForKey:@"outputImage"]; 250 | CGRect rect = inputImage.extent; // Create Rect 251 | // 设值一下减到图片的白边 252 | rect.origin.x += blurLevel; 253 | rect.origin.y += blurLevel; 254 | rect.size.height -= blurLevel * 2.0f; 255 | rect.size.width -= blurLevel * 2.0f; 256 | CGImageRef cgImage = [context createCGImage:outputImage fromRect:rect]; 257 | // 获取新的图片 258 | UIImage *newImage = [UIImage imageWithCGImage:cgImage scale:0.5 orientation:self.imageOrientation]; 259 | // 释放图片 260 | CGImageRelease(cgImage); 261 | 262 | return newImage; 263 | } 264 | 265 | + (instancetype)hd_imageWithColor:(UIColor *)color { 266 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 267 | UIGraphicsBeginImageContext(rect.size); 268 | CGContextRef context = UIGraphicsGetCurrentContext(); 269 | CGContextSetFillColorWithColor(context, [color CGColor]); 270 | CGContextFillRect(context, rect); 271 | 272 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); 273 | UIGraphicsEndImageContext(); 274 | 275 | return theImage; 276 | } 277 | 278 | @end 279 | -------------------------------------------------------------------------------- /HDAlertView/UIView+HDExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+HDExtension.h 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 14/12/1. 6 | // Copyright © 2014年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, HDAnimationType) { 12 | HDAnimationOpen, // 动画开启 13 | HDAnimationClose // 动画关闭 14 | }; 15 | 16 | @interface UIView (HDExtension) 17 | 18 | 19 | #pragma mark - 快速设置控件的frame 20 | @property (nonatomic, assign) CGFloat hd_x; 21 | @property (nonatomic, assign) CGFloat hd_y; 22 | @property (nonatomic, assign) CGFloat hd_centerX; 23 | @property (nonatomic, assign) CGFloat hd_centerY; 24 | @property (nonatomic, assign) CGFloat hd_width; 25 | @property (nonatomic, assign) CGFloat hd_height; 26 | @property (nonatomic, assign) CGPoint hd_origin; 27 | @property (nonatomic, assign) CGSize hd_size; 28 | @property (nonatomic, assign) CGFloat hb_right; 29 | @property (nonatomic, assign) CGFloat hb_bottom; 30 | 31 | 32 | #pragma mark - 视图相关 33 | /** 34 | * 移除全部的子视图 35 | */ 36 | - (void)hd_removeAllSubviews; 37 | 38 | #pragma mark - 动画相关 39 | /** 40 | * 在某个点添加动画 41 | * 42 | * @param point 动画开始的点 43 | */ 44 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point; 45 | 46 | /** 47 | * 在某个点添加动画 48 | * 49 | * @param point 动画开始的点 50 | * @param type 动画的类型 51 | * @param color 动画的颜色 52 | */ 53 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithType:(HDAnimationType)type withColor:(UIColor *)animationColor; 54 | 55 | /** 56 | * 在某个点添加动画 57 | * 58 | * @param point 动画开始的点 59 | * @param type 动画的类型 60 | * @param color 动画的颜色 61 | * @param completion 动画结束后的代码快 62 | */ 63 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithType:(HDAnimationType)type withColor:(UIColor *)animationColor completion:(void (^)(BOOL finished))completion; 64 | 65 | /** 66 | * 在某个点添加动画 67 | * 68 | * @param point 动画开始的点 69 | * @param duration 动画时间 70 | * @param type 动画的类型 71 | * @param color 动画的颜色 72 | * @param completion 动画结束后的代码快 73 | */ 74 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithDuration:(NSTimeInterval)duration WithType:(HDAnimationType) type withColor:(UIColor *)animationColor completion:(void (^)(BOOL finished))completion; 75 | 76 | 77 | #pragma UIView变成UIImage 78 | /** 79 | 视图转成图片 80 | 81 | @return 返回图片 82 | */ 83 | - (UIImage *)hd_convertViewToImage; 84 | 85 | /** 86 | 视图裁剪成图片 87 | 88 | @return 返回图片 89 | */ 90 | - (UIImage *)hd_snapsHotView; 91 | 92 | /** 93 | 视图转成图片 94 | 95 | @param view 视图 96 | @return 返回图片 97 | */ 98 | + (UIImage *)hd_convertViewToImage:(UIView *)view; 99 | 100 | /** 101 | 视图裁剪成图片 102 | 103 | @param view 视图 104 | @return 返回图片 105 | */ 106 | + (UIImage *)hd_snapsHotView:(UIView *)view; 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /HDAlertView/UIView+HDExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+HDExtension.m 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 14/12/1. 6 | // Copyright © 2014年 hedong. All rights reserved. 7 | // 8 | 9 | #import "UIView+HDExtension.h" 10 | 11 | @implementation UIView (HDExtension) 12 | 13 | #pragma mark - 快速设置控件的frame 14 | - (void)setHd_x:(CGFloat)hd_x { 15 | CGRect frame = self.frame; 16 | frame.origin.x = hd_x; 17 | self.frame = frame; 18 | } 19 | 20 | - (CGFloat)hd_x { 21 | return self.frame.origin.x; 22 | } 23 | 24 | - (void)setHd_y:(CGFloat)hd_y { 25 | CGRect frame = self.frame; 26 | frame.origin.y = hd_y; 27 | self.frame = frame; 28 | } 29 | 30 | - (CGFloat)hd_y { 31 | return self.frame.origin.y; 32 | } 33 | 34 | - (void)setHd_centerX:(CGFloat)hd_centerX { 35 | CGPoint center = self.center; 36 | center.x = hd_centerX; 37 | self.center = center; 38 | } 39 | 40 | - (CGFloat)hd_centerX { 41 | return self.center.x; 42 | } 43 | 44 | - (void)setHd_centerY:(CGFloat)hd_centerY { 45 | CGPoint center = self.center; 46 | center.y = hd_centerY; 47 | self.center = center; 48 | } 49 | 50 | - (CGFloat)hd_centerY { 51 | return self.center.y; 52 | } 53 | 54 | - (void)setHd_width:(CGFloat)hd_width { 55 | CGRect frame = self.frame; 56 | frame.size.width = hd_width; 57 | self.frame = frame; 58 | } 59 | 60 | - (CGFloat)hd_width { 61 | return self.frame.size.width; 62 | } 63 | 64 | - (void)setHd_height:(CGFloat)hd_height { 65 | CGRect frame = self.frame; 66 | frame.size.height = hd_height; 67 | self.frame = frame; 68 | } 69 | 70 | - (CGFloat)hd_height { 71 | return self.frame.size.height; 72 | } 73 | 74 | - (void)setHd_size:(CGSize)hd_size { 75 | CGRect frame = self.frame; 76 | frame.size = hd_size; 77 | self.frame = frame; 78 | } 79 | 80 | - (CGSize)hd_size { 81 | return self.frame.size; 82 | } 83 | 84 | - (void)setHd_origin:(CGPoint)hd_origin { 85 | CGRect frame = self.frame; 86 | frame.origin = hd_origin; 87 | self.frame = frame; 88 | } 89 | 90 | - (CGPoint)hd_origin { 91 | return self.frame.origin; 92 | } 93 | 94 | - (void)setHb_right:(CGFloat)right { 95 | CGRect frame = self.frame; 96 | frame.origin.x = right - frame.size.width; 97 | self.frame = frame; 98 | } 99 | 100 | - (CGFloat)hb_right { 101 | return self.frame.origin.x + self.frame.size.width; 102 | } 103 | 104 | - (void)setHb_bottom:(CGFloat)bottom { 105 | CGRect frame = self.frame; 106 | frame.origin.y = bottom - frame.size.height; 107 | self.frame = frame; 108 | } 109 | 110 | - (CGFloat)hb_bottom { 111 | return self.frame.origin.y + self.frame.size.height; 112 | } 113 | 114 | 115 | #pragma mark - 视图相关 116 | - (void)hd_removeAllSubviews { 117 | while (self.subviews.count) { 118 | [self.subviews.lastObject removeFromSuperview]; 119 | } 120 | } 121 | 122 | 123 | #pragma mark - 动画相关 124 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point; { 125 | CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 126 | CGFloat diameter = [self hd_mdShapeDiameterForPoint:point]; 127 | shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter); 128 | shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath; 129 | [self.layer addSublayer:shapeLayer]; 130 | shapeLayer.fillColor = [UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1.0].CGColor; 131 | // animate 132 | CGFloat scale = 100.0 / shapeLayer.frame.size.width; 133 | NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault; 134 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 135 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 136 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 137 | animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName]; 138 | animation.removedOnCompletion = YES; 139 | animation.duration = 3.0; 140 | shapeLayer.transform = [animation.toValue CATransform3DValue]; 141 | 142 | [CATransaction begin]; 143 | [CATransaction setCompletionBlock:^{ 144 | [shapeLayer removeFromSuperlayer]; 145 | }]; 146 | [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"]; 147 | [CATransaction commit]; 148 | 149 | return self; 150 | } 151 | 152 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithType:(HDAnimationType)type withColor:(UIColor *)animationColor completion:(void (^)(BOOL))completion { 153 | [self hd_addAnimationAtPoint:point WithDuration:1.0 WithType:type withColor:animationColor completion:completion]; 154 | 155 | return self; 156 | } 157 | 158 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithDuration:(NSTimeInterval)duration WithType:(HDAnimationType)type withColor:(UIColor *)animationColor completion:(void (^)(BOOL finished))completion { 159 | CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 160 | CGFloat diameter = [self hd_mdShapeDiameterForPoint:point]; 161 | shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter); 162 | shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath; 163 | 164 | shapeLayer.fillColor = animationColor.CGColor; 165 | // animate 166 | CGFloat scale = 1.0 / shapeLayer.frame.size.width; 167 | NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault; 168 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 169 | switch (type) { 170 | case HDAnimationOpen: 171 | { 172 | [self.layer addSublayer:shapeLayer]; 173 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 174 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 175 | break; 176 | } 177 | case HDAnimationClose: 178 | { 179 | [self.layer insertSublayer:shapeLayer atIndex:0]; 180 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 181 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 182 | break; 183 | } 184 | default: 185 | break; 186 | } 187 | animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName]; 188 | animation.removedOnCompletion = YES; 189 | animation.duration = duration; 190 | shapeLayer.transform = [animation.toValue CATransform3DValue]; 191 | 192 | [CATransaction begin]; 193 | [CATransaction setCompletionBlock:^{ 194 | [shapeLayer removeFromSuperlayer]; 195 | completion(true); 196 | }]; 197 | [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"]; 198 | [CATransaction commit]; 199 | 200 | return self; 201 | } 202 | 203 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithType:(HDAnimationType)type withColor:(UIColor *)animationColor; { 204 | CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 205 | CGFloat diameter = [self hd_mdShapeDiameterForPoint:point]; 206 | shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter); 207 | shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath; 208 | 209 | shapeLayer.fillColor = animationColor.CGColor; 210 | // animate 211 | CGFloat scale = 100.0 / shapeLayer.frame.size.width; 212 | NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault; 213 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 214 | switch (type) { 215 | case HDAnimationOpen: 216 | { 217 | [self.layer addSublayer:shapeLayer]; 218 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 219 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 220 | break; 221 | } 222 | case HDAnimationClose: 223 | { 224 | [self.layer insertSublayer:shapeLayer atIndex:0]; 225 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 226 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 227 | break; 228 | } 229 | default: 230 | break; 231 | } 232 | animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName]; 233 | animation.removedOnCompletion = YES; 234 | animation.duration = 3.0; 235 | shapeLayer.transform = [animation.toValue CATransform3DValue]; 236 | 237 | [CATransaction begin]; 238 | [CATransaction setCompletionBlock:^{ 239 | [shapeLayer removeFromSuperlayer]; 240 | }]; 241 | [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"]; 242 | [CATransaction commit]; 243 | 244 | return self; 245 | } 246 | 247 | // 计算离屏幕的边框最大的距离 248 | - (CGFloat)hd_mdShapeDiameterForPoint:(CGPoint)point { 249 | CGPoint cornerPoints[] = { 250 | {0.0, 0.0}, 251 | {0.0, self.bounds.size.height}, 252 | {self.bounds.size.width, self.bounds.size.height}, 253 | {self.bounds.size.width, 0.0} 254 | }; 255 | 256 | CGFloat radius = 0.0; 257 | for (int i = 0; i < 4; i++) { 258 | CGPoint p = cornerPoints[i]; 259 | CGFloat d = sqrt( pow(p.x - point.x, 2.0) + pow(p.y - point.y, 2.0)); 260 | if (d > radius) { 261 | radius = d; 262 | } 263 | } 264 | 265 | return radius * 2.0; 266 | } 267 | 268 | 269 | #pragma UIView变成UIImage 270 | #pragma UIView变成UIImage 271 | + (UIImage *)hd_convertViewToImage:(UIView *)view { 272 | // 第二个参数表示是否非透明。如果需要显示半透明效果,需传NO,否则YES。第三个参数就是屏幕密度了 273 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, [UIScreen mainScreen].scale); 274 | [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 275 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 276 | UIGraphicsEndImageContext(); 277 | 278 | return image; 279 | } 280 | 281 | + (UIImage *)hd_snapsHotView:(UIView *)view { 282 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, [UIScreen mainScreen].scale); 283 | [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO]; 284 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 285 | UIGraphicsEndImageContext(); 286 | 287 | return image; 288 | } 289 | 290 | - (UIImage *)hd_convertViewToImage { 291 | return [UIView hd_convertViewToImage:self]; 292 | } 293 | 294 | - (UIImage *)hd_snapsHotView { 295 | return [UIView hd_snapsHotView:self]; 296 | } 297 | 298 | @end 299 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6702F4D91D77C06000EAA8FA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6702F4D81D77C06000EAA8FA /* main.m */; }; 11 | 6702F4DC1D77C06000EAA8FA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6702F4DB1D77C06000EAA8FA /* AppDelegate.m */; }; 12 | 6702F4DF1D77C06000EAA8FA /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6702F4DE1D77C06000EAA8FA /* ViewController.m */; }; 13 | 6702F4E21D77C06000EAA8FA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6702F4E01D77C06000EAA8FA /* Main.storyboard */; }; 14 | 6702F4E41D77C06000EAA8FA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6702F4E31D77C06000EAA8FA /* Assets.xcassets */; }; 15 | 6702F4E71D77C06000EAA8FA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6702F4E51D77C06000EAA8FA /* LaunchScreen.storyboard */; }; 16 | 6702F4FD1D77DA1600EAA8FA /* UIView+HDExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 6702F4FC1D77DA1600EAA8FA /* UIView+HDExtension.m */; }; 17 | 6702F5001D77DA2000EAA8FA /* UIImage+HDExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 6702F4FF1D77DA2000EAA8FA /* UIImage+HDExtension.m */; }; 18 | 67EB57431EBF73DE00FBF3A3 /* NSString+HDExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 67EB57421EBF73DE00FBF3A3 /* NSString+HDExtension.m */; }; 19 | 67EB57461EBF73EE00FBF3A3 /* HDAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 67EB57451EBF73EE00FBF3A3 /* HDAlertView.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 6702F4D41D77C06000EAA8FA /* HDAlertViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HDAlertViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 6702F4D81D77C06000EAA8FA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 25 | 6702F4DA1D77C06000EAA8FA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | 6702F4DB1D77C06000EAA8FA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | 6702F4DD1D77C06000EAA8FA /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | 6702F4DE1D77C06000EAA8FA /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | 6702F4E11D77C06000EAA8FA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 6702F4E31D77C06000EAA8FA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | 6702F4E61D77C06000EAA8FA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | 6702F4E81D77C06100EAA8FA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 6702F4FB1D77DA1600EAA8FA /* UIView+HDExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+HDExtension.h"; sourceTree = ""; }; 34 | 6702F4FC1D77DA1600EAA8FA /* UIView+HDExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+HDExtension.m"; sourceTree = ""; }; 35 | 6702F4FE1D77DA2000EAA8FA /* UIImage+HDExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+HDExtension.h"; sourceTree = ""; }; 36 | 6702F4FF1D77DA2000EAA8FA /* UIImage+HDExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+HDExtension.m"; sourceTree = ""; }; 37 | 67EB57401EBF73C600FBF3A3 /* HDMacro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDMacro.h; sourceTree = ""; }; 38 | 67EB57411EBF73DE00FBF3A3 /* NSString+HDExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+HDExtension.h"; sourceTree = ""; }; 39 | 67EB57421EBF73DE00FBF3A3 /* NSString+HDExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+HDExtension.m"; sourceTree = ""; }; 40 | 67EB57441EBF73EE00FBF3A3 /* HDAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDAlertView.h; sourceTree = ""; }; 41 | 67EB57451EBF73EE00FBF3A3 /* HDAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDAlertView.m; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 6702F4D11D77C06000EAA8FA /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | 6702F4CB1D77C06000EAA8FA = { 56 | isa = PBXGroup; 57 | children = ( 58 | 6702F4D61D77C06000EAA8FA /* HDAlertViewDemo */, 59 | 6702F4D51D77C06000EAA8FA /* Products */, 60 | ); 61 | sourceTree = ""; 62 | }; 63 | 6702F4D51D77C06000EAA8FA /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 6702F4D41D77C06000EAA8FA /* HDAlertViewDemo.app */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | 6702F4D61D77C06000EAA8FA /* HDAlertViewDemo */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 6702F4EE1D77C2BA00EAA8FA /* HDAlertView */, 75 | 6702F4DA1D77C06000EAA8FA /* AppDelegate.h */, 76 | 6702F4DB1D77C06000EAA8FA /* AppDelegate.m */, 77 | 6702F4DD1D77C06000EAA8FA /* ViewController.h */, 78 | 6702F4DE1D77C06000EAA8FA /* ViewController.m */, 79 | 6702F4E01D77C06000EAA8FA /* Main.storyboard */, 80 | 6702F4E31D77C06000EAA8FA /* Assets.xcassets */, 81 | 6702F4E51D77C06000EAA8FA /* LaunchScreen.storyboard */, 82 | 6702F4E81D77C06100EAA8FA /* Info.plist */, 83 | 6702F4D71D77C06000EAA8FA /* Supporting Files */, 84 | ); 85 | path = HDAlertViewDemo; 86 | sourceTree = ""; 87 | }; 88 | 6702F4D71D77C06000EAA8FA /* Supporting Files */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 6702F4D81D77C06000EAA8FA /* main.m */, 92 | ); 93 | name = "Supporting Files"; 94 | sourceTree = ""; 95 | }; 96 | 6702F4EE1D77C2BA00EAA8FA /* HDAlertView */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 67EB57441EBF73EE00FBF3A3 /* HDAlertView.h */, 100 | 67EB57451EBF73EE00FBF3A3 /* HDAlertView.m */, 101 | 67EB57411EBF73DE00FBF3A3 /* NSString+HDExtension.h */, 102 | 67EB57421EBF73DE00FBF3A3 /* NSString+HDExtension.m */, 103 | 67EB57401EBF73C600FBF3A3 /* HDMacro.h */, 104 | 6702F4FB1D77DA1600EAA8FA /* UIView+HDExtension.h */, 105 | 6702F4FC1D77DA1600EAA8FA /* UIView+HDExtension.m */, 106 | 6702F4FE1D77DA2000EAA8FA /* UIImage+HDExtension.h */, 107 | 6702F4FF1D77DA2000EAA8FA /* UIImage+HDExtension.m */, 108 | ); 109 | path = HDAlertView; 110 | sourceTree = ""; 111 | }; 112 | /* End PBXGroup section */ 113 | 114 | /* Begin PBXNativeTarget section */ 115 | 6702F4D31D77C06000EAA8FA /* HDAlertViewDemo */ = { 116 | isa = PBXNativeTarget; 117 | buildConfigurationList = 6702F4EB1D77C06100EAA8FA /* Build configuration list for PBXNativeTarget "HDAlertViewDemo" */; 118 | buildPhases = ( 119 | 6702F4D01D77C06000EAA8FA /* Sources */, 120 | 6702F4D11D77C06000EAA8FA /* Frameworks */, 121 | 6702F4D21D77C06000EAA8FA /* Resources */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = HDAlertViewDemo; 128 | productName = HDAlertViewDemo; 129 | productReference = 6702F4D41D77C06000EAA8FA /* HDAlertViewDemo.app */; 130 | productType = "com.apple.product-type.application"; 131 | }; 132 | /* End PBXNativeTarget section */ 133 | 134 | /* Begin PBXProject section */ 135 | 6702F4CC1D77C06000EAA8FA /* Project object */ = { 136 | isa = PBXProject; 137 | attributes = { 138 | LastUpgradeCheck = 0910; 139 | ORGANIZATIONNAME = hedong; 140 | TargetAttributes = { 141 | 6702F4D31D77C06000EAA8FA = { 142 | CreatedOnToolsVersion = 7.3; 143 | }; 144 | }; 145 | }; 146 | buildConfigurationList = 6702F4CF1D77C06000EAA8FA /* Build configuration list for PBXProject "HDAlertViewDemo" */; 147 | compatibilityVersion = "Xcode 3.2"; 148 | developmentRegion = English; 149 | hasScannedForEncodings = 0; 150 | knownRegions = ( 151 | en, 152 | Base, 153 | ); 154 | mainGroup = 6702F4CB1D77C06000EAA8FA; 155 | productRefGroup = 6702F4D51D77C06000EAA8FA /* Products */; 156 | projectDirPath = ""; 157 | projectRoot = ""; 158 | targets = ( 159 | 6702F4D31D77C06000EAA8FA /* HDAlertViewDemo */, 160 | ); 161 | }; 162 | /* End PBXProject section */ 163 | 164 | /* Begin PBXResourcesBuildPhase section */ 165 | 6702F4D21D77C06000EAA8FA /* Resources */ = { 166 | isa = PBXResourcesBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | 6702F4E71D77C06000EAA8FA /* LaunchScreen.storyboard in Resources */, 170 | 6702F4E41D77C06000EAA8FA /* Assets.xcassets in Resources */, 171 | 6702F4E21D77C06000EAA8FA /* Main.storyboard in Resources */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXResourcesBuildPhase section */ 176 | 177 | /* Begin PBXSourcesBuildPhase section */ 178 | 6702F4D01D77C06000EAA8FA /* Sources */ = { 179 | isa = PBXSourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 6702F4DF1D77C06000EAA8FA /* ViewController.m in Sources */, 183 | 67EB57431EBF73DE00FBF3A3 /* NSString+HDExtension.m in Sources */, 184 | 67EB57461EBF73EE00FBF3A3 /* HDAlertView.m in Sources */, 185 | 6702F5001D77DA2000EAA8FA /* UIImage+HDExtension.m in Sources */, 186 | 6702F4DC1D77C06000EAA8FA /* AppDelegate.m in Sources */, 187 | 6702F4FD1D77DA1600EAA8FA /* UIView+HDExtension.m in Sources */, 188 | 6702F4D91D77C06000EAA8FA /* main.m in Sources */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | /* End PBXSourcesBuildPhase section */ 193 | 194 | /* Begin PBXVariantGroup section */ 195 | 6702F4E01D77C06000EAA8FA /* Main.storyboard */ = { 196 | isa = PBXVariantGroup; 197 | children = ( 198 | 6702F4E11D77C06000EAA8FA /* Base */, 199 | ); 200 | name = Main.storyboard; 201 | sourceTree = ""; 202 | }; 203 | 6702F4E51D77C06000EAA8FA /* LaunchScreen.storyboard */ = { 204 | isa = PBXVariantGroup; 205 | children = ( 206 | 6702F4E61D77C06000EAA8FA /* Base */, 207 | ); 208 | name = LaunchScreen.storyboard; 209 | sourceTree = ""; 210 | }; 211 | /* End PBXVariantGroup section */ 212 | 213 | /* Begin XCBuildConfiguration section */ 214 | 6702F4E91D77C06100EAA8FA /* Debug */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | ALWAYS_SEARCH_USER_PATHS = NO; 218 | CLANG_ANALYZER_NONNULL = YES; 219 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 220 | CLANG_CXX_LIBRARY = "libc++"; 221 | CLANG_ENABLE_MODULES = YES; 222 | CLANG_ENABLE_OBJC_ARC = YES; 223 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 224 | CLANG_WARN_BOOL_CONVERSION = YES; 225 | CLANG_WARN_COMMA = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 228 | CLANG_WARN_EMPTY_BODY = YES; 229 | CLANG_WARN_ENUM_CONVERSION = YES; 230 | CLANG_WARN_INFINITE_RECURSION = YES; 231 | CLANG_WARN_INT_CONVERSION = YES; 232 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 233 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 234 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 235 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 236 | CLANG_WARN_STRICT_PROTOTYPES = YES; 237 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 238 | CLANG_WARN_UNREACHABLE_CODE = YES; 239 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 240 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 241 | COPY_PHASE_STRIP = NO; 242 | DEBUG_INFORMATION_FORMAT = dwarf; 243 | ENABLE_STRICT_OBJC_MSGSEND = YES; 244 | ENABLE_TESTABILITY = YES; 245 | GCC_C_LANGUAGE_STANDARD = gnu99; 246 | GCC_DYNAMIC_NO_PIC = NO; 247 | GCC_NO_COMMON_BLOCKS = YES; 248 | GCC_OPTIMIZATION_LEVEL = 0; 249 | GCC_PREPROCESSOR_DEFINITIONS = ( 250 | "DEBUG=1", 251 | "$(inherited)", 252 | ); 253 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 254 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 255 | GCC_WARN_UNDECLARED_SELECTOR = YES; 256 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 257 | GCC_WARN_UNUSED_FUNCTION = YES; 258 | GCC_WARN_UNUSED_VARIABLE = YES; 259 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 260 | MTL_ENABLE_DEBUG_INFO = YES; 261 | ONLY_ACTIVE_ARCH = YES; 262 | SDKROOT = iphoneos; 263 | }; 264 | name = Debug; 265 | }; 266 | 6702F4EA1D77C06100EAA8FA /* Release */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | ALWAYS_SEARCH_USER_PATHS = NO; 270 | CLANG_ANALYZER_NONNULL = YES; 271 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 272 | CLANG_CXX_LIBRARY = "libc++"; 273 | CLANG_ENABLE_MODULES = YES; 274 | CLANG_ENABLE_OBJC_ARC = YES; 275 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 276 | CLANG_WARN_BOOL_CONVERSION = YES; 277 | CLANG_WARN_COMMA = YES; 278 | CLANG_WARN_CONSTANT_CONVERSION = YES; 279 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 280 | CLANG_WARN_EMPTY_BODY = YES; 281 | CLANG_WARN_ENUM_CONVERSION = YES; 282 | CLANG_WARN_INFINITE_RECURSION = YES; 283 | CLANG_WARN_INT_CONVERSION = YES; 284 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 285 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 286 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 287 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 288 | CLANG_WARN_STRICT_PROTOTYPES = YES; 289 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 290 | CLANG_WARN_UNREACHABLE_CODE = YES; 291 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 292 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 293 | COPY_PHASE_STRIP = NO; 294 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 295 | ENABLE_NS_ASSERTIONS = NO; 296 | ENABLE_STRICT_OBJC_MSGSEND = YES; 297 | GCC_C_LANGUAGE_STANDARD = gnu99; 298 | GCC_NO_COMMON_BLOCKS = YES; 299 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 300 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 301 | GCC_WARN_UNDECLARED_SELECTOR = YES; 302 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 303 | GCC_WARN_UNUSED_FUNCTION = YES; 304 | GCC_WARN_UNUSED_VARIABLE = YES; 305 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 306 | MTL_ENABLE_DEBUG_INFO = NO; 307 | SDKROOT = iphoneos; 308 | VALIDATE_PRODUCT = YES; 309 | }; 310 | name = Release; 311 | }; 312 | 6702F4EC1D77C06100EAA8FA /* Debug */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 316 | CODE_SIGN_IDENTITY = "iPhone Developer"; 317 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 318 | DEVELOPMENT_TEAM = ""; 319 | INFOPLIST_FILE = HDAlertViewDemo/Info.plist; 320 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 321 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 322 | PRODUCT_BUNDLE_IDENTIFIER = com.hedong.www.HDAlertViewDemo; 323 | PRODUCT_NAME = "$(TARGET_NAME)"; 324 | PROVISIONING_PROFILE = ""; 325 | }; 326 | name = Debug; 327 | }; 328 | 6702F4ED1D77C06100EAA8FA /* Release */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 332 | CODE_SIGN_IDENTITY = "iPhone Developer"; 333 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 334 | DEVELOPMENT_TEAM = ""; 335 | INFOPLIST_FILE = HDAlertViewDemo/Info.plist; 336 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 337 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 338 | PRODUCT_BUNDLE_IDENTIFIER = com.hedong.www.HDAlertViewDemo; 339 | PRODUCT_NAME = "$(TARGET_NAME)"; 340 | PROVISIONING_PROFILE = ""; 341 | }; 342 | name = Release; 343 | }; 344 | /* End XCBuildConfiguration section */ 345 | 346 | /* Begin XCConfigurationList section */ 347 | 6702F4CF1D77C06000EAA8FA /* Build configuration list for PBXProject "HDAlertViewDemo" */ = { 348 | isa = XCConfigurationList; 349 | buildConfigurations = ( 350 | 6702F4E91D77C06100EAA8FA /* Debug */, 351 | 6702F4EA1D77C06100EAA8FA /* Release */, 352 | ); 353 | defaultConfigurationIsVisible = 0; 354 | defaultConfigurationName = Release; 355 | }; 356 | 6702F4EB1D77C06100EAA8FA /* Build configuration list for PBXNativeTarget "HDAlertViewDemo" */ = { 357 | isa = XCConfigurationList; 358 | buildConfigurations = ( 359 | 6702F4EC1D77C06100EAA8FA /* Debug */, 360 | 6702F4ED1D77C06100EAA8FA /* Release */, 361 | ); 362 | defaultConfigurationIsVisible = 0; 363 | defaultConfigurationName = Release; 364 | }; 365 | /* End XCConfigurationList section */ 366 | }; 367 | rootObject = 6702F4CC1D77C06000EAA8FA /* Project object */; 368 | } 369 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HDAlertViewDemo 4 | // 5 | // Created by HeDong on 16/9/1. 6 | // Copyright © 2016年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HDAlertViewDemo 4 | // 5 | // Created by HeDong on 16/9/1. 6 | // Copyright © 2016年 hedong. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 32 | 40 | 48 | 56 | 64 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/HDAlertView/HDAlertView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HDAlertView.h 3 | // Seven 4 | // 5 | // Created by HeDong on 16/9/1. 6 | // Copyright © 2016年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "HDMacro.h" 11 | 12 | HD_EXTERN NSString *const HDAlertViewWillShowNotification; 13 | HD_EXTERN NSString *const HDAlertViewDidShowNotification; 14 | HD_EXTERN NSString *const HDAlertViewWillDismissNotification; 15 | HD_EXTERN NSString *const HDAlertViewDidDismissNotification; 16 | 17 | typedef NS_ENUM(NSInteger, HDAlertViewStyle) { 18 | HDAlertViewStyleAlert = 0, // 默认 19 | HDAlertViewStyleActionSheet 20 | }; 21 | 22 | typedef NS_ENUM(NSInteger, HDAlertViewButtonType) { 23 | HDAlertViewButtonTypeDefault = 0, // 字体默认蓝色 24 | HDAlertViewButtonTypeDestructive, // 字体默认红色 25 | HDAlertViewButtonTypeCancel // 字体默认绿色 26 | }; 27 | 28 | typedef NS_ENUM(NSInteger, HDAlertViewBackgroundStyle) { 29 | HDAlertViewBackgroundStyleSolid = 0, // 平面的 30 | HDAlertViewBackgroundStyleGradient // 聚光的 31 | }; 32 | 33 | typedef NS_ENUM(NSInteger, HDAlertViewButtonsListStyle) { 34 | HDAlertViewButtonsListStyleNormal = 0, 35 | HDAlertViewButtonsListStyleRows // 每个按钮都是一行 36 | }; 37 | 38 | typedef NS_ENUM(NSInteger, HDAlertViewTransitionStyle) { 39 | HDAlertViewTransitionStyleFade = 0, // 渐退 40 | HDAlertViewTransitionStyleSlideFromTop, // 从顶部滑入滑出 41 | HDAlertViewTransitionStyleSlideFromBottom, // 从底部滑入滑出 42 | HDAlertViewTransitionStyleBounce, // 弹窗效果 43 | HDAlertViewTransitionStyleDropDown // 顶部滑入底部滑出 44 | }; 45 | 46 | @class HDAlertView; 47 | typedef void(^HDAlertViewHandler)(HDAlertView *alertView); 48 | 49 | @interface HDAlertView : UIView 50 | 51 | /** 是否支持旋转 */ 52 | @property (nonatomic, assign) BOOL isSupportRotating; 53 | 54 | /** 图标的名字 */ 55 | @property (nonatomic, copy) NSString *imageName; 56 | 57 | @property (nonatomic, copy) NSString *title; // ActionSheet模式最多2行 58 | @property (nonatomic, copy) NSString *message; 59 | @property (nonatomic, assign) NSTextAlignment titleTextAlignment; 60 | @property (nonatomic, assign) NSTextAlignment messageTextAlignment; 61 | 62 | 63 | @property (nonatomic, assign) HDAlertViewStyle alertViewStyle; // 默认是HDAlertViewStyleAlert 64 | @property (nonatomic, assign) HDAlertViewTransitionStyle transitionStyle; // 默认是 HDAlertViewTransitionStyleFade 65 | @property (nonatomic, assign) HDAlertViewBackgroundStyle backgroundStyle; // 默认是 HDAlertViewBackgroundStyleSolid 66 | @property (nonatomic, assign) HDAlertViewButtonsListStyle buttonsListStyle; // 默认是 HDAlertViewButtonsListStyleNormal 67 | 68 | @property (nonatomic, copy) HDAlertViewHandler willShowHandler; 69 | @property (nonatomic, copy) HDAlertViewHandler didShowHandler; 70 | @property (nonatomic, copy) HDAlertViewHandler willDismissHandler; 71 | @property (nonatomic, copy) HDAlertViewHandler didDismissHandler; 72 | 73 | @property (nonatomic, strong) UIColor *viewBackgroundColor UI_APPEARANCE_SELECTOR; // 默认是clearColor 74 | @property (nonatomic, strong) UIColor *titleColor UI_APPEARANCE_SELECTOR; // 默认是blackColor 75 | @property (nonatomic, strong) UIColor *messageColor UI_APPEARANCE_SELECTOR; // 默认是darkGrayColor 76 | @property (nonatomic, strong) UIColor *defaultButtonTitleColor UI_APPEARANCE_SELECTOR; // 默认是blueColor 77 | @property (nonatomic, strong) UIColor *cancelButtonTitleColor UI_APPEARANCE_SELECTOR; // 默认是greenColor 78 | @property (nonatomic, strong) UIColor *destructiveButtonTitleColor UI_APPEARANCE_SELECTOR; // 默认是redColor 79 | @property (nonatomic, strong) UIFont *titleFont UI_APPEARANCE_SELECTOR; // 默认是bold 18.0 80 | @property (nonatomic, strong) UIFont *messageFont UI_APPEARANCE_SELECTOR; // 默认是system 16.0 81 | @property (nonatomic, strong) UIFont *buttonFont UI_APPEARANCE_SELECTOR; // 默认是bold buttonFontSize 82 | @property (nonatomic, assign) CGFloat cornerRadius UI_APPEARANCE_SELECTOR; // 默认是10.0 83 | 84 | 85 | /** 86 | * 设置默认按钮图片和状态 87 | */ 88 | - (void)setDefaultButtonImage:(UIImage *)defaultButtonImage forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 89 | 90 | /** 91 | * 设置取消按钮图片和状态 92 | */ 93 | - (void)setCancelButtonImage:(UIImage *)cancelButtonImage forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 94 | 95 | /** 96 | * 设置毁灭性按钮图片和状态 97 | */ 98 | - (void)setDestructiveButtonImage:(UIImage *)destructiveButtonImage forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 99 | 100 | /** 101 | * 初始化一个弹窗提示 102 | */ 103 | - (instancetype)initWithTitle:(NSString *)title andMessage:(NSString *)message; 104 | + (instancetype)alertViewWithTitle:(NSString *)title andMessage:(NSString *)message; 105 | 106 | /** 107 | * 添加按钮点击时候和处理 108 | * 109 | * @param title 按钮名字 110 | * @param type 按钮类型 111 | * @param handler 点击按钮处理事件 112 | */ 113 | - (void)addButtonWithTitle:(NSString *)title type:(HDAlertViewButtonType)type handler:(HDAlertViewHandler)handler; 114 | 115 | /** 116 | * 显示弹窗提示 117 | */ 118 | - (void)show; 119 | 120 | /** 121 | * 移除视图 122 | */ 123 | - (void)removeAlertView; 124 | 125 | /** 126 | 快速弹窗 127 | 128 | @param title 标题 129 | @param message 消息体 130 | @param cancelButtonTitle 取消按钮文字 131 | @param otherButtonTitles 其他按钮 132 | @param block 回调 133 | @return 返回HDAlertView对象 134 | */ 135 | + (HDAlertView *)showAlertViewWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles handler:(void (^)(HDAlertView *alertView, NSInteger buttonIndex))block; 136 | 137 | /** 138 | ActionSheet样式弹窗 139 | 140 | @param title 标题 141 | @return 返回HBAlertView对象 142 | */ 143 | + (HDAlertView *)showActionSheetWithTitle:(NSString *)title; 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/HDAlertView/HDMacro.h: -------------------------------------------------------------------------------- 1 | // 2 | // HDMacro.h 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/03/20. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | //// 判断是真机还是模拟器 10 | //#if TARGET_OS_IPHONE 11 | //// iPhone Device 12 | //#endif 13 | // 14 | //#if TARGET_IPHONE_SIMULATOR 15 | //// iPhone Simulator 16 | //#endif 17 | 18 | 19 | #ifdef __cplusplus 20 | #define HD_EXTERN extern "C" __attribute__((visibility ("default"))) 21 | #else 22 | #define HD_EXTERN extern __attribute__((visibility ("default"))) 23 | #endif 24 | 25 | 26 | #define weakSelf(weakSelf) __weak typeof(self)weakSelf = self; 27 | #define strongSelf(strongSelf) __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf) return; 28 | 29 | 30 | // 由角度获取弧度 31 | #define HDDegreesToRadian(x) (M_PI * (x) / 180.0) 32 | // 由弧度获取角度 33 | #define HDRadianToDegrees(radian) (radian * 180.0) / (M_PI) 34 | 35 | 36 | #define HDNotificationCenter [NSNotificationCenter defaultCenter] 37 | #define HDUserDefaults [NSUserDefaults standardUserDefaults] 38 | #define HDFirstWindow [UIApplication sharedApplication].windows.firstObject 39 | #define HDRootViewController HDFirstWindow.rootViewController 40 | 41 | 42 | /******* 效验对象是否是空 *******/ 43 | #define HDStringIsEmpty(str) ([str isKindOfClass:[NSNull class]] || str == nil || [str length] < 1 ? YES : NO ) 44 | #define HDArrayIsEmpty(array) (array == nil || [array isKindOfClass:[NSNull class]] || array.count == 0) 45 | #define HDDictionaryIsEmpty(dic) (dic == nil || [dic isKindOfClass:[NSNull class]] || dic.allKeys == 0) 46 | #define HDObjectIsEmpty(_object) (_object == nil \ 47 | || [_object isKindOfClass:[NSNull class]] \ 48 | || ([_object respondsToSelector:@selector(length)] && [(NSData *)_object length] == 0) \ 49 | || ([_object respondsToSelector:@selector(count)] && [(NSArray *)_object count] == 0)) 50 | /******* 效验对象是否是空 *******/ 51 | 52 | 53 | /******* APP_INFO *******/ 54 | /** APP版本号 */ 55 | #define HDAppVersion [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] 56 | /** APP BUILD 版本号 */ 57 | #define HDAppBuildVersion [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] 58 | /** APP名字 */ 59 | #define HDAppDisplayName [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] 60 | /** 当前语言 */ 61 | #define HDLocalLanguage [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] 62 | /** 当前国家 */ 63 | #define HDLocalCountry [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode] 64 | /******* APP_INFO *******/ 65 | 66 | 67 | /******* 回到主线程 *******/ 68 | #define dispatch_main_sync_safe(block)\ 69 | if ([NSThread isMainThread]) {\ 70 | block();\ 71 | } else {\ 72 | dispatch_sync(dispatch_get_main_queue(), block);\ 73 | } 74 | 75 | #define dispatch_main_async_safe(block) \ 76 | if ([NSThread isMainThread]) { \ 77 | block(); \ 78 | } else { \ 79 | dispatch_async(dispatch_get_main_queue(), block); \ 80 | } 81 | /******* 回到主线程 *******/ 82 | 83 | 84 | /******* RGB颜色 *******/ 85 | #define HDColorAlpha(r, g, b, a) [UIColor colorWithRed:(r) / 255.0 green:(g) / 255.0 blue:(b) / 255.0 alpha:a] 86 | #define HDColor(r, g, b) HDColorAlpha(r, g, b, 1.0) 87 | 88 | #define HDColorFromHexAlpha(rgbValue, a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16)) / 255.0 green:((float)((rgbValue & 0xFF00) >> 8)) / 255.0 blue:((float)(rgbValue & 0xFF)) / 255.0 alpha:a] 89 | #define HDColorFromHex(rgbValue) HDColorFromHexAlpha(rgbValue, 1.0) 90 | /******* RGB颜色 *******/ 91 | 92 | 93 | /******* 屏幕尺寸 *******/ 94 | #define HDMainScreenWidth [UIScreen mainScreen].bounds.size.width 95 | #define HDMainScreenHeight [UIScreen mainScreen].bounds.size.height 96 | #define HDMainScreenBounds [UIScreen mainScreen].bounds 97 | /******* 屏幕尺寸 *******/ 98 | 99 | 100 | /******* 屏幕系数 *******/ 101 | #define HDiPhone6WidthCoefficient(width) (width / 375.0) // 以苹果6为准的系数 102 | #define HDiPhone6HeightCoefficient(height) (height / 667.0) // 以苹果6为准的系数 103 | #define HDiPhone6ScaleWidth(width) (HDiPhone6WidthCoefficient(width) * HDMainScreenWidth) // 以苹果6为准的系数得到的宽 104 | #define HDiPhone6ScaleHeight(height) (HDiPhone6HeightCoefficient(height) * HDMainScreenHeight) // 以苹果6为准的系数得到的高 105 | /******* 屏幕系数 *******/ 106 | 107 | 108 | /******* 设备型号和系统 *******/ 109 | /** 检查系统版本 */ 110 | #define HDSYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) 111 | #define HDSYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) 112 | #define HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 113 | #define HDSYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) 114 | #define HDSYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) 115 | 116 | #define iOS5_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.0") 117 | #define iOS6_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0") 118 | #define iOS7_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0") 119 | #define iOS8_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0") 120 | #define iOS9_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9.0") 121 | #define iOS10_OR_LATER HDSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0") 122 | 123 | /** 系统和版本号 */ 124 | #define HDDevice [UIDevice currentDevice] 125 | #define HDDeviceName HDDevice.name // 设备名称 126 | #define HDDeviceModel HDDevice.model // 设备类型 127 | #define HDDeviceLocalizedModel HDDevice.localizedModel // 本地化模式 128 | #define HDDeviceSystemName HDDevice.systemName // 系统名字 129 | #define HDDeviceSystemVersion HDDevice.systemVersion // 系统版本 130 | #define HDDeviceOrientation HDDevice.orientation // 设备朝向 131 | //#define HDDeviceUUID HDDevice.identifierForVendor.UUIDString // UUID // 使用苹果不让上传App Store!!! 132 | #define HDiOS8 ([HDDeviceSystemVersion floatValue] >= 8.0) // iOS8以上 133 | #define HDiPhone ([HDDeviceModel rangeOfString:@"iPhone"].length > 0) 134 | #define HDiPod ([HDDeviceModel rangeOfString:@"iPod"].length > 0) 135 | #define HDiPad (HDDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) 136 | /******* 设备型号和系统 *******/ 137 | 138 | 139 | /******* 日志打印替换 *******/ 140 | //#import 141 | #ifdef DEBUG 142 | 143 | //#define HDLog(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagVerbose, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 144 | // 145 | //#define HDLogError(frmt, ...) LOG_MAYBE(NO, LOG_LEVEL_DEF, DDLogFlagError, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 146 | // 147 | //#define HDLogWarn(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagWarning, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 148 | // 149 | //#define HDLogInfo(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagInfo, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 150 | // 151 | //#define HDLogDebug(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagDebug, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 152 | // 153 | //#define HDLogVerbose(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagVerbose, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__) 154 | 155 | 156 | #define HDAssert(...) NSAssert(__VA_ARGS__) 157 | #define HDParameterAssert(condition) NSAssert((condition), @"Invalid parameter not satisfying: %@", @#condition) 158 | 159 | //static const int ddLogLevel = LOG_LEVEL_VERBOSE; 160 | 161 | #else 162 | 163 | #define HDLog(...) 164 | #define HDLogError(frmt, ...) 165 | #define HDLogWarn(frmt, ...) 166 | #define HDLogInfo(frmt, ...) 167 | #define HDLogDebug(frmt, ...) 168 | 169 | #define HDAssert(...) 170 | #define HDParameterAssert(condition) 171 | //static const int ddLogLevel = LOG_LEVEL_OFF; 172 | 173 | #endif 174 | /******* 日志打印替换 *******/ 175 | 176 | 177 | /******* 归档解档 *******/ 178 | #define HDCodingImplementation \ 179 | - (void)encodeWithCoder:(NSCoder *)aCoder { \ 180 | unsigned int count = 0; \ 181 | Ivar *ivars = class_copyIvarList([self class], &count); \ 182 | for (int i = 0; i < count; i++) { \ 183 | Ivar ivar = ivars[i]; \ 184 | const char *name = ivar_getName(ivar); \ 185 | NSString *key = [NSString stringWithUTF8String:name]; \ 186 | id value = [self valueForKey:key]; \ 187 | [aCoder encodeObject:value forKey:key]; \ 188 | } \ 189 | free(ivars); \ 190 | } \ 191 | \ 192 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { \ 193 | if (self = [super init]) { \ 194 | unsigned int count = 0; \ 195 | Ivar *ivars = class_copyIvarList([self class], &count); \ 196 | for (int i = 0; i < count; i++) { \ 197 | Ivar ivar = ivars[i]; \ 198 | const char *name = ivar_getName(ivar); \ 199 | NSString *key = [NSString stringWithUTF8String:name]; \ 200 | id value = [aDecoder decodeObjectForKey:key]; \ 201 | [self setValue:value forKey:key]; \ 202 | } \ 203 | free(ivars); \ 204 | } \ 205 | return self; \ 206 | } 207 | /******* 归档解档 *******/ 208 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/HDAlertView/NSString+HDExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+HDExtension.h 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/5/10. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "HDMacro.h" 11 | 12 | @interface NSString (HDExtension) 13 | 14 | #pragma mark - 散列函数 15 | /** 16 | * 计算MD5散列结果 17 | * 18 | * 终端测试命令: 19 | * @code 20 | * md5 -s "string" 21 | * @endcode 22 | * 23 | *

提示:随着 MD5 碰撞生成器的出现,MD5 算法不应被用于任何软件完整性检查或代码签名的用途。

24 | * 25 | * @return 32个字符的MD5散列字符串 26 | */ 27 | - (instancetype)hd_md5String; 28 | 29 | /** 30 | * 计算SHA1散列结果 31 | * 32 | * 终端测试命令: 33 | * @code 34 | * echo -n "string" | openssl sha -sha1 35 | * @endcode 36 | * 37 | * @return 40个字符的SHA1散列字符串 38 | */ 39 | - (instancetype)hd_sha1String; 40 | 41 | /** 42 | * 计算SHA224散列结果 43 | * 44 | * 终端测试命令: 45 | * @code 46 | * echo -n "string" | openssl sha -sha224 47 | * @endcode 48 | * 49 | * @return 56个字符的SHA224散列字符串 50 | */ 51 | - (instancetype)hd_sha224String; 52 | 53 | /** 54 | * 计算SHA256散列结果 55 | * 56 | * 终端测试命令: 57 | * @code 58 | * echo -n "string" | openssl sha -sha256 59 | * @endcode 60 | * 61 | * @return 64个字符的SHA256散列字符串 62 | */ 63 | - (instancetype)hd_sha256String; 64 | 65 | /** 66 | * 计算SHA 384散列结果 67 | * 68 | * 终端测试命令: 69 | * @code 70 | * echo -n "string" | openssl sha -sha384 71 | * @endcode 72 | * 73 | * @return 96个字符的SHA 384散列字符串 74 | */ 75 | - (instancetype)hd_sha384String; 76 | 77 | /** 78 | * 计算SHA 512散列结果 79 | * 80 | * 终端测试命令: 81 | * @code 82 | * echo -n "string" | openssl sha -sha512 83 | * @endcode 84 | * 85 | * @return 128个字符的SHA 512散列字符串 86 | */ 87 | - (instancetype)hd_sha512String; 88 | 89 | #pragma mark - HMAC 散列函数 90 | /** 91 | * 计算HMAC MD5散列结果 92 | * 93 | * 终端测试命令: 94 | * @code 95 | * echo -n "string" | openssl dgst -md5 -hmac "key" 96 | * @endcode 97 | * 98 | * @return 32个字符的HMAC MD5散列字符串 99 | */ 100 | - (instancetype)hd_hmacMD5StringWithKey:(NSString *)key; 101 | 102 | /** 103 | * 计算HMAC SHA1散列结果 104 | * 105 | * 终端测试命令: 106 | * @code 107 | * echo -n "string" | openssl sha -sha1 -hmac "key" 108 | * @endcode 109 | * 110 | * @return 40个字符的HMAC SHA1散列字符串 111 | */ 112 | - (instancetype)hd_hmacSHA1StringWithKey:(NSString *)key; 113 | 114 | /** 115 | * 计算HMAC SHA256散列结果 116 | * 117 | * 终端测试命令: 118 | * @code 119 | * echo -n "string" | openssl sha -sha256 -hmac "key" 120 | * @endcode 121 | * 122 | * @return 64个字符的HMAC SHA256散列字符串 123 | */ 124 | - (instancetype)hd_hmacSHA256StringWithKey:(NSString *)key; 125 | 126 | /** 127 | * 计算HMAC SHA512散列结果 128 | * 129 | * 终端测试命令: 130 | * @code 131 | * echo -n "string" | openssl sha -sha512 -hmac "key" 132 | * @endcode 133 | * 134 | * @return 128个字符的HMAC SHA512散列字符串 135 | */ 136 | - (instancetype)hd_hmacSHA512StringWithKey:(NSString *)key; 137 | 138 | #pragma mark - 文件散列函数 139 | /** 140 | * 计算文件的MD5散列结果 141 | * 142 | * 终端测试命令: 143 | * @code 144 | * md5 file.dat 145 | * @endcode 146 | * 147 | * @return 32个字符的MD5散列字符串 148 | */ 149 | - (instancetype)hd_fileMD5Hash; 150 | 151 | /** 152 | * 计算文件的SHA1散列结果 153 | * 154 | * 终端测试命令: 155 | * @code 156 | * openssl sha -sha1 file.dat 157 | * @endcode 158 | * 159 | * @return 40个字符的SHA1散列字符串 160 | */ 161 | - (instancetype)hd_fileSHA1Hash; 162 | 163 | /** 164 | * 计算文件的SHA256散列结果 165 | * 166 | * 终端测试命令: 167 | * @code 168 | * openssl sha -sha256 file.dat 169 | * @endcode 170 | * 171 | * @return 64个字符的SHA256散列字符串 172 | */ 173 | - (instancetype)hd_fileSHA256Hash; 174 | 175 | /** 176 | * 计算文件的SHA512散列结果 177 | * 178 | * 终端测试命令: 179 | * @code 180 | * openssl sha -sha512 file.dat 181 | * @endcode 182 | * 183 | * @return 128个字符的SHA512散列字符串 184 | */ 185 | - (instancetype)hd_fileSHA512Hash; 186 | 187 | #pragma mark - Base64编码 188 | /** 189 | * 返回Base64遍码后的字符串 190 | */ 191 | - (instancetype)hd_base64Encode; 192 | 193 | /** 194 | * 返回Base64解码后的字符串 195 | */ 196 | - (instancetype)hd_base64Decode; 197 | 198 | #pragma mark - 路径方法 199 | /** 200 | * 快速返回沙盒中,Documents文件的路径 201 | * 202 | * @return Documents文件的路径 203 | */ 204 | + (instancetype)hd_pathForDocuments; 205 | 206 | /** 207 | * 快速返回沙盒中,Documents文件中某个子文件的路径 208 | * 209 | * @param fileName 子文件名称 210 | * 211 | * @return 快速返回Documents文件中某个子文件的路径 212 | */ 213 | + (instancetype)hd_filePathAtDocumentsWithFileName:(NSString *)fileName; 214 | 215 | /** 216 | * 快速返回沙盒中,Library下Caches文件的路径 217 | * 218 | * @return 快速返回沙盒中Library下Caches文件的路径 219 | */ 220 | + (instancetype)hd_pathForCaches; 221 | 222 | /** 223 | * 快速返回沙盒中,Library下Caches文件中某个子文件的路径 224 | * 225 | * @param fileName 子文件名称 226 | * 227 | * @return 快速返回Caches文件中某个子文件的路径 228 | */ 229 | + (instancetype)hd_filePathAtCachesWithFileName:(NSString *)fileName; 230 | 231 | /** 232 | * 快速返回沙盒中,MainBundle(资源捆绑包的)的路径 233 | * 234 | * @return 快速返回MainBundle(资源捆绑包的)的路径 235 | */ 236 | + (instancetype)hd_pathForMainBundle; 237 | 238 | /** 239 | * 快速返回沙盒中,MainBundle(资源捆绑包的)中某个子文件的路径 240 | * 241 | * @param fileName 子文件名称 242 | * 243 | * @return 快速返回MainBundle(资源捆绑包的)中某个子文件的路径 244 | */ 245 | + (instancetype)hd_filePathAtMainBundleWithFileName:(NSString *)fileName; 246 | 247 | /** 248 | * 快速返回沙盒中,tmp(临时文件)文件的路径 249 | * 250 | * @return 快速返回沙盒中tmp文件的路径 251 | */ 252 | + (instancetype)hd_pathForTemp; 253 | 254 | /** 255 | * 快速返回沙盒中,temp文件中某个子文件的路径 256 | * 257 | * @param fileName 子文件名 258 | * 259 | * @return 快速返回temp文件中某个子文件的路径 260 | */ 261 | + (instancetype)hd_filePathAtTempWithFileName:(NSString *)fileName; 262 | 263 | /** 264 | * 快速返回沙盒中,Library下Preferences文件的路径 265 | * 266 | * @return 快速返回沙盒中Library下Caches文件的路径 267 | */ 268 | + (instancetype)hd_pathForPreferences; 269 | 270 | /** 271 | * 快速返回沙盒中,Library下Preferences文件中某个子文件的路径 272 | * 273 | * @param fileName 子文件名称 274 | * 275 | * @return 快速返回Preferences文件中某个子文件的路径 276 | */ 277 | + (instancetype)hd_filePathAtPreferencesWithFileName:(NSString *)fileName; 278 | 279 | /** 280 | * 快速返回沙盒中,你指定的系统文件的路径。tmp文件除外,tmp用系统的NSTemporaryDirectory()函数更加便捷 281 | * 282 | * @param directory NSSearchPathDirectory枚举 283 | * 284 | * @return 快速你指定的系统文件的路径 285 | */ 286 | + (instancetype)hd_pathForSystemFile:(NSSearchPathDirectory)directory; 287 | 288 | /** 289 | * 快速返回沙盒中,你指定的系统文件的中某个子文件的路径。tmp文件除外,请使用filePathAtTempWithFileName 290 | * 291 | * @param directory 你指的的系统文件 292 | * @param fileName 子文件名 293 | * 294 | * @return 快速返回沙盒中,你指定的系统文件的中某个子文件的路径 295 | */ 296 | + (instancetype)hd_filePathForSystemFile:(NSSearchPathDirectory)directory withFileName:(NSString *)fileName; 297 | 298 | #pragma mark - 文本计算方法 299 | /** 300 | * 计算文字大小 301 | * 302 | * @param font 字体 303 | * @param size 计算范围的大小 304 | * @param mode 段落样式 305 | * 306 | * @return 计算出来的大小 307 | */ 308 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode; 309 | 310 | /** 311 | 计算字符串高度 312 | 313 | @param font 字体 314 | @param size 限制大小 315 | @param mode 计算的换行模型 316 | @param numberOfLine 限制计算高度的行数 317 | @return 返回计算大小 318 | */ 319 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode numberOfLine:(NSInteger)numberOfLine; 320 | 321 | /** 322 | * 计算文字大小 323 | * 324 | * @param font 字体 325 | * @param size 计算范围的大小 326 | * 327 | * @return 计算出来的大小 328 | */ 329 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size; 330 | 331 | /** 332 | * 计算文字大小 333 | * 334 | * @param text 文字 335 | * @param font 字体 336 | * @param size 计算范围的大小 337 | * 338 | * @return 计算出来的大小 339 | */ 340 | + (CGSize)hd_sizeWithText:(NSString *)text systemFont:(UIFont *)font constrainedToSize:(CGSize)size; 341 | 342 | /** 343 | 计算粗体文字大小 344 | 345 | @param font 字体 346 | @param size 计算范围的大小 347 | @param mode 计算的换行模型 348 | @return 计算出来的大小 349 | */ 350 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode; 351 | 352 | /** 353 | 计算粗体文字大小 354 | 355 | @param font 字体 356 | @param size 计算范围的大小 357 | @return 计算出来的大小 358 | */ 359 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size; 360 | 361 | /** 362 | 计算粗体文字大小 363 | 364 | @param font 字体 365 | @param size 计算范围的大小 366 | @param mode 计算的换行模型 367 | @param numberOfLine 限制计算高度的行数 368 | @return 计算出来的大小 369 | */ 370 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode numberOfLine:(NSInteger)numberOfLine; 371 | 372 | 373 | #pragma mark - 富文本相关 374 | /** 375 | 转变成富文本 376 | 377 | @param lineSpacing 行间距 378 | @param kern 文字间的间距 379 | @param lineBreakMode 换行方式 380 | @param alignment 文字对齐格式 381 | @return 转变后的富文本 382 | */ 383 | - (NSAttributedString *)hd_conversionToAttributedStringWithLineSpeace:(CGFloat)lineSpacing kern:(CGFloat)kern lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment; 384 | 385 | /** 386 | 计算富文本字体大小 387 | 388 | @param lineSpeace 行间距 389 | @param kern 文字间的间距 390 | @param font 字体 391 | @param size 计算范围 392 | @param lineBreakMode 换行方式 393 | @param alignment 文字对齐格式 394 | @return 计算后的字体大小 395 | */ 396 | - (CGSize)hd_sizeWithAttributedStringLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment; 397 | 398 | /** 399 | 计算富文本字体大小 400 | 401 | @param lineSpeace 行间距 402 | @param kern 文字间的间距 403 | @param font 字体 404 | @param size 计算范围 405 | @param lineBreakMode 换行方式 406 | @param alignment 文字对齐格式 407 | @param numberOfLine 限制计算行数 408 | @return 计算后的字体大小 409 | */ 410 | - (CGSize)hd_sizeWithAttributedStringLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment numberOfLine:(NSInteger)numberOfLine; 411 | 412 | /** 413 | 是否是一行高度 414 | 415 | @param lineSpeace 行间距 416 | @param kern 文字间的间距 417 | @param font 字体 418 | @param size 计算范围 419 | @param lineBreakMode 换行方式 420 | @param alignment 文字对齐格式 421 | @return 返回YES代表1行, NO代表多行 422 | */ 423 | - (BOOL)hd_numberOfLineWithLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment; 424 | 425 | #pragma mark - 设备相关 426 | /** 427 | * 设备版本 428 | */ 429 | + (instancetype)hd_deviceVersion; 430 | 431 | /** 432 | * 设备类型(用于区分iPhone屏幕大小) 433 | */ 434 | HD_EXTERN NSString *const iPhone6_6s_7_8; 435 | HD_EXTERN NSString *const iPhone6_6s_7_8Plus; 436 | HD_EXTERN NSString *const iPhone_X; 437 | + (instancetype)hd_deviceType; 438 | 439 | 440 | #pragma mark - 效验相关 441 | /** 442 | * 判断是否是邮箱 443 | */ 444 | - (BOOL)hd_isValidEmail; 445 | 446 | /** 447 | * 判断是否是中文 448 | */ 449 | - (BOOL)hd_isChinese; 450 | 451 | /** 452 | * 判断是不是url地址 453 | */ 454 | - (BOOL)hd_isValidUrl; 455 | 456 | /** 457 | * 验证是否是手机号 458 | */ 459 | - (BOOL)hd_isValidateMobile; 460 | 461 | 462 | #pragma mark - 限制相关 463 | /** 464 | 限制字符串长度 465 | 466 | @param length 限制的长度 467 | */ 468 | - (instancetype)hd_limitLength:(NSInteger)length; 469 | 470 | /** 471 | 字符串长度 472 | 473 | @return 返回字符串长度 474 | */ 475 | - (NSUInteger)hd_length; 476 | 477 | /** 478 | 字符串截串 479 | 480 | @param maxLength 最大长度 481 | @return 返回截取到最大长度的字符串 482 | */ 483 | - (instancetype)hd_substringMaxLength:(NSUInteger)maxLength; 484 | 485 | @end 486 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/HDAlertView/NSString+HDExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+HDExtension.m 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/5/10. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | #import "NSString+HDExtension.h" 10 | #import "sys/utsname.h" 11 | #import 12 | 13 | @implementation NSString (HDExtension) 14 | 15 | 16 | #pragma mark - 散列函数 17 | - (instancetype)hd_md5String { 18 | const char *str = self.UTF8String; 19 | uint8_t buffer[CC_MD5_DIGEST_LENGTH]; 20 | 21 | CC_MD5(str, (CC_LONG)strlen(str), buffer); 22 | 23 | return [self hd_stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; 24 | } 25 | 26 | - (instancetype)hd_sha1String { 27 | const char *str = self.UTF8String; 28 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; 29 | 30 | CC_SHA1(str, (CC_LONG)strlen(str), buffer); 31 | 32 | return [self hd_stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; 33 | } 34 | 35 | - (instancetype)hd_sha224String { 36 | const char *str = self.UTF8String; 37 | uint8_t buffer[CC_SHA224_DIGEST_LENGTH]; 38 | 39 | CC_SHA224(str, (CC_LONG)strlen(str), buffer); 40 | 41 | return [self hd_stringFromBytes:buffer length:CC_SHA224_DIGEST_LENGTH]; 42 | } 43 | 44 | - (instancetype)hd_sha256String { 45 | const char *str = self.UTF8String; 46 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; 47 | 48 | CC_SHA256(str, (CC_LONG)strlen(str), buffer); 49 | 50 | return [self hd_stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; 51 | } 52 | 53 | - (instancetype)hd_sha384String { 54 | const char *str = self.UTF8String; 55 | uint8_t buffer[CC_SHA384_DIGEST_LENGTH]; 56 | 57 | CC_SHA384(str, (CC_LONG)strlen(str), buffer); 58 | 59 | return [self hd_stringFromBytes:buffer length:CC_SHA384_DIGEST_LENGTH]; 60 | } 61 | 62 | - (instancetype)hd_sha512String { 63 | const char *str = self.UTF8String; 64 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; 65 | 66 | CC_SHA512(str, (CC_LONG)strlen(str), buffer); 67 | 68 | return [self hd_stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; 69 | } 70 | 71 | 72 | #pragma mark - HMAC 散列函数 73 | - (instancetype)hd_hmacMD5StringWithKey:(NSString *)key { 74 | const char *keyData = key.UTF8String; 75 | const char *strData = self.UTF8String; 76 | uint8_t buffer[CC_MD5_DIGEST_LENGTH]; 77 | 78 | CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer); 79 | 80 | return [self hd_stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; 81 | } 82 | 83 | - (instancetype)hd_hmacSHA1StringWithKey:(NSString *)key { 84 | const char *keyData = key.UTF8String; 85 | const char *strData = self.UTF8String; 86 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; 87 | 88 | CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer); 89 | 90 | return [self hd_stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; 91 | } 92 | 93 | - (instancetype)hd_hmacSHA256StringWithKey:(NSString *)key { 94 | const char *keyData = key.UTF8String; 95 | const char *strData = self.UTF8String; 96 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; 97 | 98 | CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer); 99 | 100 | return [self hd_stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; 101 | } 102 | 103 | - (instancetype)hd_hmacSHA512StringWithKey:(NSString *)key { 104 | const char *keyData = key.UTF8String; 105 | const char *strData = self.UTF8String; 106 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; 107 | 108 | CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer); 109 | 110 | return [self hd_stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; 111 | } 112 | 113 | 114 | #pragma mark - 文件散列函数 115 | #define FileHashDefaultChunkSizeForReadingData 4096 116 | - (instancetype)hd_fileMD5Hash { 117 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; 118 | if (fp == nil) return nil; 119 | 120 | CC_MD5_CTX hashCtx; 121 | CC_MD5_Init(&hashCtx); 122 | 123 | while (YES) { 124 | @autoreleasepool { 125 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; 126 | 127 | CC_MD5_Update(&hashCtx, data.bytes, (CC_LONG)data.length); 128 | 129 | if (data.length == 0) break; 130 | } 131 | } 132 | [fp closeFile]; 133 | 134 | uint8_t buffer[CC_MD5_DIGEST_LENGTH]; 135 | CC_MD5_Final(buffer, &hashCtx); 136 | 137 | return [self hd_stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]; 138 | } 139 | 140 | - (instancetype)hd_fileSHA1Hash { 141 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; 142 | if (fp == nil) return nil; 143 | 144 | CC_SHA1_CTX hashCtx; 145 | CC_SHA1_Init(&hashCtx); 146 | 147 | while (YES) { 148 | @autoreleasepool { 149 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; 150 | 151 | CC_SHA1_Update(&hashCtx, data.bytes, (CC_LONG)data.length); 152 | 153 | if (data.length == 0) break; 154 | } 155 | } 156 | [fp closeFile]; 157 | 158 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH]; 159 | CC_SHA1_Final(buffer, &hashCtx); 160 | 161 | return [self hd_stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]; 162 | } 163 | 164 | - (instancetype)hd_fileSHA256Hash { 165 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; 166 | if (fp == nil) return nil; 167 | 168 | CC_SHA256_CTX hashCtx; 169 | CC_SHA256_Init(&hashCtx); 170 | 171 | while (YES) { 172 | @autoreleasepool { 173 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; 174 | 175 | CC_SHA256_Update(&hashCtx, data.bytes, (CC_LONG)data.length); 176 | 177 | if (data.length == 0) break; 178 | } 179 | } 180 | [fp closeFile]; 181 | 182 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH]; 183 | CC_SHA256_Final(buffer, &hashCtx); 184 | 185 | return [self hd_stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]; 186 | } 187 | 188 | - (instancetype)hd_fileSHA512Hash { 189 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; 190 | if (fp == nil) return nil; 191 | 192 | CC_SHA512_CTX hashCtx; 193 | CC_SHA512_Init(&hashCtx); 194 | 195 | while (YES) { 196 | @autoreleasepool { 197 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData]; 198 | 199 | CC_SHA512_Update(&hashCtx, data.bytes, (CC_LONG)data.length); 200 | 201 | if (data.length == 0) break; 202 | } 203 | } 204 | [fp closeFile]; 205 | 206 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH]; 207 | CC_SHA512_Final(buffer, &hashCtx); 208 | 209 | return [self hd_stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]; 210 | } 211 | 212 | 213 | #pragma mark - Base64编码 214 | - (instancetype)hd_base64Encode { 215 | NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; 216 | 217 | return [data base64EncodedStringWithOptions:0]; 218 | } 219 | 220 | - (instancetype)hd_base64Decode { 221 | NSData *data = [[NSData alloc] initWithBase64EncodedString:self options:0]; 222 | 223 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 224 | } 225 | 226 | 227 | #pragma mark - 路径方法 228 | + (instancetype)hd_pathForDocuments { 229 | return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 230 | } 231 | 232 | + (instancetype)hd_filePathAtDocumentsWithFileName:(NSString *)fileName { 233 | return [[self hd_pathForDocuments] stringByAppendingPathComponent:fileName]; 234 | } 235 | 236 | + (instancetype)hd_pathForCaches { 237 | return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 238 | } 239 | 240 | + (instancetype)hd_filePathAtCachesWithFileName:(NSString *)fileName { 241 | return [[self hd_pathForCaches] stringByAppendingPathComponent:fileName]; 242 | } 243 | 244 | + (instancetype)hd_pathForMainBundle { 245 | return [NSBundle mainBundle].bundlePath; 246 | } 247 | 248 | + (instancetype)hd_filePathAtMainBundleWithFileName:(NSString *)fileName { 249 | return [[self hd_pathForMainBundle] stringByAppendingPathComponent:fileName]; 250 | } 251 | 252 | + (instancetype)hd_pathForTemp { 253 | return NSTemporaryDirectory(); 254 | } 255 | 256 | + (instancetype)hd_filePathAtTempWithFileName:(NSString *)fileName { 257 | return [[self hd_pathForTemp] stringByAppendingPathComponent:fileName]; 258 | } 259 | 260 | + (instancetype)hd_pathForPreferences { 261 | return [NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES) lastObject]; 262 | } 263 | 264 | + (instancetype)hd_filePathAtPreferencesWithFileName:(NSString *)fileName { 265 | return [[self hd_pathForPreferences] stringByAppendingPathComponent:fileName]; 266 | } 267 | 268 | + (instancetype)hd_pathForSystemFile:(NSSearchPathDirectory)directory { 269 | return [NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES) lastObject]; 270 | } 271 | 272 | + (instancetype)hd_filePathForSystemFile:(NSSearchPathDirectory)directory withFileName:(NSString *)fileName { 273 | return [[self hd_pathForSystemFile:directory] stringByAppendingPathComponent:fileName]; 274 | } 275 | 276 | 277 | #pragma mark - 文本计算方法 278 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode { 279 | NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; 280 | paragraphStyle.lineBreakMode = mode; 281 | paragraphStyle.alignment = NSTextAlignmentLeft; 282 | 283 | NSDictionary *attributes = @{NSFontAttributeName : font, 284 | NSParagraphStyleAttributeName : paragraphStyle}; 285 | CGRect rect = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil]; 286 | return CGSizeMake(ceil(rect.size.width), ceil(rect.size.height)); 287 | } 288 | 289 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode numberOfLine:(NSInteger)numberOfLine { 290 | CGSize maxSize = [self hd_sizeWithSystemFont:font constrainedToSize:size lineBreakMode:mode]; 291 | CGFloat oneLineHeight = [self hd_sizeWithSystemFont:font constrainedToSize:CGSizeMake(size.width, font.lineHeight) lineBreakMode:NSLineBreakByTruncatingTail].height; 292 | CGFloat height = 0; 293 | CGFloat limitHeight = oneLineHeight * numberOfLine; 294 | 295 | if (maxSize.height > limitHeight) { 296 | height = limitHeight; 297 | } else { 298 | height = maxSize.height; 299 | } 300 | 301 | return CGSizeMake(maxSize.width, height); 302 | } 303 | 304 | - (CGSize)hd_sizeWithSystemFont:(UIFont *)font constrainedToSize:(CGSize)size { 305 | return [self hd_sizeWithSystemFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping]; 306 | } 307 | 308 | + (CGSize)hd_sizeWithText:(NSString *)text systemFont:(UIFont *)font constrainedToSize:(CGSize)size { 309 | return [text hd_sizeWithSystemFont:font constrainedToSize:size]; 310 | } 311 | 312 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode { 313 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 314 | paragraphStyle.lineBreakMode = mode; 315 | paragraphStyle.alignment = NSTextAlignmentLeft; 316 | NSDictionary *attributes = @{NSFontAttributeName: font, 317 | NSParagraphStyleAttributeName: paragraphStyle}; 318 | 319 | CGRect rect = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil]; 320 | return CGSizeMake(ceil(rect.size.width), ceil(rect.size.height)); 321 | } 322 | 323 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size { 324 | return [self hd_sizeWithBoldFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping]; 325 | } 326 | 327 | - (CGSize)hd_sizeWithBoldFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)mode numberOfLine:(NSInteger)numberOfLine { 328 | CGSize maxSize = [self hd_sizeWithBoldFont:font constrainedToSize:size lineBreakMode:mode]; 329 | CGFloat oneLineHeight = [self hd_sizeWithBoldFont:font constrainedToSize:CGSizeMake(size.width, font.lineHeight) lineBreakMode:NSLineBreakByTruncatingTail].height; 330 | CGFloat height = 0; 331 | CGFloat limitHeight = oneLineHeight * numberOfLine; 332 | 333 | if (maxSize.height > limitHeight) { 334 | height = limitHeight; 335 | } else { 336 | height = maxSize.height; 337 | } 338 | 339 | return CGSizeMake(maxSize.width, height); 340 | } 341 | 342 | 343 | #pragma mark - 富文本相关 344 | - (NSAttributedString *)hd_conversionToAttributedStringWithLineSpeace:(CGFloat)lineSpacing kern:(CGFloat)kern lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment { 345 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 346 | paragraphStyle.lineSpacing = lineSpacing; 347 | paragraphStyle.lineBreakMode = lineBreakMode; 348 | paragraphStyle.alignment = alignment; 349 | 350 | NSDictionary *attributes = @{NSParagraphStyleAttributeName:paragraphStyle, 351 | NSKernAttributeName:@(kern)}; 352 | 353 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self attributes:attributes]; 354 | 355 | return attributedString; 356 | } 357 | 358 | - (CGSize)hd_sizeWithAttributedStringLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment { 359 | if (font == nil) { 360 | HDAssert(!HDObjectIsEmpty(font), @"font不能为空"); 361 | return CGSizeMake(0, 0); 362 | } 363 | 364 | NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init]; 365 | paraStyle.lineSpacing = lineSpeace; 366 | paraStyle.lineBreakMode = lineBreakMode; 367 | paraStyle.alignment = alignment; 368 | 369 | NSDictionary *dic = @{NSFontAttributeName:font, 370 | NSParagraphStyleAttributeName:paraStyle, 371 | NSKernAttributeName:@(kern)}; 372 | CGRect rect = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil]; 373 | return CGSizeMake(ceil(rect.size.width), ceil(rect.size.height)); 374 | } 375 | 376 | - (CGSize)hd_sizeWithAttributedStringLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment numberOfLine:(NSInteger)numberOfLine { 377 | CGSize maxSize = [self hd_sizeWithAttributedStringLineSpeace:lineSpeace kern:kern font:font size:size lineBreakMode:lineBreakMode alignment:alignment]; 378 | CGFloat oneLineHeight = [self hd_sizeWithAttributedStringLineSpeace:lineSpeace kern:kern font:font size:CGSizeMake(size.width, font.lineHeight) lineBreakMode:NSLineBreakByTruncatingTail alignment:alignment].height; 379 | CGFloat height = 0; 380 | CGFloat limitHeight = oneLineHeight * numberOfLine; 381 | 382 | if (maxSize.height > limitHeight) { 383 | height = limitHeight; 384 | } else { 385 | height = maxSize.height; 386 | } 387 | 388 | return CGSizeMake(maxSize.width, height); 389 | } 390 | 391 | - (BOOL)hd_numberOfLineWithLineSpeace:(CGFloat)lineSpeace kern:(CGFloat)kern font:(UIFont *)font size:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment { 392 | CGFloat oneHeight = [self hd_sizeWithAttributedStringLineSpeace:lineSpeace kern:kern font:font size:CGSizeMake(size.width, font.lineHeight) lineBreakMode:NSLineBreakByTruncatingTail alignment:alignment].height; 393 | CGFloat maxHeight = [self hd_sizeWithAttributedStringLineSpeace:lineSpeace kern:kern font:font size:size lineBreakMode:lineBreakMode alignment:alignment].height; 394 | 395 | if (maxHeight > oneHeight) { 396 | return NO; 397 | } 398 | 399 | return YES; 400 | } 401 | 402 | 403 | #pragma mark - 设备相关 404 | /** 405 | * 设备版本 406 | */ 407 | + (instancetype)hd_deviceVersion { 408 | // 需要#import "sys/utsname.h" 409 | struct utsname systemInfo; 410 | uname(&systemInfo); 411 | NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; 412 | 413 | // iPhone 414 | if ([deviceString isEqualToString:@"iPhone1,1"]) return @"iPhone 1G"; 415 | if ([deviceString isEqualToString:@"iPhone1,2"]) return @"iPhone 3G"; 416 | if ([deviceString isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS"; 417 | if ([deviceString isEqualToString:@"iPhone3,1"]) return @"iPhone 4"; 418 | if ([deviceString isEqualToString:@"iPhone3,2"]) return @"Verizon iPhone 4"; 419 | if ([deviceString isEqualToString:@"iPhone4,1"]) return @"iPhone 4S"; 420 | if ([deviceString isEqualToString:@"iPhone5,1"]) return @"iPhone 5"; 421 | if ([deviceString isEqualToString:@"iPhone5,2"]) return @"iPhone 5"; 422 | if ([deviceString isEqualToString:@"iPhone5,3"]) return @"iPhone 5C"; 423 | if ([deviceString isEqualToString:@"iPhone5,4"]) return @"iPhone 5C"; 424 | if ([deviceString isEqualToString:@"iPhone6,1"]) return @"iPhone 5S"; 425 | if ([deviceString isEqualToString:@"iPhone6,2"]) return @"iPhone 5S"; 426 | if ([deviceString isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus"; 427 | if ([deviceString isEqualToString:@"iPhone7,2"]) return @"iPhone 6"; 428 | if ([deviceString isEqualToString:@"iPhone8,1"]) return @"iPhone 6s"; 429 | if ([deviceString isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus"; 430 | if ([deviceString isEqualToString:@"iPhone9,1"]) return @"iPhone 7"; 431 | if ([deviceString isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus"; 432 | if ([deviceString isEqualToString:@"iPhone9,3"]) return @"iPhone 7"; 433 | if ([deviceString isEqualToString:@"iPhone9,4"]) return @"iPhone 7 Plus"; 434 | 435 | // iPod 436 | if ([deviceString isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G"; 437 | if ([deviceString isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G"; 438 | if ([deviceString isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G"; 439 | if ([deviceString isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G"; 440 | if ([deviceString isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G"; 441 | 442 | // iPad 443 | if ([deviceString isEqualToString:@"iPad1,1"]) return @"iPad"; 444 | if ([deviceString isEqualToString:@"iPad2,1"]) return @"iPad 2 (WiFi)"; 445 | if ([deviceString isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)"; 446 | if ([deviceString isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)"; 447 | if ([deviceString isEqualToString:@"iPad2,4"]) return @"iPad 2 (32nm)"; 448 | if ([deviceString isEqualToString:@"iPad2,5"]) return @"iPad mini (WiFi)"; 449 | if ([deviceString isEqualToString:@"iPad2,6"]) return @"iPad mini (GSM)"; 450 | if ([deviceString isEqualToString:@"iPad2,7"]) return @"iPad mini (CDMA)"; 451 | 452 | if ([deviceString isEqualToString:@"iPad3,1"]) return @"iPad 3(WiFi)"; 453 | if ([deviceString isEqualToString:@"iPad3,2"]) return @"iPad 3(CDMA)"; 454 | if ([deviceString isEqualToString:@"iPad3,3"]) return @"iPad 3(4G)"; 455 | if ([deviceString isEqualToString:@"iPad3,4"]) return @"iPad 4 (WiFi)"; 456 | if ([deviceString isEqualToString:@"iPad3,5"]) return @"iPad 4 (4G)"; 457 | if ([deviceString isEqualToString:@"iPad3,6"]) return @"iPad 4 (CDMA)"; 458 | 459 | if ([deviceString isEqualToString:@"iPad4,1"]) return @"iPad Air"; 460 | if ([deviceString isEqualToString:@"iPad4,2"]) return @"iPad Air"; 461 | if ([deviceString isEqualToString:@"iPad4,3"]) return @"iPad Air"; 462 | if ([deviceString isEqualToString:@"iPad5,3"]) return @"iPad Air 2"; 463 | if ([deviceString isEqualToString:@"iPad5,4"]) return @"iPad Air 2"; 464 | if ([deviceString isEqualToString:@"i386"]) return @"Simulator"; 465 | if ([deviceString isEqualToString:@"x86_64"]) return @"Simulator"; 466 | 467 | if ([deviceString isEqualToString:@"iPad4,4"] 468 | ||[deviceString isEqualToString:@"iPad4,5"] 469 | ||[deviceString isEqualToString:@"iPad4,6"]) return @"iPad mini 2"; 470 | 471 | if ([deviceString isEqualToString:@"iPad4,7"] 472 | ||[deviceString isEqualToString:@"iPad4,8"] 473 | ||[deviceString isEqualToString:@"iPad4,9"]) return @"iPad mini 3"; 474 | 475 | return deviceString; 476 | } 477 | 478 | 479 | NSString *const iPhone6_6s_7_8 = @"iPhone6_6s_7_8"; 480 | NSString *const iPhone6_6s_7_8Plus = @"iPhone6_6s_7_8Plus"; 481 | NSString *const iPhone_X = @"iPhone_X"; 482 | 483 | + (instancetype)hd_deviceType { 484 | struct utsname systemInfo; 485 | uname(&systemInfo); 486 | NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; 487 | 488 | // iPhone 489 | if ([deviceString isEqualToString:@"iPhone7,1"]) return iPhone6_6s_7_8Plus; 490 | if ([deviceString isEqualToString:@"iPhone7,2"]) return iPhone6_6s_7_8; 491 | if ([deviceString isEqualToString:@"iPhone8,1"]) return iPhone6_6s_7_8; 492 | if ([deviceString isEqualToString:@"iPhone8,2"]) return iPhone6_6s_7_8Plus; 493 | if ([deviceString isEqualToString:@"iPhone9,1"]) return iPhone6_6s_7_8; 494 | if ([deviceString isEqualToString:@"iPhone9,2"]) return iPhone6_6s_7_8Plus; 495 | if ([deviceString isEqualToString:@"iPhone9,3"]) return iPhone6_6s_7_8; 496 | if ([deviceString isEqualToString:@"iPhone9,4"]) return iPhone6_6s_7_8Plus; 497 | if ([deviceString isEqualToString:@"iPhone10,1"]) return iPhone6_6s_7_8; 498 | if ([deviceString isEqualToString:@"iPhone10,4"]) return iPhone6_6s_7_8; 499 | if ([deviceString isEqualToString:@"iPhone10,2"]) return iPhone6_6s_7_8Plus; 500 | if ([deviceString isEqualToString:@"iPhone10,5"]) return iPhone6_6s_7_8Plus; 501 | if ([deviceString isEqualToString:@"iPhone10,3"]) return iPhone_X; 502 | if ([deviceString isEqualToString:@"iPhone10,6"]) return iPhone_X; 503 | 504 | return deviceString; 505 | } 506 | 507 | 508 | #pragma mark - 效验相关 509 | - (BOOL)hd_isValidEmail { 510 | NSString *emailRegex = @"((?]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^;&*+?:_/=<>]*)?)"; 525 | NSPredicate *urlTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; 526 | return [urlTest evaluateWithObject:self]; 527 | } 528 | 529 | - (BOOL)hd_isValidateMobile { 530 | if (self.length < 1) { 531 | return NO; 532 | } 533 | 534 | return YES; // 现在新增手机号段很多_国际别的手机不一定11位_手机号其实没必要限制死! 535 | } 536 | 537 | 538 | #pragma mark - 限制相关 539 | - (instancetype)hd_limitLength:(NSInteger)length { 540 | NSString *str = self; 541 | if (str.length > length) { 542 | str = [str substringToIndex:length]; 543 | } 544 | 545 | return str; 546 | } 547 | 548 | - (NSUInteger)hd_length { 549 | float number = 0.0; 550 | 551 | for (int i = 0; i < self.length; i++) { 552 | NSString *character = [self substringWithRange:NSMakeRange(i, 1)]; 553 | 554 | if ([character lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 3) { 555 | number++; 556 | } else { 557 | number = number + 0.5; 558 | } 559 | } 560 | 561 | return ceil(number); 562 | } 563 | 564 | - (instancetype)hd_substringMaxLength:(NSUInteger)maxLength { 565 | NSMutableString *ret = [[NSMutableString alloc] init]; 566 | float number = 0.0; 567 | 568 | for (int i = 0; i < self.length; i++) { 569 | NSString *character = [self substringWithRange:NSMakeRange(i, 1)]; 570 | 571 | if ([character lengthOfBytesUsingEncoding:NSUTF8StringEncoding] == 3) { 572 | number++; 573 | } else { 574 | number = number + 0.5; 575 | } 576 | 577 | if (number <= maxLength) { 578 | [ret appendString:character]; 579 | } else { 580 | break; 581 | } 582 | } 583 | 584 | return [ret copy]; 585 | } 586 | 587 | 588 | #pragma mark - 其他 589 | /** 590 | * 返回二进制 Bytes 流的字符串表示形式 591 | * 592 | * @param bytes 二进制 Bytes 数组 593 | * @param length 数组长度 594 | * 595 | * @return 字符串表示形式 596 | */ 597 | - (instancetype)hd_stringFromBytes:(uint8_t *)bytes length:(int)length { 598 | NSMutableString *strM = [NSMutableString string]; 599 | 600 | for (int i = 0; i < length; i++) { 601 | [strM appendFormat:@"%02x", bytes[i]]; 602 | } 603 | 604 | return [strM copy]; 605 | } 606 | 607 | @end 608 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/HDAlertView/UIImage+HDExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+HDExtension.h 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/1/17. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (HDExtension) 12 | 13 | /** 14 | * 拉伸图片 15 | * 16 | * @param name 图片名字 17 | * 18 | * @return 拉伸好的图片 19 | */ 20 | + (instancetype)hd_resizedImageWithImageName:(NSString *)name; 21 | 22 | /** 23 | * 拉伸图片 24 | * 25 | * @param image 要拉伸的图片 26 | * 27 | * @return 拉伸好的图片 28 | */ 29 | + (instancetype)hd_resizedImageWithImage:(UIImage *)image; 30 | 31 | /** 32 | * 返回一个缩放好的图片 33 | * 34 | * @param image 要切割的图片 35 | * @param imageSize 边框的宽度 36 | * 37 | * @return 切割好的图片 38 | */ 39 | + (instancetype)hd_cutImage:(UIImage*)image andSize:(CGSize)imageSize; 40 | 41 | /** 42 | * 返回一个下边有半个红圈的原型头像 43 | * 44 | * @param image 要切割的图片 45 | * 46 | * @return 切割好的头像 47 | */ 48 | + (instancetype)hd_captureCircleImage:(UIImage*)image; 49 | 50 | /** 51 | * 根据url返回一个圆形的头像 52 | * 53 | * @param iconUrl 头像的URL 54 | * @param border 边框的宽度 55 | * @param color 边框的颜色 56 | * 57 | * @return 切割好的头像 58 | */ 59 | + (instancetype)hd_captureCircleImageWithURL:(NSString *)iconUrl andBorderWith:(CGFloat)border andBorderColor:(UIColor *)color; 60 | 61 | /** 62 | * 根据iamge返回一个圆形的头像 63 | * 64 | * @param iconImage 要切割的头像 65 | * @param border 边框的宽度 66 | * @param color 边框的颜色 67 | * 68 | * @return 切割好的头像 69 | */ 70 | + (instancetype)hd_captureCircleImageWithImage:(UIImage *)iconImage andBorderWith:(CGFloat)border andBorderColor:(UIColor *)color; 71 | 72 | /** 73 | * 生成毛玻璃效果的图片 74 | * 75 | * @param image 要模糊化的图片 76 | * @param blurAmount 模糊化指数 77 | * 78 | * @return 返回模糊化之后的图片 79 | */ 80 | + (instancetype)hd_blurredImageWithImage:(UIImage *)image andBlurAmount:(CGFloat)blurAmount; 81 | 82 | /** 83 | * 截取对应的view生成一张图片 84 | * 85 | * @param view 要截的view 86 | * 87 | * @return 生成的图片 88 | */ 89 | + (instancetype)hd_viewShotWithView:(UIView *)view; 90 | 91 | /** 92 | * 截屏 93 | * 94 | * @return 返回截屏的图片 95 | */ 96 | + (instancetype)hd_screenShot; 97 | 98 | /** 99 | * 给图片添加水印 100 | * 101 | * @param bgName 原图的名字 102 | * @param waterImageName 水印的名字 103 | * 104 | * @return 添加完水印的图片 105 | */ 106 | + (instancetype)hd_waterImageWithBgImageName:(NSString *)bgName andWaterImageName:(NSString *)waterImageName ; 107 | 108 | /** 109 | * 图片进行压缩 110 | * 111 | * @param image 要压缩的图片 112 | * @param percent 要压缩的比例(建议在0.3以上) 113 | * 114 | * @return 压缩之后的图片 115 | * 116 | * @exception 压缩之后为image/jpeg 格式 117 | */ 118 | + (instancetype)hd_reduceImage:(UIImage *)image percent:(CGFloat)percent; 119 | 120 | /** 121 | * 对图片进行压缩 122 | * 123 | * @param image 要压缩的图片 124 | * @param newSize 压缩后的图片的像素尺寸 125 | * 126 | * @return 压缩好的图片 127 | */ 128 | + (instancetype)hd_imageWithImageSimple:(UIImage *)image scaledToSize:(CGSize)newSize; 129 | 130 | /** 131 | * 对图片进行压缩 132 | * 133 | * @param image 要压缩的图片 134 | * @param newSize 压缩后的图片的像素尺寸 135 | * 136 | * @return 压缩好的图片 137 | */ 138 | + (instancetype)hd_imageWithDataSimple:(NSData *)imageData scaledToSize:(CGSize)newSize; 139 | 140 | /** 141 | * 生成了一个毛玻璃效果的图片 142 | * 143 | * @return 返回模糊化好的图片 144 | */ 145 | - (instancetype)hd_blurredImage:(CGFloat)blurAmount; 146 | 147 | /** 148 | * 生成一个毛玻璃效果的图片 149 | * 150 | * @param blurLevel 毛玻璃的模糊程度 151 | * 152 | * @return 毛玻璃好的图片 153 | */ 154 | - (instancetype)hd_blearImageWithBlurLevel:(CGFloat)blurLevel; 155 | 156 | /** 157 | * 根据颜色返回图片 158 | * 159 | * @param color 颜色 160 | * 161 | * @return 图片 162 | */ 163 | + (instancetype)hd_imageWithColor:(UIColor *)color; 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/HDAlertView/UIImage+HDExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+HDExtension.m 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 15/1/17. 6 | // Copyright © 2015年 hedong. All rights reserved. 7 | // 8 | 9 | #import "UIImage+HDExtension.h" 10 | #import 11 | #import 12 | 13 | @implementation UIImage (HDExtension) 14 | 15 | + (instancetype)hd_resizedImageWithImageName:(NSString *)name { 16 | return [self hd_resizedImageWithImage:[UIImage imageNamed:name]]; 17 | } 18 | 19 | + (instancetype)hd_resizedImageWithImage:(UIImage *)image { 20 | return [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5]; 21 | } 22 | 23 | + (instancetype)hd_cutImage:(UIImage*)image andSize:(CGSize)newImageSize { 24 | UIGraphicsBeginImageContextWithOptions(newImageSize, NO, 0.0); 25 | [image drawInRect:CGRectMake(0, 0, newImageSize.width, newImageSize.height)]; 26 | // 从上下文中取出图片 27 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 28 | UIGraphicsEndImageContext(); 29 | 30 | return newImage; 31 | } 32 | 33 | + (instancetype)hd_captureCircleImage:(UIImage *)image { 34 | CGFloat imageW = image.size.width; 35 | CGFloat imageH = image.size.height; 36 | imageW = MIN(imageH, imageW); 37 | imageH = imageW; 38 | 39 | CGFloat border = imageW / 100 * 2; 40 | CGSize imageSize = CGSizeMake(imageW, imageH); 41 | CGFloat radius = imageSize.width * 0.5; 42 | 43 | CGSize graphicSize = CGSizeMake(imageSize.width + 2 * border, imageSize.height + 2 * border); 44 | UIGraphicsBeginImageContextWithOptions(graphicSize, NO, 0.0); 45 | 46 | // 灰色边框 47 | [[UIColor darkGrayColor] setFill]; 48 | CGContextRef context=UIGraphicsGetCurrentContext(); 49 | CGContextAddArc(context,graphicSize.width * 0.5, graphicSize.height * 0.5, radius+border, -M_PI, M_PI, 0); 50 | CGContextFillPath(context); 51 | 52 | // 红色边框 53 | [[UIColor colorWithRed:247 / 255.0 green:98 / 255.0 blue:46 / 255.0 alpha:1.0] setFill]; 54 | CGContextAddArc(context, graphicSize.width * 0.5, graphicSize.height * 0.5, radius + border, -M_PI * 1.35, M_PI * 0.35, 1); 55 | CGContextFillPath(context); 56 | 57 | UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(graphicSize.width * 0.5, graphicSize.height * 0.5) radius:radius startAngle:-M_PI endAngle:M_PI clockwise:YES]; 58 | [path addClip]; 59 | 60 | CGRect imageFrame = CGRectMake(border, border, imageSize.width, imageSize.height); 61 | [image drawInRect:imageFrame]; 62 | UIImage *finishImage = UIGraphicsGetImageFromCurrentImageContext(); 63 | UIGraphicsEndImageContext(); 64 | 65 | return finishImage; 66 | } 67 | 68 | + (instancetype)hd_captureCircleImageWithURL:(NSString *)iconUrl andBorderWith:(CGFloat)border andBorderColor:(UIColor *)color { 69 | return [self hd_captureCircleImageWithImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:iconUrl]]] andBorderWith:border andBorderColor:color]; 70 | } 71 | 72 | + (instancetype)hd_captureCircleImageWithImage:(UIImage *)iconImage andBorderWith:(CGFloat)border andBorderColor:(UIColor *)color { 73 | CGFloat imageW = iconImage.size.width + border * 2; 74 | CGFloat imageH = iconImage.size.height + border * 2; 75 | imageW = MIN(imageH, imageW); 76 | imageH = imageW; 77 | CGSize imageSize = CGSizeMake(imageW, imageH); 78 | // 新建一个图形上下文 79 | UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0); 80 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 81 | [color set]; 82 | // 画大圆 83 | CGFloat bigRadius = imageW * 0.5; 84 | CGFloat centerX = imageW * 0.5; 85 | CGFloat centerY = imageH * 0.5; 86 | CGContextAddArc(ctx, centerX, centerY, bigRadius, 0, M_PI * 2, 0); 87 | CGContextFillPath(ctx); 88 | // 画小圆 89 | CGFloat smallRadius = bigRadius - border; 90 | CGContextAddArc(ctx , centerX , centerY , smallRadius ,0, M_PI * 2, 0); 91 | // 切割 92 | CGContextClip(ctx); 93 | // 画图片 94 | [iconImage drawInRect:CGRectMake(border, border, iconImage.size.width, iconImage.size.height)]; 95 | //从上下文中取出图片 96 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 97 | UIGraphicsEndImageContext(); 98 | 99 | return newImage; 100 | } 101 | 102 | + (instancetype)hd_blurredImageWithImage:(UIImage *)image andBlurAmount:(CGFloat)blurAmount { 103 | return [image hd_blurredImage:blurAmount]; 104 | } 105 | 106 | + (instancetype)hd_viewShotWithView:(UIView *)view { 107 | UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0); 108 | [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 109 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 110 | UIGraphicsEndImageContext(); 111 | 112 | return newImage; 113 | } 114 | 115 | + (instancetype)hd_screenShot { 116 | CGSize imageSize = [[UIScreen mainScreen] bounds].size; 117 | // 开启图形上下文 118 | UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); 119 | CGContextRef context = UIGraphicsGetCurrentContext(); 120 | for (UIWindow *window in [[UIApplication sharedApplication] windows]) { 121 | if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen]) { 122 | CGContextSaveGState(context); 123 | CGContextTranslateCTM(context, [window center].x, [window center].y); 124 | CGContextConcatCTM(context, [window transform]); 125 | CGContextTranslateCTM(context, 126 | -[window bounds].size.width * [[window layer] anchorPoint].x, 127 | -[window bounds].size.height * [[window layer] anchorPoint].y); 128 | [[window layer] renderInContext:context]; 129 | 130 | CGContextRestoreGState(context); 131 | } 132 | } 133 | 134 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 135 | UIGraphicsEndImageContext(); 136 | 137 | return image; 138 | } 139 | 140 | + (instancetype)hd_waterImageWithBgImageName:(NSString *)bgName andWaterImageName:(NSString *)waterImageName { 141 | UIImage *bgImage = [UIImage imageNamed:bgName]; 142 | CGSize imageViewSize = bgImage.size; 143 | 144 | UIGraphicsBeginImageContextWithOptions(imageViewSize, NO, 0.0); 145 | [bgImage drawInRect:CGRectMake(0, 0, imageViewSize.width, imageViewSize.height)]; 146 | 147 | UIImage *waterImage = [UIImage imageNamed:waterImageName]; 148 | CGFloat scale = 0.2; 149 | CGFloat margin = 5; 150 | CGFloat waterW = imageViewSize.width * scale; 151 | CGFloat waterH = imageViewSize.height * scale; 152 | CGFloat waterX = imageViewSize.width - waterW - margin; 153 | CGFloat waterY = imageViewSize.height - waterH - margin; 154 | 155 | [waterImage drawInRect:CGRectMake(waterX, waterY, waterW, waterH)]; 156 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 157 | UIGraphicsEndImageContext(); 158 | 159 | return newImage; 160 | } 161 | 162 | + (instancetype)hd_reduceImage:(UIImage *)image percent:(CGFloat)percent { 163 | NSData *imageData = UIImageJPEGRepresentation(image, percent); 164 | UIImage *newImage = [UIImage imageWithData:imageData]; 165 | 166 | return newImage; 167 | } 168 | 169 | + (instancetype)hd_imageWithImageSimple:(UIImage*)image scaledToSize:(CGSize)newSize { 170 | UIGraphicsBeginImageContext(newSize); 171 | [image drawInRect:CGRectMake(0, 0, newSize.width,newSize.height)]; 172 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 173 | UIGraphicsEndImageContext(); 174 | 175 | return newImage; 176 | } 177 | 178 | + (instancetype)hd_imageWithDataSimple:(NSData *)imageData scaledToSize:(CGSize)newSize { 179 | return [self hd_imageWithImageSimple:[UIImage imageWithData:imageData] scaledToSize:newSize]; 180 | } 181 | 182 | - (instancetype)hd_blurredImage:(CGFloat)blurAmount { 183 | if (blurAmount < 0.0 || blurAmount > 2.0) { 184 | blurAmount = 0.5; 185 | } 186 | 187 | CGImageRef img = self.CGImage; 188 | 189 | vImage_Buffer inBuffer, outBuffer; 190 | vImage_Error error; 191 | 192 | void *pixelBuffer; 193 | 194 | CGDataProviderRef inProvider = CGImageGetDataProvider(img); 195 | CFDataRef inBitmapData = CGDataProviderCopyData(inProvider); 196 | 197 | inBuffer.width = CGImageGetWidth(img); 198 | inBuffer.height = CGImageGetHeight(img); 199 | inBuffer.rowBytes = CGImageGetBytesPerRow(img); 200 | 201 | inBuffer.data = (void *)CFDataGetBytePtr(inBitmapData); 202 | 203 | pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img)); 204 | 205 | outBuffer.data = pixelBuffer; 206 | outBuffer.width = CGImageGetWidth(img); 207 | outBuffer.height = CGImageGetHeight(img); 208 | outBuffer.rowBytes = CGImageGetBytesPerRow(img); 209 | int boxSize = blurAmount * 40; 210 | boxSize = boxSize - (boxSize % 2) + 1; 211 | error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 212 | if (!error) 213 | { 214 | error = vImageBoxConvolve_ARGB8888(&outBuffer, &inBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 215 | } 216 | 217 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 218 | 219 | CGContextRef ctx = CGBitmapContextCreate(outBuffer.data, 220 | outBuffer.width, 221 | outBuffer.height, 222 | 8, 223 | outBuffer.rowBytes, 224 | colorSpace, 225 | (CGBitmapInfo)kCGImageAlphaNoneSkipLast); 226 | 227 | CGImageRef imageRef = CGBitmapContextCreateImage(ctx); 228 | 229 | UIImage *returnImage = [UIImage imageWithCGImage:imageRef]; 230 | 231 | CGContextRelease(ctx); 232 | CGColorSpaceRelease(colorSpace); 233 | 234 | free(pixelBuffer); 235 | CFRelease(inBitmapData); 236 | CGImageRelease(imageRef); 237 | 238 | return returnImage; 239 | } 240 | 241 | - (instancetype)hd_blearImageWithBlurLevel:(CGFloat)blurLevel { 242 | CIContext *context = [CIContext contextWithOptions:nil]; 243 | CIImage *inputImage = [[CIImage alloc] initWithImage:self]; 244 | CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; 245 | [blurFilter setDefaults]; 246 | [blurFilter setValue:inputImage forKey:@"inputImage"]; 247 | // 设值模糊的级别 248 | [blurFilter setValue:[NSNumber numberWithFloat:blurLevel] forKey:@"inputRadius"]; 249 | CIImage *outputImage = [blurFilter valueForKey:@"outputImage"]; 250 | CGRect rect = inputImage.extent; // Create Rect 251 | // 设值一下减到图片的白边 252 | rect.origin.x += blurLevel; 253 | rect.origin.y += blurLevel; 254 | rect.size.height -= blurLevel * 2.0f; 255 | rect.size.width -= blurLevel * 2.0f; 256 | CGImageRef cgImage = [context createCGImage:outputImage fromRect:rect]; 257 | // 获取新的图片 258 | UIImage *newImage = [UIImage imageWithCGImage:cgImage scale:0.5 orientation:self.imageOrientation]; 259 | // 释放图片 260 | CGImageRelease(cgImage); 261 | 262 | return newImage; 263 | } 264 | 265 | + (instancetype)hd_imageWithColor:(UIColor *)color { 266 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 267 | UIGraphicsBeginImageContext(rect.size); 268 | CGContextRef context = UIGraphicsGetCurrentContext(); 269 | CGContextSetFillColorWithColor(context, [color CGColor]); 270 | CGContextFillRect(context, rect); 271 | 272 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); 273 | UIGraphicsEndImageContext(); 274 | 275 | return theImage; 276 | } 277 | 278 | @end 279 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/HDAlertView/UIView+HDExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+HDExtension.h 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 14/12/1. 6 | // Copyright © 2014年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, HDAnimationType) { 12 | HDAnimationOpen, // 动画开启 13 | HDAnimationClose // 动画关闭 14 | }; 15 | 16 | @interface UIView (HDExtension) 17 | 18 | 19 | #pragma mark - 快速设置控件的frame 20 | @property (nonatomic, assign) CGFloat hd_x; 21 | @property (nonatomic, assign) CGFloat hd_y; 22 | @property (nonatomic, assign) CGFloat hd_centerX; 23 | @property (nonatomic, assign) CGFloat hd_centerY; 24 | @property (nonatomic, assign) CGFloat hd_width; 25 | @property (nonatomic, assign) CGFloat hd_height; 26 | @property (nonatomic, assign) CGPoint hd_origin; 27 | @property (nonatomic, assign) CGSize hd_size; 28 | @property (nonatomic, assign) CGFloat hb_right; 29 | @property (nonatomic, assign) CGFloat hb_bottom; 30 | 31 | 32 | #pragma mark - 视图相关 33 | /** 34 | * 移除全部的子视图 35 | */ 36 | - (void)hd_removeAllSubviews; 37 | 38 | #pragma mark - 动画相关 39 | /** 40 | * 在某个点添加动画 41 | * 42 | * @param point 动画开始的点 43 | */ 44 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point; 45 | 46 | /** 47 | * 在某个点添加动画 48 | * 49 | * @param point 动画开始的点 50 | * @param type 动画的类型 51 | * @param color 动画的颜色 52 | */ 53 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithType:(HDAnimationType)type withColor:(UIColor *)animationColor; 54 | 55 | /** 56 | * 在某个点添加动画 57 | * 58 | * @param point 动画开始的点 59 | * @param type 动画的类型 60 | * @param color 动画的颜色 61 | * @param completion 动画结束后的代码快 62 | */ 63 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithType:(HDAnimationType)type withColor:(UIColor *)animationColor completion:(void (^)(BOOL finished))completion; 64 | 65 | /** 66 | * 在某个点添加动画 67 | * 68 | * @param point 动画开始的点 69 | * @param duration 动画时间 70 | * @param type 动画的类型 71 | * @param color 动画的颜色 72 | * @param completion 动画结束后的代码快 73 | */ 74 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithDuration:(NSTimeInterval)duration WithType:(HDAnimationType) type withColor:(UIColor *)animationColor completion:(void (^)(BOOL finished))completion; 75 | 76 | 77 | #pragma UIView变成UIImage 78 | /** 79 | 视图转成图片 80 | 81 | @return 返回图片 82 | */ 83 | - (UIImage *)hd_convertViewToImage; 84 | 85 | /** 86 | 视图裁剪成图片 87 | 88 | @return 返回图片 89 | */ 90 | - (UIImage *)hd_snapsHotView; 91 | 92 | /** 93 | 视图转成图片 94 | 95 | @param view 视图 96 | @return 返回图片 97 | */ 98 | + (UIImage *)hd_convertViewToImage:(UIView *)view; 99 | 100 | /** 101 | 视图裁剪成图片 102 | 103 | @param view 视图 104 | @return 返回图片 105 | */ 106 | + (UIImage *)hd_snapsHotView:(UIView *)view; 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/HDAlertView/UIView+HDExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+HDExtension.m 3 | // PortableTreasure 4 | // 5 | // Created by HeDong on 14/12/1. 6 | // Copyright © 2014年 hedong. All rights reserved. 7 | // 8 | 9 | #import "UIView+HDExtension.h" 10 | 11 | @implementation UIView (HDExtension) 12 | 13 | #pragma mark - 快速设置控件的frame 14 | - (void)setHd_x:(CGFloat)hd_x { 15 | CGRect frame = self.frame; 16 | frame.origin.x = hd_x; 17 | self.frame = frame; 18 | } 19 | 20 | - (CGFloat)hd_x { 21 | return self.frame.origin.x; 22 | } 23 | 24 | - (void)setHd_y:(CGFloat)hd_y { 25 | CGRect frame = self.frame; 26 | frame.origin.y = hd_y; 27 | self.frame = frame; 28 | } 29 | 30 | - (CGFloat)hd_y { 31 | return self.frame.origin.y; 32 | } 33 | 34 | - (void)setHd_centerX:(CGFloat)hd_centerX { 35 | CGPoint center = self.center; 36 | center.x = hd_centerX; 37 | self.center = center; 38 | } 39 | 40 | - (CGFloat)hd_centerX { 41 | return self.center.x; 42 | } 43 | 44 | - (void)setHd_centerY:(CGFloat)hd_centerY { 45 | CGPoint center = self.center; 46 | center.y = hd_centerY; 47 | self.center = center; 48 | } 49 | 50 | - (CGFloat)hd_centerY { 51 | return self.center.y; 52 | } 53 | 54 | - (void)setHd_width:(CGFloat)hd_width { 55 | CGRect frame = self.frame; 56 | frame.size.width = hd_width; 57 | self.frame = frame; 58 | } 59 | 60 | - (CGFloat)hd_width { 61 | return self.frame.size.width; 62 | } 63 | 64 | - (void)setHd_height:(CGFloat)hd_height { 65 | CGRect frame = self.frame; 66 | frame.size.height = hd_height; 67 | self.frame = frame; 68 | } 69 | 70 | - (CGFloat)hd_height { 71 | return self.frame.size.height; 72 | } 73 | 74 | - (void)setHd_size:(CGSize)hd_size { 75 | CGRect frame = self.frame; 76 | frame.size = hd_size; 77 | self.frame = frame; 78 | } 79 | 80 | - (CGSize)hd_size { 81 | return self.frame.size; 82 | } 83 | 84 | - (void)setHd_origin:(CGPoint)hd_origin { 85 | CGRect frame = self.frame; 86 | frame.origin = hd_origin; 87 | self.frame = frame; 88 | } 89 | 90 | - (CGPoint)hd_origin { 91 | return self.frame.origin; 92 | } 93 | 94 | - (void)setHb_right:(CGFloat)right { 95 | CGRect frame = self.frame; 96 | frame.origin.x = right - frame.size.width; 97 | self.frame = frame; 98 | } 99 | 100 | - (CGFloat)hb_right { 101 | return self.frame.origin.x + self.frame.size.width; 102 | } 103 | 104 | - (void)setHb_bottom:(CGFloat)bottom { 105 | CGRect frame = self.frame; 106 | frame.origin.y = bottom - frame.size.height; 107 | self.frame = frame; 108 | } 109 | 110 | - (CGFloat)hb_bottom { 111 | return self.frame.origin.y + self.frame.size.height; 112 | } 113 | 114 | 115 | #pragma mark - 视图相关 116 | - (void)hd_removeAllSubviews { 117 | while (self.subviews.count) { 118 | [self.subviews.lastObject removeFromSuperview]; 119 | } 120 | } 121 | 122 | 123 | #pragma mark - 动画相关 124 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point; { 125 | CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 126 | CGFloat diameter = [self hd_mdShapeDiameterForPoint:point]; 127 | shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter); 128 | shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath; 129 | [self.layer addSublayer:shapeLayer]; 130 | shapeLayer.fillColor = [UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1.0].CGColor; 131 | // animate 132 | CGFloat scale = 100.0 / shapeLayer.frame.size.width; 133 | NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault; 134 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 135 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 136 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 137 | animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName]; 138 | animation.removedOnCompletion = YES; 139 | animation.duration = 3.0; 140 | shapeLayer.transform = [animation.toValue CATransform3DValue]; 141 | 142 | [CATransaction begin]; 143 | [CATransaction setCompletionBlock:^{ 144 | [shapeLayer removeFromSuperlayer]; 145 | }]; 146 | [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"]; 147 | [CATransaction commit]; 148 | 149 | return self; 150 | } 151 | 152 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithType:(HDAnimationType)type withColor:(UIColor *)animationColor completion:(void (^)(BOOL))completion { 153 | [self hd_addAnimationAtPoint:point WithDuration:1.0 WithType:type withColor:animationColor completion:completion]; 154 | 155 | return self; 156 | } 157 | 158 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithDuration:(NSTimeInterval)duration WithType:(HDAnimationType)type withColor:(UIColor *)animationColor completion:(void (^)(BOOL finished))completion { 159 | CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 160 | CGFloat diameter = [self hd_mdShapeDiameterForPoint:point]; 161 | shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter); 162 | shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath; 163 | 164 | shapeLayer.fillColor = animationColor.CGColor; 165 | // animate 166 | CGFloat scale = 1.0 / shapeLayer.frame.size.width; 167 | NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault; 168 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 169 | switch (type) { 170 | case HDAnimationOpen: 171 | { 172 | [self.layer addSublayer:shapeLayer]; 173 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 174 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 175 | break; 176 | } 177 | case HDAnimationClose: 178 | { 179 | [self.layer insertSublayer:shapeLayer atIndex:0]; 180 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 181 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 182 | break; 183 | } 184 | default: 185 | break; 186 | } 187 | animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName]; 188 | animation.removedOnCompletion = YES; 189 | animation.duration = duration; 190 | shapeLayer.transform = [animation.toValue CATransform3DValue]; 191 | 192 | [CATransaction begin]; 193 | [CATransaction setCompletionBlock:^{ 194 | [shapeLayer removeFromSuperlayer]; 195 | completion(true); 196 | }]; 197 | [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"]; 198 | [CATransaction commit]; 199 | 200 | return self; 201 | } 202 | 203 | - (instancetype)hd_addAnimationAtPoint:(CGPoint)point WithType:(HDAnimationType)type withColor:(UIColor *)animationColor; { 204 | CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 205 | CGFloat diameter = [self hd_mdShapeDiameterForPoint:point]; 206 | shapeLayer.frame = CGRectMake(floor(point.x - diameter * 0.5), floor(point.y - diameter * 0.5), diameter, diameter); 207 | shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0.0, 0.0, diameter, diameter)].CGPath; 208 | 209 | shapeLayer.fillColor = animationColor.CGColor; 210 | // animate 211 | CGFloat scale = 100.0 / shapeLayer.frame.size.width; 212 | NSString *timingFunctionName = kCAMediaTimingFunctionDefault; //inflating ? kCAMediaTimingFunctionDefault : kCAMediaTimingFunctionDefault; 213 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 214 | switch (type) { 215 | case HDAnimationOpen: 216 | { 217 | [self.layer addSublayer:shapeLayer]; 218 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 219 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 220 | break; 221 | } 222 | case HDAnimationClose: 223 | { 224 | [self.layer insertSublayer:shapeLayer atIndex:0]; 225 | animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1.0)]; 226 | animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 227 | break; 228 | } 229 | default: 230 | break; 231 | } 232 | animation.timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName]; 233 | animation.removedOnCompletion = YES; 234 | animation.duration = 3.0; 235 | shapeLayer.transform = [animation.toValue CATransform3DValue]; 236 | 237 | [CATransaction begin]; 238 | [CATransaction setCompletionBlock:^{ 239 | [shapeLayer removeFromSuperlayer]; 240 | }]; 241 | [shapeLayer addAnimation:animation forKey:@"shapeBackgroundAnimation"]; 242 | [CATransaction commit]; 243 | 244 | return self; 245 | } 246 | 247 | // 计算离屏幕的边框最大的距离 248 | - (CGFloat)hd_mdShapeDiameterForPoint:(CGPoint)point { 249 | CGPoint cornerPoints[] = { 250 | {0.0, 0.0}, 251 | {0.0, self.bounds.size.height}, 252 | {self.bounds.size.width, self.bounds.size.height}, 253 | {self.bounds.size.width, 0.0} 254 | }; 255 | 256 | CGFloat radius = 0.0; 257 | for (int i = 0; i < 4; i++) { 258 | CGPoint p = cornerPoints[i]; 259 | CGFloat d = sqrt( pow(p.x - point.x, 2.0) + pow(p.y - point.y, 2.0)); 260 | if (d > radius) { 261 | radius = d; 262 | } 263 | } 264 | 265 | return radius * 2.0; 266 | } 267 | 268 | 269 | #pragma UIView变成UIImage 270 | #pragma UIView变成UIImage 271 | + (UIImage *)hd_convertViewToImage:(UIView *)view { 272 | // 第二个参数表示是否非透明。如果需要显示半透明效果,需传NO,否则YES。第三个参数就是屏幕密度了 273 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, [UIScreen mainScreen].scale); 274 | [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 275 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 276 | UIGraphicsEndImageContext(); 277 | 278 | return image; 279 | } 280 | 281 | + (UIImage *)hd_snapsHotView:(UIView *)view { 282 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, [UIScreen mainScreen].scale); 283 | [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO]; 284 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 285 | UIGraphicsEndImageContext(); 286 | 287 | return image; 288 | } 289 | 290 | - (UIImage *)hd_convertViewToImage { 291 | return [UIView hd_convertViewToImage:self]; 292 | } 293 | 294 | - (UIImage *)hd_snapsHotView { 295 | return [UIView hd_snapsHotView:self]; 296 | } 297 | 298 | @end 299 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 2.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // HDAlertViewDemo 4 | // 5 | // Created by HeDong on 16/9/1. 6 | // Copyright © 2016年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // HDAlertViewDemo 4 | // 5 | // Created by HeDong on 16/9/1. 6 | // Copyright © 2016年 hedong. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "HDAlertView.h" 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 28 | HDAlertView *alertView = [HDAlertView showActionSheetWithTitle:@"是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX"]; 29 | 30 | [alertView addButtonWithTitle:@"退出" type:HDAlertViewButtonTypeCancel handler:^(HDAlertView *alertView) { 31 | 32 | }]; 33 | 34 | [alertView addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 35 | 36 | }]; 37 | 38 | [alertView addButtonWithTitle:@"好的" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 39 | 40 | }]; 41 | 42 | [alertView show]; 43 | 44 | 45 | [HDAlertView showAlertViewWithTitle:nil message:@"是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX是否退出XXX" cancelButtonTitle:@"取消" otherButtonTitles:@[@"好的", @"好的", @"好的"] handler:^(HDAlertView *alertView, NSInteger buttonIndex) { 46 | 47 | }]; 48 | } 49 | 50 | - (IBAction)styleOne { 51 | HDAlertView *alertView = [HDAlertView alertViewWithTitle:@"样式1" andMessage:@"~\(≧▽≦)/~啦啦啦"]; 52 | alertView.isSupportRotating = YES; 53 | 54 | [alertView addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 55 | NSLog(@"styleOne"); 56 | }]; 57 | 58 | [alertView show]; 59 | } 60 | 61 | - (IBAction)styleTwo { 62 | HDAlertView *alertView = [HDAlertView alertViewWithTitle:@"样式2" andMessage:@"~\(≧▽≦)/~啦啦啦"]; 63 | alertView.isSupportRotating = YES; 64 | 65 | [alertView addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 66 | NSLog(@"styleTwo 确定"); 67 | }]; 68 | 69 | [alertView addButtonWithTitle:@"取消" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 70 | NSLog(@"styleTwo 取消"); 71 | }]; 72 | 73 | [alertView show]; 74 | } 75 | 76 | - (IBAction)styleThree { 77 | HDAlertView *alertView = [HDAlertView alertViewWithTitle:@"样式3" andMessage:@"~\(≧▽≦)/~啦啦啦"]; 78 | alertView.buttonsListStyle = HDAlertViewButtonsListStyleRows; 79 | alertView.isSupportRotating = YES; 80 | 81 | [alertView addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 82 | NSLog(@"styleThree 确定"); 83 | }]; 84 | 85 | [alertView addButtonWithTitle:@"取消" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 86 | NSLog(@"styleThree 取消"); 87 | }]; 88 | 89 | [alertView show]; 90 | } 91 | 92 | - (IBAction)styleFour { 93 | HDAlertView *alertView = [HDAlertView alertViewWithTitle:@"样式4" andMessage:@"~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦~\(≧▽≦)/~啦啦啦"]; 94 | alertView.isSupportRotating = YES; 95 | 96 | [alertView addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 97 | NSLog(@"styleFour 确定"); 98 | }]; 99 | 100 | [alertView addButtonWithTitle:@"取消" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 101 | NSLog(@"styleFour 取消"); 102 | }]; 103 | 104 | [alertView addButtonWithTitle:@"来呀" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 105 | NSLog(@"styleFour 来呀"); 106 | }]; 107 | 108 | [alertView addButtonWithTitle:@"互相" type:HDAlertViewButtonTypeCancel handler:^(HDAlertView *alertView) { 109 | NSLog(@"styleFour 互相"); 110 | }]; 111 | 112 | [alertView addButtonWithTitle:@"伤害" type:HDAlertViewButtonTypeDestructive handler:^(HDAlertView *alertView) { 113 | NSLog(@"styleFour 伤害"); 114 | }]; 115 | 116 | [alertView show]; 117 | } 118 | 119 | - (IBAction)styleFive { 120 | HDAlertView *alertView = [HDAlertView alertViewWithTitle:@"样式5" andMessage:@"其他的自己写着玩吧~~~"]; 121 | alertView.transitionStyle = HDAlertViewTransitionStyleDropDown; 122 | alertView.backgroundStyle = HDAlertViewBackgroundStyleGradient; 123 | alertView.isSupportRotating = YES; 124 | 125 | [alertView addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 126 | NSLog(@"styleFive"); 127 | }]; 128 | 129 | [alertView show]; 130 | } 131 | 132 | /** 133 | * 宝宝们, 别乱玩... 134 | */ 135 | - (IBAction)styleSix { 136 | HDAlertView *alertView = [HDAlertView alertViewWithTitle:@"真的没了" andMessage:@"不骗你, 真的最后一个了"]; 137 | alertView.transitionStyle = HDAlertViewTransitionStyleFade; 138 | alertView.isSupportRotating = YES; 139 | 140 | [alertView addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 141 | NSLog(@"styleSix 1"); 142 | }]; 143 | 144 | [alertView show]; 145 | 146 | 147 | HDAlertView *alertView1 = [HDAlertView alertViewWithTitle:@"最后一个" andMessage:@"点了就没了"]; 148 | alertView1.transitionStyle = HDAlertViewTransitionStyleSlideFromTop; 149 | alertView1.isSupportRotating = YES; 150 | 151 | [alertView1 addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 152 | NSLog(@"styleSix 2"); 153 | }]; 154 | 155 | [alertView1 show]; 156 | 157 | 158 | HDAlertView *alertView2 = [HDAlertView alertViewWithTitle:@"没有惊喜" andMessage:@"哈哈, 骗你的, 没有惊喜"]; 159 | alertView2.transitionStyle = HDAlertViewTransitionStyleSlideFromBottom; 160 | alertView2.isSupportRotating = YES; 161 | 162 | [alertView2 addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 163 | NSLog(@"styleSix 3"); 164 | }]; 165 | 166 | [alertView2 show]; 167 | 168 | 169 | HDAlertView *alertView3 = [HDAlertView alertViewWithTitle:@"惊喜往往在后面" andMessage:@"再次点击就告诉你"]; 170 | alertView3.isSupportRotating = YES; 171 | alertView3.transitionStyle = HDAlertViewTransitionStyleBounce; 172 | alertView3.backgroundStyle = HDAlertViewBackgroundStyleGradient; 173 | 174 | [alertView3 addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 175 | NSLog(@"styleSix 4"); 176 | }]; 177 | 178 | [alertView3 show]; 179 | 180 | 181 | HDAlertView *alertView4 = [HDAlertView alertViewWithTitle:@"有个秘密告诉你" andMessage:@"确定之后会有意外惊喜"]; 182 | alertView4.transitionStyle = HDAlertViewTransitionStyleDropDown; 183 | alertView4.backgroundStyle = HDAlertViewBackgroundStyleGradient; 184 | alertView4.isSupportRotating = YES; 185 | 186 | [alertView4 addButtonWithTitle:@"确定" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 187 | NSLog(@"styleSix 5"); 188 | }]; 189 | 190 | [alertView4 show]; 191 | } 192 | 193 | @end 194 | -------------------------------------------------------------------------------- /HDAlertViewDemo/HDAlertViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HDAlertViewDemo 4 | // 5 | // Created by HeDong on 16/9/1. 6 | // Copyright © 2016年 hedong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Images/HDAlertViewDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bruce-7/HDAlertView/43634d815f2f7d6d4bcbdaa4ce8cf90b25ed0746/Images/HDAlertViewDemo.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 seven 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 | # HDAlertView 2 | 3 | HDAlertView是一个类似系统, 微信, QQ, 等等App的alertView弹窗. 4 | ### Demo【演示】 5 | ![演示](https://github.com/Bruce-7/HDAlertView/blob/master/Images/HDAlertViewDemo.gif) 6 | 7 | ### Examples【示例】 8 | 9 | ``` 10 | HDAlertView *alertView = [HDAlertView alertViewWithTitle:@"HDAlertView" andMessage:@"similar system UIAlertView"]; 11 | 12 | [alertView addButtonWithTitle:@"ok" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 13 | NSLog(@"ok"); 14 | }]; 15 | 16 | [alertView addButtonWithTitle:@"cancel" type:HDAlertViewButtonTypeDefault handler:^(HDAlertView *alertView) { 17 | NSLog(@"cancel"); 18 | }]; 19 | 20 | [alertView show]; 21 | 22 | ``` 23 | 24 | 25 | ### CocoaPods 26 | 27 | 推荐使用CocoaPods安装 28 | 29 | platform :ios, '7.0' 30 | 31 | target :'your project' do 32 | 33 | pod 'HDAlertView' 34 | 35 | end 36 | 37 | Pod install 38 | 39 | ### Manually【手动导入】 40 | 1. 通过 Clone or download 下载 HDAlertView 文件夹内的所有内容. 41 | 2. 将 HDAlertView 内的源文件添加(拖放)到你的工程. 42 | 3. 导入#import "HDAlertView.h". 43 | 44 | ### 补充 45 | 系统自带UIAlertView有常见BUG, 比如和系统键盘动画冲突等等, 需要代理操作等诸多不方便使用. 使用UIAlertController就不会有UIAlertView等等问题, 但是又不支持iOS7.所以才自定义一个类似系统的UIAlertView, 用法和UIAlertController相似, 而且简单. 46 | 47 | ##### 如果在使用过程中遇到BUG, 希望你能Issues我. 如果对你有所帮助请Star 48 | ##### Sina : [@小七柒_7](http://weibo.com/5671953891) 49 | 50 | ## License 51 | 52 | HDAlertView is released under the MIT license. See LICENSE for details. 53 | 54 | --------------------------------------------------------------------------------