This commit is contained in:
DDIsFriend
2023-08-18 17:28:57 +08:00
commit f0e8a1709d
4282 changed files with 192396 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
//
// CALayer+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <QuartzCore/QuartzCore.h>
NS_ASSUME_NONNULL_BEGIN
@interface CALayer (DDCategory)
/**
*give the layer shadow
*@param shadowColor layer shadowColor
*@param shadowOffset layer shadowOffset
*@param shadowRadius layer shadowRadius
*@param shadowOpacity layer shadowOpacity
*@param layerBackground you must set layerBackground,otherwise shadow can not be show.
*@warning this function maybe effect fps, you should set rasterize to reduce impact. and you can set shadowPath to reduce consumption of cpu. the layerBackground must be setted.
*/
+ (CALayer *)dd_layerWithShadowColor:(CGColorRef)shadowColor shadowOffset:(CGSize)shadowOffset shadowRadius:(CGFloat)shadowRadius shadowOpacity:(CGFloat)shadowOpacity cornerRadius:(CGFloat)cornerRadius layerBackground:(nullable CGColorRef)layerBackground;
/**
*the view transfer this function must already has setted background.
*/
- (void)dd_layerWithShadowColor:(CGColorRef)shadowColor shadowOffset:(CGSize)shadowOffset shadowRadius:(CGFloat)shadowRadius shadowOpacity:(CGFloat)shadowOpacity cornerRadius:(CGFloat)cornerRadius layerBackground:(nullable CGColorRef)layerBackground;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,41 @@
//
// CALayer+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "CALayer+DDCategory.h"
@implementation CALayer (DDCategory)
+ (CALayer *)dd_layerWithShadowColor:(CGColorRef)shadowColor shadowOffset:(CGSize)shadowOffset shadowRadius:(CGFloat)shadowRadius shadowOpacity:(CGFloat)shadowOpacity cornerRadius:(CGFloat)cornerRadius layerBackground:(nullable CGColorRef)layerBackground{
CALayer *layer = [CALayer layer];
layer.shadowColor = shadowColor;
layer.shadowOffset = shadowOffset;
layer.shadowRadius = shadowRadius;
layer.shadowOpacity = shadowOpacity;
layer.cornerRadius = cornerRadius;
layer.backgroundColor = layerBackground;
layer.shouldRasterize = YES;
layer.rasterizationScale = UIScreen.mainScreen.scale;
return layer;
}
- (void)dd_layerWithShadowColor:(CGColorRef)shadowColor shadowOffset:(CGSize)shadowOffset shadowRadius:(CGFloat)shadowRadius shadowOpacity:(CGFloat)shadowOpacity cornerRadius:(CGFloat)cornerRadius layerBackground:(nullable CGColorRef)layerBackground{
if (!self) return ;
self.shadowColor = shadowColor;
self.shadowOffset = shadowOffset;
self.shadowRadius = shadowRadius;
self.shadowOpacity = shadowOpacity;
self.cornerRadius = cornerRadius;
self.backgroundColor = layerBackground;
self.shouldRasterize = YES;
self.rasterizationScale = UIScreen.mainScreen.scale;
}
@end

View File

@@ -0,0 +1,37 @@
//
// DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#ifndef DDCategory_h
#define DDCategory_h
#import <DDCategoryKit_Private/UILabel+DDCategory.h>
#import <DDCategoryKit_Private/NSMutableAttributedString+DDCategory.h>
#import <DDCategoryKit_Private/NSAttributedString+DDCategory.h>
#import <DDCategoryKit_Private/UIButton+DDCategory.h>
#import <DDCategoryKit_Private/UIView+DDCategory.h>
#import <DDCategoryKit_Private/CALayer+DDCategory.h>
#import <DDCategoryKit_Private/NSObject+DDCategory.h>
#import <DDCategoryKit_Private/NSBundle+DDCategory.h>
#import <DDCategoryKit_Private/UIImage+DDCategory.h>
#import <DDCategoryKit_Private/UINavigationController+DDCategory.h>
#import <DDCategoryKit_Private/UIViewController+DDCategory.h>
#import <DDCategoryKit_Private/UINavigationBar+DDCategory.h>
#import <DDCategoryKit_Private/NSThread+DDCategory.h>
#import <DDCategoryKit_Private/UIApplication+DDCategory.h>
#import <DDCategoryKit_Private/UIWindow+DDCategory.h>
#import <DDCategoryKit_Private/UIScreen+DDCategory.h>
#import <DDCategoryKit_Private/NSUrl+DDCategory.h>
#import <DDCategoryKit_Private/UIFont+DDCategory.h>
#import <DDCategoryKit_Private/UIBarButtonItem+DDCategory.h>
#import <DDCategoryKit_Private/UICollectionView+DDCategory.h>
#import <DDCategoryKit_Private/UICollectionViewCell+DDCategory.h>
#import <DDCategoryKit_Private/UITableView+DDCategory.h>
#import <DDCategoryKit_Private/UITableViewCell+DDCategory.h>
#import <DDCategoryKit_Private/UIImageView+DDCategory.h>
#import <DDCategoryKit_Private/UITextField+DDCategory.h>
#import <DDCategoryKit_Private/UITextView+DDCategory.h>
#import <DDCategoryKit_Private/UIScrollView+DDCategory.h>
#endif /* DDCategory_h */

View File

@@ -0,0 +1,49 @@
//
// NSAttributedString+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <Foundation/Foundation.h>
// NSFontAttributeName 设置字体属性默认值字体Helvetica(Neue) 字号12
// NSForegroundColorAttributeName 设置字体颜色,取值为 UIColor对象默认值为黑色
// NSBackgroundColorAttributeName 设置字体所在区域背景颜色,取值为 UIColor对象默认值为nil, 透明色
// NSLigatureAttributeName 设置连体属性取值为NSNumber 对象(整数)0 表示没有连体字符1 表示使用默认的连体字符
// NSKernAttributeName 设定字符间距,取值为 NSNumber 对象(整数),正值间距加宽,负值间距变窄
// NSStrikethroughStyleAttributeName 设置删除线,取值为 NSNumber 对象(整数)
// NSStrikethroughColorAttributeName 设置删除线颜色,取值为 UIColor 对象,默认值为黑色
// NSUnderlineStyleAttributeName 设置下划线,取值为 NSNumber 对象(整数),枚举常量 NSUnderlineStyle中的值与删除线类似
// NSUnderlineColorAttributeName 设置下划线颜色,取值为 UIColor 对象,默认值为黑色
// NSStrokeWidthAttributeName 设置笔画宽度,取值为 NSNumber 对象(整数),负值填充效果,正值中空效果
// NSStrokeColorAttributeName 填充部分颜色,不是字体颜色,取值为 UIColor 对象
// NSShadowAttributeName 设置阴影属性,取值为 NSShadow 对象
// NSTextEffectAttributeName 设置文本特殊效果,取值为 NSString 对象,目前只有图版印刷效果可用:
// NSBaselineOffsetAttributeName 设置基线偏移值,取值为 NSNumber float,正值上偏,负值下偏
// NSObliquenessAttributeName 设置字形倾斜度,取值为 NSNumber float,正值右倾,负值左倾
// NSExpansionAttributeName 设置文本横向拉伸属性,取值为 NSNumber float,正值横向拉伸文本,负值横向压缩文本
// NSWritingDirectionAttributeName 设置文字书写方向,从左向右书写或者从右向左书写
// NSVerticalGlyphFormAttributeName 设置文字排版方向,取值为 NSNumber 对象(整数)0 表示横排文本1 表示竖排文本
// NSLinkAttributeName 设置链接属性点击后调用浏览器打开指定URL地址
// NSAttachmentAttributeName 设置文本附件,取值为NSTextAttachment对象,常用于文字图片混排
// NSParagraphStyleAttributeName 设置文本段落排版格式,取值为 NSParagraphStyle 对象&emsp;
NS_ASSUME_NONNULL_BEGIN
@interface NSAttributedString (DDCategory)
/**
@param string NSString.
@param attrs @{NSAttributedStringKey : value}.
*/
- (NSAttributedString *)dd_initWithString:(NSString *)string attributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs;
/**
* return mutableAttributedString.
*/
- (NSMutableAttributedString *)dd_mutable;
/**
*@param textAttachment textAttachment can contain image.
*/
+ (NSAttributedString *)dd_attributedStringWithAttachment:(NSTextAttachment *)textAttachment;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,23 @@
//
// NSAttributedString+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "NSAttributedString+DDCategory.h"
@implementation NSAttributedString (DDCategory)
- (NSAttributedString *)dd_initWithString:(NSString *)string attributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs{
return [[NSAttributedString alloc] initWithString:string attributes:attrs];
}
- (NSMutableAttributedString *)dd_mutable
{
return [[NSMutableAttributedString alloc] initWithAttributedString:self];
}
+ (NSAttributedString *)dd_attributedStringWithAttachment:(NSTextAttachment *)textAttachment{
return [NSAttributedString attributedStringWithAttachment:textAttachment];
}
@end

View File

@@ -0,0 +1,40 @@
//
// NSMutableAttributedString+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSMutableAttributedString (DDCategory)
/**
*@param string this string will be a mutableAttributedString with attrs.
*@param attrs @{NSAttributedStringKey : value}.
*/
- (NSMutableAttributedString *)dd_appendString:(NSString *)string attributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs;
/**
*return a unmutableAttributedString.
*/
- (NSAttributedString *)dd_immutable;
/**
*@param attributedString attributedString
*/
- (NSMutableAttributedString *)dd_appendAttributedString:(NSAttributedString *)attributedString;
/**
@param pattern RegularExpressionWithPattern.
@param attrs pattern be matched will be with attrs.
*/
- (NSMutableAttributedString *)dd_matchesRegularExpressionWithPattern:(NSString *)pattern withAttributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs;
/**
@param pattern RegularExpressionWithPattern.
@param attrs the first pattern be matched will be with attrs.
*/
- (NSMutableAttributedString *)dd_firstMatchesRegularExpressionWithPattern:(NSString *)pattern withAttributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,66 @@
//
// NSMutableAttributedString+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "NSMutableAttributedString+DDCategory.h"
#import "NSAttributedString+DDCategory.h"
@implementation NSMutableAttributedString (DDCategory)
- (NSMutableAttributedString *)dd_appendString:(NSString *)string attributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs{
// while self is not init yet, return string
if (self.length == 0) {
return [[NSMutableAttributedString alloc] initWithString:string attributes:attrs];
}
[self appendAttributedString:[[NSMutableAttributedString alloc] dd_initWithString:string attributes:attrs]];
return self;
}
- (NSMutableAttributedString *)dd_appendAttributedString:(NSAttributedString *)attributedString{
[self appendAttributedString:attributedString];
return self;
}
- (NSAttributedString *)dd_immutable{
return [[NSAttributedString alloc] initWithAttributedString:self];
}
- (NSMutableAttributedString *)dd_matchesRegularExpressionWithPattern:(NSString *)pattern withAttributes:(NSDictionary<NSAttributedStringKey,id> *)attrs{
if (attrs == nil || [attrs isEqualToDictionary:@{}]) {
return self;
}
NSError *error;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
__weak typeof(self) weakSelf = self;
[expression enumerateMatchesInString:self.string options:NSMatchingReportProgress range:NSMakeRange(0, self.string.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[attrs enumerateKeysAndObjectsUsingBlock:^(NSAttributedStringKey _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[strongSelf addAttribute:key value:obj range:[result range]];
}];
}];
return self;
}
- (NSMutableAttributedString *)dd_firstMatchesRegularExpressionWithPattern:(NSString *)pattern withAttributes:(NSDictionary<NSAttributedStringKey,id> *)attrs{
if (attrs == nil || [attrs isEqualToDictionary:@{}]) {
return self;
}
NSError *error;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
NSRange range = [expression rangeOfFirstMatchInString:self.string options:NSMatchingReportProgress range:NSMakeRange(0, self.string.length)];
__weak typeof(self) weakSelf = self;
[attrs enumerateKeysAndObjectsUsingBlock:^(NSAttributedStringKey _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf addAttribute:key value:obj range:range];
}];
return self;
}
@end

View File

@@ -0,0 +1,20 @@
//
// NSMutableParagraphStyle+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSMutableParagraphStyle (DDCategory)
/**
*@param lineSpace line space
*@param paragraphSpacing paragraph spacing,the effect with '\n'
*@param alignment text alignment
*@param firstLineHeadIndent firstLineHeadIndent, the effect with '\n'
*/
+ (NSMutableParagraphStyle *)dd_initWithLineSpacing:(CGFloat)lineSpace paragraphSpacing:(CGFloat)paragraphSpacing alignment:(NSTextAlignment)alignment firstLineHeadIndent:(CGFloat)firstLineHeadIndent;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,17 @@
//
// NSMutableParagraphStyle+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "NSMutableParagraphStyle+DDCategory.h"
@implementation NSMutableParagraphStyle (DDCategory)
+ (NSMutableParagraphStyle *)dd_initWithLineSpacing:(CGFloat)lineSpace paragraphSpacing:(CGFloat)paragraphSpacing alignment:(NSTextAlignment)alignment firstLineHeadIndent:(CGFloat)firstLineHeadIndent{
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineSpacing = lineSpace;
paragraph.paragraphSpacing = paragraphSpacing;
paragraph.alignment = alignment;
paragraph.firstLineHeadIndent = firstLineHeadIndent;
return paragraph;
}
@end

View File

@@ -0,0 +1,14 @@
//
// NSBundle+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSBundle (DDCategory)
- (nullable NSBundle *)bundleWithName:(NSString *)bundleName aClass:(Class)aClass;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,20 @@
//
// NSBundle+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "NSBundle+DDCategory.h"
@implementation NSBundle (DDCategory)
- (nullable NSBundle *)bundleWithName:(NSString *)bundleName aClass:(Class)aClass{
NSString *bundlePath = [[NSBundle bundleForClass:aClass].resourcePath stringByAppendingPathComponent:bundleName];
NSString *bundleType = @".bundle";
if (![bundlePath hasSuffix:bundleType]) {
bundlePath = [bundlePath stringByAppendingString:bundleType];
}
NSBundle *sourceBundle = [NSBundle bundleWithPath:bundlePath];
return sourceBundle;
}
@end

View File

@@ -0,0 +1,16 @@
//
// NSObject+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSObject (DDCategory)
+ (void)dd_class:(Class)class originSelector:(SEL)originSelector swizzleSelector:(SEL)swizzleSelector;
+ (void)dd_originSelector:(SEL)originSelector swizzleSelector:(SEL)swizzleSelector;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
//
// NSObject+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "NSObject+DDCategory.h"
#import <objc/runtime.h>
@implementation NSObject (DDCategory)
+ (void)dd_class:(Class)class originSelector:(SEL)originSelector swizzleSelector:(SEL)swizzleSelector{
Method originMethod = class_getInstanceMethod(class, originSelector);
Method swizzleMethod = class_getInstanceMethod(class, swizzleSelector);
BOOL success = class_addMethod(class, originSelector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
if (success){
class_replaceMethod(class, swizzleSelector, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
}else{
method_exchangeImplementations(originMethod, swizzleMethod);
}
}
+ (void)dd_originSelector:(SEL)originSelector swizzleSelector:(SEL)swizzleSelector{
Class class = [self class];
Method originMethod = class_getInstanceMethod(class, originSelector);
Method swizzleMethod = class_getInstanceMethod(class, swizzleSelector);
BOOL success = class_addMethod(class, originSelector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
if (success){
class_replaceMethod(class, swizzleSelector, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
}else{
method_exchangeImplementations(originMethod, swizzleMethod);
}
}
@end

View File

@@ -0,0 +1,17 @@
//
// NSThread+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/12/28.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSThread (DDCategory)
+ (instancetype)defaultRunThread;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,20 @@
//
// NSThread+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/12/28.
#import "NSThread+DDCategory.h"
#import <objc/runtime.h>
@implementation NSThread (DDCategory)
+ (instancetype)defaultRunThread{
return [[NSThread alloc] initWithBlock:^{
NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
while (!NSThread.currentThread.isCancelled) {
[currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]];
}
NSAssert([NSThread currentThread].isCancelled, @"%@ 子线程即将 'exit' ",[NSThread currentThread]);
}];;
}
@end

View File

@@ -0,0 +1,14 @@
//
// NSURL+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSURL (DDCategory)
+ (NSURL *)encodingUrlString:(NSString *)urlString withAllowedCharactersString:(nullable NSString *)allowedCharactersString;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,15 @@
//
// NSURL+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import "NSURL+DDCategory.h"
@implementation NSURL (DDCategory)
+ (NSURL *)encodingUrlString:(NSString *)urlString withAllowedCharactersString:(nullable NSString *)allowedCharactersString{
if (allowedCharactersString == nil) {
allowedCharactersString = @"\"#%<>[\\]^`{|}";
}
return [self URLWithString:[urlString stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:allowedCharactersString] invertedSet]]];
}
@end

View File

@@ -0,0 +1,20 @@
//
// UIApplication+DDCategory.h
// DDCategoryKit_Private
//
// Created by 中道 on 2023/2/6.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIApplication (DDCategory)
@property (nonatomic, strong, readonly)UIWindow *dd_keyWindow;
@property (nonatomic, assign, readonly)CGRect dd_statusBarFrame;
- (UIWindow *)dd_keyWindow;
- (CGRect)dd_statusBarFrame;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,88 @@
//
// UIApplication+DDCategory.m
// DDCategoryKit_Private
//
// Created by on 2023/2/6.
//
#import "UIApplication+DDCategory.h"
@implementation UIApplication (DDCategory)
@dynamic dd_keyWindow;
@dynamic dd_statusBarFrame;
- (UIWindow *)dd_keyWindow{
static __weak UIWindow *cachedKeyWindow = nil;
UIWindow *originalKeyWindow = nil;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
NSSet<UIScene *> *connectedScenes = [UIApplication sharedApplication].connectedScenes;
for (UIScene *scene in connectedScenes) {
if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
UIWindowScene *windowScene = (UIWindowScene *)scene;
for (UIWindow *window in windowScene.windows) {
if (window.isKeyWindow) {
originalKeyWindow = window;
break;
}
}
}
}
} else
#endif
{
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
originalKeyWindow = [UIApplication sharedApplication].keyWindow;
#endif
}
// appstoryboardkeyWindow
if (originalKeyWindow == nil) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
NSSet<UIScene *> *connectedScenes = [UIApplication sharedApplication].connectedScenes;
for (UIScene *scene in connectedScenes) {
if ([scene isKindOfClass:[UIWindowScene class]]) {
UIWindowScene *windowScene = (UIWindowScene *)scene;
originalKeyWindow = windowScene.windows.firstObject;
break;
}
}
} else
#endif
{
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
originalKeyWindow = [UIApplication sharedApplication].windows.firstObject;
#endif
}
}
//If original key window is not nil and the cached keywindow is also not original keywindow then changing keywindow.
if (originalKeyWindow)
{
cachedKeyWindow = originalKeyWindow;
}
return cachedKeyWindow;
}
- (CGRect)dd_statusBarFrame{
CGRect statusBarFrame = CGRectZero;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
if (@available(iOS 13.0, *)) {
UIWindow *window = [self dd_keyWindow];
statusBarFrame = window.windowScene.statusBarManager.statusBarFrame;
} else
#endif
{
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
#endif
}
return statusBarFrame;
}
@end

View File

@@ -0,0 +1,22 @@
//
// UIBarButtonItem+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, DDBarButtonItemPlacement) {
DDBarButtonItemPlacementLeft,
DDBarButtonItemPlacementRight,
};
@interface UIBarButtonItem (DDCategory)
/// @param buttons 按钮数组
/// @param itemPadding 两个按钮间的间距
/// @param placement barButtonItems在导航栏的位置
+ (NSArray<UIBarButtonItem *> *)dd_barButtonItemsWithButtons:(NSArray<UIButton *> *)buttons itemPadding:(CGFloat)itemPadding placement:(DDBarButtonItemPlacement)placement;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,49 @@
//
// UIBarButtonItem+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import "UIBarButtonItem+DDCategory.h"
@implementation UIBarButtonItem (DDCategory)
+ (NSArray<UIBarButtonItem *> *)dd_barButtonItemsWithButtons:(NSArray<UIButton *> *)buttons itemPadding:(CGFloat)itemPadding placement:(DDBarButtonItemPlacement)placement{
UIView *backgroundView = [UIView new];
// offsetbackgroundView
__block CGFloat offset = 0;
__block CGFloat backgroundViewWidth = 0.0;
__block CGFloat buttonInBackgroundViewX = 0.0;
__block CGFloat maxHeight = 0.0;
[buttons enumerateObjectsUsingBlock:^(UIButton * _Nonnull btn, NSUInteger idx, BOOL * _Nonnull stop) {
if (CGRectEqualToRect(btn.frame, CGRectZero)) {
[btn sizeToFit];
}
CGFloat btnWidth = btn.frame.size.width;
CGFloat btnHeight = btn.frame.size.height;
btn.frame = CGRectMake(buttonInBackgroundViewX, 0, btnWidth, btnHeight);
if (placement == DDBarButtonItemPlacementLeft) {
btn.contentEdgeInsets = UIEdgeInsetsMake(0, -offset, 0, 0);
}else if (placement == DDBarButtonItemPlacementRight){
btn.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -offset);
}
[backgroundView addSubview:btn];
// barButtonItem
backgroundViewWidth = btnWidth + backgroundViewWidth + (idx != (buttons.count - 1) ? itemPadding : 0);
buttonInBackgroundViewX = buttonInBackgroundViewX + btnWidth + offset + (idx != (buttons.count - 1) ? itemPadding : 0);
if (btn.frame.size.height > maxHeight) {
maxHeight = btn.frame.size.height;
}
}];
backgroundView.frame = CGRectMake(0, 0, backgroundViewWidth, maxHeight);
// spacerightBarButtonItem7,8pt
UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *customItem = [[UIBarButtonItem alloc] initWithCustomView:backgroundView];
return @[spaceItem,customItem];
}
@end

View File

@@ -0,0 +1,97 @@
//
// UIButton+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, DDCustomButtonState) {
DDCustomButtonStateNormal,
DDCustomButtonStateSelected,
DDCustomButtonStateHighlight,
};
typedef NS_ENUM(NSInteger, DDCustomButtonStyle) {
/**
* image is left of the button,title is right, image and title is whole center.
*/
ImageLeftPaddingTitleRightWithWholeCenter = 0,
/**
* image is right of the button, title is left , image and title is whole center.
*/
ImageRightPaddingTitleLeftWithWholeCenter,
/**
* image is top of the button,title is bottom, image and title is whole center.
*/
ImageTopPaddingTitleBottomWithWholeCenter,
/**
*image is bottom of the button,title is top, image and title is whole center.
*/
ImageBottomPaddingTitleTopWithWholeCenter,
};
@interface UIButton (DDCategory)
/**
* return a instance of custom button
*/
+ (instancetype)dd_initCustomButton;
- (instancetype)dd_addTarget:(nullable id)target action:(nonnull SEL)action forControlEvents:(UIControlEvents)controlEvents;
@end
typedef NSString * DDCustomButtonAttributedStringKey NS_TYPED_EXTENSIBLE_ENUM;
FOUNDATION_EXPORT const DDCustomButtonAttributedStringKey DDCustomButtonAttributedStringState;
FOUNDATION_EXPORT const DDCustomButtonAttributedStringKey DDCustomButtonAttributedStringAttributedText;
FOUNDATION_EXPORT const DDCustomButtonAttributedStringKey DDCustomButtonAttributedStringImage;
@interface UIButton (AttributedString)
+ (instancetype)dd_initWithAttributedTitles:(NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles;
+ (instancetype)dd_initWithImages:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images;
+ (instancetype)dd_initWithBackgroundColor:(UIColor *)backgroundColor;
/**
* return a instance of custom button
* @param attributedTitles button attributedTitle example: @[@{DDCustomButtonAttributedStringStateName : @(DDCustomButtonStateNormal.rawValue),DDCustomButtonAttributedStringTextName : attributedString}]
* @param images button images
* @param backgroundColor button backgroundColor
*/
+ (instancetype)dd_initWithAttributedTitles:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles images:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images backgroundColor:(nullable UIColor *)backgroundColor;
/**
* return a instance of custom button
* @param buttonType button type
* @param attributedTitles button attributedTitle example: @[@{DDCustomButtonAttributedStringStateName : @(DDCustomButtonStateNormal.rawValue),DDCustomButtonAttributedStringTextName : attributedString}]
* @param images button images
* @param backgroundColor button backgroundColor
*/
+ (instancetype)dd_initWithType:(UIButtonType)buttonType attributedTitles:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles images:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images backgroundColor:(nullable UIColor *)backgroundColor;
/**
* return a instance of custom button
* @param attributedTitles button attributedTitle example: @[@{DDCustomButtonAttributedStringStateName : @(DDCustomButtonStateNormal.rawValue),DDCustomButtonAttributedStringTextName : attributedString}]
* @param images button images
* @param backgroundColor button backgroundColor
*/
- (instancetype)dd_setAttributedTitles:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles images:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images backgroundColor:(nullable UIColor *)backgroundColor;
- (instancetype)dd_setAttributedTitles:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles;
- (instancetype)dd_setImages:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images;
- (instancetype)dd_setBackgroundColor:(nullable UIColor *)backgroundColor;
@end
@interface UIButton (Placement)
/**
* layout image and title position.
* @param style ButtonImageTitleStyle
* @param padding image and title padding
* @warning use this function after button already has frame, image and title is not nil,such as user use masonry to constraint button, you should transfer layoutIfNeeded before to sure button has already bounds, example:sizeToFit().
*/
- (instancetype)dd_customizeWithStyle:(DDCustomButtonStyle)style padding:(CGFloat)padding;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,412 @@
//
// UIButton+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "UIButton+DDCategory.h"
#import <DDCategoryKit_Private/NSObject+DDCategory.h>
DDCustomButtonAttributedStringKey const DDCustomButtonAttributedStringState = @"DDCustomButtonAttributedStringStateName";
DDCustomButtonAttributedStringKey const DDCustomButtonAttributedStringAttributedText = @"DDCustomButtonAttributedStringTextName";
DDCustomButtonAttributedStringKey const DDCustomButtonAttributedStringImage = @"DDCustomButtonAttributedStringImage";
@implementation UIButton (DDCategory)
+ (void)load{
static dispatch_once_t onceToken;
__weak typeof(self) weakSelf = self;
dispatch_once(&onceToken, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf dd_originSelector:@selector(pointInside:withEvent:) swizzleSelector:@selector(dd_pointInside:withEvent:)];
[strongSelf dd_originSelector:@selector(layoutSubviews) swizzleSelector:@selector(dd_layoutSubviews)];
});
}
+ (instancetype)dd_initCustomButton{
return [UIButton buttonWithType:UIButtonTypeCustom];
}
- (instancetype)dd_addTarget:(nullable id)target action:(nonnull SEL)action forControlEvents:(UIControlEvents)controlEvents {
[self addTarget:target action:action forControlEvents:controlEvents];
return self;
}
- (void)dd_layoutSubviews{
[self dd_layoutSubviews];
}
/**
* if another button is added to the view beside the button added before, it is too close less the widthDelta, the valid touch area is belong to the button added later.
*/
- (BOOL)dd_pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
// if (UIEdgeInsetsEqualToEdgeInsets(self.hitTestEdgeInsets, UIEdgeInsetsZero)) {
// return [self dd_pointInside:point withEvent:event];
// }
CGRect bounds = self.bounds;
CGFloat widthDelta = MAX(44.0 - bounds.size.width, 0);
CGFloat heightDelta = MAX(44.0 - bounds.size.height, 0);
bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
return CGRectContainsPoint(bounds, point);
}
@end
@implementation UIButton (AttributedString)
+ (instancetype)dd_initWithAttributedTitles:(NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles
{
return [self dd_initWithAttributedTitles:attributedTitles images:nil backgroundColor:nil];
}
+ (instancetype)dd_initWithImages:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images
{
return [self dd_initWithAttributedTitles:nil images:images backgroundColor:nil];
}
+ (instancetype)dd_initWithBackgroundColor:(UIColor *)backgroundColor{
return [self dd_initWithAttributedTitles:nil images:nil backgroundColor:backgroundColor];
}
+ (instancetype)dd_initWithAttributedTitles:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles images:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images backgroundColor:(nullable UIColor *)backgroundColor {
return [UIButton dd_initWithType:UIButtonTypeCustom attributedTitles:attributedTitles images:images backgroundColor:backgroundColor];
}
+ (instancetype)dd_initWithType:(UIButtonType)buttonType attributedTitles:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles images:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images backgroundColor:(nullable UIColor *)backgroundColor {
return [[UIButton buttonWithType:buttonType] dd_setAttributedTitles:attributedTitles images:images backgroundColor:backgroundColor];
}
- (instancetype)dd_setAttributedTitles:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles images:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images backgroundColor:(nullable UIColor *)backgroundColor {
// if (@available(iOS 15.0, *)) {
// UIButtonConfiguration *configuration = self.configuration;
// if (configuration == nil){
// configuration = [UIButtonConfiguration plainButtonConfiguration];
// self.configuration = configuration;
// }
//
// configuration.baseBackgroundColor = backgroundColor;
// self.configuration = configuration;
// self.backgroundColor = backgroundColor;
//
// __weak typeof(self) weakSelf = self;
// self.configurationUpdateHandler = ^(UIButton *button){
// __strong typeof(weakSelf) strongSelf = weakSelf;
//
// NSAttributedString *textAttributes = nil;
// UIImage *image = nil;
// for (NSDictionary *dict in attributedTitles) {
// if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateNormal)]) {
// textAttributes = dict[DDCustomButtonAttributedStringAttributedText];
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateSelected)]){
// textAttributes = dict[DDCustomButtonAttributedStringAttributedText];
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateHighlight)]){
// textAttributes = dict[DDCustomButtonAttributedStringAttributedText];
// }
// }
//
// for (NSDictionary *dict in images){
// if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateNormal)]) {
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// image = dict[DDCustomButtonAttributedStringImage];
// }
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateSelected)]){
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// image = dict[DDCustomButtonAttributedStringImage];
// }
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateHighlight)]){
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// image = dict[DDCustomButtonAttributedStringImage];
// }
// }
// }
//
// configuration.attributedTitle = textAttributes;
// configuration.image = image;
// strongSelf.configuration = configuration;
// };
//
// }else{
// self.adjustsImageWhenHighlighted = false;
// [self setBackgroundColor:backgroundColor];
// for (NSDictionary *dict in attributedTitles) {
// if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateNormal)]) {
// [self setAttributedTitle:dict[DDCustomButtonAttributedStringAttributedText] forState:UIControlStateNormal];
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateSelected)]){
// [self setAttributedTitle:dict[DDCustomButtonAttributedStringAttributedText] forState:UIControlStateSelected];
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateHighlight)]){
// [self setAttributedTitle:dict[DDCustomButtonAttributedStringAttributedText] forState:UIControlStateHighlighted];
// }
//
// }
// for (NSDictionary *dict in images){
// if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateNormal)]) {
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// [self setImage:dict[DDCustomButtonAttributedStringImage] forState:UIControlStateNormal];
// }
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateSelected)]){
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// [self setImage:dict[DDCustomButtonAttributedStringImage] forState:UIControlStateSelected];
// }
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateHighlight)]){
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// [self setImage:dict[DDCustomButtonAttributedStringImage] forState:UIControlStateHighlighted];
// }
// }
// }
// }
return [[[self dd_setAttributedTitles:attributedTitles] dd_setImages:images] dd_setBackgroundColor:backgroundColor];
}
- (instancetype)dd_setAttributedTitles:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)attributedTitles{
// if (@available(iOS 15.0, *)) {
// UIButtonConfiguration *configuration = self.configuration;
// if (configuration == nil){
// configuration = [UIButtonConfiguration plainButtonConfiguration];
// self.configuration = configuration;
// }
//
// __weak typeof(self) weakSelf = self;
// self.configurationUpdateHandler = ^(UIButton *button){
// __strong typeof(weakSelf) strongSelf = weakSelf;
//
// NSAttributedString *textAttributes = nil;
// for (NSDictionary *dict in attributedTitles) {
// if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateNormal)]) {
// textAttributes = dict[DDCustomButtonAttributedStringAttributedText];
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateSelected)]){
// textAttributes = dict[DDCustomButtonAttributedStringAttributedText];
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateHighlight)]){
// textAttributes = dict[DDCustomButtonAttributedStringAttributedText];
// }
// }
// configuration.attributedTitle = textAttributes;
// strongSelf.configuration = configuration;
// };
//
// }else{
self.adjustsImageWhenHighlighted = false;
for (NSDictionary *dict in attributedTitles) {
if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateNormal)]) {
[self setAttributedTitle:dict[DDCustomButtonAttributedStringAttributedText] forState:UIControlStateNormal];
}else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateSelected)]){
[self setAttributedTitle:dict[DDCustomButtonAttributedStringAttributedText] forState:UIControlStateSelected];
}else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateHighlight)]){
[self setAttributedTitle:dict[DDCustomButtonAttributedStringAttributedText] forState:UIControlStateHighlighted];
}
}
// }
return self;
}
- (instancetype)dd_setImages:(nullable NSArray<NSDictionary<DDCustomButtonAttributedStringKey,id> *> *)images{
// if (@available(iOS 15.0, *)) {
// UIButtonConfiguration *configuration = self.configuration;
// if (configuration == nil){
// configuration = [UIButtonConfiguration plainButtonConfiguration];
// self.configuration = configuration;
// }
//
// __weak typeof(self) weakSelf = self;
// self.configurationUpdateHandler = ^(UIButton *button){
// __strong typeof(weakSelf) strongSelf = weakSelf;
//
// UIImage *image = nil;
// for (NSDictionary *dict in images){
// if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateNormal)]) {
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// image = dict[DDCustomButtonAttributedStringImage];
// }
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateSelected)]){
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// image = dict[DDCustomButtonAttributedStringImage];
// }
// }else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateHighlight)]){
// if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
// image = dict[DDCustomButtonAttributedStringImage];
// }
// }
// }
// configuration.image = image;
// strongSelf.configuration = configuration;
// };
//
// }else{
self.adjustsImageWhenHighlighted = false;
for (NSDictionary *dict in images){
if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateNormal)]) {
if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
[self setImage:dict[DDCustomButtonAttributedStringImage] forState:UIControlStateNormal];
}
}else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateSelected)]){
if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
[self setImage:dict[DDCustomButtonAttributedStringImage] forState:UIControlStateSelected];
}
}else if ([dict[DDCustomButtonAttributedStringState] isEqualToNumber:@(DDCustomButtonStateHighlight)]){
if(![dict[DDCustomButtonAttributedStringImage] isKindOfClass:[NSNull class]]){
[self setImage:dict[DDCustomButtonAttributedStringImage] forState:UIControlStateHighlighted];
}
}
}
// }
return self;
}
- (instancetype)dd_setBackgroundColor:(nullable UIColor *)backgroundColor{
// if (@available(iOS 15.0, *)) {
// UIButtonConfiguration *configuration = self.configuration;
// if (configuration == nil){
// configuration = [UIButtonConfiguration plainButtonConfiguration];
// self.configuration = configuration;
// }
// configuration.baseBackgroundColor = backgroundColor;
// self.configuration = configuration;
// self.backgroundColor = backgroundColor;
//
// }else{
self.adjustsImageWhenHighlighted = false;
[self setBackgroundColor:backgroundColor];
// }
return self;
}
@end
@implementation UIButton (Placement)
- (instancetype)dd_customizeWithStyle:(DDCustomButtonStyle)style padding:(CGFloat)padding
{
if (self.imageView.image == nil || self.titleLabel.text == nil) return self;
// if (@available(iOS 15.0,*)) {
// switch (style) {
// case ImageRightPaddingTitleLeftWithWholeCenter:
// {
// UIButtonConfiguration *configuration = self.configuration;
// configuration.imagePlacement = NSDirectionalRectEdgeTrailing;
// configuration.imagePadding = padding;
// self.configuration = configuration;
// break;
// }
// case ImageTopPaddingTitleBottomWithWholeCenter:
// {
// UIButtonConfiguration *configuration = self.configuration;
// if (configuration == nil) {
// configuration = [UIButtonConfiguration plainButtonConfiguration];
// self.configuration = configuration;
// }
// configuration.imagePlacement = NSDirectionalRectEdgeTop;
// configuration.imagePadding = padding;
// self.configuration = configuration;
// break;
// }
// case ImageBottomPaddingTitleTopWithWholeCenter:
// {
// UIButtonConfiguration *configuration = self.configuration;
// configuration.imagePlacement = NSDirectionalRectEdgeBottom;
// configuration.imagePadding = padding;
// self.configuration = configuration;
// break;
// }
// case ImageLeftPaddingTitleRightWithWholeCenter:
// {
// UIButtonConfiguration *configuration = self.configuration;
// configuration.imagePlacement = NSDirectionalRectEdgeLeading;
// configuration.imagePadding = padding;
// self.configuration = configuration;
// break;
// }
// default:
// break;
// }
// }else{
// size
CGSize imageSizeOrigin = [self.imageView sizeThatFits:CGSizeZero];
CGSize titleSizeOrigin = [self.titleLabel sizeThatFits:CGSizeZero];
CGSize fitSizeOrigin = [self sizeThatFits:CGSizeZero];
// size
CGSize imageSize = CGSizeMake(ceilf(imageSizeOrigin.width), ceilf(imageSizeOrigin.height));
CGSize titleSize = CGSizeMake(ceilf(titleSizeOrigin.width), ceilf(titleSizeOrigin.height));
CGSize fitSize = CGSizeMake(ceilf(fitSizeOrigin.width), ceilf(fitSizeOrigin.height));
// frame
CGFloat finalFitWidth = 0.0;
switch (style) {
case ImageLeftPaddingTitleRightWithWholeCenter:
{
finalFitWidth = fitSize.width + padding;
self.titleEdgeInsets = UIEdgeInsetsMake(0,
padding/2,
0,
-padding/2);
self.imageEdgeInsets = UIEdgeInsetsMake(0,
-padding/2,
0,
padding/2);
}
break;
case ImageRightPaddingTitleLeftWithWholeCenter:
{
finalFitWidth = fitSize.width + padding;
self.titleEdgeInsets = UIEdgeInsetsMake(0,
-(imageSize.width + padding/2),
0,
(imageSize.width + padding/2));
self.imageEdgeInsets = UIEdgeInsetsMake(0,
(titleSize.width + padding/2),
0,
-(titleSize.width + padding/2));
}
break;
case ImageTopPaddingTitleBottomWithWholeCenter:
{
finalFitWidth = imageSize.width > titleSize.width ? imageSize.width : titleSize.width;
// (selfSize.width - finalWidth) marginmargin0
self.titleEdgeInsets = UIEdgeInsetsMake(titleSize.height/2.0+padding/2.0+(imageSize.height-titleSize.height)/2.0,
(titleSize.width + imageSize.width)/2.0 - (titleSize.width/2.0 + imageSize.width) - (fitSize.width - finalFitWidth),
-(titleSize.height/2.0+padding/2.0+(imageSize.height-titleSize.height)/2.0),
(titleSize.width/2.0 + imageSize.width) - (titleSize.width + imageSize.width)/2.0 - (fitSize.width - finalFitWidth) );
self.imageEdgeInsets = UIEdgeInsetsMake(-(imageSize.height/2.0+padding/2.0-(imageSize.height-titleSize.height)/2.0),
(imageSize.width + titleSize.width)/2.0 - imageSize.width/2.0 - (titleSize.height/2.0 + padding) - (fitSize.width - finalFitWidth),
imageSize.height/2.0+padding/2.0-(imageSize.height-titleSize.height)/2.0,
imageSize.width/2.0 - (imageSize.width + titleSize.width)/2.0 - (titleSize.height/2.0 + padding) - (fitSize.width - finalFitWidth));
}
break;
case ImageBottomPaddingTitleTopWithWholeCenter:
{
finalFitWidth = imageSize.width > titleSize.width ? imageSize.width : titleSize.width;
// (selfSize.width - finalWidth) marginmargin0
self.titleEdgeInsets = UIEdgeInsetsMake(-(titleSize.height/2.0 + padding/2.0),
(imageSize.width + titleSize.width)/2.0 - (titleSize.width/2.0 + imageSize.width) - (fitSize.width - finalFitWidth),
(titleSize.height/2.0 + padding/2.0),
(titleSize.width/2.0 + imageSize.width) - (imageSize.width + titleSize.width)/2.0 - (fitSize.width - finalFitWidth));
self.imageEdgeInsets = UIEdgeInsetsMake((imageSize.height/2.0 - padding/2.0),
(imageSize.width + titleSize.width)/2.0 - imageSize.width/2.0 - (fitSize.width - finalFitWidth),
-(imageSize.height/2.0 - padding/2.0),
imageSize.width/2.0 - (imageSize.width + titleSize.width)/2.0 - (fitSize.width - finalFitWidth));
}
break;
default:
break;
}
// }
return self;
}
@end

View File

@@ -0,0 +1,15 @@
//
// UICollectionView+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/10.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UICollectionView (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,11 @@
//
// UICollectionView+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/10.
#import "UICollectionView+DDCategory.h"
@implementation UICollectionView (DDCategory)
@end

View File

@@ -0,0 +1,15 @@
//
// UICollectionViewCell+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/10.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UICollectionViewCell (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,11 @@
//
// UICollectionViewCell+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/10.
#import "UICollectionViewCell+DDCategory.h"
@implementation UICollectionViewCell (DDCategory)
@end

View File

@@ -0,0 +1,14 @@
//
// UIFont+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIFont (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,10 @@
//
// UIFont+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import "UIFont+DDCategory.h"
@implementation UIFont (DDCategory)
@end

View File

@@ -0,0 +1,87 @@
//
// UIImage+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef NSString *DDWaterMarkInfoName NS_TYPED_EXTENSIBLE_ENUM;
typedef NSString *DDWaterMarkLayoutName NS_TYPED_EXTENSIBLE_ENUM;
FOUNDATION_EXPORT DDWaterMarkInfoName const DDWaterMarkInfoText;
FOUNDATION_EXPORT DDWaterMarkInfoName const DDWaterMarkInfoAttributes;
FOUNDATION_EXPORT DDWaterMarkInfoName const DDWaterMarkLayoutTop;
FOUNDATION_EXPORT DDWaterMarkInfoName const DDWaterMarkLayoutLeft;
FOUNDATION_EXPORT DDWaterMarkInfoName const DDWaterMarkLayoutBottom;
FOUNDATION_EXPORT DDWaterMarkInfoName const DDWaterMarkLayoutRight;
@interface UIImage (DDCategory)
/**
* return a thumbnailImage that cutted from the remote video.
*/
+ (UIImage *)dd_thumbnailImageForVideo:(NSURL *)videoURL;
/// @brief return a compressed image
/// @param maxLength bytes = 1024 * (kb)
- (UIImage *)dd_compressWithQulitySize:(NSInteger)maxLength;
- (NSData *)dd_compressedToDataWithQulitySize:(NSInteger)maxLength;
/// @brief return a marked image
/// @param infoArr this array contain a list of dictionary,the dictionary is consists of DDWaterMarkInfoName
- (UIImage *)dd_addWaterMarkWithInfoArray:(NSArray<NSDictionary<DDWaterMarkInfoName,id> *> *)infoArr;
@end
@interface UIImage (LoadWithTrait)
/// @briefthis function will return different image as the system interface mode changes.
/// @param lightImage return this image when appearance(UIUserInterfaceStyle) or system interface is Light.
/// @param darkImage return this image when appearance(UIUserInterfaceStyle) or system interface is Dark.
/// @warning Note the 'Appearance' property in info.plist.
+ (nullable UIImage *)dd_imageWithUserInerfaceStyleLightImage:(UIImage *)lightImage darkImage:(UIImage *)darkImage API_AVAILABLE(tvos(10.0)) API_AVAILABLE(ios(12.0)) API_UNAVAILABLE(watchos);
@end
@interface UIImage (LoadWithBundle)
/// @brief convenient function based on 'dd_imageNamed:(nonnull NSString *)name bundlePath:(nonnull NSString *)bundlePath'.
///
/// @param name resource name like this 'fileName/imageName'.
/// @param bundleName the name of the bundle where the resource located.
/// @param aClass The purpose of specifying the current type is to get the bundle location of the current library, it's related to the method '[NSBundle bundleForClass:aClass].resourcePath'.
+ (nullable UIImage *)dd_imageNamed:(nonnull NSString *)name bundleName:(nonnull NSString *)bundleName aClass:(nonnull Class)aClass;
/// @brief convenient function based on 'dd_imageForResource:(nullable NSString *)resource ofType:(nullable NSString *)type bundlePath:(nonnull NSString *)bundlePath'.
///
/// @param resource resource name like this 'fileName/imageName'.
/// @param type resource type.
/// @param bundleName the name of the bundle where the resource located.
/// @param aClass The purpose of specifying the current type is to get the bundle location of the current library, it's related to the method '[NSBundle bundleForClass:aClass].resourcePath'.
+ (nullable UIImage *)dd_imageForResource:(nullable NSString *)resource ofType:(nullable NSString *)type bundleName:(nonnull NSString *)bundleName aClass:(nonnull Class)aClass;
/// @brief return a image from a bundle.
/// @param name the image name.
/// @param bundlePath the bundle path like this 'Frameworks/DDCategoryKit_Private.framework/resources.bundle'.
/// @warning where the bundle is is important.
+ (nullable UIImage *)dd_imageNamed:(nonnull NSString *)name bundlePath:(nonnull NSString *)bundlePath;
/// @brief return a image from a bundle.
/// @param resource the format of resource is like this 'fileName/imageName'.
/// @param type image type.
/// @param bundlePath the bundle path like this 'Frameworks/DDCategoryKit_Private.framework/resources.bundle'.
+ (nullable UIImage *)dd_imageForResource:(nullable NSString *)resource ofType:(nullable NSString *)type bundlePath:(nonnull NSString *)bundlePath;
+ (nullable NSData *)dd_imageGifNamed:(nonnull NSString *)name bundleName:(nonnull NSString *)bundleName aClass:(nonnull Class)aClass;
+ (nullable NSData *)dd_imageForGifResource:(nullable NSString *)resource ofType:(nullable NSString *)type bundleName:(nonnull NSString *)bundleName aClass:(nonnull Class)aClass;
/// @brief return QRCode.
+ (instancetype)dd_generateQrcodeImageWithStr:(NSString *)QcodeStr size:(float)size;
@end
@interface UIImage (NullSafe)
- (instancetype)dd_nullSafe;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,345 @@
//
// UIImage+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "UIImage+DDCategory.h"
#import <AVFoundation/AVAsset.h>
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVFoundation.h>
DDWaterMarkInfoName const DDWaterMarkInfoText = @"DDWaterMarkInfoText";
DDWaterMarkInfoName const DDWaterMarkInfoAttributes = @"DDWaterMarkInfoAttributes";
DDWaterMarkInfoName const DDWaterMarkLayoutTop = @"DDWaterMarkInfoTop";
DDWaterMarkInfoName const DDWaterMarkLayoutLeft = @"DDWaterMarkLayoutLeft";
DDWaterMarkInfoName const DDWaterMarkLayoutBottom = @"DDWaterMarkLayoutBottom";
DDWaterMarkInfoName const DDWaterMarkLayoutRight = @"DDWaterMarkLayoutRight";
@implementation UIImage (DDCategory)
+ (UIImage *)dd_thumbnailImageForVideo:(NSURL *)videoURL{
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
NSParameterAssert(asset);
AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:asset];
assetImageGenerator.appliesPreferredTrackTransform = YES;
assetImageGenerator.apertureMode =AVAssetImageGeneratorApertureModeEncodedPixels;
CGImageRef thumbnailImageRef = NULL;
// CFTimeInterval thumbnailImageTime = 1;
NSError *thumbnailImageGenerationError = nil;
thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(0, 1) actualTime:NULL error:&thumbnailImageGenerationError];
NSAssert(thumbnailImageRef, @"thumbnailImageGenerationError");
UIImage *thumbnailImage = thumbnailImageRef ? [[UIImage alloc] initWithCGImage:thumbnailImageRef] : nil;
return thumbnailImage;
}
- (UIImage *)dd_compressWithQulitySize:(NSInteger)maxLength {
// Compress by quality
CGFloat compression = 1;
NSData *data = UIImageJPEGRepresentation(self, compression);
if (data.length < maxLength) return self;
CGFloat max = 1;
CGFloat min = 0;
for (int i = 0; i < 6; ++i) {
compression = (max + min) / 2;
data = UIImageJPEGRepresentation(self, compression);
if (data.length < maxLength * 0.9) {
min = compression;
} else if (data.length > maxLength) {
max = compression;
} else {
break;
}
}
UIImage *resultImage = [UIImage imageWithData:data];
if (data.length < maxLength) return resultImage;
// Compress by size
NSUInteger lastDataLength = 0;
while (data.length > maxLength && data.length != lastDataLength) {
lastDataLength = data.length;
CGFloat ratio = (CGFloat)maxLength / data.length;
CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
(NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank
UIGraphicsBeginImageContext(size);
[resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
data = UIImageJPEGRepresentation(resultImage, compression);
}
return resultImage;
}
- (NSData *)dd_compressedToDataWithQulitySize:(NSInteger)maxLength {
// Compress by quality
CGFloat compression = 1;
NSData *data = UIImageJPEGRepresentation(self, compression);
if (data.length < maxLength) return data;
CGFloat max = 1;
CGFloat min = 0;
for (int i = 0; i < 6; ++i) {
compression = (max + min) / 2;
data = UIImageJPEGRepresentation(self, compression);
if (data.length < maxLength * 0.9) {
min = compression;
} else if (data.length > maxLength) {
max = compression;
} else {
break;
}
}
UIImage *resultImage = [UIImage imageWithData:data];
if (data.length < maxLength) return data;
// Compress by size
NSUInteger lastDataLength = 0;
while (data.length > maxLength && data.length != lastDataLength) {
lastDataLength = data.length;
CGFloat ratio = (CGFloat)maxLength / data.length;
CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
(NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank
UIGraphicsBeginImageContext(size);
[resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
data = UIImageJPEGRepresentation(resultImage, compression);
}
return data;
}
- (UIImage *)dd_addWaterMarkWithInfoArray:(NSArray<NSDictionary<DDWaterMarkInfoName,id> *> *)infoArr{
UIGraphicsBeginImageContextWithOptions(self.size, NO, [UIScreen mainScreen].scale);
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
[infoArr enumerateObjectsUsingBlock:^(NSDictionary<DDWaterMarkInfoName,id> * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSString *text = obj[DDWaterMarkInfoText];
NSNumber *_Nullable top = obj[DDWaterMarkLayoutTop];
NSNumber *_Nullable left = obj[DDWaterMarkLayoutLeft];
NSNumber *_Nullable bottom = obj[DDWaterMarkLayoutBottom];
NSNumber *_Nullable right = obj[DDWaterMarkLayoutRight];
NSDictionary<NSAttributedStringKey, id> *attrs = obj[DDWaterMarkInfoAttributes];
CGFloat textMaxWidth = self.size.width;
CGFloat textMaxHeight = self.size.height;
if (left != nil && right != nil) {
textMaxWidth = self.size.width - left.floatValue - right.floatValue;
}else if (left != nil && right == nil){
textMaxWidth = self.size.width - left.floatValue;
}else if (left == nil && right != nil){
textMaxWidth = self.size.width - right.floatValue;
}else{
// default
}
if (top != nil && bottom != nil) {
textMaxHeight = self.size.height - top.floatValue - bottom.floatValue;
}else if (top != nil && bottom == nil){
textMaxHeight = self.size.height - top.floatValue;
}else if (top == nil && bottom != nil){
textMaxHeight = self.size.height - bottom.floatValue;
}else{
// default
}
CGFloat width = [text boundingRectWithSize:CGSizeMake(textMaxWidth, textMaxHeight) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width;
CGFloat height = [text boundingRectWithSize:CGSizeMake(textMaxWidth, textMaxHeight) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.height;
CGFloat textX = 0.0;
CGFloat textY = 0.0;
if (left == nil && right != nil){
textX = self.size.width - right.floatValue - width;
}else{
textX = left.floatValue;
}
if (top == nil && bottom != nil) {
textY = self.size.height - bottom.floatValue - height;
}else{
textY = top.floatValue;
}
[text drawInRect:CGRectMake(textX, textY, width, height) withAttributes:attrs];
}];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
@end
@implementation UIImage (LoadWithTrait)
+ (nullable UIImage *)dd_imageWithUserInerfaceStyleLightImage:(UIImage *)lightImage darkImage:(UIImage *)darkImage{
UIImageAsset *imageAsset = [UIImageAsset new];
if (@available(iOS 12.0, *)) {
[imageAsset registerImage:lightImage withTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]];
[imageAsset registerImage:darkImage withTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark]];
// No mater what user interface style filled here,it will return the user interface style of the current system.
return [imageAsset imageWithTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]];
}
if (lightImage != nil) return lightImage;
if (darkImage != nil) return darkImage;
return nil;
}
@end
@implementation UIImage (LoadWithBundle)
+ (nullable UIImage *)dd_imageNamed:(nonnull NSString *)name bundleName:(nonnull NSString *)bundleName aClass:(nonnull Class)aClass{
NSString *bundlePath = [[NSBundle bundleForClass:aClass].resourcePath stringByAppendingPathComponent:bundleName];
UIImage *image = [UIImage dd_imageNamed:name bundlePath:bundlePath];
return image;
}
+ (nullable UIImage *)dd_imageForResource:(nullable NSString *)resource ofType:(nullable NSString *)type bundleName:(nonnull NSString *)bundleName aClass:(nonnull Class)aClass{
NSString *bundlePath = [[NSBundle bundleForClass:aClass].resourcePath stringByAppendingPathComponent:bundleName];
UIImage *image = [UIImage dd_imageForResource:resource ofType:type bundlePath:bundlePath];
return image;
}
+ (nullable UIImage *)dd_imageNamed:(nonnull NSString *)name bundlePath:(nonnull NSString *)bundlePath{
NSString *bundleType = @".bundle";
if (![bundlePath hasSuffix:bundleType]) {
bundlePath = [bundlePath stringByAppendingString:bundleType];
}
NSBundle *sourceBundle = [NSBundle bundleWithPath:bundlePath];
if (sourceBundle == nil) {
return nil;
}
UIImage *image = [UIImage imageNamed:name inBundle:sourceBundle compatibleWithTraitCollection:nil];
return image;
}
+ (nullable UIImage *)dd_imageForResource:(nullable NSString *)resource ofType:(nullable NSString *)type bundlePath:(nonnull NSString *)bundlePath{
NSString *bundleType = @".bundle";
if (![bundlePath hasSuffix:bundleType]) {
bundlePath = [bundlePath stringByAppendingString:bundleType];
}
NSBundle *sourceBundle = [NSBundle bundleWithPath:bundlePath];
if (sourceBundle == nil) {
return nil;
}
NSString *imagePath = [sourceBundle pathForResource:resource ofType:type];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
return image;
}
+ (nullable NSData *)dd_imageGifNamed:(nonnull NSString *)name bundleName:(nonnull NSString *)bundleName aClass:(nonnull Class)aClass{
NSString *bundlePath = [[NSBundle bundleForClass:aClass].resourcePath stringByAppendingPathComponent:bundleName];
NSData *imageData = [UIImage dd_imageGifNamed:name bundlePath:bundlePath];
return imageData;
}
+ (nullable NSData *)dd_imageForGifResource:(nullable NSString *)resource ofType:(nullable NSString *)type bundleName:(nonnull NSString *)bundleName aClass:(nonnull Class)aClass{
NSString *bundlePath = [[NSBundle bundleForClass:aClass].resourcePath stringByAppendingPathComponent:bundleName];
NSData *imageData = [UIImage dd_imageForGifResource:resource ofType:type bundlePath:bundlePath];
return imageData;
}
+ (nullable NSData *)dd_imageGifNamed:(nonnull NSString *)name bundlePath:(nonnull NSString *)bundlePath{
NSString *bundleType = @".bundle";
if (![bundlePath hasSuffix:bundleType]) {
bundlePath = [bundlePath stringByAppendingString:bundleType];
}
NSBundle *sourceBundle = [NSBundle bundleWithPath:bundlePath];
if (sourceBundle == nil) {
return nil;
}
NSString *extension = @".gif";
if (![name hasSuffix:extension]) {
name = [name stringByAppendingString:extension];
}
NSURL *url = [sourceBundle URLForResource:name withExtension:nil];
if (url == nil) {
return nil;
}
NSData *imageData = [NSData dataWithContentsOfURL:url];
return imageData;
}
+ (nullable NSData *)dd_imageForGifResource:(nullable NSString *)resource ofType:(nullable NSString *)type bundlePath:(nonnull NSString *)bundlePath{
NSString *bundleType = @".bundle";
if (![bundlePath hasSuffix:bundleType]) {
bundlePath = [bundlePath stringByAppendingString:bundleType];
}
NSBundle *sourceBundle = [NSBundle bundleWithPath:bundlePath];
if (sourceBundle == nil) {
return nil;
}
NSURL *url = [sourceBundle URLForResource:resource withExtension:@".gif"];
NSData *imageData = [NSData dataWithContentsOfURL:url];
return imageData;
}
+ (instancetype)dd_generateQrcodeImageWithStr:(NSString *)QcodeStr size:(float)size {
//coreImage
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//
[filter setDefaults];
//
NSData *data = [QcodeStr dataUsingEncoding:NSUTF8StringEncoding];
[filter setValue:data forKeyPath:@"inputMessage"];
//
return [self createHDUIImageFormCIImage:[filter outputImage] withSize:size];
}
//
+ (UIImage *)createHDUIImageFormCIImage:(CIImage *)image withSize:(CGFloat)size {
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
// 1.bitmap;
size_t width = CGRectGetWidth(extent) * scale;
size_t height = CGRectGetHeight(extent) * scale;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
CGContextRef bitmapRef =
CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
CGContextScaleCTM(bitmapRef, scale, scale);
CGContextDrawImage(bitmapRef, extent, bitmapImage);
// 2.bitmap
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
CGColorSpaceRelease(cs);
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
UIImage *newImage = [UIImage imageWithCGImage:scaledImage];
CGImageRelease(scaledImage);
return newImage;
}
@end
@implementation UIImage (NullSafe)
- (instancetype)dd_nullSafe{
return (self == nil) ? [[UIImage alloc] init] : self;
}
@end

View File

@@ -0,0 +1,15 @@
//
// UIImageView+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/15.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImageView (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,11 @@
//
// UIImageView+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/15.
#import "UIImageView+DDCategory.h"
@implementation UIImageView (DDCategory)
@end

View File

@@ -0,0 +1,32 @@
//
// UILabel+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UILabel (DDCategory)
/**
*@param text content string
*@param font text font
*@param textColor text color
*/
+ (instancetype)dd_initWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor;
/// return a instance of label
/// @param text content string
/// @param font text font
/// @param textColor text color
/// @param backgroundColor backgroundColor of label
+ (instancetype)dd_initWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor backgroundColor:(UIColor *)backgroundColor;
/**
*@param attributedText attributed string
*/
+ (instancetype)dd_initWithAttributedText:(NSAttributedString *)attributedText;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,31 @@
//
// UILabel+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "UILabel+DDCategory.h"
@implementation UILabel (DDCategory)
+ (instancetype)dd_initWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor{
UILabel *label = [[UILabel alloc] init];
label.text = text;
label.font = font;
label.textColor = textColor;
return label;
}
+ (instancetype)dd_initWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor backgroundColor:(UIColor *)backgroundColor{
UILabel *label = [[UILabel alloc] init];
label.text = text;
label.font = font;
label.textColor = textColor;
label.backgroundColor = backgroundColor;
return label;
}
+ (instancetype)dd_initWithAttributedText:(NSAttributedString *)attributedText{
UILabel *label = [[UILabel alloc] init];
label.attributedText = attributedText;
return label;
}
@end

View File

@@ -0,0 +1,15 @@
//
// UINavigationBar+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/11/2.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UINavigationBar (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,113 @@
//
// UINavigationBar+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/11/2.
#import "UINavigationBar+DDCategory.h"
#import <objc/runtime.h>
#import <DDCategoryKit_Private/NSObject+DDCategory.h>
#import <DDCategoryKit_Private/UIViewController+DDCategory.h>
@implementation UINavigationBar (DDCategory)
+ (void)load{
static dispatch_once_t onceToken;
__weak typeof(self) weakSelf = self;
dispatch_once(&onceToken, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf dd_originSelector:@selector(setBarTintColor:) swizzleSelector:@selector(dd_setBarTintColor:)];
[strongSelf dd_originSelector:@selector(setBackgroundImage:forBarMetrics:) swizzleSelector:@selector(dd_setBackgroundImage:forBarMetrics:)];
[strongSelf dd_originSelector:@selector(setTitleTextAttributes:) swizzleSelector:@selector(dd_setTitleTextAttributes:)];
if (@available(iOS 13.0, *)){
[strongSelf dd_originSelector:@selector(setStandardAppearance:) swizzleSelector:@selector(dd_setStandardAppearance:)];
[strongSelf dd_originSelector:@selector(setCompactAppearance:) swizzleSelector:@selector(dd_setCompactAppearance:)];
[strongSelf dd_originSelector:@selector(setScrollEdgeAppearance:) swizzleSelector:@selector(dd_setScrollEdgeAppearance:)];
if (@available(iOS 15.0, *)){
[strongSelf dd_originSelector:@selector(setCompactScrollEdgeAppearance:) swizzleSelector:@selector(dd_setCompactScrollEdgeAppearance:)];
}
}
});
}
// MARK: <Change NavigationBar Color And BackgroundImage>
- (void)dd_setBarTintColor:(nullable UIColor *)barTintColor{
[self dd_saveBarBackgroundColor:barTintColor];
[self dd_setBarTintColor:barTintColor];
}
- (void)dd_setBackgroundImage:(nullable UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics{
[self dd_saveBarBackgroundImage:backgroundImage];
[self dd_setBackgroundImage:backgroundImage forBarMetrics:barMetrics];
}
- (void)dd_setTitleTextAttributes:(NSDictionary<NSAttributedStringKey,id> *)titleTextAttributes{
[self dd_saveBarTitleTextAttributes:titleTextAttributes];
[self dd_setTitleTextAttributes:titleTextAttributes];
}
- (void)dd_setStandardAppearance:(UINavigationBarAppearance *)standardAppearance UI_APPEARANCE_SELECTOR API_AVAILABLE(ios(13.0), tvos(13.0)){
[self dd_saveBarBackgroundImageOrColorWithAppearance:standardAppearance];
[self dd_setStandardAppearance:standardAppearance];
}
- (void)dd_setCompactAppearance:(UINavigationBarAppearance *)compactAppearance UI_APPEARANCE_SELECTOR API_AVAILABLE(ios(13.0)){
[self dd_saveBarBackgroundImageOrColorWithAppearance:compactAppearance];
[self dd_setCompactAppearance:compactAppearance];
}
- (void)dd_setScrollEdgeAppearance:(UINavigationBarAppearance *)scrollEdgeAppearance UI_APPEARANCE_SELECTOR API_AVAILABLE(ios(13.0)){
[self dd_saveBarBackgroundImageOrColorWithAppearance:scrollEdgeAppearance];
[self dd_setScrollEdgeAppearance:scrollEdgeAppearance];
}
- (void)dd_setCompactScrollEdgeAppearance:(UINavigationBarAppearance *)compactScrollEdgeAppearance UI_APPEARANCE_SELECTOR API_AVAILABLE(ios(15.0)){
[self dd_saveBarBackgroundImageOrColorWithAppearance:compactScrollEdgeAppearance];
[self dd_setCompactScrollEdgeAppearance:compactScrollEdgeAppearance];
}
- (void)dd_saveBarBackgroundImageOrColorWithAppearance:(UINavigationBarAppearance *)navigationBarAppearance API_AVAILABLE(ios(13.0)) {
[self dd_saveBarBackgroundImage:navigationBarAppearance.backgroundImage color:navigationBarAppearance.backgroundColor];
}
- (void)dd_saveBarBackgroundImage:(nullable UIImage *)dd_barBackgroundImage color:(nullable UIColor *)dd_barBackgroundColor{
[self dd_saveBarBackgroundImage:dd_barBackgroundImage];
[self dd_saveBarBackgroundColor:dd_barBackgroundColor];
}
- (void)dd_saveBarBackgroundColor:(nullable UIColor *)dd_barBackgroundColor{
UINavigationController *navigationController = (UINavigationController *)self.delegate;
UIViewController *viewController = [navigationController.viewControllers lastObject];
[viewController dd_saveNavigationBarBackgroundColor:dd_barBackgroundColor];
}
- (void)dd_saveBarBackgroundImage:(nullable UIImage *)dd_barBackgroundImage{
UINavigationController *navigationController = (UINavigationController *)self.delegate;
UIViewController *viewController = [navigationController.viewControllers lastObject];
[viewController dd_saveNavigationBarBackgroundImage:dd_barBackgroundImage];
}
- (void)dd_saveBarTitleTextAttributes:(NSDictionary<NSAttributedStringKey,id> *)dd_titleTextAttributes{
UINavigationController *navigationController = (UINavigationController *)self.delegate;
UIViewController *viewController = [navigationController.viewControllers lastObject];
[viewController dd_saveNavigationBarTitleTextAttributes:dd_titleTextAttributes];
}
@end

View File

@@ -0,0 +1,19 @@
//
// UINavigationController+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/9/22.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UINavigationController (DDCategory)
@property (nonatomic,assign)CGFloat dd_navigationBarHeight;
- (CGFloat)dd_navigationBarHeight;
/// 是否需要在push时去掉tabBar
@property (nonatomic, assign) BOOL dd_hidesBottomBarWhenPushed;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,94 @@
//
// UINavigationController+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/9/22.
#import "UINavigationController+DDCategory.h"
#import <objc/runtime.h>
#import <DDCategoryKit_Private/NSObject+DDCategory.h>
@interface UINavigationController ()
@end
@implementation UINavigationController (DDCategory)
@dynamic dd_navigationBarHeight;
+ (void)load{
static dispatch_once_t onceToken;
__weak typeof(self) weakSelf = self;
dispatch_once(&onceToken, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf dd_originSelector:@selector(viewDidLoad) swizzleSelector:@selector(dd_navViewDidLoad)];
[strongSelf dd_originSelector:@selector(viewWillAppear:) swizzleSelector:@selector(dd_navViewWillAppear:)];
[strongSelf dd_originSelector:@selector(viewDidAppear:) swizzleSelector:@selector(dd_navViewDidAppear:)];
[strongSelf dd_originSelector:@selector(pushViewController:animated:) swizzleSelector:@selector(dd_pushViewController:animated:)];
[strongSelf dd_originSelector:@selector(popToRootViewControllerAnimated:) swizzleSelector:@selector(dd_popToRootViewControllerAnimated:)];
[strongSelf dd_originSelector:@selector(popViewControllerAnimated:) swizzleSelector:@selector(dd_popViewControllerAnimated:)];
});
}
- (void)dd_navViewDidLoad{
[self dd_navViewDidLoad];
}
- (void)dd_navViewWillAppear:(BOOL)animated{
[self dd_navViewWillAppear:animated];
}
- (void)dd_navViewDidAppear:(BOOL)animated{
[self dd_navViewDidAppear:animated];
}
// MARK: <Push>
- (void)dd_pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
[self dd_endEditingAtController:self.topViewController];
if (self.dd_hidesBottomBarWhenPushed == YES) {
[self dd_hidesBottomBarWhenPushedAtChildController:viewController];
}
[self dd_pushViewController:viewController animated:animated];
}
// MARK: <Pop>
- (nullable NSArray<__kindof UIViewController *> *)dd_popToRootViewControllerAnimated:(BOOL)animated{
NSArray *vcs = [self dd_popToRootViewControllerAnimated:animated];
[self dd_endEditingAtController:(UIViewController *)(vcs.lastObject)];
return vcs;
}
- (UIViewController *)dd_popViewControllerAnimated:(BOOL)animated{
UIViewController *vc = [self dd_popViewControllerAnimated:animated];
[self dd_endEditingAtController:vc];
return vc;
}
// MARK: <Custom Property>
- (CGFloat)dd_navigationBarHeight{
return (self.navigationBar.frame.size.height + (self.navigationItem.prompt != nil ? 34 : 0) + (self.navigationBar.prefersLargeTitles == YES ? 34 : 0));
}
- (BOOL)dd_hidesBottomBarWhenPushed{
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setDd_hidesBottomBarWhenPushed:(BOOL)dd_hidesBottomBarWhenPushed{
objc_setAssociatedObject(self, @selector(dd_hidesBottomBarWhenPushed), @(dd_hidesBottomBarWhenPushed), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
// MARK: <Custom Function>
/// pushview
- (void)dd_endEditingAtController:(UIViewController *)controller{
[controller.view endEditing:YES];
}
/// pushtabbar
- (void)dd_hidesBottomBarWhenPushedAtChildController:(UIViewController *)viewController{
if (self.viewControllers.count >= 1){
viewController.hidesBottomBarWhenPushed = YES;
}
}
@end

View File

@@ -0,0 +1,15 @@
//
// UINavigationItem+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/11/10.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UINavigationItem (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,70 @@
//
// UINavigationItem+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/11/10.
#import "UINavigationItem+DDCategory.h"
#import <DDCategoryKit_Private/NSObject+DDCategory.h>
#import <DDCategoryKit_Private/UIViewController+DDCategory.h>
#import <objc/runtime.h>
@implementation UINavigationItem (DDCategory)
+ (void)load{
__weak typeof(self) weakSelf = self;
static dispatch_once_t token;
dispatch_once(&token, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf dd_originSelector:@selector(setLeftBarButtonItem:) swizzleSelector:@selector(dd_setLeftBarButtonItem:)];
[strongSelf dd_originSelector:@selector(setLeftBarButtonItems:) swizzleSelector:@selector(dd_setLeftBarButtonItems:)];
[strongSelf dd_originSelector:@selector(setLeftBarButtonItem:animated:) swizzleSelector:@selector(dd_setLeftBarButtonItem:animated:)];
[strongSelf dd_originSelector:@selector(setLeftBarButtonItems:animated:) swizzleSelector:@selector(dd_setLeftBarButtonItems:animated:)];
[strongSelf dd_originSelector:@selector(setRightBarButtonItem:) swizzleSelector:@selector(dd_setRightBarButtonItem:)];
[strongSelf dd_originSelector:@selector(setRightBarButtonItems:) swizzleSelector:@selector(dd_setRightBarButtonItems:)];
[strongSelf dd_originSelector:@selector(setRightBarButtonItem:animated:) swizzleSelector:@selector(dd_setRightBarButtonItem:animated:)];
[strongSelf dd_originSelector:@selector(setRightBarButtonItems:animated:) swizzleSelector:@selector(dd_setRightBarButtonItems:animated:)];
});
}
- (void)dd_setLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem{
[self dd_setLeftBarButtonItem:leftBarButtonItem];
}
- (void)dd_setLeftBarButtonItems:(NSArray<UIBarButtonItem *> *)leftBarButtonItems{
[self dd_setLeftBarButtonItems:leftBarButtonItems];
}
- (void)dd_setLeftBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated{
[self dd_setLeftBarButtonItem:item animated:animated];
}
- (void)dd_setLeftBarButtonItems:(NSArray<UIBarButtonItem *> *)items animated:(BOOL)animated{
[self dd_setLeftBarButtonItems:items animated:animated];
}
- (void)dd_setRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem{
[self dd_setRightBarButtonItem:rightBarButtonItem];
}
- (void)dd_setRightBarButtonItems:(NSArray<UIBarButtonItem *> *)rightBarButtonItems{
[self dd_setRightBarButtonItems:rightBarButtonItems];
}
- (void)dd_setRightBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated{
[self dd_setRightBarButtonItem:item animated:animated];
}
- (void)dd_setRightBarButtonItems:(NSArray<UIBarButtonItem *> *)items animated:(BOOL)animated{
[self dd_setRightBarButtonItems:items animated:animated];
}
@end

View File

@@ -0,0 +1,20 @@
//
// UIScreen+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIScreen (DDCategory)
@property (nonatomic, assign)CGFloat dd_screenWidth;
@property (nonatomic, assign)CGFloat dd_screenHeight;
- (CGFloat)dd_screenWidth;
- (CGFloat)dd_screenHeight;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,18 @@
//
// UIScreen+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import "UIScreen+DDCategory.h"
@implementation UIScreen (DDCategory)
@dynamic dd_screenWidth;
@dynamic dd_screenHeight;
- (CGFloat)dd_screenWidth {
return self.bounds.size.width;
}
- (CGFloat)dd_screenHeight {
return self.bounds.size.height;
}
@end

View File

@@ -0,0 +1,15 @@
//
// UIScrollView+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/26.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIScrollView (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,11 @@
//
// UIScrollView+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/26.
#import "UIScrollView+DDCategory.h"
@implementation UIScrollView (DDCategory)
@end

View File

@@ -0,0 +1,18 @@
//
// UITabBarController+DDCategory.h
// DDCategoryKit_Private
//
// Created by 中道 on 2023/7/7.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UITabBarController (DDCategory)
@property (nonatomic, assign) CGFloat dd_tabBarHeight;
- (CGFloat)dd_tabBarHeight;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,17 @@
//
// UITabBarController+DDCategory.m
// DDCategoryKit_Private
//
// Created by on 2023/7/7.
//
#import "UITabBarController+DDCategory.h"
@implementation UITabBarController (DDCategory)
@dynamic dd_tabBarHeight;
- (CGFloat)dd_tabBarHeight {
return 49;
}
@end

View File

@@ -0,0 +1,15 @@
//
// UITableView+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/10.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UITableView (DDCategory)
+ (instancetype)dd_initWithDelegate:(nullable id)delegate style:(UITableViewStyle)style;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,16 @@
//
// UITableView+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/10.
#import "UITableView+DDCategory.h"
@implementation UITableView (DDCategory)
+ (instancetype)dd_initWithDelegate:(nullable id)delegate style:(UITableViewStyle)style {
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:style];
tableView.delegate = delegate;
tableView.dataSource = delegate;
return tableView;
}
@end

View File

@@ -0,0 +1,15 @@
//
// UITableViewCell+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/10.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UITableViewCell (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,11 @@
//
// UITableViewCell+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/10.
#import "UITableViewCell+DDCategory.h"
@implementation UITableViewCell (DDCategory)
@end

View File

@@ -0,0 +1,15 @@
//
// UITextField+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/21.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UITextField (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,11 @@
//
// UITextField+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/21.
#import "UITextField+DDCategory.h"
@implementation UITextField (DDCategory)
@end

View File

@@ -0,0 +1,15 @@
//
// UITextView+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/22.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UITextView (DDCategory)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,11 @@
//
// UITextView+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/22.
#import "UITextView+DDCategory.h"
@implementation UITextView (DDCategory)
@end

View File

@@ -0,0 +1,46 @@
//
// UIView+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (DDCategory)
@property (nonatomic, assign)CGFloat width;// view's width of size.
@property (nonatomic, assign)CGFloat height;// view's height of size.
@property (nonatomic, assign)CGFloat x;// view's x of origin.
@property (nonatomic, assign)CGFloat y;// view's y of origin.
@end
@interface UIView (Layer)
/**
* give the view shadow
*@param shadowColor layer shadowColor
*@param shadowOffset layer shadowOffset
*@param shadowRadius layer shadowRadius
*@param shadowOpacity layer shadowOpacity
*@param viewBackgroundColor you must set viewBackgroundColor,otherwise shadow can not be show.
*@param cornerRadius this property maybe cooperate with maskToBounds, such as imageView, you can not set maskToBounds to yes when you set shadow, they are mutually exclusive.
*@warning this function maybe effect fps, you should set rasterize to reduce impact. and you can set shadowPath to reduce consumption of cpu. the viewBackgroundColor must be setted.
*/
+ (UIView *)dd_layerWithShadowColor:(CGColorRef)shadowColor shadowOffset:(CGSize)shadowOffset shadowRadius:(CGFloat)shadowRadius shadowOpacity:(CGFloat)shadowOpacity cornerRadius:(CGFloat)cornerRadius viewBackgroundColor:(nullable UIColor *)viewBackgroundColor;
/**
*the view transfer this function must already has setted background.
*/
- (void)dd_layerWithShadowColor:(CGColorRef)shadowColor shadowOffset:(CGSize)shadowOffset shadowRadius:(CGFloat)shadowRadius shadowOpacity:(CGFloat)shadowOpacity cornerRadius:(CGFloat)cornerRadius viewBackgroundColor:(nullable UIColor *)viewBackgroundColor;
@end
@interface UIView (Controller)
/// 当前view所在的控制器
@property (nonatomic, strong, readonly,nullable)UIViewController *dd_currentViewController;
/// 获取某个view所在的控制器
+ (nullable UIViewController *)dd_viewControllerOfView:(nonnull UIView *)view;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,104 @@
//
// UIView+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/7/29.
#import "UIView+DDCategory.h"
@implementation UIView (DDCategory)
- (CGFloat)width{
return self.frame.size.width;
}
- (CGFloat)height{
return self.frame.size.height;
}
- (CGFloat)x{
return self.frame.origin.x;
}
- (CGFloat)y{
return self.frame.origin.y;
}
- (void)setWidth:(CGFloat)width{
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
- (void)setHeight:(CGFloat)height{
CGRect frame = self.frame;
frame.size.height = height;
self.frame = frame;
}
- (void)setX:(CGFloat)x{
CGRect frame = self.frame;
frame.origin.x = x;
self.frame = frame;
}
- (void)setY:(CGFloat)y{
CGRect frame = self.frame;
frame.origin.y = y;
self.frame = frame;
}
@end
@implementation UIView (Layer)
+ (UIView *)dd_layerWithShadowColor:(CGColorRef)shadowColor shadowOffset:(CGSize)shadowOffset shadowRadius:(CGFloat)shadowRadius shadowOpacity:(CGFloat)shadowOpacity cornerRadius:(CGFloat)cornerRadius viewBackgroundColor:(nullable UIColor *)viewBackgroundColor{
UIView *view = [UIView new];
view.layer.shadowColor = shadowColor;
view.layer.shadowOffset = shadowOffset;
view.layer.shadowRadius = shadowRadius;
view.layer.shadowOpacity = shadowOpacity;
view.layer.cornerRadius = cornerRadius;
view.backgroundColor = viewBackgroundColor;
view.layer.shouldRasterize = YES;
view.layer.rasterizationScale = UIScreen.mainScreen.scale;
return view;
}
- (void)dd_layerWithShadowColor:(CGColorRef)shadowColor shadowOffset:(CGSize)shadowOffset shadowRadius:(CGFloat)shadowRadius shadowOpacity:(CGFloat)shadowOpacity cornerRadius:(CGFloat)cornerRadius viewBackgroundColor:(nullable UIColor *)viewBackgroundColor{
if (!self) return ;
self.layer.shadowColor = shadowColor;
self.layer.shadowOffset = shadowOffset;
self.layer.shadowRadius = shadowRadius;
self.layer.shadowOpacity = shadowOpacity;
self.layer.cornerRadius = cornerRadius;
self.backgroundColor = viewBackgroundColor;
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = UIScreen.mainScreen.scale;
}
@end
@implementation UIView (Controller)
- (nullable UIViewController *)dd_currentViewController {
return [UIView dd_viewControllerOfView:self];
}
+ (nullable UIViewController *)dd_viewControllerOfView:(nonnull UIView *)view {
//
UIResponder *responder = view;
while ((responder = [responder nextResponder])){
if ([responder isKindOfClass: [UIViewController class]]){
return (UIViewController *)responder;
}
}
// nil
return nil;
}
@end

View File

@@ -0,0 +1,28 @@
//
// UIViewController+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/9/23.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIViewController (DDCategory)
/**
* It is recommended to set the background color or image of the navigation bar by these properties.These properties will be set automatically between the end of viewController's viewdidload and the begin of viewController's viewwillappear.
*/
@property (nonatomic, strong, nullable)UIColor *dd_navigationBarBackgroundColor;// navigationBar's backgroundColor.
@property (nonatomic, strong, nullable)UIImage *dd_navigationBarBackgroundImage;// navigationBar's backgroundImage.
@property (nonatomic, strong, nullable)UIColor *dd_navigationBarShadowColor API_AVAILABLE(ios(13.0), tvos(13.0));// navigationBar's shadowColor.
@property (nonatomic, strong, nullable)UIImage *dd_navigationBarShadowImage;// navigationBar's shadowImage.
@property (nonatomic, strong, nullable)NSDictionary<NSAttributedStringKey,id> *dd_navigationBarTitleTextAttributes;// navigationBar's title attributes.
@property (nonatomic, strong, nullable) NSDictionary<NSAttributedStringKey,id> *dd_navigationBarBarButtonItemAttributes;// navigationBar's left or right barButtonItem's attributes,this property should be invoked after barButtonItem has be set.
- (void)dd_saveNavigationBarBackgroundColor:(nullable UIColor *)dd_navigationBarBackgroundColor;
- (void)dd_saveNavigationBarBackgroundImage:(nullable UIImage *)dd_navigationBarBackgroundImage;
- (void)dd_saveNavigationBarShadowColor:(nullable UIColor *)dd_navigationBarShadowColor API_AVAILABLE(ios(13.0), tvos(13.0));
- (void)dd_saveNavigationBarShadowImage:(nullable UIImage *)dd_navigationBarShadowImage;
- (void)dd_saveNavigationBarTitleTextAttributes:(NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarTitleTextAttributes;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,252 @@
//
// UIViewController+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2022/9/23.
#import "UIViewController+DDCategory.h"
#import <objc/runtime.h>
#import <DDCategoryKit_Private/NSObject+DDCategory.h>
@interface UIViewController ()
@end
@implementation UIViewController (DDCategory)
+ (void)load{
static dispatch_once_t onceToken;
__weak typeof(self) weakSelf = self;
dispatch_once(&onceToken, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf dd_originSelector:@selector(viewDidLoad) swizzleSelector:@selector(dd_viewDidLoad)];
[strongSelf dd_originSelector:@selector(viewWillAppear:) swizzleSelector:@selector(dd_viewWillAppear:)];
[strongSelf dd_originSelector:@selector(viewDidAppear:) swizzleSelector:@selector(dd_viewDidAppear:)];
[strongSelf dd_originSelector:@selector(viewWillDisappear:) swizzleSelector:@selector(dd_viewWillDisappear:)];
[strongSelf dd_originSelector:@selector(viewDidDisappear:) swizzleSelector:@selector(dd_viewDidDisappear:)];
});
}
- (void)dd_viewDidLoad{
[self dd_viewDidLoad];
}
- (void)dd_viewWillAppear:(BOOL)animated{
// When the interface is displayed, the color or image of the navigationBar at the current controller needs to be updated.
UIImage *navigationBarBackgroundImage;
UIColor *navigationBarBackgroundColor;
UIImage *navigationBarShadowImage;
UIColor *navigationBarShadowColor;
NSDictionary<NSAttributedStringKey,id> *navigationBarTitleTextAttributes;
if (@available(iOS 13.0, *)){
navigationBarBackgroundImage = self.navigationController.navigationBar.standardAppearance.backgroundImage;
navigationBarBackgroundColor = self.navigationController.navigationBar.standardAppearance.backgroundColor;
navigationBarShadowImage = self.navigationController.navigationBar.standardAppearance.shadowImage;
navigationBarShadowColor = self.navigationController.navigationBar.standardAppearance.shadowColor;
navigationBarTitleTextAttributes = self.navigationController.navigationBar.standardAppearance.titleTextAttributes;
}else{
navigationBarBackgroundImage = [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault];
navigationBarBackgroundColor = self.navigationController.navigationBar.barTintColor;
navigationBarShadowImage = self.navigationController.navigationBar.shadowImage;
navigationBarTitleTextAttributes = self.navigationController.navigationBar.titleTextAttributes;
}
if (@available(iOS 13.0, *)) {
if (!(self.dd_navigationBarBackgroundImage == navigationBarBackgroundImage && CGColorEqualToColor(self.dd_navigationBarBackgroundColor.CGColor, navigationBarBackgroundColor.CGColor) && self.dd_navigationBarShadowImage == navigationBarShadowImage && self.dd_navigationBarShadowColor == navigationBarShadowColor && self.dd_navigationBarTitleTextAttributes == navigationBarTitleTextAttributes)){
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:self.dd_navigationBarShadowColor titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
}
}else{
if (!(self.dd_navigationBarBackgroundImage == navigationBarBackgroundImage && CGColorEqualToColor(self.dd_navigationBarBackgroundColor.CGColor, navigationBarBackgroundColor.CGColor) && self.dd_navigationBarShadowImage == navigationBarShadowImage && self.dd_navigationBarTitleTextAttributes == navigationBarTitleTextAttributes)){
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:nil titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
}
}
[self dd_changeNavigationBarBarButtonItemAttributes:self.dd_navigationBarBarButtonItemAttributes];
[self dd_viewWillAppear:animated];
}
- (void)dd_viewDidAppear:(BOOL)animated{
[self dd_viewDidAppear:animated];
}
- (void)dd_viewWillDisappear:(BOOL)animated{
[self dd_viewWillDisappear:animated];
}
- (void)dd_viewDidDisappear:(BOOL)animated{
[self dd_viewDidDisappear:animated];
}
// MARK: <NavigationBar Color,BackgroundImage,TextAttributes>
- (nullable UIColor *)dd_navigationBarBackgroundColor{
return objc_getAssociatedObject(self, _cmd);
}
- (nullable UIImage *)dd_navigationBarBackgroundImage{
return objc_getAssociatedObject(self, _cmd);
}
- (nullable UIColor *)dd_navigationBarShadowColor{
return objc_getAssociatedObject(self, _cmd);
}
- (nullable UIImage *)dd_navigationBarShadowImage{
return objc_getAssociatedObject(self, _cmd);
}
- (nullable NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarTitleTextAttributes{
return objc_getAssociatedObject(self, _cmd);
}
- (nullable NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarBarButtonItemAttributes{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setDd_navigationBarBackgroundImage:(nullable UIImage *)dd_navigationBarBackgroundImage{
[self dd_saveNavigationBarBackgroundImage:dd_navigationBarBackgroundImage];
if (@available(iOS 13.0, *)) {
[self dd_changeNavigationBarbackgroundImage:dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:self.dd_navigationBarShadowColor titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
} else {
// Fallback on earlier versions
[self dd_changeNavigationBarbackgroundImage:dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:nil titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
}
}
- (void)setDd_navigationBarBackgroundColor:(nullable UIColor *)dd_navigationBarBackgroundColor{
[self dd_saveNavigationBarBackgroundColor:dd_navigationBarBackgroundColor];
if (@available(iOS 13.0, *)) {
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:self.dd_navigationBarShadowColor titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
} else {
// Fallback on earlier versions
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:nil titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
}
}
- (void)setDd_navigationBarShadowColor:(nullable UIColor *)dd_navigationBarShadowColor{
[self dd_saveNavigationBarShadowColor:dd_navigationBarShadowColor];
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:dd_navigationBarShadowColor titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
}
- (void)setDd_navigationBarShadowImage:(nullable UIImage *)dd_navigationBarShadowImage{
[self dd_saveNavigationBarShadowImage:dd_navigationBarShadowImage];
if (@available(iOS 13.0, *)) {
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:dd_navigationBarShadowImage color:self.dd_navigationBarShadowColor titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
} else {
// Fallback on earlier versions
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:dd_navigationBarShadowImage color:nil titleTextAttributes:self.dd_navigationBarTitleTextAttributes];
}
}
- (void)setDd_navigationBarTitleTextAttributes:(nullable NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarTitleTextAttributes{
[self dd_saveNavigationBarTitleTextAttributes:dd_navigationBarTitleTextAttributes];
if (@available(iOS 13.0, *)) {
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:self.dd_navigationBarShadowColor titleTextAttributes:dd_navigationBarTitleTextAttributes];
} else {
// Fallback on earlier versions
[self dd_changeNavigationBarbackgroundImage:self.dd_navigationBarBackgroundImage color:self.dd_navigationBarBackgroundColor shadowImage:self.dd_navigationBarShadowImage color:nil titleTextAttributes:dd_navigationBarTitleTextAttributes];
}
}
- (void)setDd_navigationBarBarButtonItemAttributes:(nullable NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarBarButtonItemAttributes{
[self dd_saveNavigationBarBarButtonItemAttributes:dd_navigationBarBarButtonItemAttributes];
[self dd_changeNavigationBarBarButtonItemAttributes:dd_navigationBarBarButtonItemAttributes];
}
- (void)dd_saveNavigationBarBackgroundImage:(nullable UIImage *)dd_navigationBarBackgroundImage{
objc_setAssociatedObject(self, @selector(dd_navigationBarBackgroundImage), dd_navigationBarBackgroundImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)dd_saveNavigationBarBackgroundColor:(nullable UIColor *)dd_navigationBarBackgroundColor{
objc_setAssociatedObject(self, @selector(dd_navigationBarBackgroundColor), dd_navigationBarBackgroundColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)dd_saveNavigationBarShadowColor:(nullable UIColor *)dd_navigationBarShadowColor {
objc_setAssociatedObject(self, @selector(dd_navigationBarShadowColor), dd_navigationBarShadowColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)dd_saveNavigationBarShadowImage:(nullable UIImage *)dd_navigationBarShadowImage {
objc_setAssociatedObject(self, @selector(dd_navigationBarShadowImage), dd_navigationBarShadowImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)dd_saveNavigationBarTitleTextAttributes:(NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarTitleTextAttributes{
objc_setAssociatedObject(self, @selector(dd_navigationBarTitleTextAttributes), dd_navigationBarTitleTextAttributes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)dd_saveNavigationBarBarButtonItemAttributes:(NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarBarButtonItemAttributes{
objc_setAssociatedObject(self, @selector(dd_navigationBarBarButtonItemAttributes), dd_navigationBarBarButtonItemAttributes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)dd_changeNavigationBarbackgroundImage:(nullable UIImage *)dd_navigationBarBackgroundImage color:(nullable UIColor *)dd_navigationBarBackgroundColor shadowImage:(nullable UIImage *)dd_navigationBarShadowImage color:(nullable UIColor *)dd_navigationBarShadowColor titleTextAttributes:(NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarTitleTextAttributes{
if (@available(iOS 13.0,*)){
UINavigationBarAppearance *navigationBarAppearance = [[UINavigationBarAppearance alloc] init];
[navigationBarAppearance configureWithTransparentBackground];
navigationBarAppearance.backgroundImage = dd_navigationBarBackgroundImage;
navigationBarAppearance.backgroundColor = dd_navigationBarBackgroundColor;
navigationBarAppearance.shadowImage = dd_navigationBarShadowImage;
navigationBarAppearance.shadowColor = dd_navigationBarShadowColor;
navigationBarAppearance.titleTextAttributes = dd_navigationBarTitleTextAttributes;
self.navigationController.navigationBar.standardAppearance = navigationBarAppearance;
self.navigationController.navigationBar.compactAppearance = navigationBarAppearance;
self.navigationController.navigationBar.scrollEdgeAppearance = navigationBarAppearance;
if (@available(iOS 15.0, *)){
self.navigationController.navigationBar.compactScrollEdgeAppearance = navigationBarAppearance;
}
}else{
self.navigationController.navigationBar.barTintColor = dd_navigationBarBackgroundColor;
[self.navigationController.navigationBar setBackgroundImage:dd_navigationBarBackgroundImage forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setBackgroundImage:dd_navigationBarBackgroundImage forBarMetrics:UIBarMetricsCompact];
[self.navigationController.navigationBar setBackgroundImage:dd_navigationBarBackgroundImage forBarMetrics:UIBarMetricsDefaultPrompt];
[self.navigationController.navigationBar setBackgroundImage:dd_navigationBarBackgroundImage forBarMetrics:UIBarMetricsCompactPrompt];
[self.navigationController.navigationBar setShadowImage:dd_navigationBarShadowImage];
self.navigationController.navigationBar.titleTextAttributes = dd_navigationBarTitleTextAttributes;
}
}
- (void)dd_changeNavigationBarBarButtonItemAttributes:(NSDictionary<NSAttributedStringKey,id> *)dd_navigationBarBarButtonItemAttributes{
if (self.navigationItem.leftBarButtonItems.count > 0){
for (int i = 0; i < self.navigationItem.leftBarButtonItems.count; i++) {
UIBarButtonItem *barButtonItem = self.navigationItem.leftBarButtonItems[i];
[barButtonItem setTitleTextAttributes:dd_navigationBarBarButtonItemAttributes forState:UIControlStateNormal];
[barButtonItem setTitleTextAttributes:dd_navigationBarBarButtonItemAttributes forState:UIControlStateHighlighted];
}
}
if (self.navigationItem.rightBarButtonItems.count > 0){
for (int i = 0; i < self.navigationItem.rightBarButtonItems.count; i++) {
UIBarButtonItem *barButtonItem = self.navigationItem.rightBarButtonItems[i];
[barButtonItem setTitleTextAttributes:dd_navigationBarBarButtonItemAttributes forState:UIControlStateNormal];
[barButtonItem setTitleTextAttributes:dd_navigationBarBarButtonItemAttributes forState:UIControlStateHighlighted];
}
}
// update system backBarButtonItem's color, but this item's font we didn't modify it,usually we will replace this item by our custom items,so the problem of font is unimportant.
UIColor *tintColor = [dd_navigationBarBarButtonItemAttributes objectForKey:NSForegroundColorAttributeName];
if (tintColor != nil && tintColor != self.navigationController.navigationBar.tintColor) {
self.navigationController.navigationBar.tintColor = dd_navigationBarBarButtonItemAttributes[NSForegroundColorAttributeName];
// self.navigationController.navigationBar.backItem's title font didn't modified.
}
}
@end

View File

@@ -0,0 +1,22 @@
//
// UIWindow+DDCategory.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIWindow (DDCategory)
@property (nonatomic, assign)CGFloat dd_safeAreaTop;
@property (nonatomic, assign)CGFloat dd_safeAreaBottom;
@property (nonatomic, assign)CGFloat dd_safeAreaLeft;
@property (nonatomic, assign)CGFloat dd_safeAreaRight;
- (CGFloat)dd_safeAreaTop;
- (CGFloat)dd_safeAreaBottom;
- (CGFloat)dd_safeAreaLeft;
- (CGFloat)dd_safeAreaRight;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,45 @@
//
// UIWindow+DDCategory.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/6.
#import "UIWindow+DDCategory.h"
@implementation UIWindow (DDCategory)
@dynamic dd_safeAreaTop;
@dynamic dd_safeAreaBottom;
@dynamic dd_safeAreaLeft;
@dynamic dd_safeAreaRight;
- (CGFloat)dd_safeAreaTop {
if (@available(iOS 11.0, *)) {
return self.safeAreaInsets.top;
} else {
return 0.0;
}
}
- (CGFloat)dd_safeAreaBottom {
if (@available(iOS 11.0, *)) {
return self.safeAreaInsets.bottom;
} else {
return 0.0;
}
}
- (CGFloat)dd_safeAreaLeft {
if (@available(iOS 11.0, *)) {
return self.safeAreaInsets.left;
} else {
return 0.0;
}
}
- (CGFloat)dd_safeAreaRight {
if (@available(iOS 11.0, *)) {
return self.safeAreaInsets.right;
} else {
return 0.0;
}
}
@end

19
Pods/DDCategoryKit_Private/LICENSE generated Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2022 DDIsFriend <DDIsFriend@163.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

29
Pods/DDCategoryKit_Private/README.md generated Normal file
View File

@@ -0,0 +1,29 @@
# DDCategoryKit_Private
[![CI Status](https://img.shields.io/travis/DDIsFriend/DDCategoryKit_Private.svg?style=flat)](https://travis-ci.org/DDIsFriend/DDCategoryKit_Private)
[![Version](https://img.shields.io/cocoapods/v/DDCategoryKit_Private.svg?style=flat)](https://cocoapods.org/pods/DDCategoryKit_Private)
[![License](https://img.shields.io/cocoapods/l/DDCategoryKit_Private.svg?style=flat)](https://cocoapods.org/pods/DDCategoryKit_Private)
[![Platform](https://img.shields.io/cocoapods/p/DDCategoryKit_Private.svg?style=flat)](https://cocoapods.org/pods/DDCategoryKit_Private)
## Example
To run the example project, clone the repo, and run `pod install` from the Example directory first.
## Requirements
## Installation
DDCategoryKit_Private is available through [CocoaPods](https://cocoapods.org). To install
it, simply add the following line to your Podfile:
```ruby
pod 'DDCategoryKit_Private'
```
## Author
DDIsFriend, DDIsFriend@163.com
## License
DDCategoryKit_Private is available under the MIT license. See the LICENSE file for more info.