├── README.md └── iOS-Category ├── iOS-Category.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── ZBB.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── ZBB.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── iOS-Category.xcscheme │ └── xcschememanagement.plist └── iOS-Category ├── NSArray+Safe.h ├── NSArray+Safe.m ├── NSAttributedString+Category.h ├── NSAttributedString+Category.m ├── NSData+CommonCryptor.h ├── NSData+CommonCryptor.m ├── NSDate+Category.h ├── NSDate+Category.m ├── NSDictionary+Category.h ├── NSDictionary+Category.m ├── NSDictionary+Safe.h ├── NSDictionary+Safe.m ├── NSMutableArray+Safe.h ├── NSMutableArray+Safe.m ├── NSMutableDictionary+Safe.h ├── NSMutableDictionary+Safe.m ├── NSMutableString+Safe.h ├── NSMutableString+Safe.m ├── NSObject+Category.h ├── NSObject+Category.m ├── NSObject+PerformBlock.h ├── NSObject+PerformBlock.m ├── NSObject+Swizzle.h ├── NSObject+Swizzle.m ├── NSString+Category.h ├── NSString+Category.m ├── NSString+DisplayTime.h ├── NSString+DisplayTime.m ├── NSString+MD5.h ├── NSString+MD5.m ├── NSString+Predicate.h ├── NSString+Predicate.m ├── NSString+Safe.h ├── NSString+Safe.m ├── UIButton+Category.h ├── UIButton+Category.m ├── UIColor+Category.h ├── UIColor+Category.m ├── UIImage+Category.h ├── UIImage+Category.m ├── UIMenuItem+Category.h ├── UIMenuItem+Category.m ├── UITableView+CellAnimation.h ├── UITableView+CellAnimation.m ├── UIView+Category.h ├── UIView+Category.m ├── UIView+Frame.h └── UIView+Frame.m /README.md: -------------------------------------------------------------------------------- 1 | # iOS 常用Category类别分享(持续更新) 2 | 以后会持续更新,可以继续关注哦!   
3 | [简书地址](http://www.jianshu.com/p/68ba104b9061)   
4 | # 前言 5 | 没有其他巴拉巴拉的一堆,直接上干货,分享自己从事iOS开发以来积累的Category工具类别,提高大家的开发效率!
6 |    **PS:我会不定期进行更新,加入一些新的方法;**
7 |    
8 |  ------
9 |    ##20.5.30更新
10 |    1.增加NSDate类一些常用的转换方法;
11 |    2.增加快速创建富文本字符串的方法;
12 |    3.优化了字典转字符串方法, 处理了转出来的字符串带/n和空格的情况;
13 |    4.NSString+Safe增加了stringWithFormat避免显示null的方法;
14 |    
15 |    
16 |  ------
17 |    ##18.5.22更新
18 |    1.优化了千分符方法;
19 |    2.将各个健壮性方法单独提取出来;
20 |    3.优化了覆盖及拦截method;
21 |    
22 |    
23 |    ------
24 |    ##17.8.25更新
25 |    1.进行了局部的重新排版;
26 |    2.添加了NSObject的一些分类方法(具体见下面内容);
27 |    3.合并了一些类目方法;
28 |    4.整理了整个项目文件夹,条目更加清晰;
29 |    5.添加了更多的注释;
30 |    
31 |    
32 |    ------
33 | 这边我给大家分享的基本都是常用类,其中包括**NSObject**、 **NSString**、 **NSArray**、**NSDictionary**、**UIView**、**UIImage**、**UIButton**、**UIView**、**UIView**、**NSData**、**UIMenuItem**、**NSDate**。
34 | 这边把一些常用的工具类分享给了大家,基本每个方法都是我在实际项目因为某些需求写的、还有部分是网上找的。如果不会使用可以来询问我,发现错误请及时联系我,不喜勿喷,谢谢~
35 | 以后我还会持续更新的!如果各位下载的同学喜欢,请给点个星 ,谢谢啦!
36 | 37 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3D5E53F62482358300637812 /* NSDate+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D5E53F52482358300637812 /* NSDate+Category.m */; }; 11 | 3D8217E11D3F45A20077850F /* NSAttributedString+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217A61D3F45A20077850F /* NSAttributedString+Category.m */; }; 12 | 3D8217E31D3F45A20077850F /* NSData+CommonCryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217AA1D3F45A20077850F /* NSData+CommonCryptor.m */; }; 13 | 3D8217E41D3F45A20077850F /* NSDictionary+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217AC1D3F45A20077850F /* NSDictionary+Category.m */; }; 14 | 3D8217E81D3F45A20077850F /* NSString+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217B41D3F45A20077850F /* NSString+Category.m */; }; 15 | 3D8217EA1D3F45A20077850F /* NSString+MD5.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217B81D3F45A20077850F /* NSString+MD5.m */; }; 16 | 3D8217EF1D3F45A20077850F /* UIButton+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217C21D3F45A20077850F /* UIButton+Category.m */; }; 17 | 3D8217F51D3F45A20077850F /* UIImage+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217CE1D3F45A20077850F /* UIImage+Category.m */; }; 18 | 3D8217F71D3F45A20077850F /* UIMenuItem+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217D21D3F45A20077850F /* UIMenuItem+Category.m */; }; 19 | 3D8217FB1D3F45A20077850F /* UIView+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8217DA1D3F45A20077850F /* UIView+Category.m */; }; 20 | 3D8218091D3F5ECB0077850F /* NSString+Predicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D8218081D3F5ECB0077850F /* NSString+Predicate.m */; }; 21 | 3D82180F1D3F6A930077850F /* NSString+DisplayTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D82180E1D3F6A930077850F /* NSString+DisplayTime.m */; }; 22 | 3DC904131F4D748700E56004 /* NSObject+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DC904121F4D748700E56004 /* NSObject+Category.m */; }; 23 | 3DC904161F4D790F00E56004 /* NSObject+PerformBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DC904151F4D790F00E56004 /* NSObject+PerformBlock.m */; }; 24 | 3DC9041C1F4D7E6E00E56004 /* UIView+Frame.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DC9041B1F4D7E6E00E56004 /* UIView+Frame.m */; }; 25 | 3DC9041F1F4D87E200E56004 /* UIColor+Category.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DC9041E1F4D87E200E56004 /* UIColor+Category.m */; }; 26 | 3DC904221F4EAE2F00E56004 /* NSString+Safe.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DC904211F4EAE2F00E56004 /* NSString+Safe.m */; }; 27 | 3DC904251F4EB8CD00E56004 /* NSMutableString+Safe.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DC904241F4EB8CD00E56004 /* NSMutableString+Safe.m */; }; 28 | 3DD78BCD1F669053003B8E9F /* UITableView+CellAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DD78BCC1F669053003B8E9F /* UITableView+CellAnimation.m */; }; 29 | 3DFAD8EC20AEA1400067ACDE /* NSDictionary+Safe.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DFAD8EB20AEA1400067ACDE /* NSDictionary+Safe.m */; }; 30 | 3DFAD8EF20AEA1870067ACDE /* NSMutableDictionary+Safe.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DFAD8EE20AEA1870067ACDE /* NSMutableDictionary+Safe.m */; }; 31 | 3DFAD8F220AEA7F80067ACDE /* NSArray+Safe.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DFAD8F120AEA7F80067ACDE /* NSArray+Safe.m */; }; 32 | 3DFAD8F520AEB58C0067ACDE /* NSMutableArray+Safe.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DFAD8F420AEB58C0067ACDE /* NSMutableArray+Safe.m */; }; 33 | 3DFAD93820B2E0960067ACDE /* NSObject+Swizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DFAD93720B2E0950067ACDE /* NSObject+Swizzle.m */; }; 34 | /* End PBXBuildFile section */ 35 | 36 | /* Begin PBXCopyFilesBuildPhase section */ 37 | 3D8217931D3F44C90077850F /* CopyFiles */ = { 38 | isa = PBXCopyFilesBuildPhase; 39 | buildActionMask = 2147483647; 40 | dstPath = "include/$(PRODUCT_NAME)"; 41 | dstSubfolderSpec = 16; 42 | files = ( 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXCopyFilesBuildPhase section */ 47 | 48 | /* Begin PBXFileReference section */ 49 | 3D5E53F42482358300637812 /* NSDate+Category.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDate+Category.h"; sourceTree = ""; }; 50 | 3D5E53F52482358300637812 /* NSDate+Category.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+Category.m"; sourceTree = ""; }; 51 | 3D8217951D3F44C90077850F /* libiOS-Category.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libiOS-Category.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 3D8217A51D3F45A20077850F /* NSAttributedString+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSAttributedString+Category.h"; sourceTree = ""; }; 53 | 3D8217A61D3F45A20077850F /* NSAttributedString+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSAttributedString+Category.m"; sourceTree = ""; }; 54 | 3D8217A91D3F45A20077850F /* NSData+CommonCryptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+CommonCryptor.h"; sourceTree = ""; }; 55 | 3D8217AA1D3F45A20077850F /* NSData+CommonCryptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+CommonCryptor.m"; sourceTree = ""; }; 56 | 3D8217AB1D3F45A20077850F /* NSDictionary+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Category.h"; sourceTree = ""; }; 57 | 3D8217AC1D3F45A20077850F /* NSDictionary+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Category.m"; sourceTree = ""; }; 58 | 3D8217B31D3F45A20077850F /* NSString+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Category.h"; sourceTree = ""; }; 59 | 3D8217B41D3F45A20077850F /* NSString+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Category.m"; sourceTree = ""; }; 60 | 3D8217B71D3F45A20077850F /* NSString+MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MD5.h"; sourceTree = ""; }; 61 | 3D8217B81D3F45A20077850F /* NSString+MD5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MD5.m"; sourceTree = ""; }; 62 | 3D8217C11D3F45A20077850F /* UIButton+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+Category.h"; sourceTree = ""; }; 63 | 3D8217C21D3F45A20077850F /* UIButton+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+Category.m"; sourceTree = ""; }; 64 | 3D8217CD1D3F45A20077850F /* UIImage+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Category.h"; sourceTree = ""; }; 65 | 3D8217CE1D3F45A20077850F /* UIImage+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Category.m"; sourceTree = ""; }; 66 | 3D8217D11D3F45A20077850F /* UIMenuItem+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIMenuItem+Category.h"; sourceTree = ""; }; 67 | 3D8217D21D3F45A20077850F /* UIMenuItem+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIMenuItem+Category.m"; sourceTree = ""; }; 68 | 3D8217D91D3F45A20077850F /* UIView+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Category.h"; sourceTree = ""; }; 69 | 3D8217DA1D3F45A20077850F /* UIView+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Category.m"; sourceTree = ""; }; 70 | 3D8218071D3F5ECB0077850F /* NSString+Predicate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Predicate.h"; sourceTree = ""; }; 71 | 3D8218081D3F5ECB0077850F /* NSString+Predicate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Predicate.m"; sourceTree = ""; }; 72 | 3D82180D1D3F6A930077850F /* NSString+DisplayTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+DisplayTime.h"; sourceTree = ""; }; 73 | 3D82180E1D3F6A930077850F /* NSString+DisplayTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+DisplayTime.m"; sourceTree = ""; }; 74 | 3DC904111F4D748700E56004 /* NSObject+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Category.h"; sourceTree = ""; }; 75 | 3DC904121F4D748700E56004 /* NSObject+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Category.m"; sourceTree = ""; }; 76 | 3DC904141F4D790F00E56004 /* NSObject+PerformBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PerformBlock.h"; sourceTree = ""; }; 77 | 3DC904151F4D790F00E56004 /* NSObject+PerformBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PerformBlock.m"; sourceTree = ""; }; 78 | 3DC9041A1F4D7E6E00E56004 /* UIView+Frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Frame.h"; sourceTree = ""; }; 79 | 3DC9041B1F4D7E6E00E56004 /* UIView+Frame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Frame.m"; sourceTree = ""; }; 80 | 3DC9041D1F4D87E200E56004 /* UIColor+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+Category.h"; sourceTree = ""; }; 81 | 3DC9041E1F4D87E200E56004 /* UIColor+Category.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Category.m"; sourceTree = ""; }; 82 | 3DC904201F4EAE2F00E56004 /* NSString+Safe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Safe.h"; sourceTree = ""; }; 83 | 3DC904211F4EAE2F00E56004 /* NSString+Safe.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Safe.m"; sourceTree = ""; }; 84 | 3DC904231F4EB8CD00E56004 /* NSMutableString+Safe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableString+Safe.h"; sourceTree = ""; }; 85 | 3DC904241F4EB8CD00E56004 /* NSMutableString+Safe.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableString+Safe.m"; sourceTree = ""; }; 86 | 3DD78BCB1F669053003B8E9F /* UITableView+CellAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableView+CellAnimation.h"; sourceTree = ""; }; 87 | 3DD78BCC1F669053003B8E9F /* UITableView+CellAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableView+CellAnimation.m"; sourceTree = ""; }; 88 | 3DFAD8EA20AEA1400067ACDE /* NSDictionary+Safe.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Safe.h"; sourceTree = ""; }; 89 | 3DFAD8EB20AEA1400067ACDE /* NSDictionary+Safe.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Safe.m"; sourceTree = ""; }; 90 | 3DFAD8ED20AEA1870067ACDE /* NSMutableDictionary+Safe.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+Safe.h"; sourceTree = ""; }; 91 | 3DFAD8EE20AEA1870067ACDE /* NSMutableDictionary+Safe.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+Safe.m"; sourceTree = ""; }; 92 | 3DFAD8F020AEA7F80067ACDE /* NSArray+Safe.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSArray+Safe.h"; sourceTree = ""; }; 93 | 3DFAD8F120AEA7F80067ACDE /* NSArray+Safe.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Safe.m"; sourceTree = ""; }; 94 | 3DFAD8F320AEB58C0067ACDE /* NSMutableArray+Safe.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+Safe.h"; sourceTree = ""; }; 95 | 3DFAD8F420AEB58C0067ACDE /* NSMutableArray+Safe.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+Safe.m"; sourceTree = ""; }; 96 | 3DFAD93620B2E0950067ACDE /* NSObject+Swizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Swizzle.h"; sourceTree = ""; }; 97 | 3DFAD93720B2E0950067ACDE /* NSObject+Swizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Swizzle.m"; sourceTree = ""; }; 98 | /* End PBXFileReference section */ 99 | 100 | /* Begin PBXFrameworksBuildPhase section */ 101 | 3D8217921D3F44C90077850F /* Frameworks */ = { 102 | isa = PBXFrameworksBuildPhase; 103 | buildActionMask = 2147483647; 104 | files = ( 105 | ); 106 | runOnlyForDeploymentPostprocessing = 0; 107 | }; 108 | /* End PBXFrameworksBuildPhase section */ 109 | 110 | /* Begin PBXGroup section */ 111 | 3D5E53F32482356100637812 /* NSdate */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 3D5E53F42482358300637812 /* NSDate+Category.h */, 115 | 3D5E53F52482358300637812 /* NSDate+Category.m */, 116 | ); 117 | name = NSdate; 118 | sourceTree = ""; 119 | }; 120 | 3D82178C1D3F44C90077850F = { 121 | isa = PBXGroup; 122 | children = ( 123 | 3D8217971D3F44C90077850F /* iOS-Category */, 124 | 3D8217961D3F44C90077850F /* Products */, 125 | ); 126 | sourceTree = ""; 127 | }; 128 | 3D8217961D3F44C90077850F /* Products */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 3D8217951D3F44C90077850F /* libiOS-Category.a */, 132 | ); 133 | name = Products; 134 | sourceTree = ""; 135 | }; 136 | 3D8217971D3F44C90077850F /* iOS-Category */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 3D5E53F32482356100637812 /* NSdate */, 140 | 3DD78BCA1F669025003B8E9F /* TableView */, 141 | 3DC904061F4D5DC700E56004 /* NSString */, 142 | 3DC904091F4D5EF200E56004 /* NSDictionary */, 143 | 3DC904081F4D5EE300E56004 /* NSArray */, 144 | 3DC904101F4D746C00E56004 /* NSObject */, 145 | 3DC9040F1F4D6D2500E56004 /* UIMenuItem */, 146 | 3DC9040E1F4D683D00E56004 /* NSData */, 147 | 3DC9040D1F4D66A100E56004 /* UIColor */, 148 | 3DC9040C1F4D669900E56004 /* UIImage */, 149 | 3DC9040B1F4D663200E56004 /* UIView */, 150 | 3DC9040A1F4D651200E56004 /* UIButton */, 151 | 3DC904071F4D5E2200E56004 /* NSAttributedString */, 152 | ); 153 | path = "iOS-Category"; 154 | sourceTree = ""; 155 | }; 156 | 3DC904061F4D5DC700E56004 /* NSString */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 3D8217B31D3F45A20077850F /* NSString+Category.h */, 160 | 3D8217B41D3F45A20077850F /* NSString+Category.m */, 161 | 3D8218071D3F5ECB0077850F /* NSString+Predicate.h */, 162 | 3D8218081D3F5ECB0077850F /* NSString+Predicate.m */, 163 | 3D82180D1D3F6A930077850F /* NSString+DisplayTime.h */, 164 | 3D82180E1D3F6A930077850F /* NSString+DisplayTime.m */, 165 | 3D8217B71D3F45A20077850F /* NSString+MD5.h */, 166 | 3D8217B81D3F45A20077850F /* NSString+MD5.m */, 167 | 3DC904201F4EAE2F00E56004 /* NSString+Safe.h */, 168 | 3DC904211F4EAE2F00E56004 /* NSString+Safe.m */, 169 | 3DC904231F4EB8CD00E56004 /* NSMutableString+Safe.h */, 170 | 3DC904241F4EB8CD00E56004 /* NSMutableString+Safe.m */, 171 | ); 172 | name = NSString; 173 | sourceTree = ""; 174 | }; 175 | 3DC904071F4D5E2200E56004 /* NSAttributedString */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | 3D8217A51D3F45A20077850F /* NSAttributedString+Category.h */, 179 | 3D8217A61D3F45A20077850F /* NSAttributedString+Category.m */, 180 | ); 181 | name = NSAttributedString; 182 | sourceTree = ""; 183 | }; 184 | 3DC904081F4D5EE300E56004 /* NSArray */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | 3DFAD8F020AEA7F80067ACDE /* NSArray+Safe.h */, 188 | 3DFAD8F120AEA7F80067ACDE /* NSArray+Safe.m */, 189 | 3DFAD8F320AEB58C0067ACDE /* NSMutableArray+Safe.h */, 190 | 3DFAD8F420AEB58C0067ACDE /* NSMutableArray+Safe.m */, 191 | ); 192 | name = NSArray; 193 | sourceTree = ""; 194 | }; 195 | 3DC904091F4D5EF200E56004 /* NSDictionary */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | 3D8217AB1D3F45A20077850F /* NSDictionary+Category.h */, 199 | 3D8217AC1D3F45A20077850F /* NSDictionary+Category.m */, 200 | 3DFAD8EA20AEA1400067ACDE /* NSDictionary+Safe.h */, 201 | 3DFAD8EB20AEA1400067ACDE /* NSDictionary+Safe.m */, 202 | 3DFAD8ED20AEA1870067ACDE /* NSMutableDictionary+Safe.h */, 203 | 3DFAD8EE20AEA1870067ACDE /* NSMutableDictionary+Safe.m */, 204 | ); 205 | name = NSDictionary; 206 | sourceTree = ""; 207 | }; 208 | 3DC9040A1F4D651200E56004 /* UIButton */ = { 209 | isa = PBXGroup; 210 | children = ( 211 | 3D8217C11D3F45A20077850F /* UIButton+Category.h */, 212 | 3D8217C21D3F45A20077850F /* UIButton+Category.m */, 213 | ); 214 | name = UIButton; 215 | sourceTree = ""; 216 | }; 217 | 3DC9040B1F4D663200E56004 /* UIView */ = { 218 | isa = PBXGroup; 219 | children = ( 220 | 3D8217D91D3F45A20077850F /* UIView+Category.h */, 221 | 3D8217DA1D3F45A20077850F /* UIView+Category.m */, 222 | 3DC9041A1F4D7E6E00E56004 /* UIView+Frame.h */, 223 | 3DC9041B1F4D7E6E00E56004 /* UIView+Frame.m */, 224 | ); 225 | name = UIView; 226 | sourceTree = ""; 227 | }; 228 | 3DC9040C1F4D669900E56004 /* UIImage */ = { 229 | isa = PBXGroup; 230 | children = ( 231 | 3D8217CD1D3F45A20077850F /* UIImage+Category.h */, 232 | 3D8217CE1D3F45A20077850F /* UIImage+Category.m */, 233 | ); 234 | name = UIImage; 235 | sourceTree = ""; 236 | }; 237 | 3DC9040D1F4D66A100E56004 /* UIColor */ = { 238 | isa = PBXGroup; 239 | children = ( 240 | 3DC9041D1F4D87E200E56004 /* UIColor+Category.h */, 241 | 3DC9041E1F4D87E200E56004 /* UIColor+Category.m */, 242 | ); 243 | name = UIColor; 244 | sourceTree = ""; 245 | }; 246 | 3DC9040E1F4D683D00E56004 /* NSData */ = { 247 | isa = PBXGroup; 248 | children = ( 249 | 3D8217A91D3F45A20077850F /* NSData+CommonCryptor.h */, 250 | 3D8217AA1D3F45A20077850F /* NSData+CommonCryptor.m */, 251 | ); 252 | name = NSData; 253 | sourceTree = ""; 254 | }; 255 | 3DC9040F1F4D6D2500E56004 /* UIMenuItem */ = { 256 | isa = PBXGroup; 257 | children = ( 258 | 3D8217D11D3F45A20077850F /* UIMenuItem+Category.h */, 259 | 3D8217D21D3F45A20077850F /* UIMenuItem+Category.m */, 260 | ); 261 | name = UIMenuItem; 262 | sourceTree = ""; 263 | }; 264 | 3DC904101F4D746C00E56004 /* NSObject */ = { 265 | isa = PBXGroup; 266 | children = ( 267 | 3DFAD93620B2E0950067ACDE /* NSObject+Swizzle.h */, 268 | 3DFAD93720B2E0950067ACDE /* NSObject+Swizzle.m */, 269 | 3DC904111F4D748700E56004 /* NSObject+Category.h */, 270 | 3DC904121F4D748700E56004 /* NSObject+Category.m */, 271 | 3DC904141F4D790F00E56004 /* NSObject+PerformBlock.h */, 272 | 3DC904151F4D790F00E56004 /* NSObject+PerformBlock.m */, 273 | ); 274 | name = NSObject; 275 | sourceTree = ""; 276 | }; 277 | 3DD78BCA1F669025003B8E9F /* TableView */ = { 278 | isa = PBXGroup; 279 | children = ( 280 | 3DD78BCB1F669053003B8E9F /* UITableView+CellAnimation.h */, 281 | 3DD78BCC1F669053003B8E9F /* UITableView+CellAnimation.m */, 282 | ); 283 | name = TableView; 284 | sourceTree = ""; 285 | }; 286 | /* End PBXGroup section */ 287 | 288 | /* Begin PBXNativeTarget section */ 289 | 3D8217941D3F44C90077850F /* iOS-Category */ = { 290 | isa = PBXNativeTarget; 291 | buildConfigurationList = 3D82179E1D3F44C90077850F /* Build configuration list for PBXNativeTarget "iOS-Category" */; 292 | buildPhases = ( 293 | 3D8217911D3F44C90077850F /* Sources */, 294 | 3D8217921D3F44C90077850F /* Frameworks */, 295 | 3D8217931D3F44C90077850F /* CopyFiles */, 296 | ); 297 | buildRules = ( 298 | ); 299 | dependencies = ( 300 | ); 301 | name = "iOS-Category"; 302 | productName = "iOS-Category"; 303 | productReference = 3D8217951D3F44C90077850F /* libiOS-Category.a */; 304 | productType = "com.apple.product-type.library.static"; 305 | }; 306 | /* End PBXNativeTarget section */ 307 | 308 | /* Begin PBXProject section */ 309 | 3D82178D1D3F44C90077850F /* Project object */ = { 310 | isa = PBXProject; 311 | attributes = { 312 | LastUpgradeCheck = 0730; 313 | ORGANIZATIONNAME = BBFC; 314 | TargetAttributes = { 315 | 3D8217941D3F44C90077850F = { 316 | CreatedOnToolsVersion = 7.3.1; 317 | }; 318 | }; 319 | }; 320 | buildConfigurationList = 3D8217901D3F44C90077850F /* Build configuration list for PBXProject "iOS-Category" */; 321 | compatibilityVersion = "Xcode 3.2"; 322 | developmentRegion = English; 323 | hasScannedForEncodings = 0; 324 | knownRegions = ( 325 | English, 326 | en, 327 | ); 328 | mainGroup = 3D82178C1D3F44C90077850F; 329 | productRefGroup = 3D8217961D3F44C90077850F /* Products */; 330 | projectDirPath = ""; 331 | projectRoot = ""; 332 | targets = ( 333 | 3D8217941D3F44C90077850F /* iOS-Category */, 334 | ); 335 | }; 336 | /* End PBXProject section */ 337 | 338 | /* Begin PBXSourcesBuildPhase section */ 339 | 3D8217911D3F44C90077850F /* Sources */ = { 340 | isa = PBXSourcesBuildPhase; 341 | buildActionMask = 2147483647; 342 | files = ( 343 | 3DFAD93820B2E0960067ACDE /* NSObject+Swizzle.m in Sources */, 344 | 3DFAD8EF20AEA1870067ACDE /* NSMutableDictionary+Safe.m in Sources */, 345 | 3D5E53F62482358300637812 /* NSDate+Category.m in Sources */, 346 | 3D82180F1D3F6A930077850F /* NSString+DisplayTime.m in Sources */, 347 | 3D8217E31D3F45A20077850F /* NSData+CommonCryptor.m in Sources */, 348 | 3DFAD8F520AEB58C0067ACDE /* NSMutableArray+Safe.m in Sources */, 349 | 3DC9041C1F4D7E6E00E56004 /* UIView+Frame.m in Sources */, 350 | 3D8217E81D3F45A20077850F /* NSString+Category.m in Sources */, 351 | 3DD78BCD1F669053003B8E9F /* UITableView+CellAnimation.m in Sources */, 352 | 3DC904131F4D748700E56004 /* NSObject+Category.m in Sources */, 353 | 3D8217EA1D3F45A20077850F /* NSString+MD5.m in Sources */, 354 | 3D8217E11D3F45A20077850F /* NSAttributedString+Category.m in Sources */, 355 | 3D8217EF1D3F45A20077850F /* UIButton+Category.m in Sources */, 356 | 3DFAD8F220AEA7F80067ACDE /* NSArray+Safe.m in Sources */, 357 | 3D8217E41D3F45A20077850F /* NSDictionary+Category.m in Sources */, 358 | 3DC904161F4D790F00E56004 /* NSObject+PerformBlock.m in Sources */, 359 | 3DC904221F4EAE2F00E56004 /* NSString+Safe.m in Sources */, 360 | 3D8217F71D3F45A20077850F /* UIMenuItem+Category.m in Sources */, 361 | 3D8217FB1D3F45A20077850F /* UIView+Category.m in Sources */, 362 | 3DFAD8EC20AEA1400067ACDE /* NSDictionary+Safe.m in Sources */, 363 | 3D8217F51D3F45A20077850F /* UIImage+Category.m in Sources */, 364 | 3DC904251F4EB8CD00E56004 /* NSMutableString+Safe.m in Sources */, 365 | 3D8218091D3F5ECB0077850F /* NSString+Predicate.m in Sources */, 366 | 3DC9041F1F4D87E200E56004 /* UIColor+Category.m in Sources */, 367 | ); 368 | runOnlyForDeploymentPostprocessing = 0; 369 | }; 370 | /* End PBXSourcesBuildPhase section */ 371 | 372 | /* Begin XCBuildConfiguration section */ 373 | 3D82179C1D3F44C90077850F /* Debug */ = { 374 | isa = XCBuildConfiguration; 375 | buildSettings = { 376 | ALWAYS_SEARCH_USER_PATHS = NO; 377 | CLANG_ANALYZER_NONNULL = YES; 378 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 379 | CLANG_CXX_LIBRARY = "libc++"; 380 | CLANG_ENABLE_MODULES = YES; 381 | CLANG_ENABLE_OBJC_ARC = YES; 382 | CLANG_WARN_BOOL_CONVERSION = YES; 383 | CLANG_WARN_CONSTANT_CONVERSION = YES; 384 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 385 | CLANG_WARN_EMPTY_BODY = YES; 386 | CLANG_WARN_ENUM_CONVERSION = YES; 387 | CLANG_WARN_INT_CONVERSION = YES; 388 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 389 | CLANG_WARN_UNREACHABLE_CODE = YES; 390 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 391 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 392 | COPY_PHASE_STRIP = NO; 393 | DEBUG_INFORMATION_FORMAT = dwarf; 394 | ENABLE_STRICT_OBJC_MSGSEND = YES; 395 | ENABLE_TESTABILITY = YES; 396 | GCC_C_LANGUAGE_STANDARD = gnu99; 397 | GCC_DYNAMIC_NO_PIC = NO; 398 | GCC_NO_COMMON_BLOCKS = YES; 399 | GCC_OPTIMIZATION_LEVEL = 0; 400 | GCC_PREPROCESSOR_DEFINITIONS = ( 401 | "DEBUG=1", 402 | "$(inherited)", 403 | ); 404 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 405 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 406 | GCC_WARN_UNDECLARED_SELECTOR = YES; 407 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 408 | GCC_WARN_UNUSED_FUNCTION = YES; 409 | GCC_WARN_UNUSED_VARIABLE = YES; 410 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 411 | MTL_ENABLE_DEBUG_INFO = YES; 412 | ONLY_ACTIVE_ARCH = YES; 413 | SDKROOT = iphoneos; 414 | }; 415 | name = Debug; 416 | }; 417 | 3D82179D1D3F44C90077850F /* Release */ = { 418 | isa = XCBuildConfiguration; 419 | buildSettings = { 420 | ALWAYS_SEARCH_USER_PATHS = NO; 421 | CLANG_ANALYZER_NONNULL = YES; 422 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 423 | CLANG_CXX_LIBRARY = "libc++"; 424 | CLANG_ENABLE_MODULES = YES; 425 | CLANG_ENABLE_OBJC_ARC = YES; 426 | CLANG_WARN_BOOL_CONVERSION = YES; 427 | CLANG_WARN_CONSTANT_CONVERSION = YES; 428 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 429 | CLANG_WARN_EMPTY_BODY = YES; 430 | CLANG_WARN_ENUM_CONVERSION = YES; 431 | CLANG_WARN_INT_CONVERSION = YES; 432 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 433 | CLANG_WARN_UNREACHABLE_CODE = YES; 434 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 435 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 436 | COPY_PHASE_STRIP = NO; 437 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 438 | ENABLE_NS_ASSERTIONS = NO; 439 | ENABLE_STRICT_OBJC_MSGSEND = YES; 440 | GCC_C_LANGUAGE_STANDARD = gnu99; 441 | GCC_NO_COMMON_BLOCKS = YES; 442 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 443 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 444 | GCC_WARN_UNDECLARED_SELECTOR = YES; 445 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 446 | GCC_WARN_UNUSED_FUNCTION = YES; 447 | GCC_WARN_UNUSED_VARIABLE = YES; 448 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 449 | MTL_ENABLE_DEBUG_INFO = NO; 450 | SDKROOT = iphoneos; 451 | VALIDATE_PRODUCT = YES; 452 | }; 453 | name = Release; 454 | }; 455 | 3D82179F1D3F44C90077850F /* Debug */ = { 456 | isa = XCBuildConfiguration; 457 | buildSettings = { 458 | OTHER_LDFLAGS = "-ObjC"; 459 | PRODUCT_NAME = "$(TARGET_NAME)"; 460 | SKIP_INSTALL = YES; 461 | }; 462 | name = Debug; 463 | }; 464 | 3D8217A01D3F44C90077850F /* Release */ = { 465 | isa = XCBuildConfiguration; 466 | buildSettings = { 467 | OTHER_LDFLAGS = "-ObjC"; 468 | PRODUCT_NAME = "$(TARGET_NAME)"; 469 | SKIP_INSTALL = YES; 470 | }; 471 | name = Release; 472 | }; 473 | /* End XCBuildConfiguration section */ 474 | 475 | /* Begin XCConfigurationList section */ 476 | 3D8217901D3F44C90077850F /* Build configuration list for PBXProject "iOS-Category" */ = { 477 | isa = XCConfigurationList; 478 | buildConfigurations = ( 479 | 3D82179C1D3F44C90077850F /* Debug */, 480 | 3D82179D1D3F44C90077850F /* Release */, 481 | ); 482 | defaultConfigurationIsVisible = 0; 483 | defaultConfigurationName = Release; 484 | }; 485 | 3D82179E1D3F44C90077850F /* Build configuration list for PBXNativeTarget "iOS-Category" */ = { 486 | isa = XCConfigurationList; 487 | buildConfigurations = ( 488 | 3D82179F1D3F44C90077850F /* Debug */, 489 | 3D8217A01D3F44C90077850F /* Release */, 490 | ); 491 | defaultConfigurationIsVisible = 0; 492 | defaultConfigurationName = Release; 493 | }; 494 | /* End XCConfigurationList section */ 495 | }; 496 | rootObject = 3D82178D1D3F44C90077850F /* Project object */; 497 | } 498 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category.xcodeproj/project.xcworkspace/xcuserdata/ZBB.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazamihayato/iOS-Category/e863413653591e1752d23dc72b9e5305e48cda8a/iOS-Category/iOS-Category.xcodeproj/project.xcworkspace/xcuserdata/ZBB.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOS-Category/iOS-Category.xcodeproj/xcuserdata/ZBB.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category.xcodeproj/xcuserdata/ZBB.xcuserdatad/xcschemes/iOS-Category.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category.xcodeproj/xcuserdata/ZBB.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iOS-Category.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 3D8217941D3F44C90077850F 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSArray+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Safe.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2018/5/18. 6 | // Copyright © 2018年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSArray (Safe) 12 | 13 | + (instancetype)safeArrayWithObject:(id)object; 14 | 15 | - (id)safeObjectAtIndex:(NSUInteger)index; 16 | 17 | - (NSArray *)safeSubarrayWithRange:(NSRange)range; 18 | 19 | - (NSUInteger)safeIndexOfObject:(id)anObject; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSArray+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Safe.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2018/5/18. 6 | // Copyright © 2018年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSArray+Safe.h" 10 | 11 | 12 | @implementation NSArray (Safe) 13 | 14 | + (instancetype)safeArrayWithObject:(id)object 15 | { 16 | if (object == nil) { 17 | return [self array]; 18 | } else { 19 | return [self arrayWithObject:object]; 20 | } 21 | } 22 | 23 | 24 | - (id)safeObjectAtIndex:(NSUInteger)index 25 | { 26 | if (index >= self.count) { 27 | return nil; 28 | } else { 29 | return [self objectAtIndex:index]; 30 | } 31 | } 32 | 33 | - (NSUInteger)safeIndexOfObject:(id)anObject 34 | { 35 | if (anObject == nil) { 36 | return NSNotFound; 37 | } else { 38 | return [self indexOfObject:anObject]; 39 | } 40 | } 41 | 42 | - (NSArray *)safeSubarrayWithRange:(NSRange)range 43 | { 44 | NSUInteger location = range.location; 45 | NSUInteger length = range.length; 46 | if (location + length > self.count) { 47 | //超过了边界,就获取从loction开始所有的item 48 | if ((location + length) > self.count) { 49 | length = (self.count - location); 50 | return [self safeSubarrayWithRange:NSMakeRange(location, length)]; 51 | } 52 | 53 | return nil; 54 | } 55 | else { 56 | return [self subarrayWithRange:range]; 57 | } 58 | } 59 | 60 | 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSAttributedString+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+Category.h 3 | // PKWSevers 4 | // 5 | // Created by chenguangjiang on 16/5/23. 6 | // Copyright © 2016年 peikua. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @interface NSAttributedString (Category) 12 | // 快速创建富文本字符串,包含了Str 颜色 字体 字体间距 行间距 range 13 | + (NSAttributedString *)attributedWithString:(NSString *)string 14 | font:(UIFont*)font 15 | color:(UIColor *)color; 16 | 17 | + (NSAttributedString *)attributedWithString:(NSString *)string 18 | font:(UIFont*)font 19 | color:(UIColor *)color 20 | wordSpacing:(CGFloat)wordSpacing 21 | lineSpacing:(CGFloat)lineSpacing; 22 | 23 | + (NSAttributedString *)attributedWithString:(NSString *)string 24 | font:(UIFont*)font 25 | color:(UIColor *)color 26 | wordSpacing:(CGFloat)wordSpacing 27 | lineSpacing:(CGFloat)lineSpacing 28 | range:(NSRange)range; 29 | 30 | //html片段转为富文本放在Label、Button上显示,这样HTML标签才会生效 31 | + (NSAttributedString*)htmlToAttString:(NSString*)string; 32 | 33 | 34 | //由于系统计算富文本的高度不正确,自己写了方法 35 | - (CGFloat)heightWithContainWidth:(CGFloat)width; 36 | @end 37 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSAttributedString+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+Category.m 3 | // PKWSevers 4 | // 5 | // Created by chenguangjiang on 16/5/23. 6 | // Copyright © 2016年 peikua. All rights reserved. 7 | // 8 | 9 | #import "NSAttributedString+Category.h" 10 | #import 11 | @implementation NSAttributedString (Category) 12 | + (NSAttributedString *)attributedWithString:(NSString *)string 13 | font:(UIFont*)font 14 | color:(UIColor *)color{ 15 | return [self attributedWithString:string font:font color:color wordSpacing:0 lineSpacing:0 range:NSMakeRange(0, string.length)]; 16 | } 17 | 18 | + (NSAttributedString *)attributedWithString:(NSString *)string 19 | font:(UIFont*)font 20 | color:(UIColor *)color 21 | wordSpacing:(CGFloat)wordSpacing 22 | lineSpacing:(CGFloat)lineSpacing{ 23 | return [self attributedWithString:string font:font color:color wordSpacing:wordSpacing lineSpacing:lineSpacing range:NSMakeRange(0, string.length)]; 24 | } 25 | 26 | 27 | + (NSAttributedString *)attributedWithString:(NSString *)string 28 | font:(UIFont*)font 29 | color:(UIColor *)color 30 | wordSpacing:(CGFloat)wordSpacing 31 | lineSpacing:(CGFloat)lineSpacing 32 | range:(NSRange)range{ 33 | if (string==NULL || string.length==0) { 34 | return [[NSAttributedString alloc] initWithString:@""]; 35 | } 36 | NSRange getRange = NSIntersectionRange(NSMakeRange(0, string.length), range); 37 | NSMutableDictionary* muAttbutes = [NSMutableDictionary dictionary]; 38 | if(color){ 39 | [muAttbutes setObject:color forKey:NSForegroundColorAttributeName]; 40 | } 41 | 42 | if(font){ 43 | [muAttbutes setObject:font forKey:NSFontAttributeName]; 44 | } 45 | 46 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 47 | 48 | if (wordSpacing > 0) { 49 | [muAttbutes setObject:@(wordSpacing) forKey:NSKernAttributeName]; 50 | 51 | } 52 | 53 | if (lineSpacing > 0) { 54 | [paragraphStyle setLineSpacing:lineSpacing]; 55 | [muAttbutes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName]; 56 | 57 | } 58 | 59 | 60 | NSDictionary * attributes = [NSDictionary dictionaryWithDictionary:muAttbutes]; 61 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string]; 62 | [attributedString addAttributes:attributes range:getRange]; 63 | 64 | return attributedString; 65 | 66 | } 67 | 68 | 69 | + (NSAttributedString*)htmlToAttString:(NSString*)string{ 70 | NSData* data = [string dataUsingEncoding:NSUnicodeStringEncoding]; 71 | NSDictionary* options = @{ 72 | NSDocumentTypeDocumentOption: NSHTMLTextDocumentType 73 | }; 74 | return [[NSAttributedString alloc]initWithData:data options:options documentAttributes:nil error:nil]; 75 | } 76 | 77 | 78 | - (CGFloat)heightWithContainWidth:(CGFloat)width{ 79 | int total_height = 0; 80 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self); 81 | CGRect drawingRect = CGRectMake(0, 0, width, 100000); 82 | CGMutablePathRef path = CGPathCreateMutable(); 83 | CGPathAddRect(path, NULL, drawingRect); 84 | CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL); 85 | CGPathRelease(path); 86 | CFRelease(framesetter); 87 | 88 | NSArray *linesArray = (NSArray *) CTFrameGetLines(textFrame); 89 | if(linesArray.count == 0)return 0; 90 | CGPoint origins[[linesArray count]]; 91 | CTFrameGetLineOrigins(textFrame, CFRangeMake(0, 0), origins); 92 | int line_y = (int) origins[[linesArray count] -1].y; 93 | CGFloat ascent; 94 | CGFloat descent; 95 | CGFloat leading; 96 | CTLineRef line = (__bridge CTLineRef) [linesArray objectAtIndex:[linesArray count]-1]; 97 | CTLineGetTypographicBounds(line, &ascent, &descent, &leading); 98 | 99 | total_height = 100000 - line_y + (int) descent +1; 100 | CFRelease(textFrame); 101 | return total_height; 102 | } 103 | @end 104 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSData+CommonCryptor.h: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | #import 11 | #import 12 | 13 | 14 | extern NSString * const kCommonCryptoErrorDomain; 15 | 16 | @interface NSError (CommonCryptoErrorDomain) 17 | + (NSError *) errorWithCCCryptorStatus: (CCCryptorStatus) status; 18 | @end 19 | 20 | @interface NSData (CommonDigest) 21 | 22 | - (NSData *) MD2Sum; 23 | - (NSData *) MD4Sum; 24 | - (NSData *) MD5Sum; 25 | 26 | - (NSData *) SHA1Hash; 27 | - (NSData *) SHA224Hash; 28 | - (NSData *) SHA256Hash; 29 | - (NSData *) SHA384Hash; 30 | - (NSData *) SHA512Hash; 31 | 32 | @end 33 | 34 | @interface NSData (CommonCryptor) 35 | 36 | - (NSData *) AES256EncryptedDataUsingKey: (id) key error: (NSError **) error; 37 | - (NSData *) decryptedAES256DataUsingKey: (id) key error: (NSError **) error; 38 | 39 | - (NSData *) DESEncryptedDataUsingKey: (id) key error: (NSError **) error; 40 | - (NSData *) decryptedDESDataUsingKey: (id) key error: (NSError **) error; 41 | 42 | - (NSData *) CASTEncryptedDataUsingKey: (id) key error: (NSError **) error; 43 | - (NSData *) decryptedCASTDataUsingKey: (id) key error: (NSError **) error; 44 | 45 | @end 46 | 47 | @interface NSData (LowLevelCommonCryptor) 48 | 49 | - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm 50 | key: (id) key // data or string 51 | error: (CCCryptorStatus *) error; 52 | - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm 53 | key: (id) key // data or string 54 | options: (CCOptions) options 55 | error: (CCCryptorStatus *) error; 56 | - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm 57 | key: (id) key // data or string 58 | initializationVector: (id) iv // data or string 59 | options: (CCOptions) options 60 | error: (CCCryptorStatus *) error; 61 | 62 | - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm 63 | key: (id) key // data or string 64 | error: (CCCryptorStatus *) error; 65 | - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm 66 | key: (id) key // data or string 67 | options: (CCOptions) options 68 | error: (CCCryptorStatus *) error; 69 | - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm 70 | key: (id) key // data or string 71 | initializationVector: (id) iv // data or string 72 | options: (CCOptions) options 73 | error: (CCCryptorStatus *) error; 74 | 75 | @end 76 | 77 | @interface NSData (CommonHMAC) 78 | 79 | - (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm; 80 | - (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm key: (id) key; 81 | 82 | @end 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSData+CommonCryptor.m: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import "NSData+CommonCryptor.h" 9 | #import 10 | #import 11 | #import 12 | #import 13 | 14 | 15 | NSString * const kCommonCryptoErrorDomain = @"CommonCryptoErrorDomain"; 16 | 17 | @implementation NSError (CommonCryptoErrorDomain) 18 | 19 | + (NSError *) errorWithCCCryptorStatus: (CCCryptorStatus) status 20 | { 21 | NSString * description = nil, * reason = nil; 22 | 23 | switch ( status ) 24 | { 25 | case kCCSuccess: 26 | description = NSLocalizedString(@"Success", @"Error description"); 27 | break; 28 | 29 | case kCCParamError: 30 | description = NSLocalizedString(@"Parameter Error", @"Error description"); 31 | reason = NSLocalizedString(@"Illegal parameter supplied to encryption/decryption algorithm", @"Error reason"); 32 | break; 33 | 34 | case kCCBufferTooSmall: 35 | description = NSLocalizedString(@"Buffer Too Small", @"Error description"); 36 | reason = NSLocalizedString(@"Insufficient buffer provided for specified operation", @"Error reason"); 37 | break; 38 | 39 | case kCCMemoryFailure: 40 | description = NSLocalizedString(@"Memory Failure", @"Error description"); 41 | reason = NSLocalizedString(@"Failed to allocate memory", @"Error reason"); 42 | break; 43 | 44 | case kCCAlignmentError: 45 | description = NSLocalizedString(@"Alignment Error", @"Error description"); 46 | reason = NSLocalizedString(@"Input size to encryption algorithm was not aligned correctly", @"Error reason"); 47 | break; 48 | 49 | case kCCDecodeError: 50 | description = NSLocalizedString(@"Decode Error", @"Error description"); 51 | reason = NSLocalizedString(@"Input data did not decode or decrypt correctly", @"Error reason"); 52 | break; 53 | 54 | case kCCUnimplemented: 55 | description = NSLocalizedString(@"Unimplemented Function", @"Error description"); 56 | reason = NSLocalizedString(@"Function not implemented for the current algorithm", @"Error reason"); 57 | break; 58 | 59 | default: 60 | description = NSLocalizedString(@"Unknown Error", @"Error description"); 61 | break; 62 | } 63 | 64 | NSMutableDictionary * userInfo = [[NSMutableDictionary alloc] init]; 65 | [userInfo setObject: description forKey: NSLocalizedDescriptionKey]; 66 | 67 | if ( reason != nil ) 68 | [userInfo setObject: reason forKey: NSLocalizedFailureReasonErrorKey]; 69 | 70 | NSError * result = [NSError errorWithDomain: kCommonCryptoErrorDomain code: status userInfo: userInfo]; 71 | #if !__has_feature(objc_arc) 72 | [userInfo release]; 73 | #endif 74 | 75 | return ( result ); 76 | } 77 | 78 | @end 79 | 80 | #pragma mark - 81 | 82 | @implementation NSData (CommonDigest) 83 | 84 | - (NSData *) MD2Sum 85 | { 86 | unsigned char hash[CC_MD2_DIGEST_LENGTH]; 87 | (void) CC_MD2( [self bytes], (CC_LONG)[self length], hash ); 88 | return ( [NSData dataWithBytes: hash length: CC_MD2_DIGEST_LENGTH] ); 89 | } 90 | 91 | - (NSData *) MD4Sum 92 | { 93 | unsigned char hash[CC_MD4_DIGEST_LENGTH]; 94 | (void) CC_MD4( [self bytes], (CC_LONG)[self length], hash ); 95 | return ( [NSData dataWithBytes: hash length: CC_MD4_DIGEST_LENGTH] ); 96 | } 97 | 98 | - (NSData *) MD5Sum 99 | { 100 | unsigned char hash[CC_MD5_DIGEST_LENGTH]; 101 | (void) CC_MD5( [self bytes], (CC_LONG)[self length], hash ); 102 | return ( [NSData dataWithBytes: hash length: CC_MD5_DIGEST_LENGTH] ); 103 | } 104 | 105 | - (NSData *) SHA1Hash 106 | { 107 | unsigned char hash[CC_SHA1_DIGEST_LENGTH]; 108 | (void) CC_SHA1( [self bytes], (CC_LONG)[self length], hash ); 109 | return ( [NSData dataWithBytes: hash length: CC_SHA1_DIGEST_LENGTH] ); 110 | } 111 | 112 | - (NSData *) SHA224Hash 113 | { 114 | unsigned char hash[CC_SHA224_DIGEST_LENGTH]; 115 | (void) CC_SHA224( [self bytes], (CC_LONG)[self length], hash ); 116 | return ( [NSData dataWithBytes: hash length: CC_SHA224_DIGEST_LENGTH] ); 117 | } 118 | 119 | - (NSData *) SHA256Hash 120 | { 121 | unsigned char hash[CC_SHA256_DIGEST_LENGTH]; 122 | (void) CC_SHA256( [self bytes], (CC_LONG)[self length], hash ); 123 | return ( [NSData dataWithBytes: hash length: CC_SHA256_DIGEST_LENGTH] ); 124 | } 125 | 126 | - (NSData *) SHA384Hash 127 | { 128 | unsigned char hash[CC_SHA384_DIGEST_LENGTH]; 129 | (void) CC_SHA384( [self bytes], (CC_LONG)[self length], hash ); 130 | return ( [NSData dataWithBytes: hash length: CC_SHA384_DIGEST_LENGTH] ); 131 | } 132 | 133 | - (NSData *) SHA512Hash 134 | { 135 | unsigned char hash[CC_SHA512_DIGEST_LENGTH]; 136 | (void) CC_SHA512( [self bytes], (CC_LONG)[self length], hash ); 137 | return ( [NSData dataWithBytes: hash length: CC_SHA512_DIGEST_LENGTH] ); 138 | } 139 | 140 | @end 141 | 142 | @implementation NSData (CommonCryptor) 143 | 144 | - (NSData *) AES256EncryptedDataUsingKey: (id) key error: (NSError **) error 145 | { 146 | CCCryptorStatus status = kCCSuccess; 147 | NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmAES128 148 | key: key 149 | options: kCCOptionPKCS7Padding 150 | error: &status]; 151 | 152 | if ( result != nil ) 153 | return ( result ); 154 | 155 | if ( error != NULL ) 156 | *error = [NSError errorWithCCCryptorStatus: status]; 157 | 158 | return ( nil ); 159 | } 160 | 161 | - (NSData *) decryptedAES256DataUsingKey: (id) key error: (NSError **) error 162 | { 163 | CCCryptorStatus status = kCCSuccess; 164 | NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmAES128 165 | key: key 166 | options: kCCOptionPKCS7Padding 167 | error: &status]; 168 | 169 | if ( result != nil ) 170 | return ( result ); 171 | 172 | if ( error != NULL ) 173 | *error = [NSError errorWithCCCryptorStatus: status]; 174 | 175 | return ( nil ); 176 | } 177 | 178 | - (NSData *) DESEncryptedDataUsingKey: (id) key error: (NSError **) error 179 | { 180 | CCCryptorStatus status = kCCSuccess; 181 | NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmDES 182 | key: key 183 | options: kCCOptionPKCS7Padding 184 | error: &status]; 185 | 186 | if ( result != nil ) 187 | return ( result ); 188 | 189 | if ( error != NULL ) 190 | *error = [NSError errorWithCCCryptorStatus: status]; 191 | 192 | return ( nil ); 193 | } 194 | 195 | - (NSData *) decryptedDESDataUsingKey: (id) key error: (NSError **) error 196 | { 197 | CCCryptorStatus status = kCCSuccess; 198 | NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmDES 199 | key: key 200 | options: kCCOptionPKCS7Padding 201 | error: &status]; 202 | 203 | if ( result != nil ) 204 | return ( result ); 205 | 206 | if ( error != NULL ) 207 | *error = [NSError errorWithCCCryptorStatus: status]; 208 | 209 | return ( nil ); 210 | } 211 | 212 | - (NSData *) CASTEncryptedDataUsingKey: (id) key error: (NSError **) error 213 | { 214 | CCCryptorStatus status = kCCSuccess; 215 | NSData * result = [self dataEncryptedUsingAlgorithm: kCCAlgorithmCAST 216 | key: key 217 | options: kCCOptionPKCS7Padding 218 | error: &status]; 219 | 220 | if ( result != nil ) 221 | return ( result ); 222 | 223 | if ( error != NULL ) 224 | *error = [NSError errorWithCCCryptorStatus: status]; 225 | 226 | return ( nil ); 227 | } 228 | 229 | - (NSData *) decryptedCASTDataUsingKey: (id) key error: (NSError **) error 230 | { 231 | CCCryptorStatus status = kCCSuccess; 232 | NSData * result = [self decryptedDataUsingAlgorithm: kCCAlgorithmCAST 233 | key: key 234 | options: kCCOptionPKCS7Padding 235 | error: &status]; 236 | 237 | if ( result != nil ) 238 | return ( result ); 239 | 240 | if ( error != NULL ) 241 | *error = [NSError errorWithCCCryptorStatus: status]; 242 | 243 | return ( nil ); 244 | } 245 | 246 | @end 247 | 248 | static void FixKeyLengths( CCAlgorithm algorithm, NSMutableData * keyData, NSMutableData * ivData ) 249 | { 250 | NSUInteger keyLength = [keyData length]; 251 | switch ( algorithm ) 252 | { 253 | case kCCAlgorithmAES128: 254 | { 255 | if ( keyLength < 16 ) 256 | { 257 | [keyData setLength: 16]; 258 | } 259 | else if ( keyLength < 24 ) 260 | { 261 | [keyData setLength: 24]; 262 | } 263 | else 264 | { 265 | [keyData setLength: 32]; 266 | } 267 | 268 | break; 269 | } 270 | 271 | case kCCAlgorithmDES: 272 | { 273 | [keyData setLength: 8]; 274 | break; 275 | } 276 | 277 | case kCCAlgorithm3DES: 278 | { 279 | [keyData setLength: 24]; 280 | break; 281 | } 282 | 283 | case kCCAlgorithmCAST: 284 | { 285 | if ( keyLength < 5 ) 286 | { 287 | [keyData setLength: 5]; 288 | } 289 | else if ( keyLength > 16 ) 290 | { 291 | [keyData setLength: 16]; 292 | } 293 | 294 | break; 295 | } 296 | 297 | case kCCAlgorithmRC4: 298 | { 299 | if ( keyLength > 512 ) 300 | [keyData setLength: 512]; 301 | break; 302 | } 303 | 304 | default: 305 | break; 306 | } 307 | 308 | [ivData setLength: [keyData length]]; 309 | } 310 | 311 | @implementation NSData (LowLevelCommonCryptor) 312 | 313 | - (NSData *) _runCryptor: (CCCryptorRef) cryptor result: (CCCryptorStatus *) status 314 | { 315 | size_t bufsize = CCCryptorGetOutputLength( cryptor, (size_t)[self length], true ); 316 | void * buf = malloc( bufsize ); 317 | size_t bufused = 0; 318 | size_t bytesTotal = 0; 319 | *status = CCCryptorUpdate( cryptor, [self bytes], (size_t)[self length], 320 | buf, bufsize, &bufused ); 321 | if ( *status != kCCSuccess ) 322 | { 323 | free( buf ); 324 | return ( nil ); 325 | } 326 | 327 | bytesTotal += bufused; 328 | 329 | // From Brent Royal-Gordon (Twitter: architechies): 330 | // Need to update buf ptr past used bytes when calling CCCryptorFinal() 331 | *status = CCCryptorFinal( cryptor, buf + bufused, bufsize - bufused, &bufused ); 332 | if ( *status != kCCSuccess ) 333 | { 334 | free( buf ); 335 | return ( nil ); 336 | } 337 | 338 | bytesTotal += bufused; 339 | 340 | return ( [NSData dataWithBytesNoCopy: buf length: bytesTotal] ); 341 | } 342 | 343 | - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm 344 | key: (id) key 345 | error: (CCCryptorStatus *) error 346 | { 347 | return ( [self dataEncryptedUsingAlgorithm: algorithm 348 | key: key 349 | initializationVector: nil 350 | options: 0 351 | error: error] ); 352 | } 353 | 354 | - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm 355 | key: (id) key 356 | options: (CCOptions) options 357 | error: (CCCryptorStatus *) error 358 | { 359 | return ( [self dataEncryptedUsingAlgorithm: algorithm 360 | key: key 361 | initializationVector: nil 362 | options: options 363 | error: error] ); 364 | } 365 | 366 | - (NSData *) dataEncryptedUsingAlgorithm: (CCAlgorithm) algorithm 367 | key: (id) key 368 | initializationVector: (id) iv 369 | options: (CCOptions) options 370 | error: (CCCryptorStatus *) error 371 | { 372 | CCCryptorRef cryptor = NULL; 373 | CCCryptorStatus status = kCCSuccess; 374 | 375 | NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); 376 | NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]); 377 | 378 | NSMutableData * keyData, * ivData; 379 | if ( [key isKindOfClass: [NSData class]] ) 380 | keyData = (NSMutableData *) [key mutableCopy]; 381 | else 382 | keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; 383 | 384 | if ( [iv isKindOfClass: [NSString class]] ) 385 | ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; 386 | else 387 | ivData = (NSMutableData *) [iv mutableCopy]; // data or nil 388 | 389 | #if !__has_feature(objc_arc) 390 | [keyData autorelease]; 391 | [ivData autorelease]; 392 | #endif 393 | // ensure correct lengths for key and iv data, based on algorithms 394 | FixKeyLengths( algorithm, keyData, ivData ); 395 | 396 | status = CCCryptorCreate( kCCEncrypt, algorithm, options, 397 | [keyData bytes], [keyData length], [ivData bytes], 398 | &cryptor ); 399 | 400 | if ( status != kCCSuccess ) 401 | { 402 | if ( error != NULL ) 403 | *error = status; 404 | return ( nil ); 405 | } 406 | 407 | NSData * result = [self _runCryptor: cryptor result: &status]; 408 | if ( (result == nil) && (error != NULL) ) 409 | *error = status; 410 | 411 | CCCryptorRelease( cryptor ); 412 | 413 | return ( result ); 414 | } 415 | 416 | - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm 417 | key: (id) key // data or string 418 | error: (CCCryptorStatus *) error 419 | { 420 | return ( [self decryptedDataUsingAlgorithm: algorithm 421 | key: key 422 | initializationVector: nil 423 | options: 0 424 | error: error] ); 425 | } 426 | 427 | - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm 428 | key: (id) key // data or string 429 | options: (CCOptions) options 430 | error: (CCCryptorStatus *) error 431 | { 432 | return ( [self decryptedDataUsingAlgorithm: algorithm 433 | key: key 434 | initializationVector: nil 435 | options: options 436 | error: error] ); 437 | } 438 | 439 | - (NSData *) decryptedDataUsingAlgorithm: (CCAlgorithm) algorithm 440 | key: (id) key // data or string 441 | initializationVector: (id) iv // data or string 442 | options: (CCOptions) options 443 | error: (CCCryptorStatus *) error 444 | { 445 | CCCryptorRef cryptor = NULL; 446 | CCCryptorStatus status = kCCSuccess; 447 | 448 | NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); 449 | NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]); 450 | 451 | NSMutableData * keyData, * ivData; 452 | if ( [key isKindOfClass: [NSData class]] ) 453 | keyData = (NSMutableData *) [key mutableCopy]; 454 | else 455 | keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; 456 | 457 | if ( [iv isKindOfClass: [NSString class]] ) 458 | ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy]; 459 | else 460 | ivData = (NSMutableData *) [iv mutableCopy]; // data or nil 461 | 462 | #if !__has_feature(objc_arc) 463 | [keyData autorelease]; 464 | [ivData autorelease]; 465 | #endif 466 | 467 | // ensure correct lengths for key and iv data, based on algorithms 468 | FixKeyLengths( algorithm, keyData, ivData ); 469 | 470 | status = CCCryptorCreate( kCCDecrypt, algorithm, options, 471 | [keyData bytes], [keyData length], [ivData bytes], 472 | &cryptor ); 473 | 474 | if ( status != kCCSuccess ) 475 | { 476 | if ( error != NULL ) 477 | *error = status; 478 | return ( nil ); 479 | } 480 | 481 | NSData * result = [self _runCryptor: cryptor result: &status]; 482 | if ( (result == nil) && (error != NULL) ) 483 | *error = status; 484 | 485 | CCCryptorRelease( cryptor ); 486 | 487 | return ( result ); 488 | } 489 | 490 | @end 491 | 492 | @implementation NSData (CommonHMAC) 493 | 494 | - (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm 495 | { 496 | return ( [self HMACWithAlgorithm: algorithm key: nil] ); 497 | } 498 | 499 | - (NSData *) HMACWithAlgorithm: (CCHmacAlgorithm) algorithm key: (id) key 500 | { 501 | NSParameterAssert(key == nil || [key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]); 502 | 503 | NSData * keyData = nil; 504 | if ( [key isKindOfClass: [NSString class]] ) 505 | keyData = [key dataUsingEncoding: NSUTF8StringEncoding]; 506 | else 507 | keyData = (NSData *) key; 508 | 509 | // this could be either CC_SHA1_DIGEST_LENGTH or CC_MD5_DIGEST_LENGTH. SHA1 is larger. 510 | unsigned char buf[CC_SHA1_DIGEST_LENGTH]; 511 | CCHmac( algorithm, [keyData bytes], [keyData length], [self bytes], [self length], buf ); 512 | 513 | return ( [NSData dataWithBytes: buf length: (algorithm == kCCHmacAlgMD5 ? CC_MD5_DIGEST_LENGTH : CC_SHA1_DIGEST_LENGTH)] ); 514 | } 515 | 516 | @end 517 | 518 | 519 | 520 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSDate+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+Category.h 3 | // iOS-Category 4 | // 5 | // Created by zhuangbb on 2020/5/30. 6 | // Copyright © 2020 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSDate (Category) 14 | #pragma mark - 返回NSString部分 15 | 16 | /// NSDate转格式显示 17 | /// @param date 例如:[NSDate date] 18 | /// @param formatter @"yyyy-MM-dd" 19 | + (NSString *)dateToString:(NSDate *)date dateFormatter:(NSString *)formatter; 20 | 21 | /// 时间戳转格式显示 22 | /// @param timeInterval 23 | /// @param formatter @"yyyy-MM-dd" 24 | + (NSString *)timeIntervalToString:(NSTimeInterval)timeInterval dateFormatter:(NSString *)formatter; 25 | 26 | #pragma mark - 返回NSDate部分 27 | 28 | /// 根据显示时间的字符串返回NSDate 29 | /// @param timeString 例如:1980-01-01 30 | /// @param format @"yyyy-MM-dd" 31 | + (NSDate *)dateWithDateString:(NSString *)timeString formatString:(NSString *)format; 32 | 33 | /// 在已有NSDate的情况下,加减具体数字的年月日,获取未来或者过去的NSDate 34 | /// @param presentDate 35 | /// @param year 小于0为过去,大于0则为未来 36 | /// @param month 37 | /// @param day 38 | + (NSDate *)dateWithPresentDate:(NSDate*)presentDate year:(NSInteger)year month:(NSInteger)month day:(NSInteger)day; 39 | 40 | /// 根据具体的年月日获取NSDate 41 | /// @param year 42 | /// @param month 43 | /// @param day 44 | + (NSDate *)dateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day; 45 | 46 | #pragma mark - 返回整型部分 47 | /// 根据前后NSDate,获取中间差了多少天 48 | /// @param startDate 开始时间 49 | /// @param endDate 结束时间 50 | + (NSInteger)daysBetweenStartDate:(NSDate *)startDate endDate:(NSDate *)endDate; 51 | 52 | /// 获取传入Date对应的月份有多少天 53 | /// @param date 54 | + (NSInteger)totaldaysInMonth:(NSDate *)date; 55 | 56 | // 是否和当前同一天 57 | + (BOOL)isCurrentDay:(NSDate *)date; 58 | @end 59 | 60 | NS_ASSUME_NONNULL_END 61 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSDate+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+Category.m 3 | // iOS-Category 4 | // 5 | // Created by zhuangbb on 2020/5/30. 6 | // Copyright © 2020 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSDate+Category.h" 10 | 11 | @implementation NSDate (Category) 12 | //内部方法、也可以自己暴露 13 | + (NSDateFormatter *)setDateFormatter:(NSString *)formatter { 14 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 15 | [dateFormatter setDateFormat:formatter]; 16 | //这条很重要,不加的话。手机设置选择外国可能就会返回中文 17 | [dateFormatter setLocale:[NSLocale currentLocale]]; 18 | return dateFormatter; 19 | } 20 | 21 | + (NSDateComponents *)components:(NSDate *)date { 22 | NSDateFormatter *dateFormatter = [[self class] setDateFormatter:@"yyyy-MM-dd"]; 23 | NSString *dateString = [NSDate timeIntervalToString:date.timeIntervalSince1970 dateFormatter:dateFormatter.dateFormat]; 24 | NSDate *startDate = [dateFormatter dateFromString:dateString]; 25 | NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | kCFCalendarUnitWeekday | kCFCalendarUnitWeekdayOrdinal) fromDate:startDate]; 26 | 27 | return components; 28 | } 29 | #pragma mark - 返回NSString部分 30 | + (NSString *)dateToString:(NSDate *)date dateFormatter:(NSString *)formatter { 31 | NSDateFormatter *dateFormatter = [[self class] setDateFormatter:formatter]; 32 | NSString *dateString = [dateFormatter stringFromDate:date]; 33 | return dateString; 34 | } 35 | 36 | + (NSString *)timeIntervalToString:(NSTimeInterval)timeInterval dateFormatter:(NSString *)formatter { 37 | NSDateFormatter *dateFormatter = [[self class] setDateFormatter:formatter]; 38 | NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval]; 39 | NSString *dateString = [dateFormatter stringFromDate:date]; 40 | return dateString; 41 | } 42 | #pragma mark - 返回NSDate部分 43 | 44 | + (NSDate *)dateWithDateString:(NSString *)dateString formatString:(NSString *)format { 45 | NSDateFormatter *dateFormatter = [[self class] setDateFormatter:format]; 46 | NSDate *date = [dateFormatter dateFromString:dateString]; 47 | return date; 48 | } 49 | 50 | + (NSDate *)dateWithPresentDate:(NSDate*)presentDate year:(NSInteger)year month:(NSInteger)month day:(NSInteger)day{ 51 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 52 | 53 | NSDateComponents *adcomps = [[NSDateComponents alloc] init]; 54 | 55 | [adcomps setYear:year]; 56 | 57 | [adcomps setMonth:month]; 58 | 59 | [adcomps setDay:day]; 60 | 61 | return [calendar dateByAddingComponents:adcomps toDate:presentDate options:0]; 62 | } 63 | 64 | + (NSDate *)dateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day{ 65 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 66 | 67 | NSDateComponents *adcomps = [[NSDateComponents alloc] init]; 68 | 69 | [adcomps setYear:year]; 70 | 71 | [adcomps setMonth:month]; 72 | 73 | [adcomps setDay:day]; 74 | 75 | return [calendar dateFromComponents:adcomps]; 76 | } 77 | #pragma mark - 返回整型部分 78 | 79 | + (NSInteger)daysBetweenStartDate:(NSDate *)startDate endDate:(NSDate *)endDate { 80 | NSDateComponents *startComponents = [NSDate components:startDate]; 81 | NSDateComponents *endComponents = [NSDate components:endDate]; 82 | 83 | NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay fromDateComponents:startComponents toDateComponents:endComponents options:nil]; 84 | 85 | return components.day; 86 | } 87 | 88 | // 获取当前月共有多少天 89 | + (NSInteger)totaldaysInMonth:(NSDate *)date { 90 | NSRange daysInLastMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date]; 91 | 92 | return daysInLastMonth.length; 93 | } 94 | 95 | // 日期判断 96 | 97 | + (BOOL)isCurrentDay:(NSDate *)date { 98 | BOOL result = NO; 99 | 100 | NSString *dateString = [NSDate dateToString:date dateFormatter:@"yyyy-MM-dd"]; 101 | NSString *nowString = [NSDate dateToString:[NSDate date] dateFormatter:@"yyyy-MM-dd"]; 102 | 103 | if ([dateString isEqualToString:nowString]) { 104 | result = YES; 105 | } 106 | 107 | return result; 108 | } 109 | 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSDictionary+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface NSDictionary (Category) 11 | 12 | + (NSDictionary *)JSONStringTransToDic:(NSString *)JSONString; 13 | @end 14 | 15 | 16 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSDictionary+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import "NSDictionary+Category.h" 9 | 10 | 11 | @implementation NSDictionary (Category) 12 | 13 | + (NSDictionary *)JSONStringTransToDic:(NSString *)JSONString { 14 | if (JSONString == nil) { 15 | return nil; 16 | } 17 | NSData *jsonData = [JSONString dataUsingEncoding:NSUTF8StringEncoding]; 18 | NSError *err; 19 | NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData 20 | 21 | options:NSJSONReadingMutableContainers 22 | 23 | error:&err]; 24 | if(err) { 25 | NSLog(@"json解析失败:%@",err); 26 | return nil; 27 | } 28 | return dic; 29 | } 30 | 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSDictionary+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Safe.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2018/5/18. 6 | // Copyright © 2018年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (Safe) 12 | 13 | - (id)safeObjectForKey:(NSString *)key; 14 | 15 | - (void)safeSetValue:(id)object forKey:(id)key; 16 | 17 | - (id)objectForKeyCustom:(id)aKey; 18 | 19 | - (id)safeKeyForValue:(id)value; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSDictionary+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Safe.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2018/5/18. 6 | // Copyright © 2018年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+Safe.h" 10 | 11 | @implementation NSDictionary (Safe) 12 | 13 | - (id)safeObjectForKey:(NSString *)key { 14 | if (key == nil || [self isKindOfClass:[NSNull class]]) { 15 | return nil; 16 | } 17 | id object = [self objectForKey:key]; 18 | if (object==nil || object == [NSNull null]) { 19 | return @""; 20 | } 21 | return object; 22 | } 23 | 24 | 25 | - (void)safeSetValue:(id)object forKey:(id)key { 26 | if ([key isKindOfClass:[NSNull class]]) { 27 | return; 28 | } 29 | if ([object isKindOfClass:[NSNull class]]) { 30 | [self setValue:@"" forKey:key]; 31 | }else{ 32 | [self setValue:object forKey:key]; 33 | } 34 | } 35 | 36 | - (id)objectForKeyCustom:(id)aKey { 37 | id object = nil; 38 | 39 | // 检查是否字典对象 40 | if (![self isKindOfClass:[NSDictionary class]]) { 41 | return object; 42 | } 43 | 44 | // 保证key必须为字符串 45 | if (aKey && [aKey isKindOfClass:[NSString class]]) { 46 | object = [self objectForKeyCustom:aKey]; 47 | } 48 | 49 | return object; 50 | } 51 | 52 | - (id)safeKeyForValue:(id)value { 53 | for (id key in self.allKeys) { 54 | if ([value isEqual:[self objectForKey:key]]) { 55 | return key; 56 | } 57 | } 58 | return nil; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSMutableArray+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArray+Safe.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2018/5/18. 6 | // Copyright © 2018年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableArray (Safe) 12 | - (void)safeAddObject:(id)object; 13 | 14 | - (void)safeInsertObject:(id)object atIndex:(NSUInteger)index; 15 | 16 | - (void)safeInsertObjects:(NSArray *)objects atIndexes:(NSIndexSet *)indexs; 17 | 18 | - (void)safeRemoveObjectAtIndex:(NSUInteger)index; 19 | 20 | - (void)safeRemoveObjectsInRange:(NSRange)range; 21 | @end 22 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSMutableArray+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArray+Safe.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2018/5/18. 6 | // Copyright © 2018年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSMutableArray+Safe.h" 10 | 11 | @implementation NSMutableArray (Safe) 12 | 13 | - (void)safeAddObject:(id)object 14 | { 15 | if (object == nil) { 16 | return; 17 | } else { 18 | [self addObject:object]; 19 | } 20 | } 21 | 22 | - (void)safeInsertObject:(id)object atIndex:(NSUInteger)index 23 | { 24 | if (object == nil) { 25 | return; 26 | } else if (index > self.count) { 27 | return; 28 | } else { 29 | [self insertObject:object atIndex:index]; 30 | } 31 | } 32 | 33 | - (void)safeInsertObjects:(NSArray *)objects atIndexes:(NSIndexSet *)indexs 34 | { 35 | NSUInteger firstIndex = indexs.firstIndex; 36 | if (indexs == nil) { 37 | return; 38 | } else if (indexs.count!=objects.count || firstIndex>objects.count) { 39 | return; 40 | } else { 41 | [self insertObjects:objects atIndexes:indexs]; 42 | } 43 | } 44 | 45 | - (void)safeRemoveObjectAtIndex:(NSUInteger)index 46 | { 47 | if (index >= self.count) { 48 | return; 49 | } else { 50 | [self removeObjectAtIndex:index]; 51 | } 52 | } 53 | 54 | - (void)safeRemoveObjectsInRange:(NSRange)range 55 | { 56 | NSUInteger location = range.location; 57 | NSUInteger length = range.length; 58 | if (location + length > self.count) { 59 | return; 60 | } else { 61 | [self removeObjectsInRange:range]; 62 | } 63 | } 64 | @end 65 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSMutableDictionary+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+Safe.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2018/5/18. 6 | // Copyright © 2018年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableDictionary (Safe) 12 | 13 | - (void)safeSetObject:(id)aObj forKey:(id)aKey; 14 | 15 | - (id)safeObjectForKey:(id)aKey; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSMutableDictionary+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+Safe.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2018/5/18. 6 | // Copyright © 2018年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSMutableDictionary+Safe.h" 10 | 11 | @implementation NSMutableDictionary (Safe) 12 | 13 | - (void)safeSetObject:(id)aObj forKey:(id)aKey 14 | { 15 | if (aObj && ![aObj isKindOfClass:[NSNull class]] && aKey) { 16 | [self setObject:aObj forKey:aKey]; 17 | } else { 18 | return; 19 | } 20 | } 21 | 22 | - (id)safeObjectForKey:(id)aKey 23 | { 24 | if (aKey != nil) { 25 | return [self objectForKey:aKey]; 26 | } else { 27 | return nil; 28 | } 29 | } 30 | @end 31 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSMutableString+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableString+Safe.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/24. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableString (Safe) 12 | - (void)safeInsertString:(NSString *)aString atIndex:(NSUInteger)loc; 13 | 14 | - (void)safeAppendString:(NSString *)aString; 15 | 16 | - (void)safeSetString:(NSString *)aString; 17 | 18 | - (NSUInteger)safeReplaceOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange; 19 | @end 20 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSMutableString+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableString+Safe.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/24. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSMutableString+Safe.h" 10 | 11 | @implementation NSMutableString (Safe) 12 | 13 | - (void)safeInsertString:(NSString *)aString atIndex:(NSUInteger)loc 14 | { 15 | if (aString == nil) { 16 | return; 17 | } else if (loc > self.length) { 18 | return; 19 | } else { 20 | [self insertString:aString atIndex:loc]; 21 | } 22 | } 23 | 24 | - (void)safeAppendString:(NSString *)aString 25 | { 26 | if (aString == nil) { 27 | return; 28 | } else { 29 | [self appendString:aString]; 30 | } 31 | } 32 | 33 | - (void)safeSetString:(NSString *)aString 34 | { 35 | if (aString == nil) { 36 | return; 37 | } else { 38 | [self setString:aString]; 39 | } 40 | } 41 | 42 | - (NSUInteger)safeReplaceOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange 43 | { 44 | NSUInteger location = searchRange.location; 45 | NSUInteger length = searchRange.length; 46 | 47 | if (target == nil || replacement == nil) { 48 | return 0; 49 | } else if (location + length > self.length) { 50 | return 0; 51 | } else { 52 | return [self replaceOccurrencesOfString:target withString:replacement options:options range:searchRange]; 53 | } 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSObject+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Category.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NSObject (Category) 13 | @property (nonatomic, strong, readonly) NSMutableArray *associatedObjectNames; 14 | 15 | /** 16 | * 为当前object动态增加分类 17 | * 18 | * @param propertyName 分类名称 19 | * @param value 分类值 20 | * @param policy 分类内存管理类型 21 | */ 22 | - (void)objc_setAssociatedObject:(NSString *)propertyName value:(id)value policy:(objc_AssociationPolicy)policy; 23 | /** 24 | * 获取当前object某个动态增加的分类 25 | * 26 | * @param propertyName 分类名称 27 | * 28 | * @return 值 29 | */ 30 | - (id)objc_getAssociatedObject:(NSString *)propertyName; 31 | /** 32 | * 删除动态增加的所有分类 33 | */ 34 | - (void)objc_removeAssociatedObjects; 35 | 36 | /** 37 | * 获取对象的所有属性 38 | * 39 | * @return 属性dict 40 | */ 41 | - (NSArray *)getProperties; 42 | 43 | 44 | @end 45 | 46 | 47 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSObject+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Category.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Category.h" 10 | 11 | @implementation NSObject (Category) 12 | static char associatedObjectNamesKey; 13 | 14 | - (void)setAssociatedObjectNames:(NSMutableArray *)associatedObjectNames 15 | { 16 | objc_setAssociatedObject(self, &associatedObjectNamesKey, associatedObjectNames,OBJC_ASSOCIATION_RETAIN_NONATOMIC); 17 | } 18 | 19 | - (NSMutableArray *)associatedObjectNames 20 | { 21 | NSMutableArray *array = objc_getAssociatedObject(self, &associatedObjectNamesKey); 22 | if (!array) { 23 | array = [NSMutableArray array]; 24 | [self setAssociatedObjectNames:array]; 25 | } 26 | return array; 27 | } 28 | 29 | - (void)objc_setAssociatedObject:(NSString *)propertyName value:(id)value policy:(objc_AssociationPolicy)policy 30 | { 31 | objc_setAssociatedObject(self, (__bridge objc_objectptr_t)propertyName, value, policy); 32 | [self.associatedObjectNames addObject:propertyName]; 33 | } 34 | 35 | - (id)objc_getAssociatedObject:(NSString *)propertyName 36 | { 37 | return objc_getAssociatedObject(self, (__bridge objc_objectptr_t)propertyName); 38 | } 39 | 40 | - (void)objc_removeAssociatedObjects 41 | { 42 | [self.associatedObjectNames removeAllObjects]; 43 | objc_removeAssociatedObjects(self); 44 | } 45 | 46 | - (void)setValue:(id)value forUndefinedKey:(NSString *)key 47 | { 48 | NSLog(@"setValue %@ forUndefinedKey %@",value,key); 49 | } 50 | 51 | - (void)setNilValueForKey:(NSString *)key 52 | { 53 | NSLog(@"setNilValue forKey %@",key); 54 | } 55 | 56 | /** 57 | * 获取对象的所有属性,包括父类的。可以一直遍历到JSONModel层。如果不是继承JSONMOdel,最上层为NSObject 58 | * 59 | * @return Properties数组 60 | */ 61 | - (NSArray *)getProperties 62 | { 63 | NSMutableArray *props = [NSMutableArray array]; 64 | unsigned int outCount, i; 65 | Class targetClass = [self class]; 66 | while (targetClass != [NSObject class]) { 67 | objc_property_t *properties = class_copyPropertyList(targetClass, &outCount); 68 | for (i = 0; i < outCount; i++) 69 | { 70 | objc_property_t property = properties[i]; 71 | const char *char_f = property_getName(property); 72 | NSString *propertyName = [NSString stringWithUTF8String:char_f]; 73 | [props addObject:propertyName]; 74 | } 75 | free(properties); 76 | targetClass = [targetClass superclass]; 77 | } 78 | return props; 79 | } 80 | 81 | /* 获取对象的所有方法 */ 82 | - (void)printMothList 83 | { 84 | unsigned int mothCout_f = 0; 85 | Method *mothList_f = class_copyMethodList([self class], &mothCout_f); 86 | for(int i = 0; i < mothCout_f; i++) 87 | { 88 | Method temp_f = mothList_f[i]; 89 | // IMP imp_f = method_getImplementation(temp_f); 90 | SEL name_f = method_getName(temp_f); 91 | const char* name_s = sel_getName(name_f); 92 | int arguments = method_getNumberOfArguments(temp_f); 93 | const char* encoding = method_getTypeEncoding(temp_f); 94 | 95 | NSLog(@"方法名:%@,参数个数:%d,编码方式:%@",[NSString stringWithUTF8String:name_s], arguments, [NSString stringWithUTF8String:encoding]); 96 | } 97 | 98 | free(mothList_f); 99 | } 100 | 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSObject+PerformBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+PerformBlock.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (PerformBlock) 12 | // try catch 13 | + (NSException *)tryCatch:(void(^)())block; 14 | + (NSException *)tryCatch:(void(^)())block finally:(void(^)())aFinisheBlock; 15 | 16 | /** 17 | * 在主线程运行block 18 | * 19 | * @param aInMainBlock 被运行的block 20 | */ 21 | + (void)performInMainThreadBlock:(void(^)())aInMainBlock; 22 | /** 23 | * 延时在主线程运行block 24 | * 25 | * @param aInMainBlock 被运行的block 26 | * @param delay 延时时间 27 | */ 28 | + (void)performInMainThreadBlock:(void(^)())aInMainBlock afterSecond:(NSTimeInterval)delay; 29 | /** 30 | * 在非主线程运行block 31 | * 32 | * @param aInThreadBlock 被运行的block 33 | */ 34 | + (void)performInThreadBlock:(void(^)())aInThreadBlock; 35 | /** 36 | * 延时在非主线程运行block 37 | * 38 | * @param aInThreadBlock 被运行的block 39 | * @param delay 延时时间 40 | */ 41 | + (void)performInThreadBlock:(void(^)())aInThreadBlock afterSecond:(NSTimeInterval)delay; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSObject+PerformBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+PerformBlock.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSObject+PerformBlock.h" 10 | 11 | @implementation NSObject (PerformBlock) 12 | + (NSException *)tryCatch:(void (^)())block 13 | { 14 | NSException *result = nil; 15 | 16 | @try 17 | { 18 | block(); 19 | } 20 | @catch (NSException *e) 21 | { 22 | result = e; 23 | } 24 | 25 | return result; 26 | } 27 | 28 | + (NSException *)tryCatch:(void (^)())block finally:(void(^)())aFinisheBlock 29 | { 30 | NSException *result = nil; 31 | 32 | @try 33 | { 34 | block(); 35 | } 36 | @catch (NSException *e) 37 | { 38 | result = e; 39 | } 40 | @finally 41 | { 42 | aFinisheBlock(); 43 | } 44 | 45 | return result; 46 | } 47 | 48 | + (void)performInMainThreadBlock:(void(^)())aInMainBlock 49 | { 50 | dispatch_async(dispatch_get_main_queue(), ^{ 51 | 52 | aInMainBlock(); 53 | 54 | }); 55 | } 56 | 57 | + (void)performInThreadBlock:(void(^)())aInThreadBlock 58 | { 59 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 60 | 61 | aInThreadBlock(); 62 | 63 | }); 64 | } 65 | 66 | + (void)performInMainThreadBlock:(void(^)())aInMainBlock afterSecond:(NSTimeInterval)delay 67 | { 68 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delay * NSEC_PER_SEC)); 69 | 70 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 71 | 72 | aInMainBlock(); 73 | 74 | }); 75 | } 76 | 77 | + (void)performInThreadBlock:(void(^)())aInThreadBlock afterSecond:(NSTimeInterval)delay 78 | { 79 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delay * NSEC_PER_SEC)); 80 | 81 | dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ 82 | 83 | aInThreadBlock(); 84 | 85 | }); 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSObject+Swizzle.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Swizzle.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (Swizzle) 12 | 13 | //覆盖实例方法 14 | + (void)overrideInstanceMethod:(SEL)origSelector withInstanceMethod:(SEL)newSelector; 15 | 16 | //覆盖类方法 17 | + (void)overrideClassMethod:(SEL)origSelector withClassMethod:(SEL)newSelector; 18 | 19 | 20 | //拦截实例方法 21 | + (void)exchangeInstanceMethod:(SEL)origSelector withInstanceMethod:(SEL)newSelector; 22 | 23 | //拦截类方法 24 | + (void)exchangeClassMethod:(SEL)origSelector withClassMethod:(SEL)newSelector; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSObject+Swizzle.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Swizzle.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Swizzle.h" 10 | #import 11 | 12 | @implementation NSObject (Swizzle) 13 | + (void)overrideInstanceMethod:(SEL)origSelector withInstanceMethod:(SEL)newSelector 14 | { 15 | Class class = [self class]; 16 | 17 | Method originalMethod = class_getInstanceMethod(class, origSelector); 18 | if (!originalMethod) { 19 | NSLog(@"original method %@ not found for class %@", NSStringFromSelector(origSelector), [self class]); 20 | return; 21 | } 22 | 23 | Method overrideMethod = class_getInstanceMethod(class, newSelector); 24 | if (!overrideMethod) { 25 | NSLog(@"original method %@ not found for class %@", NSStringFromSelector(newSelector), [self class]); 26 | return; 27 | } 28 | 29 | 30 | BOOL didAddMethod = class_addMethod(class, 31 | origSelector, 32 | method_getImplementation(overrideMethod), 33 | method_getTypeEncoding(overrideMethod)); 34 | if (didAddMethod) { 35 | class_replaceMethod(class, 36 | newSelector, 37 | method_getImplementation(originalMethod), 38 | method_getTypeEncoding(originalMethod)); 39 | } else { 40 | method_setImplementation(originalMethod, class_getMethodImplementation(self, newSelector)); 41 | } 42 | } 43 | 44 | + (void)overrideClassMethod:(SEL)origSelector withClassMethod:(SEL)newSelector 45 | { 46 | Class class = [self class]; 47 | 48 | Method originalMethod = class_getClassMethod(class, origSelector); 49 | Method overrideMethod = class_getClassMethod(class, newSelector); 50 | 51 | BOOL didAddMethod = class_addMethod(class, 52 | origSelector, 53 | method_getImplementation(overrideMethod), 54 | method_getTypeEncoding(overrideMethod)); 55 | if (didAddMethod) { 56 | class_replaceMethod(class, 57 | newSelector, 58 | method_getImplementation(originalMethod), 59 | method_getTypeEncoding(originalMethod)); 60 | } else { 61 | method_setImplementation(originalMethod, class_getMethodImplementation(self, newSelector)); 62 | } 63 | } 64 | 65 | 66 | + (void)exchangeInstanceMethod:(SEL)origSelector withInstanceMethod:(SEL)newSelector 67 | { 68 | Class class = [self class]; 69 | 70 | Method originalMethod = class_getInstanceMethod(class, origSelector); 71 | Method swizzledMethod = class_getInstanceMethod(class, newSelector); 72 | 73 | BOOL didAddMethod = class_addMethod(class, 74 | origSelector, 75 | method_getImplementation(swizzledMethod), 76 | method_getTypeEncoding(swizzledMethod)); 77 | if (didAddMethod) { 78 | class_replaceMethod(class, 79 | newSelector, 80 | method_getImplementation(originalMethod), 81 | method_getTypeEncoding(originalMethod)); 82 | } else { 83 | method_exchangeImplementations(originalMethod, swizzledMethod); 84 | } 85 | } 86 | 87 | + (void)exchangeClassMethod:(SEL)origSelector withClassMethod:(SEL)newSelector 88 | { 89 | Class class = [self class]; 90 | 91 | Method originalMethod = class_getClassMethod(class, origSelector); 92 | Method swizzledMethod = class_getClassMethod(class, newSelector); 93 | 94 | BOOL didAddMethod = class_addMethod(class, 95 | origSelector, 96 | method_getImplementation(swizzledMethod), 97 | method_getTypeEncoding(swizzledMethod)); 98 | if (didAddMethod) { 99 | class_replaceMethod(class, 100 | newSelector, 101 | method_getImplementation(originalMethod), 102 | method_getTypeEncoding(originalMethod)); 103 | } else { 104 | method_exchangeImplementations(originalMethod, swizzledMethod); 105 | } 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #import 11 | 12 | @interface NSString (Category) 13 | /// 字典转Json字符串 14 | /// @param dic 15 | + (NSString *) dicTransToJSONStringWith:(NSDictionary *)dic; 16 | /** 17 | 电话号码中间4位*显示 18 | 19 | @param phoneNum 电话号码 20 | @return 135*****262 21 | */ 22 | + (NSString*) getSecrectStringWithPhoneNumber:(NSString*)phoneNum; 23 | 24 | 25 | /** 26 | 银行卡号中间8位*显示 27 | 28 | @param accountNo 银行卡号 29 | @return <#return value description#> 30 | */ 31 | + (NSString*) getSecrectStringWithAccountNo:(NSString*)accountNo; 32 | 33 | 34 | /** 35 | 转为手机格式,默认为- 36 | 37 | @param mobile 38 | @return <#return value description#> 39 | */ 40 | + (NSString*) stringMobileFormat:(NSString*)mobile; 41 | 42 | //数组中文格式(几万)可自行添加 43 | 44 | /** 45 | 金额数字添加单位(暂时写了万和亿,有更多的需求请参考写法来自行添加) 46 | 47 | @param value 金额 48 | @return <#return value description#> 49 | */ 50 | + (NSString*) stringChineseFormat:(double)value; 51 | 52 | 53 | /** 54 | 添加数字的千位符 55 | 56 | @param num <#num description#> 57 | @return <#return value description#> 58 | */ 59 | + (NSString*) countNumAndChangeformat:(NSString *)num; 60 | 61 | /** 62 | * NSString转为NSNumber 63 | * 64 | * @return NSNumber 65 | */ 66 | - (NSNumber*) toNumber; 67 | 68 | /** 69 | 计算文字高度 70 | 71 | @param fontSize 字体 72 | @param width 最大宽度 73 | @return <#return value description#> 74 | */ 75 | - (CGFloat ) heightWithFontSize:(CGFloat)fontSize width:(CGFloat)width; 76 | 77 | /** 78 | 计算文字宽度 79 | 80 | @param fontSize 字体 81 | @param maxHeight 最大高度 82 | @return <#return value description#> 83 | */ 84 | - (CGFloat ) widthWithFontSize:(CGFloat)fontSize height:(CGFloat)maxHeight; 85 | /** 86 | 抹除小数末尾的0 87 | 88 | @return <#return value description#> 89 | */ 90 | - (NSString*) removeUnwantedZero; 91 | 92 | /** 93 | //去掉前后空格 94 | 95 | @return <#return value description#> 96 | */ 97 | - (NSString*) trimmedString; 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import "NSString+Category.h" 9 | 10 | @implementation NSString (Category) 11 | + (NSString *) dicTransToJSONStringWith:(NSDictionary *)dic{ 12 | NSError *error; 13 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&error]; 14 | NSString *jsonString; 15 | if (!jsonData) { 16 | return nil; 17 | }else{ 18 | jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding]; 19 | } 20 | 21 | NSMutableString *mutStr = [NSMutableString stringWithString:jsonString]; 22 | //去掉字符串中的空格 23 | NSRange range = {0,jsonString.length}; 24 | [mutStr replaceOccurrencesOfString:@" " withString:@"" options:NSLiteralSearch range:range]; 25 | 26 | //去掉字符串中的换行符 27 | NSRange range2 = {0,mutStr.length}; 28 | [mutStr replaceOccurrencesOfString:@"\n" withString:@"" options:NSLiteralSearch range:range2]; 29 | return mutStr; 30 | } 31 | 32 | 33 | 34 | 35 | + (NSString*) getSecrectStringWithPhoneNumber:(NSString*)phoneNum 36 | { 37 | if (phoneNum.length==11) { 38 | NSMutableString *newStr = [NSMutableString stringWithString:phoneNum]; 39 | NSRange range = NSMakeRange(3, 7); 40 | [newStr replaceCharactersInRange:range withString:@"*****"]; 41 | return newStr; 42 | } 43 | return nil; 44 | } 45 | 46 | + (NSString*) getSecrectStringWithAccountNo:(NSString*)accountNo 47 | { 48 | NSMutableString *newStr = [NSMutableString stringWithString:accountNo]; 49 | NSRange range = NSMakeRange(4, 8); 50 | if (newStr.length>12) { 51 | [newStr replaceCharactersInRange:range withString:@" **** **** "]; 52 | } 53 | return newStr; 54 | } 55 | 56 | + (NSString*) stringMobileFormat:(NSString *)mobile { 57 | if (mobile.length==11) { 58 | NSMutableString* value = [[NSMutableString alloc] initWithString:mobile]; 59 | [value insertString:@"-" atIndex:3]; 60 | [value insertString:@"-" atIndex:8]; 61 | return value; 62 | } 63 | 64 | return nil; 65 | } 66 | 67 | + (NSString*) stringChineseFormat:(double)value{ 68 | 69 | if (value / 100000000 >= 1) { 70 | return [NSString stringWithFormat:@"%.0f亿",value/100000000]; 71 | } 72 | else if (value / 10000 >= 1 && value / 100000000 < 1) { 73 | return [NSString stringWithFormat:@"%.0f万",value/10000]; 74 | } 75 | else { 76 | return [NSString stringWithFormat:@"%.0f",value]; 77 | } 78 | } 79 | 80 | +(NSString *)countNumAndChangeformat:(NSString *)num 81 | { 82 | NSNumberFormatter *moneyFormatter = [[NSNumberFormatter alloc] init]; 83 | moneyFormatter.positiveFormat = @"###,###"; 84 | //如要增加小数点请自行修改为@"###,###,##" 85 | return [moneyFormatter stringFromNumber:[num toNumber]]; 86 | } 87 | 88 | -(CGFloat)heightWithFontSize:(CGFloat)fontSize width:(CGFloat)width 89 | { 90 | NSDictionary *attrs = @{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}; 91 | return [self boundingRectWithSize:CGSizeMake(width, 0) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attrs context:nil].size.height; 92 | } 93 | 94 | - (CGFloat) widthWithFontSize:(CGFloat)fontSize height:(CGFloat)maxHeight 95 | { 96 | NSDictionary *attrs = @{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}; 97 | return [self boundingRectWithSize:CGSizeMake(0, maxHeight) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attrs context:nil].size.width; 98 | } 99 | 100 | - (NSNumber*)toNumber 101 | { 102 | NSNumberFormatter *formatter=[[NSNumberFormatter alloc] init]; 103 | [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; 104 | NSNumber *number=[formatter numberFromString:self]; 105 | return number; 106 | } 107 | 108 | /*抹除运费小数末尾的0*/ 109 | - (NSString *)removeUnwantedZero { 110 | if ([[self substringWithRange:NSMakeRange(self.length- 3, 3)] isEqualToString:@"000"]) { 111 | return [self substringWithRange:NSMakeRange(0, self.length-4)]; // 多一个小数点 112 | } else if ([[self substringWithRange:NSMakeRange(self.length- 2, 2)] isEqualToString:@"00"]) { 113 | return [self substringWithRange:NSMakeRange(0, self.length-2)]; 114 | } else if ([[self substringWithRange:NSMakeRange(self.length- 1, 1)] isEqualToString:@"0"]) { 115 | return [self substringWithRange:NSMakeRange(0, self.length-1)]; 116 | } else { 117 | return self; 118 | } 119 | } 120 | 121 | //去掉前后空格 122 | - (NSString *)trimmedString{ 123 | return [self stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]]; 124 | } 125 | 126 | 127 | @end 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+DisplayTime.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DisplayTime.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 16/7/20. 6 | // Copyright © 2016年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (DisplayTime) 12 | /** 13 | 通过时间戳计算时间差(几小时前、几天前 14 | 15 | @param compareDate <#compareDate description#> 16 | @return <#return value description#> 17 | */ 18 | + (NSString *) compareCurrentTime:(NSTimeInterval) compareDate; 19 | 20 | /** 21 | 通过时间戳得出对应的时间 22 | 23 | @param timestamp 时间戳 24 | @return <#return value description#> 25 | */ 26 | + (NSString *) getDateStringWithTimestamp:(NSTimeInterval)timestamp; 27 | 28 | /** 29 | //通过时间戳和显示时间 30 | @param timestamp 时间戳 31 | @param formatter 格式 32 | @return <#return value description#> 33 | */ 34 | + (NSString *) getStringWithTimestamp:(NSTimeInterval)timestamp formatter:(NSString*)formatter; 35 | @end 36 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+DisplayTime.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DisplayTime.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 16/7/20. 6 | // Copyright © 2016年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSString+DisplayTime.h" 10 | 11 | @implementation NSString (DisplayTime) 12 | 13 | +(NSString *) compareCurrentTime:(NSTimeInterval) compareDate 14 | { 15 | NSDate *confromTimesp = [NSDate dateWithTimeIntervalSince1970:compareDate/1000]; 16 | 17 | NSTimeInterval timeInterval = [confromTimesp timeIntervalSinceNow]; 18 | timeInterval = -timeInterval; 19 | long temp = 0; 20 | NSString *result; 21 | 22 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 23 | NSInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday | 24 | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 25 | NSDateComponents*referenceComponents=[calendar components:unitFlags fromDate:confromTimesp]; 26 | // NSInteger referenceYear =referenceComponents.year; 27 | // NSInteger referenceMonth =referenceComponents.month; 28 | // NSInteger referenceDay =referenceComponents.day; 29 | NSInteger referenceHour =referenceComponents.hour; 30 | // NSInteger referemceMinute=referenceComponents.minute; 31 | 32 | if (timeInterval < 60) { 33 | result = [NSString stringWithFormat:@"刚刚"]; 34 | } 35 | else if((temp= timeInterval/60) < 60){ 36 | result = [NSString stringWithFormat:@"%ld分钟前",temp]; 37 | } 38 | 39 | else if((temp = timeInterval/3600) <24){ 40 | result = [NSString stringWithFormat:@"%ld小时前",temp]; 41 | } 42 | else if ((temp = timeInterval/3600/24)==1) 43 | { 44 | result = [NSString stringWithFormat:@"昨天%ld时",(long)referenceHour]; 45 | } 46 | else if ((temp = timeInterval/3600/24)==2) 47 | { 48 | result = [NSString stringWithFormat:@"前天%ld时",(long)referenceHour]; 49 | } 50 | 51 | else if((temp = timeInterval/3600/24) <31){ 52 | result = [NSString stringWithFormat:@"%ld天前",temp]; 53 | } 54 | 55 | else if((temp = timeInterval/3600/24/30) <12){ 56 | result = [NSString stringWithFormat:@"%ld个月前",temp]; 57 | } 58 | else{ 59 | temp = temp/12; 60 | result = [NSString stringWithFormat:@"%ld年前",temp]; 61 | } 62 | 63 | return result; 64 | } 65 | + (NSString*) getDateStringWithTimestamp:(NSTimeInterval)timestamp 66 | { 67 | NSDate *confromTimesp = [NSDate dateWithTimeIntervalSince1970:timestamp/1000]; 68 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 69 | NSInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday | 70 | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 71 | NSDateComponents*referenceComponents=[calendar components:unitFlags fromDate:confromTimesp]; 72 | NSInteger referenceYear =referenceComponents.year; 73 | NSInteger referenceMonth =referenceComponents.month; 74 | NSInteger referenceDay =referenceComponents.day; 75 | 76 | return [NSString stringWithFormat:@"%ld年%ld月%ld日",referenceYear,(long)referenceMonth,(long)referenceDay]; 77 | } 78 | 79 | 80 | 81 | + (NSString*) getStringWithTimestamp:(NSTimeInterval)timestamp formatter:(NSString*)formatter 82 | { 83 | if ([NSString stringWithFormat:@"%@", @(timestamp)].length == 13) { 84 | timestamp /= 1000.0f; 85 | } 86 | NSDate*timestampDate=[NSDate dateWithTimeIntervalSince1970:timestamp]; 87 | 88 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 89 | [dateFormatter setDateFormat:formatter]; 90 | NSString *strDate = [dateFormatter stringFromDate:timestampDate]; 91 | 92 | return strDate; 93 | } 94 | @end 95 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+MD5.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MD5.h 3 | // PKWSevers 4 | // 5 | // Created by peikua on 16/4/27. 6 | // Copyright © 2016年 peikua. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (MD5) 12 | - (NSString *) md5WithString;//MD5加密 13 | @end 14 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+MD5.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MD5.m 3 | // PKWSevers 4 | // 5 | // Created by peikua on 16/4/27. 6 | // Copyright © 2016年 peikua. All rights reserved. 7 | // 8 | 9 | #import "NSString+MD5.h" 10 | #import 11 | 12 | @implementation NSString (MD5) 13 | 14 | - (NSString *) md5WithString 15 | { 16 | if (self==nil || [self length]==0) { 17 | return nil; 18 | } 19 | 20 | const char *value = [self UTF8String]; 21 | 22 | unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH]; 23 | CC_MD5(value, (CC_LONG)strlen(value), outputBuffer); 24 | 25 | NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2]; 26 | for (NSInteger count=0; count 10 | 11 | @interface NSString (Predicate) 12 | 13 | //有效的电话号码 14 | - (BOOL) isValidMobileNumber; 15 | 16 | //有效的真实姓名 17 | - (BOOL) isValidRealName; 18 | 19 | //是否只有中文 20 | - (BOOL) isOnlyChinese; 21 | 22 | //有效的验证码(根据自家的验证码位数进行修改) 23 | - (BOOL) isValidVerifyCode; 24 | 25 | //有效的银行卡号 26 | - (BOOL) isValidBankCardNumber; 27 | 28 | //有效的邮箱 29 | - (BOOL) isValidEmail; 30 | 31 | //有效的字母数字密码 32 | - (BOOL) isValidAlphaNumberPassword; 33 | 34 | //检测有效身份证 35 | //15位 36 | - (BOOL) isValidIdentifyFifteen; 37 | 38 | //18位 39 | - (BOOL) isValidIdentifyEighteen; 40 | 41 | //限制只能输入数字 42 | - (BOOL) isOnlyNumber; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+Predicate.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Predicate.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 16/7/20. 6 | // Copyright © 2016年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSString+Predicate.h" 10 | 11 | @implementation NSString (Predicate) 12 | - (BOOL) isValidMobileNumber { 13 | NSString* const MOBILE = @"^1(3|4|5|7|8)\\d{9}$"; 14 | 15 | NSPredicate* predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE]; 16 | return [predicate evaluateWithObject:self]; 17 | } 18 | 19 | - (BOOL) isValidVerifyCode 20 | { 21 | NSString *pattern = @"^[0-9]{4}"; 22 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern]; 23 | return [predicate evaluateWithObject:self]; 24 | } 25 | 26 | - (BOOL) isValidRealName 27 | 28 | { 29 | NSString *nicknameRegex = @"^[\u4e00-\u9fa5]{2,8}$"; 30 | 31 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",nicknameRegex]; 32 | 33 | return [predicate evaluateWithObject:self]; 34 | } 35 | 36 | - (BOOL) isOnlyChinese 37 | { 38 | NSString * chineseTest=@"^[\u4e00-\u9fa5]{0,}$"; 39 | NSPredicate*chinesePredicate=[NSPredicate predicateWithFormat:@"SELF MATCHES %@",chineseTest]; 40 | return [chinesePredicate evaluateWithObject:self]; 41 | } 42 | 43 | 44 | - (BOOL) isValidBankCardNumber { 45 | NSString* const BANKCARD = @"^(\\d{16}|\\d{19})$"; 46 | 47 | NSPredicate* predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", BANKCARD]; 48 | return [predicate evaluateWithObject:self]; 49 | } 50 | 51 | 52 | - (BOOL) isValidEmail 53 | { 54 | 55 | NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; 56 | NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex]; 57 | 58 | return [emailTest evaluateWithObject:self]; 59 | 60 | } 61 | - (BOOL) validateNickName 62 | { 63 | NSString *userNameRegex = @"^[A-Za-z0-9\u4e00-\u9fa5]{1,24}+$"; 64 | 65 | NSPredicate *userNamePredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",userNameRegex]; 66 | 67 | return [userNamePredicate evaluateWithObject:self]; 68 | } 69 | - (BOOL) isValidAlphaNumberPassword 70 | { 71 | NSString *regex = @"^(?!\\d+$|[a-zA-Z]+$)\\w{6,12}$"; 72 | NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; 73 | return [identityCardPredicate evaluateWithObject:self]; 74 | } 75 | 76 | 77 | - (BOOL) isValidIdentifyFifteen 78 | { 79 | NSString * identifyTest=@"^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$"; 80 | NSPredicate*identifyPredicate=[NSPredicate predicateWithFormat:@"SELF MATCHES %@",identifyTest]; 81 | return [identifyPredicate evaluateWithObject:self]; 82 | } 83 | 84 | - (BOOL) isValidIdentifyEighteen 85 | { 86 | NSString * identifyTest=@"^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$"; 87 | NSPredicate*identifyPredicate=[NSPredicate predicateWithFormat:@"SELF MATCHES %@",identifyTest]; 88 | return [identifyPredicate evaluateWithObject:self]; 89 | } 90 | 91 | 92 | - (BOOL) isOnlyNumber 93 | { 94 | BOOL res = YES; 95 | NSCharacterSet* tmpSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"]; 96 | int i = 0; 97 | while (i < self.length) { 98 | NSString * string = [self substringWithRange:NSMakeRange(i, 1)]; 99 | NSRange range = [string rangeOfCharacterFromSet:tmpSet]; 100 | if (range.length == 0) { 101 | res = NO; 102 | break; 103 | } 104 | i++; 105 | } 106 | 107 | return res; 108 | } 109 | 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Safe.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/24. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Safe) 12 | //避免Format所得的字符串带有null 13 | + (instancetype)noNULLStringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); 14 | 15 | - (NSString *)safeSubstringFromIndex:(NSUInteger)from; 16 | 17 | - (NSString *)safeSubstringToIndex:(NSUInteger)to; 18 | 19 | - (NSString *)safeSubstringWithRange:(NSRange)range; 20 | 21 | - (NSRange)safeRangeOfString:(NSString *)aString; 22 | 23 | - (NSRange)safeRangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask; 24 | 25 | - (NSString *)safeStringByAppendingString:(NSString *)aString; 26 | 27 | - (NSString *)safeStringByReplacingCharactersInRange:(NSRange)aRange withString:(NSString *)aString; 28 | @end 29 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/NSString+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Safe.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/24. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "NSString+Safe.h" 10 | 11 | @implementation NSString (Safe) 12 | + (instancetype)noNULLStringWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2) { 13 | va_list arglist; 14 | va_start(arglist, format); 15 | NSString *outStr = [[NSString alloc] initWithFormat:format arguments:arglist]; 16 | va_end(arglist); 17 | 18 | if ([outStr containsString:@"(null)"]) 19 | return [outStr stringByReplacingOccurrencesOfString:@"(null)" withString:@""]; 20 | return outStr; 21 | } 22 | 23 | 24 | - (NSString *)safeSubstringFromIndex:(NSUInteger)from 25 | { 26 | if (from > self.length) { 27 | return nil; 28 | } else { 29 | return [self substringFromIndex:from]; 30 | } 31 | } 32 | 33 | - (NSString *)safeSubstringToIndex:(NSUInteger)to 34 | { 35 | if (to > self.length) { 36 | return nil; 37 | } else { 38 | return [self substringToIndex:to]; 39 | } 40 | } 41 | 42 | - (NSString *)safeSubstringWithRange:(NSRange)range 43 | { 44 | NSUInteger location = range.location; 45 | NSUInteger length = range.length; 46 | if (location+length > self.length) { 47 | return nil; 48 | } else { 49 | return [self substringWithRange:range]; 50 | } 51 | } 52 | 53 | - (NSRange)safeRangeOfString:(NSString *)aString 54 | { 55 | if (aString == nil) { 56 | return NSMakeRange(NSNotFound, 0); 57 | } else { 58 | return [self rangeOfString:aString]; 59 | } 60 | } 61 | 62 | - (NSRange)safeRangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask 63 | { 64 | if (aString == nil) { 65 | return NSMakeRange(NSNotFound, 0); 66 | } else { 67 | return [self rangeOfString:aString options:mask]; 68 | } 69 | } 70 | 71 | - (NSString *)safeStringByAppendingString:(NSString *)aString 72 | { 73 | if (aString == nil) { 74 | return [self stringByAppendingString:@""]; 75 | } else { 76 | return [self stringByAppendingString:aString]; 77 | } 78 | } 79 | 80 | - (NSString *)safeStringByReplacingCharactersInRange:(NSRange)aRange withString:(NSString *)aString 81 | { 82 | if (aString == nil || ![aString isKindOfClass:[NSString class]]) { 83 | return self; 84 | } 85 | return [self safeStringByReplacingCharactersInRange:aRange withString:aString]; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIButton+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Category.h 3 | // haitao 4 | // 5 | // Created by Yuen-iMac on 16/5/4. 6 | // Copyright © 2016年 上海市配夸网络科技有限公司. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void(^ButtonActionCallBack)(UIButton *button); 12 | @interface UIButton (Category) 13 | 14 | -(void)addCallBackAction:(ButtonActionCallBack)action 15 | forControlEvents:(UIControlEvents)controlEvents; 16 | 17 | -(void)addCallBackAction:(ButtonActionCallBack)action; 18 | 19 | @end 20 | 21 | @interface UIButton (EnlargeTouchArea) 22 | 23 | /** 24 | * 扩大 UIButton 的點擊範圍 25 | * 控制上下左右的延長範圍 26 | * 27 | * @param top <#top description#> 28 | * @param right <#right description#> 29 | * @param bottom <#bottom description#> 30 | * @param left <#left description#> 31 | */ 32 | - (void)setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIButton+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Category.m 3 | // haitao 4 | // 5 | // Created by Yuen-iMac on 16/5/4. 6 | // Copyright © 2016年 上海市配夸网络科技有限公司. All rights reserved. 7 | // 8 | 9 | #import "UIButton+Category.h" 10 | #import 11 | 12 | @interface UIButton () 13 | @property(nonatomic ,copy) ButtonActionCallBack block; 14 | @end 15 | 16 | @implementation UIButton (Category) 17 | 18 | -(void)addCallBackAction:(ButtonActionCallBack)action 19 | forControlEvents:(UIControlEvents)controlEvents 20 | { 21 | self.block = action; 22 | [self addTarget:self action:@selector(click:)forControlEvents:controlEvents]; 23 | } 24 | 25 | -(void)addCallBackAction:(ButtonActionCallBack)action 26 | { 27 | [self addCallBackAction:action forControlEvents:UIControlEventTouchUpInside]; 28 | } 29 | 30 | -(void)click:(UIButton*)btn 31 | { 32 | if(self.block) { 33 | self.block(btn); 34 | } 35 | } 36 | 37 | -(void)setBlock:(void(^)(UIButton*))block 38 | 39 | { 40 | objc_setAssociatedObject(self,@selector(block), block,OBJC_ASSOCIATION_COPY_NONATOMIC); 41 | 42 | } 43 | 44 | -(void(^)(UIButton*))block 45 | 46 | { 47 | return objc_getAssociatedObject(self,@selector(block)); 48 | } 49 | @end 50 | 51 | 52 | 53 | @implementation UIButton (EnlargeTouchArea) 54 | 55 | static char topNameKey; 56 | static char rightNameKey; 57 | static char bottomNameKey; 58 | static char leftNameKey; 59 | 60 | - (void)setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left 61 | { 62 | objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC); 63 | objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC); 64 | objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC); 65 | objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC); 66 | } 67 | 68 | - (CGRect)enlargedRect 69 | { 70 | NSNumber *topEdge = objc_getAssociatedObject(self, &topNameKey); 71 | NSNumber *rightEdge = objc_getAssociatedObject(self, &rightNameKey); 72 | NSNumber *bottomEdge = objc_getAssociatedObject(self, &bottomNameKey); 73 | NSNumber *leftEdge = objc_getAssociatedObject(self, &leftNameKey); 74 | if (topEdge && rightEdge && bottomEdge && leftEdge) { 75 | return CGRectMake(self.bounds.origin.x - leftEdge.floatValue, 76 | self.bounds.origin.y - topEdge.floatValue, 77 | self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue, 78 | self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue); 79 | } 80 | else 81 | { 82 | return self.bounds; 83 | } 84 | } 85 | 86 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 87 | { 88 | CGRect rect = [self enlargedRect]; 89 | if (CGRectEqualToRect(rect, self.bounds)) { 90 | return [super hitTest:point withEvent:event]; 91 | } 92 | return CGRectContainsPoint(rect, point) ? self : nil; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIColor+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Category.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | /** 13 | * 功能:通过RGB创建颜色 14 | * 15 | * @param red <范围:0~255.0> 16 | * @param green <范围:0~255.0> 17 | * @param blue <范围:0~255.0> 18 | * 19 | * @return UIColor 20 | * 21 | * example: rgb(173.0,23.0,11.0) 22 | */ 23 | UIColor *rgb(CGFloat red, CGFloat green, CGFloat blue); 24 | 25 | /** 26 | * 功能:通过RGB以及alpha创建颜色 27 | * 28 | * @param red <范围:0~255.0> 29 | * @param green <范围:0~255.0> 30 | * @param blue <范围:0~255.0> 31 | * @param alpha <范围:0~1.0> 32 | * 33 | * @return UIColor 34 | * 35 | * example: rgbA(173.0,23.0,11.0,0.5) 36 | */ 37 | UIColor *rgbA(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha); 38 | 39 | 40 | @interface UIColor (Category) 41 | 42 | /** 43 | * Create a color from a HEX string. 44 | * It supports the following type: 45 | * - #RGB 46 | * - #ARGB 47 | * - #RRGGBB 48 | * - #AARRGGBB 49 | * 50 | * @param hexString NSString 51 | * 52 | * @return Returns the UIColor instance 53 | */ 54 | + (UIColor *)hex:(NSString *)hexString; 55 | 56 | /** 57 | * 通过0xffffff的16进制数字创建颜色 58 | * 59 | * @param aRGB 0xffffff 60 | * 61 | * @return UIColor 62 | */ 63 | + (UIColor *)colorWithRGB:(NSUInteger)aRGB; 64 | 65 | 66 | /** 67 | 调节颜色的明亮度 68 | 69 | @param color 颜色 70 | @param delta 明亮度 71 | @return <#return value description#> 72 | */ 73 | + (UIColor*) colorRGBonvertToHSB:(UIColor*)color withBrighnessDelta:(CGFloat)delta; 74 | 75 | 76 | /** 77 | 调整颜色的透明度 78 | 79 | @param color 颜色 80 | @param delta 透明度 81 | @return <#return value description#> 82 | */ 83 | + (UIColor*) colorRGBonvertToHSB:(UIColor*)color withAlphaDelta:(CGFloat)delta; 84 | 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIColor+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Category.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "UIColor+Category.h" 10 | 11 | @implementation UIColor (Category) 12 | + (UIColor *)hex:(NSString *)hexString 13 | { 14 | NSString *cString = [[hexString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 15 | 16 | if ([cString length] < 6) 17 | return [UIColor blackColor]; 18 | if ([cString hasPrefix:@"#"]) 19 | cString = [cString substringFromIndex:1]; 20 | if ([cString length] != 6) 21 | return [UIColor blackColor]; 22 | 23 | NSRange range; 24 | range.location = 0; 25 | range.length = 2; 26 | NSString *rString = [cString substringWithRange:range]; 27 | 28 | range.location = 2; 29 | NSString *gString = [cString substringWithRange:range]; 30 | 31 | range.location = 4; 32 | NSString *bString = [cString substringWithRange:range]; 33 | 34 | unsigned int r, g, b; 35 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 36 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 37 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 38 | 39 | return [UIColor colorWithRed:((float) r / 255.0f) 40 | green:((float) g / 255.0f) 41 | blue:((float) b / 255.0f) 42 | alpha:1.0f]; 43 | } 44 | 45 | 46 | + (UIColor *)colorWithRGB:(NSUInteger)aRGB 47 | { 48 | return [UIColor colorWithRed:((float)((aRGB & 0xFF0000) >> 16))/255.0 green:((float)((aRGB & 0xFF00) >> 8))/255.0 blue:((float)(aRGB & 0xFF))/255.0 alpha:1.0]; 49 | } 50 | 51 | 52 | + (UIColor*) colorRGBonvertToHSB:(UIColor*)color withBrighnessDelta:(CGFloat)delta { 53 | CGFloat hue = 0.0f; 54 | CGFloat saturation = 0.0f; 55 | CGFloat brightness = 0.0f; 56 | CGFloat alpha = 0.0f; 57 | 58 | [color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]; 59 | 60 | brightness += delta; 61 | 62 | return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha]; 63 | } 64 | 65 | + (UIColor*) colorRGBonvertToHSB:(UIColor*)color withAlphaDelta:(CGFloat)delta { 66 | CGFloat hue = 0.0f; 67 | CGFloat saturation = 0.0f; 68 | CGFloat brightness = 0.0f; 69 | CGFloat alpha = 0.0f; 70 | 71 | [color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]; 72 | 73 | alpha += delta; 74 | 75 | return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha]; 76 | } 77 | @end 78 | 79 | UIColor *rgb(CGFloat red, CGFloat green, CGFloat blue) 80 | { 81 | return [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1]; 82 | } 83 | 84 | UIColor *rgbA(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) 85 | { 86 | return [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:alpha]; 87 | } 88 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIImage+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | 11 | @interface UIImage (Category) 12 | 13 | //由颜色生成图片 14 | + (UIImage *) imageWithColor:(UIColor*)color; 15 | 16 | //将图片剪裁至目标尺寸 17 | + (UIImage *) imageByScalingAndCroppingForSourceImage:(UIImage *)sourceImage targetSize:(CGSize)targetSize; 18 | 19 | //图片旋转角度 20 | - (UIImage *) imageRotatedByDegrees:(CGFloat)degrees; 21 | 22 | //拉伸图片UIEdgeInsets 23 | - (UIImage *) resizableImage:(UIEdgeInsets)insets; 24 | 25 | //拉伸图片CGFloat 26 | - (UIImage *) imageByResizeToScale:(CGFloat)scale; 27 | 28 | //放大图片CGSize 29 | - (UIImage *) imageByResizeWithMaxSize:(CGSize)size; 30 | 31 | //小样图图片CGSize 32 | - (UIImage *) imageWithThumbnailForSize:(CGSize)size; 33 | 34 | //通过Rect剪裁图片 35 | - (UIImage *) imageByCropToRect:(CGRect)rect; 36 | 37 | //图片增加圆角 38 | - (UIImage *) imageByRoundCornerRadius:(CGFloat)radius; 39 | 40 | //图片增加圆角及边框 41 | - (UIImage *) imageByRoundCornerRadius:(CGFloat)radius 42 | borderWidth:(CGFloat)borderWidth 43 | borderColor:(UIColor *)borderColor; 44 | 45 | //图片向左90度 46 | - (UIImage *)imageByRotateLeft90; 47 | 48 | //图片向右90度 49 | - (UIImage *)imageByRotateRight90; 50 | 51 | //图片转180度 52 | - (UIImage *)imageByRotate180; 53 | 54 | 55 | @end 56 | 57 | 58 | @interface UIImage (Blur) 59 | //玻璃化效果,这里与系统的玻璃化枚举效果一样,但只是一张图 60 | - (UIImage *)imageByBlurSoft; 61 | 62 | - (UIImage *)imageByBlurLight; 63 | 64 | - (UIImage *)imageByBlurExtraLight; 65 | 66 | - (UIImage *)imageByBlurDark; 67 | 68 | - (UIImage *)imageByBlurWithTint:(UIColor *)tintColor; 69 | 70 | - (UIImage *)imageByBlurRadius:(CGFloat)blurRadius 71 | tintColor:(UIColor *)tintColor 72 | tintMode:(CGBlendMode)tintBlendMode 73 | saturation:(CGFloat)saturation 74 | maskImage:(UIImage *)maskImage; 75 | 76 | - (UIImage *) boxblurImageWithBlur:(CGFloat)blur exclusionPath:(UIBezierPath *)exclusionPath; 77 | @end 78 | 79 | 80 | 81 | 82 | 83 | @interface UIImage (ImageEffects) 84 | 85 | //图片效果 86 | 87 | - (UIImage *)applyLightEffect; 88 | - (UIImage *)applyExtraLightEffect; 89 | - (UIImage *)applyDarkEffect; 90 | - (UIImage *)applyBlurEffect; 91 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor; 92 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius 93 | tintColor:(UIColor *)tintColor 94 | saturationDeltaFactor:(CGFloat)saturationDeltaFactor 95 | maskImage:(UIImage *)maskImage; 96 | @end 97 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIImage+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import "UIImage+Category.h" 9 | #import 10 | #import 11 | #define ORIGINAL_MAX_WIDTH 640.0f 12 | #define YY_SWAP(_a_, _b_) do { __typeof__(_a_) _tmp_ = (_a_); (_a_) = (_b_); (_b_) = _tmp_; } while (0) 13 | @implementation UIImage (Category) 14 | 15 | - (UIImage*)imageRotatedByDegrees:(CGFloat)degrees 16 | { 17 | 18 | CGFloat width = CGImageGetWidth(self.CGImage); 19 | CGFloat height = CGImageGetHeight(self.CGImage); 20 | 21 | CGSize rotatedSize; 22 | 23 | rotatedSize.width = width; 24 | rotatedSize.height = height; 25 | 26 | UIGraphicsBeginImageContext(rotatedSize); 27 | CGContextRef bitmap = UIGraphicsGetCurrentContext(); 28 | CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2); 29 | CGContextRotateCTM(bitmap, degrees * M_PI / 180); 30 | CGContextRotateCTM(bitmap, M_PI); 31 | CGContextScaleCTM(bitmap, -1.0, 1.0); 32 | CGContextDrawImage(bitmap, CGRectMake(-rotatedSize.width/2, -rotatedSize.height/2, rotatedSize.width, rotatedSize.height), self.CGImage); 33 | UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 34 | UIGraphicsEndImageContext(); 35 | return newImage; 36 | } 37 | 38 | - (UIImage*) resizableImage:(UIEdgeInsets)insets { 39 | if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0f) { 40 | return [self resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch]; 41 | } 42 | 43 | return [self stretchableImageWithLeftCapWidth:insets.left topCapHeight:insets.top]; 44 | } 45 | 46 | 47 | + (UIImage *) imageByScalingAndCroppingForSourceImage:(UIImage *)sourceImage targetSize:(CGSize)targetSize { 48 | UIImage *newImage = nil; 49 | CGSize imageSize = sourceImage.size; 50 | CGFloat width = imageSize.width; 51 | CGFloat height = imageSize.height; 52 | CGFloat targetWidth = targetSize.width; 53 | CGFloat targetHeight = targetSize.height; 54 | CGFloat scaleFactor = 0.0; 55 | CGFloat scaledWidth = targetWidth; 56 | CGFloat scaledHeight = targetHeight; 57 | CGPoint thumbnailPoint = CGPointMake(0.0,0.0); 58 | if (CGSizeEqualToSize(imageSize, targetSize) == NO) 59 | { 60 | CGFloat widthFactor = targetWidth / width; 61 | CGFloat heightFactor = targetHeight / height; 62 | 63 | if (widthFactor > heightFactor) 64 | scaleFactor = widthFactor; // scale to fit height 65 | else 66 | scaleFactor = heightFactor; // scale to fit width 67 | scaledWidth = width * scaleFactor; 68 | scaledHeight = height * scaleFactor; 69 | 70 | // center the image 71 | if (widthFactor > heightFactor) 72 | { 73 | thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 74 | } 75 | else 76 | if (widthFactor < heightFactor) 77 | { 78 | thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; 79 | } 80 | } 81 | UIGraphicsBeginImageContext(targetSize); // this will crop 82 | CGRect thumbnailRect = CGRectZero; 83 | thumbnailRect.origin = thumbnailPoint; 84 | thumbnailRect.size.width = scaledWidth; 85 | thumbnailRect.size.height = scaledHeight; 86 | 87 | [sourceImage drawInRect:thumbnailRect]; 88 | 89 | newImage = UIGraphicsGetImageFromCurrentImageContext(); 90 | if(newImage == nil) NSLog(@"could not scale image"); 91 | 92 | //pop the context to get back to the default 93 | UIGraphicsEndImageContext(); 94 | return newImage; 95 | } 96 | + (UIImage*) imageWithColor:(UIColor *)color { 97 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 98 | UIGraphicsBeginImageContext(rect.size); 99 | CGContextRef context = UIGraphicsGetCurrentContext(); 100 | CGContextSetFillColorWithColor(context, color.CGColor); 101 | CGContextFillRect(context, rect); 102 | 103 | UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); 104 | UIGraphicsEndImageContext(); 105 | 106 | NSData* imageData = UIImageJPEGRepresentation(image, 1.0f); 107 | image = [UIImage imageWithData:imageData]; 108 | return image; 109 | } 110 | 111 | 112 | - (UIImage *)imageByResizeToScale:(CGFloat)scale{ 113 | CGSize size = CGSizeMake(self.size.width *scale, self.size.height * scale); 114 | if (size.width <= 0 || size.height <= 0) return nil; 115 | UIGraphicsBeginImageContextWithOptions(size, NO, self.scale); 116 | [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; 117 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 118 | UIGraphicsEndImageContext(); 119 | return image; 120 | } 121 | - (UIImage *)imageByResizeWithMaxSize:(CGSize)size{ 122 | CGSize resize = self.size; 123 | if(resize.width > size.width){ 124 | resize = CGSizeMake(size.width, size.width/resize.width * resize.height); 125 | } 126 | if(resize.height > size.height){ 127 | resize = CGSizeMake(size.height/resize.height * resize.width, size.height); 128 | } 129 | if (resize.width <= 0 || resize.height <= 0) return nil; 130 | UIGraphicsBeginImageContextWithOptions(resize, NO, self.scale); 131 | [self drawInRect:CGRectMake(0, 0, resize.width, resize.height)]; 132 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 133 | UIGraphicsEndImageContext(); 134 | return image; 135 | } 136 | 137 | - (UIImage *)imageWithThumbnailForSize:(CGSize)size{ 138 | CGSize imageSize = self.size; 139 | if(imageSize.width < imageSize.height){ 140 | imageSize = CGSizeMake(size.width, size.width/imageSize.width * imageSize.height); 141 | } 142 | else{ 143 | imageSize = CGSizeMake(size.height/imageSize.height * imageSize.width, size.height); 144 | } 145 | if (imageSize.width <= 0 || imageSize.height <= 0) return nil; 146 | UIGraphicsBeginImageContextWithOptions(imageSize, NO, self.scale); 147 | [self drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)]; 148 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 149 | UIGraphicsEndImageContext(); 150 | return image; 151 | } 152 | 153 | - (UIImage *)imageByCropToRect:(CGRect)rect { 154 | rect.origin.x *= self.scale; 155 | rect.origin.y *= self.scale; 156 | rect.size.width *= self.scale; 157 | rect.size.height *= self.scale; 158 | if (rect.size.width <= 0 || rect.size.height <= 0) return nil; 159 | CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, rect); 160 | UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; 161 | CGImageRelease(imageRef); 162 | return image; 163 | } 164 | 165 | - (UIImage *)imageByRoundCornerRadius:(CGFloat)radius { 166 | return [self imageByRoundCornerRadius:radius borderWidth:0 borderColor:nil]; 167 | } 168 | 169 | - (UIImage *)imageByRoundCornerRadius:(CGFloat)radius 170 | borderWidth:(CGFloat)borderWidth 171 | borderColor:(UIColor *)borderColor { 172 | return [self imageByRoundCornerRadius:radius 173 | corners:UIRectCornerAllCorners 174 | borderWidth:borderWidth 175 | borderColor:borderColor 176 | borderLineJoin:kCGLineJoinMiter]; 177 | } 178 | 179 | - (UIImage *)imageByRoundCornerRadius:(CGFloat)radius 180 | corners:(UIRectCorner)corners 181 | borderWidth:(CGFloat)borderWidth 182 | borderColor:(UIColor *)borderColor 183 | borderLineJoin:(CGLineJoin)borderLineJoin { 184 | 185 | UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); 186 | CGContextRef context = UIGraphicsGetCurrentContext(); 187 | CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); 188 | CGContextScaleCTM(context, 1, -1); 189 | CGContextTranslateCTM(context, 0, -rect.size.height); 190 | 191 | CGFloat minSize = MIN(self.size.width, self.size.height); 192 | if (borderWidth < minSize / 2) { 193 | UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, borderWidth, borderWidth) byRoundingCorners:corners cornerRadii:CGSizeMake(radius, borderWidth)]; 194 | [path closePath]; 195 | 196 | CGContextSaveGState(context); 197 | [path addClip]; 198 | CGContextDrawImage(context, rect, self.CGImage); 199 | CGContextRestoreGState(context); 200 | } 201 | 202 | if (borderColor && borderWidth < minSize / 2 && borderWidth > 0) { 203 | CGFloat strokeInset = (floor(borderWidth * self.scale) + 0.5) / self.scale; 204 | CGRect strokeRect = CGRectInset(rect, strokeInset, strokeInset); 205 | CGFloat strokeRadius = radius > self.scale / 2 ? radius - self.scale / 2 : 0; 206 | UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:strokeRect byRoundingCorners:corners cornerRadii:CGSizeMake(strokeRadius, borderWidth)]; 207 | [path closePath]; 208 | 209 | path.lineWidth = borderWidth; 210 | path.lineJoinStyle = borderLineJoin; 211 | [borderColor setStroke]; 212 | [path stroke]; 213 | } 214 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 215 | UIGraphicsEndImageContext(); 216 | return image; 217 | } 218 | 219 | 220 | 221 | - (UIImage *)_yy_flipHorizontal:(BOOL)horizontal vertical:(BOOL)vertical { 222 | if (!self.CGImage) return nil; 223 | size_t width = (size_t)CGImageGetWidth(self.CGImage); 224 | size_t height = (size_t)CGImageGetHeight(self.CGImage); 225 | size_t bytesPerRow = width * 4; 226 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 227 | CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); 228 | CGColorSpaceRelease(colorSpace); 229 | if (!context) return nil; 230 | 231 | CGContextDrawImage(context, CGRectMake(0, 0, width, height), self.CGImage); 232 | UInt8 *data = (UInt8 *)CGBitmapContextGetData(context); 233 | if (!data) { 234 | CGContextRelease(context); 235 | return nil; 236 | } 237 | vImage_Buffer src = { data, height, width, bytesPerRow }; 238 | vImage_Buffer dest = { data, height, width, bytesPerRow }; 239 | if (vertical) { 240 | vImageVerticalReflect_ARGB8888(&src, &dest, kvImageBackgroundColorFill); 241 | } 242 | if (horizontal) { 243 | vImageHorizontalReflect_ARGB8888(&src, &dest, kvImageBackgroundColorFill); 244 | } 245 | CGImageRef imgRef = CGBitmapContextCreateImage(context); 246 | CGContextRelease(context); 247 | UIImage *img = [UIImage imageWithCGImage:imgRef scale:self.scale orientation:self.imageOrientation]; 248 | CGImageRelease(imgRef); 249 | return img; 250 | } 251 | 252 | - (UIImage *)imageByRotate180 { 253 | return [self _yy_flipHorizontal:YES vertical:YES]; 254 | } 255 | 256 | - (UIImage *)imageByFlipVertical { 257 | return [self _yy_flipHorizontal:NO vertical:YES]; 258 | } 259 | 260 | - (UIImage *)imageByFlipHorizontal { 261 | return [self _yy_flipHorizontal:YES vertical:NO]; 262 | } 263 | 264 | static inline CGFloat DegreesToRadians(CGFloat degrees) { 265 | return degrees * M_PI / 180; 266 | } 267 | @end 268 | 269 | 270 | @implementation UIImage (Blur) 271 | 272 | - (UIImage *)imageByBlurSoft { 273 | return [self imageByBlurRadius:60 tintColor:[UIColor colorWithWhite:0.84 alpha:0.36] tintMode:kCGBlendModeNormal saturation:1.8 maskImage:nil]; 274 | } 275 | 276 | - (UIImage *)imageByBlurLight { 277 | return [self imageByBlurRadius:60 tintColor:[UIColor colorWithWhite:1.0 alpha:0.3] tintMode:kCGBlendModeNormal saturation:1.8 maskImage:nil]; 278 | } 279 | 280 | - (UIImage *)imageByBlurExtraLight { 281 | return [self imageByBlurRadius:40 tintColor:[UIColor colorWithWhite:0.97 alpha:0.82] tintMode:kCGBlendModeNormal saturation:1.8 maskImage:nil]; 282 | } 283 | 284 | - (UIImage *)imageByBlurDark { 285 | return [self imageByBlurRadius:40 tintColor:[UIColor colorWithWhite:0.11 alpha:0.73] tintMode:kCGBlendModeNormal saturation:1.8 maskImage:nil]; 286 | } 287 | 288 | - (UIImage *)imageByBlurWithTint:(UIColor *)tintColor { 289 | const CGFloat EffectColorAlpha = 0.6; 290 | UIColor *effectColor = tintColor; 291 | size_t componentCount = CGColorGetNumberOfComponents(tintColor.CGColor); 292 | if (componentCount == 2) { 293 | CGFloat b; 294 | if ([tintColor getWhite:&b alpha:NULL]) { 295 | effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha]; 296 | } 297 | } else { 298 | CGFloat r, g, b; 299 | if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) { 300 | effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha]; 301 | } 302 | } 303 | return [self imageByBlurRadius:20 tintColor:effectColor tintMode:kCGBlendModeNormal saturation:-1.0 maskImage:nil]; 304 | } 305 | 306 | - (UIImage *)imageByBlurRadius:(CGFloat)blurRadius 307 | tintColor:(UIColor *)tintColor 308 | tintMode:(CGBlendMode)tintBlendMode 309 | saturation:(CGFloat)saturation 310 | maskImage:(UIImage *)maskImage { 311 | if (self.size.width < 1 || self.size.height < 1) { 312 | NSLog(@"UIImage+YYAdd error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self); 313 | return nil; 314 | } 315 | if (!self.CGImage) { 316 | NSLog(@"UIImage+YYAdd error: inputImage must be backed by a CGImage: %@", self); 317 | return nil; 318 | } 319 | if (maskImage && !maskImage.CGImage) { 320 | NSLog(@"UIImage+YYAdd error: effectMaskImage must be backed by a CGImage: %@", maskImage); 321 | return nil; 322 | } 323 | 324 | // iOS7 and above can use new func. 325 | BOOL hasNewFunc = (long)vImageBuffer_InitWithCGImage != 0 && (long)vImageCreateCGImageFromBuffer != 0; 326 | BOOL hasBlur = blurRadius > __FLT_EPSILON__; 327 | BOOL hasSaturation = fabs(saturation - 1.0) > __FLT_EPSILON__; 328 | 329 | CGSize size = self.size; 330 | CGRect rect = { CGPointZero, size }; 331 | CGFloat scale = self.scale; 332 | CGImageRef imageRef = self.CGImage; 333 | BOOL opaque = NO; 334 | 335 | if (!hasBlur && !hasSaturation) { 336 | return [self _yy_mergeImageRef:imageRef tintColor:tintColor tintBlendMode:tintBlendMode maskImage:maskImage opaque:opaque]; 337 | } 338 | 339 | vImage_Buffer effect = { 0 }, scratch = { 0 }; 340 | vImage_Buffer *input = NULL, *output = NULL; 341 | 342 | vImage_CGImageFormat format = { 343 | .bitsPerComponent = 8, 344 | .bitsPerPixel = 32, 345 | .colorSpace = NULL, 346 | .bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little, //requests a BGRA buffer. 347 | .version = 0, 348 | .decode = NULL, 349 | .renderingIntent = kCGRenderingIntentDefault 350 | }; 351 | 352 | if (hasNewFunc) { 353 | vImage_Error err; 354 | err = vImageBuffer_InitWithCGImage(&effect, &format, NULL, imageRef, kvImagePrintDiagnosticsToConsole); 355 | if (err != kvImageNoError) { 356 | NSLog(@"UIImage+YYAdd error: vImageBuffer_InitWithCGImage returned error code %zi for inputImage: %@", err, self); 357 | return nil; 358 | } 359 | err = vImageBuffer_Init(&scratch, effect.height, effect.width, format.bitsPerPixel, kvImageNoFlags); 360 | if (err != kvImageNoError) { 361 | NSLog(@"UIImage+YYAdd error: vImageBuffer_Init returned error code %zi for inputImage: %@", err, self); 362 | return nil; 363 | } 364 | } else { 365 | UIGraphicsBeginImageContextWithOptions(size, opaque, scale); 366 | CGContextRef effectCtx = UIGraphicsGetCurrentContext(); 367 | CGContextScaleCTM(effectCtx, 1.0, -1.0); 368 | CGContextTranslateCTM(effectCtx, 0, -size.height); 369 | CGContextDrawImage(effectCtx, rect, imageRef); 370 | effect.data = CGBitmapContextGetData(effectCtx); 371 | effect.width = CGBitmapContextGetWidth(effectCtx); 372 | effect.height = CGBitmapContextGetHeight(effectCtx); 373 | effect.rowBytes = CGBitmapContextGetBytesPerRow(effectCtx); 374 | 375 | UIGraphicsBeginImageContextWithOptions(size, opaque, scale); 376 | CGContextRef scratchCtx = UIGraphicsGetCurrentContext(); 377 | scratch.data = CGBitmapContextGetData(scratchCtx); 378 | scratch.width = CGBitmapContextGetWidth(scratchCtx); 379 | scratch.height = CGBitmapContextGetHeight(scratchCtx); 380 | scratch.rowBytes = CGBitmapContextGetBytesPerRow(scratchCtx); 381 | } 382 | 383 | input = &effect; 384 | output = &scratch; 385 | 386 | if (hasBlur) { 387 | // A description of how to compute the box kernel width from the Gaussian 388 | // radius (aka standard deviation) appears in the SVG spec: 389 | // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement 390 | // 391 | // For larger values of 's' (s >= 2.0), an approximation can be used: Three 392 | // successive box-blurs build a piece-wise quadratic convolution kernel, which 393 | // approximates the Gaussian kernel to within roughly 3%. 394 | // 395 | // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5) 396 | // 397 | // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel. 398 | // 399 | CGFloat inputRadius = blurRadius * scale; 400 | if (inputRadius - 2.0 < __FLT_EPSILON__) inputRadius = 2.0; 401 | uint32_t radius = floor((inputRadius * 3.0 * sqrt(2 * M_PI) / 4 + 0.5) / 2); 402 | radius |= 1; // force radius to be odd so that the three box-blur methodology works. 403 | int iterations; 404 | if (blurRadius * scale < 0.5) iterations = 1; 405 | else if (blurRadius * scale < 1.5) iterations = 2; 406 | else iterations = 3; 407 | NSInteger tempSize = vImageBoxConvolve_ARGB8888(input, output, NULL, 0, 0, radius, radius, NULL, kvImageGetTempBufferSize | kvImageEdgeExtend); 408 | void *temp = malloc(tempSize); 409 | for (int i = 0; i < iterations; i++) { 410 | vImageBoxConvolve_ARGB8888(input, output, temp, 0, 0, radius, radius, NULL, kvImageEdgeExtend); 411 | YY_SWAP(input, output); 412 | } 413 | free(temp); 414 | } 415 | 416 | 417 | if (hasSaturation) { 418 | // These values appear in the W3C Filter Effects spec: 419 | // https://dvcs.w3.org/hg/FXTF/raw-file/default/filters/Publish.html#grayscaleEquivalent 420 | CGFloat s = saturation; 421 | CGFloat matrixFloat[] = { 422 | 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0, 423 | 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0, 424 | 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0, 425 | 0, 0, 0, 1, 426 | }; 427 | const int32_t divisor = 256; 428 | NSUInteger matrixSize = sizeof(matrixFloat) / sizeof(matrixFloat[0]); 429 | int16_t matrix[matrixSize]; 430 | for (NSUInteger i = 0; i < matrixSize; ++i) { 431 | matrix[i] = (int16_t)roundf(matrixFloat[i] * divisor); 432 | } 433 | vImageMatrixMultiply_ARGB8888(input, output, matrix, divisor, NULL, NULL, kvImageNoFlags); 434 | YY_SWAP(input, output); 435 | } 436 | 437 | UIImage *outputImage = nil; 438 | if (hasNewFunc) { 439 | CGImageRef effectCGImage = NULL; 440 | effectCGImage = vImageCreateCGImageFromBuffer(input, &format, &_yy_cleanupBuffer, NULL, kvImageNoAllocate, NULL); 441 | if (effectCGImage == NULL) { 442 | effectCGImage = vImageCreateCGImageFromBuffer(input, &format, NULL, NULL, kvImageNoFlags, NULL); 443 | free(input->data); 444 | } 445 | free(output->data); 446 | outputImage = [self _yy_mergeImageRef:effectCGImage tintColor:tintColor tintBlendMode:tintBlendMode maskImage:maskImage opaque:opaque]; 447 | CGImageRelease(effectCGImage); 448 | } else { 449 | CGImageRef effectCGImage; 450 | UIImage *effectImage; 451 | if (input != &effect) effectImage = UIGraphicsGetImageFromCurrentImageContext(); 452 | UIGraphicsEndImageContext(); 453 | if (input == &effect) effectImage = UIGraphicsGetImageFromCurrentImageContext(); 454 | UIGraphicsEndImageContext(); 455 | effectCGImage = effectImage.CGImage; 456 | outputImage = [self _yy_mergeImageRef:effectCGImage tintColor:tintColor tintBlendMode:tintBlendMode maskImage:maskImage opaque:opaque]; 457 | } 458 | return outputImage; 459 | } 460 | 461 | static void _yy_cleanupBuffer(void *userData, void *buf_data) { 462 | free(buf_data); 463 | } 464 | - (UIImage *)_yy_mergeImageRef:(CGImageRef)effectCGImage 465 | tintColor:(UIColor *)tintColor 466 | tintBlendMode:(CGBlendMode)tintBlendMode 467 | maskImage:(UIImage *)maskImage 468 | opaque:(BOOL)opaque { 469 | BOOL hasTint = tintColor != nil && CGColorGetAlpha(tintColor.CGColor) > __FLT_EPSILON__; 470 | BOOL hasMask = maskImage != nil; 471 | CGSize size = self.size; 472 | CGRect rect = { CGPointZero, size }; 473 | CGFloat scale = self.scale; 474 | 475 | if (!hasTint && !hasMask) { 476 | return [UIImage imageWithCGImage:effectCGImage]; 477 | } 478 | 479 | UIGraphicsBeginImageContextWithOptions(size, opaque, scale); 480 | CGContextRef context = UIGraphicsGetCurrentContext(); 481 | CGContextScaleCTM(context, 1.0, -1.0); 482 | CGContextTranslateCTM(context, 0, -size.height); 483 | if (hasMask) { 484 | CGContextDrawImage(context, rect, self.CGImage); 485 | CGContextSaveGState(context); 486 | CGContextClipToMask(context, rect, maskImage.CGImage); 487 | } 488 | CGContextDrawImage(context, rect, effectCGImage); 489 | if (hasTint) { 490 | CGContextSaveGState(context); 491 | CGContextSetBlendMode(context, tintBlendMode); 492 | CGContextSetFillColorWithColor(context, tintColor.CGColor); 493 | CGContextFillRect(context, rect); 494 | CGContextRestoreGState(context); 495 | } 496 | if (hasMask) { 497 | CGContextRestoreGState(context); 498 | } 499 | UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 500 | UIGraphicsEndImageContext(); 501 | return outputImage; 502 | } 503 | 504 | 505 | - (UIImage *) boxblurImageWithBlur:(CGFloat)blur exclusionPath:(UIBezierPath *)exclusionPath { 506 | 507 | if (blur < 0.f || blur > 1.f) { 508 | blur = 0.5f; 509 | } 510 | 511 | int boxSize = (int)(blur * 40); 512 | boxSize = boxSize - (boxSize % 2) + 1; 513 | 514 | CGImageRef img = self.CGImage; 515 | vImage_Buffer inBuffer, outBuffer; 516 | vImage_Error error; 517 | void *pixelBuffer; 518 | 519 | // create unchanged copy of the area inside the exclusionPath 520 | UIImage *unblurredImage = nil; 521 | if (exclusionPath != nil) { 522 | CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; 523 | maskLayer.frame = (CGRect){CGPointZero, self.size}; 524 | maskLayer.backgroundColor = [UIColor blackColor].CGColor; 525 | maskLayer.fillColor = [UIColor whiteColor].CGColor; 526 | maskLayer.path = exclusionPath.CGPath; 527 | 528 | // create grayscale image to mask context 529 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 530 | CGContextRef context = CGBitmapContextCreate(nil, maskLayer.bounds.size.width, maskLayer.bounds.size.height, 8, 0, colorSpace, kCGImageAlphaNone); 531 | CGContextTranslateCTM(context, 0, maskLayer.bounds.size.height); 532 | CGContextScaleCTM(context, 1.f, -1.f); 533 | [maskLayer renderInContext:context]; 534 | CGImageRef imageRef = CGBitmapContextCreateImage(context); 535 | UIImage *maskImage = [UIImage imageWithCGImage:imageRef]; 536 | CGImageRelease(imageRef); 537 | CGColorSpaceRelease(colorSpace); 538 | CGContextRelease(context); 539 | 540 | UIGraphicsBeginImageContext(self.size); 541 | context = UIGraphicsGetCurrentContext(); 542 | CGContextTranslateCTM(context, 0, maskLayer.bounds.size.height); 543 | CGContextScaleCTM(context, 1.f, -1.f); 544 | CGContextClipToMask(context, maskLayer.bounds, maskImage.CGImage); 545 | CGContextDrawImage(context, maskLayer.bounds, self.CGImage); 546 | unblurredImage = UIGraphicsGetImageFromCurrentImageContext(); 547 | UIGraphicsEndImageContext(); 548 | 549 | } 550 | 551 | //create vImage_Buffer with data from CGImageRef 552 | CGDataProviderRef inProvider = CGImageGetDataProvider(img); 553 | CFDataRef inBitmapData = CGDataProviderCopyData(inProvider); 554 | 555 | inBuffer.width = CGImageGetWidth(img); 556 | inBuffer.height = CGImageGetHeight(img); 557 | inBuffer.rowBytes = CGImageGetBytesPerRow(img); 558 | 559 | inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData); 560 | 561 | //create vImage_Buffer for output 562 | pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img)); 563 | 564 | if(pixelBuffer == NULL) 565 | NSLog(@"No pixelbuffer"); 566 | 567 | outBuffer.data = pixelBuffer; 568 | outBuffer.width = CGImageGetWidth(img); 569 | outBuffer.height = CGImageGetHeight(img); 570 | outBuffer.rowBytes = CGImageGetBytesPerRow(img); 571 | 572 | // Create a third buffer for intermediate processing 573 | void *pixelBuffer2 = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img)); 574 | vImage_Buffer outBuffer2; 575 | outBuffer2.data = pixelBuffer2; 576 | outBuffer2.width = CGImageGetWidth(img); 577 | outBuffer2.height = CGImageGetHeight(img); 578 | outBuffer2.rowBytes = CGImageGetBytesPerRow(img); 579 | 580 | //perform convolution 581 | error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 582 | error = vImageBoxConvolve_ARGB8888(&outBuffer2, &inBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 583 | error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 584 | 585 | if (error) { 586 | NSLog(@"error from convolution %ld", error); 587 | } 588 | 589 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 590 | CGContextRef ctx = CGBitmapContextCreate(outBuffer.data, 591 | outBuffer.width, 592 | outBuffer.height, 593 | 8, 594 | outBuffer.rowBytes, 595 | colorSpace, 596 | kCGImageAlphaNoneSkipLast); 597 | CGImageRef imageRef = CGBitmapContextCreateImage(ctx); 598 | UIImage *returnImage = [UIImage imageWithCGImage:imageRef]; 599 | 600 | // overlay images? 601 | if (unblurredImage != nil) { 602 | UIGraphicsBeginImageContext(returnImage.size); 603 | [returnImage drawAtPoint:CGPointZero]; 604 | [unblurredImage drawAtPoint:CGPointZero]; 605 | 606 | returnImage = UIGraphicsGetImageFromCurrentImageContext(); 607 | 608 | UIGraphicsEndImageContext(); 609 | } 610 | 611 | //clean up 612 | CGContextRelease(ctx); 613 | CGColorSpaceRelease(colorSpace); 614 | free(pixelBuffer); 615 | free(pixelBuffer2); 616 | CFRelease(inBitmapData); 617 | CGImageRelease(imageRef); 618 | 619 | return returnImage; 620 | 621 | } 622 | 623 | @end 624 | 625 | 626 | @implementation UIImage (ResizableImage) 627 | 628 | - (UIImage*) resizableImage:(UIEdgeInsets)insets { 629 | // if (IOS6) { 630 | // return [self resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch]; 631 | // } 632 | // 633 | return [self stretchableImageWithLeftCapWidth:insets.left topCapHeight:insets.top]; 634 | } 635 | @end 636 | 637 | 638 | 639 | @implementation UIImage (ImageEffects) 640 | 641 | - (UIImage *)applyLightEffect { 642 | UIColor* tintColor = [UIColor colorWithWhite:1.0 alpha:0.3]; 643 | return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 644 | } 645 | 646 | - (UIImage *)applyExtraLightEffect { 647 | UIColor* tintColor = [UIColor colorWithWhite:0.97 alpha:0.82]; 648 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 649 | } 650 | 651 | - (UIImage *)applyDarkEffect { 652 | UIColor* tintColor = [UIColor colorWithWhite:0.11 alpha:0.73]; 653 | return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil]; 654 | } 655 | 656 | - (UIImage *)applyBlurEffect { 657 | UIColor* tintColor = [UIColor colorWithWhite:0.4f alpha:0.3f]; 658 | return [self applyBlurWithRadius:8.0f tintColor:tintColor saturationDeltaFactor:1.8f maskImage:nil]; 659 | } 660 | 661 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor { 662 | const CGFloat EffectColorAlpha = 0.6; 663 | UIColor* effectColor = tintColor; 664 | NSUInteger componentCount = CGColorGetNumberOfComponents(tintColor.CGColor); 665 | if (componentCount == 2) { 666 | CGFloat b; 667 | if ([tintColor getWhite:&b alpha:nil]) { 668 | effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha]; 669 | } 670 | } else { 671 | CGFloat r, g, b; 672 | if ([tintColor getRed:&r green:&g blue:&b alpha:nil]) { 673 | effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha]; 674 | } 675 | } 676 | return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil]; 677 | } 678 | 679 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius 680 | tintColor:(UIColor *)tintColor 681 | saturationDeltaFactor:(CGFloat)saturationDeltaFactor 682 | maskImage:(UIImage *)maskImage { 683 | 684 | if (self.size.width < 1 || self.size.height < 1) { 685 | NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self); 686 | return nil; 687 | } 688 | if (!self.CGImage) { 689 | NSLog (@"*** error: image must be backed by a CGImage: %@", self); 690 | return nil; 691 | } 692 | if (maskImage && !maskImage.CGImage) { 693 | NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage); 694 | return nil; 695 | } 696 | 697 | CGRect imageRect = { CGPointZero, self.size }; 698 | UIImage *effectImage = self; 699 | 700 | BOOL hasBlur = blurRadius > __FLT_EPSILON__; 701 | BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__; 702 | if (hasBlur || hasSaturationChange) { 703 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 704 | CGContextRef effectInContext = UIGraphicsGetCurrentContext(); 705 | CGContextScaleCTM(effectInContext, 1.0, -1.0); 706 | CGContextTranslateCTM(effectInContext, 0, -self.size.height); 707 | CGContextDrawImage(effectInContext, imageRect, self.CGImage); 708 | 709 | vImage_Buffer effectInBuffer; 710 | effectInBuffer.data = CGBitmapContextGetData(effectInContext); 711 | effectInBuffer.width = CGBitmapContextGetWidth(effectInContext); 712 | effectInBuffer.height = CGBitmapContextGetHeight(effectInContext); 713 | effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext); 714 | 715 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 716 | CGContextRef effectOutContext = UIGraphicsGetCurrentContext(); 717 | vImage_Buffer effectOutBuffer; 718 | effectOutBuffer.data = CGBitmapContextGetData(effectOutContext); 719 | effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext); 720 | effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext); 721 | effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext); 722 | 723 | if (hasBlur) { 724 | // A description of how to compute the box kernel width from the Gaussian 725 | // radius (aka standard deviation) appears in the SVG spec: 726 | // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement 727 | // 728 | // For larger values of 's' (s >= 2.0), an approximation can be used: Three 729 | // successive box-blurs build a piece-wise quadratic convolution kernel, which 730 | // approximates the Gaussian kernel to within roughly 3%. 731 | // 732 | // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5) 733 | // 734 | // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel. 735 | // 736 | CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale]; 737 | NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5); 738 | if (radius % 2 != 1) { 739 | radius += 1; // force radius to be odd so that the three box-blur methodology works. 740 | } 741 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend); 742 | vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend); 743 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend); 744 | } 745 | BOOL effectImageBuffersAreSwapped = NO; 746 | if (hasSaturationChange) { 747 | CGFloat s = saturationDeltaFactor; 748 | CGFloat floatingPointSaturationMatrix[] = { 749 | 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0, 750 | 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0, 751 | 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0, 752 | 0, 0, 0, 1, 753 | }; 754 | const int32_t divisor = 256; 755 | NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]); 756 | int16_t saturationMatrix[matrixSize]; 757 | for (NSUInteger i = 0; i < matrixSize; ++i) { 758 | saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor); 759 | } 760 | if (hasBlur) { 761 | vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags); 762 | effectImageBuffersAreSwapped = YES; 763 | } 764 | else { 765 | vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags); 766 | } 767 | } 768 | if (!effectImageBuffersAreSwapped) 769 | effectImage = UIGraphicsGetImageFromCurrentImageContext(); 770 | UIGraphicsEndImageContext(); 771 | 772 | if (effectImageBuffersAreSwapped) 773 | effectImage = UIGraphicsGetImageFromCurrentImageContext(); 774 | UIGraphicsEndImageContext(); 775 | } 776 | 777 | // Set up output context. 778 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]); 779 | CGContextRef outputContext = UIGraphicsGetCurrentContext(); 780 | CGContextScaleCTM(outputContext, 1.0, -1.0); 781 | CGContextTranslateCTM(outputContext, 0, -self.size.height); 782 | 783 | // Draw base image. 784 | CGContextDrawImage(outputContext, imageRect, self.CGImage); 785 | 786 | // Draw effect image. 787 | if (hasBlur) { 788 | CGContextSaveGState(outputContext); 789 | if (maskImage) { 790 | CGContextClipToMask(outputContext, imageRect, maskImage.CGImage); 791 | } 792 | CGContextDrawImage(outputContext, imageRect, effectImage.CGImage); 793 | CGContextRestoreGState(outputContext); 794 | } 795 | 796 | // Add in color tint. 797 | if (tintColor) { 798 | CGContextSaveGState(outputContext); 799 | CGContextSetFillColorWithColor(outputContext, tintColor.CGColor); 800 | CGContextFillRect(outputContext, imageRect); 801 | CGContextRestoreGState(outputContext); 802 | } 803 | 804 | // Output image is ready. 805 | UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 806 | UIGraphicsEndImageContext(); 807 | 808 | return outputImage; 809 | 810 | } 811 | 812 | @end 813 | 814 | 815 | 816 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIMenuItem+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIMenuItem+Category.h 3 | // PKWSevers 4 | // 5 | // Created by chenguangjiang on 16/7/2. 6 | // Copyright © 2016年 peikua. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIMenuItem (Category) 12 | - (instancetype)initWithTitle:(NSString *)title actionBlock:(void (^)(id sender))block; 13 | @end 14 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIMenuItem+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIMenuItem+Category.m 3 | // PKWSevers 4 | // 5 | // Created by chenguangjiang on 16/7/2. 6 | // Copyright © 2016年 peikua. All rights reserved. 7 | // 8 | 9 | #import "UIMenuItem+Category.h" 10 | #import 11 | static int UIMenuItem_key; 12 | 13 | @implementation UIMenuItem (Category) 14 | 15 | - (instancetype)initWithTitle:(NSString *)title actionBlock:(void (^)(id sender))block{ 16 | self = [self initWithTitle:title action:@selector(invoke:)]; 17 | objc_setAssociatedObject(self, &UIMenuItem_key, block, OBJC_ASSOCIATION_COPY_NONATOMIC); 18 | return self; 19 | } 20 | 21 | - (void)invoke:(id)sender { 22 | void(^block)() = objc_getAssociatedObject(self, &UIMenuItem_key); 23 | if(block){ 24 | block(); 25 | } 26 | 27 | } 28 | @end 29 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UITableView+CellAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+CellAnimation.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/9/11. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UITableView (CellAnimation) 12 | 13 | - (void)moveAnimation; //左侧飞入 14 | - (void)alphaAnimation; //透明 15 | - (void)fallAnimation; //上面掉落 16 | - (void)shakeAnimation; //抖动动画 17 | - (void)overTurnAnimation; //翻转动画 18 | - (void)toTopAnimation; //从下往上 19 | - (void)springListAnimation; //从上往下弹动动画 20 | - (void)shrinkToTopAnimation;//从下往上挤向顶部 21 | - (void)layDownAnimation; //从上往下展开 22 | - (void)roteAnimation; //翻转动画 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UITableView+CellAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIself+CellAnimation.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/9/11. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "UITableView+CellAnimation.h" 10 | 11 | #define XS_SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width 12 | #define XS_SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height 13 | 14 | @implementation UITableView (CellAnimation) 15 | 16 | - (void)moveAnimation 17 | { 18 | NSArray *cells = self.visibleCells; 19 | for (int i = 0; i < cells.count; i++) { 20 | CGFloat totalTime = 0.4; 21 | UITableViewCell *cell = [self.visibleCells objectAtIndex:i]; 22 | cell.transform = CGAffineTransformMakeTranslation(-XS_SCREEN_WIDTH, 0); 23 | [UIView animateWithDuration:0.4 delay:i*(totalTime/cells.count) usingSpringWithDamping:0.7 initialSpringVelocity:1/0.7 options:UIViewAnimationOptionCurveEaseIn animations:^{ 24 | cell.transform = CGAffineTransformIdentity; 25 | } completion:^(BOOL finished) { 26 | 27 | }]; 28 | } 29 | } 30 | 31 | - (void)alphaAnimation 32 | { 33 | NSArray *cells = self.visibleCells; 34 | for (int i = 0; i < cells.count; i++) { 35 | UITableViewCell *cell = [self.visibleCells objectAtIndex:i]; 36 | cell.alpha = 0.0; 37 | [UIView animateWithDuration:0.3 delay:i*0.05 options:0 animations:^{ 38 | cell.alpha = 1.0; 39 | } completion:^(BOOL finished) { 40 | 41 | }]; 42 | } 43 | } 44 | 45 | - (void)fallAnimation 46 | { 47 | NSArray *cells = self.visibleCells; 48 | 49 | NSTimeInterval totalTime = 0.8; 50 | 51 | for (int i = 0; i < cells.count; i++) { 52 | UITableViewCell *cell = [self.visibleCells objectAtIndex:i]; 53 | cell.transform = CGAffineTransformMakeTranslation(0, - XS_SCREEN_HEIGHT); 54 | [UIView animateWithDuration:0.3 delay:(cells.count - i)*(totalTime/cells.count) options:0 animations:^{ 55 | cell.transform = CGAffineTransformIdentity; 56 | } completion:^(BOOL finished) { 57 | 58 | }]; 59 | } 60 | } 61 | 62 | - (void)shakeAnimation 63 | { 64 | NSArray *cells = self.visibleCells; 65 | for (int i = 0; i < cells.count; i++) { 66 | UITableViewCell *cell = [cells objectAtIndex:i]; 67 | if (i%2 == 0) { 68 | cell.transform = CGAffineTransformMakeTranslation(-XS_SCREEN_WIDTH,0); 69 | }else { 70 | cell.transform = CGAffineTransformMakeTranslation(XS_SCREEN_WIDTH,0); 71 | } 72 | [UIView animateWithDuration:0.4 delay:i*0.03 usingSpringWithDamping:0.75 initialSpringVelocity:1/0.75 options:0 animations:^{ 73 | cell.transform = CGAffineTransformIdentity; 74 | } completion:^(BOOL finished) { 75 | 76 | }]; 77 | } 78 | } 79 | 80 | - (void)overTurnAnimation 81 | { 82 | NSArray *cells = self.visibleCells; 83 | for (int i = 0; i < cells.count; i++) { 84 | UITableViewCell *cell = [cells objectAtIndex:i]; 85 | cell.layer.opacity = 0.0; 86 | cell.layer.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0); 87 | NSTimeInterval totalTime = 0.7; 88 | [UIView animateWithDuration:0.3 delay:i*(totalTime/cells.count) options:0 animations:^{ 89 | cell.layer.opacity = 1.0; 90 | cell.layer.transform = CATransform3DIdentity; 91 | } completion:^(BOOL finished) { 92 | 93 | }]; 94 | 95 | } 96 | } 97 | 98 | - (void)toTopAnimation 99 | { 100 | NSArray *cells = self.visibleCells; 101 | 102 | NSTimeInterval totalTime = 0.8; 103 | 104 | for (int i = 0; i < cells.count; i++) { 105 | UITableViewCell *cell = [self.visibleCells objectAtIndex:i]; 106 | cell.transform = CGAffineTransformMakeTranslation(0, XS_SCREEN_HEIGHT); 107 | [UIView animateWithDuration:0.35 delay:i*(totalTime/cells.count) options:UIViewAnimationOptionCurveEaseOut animations:^{ 108 | cell.transform = CGAffineTransformIdentity; 109 | } completion:^(BOOL finished) { 110 | 111 | }]; 112 | } 113 | } 114 | 115 | - (void)springListAnimation 116 | { 117 | NSArray *cells = self.visibleCells; 118 | for (int i = 0; i < cells.count; i++) { 119 | UITableViewCell *cell = [cells objectAtIndex:i]; 120 | cell.layer.opacity = 0.7; 121 | cell.layer.transform = CATransform3DMakeTranslation(0, -XS_SCREEN_HEIGHT, 20); 122 | NSTimeInterval totalTime = 1.0; 123 | 124 | [UIView animateWithDuration:0.4 delay:i*(totalTime/cells.count) usingSpringWithDamping:0.65 initialSpringVelocity:1/0.65 options:UIViewAnimationOptionCurveEaseIn animations:^{ 125 | cell.layer.opacity = 1.0; 126 | cell.layer.transform = CATransform3DMakeTranslation(0, 0, 20); 127 | } completion:^(BOOL finished) { 128 | 129 | }]; 130 | } 131 | } 132 | 133 | - (void)shrinkToTopAnimation 134 | { 135 | NSArray *cells = self.visibleCells; 136 | for (int i = 0; i < cells.count; i++) { 137 | UITableViewCell *cell = [cells objectAtIndex:i]; 138 | CGRect rect = [cell convertRect:cell.bounds fromView:self]; 139 | cell.transform = CGAffineTransformMakeTranslation(0, -rect.origin.y); 140 | [UIView animateWithDuration:0.5 animations:^{ 141 | cell.transform = CGAffineTransformIdentity; 142 | }]; 143 | } 144 | } 145 | 146 | - (void)layDownAnimation 147 | { 148 | NSArray *cells = self.visibleCells; 149 | NSMutableArray *rectArr = [[NSMutableArray alloc] init]; 150 | for (int i = 0; i < cells.count; i++) { 151 | UITableViewCell *cell = [cells objectAtIndex:i]; 152 | CGRect rect = cell.frame; 153 | [rectArr addObject:[NSValue valueWithCGRect:rect]]; 154 | rect.origin.y = i * 10; 155 | cell.frame = rect; 156 | cell.layer.transform = CATransform3DMakeTranslation(0, 0, i*5); 157 | } 158 | NSTimeInterval totalTime = 0.8; 159 | for (int i = 0; i < cells.count; i++) { 160 | UITableViewCell *cell = [cells objectAtIndex:i]; 161 | CGRect rect = [[rectArr objectAtIndex:i] CGRectValue]; 162 | [UIView animateWithDuration:(totalTime/cells.count) * i animations:^{ 163 | cell.frame = rect; 164 | } completion:^(BOOL finished) { 165 | cell.layer.transform = CATransform3DIdentity; 166 | }]; 167 | } 168 | 169 | } 170 | 171 | - (void)roteAnimation 172 | { 173 | NSArray *cells = self.visibleCells; 174 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"]; 175 | animation.fromValue = @(-M_PI); 176 | animation.toValue = 0; 177 | animation.duration = 0.3; 178 | animation.removedOnCompletion = NO; 179 | animation.repeatCount = 3; 180 | animation.fillMode = kCAFillModeForwards; 181 | animation.autoreverses = NO; 182 | 183 | for (int i = 0; i < cells.count; i++) { 184 | UITableViewCell *cell = [cells objectAtIndex:i]; 185 | 186 | cell.alpha = 0.0; 187 | [UIView animateWithDuration:0.1 delay:i*0.25 options:0 animations:^{ 188 | cell.alpha = 1.0; 189 | } completion:^(BOOL finished) { 190 | [cell.layer addAnimation:animation forKey:@"rotationYkey"]; 191 | }]; 192 | } 193 | } 194 | 195 | @end 196 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIView+Category.h: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface UIView (Category) 11 | //把View加在Window上 12 | - (void) addToWindow; 13 | 14 | @end 15 | 16 | @interface UIView (Screenshot) 17 | 18 | //View截图 19 | - (UIImage*) screenshot; 20 | 21 | //ScrollView截图 contentOffset 22 | - (UIImage*) screenshotForScrollViewWithContentOffset:(CGPoint)contentOffset; 23 | 24 | //View按Rect截图 25 | - (UIImage*) screenshotInFrame:(CGRect)frame; 26 | 27 | //整个view转成图片 28 | - (UIImage*) convertToImage; 29 | @end 30 | 31 | @interface UIView (Animation) 32 | 33 | //左右抖动动画 34 | - (void) shakeAnimation; 35 | 36 | //旋转180度 37 | - (void) trans180DegreeAnimation; 38 | 39 | @end 40 | 41 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIView+Category.m: -------------------------------------------------------------------------------- 1 | // 2 | // PK-ios 3 | // 4 | // Created by peikua on 15/9/15. 5 | // Copyright (c) 2015年 peikua. All rights reserved. 6 | // 7 | 8 | #import "UIView+Category.h" 9 | #import 10 | #import 11 | 12 | @implementation UIView (Category) 13 | 14 | -(void) addToWindow 15 | { 16 | id appDelegate = [[UIApplication sharedApplication] delegate]; 17 | if ([appDelegate respondsToSelector:@selector(window)]) 18 | { 19 | UIWindow * window = (UIWindow *) [appDelegate performSelector:@selector(window)]; 20 | [window addSubview:self]; 21 | } 22 | } 23 | 24 | 25 | @end 26 | 27 | 28 | @implementation UIView (Screenshot) 29 | 30 | - (UIImage*) screenshot { 31 | 32 | UIGraphicsBeginImageContext(self.bounds.size); 33 | [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 34 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 35 | UIGraphicsEndImageContext(); 36 | 37 | // helps w/ our colors when blurring 38 | // feel free to adjust jpeg quality (lower = higher perf) 39 | NSData *imageData = UIImageJPEGRepresentation(image, 0.75); 40 | image = [UIImage imageWithData:imageData]; 41 | 42 | return image; 43 | 44 | } 45 | 46 | - (UIImage *) screenshotForScrollViewWithContentOffset:(CGPoint)contentOffset { 47 | UIGraphicsBeginImageContext(self.bounds.size); 48 | //need to translate the context down to the current visible portion of the scrollview 49 | CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0f, -contentOffset.y); 50 | [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 51 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 52 | UIGraphicsEndImageContext(); 53 | 54 | // helps w/ our colors when blurring 55 | // feel free to adjust jpeg quality (lower = higher perf) 56 | NSData *imageData = UIImageJPEGRepresentation(image, 0.55); 57 | image = [UIImage imageWithData:imageData]; 58 | 59 | return image; 60 | } 61 | 62 | - (UIImage*) screenshotInFrame:(CGRect)frame { 63 | UIGraphicsBeginImageContext(frame.size); 64 | CGContextTranslateCTM(UIGraphicsGetCurrentContext(), frame.origin.x, frame.origin.y); 65 | [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 66 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 67 | UIGraphicsEndImageContext(); 68 | 69 | // helps w/ our colors when blurring 70 | // feel free to adjust jpeg quality (lower = higher perf) 71 | NSData *imageData = UIImageJPEGRepresentation(image, 0.75); 72 | image = [UIImage imageWithData:imageData]; 73 | 74 | return image; 75 | } 76 | 77 | -(UIImage *) convertToImage { 78 | CGSize viewSize = self.bounds.size; 79 | UIGraphicsBeginImageContextWithOptions(viewSize, NO, [UIScreen mainScreen].scale); 80 | [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 81 | UIImage*image = UIGraphicsGetImageFromCurrentImageContext(); 82 | UIGraphicsEndImageContext(); 83 | return image; 84 | } 85 | 86 | @end 87 | 88 | @implementation UIView (Animation) 89 | 90 | - (void) shakeAnimation { 91 | 92 | CALayer* layer = [self layer]; 93 | CGPoint position = [layer position]; 94 | CGPoint y = CGPointMake(position.x - 8.0f, position.y); 95 | CGPoint x = CGPointMake(position.x + 8.0f, position.y); 96 | CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"position"]; 97 | [animation setTimingFunction:[CAMediaTimingFunction 98 | functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 99 | [animation setFromValue:[NSValue valueWithCGPoint:x]]; 100 | [animation setToValue:[NSValue valueWithCGPoint:y]]; 101 | [animation setAutoreverses:YES]; 102 | [animation setDuration:0.08f]; 103 | [animation setRepeatCount:3]; 104 | [layer addAnimation:animation forKey:nil]; 105 | } 106 | 107 | - (void) trans180DegreeAnimation 108 | { 109 | [UIView animateWithDuration:0.3 animations:^{ 110 | self.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0); 111 | }]; 112 | } 113 | @end 114 | 115 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIView+Frame.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Frame.h 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Frame) 12 | //不用再蛋疼的写某view.frame=CGRectMake(x,y,z,o)了。 13 | - (CGFloat)left; 14 | - (CGFloat)right; 15 | - (CGSize)size; 16 | - (CGFloat)top; 17 | - (CGFloat)bottom; 18 | - (CGFloat)width; 19 | - (CGFloat)height; 20 | - (CGFloat)centerX; 21 | - (CGFloat)centerY; 22 | - (CGFloat)maxX; 23 | - (CGFloat)maxY; 24 | 25 | - (void)setLeft:(CGFloat)left; 26 | - (void)setRight:(CGFloat)right; 27 | - (void)setSize:(CGSize)size; 28 | - (void)setTop:(CGFloat)top; 29 | - (void)setBottom:(CGFloat)bottom; 30 | - (void)setWidth:(CGFloat)width; 31 | - (void)setHeight:(CGFloat)height; 32 | - (void)setCenterX:(CGFloat)centerX; 33 | - (void)setCenterY:(CGFloat)centerY; 34 | - (void)setOrigin:(CGPoint)point; 35 | - (void)setAddTop:(CGFloat)top; 36 | - (void)setAddLeft:(CGFloat)left; 37 | @end 38 | -------------------------------------------------------------------------------- /iOS-Category/iOS-Category/UIView+Frame.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Frame.m 3 | // iOS-Category 4 | // 5 | // Created by 庄BB的MacBook on 2017/8/23. 6 | // Copyright © 2017年 BBFC. All rights reserved. 7 | // 8 | 9 | #import "UIView+Frame.h" 10 | 11 | @implementation UIView (Frame) 12 | - (CGFloat)left 13 | { 14 | return self.frame.origin.x; 15 | } 16 | 17 | - (CGFloat)right 18 | { 19 | return self.frame.origin.x + self.frame.size.width; 20 | } 21 | 22 | - (CGFloat)top 23 | { 24 | return self.frame.origin.y; 25 | } 26 | 27 | - (CGFloat)bottom 28 | { 29 | return self.frame.origin.y + self.frame.size.height; 30 | } 31 | 32 | - (CGSize)size{ 33 | return self.frame.size; 34 | } 35 | 36 | - (CGFloat)width 37 | { 38 | return self.frame.size.width; 39 | } 40 | 41 | - (CGFloat)height 42 | { 43 | return self.frame.size.height; 44 | } 45 | 46 | - (CGFloat)centerX 47 | { 48 | return self.center.x; 49 | } 50 | 51 | - (CGFloat)centerY 52 | { 53 | return self.center.y; 54 | } 55 | 56 | - (CGFloat)maxX 57 | { 58 | return CGRectGetMaxX(self.frame); 59 | } 60 | 61 | - (CGFloat)maxY 62 | { 63 | return CGRectGetMaxY(self.frame); 64 | } 65 | 66 | - (void)setLeft:(CGFloat)left 67 | { 68 | CGRect frame = self.frame; 69 | frame.origin.x = left; 70 | self.frame = frame; 71 | } 72 | 73 | - (void)setRight:(CGFloat)right; 74 | { 75 | CGRect frame = self.frame; 76 | frame.origin.x = right - frame.size.width; 77 | self.frame = frame; 78 | } 79 | 80 | - (void)setBottom:(CGFloat)bottom 81 | { 82 | CGRect frame = self.frame; 83 | frame.origin.y = bottom - frame.size.height; 84 | self.frame = frame; 85 | } 86 | 87 | - (void)setSize:(CGSize)size 88 | { 89 | CGRect frame = self.frame; 90 | frame.size = size; 91 | self.frame = frame; 92 | } 93 | 94 | - (void)setTop:(CGFloat)top 95 | { 96 | CGRect frame = self.frame; 97 | frame.origin.y = top; 98 | self.frame = frame; 99 | } 100 | 101 | - (void)setWidth:(CGFloat)width 102 | { 103 | CGRect frame = self.frame; 104 | frame.size.width = width; 105 | self.frame = frame; 106 | } 107 | 108 | - (void)setHeight:(CGFloat)height 109 | { 110 | CGRect frame = self.frame; 111 | frame.size.height = height; 112 | self.frame = frame; 113 | } 114 | 115 | - (void)setOrigin:(CGPoint)point 116 | { 117 | CGRect frame = self.frame; 118 | frame.origin = point; 119 | self.frame = frame; 120 | } 121 | 122 | - (void)setCenterX:(CGFloat)centerX 123 | { 124 | self.center = CGPointMake(centerX, self.center.y); 125 | } 126 | 127 | - (void)setCenterY:(CGFloat)centerY 128 | { 129 | self.center = CGPointMake(self.center.x, centerY); 130 | } 131 | 132 | - (void)setAddTop:(CGFloat)top 133 | { 134 | CGRect frame = self.frame; 135 | frame.origin.y += top; 136 | self.frame = frame; 137 | } 138 | 139 | - (void)setAddLeft:(CGFloat)left 140 | { 141 | CGRect frame = self.frame; 142 | frame.origin.x += left; 143 | self.frame = frame; 144 | } 145 | 146 | @end 147 | --------------------------------------------------------------------------------