增加换肤功能

This commit is contained in:
启星
2025-08-14 10:07:49 +08:00
parent f6964c1e89
commit 4f9318d98e
8789 changed files with 978530 additions and 2 deletions

View File

@@ -0,0 +1,19 @@
//
// NSDate+Category.h
// YSDTrucksProject
//
// Created by 党凯 on 2020/8/20.
// Copyright © 2020 党凯. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSDate (QX)
+ (NSString *)timeStringWithTimeInterval:(NSString *)timeStr;
@end

View File

@@ -0,0 +1,151 @@
//
// NSDate+Category.m
// YSDTrucksProject
//
// Created by on 2020/8/20.
// Copyright © 2020 . All rights reserved.
//
#import "NSDate+QX.h"
@implementation NSDate (QX)
+ (NSString *)timeStringWithTimeInterval:(NSString *)timeInterval
{
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval.longLongValue]; //,1000 , 1000
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
//
if ([date isToday]) {
// formatter.dateFormat = @"HH:mm";
//
// return [formatter stringFromDate:date];
return @"今天";
}else{
//
if ([date isYesterday]) {
// formatter.dateFormat = @"昨天HH:mm";
// return [formatter stringFromDate:date];
// [date weekdayStringFromDate]
return @"昨天";
}else if ([date isInWeak]){
// formatter.dateFormat = [NSString stringWithFormat:@"%@%@",[date weekdayStringFromDate],@"HH:mm"];
// return [formatter stringFromDate:date];
return @"一周内";
//
}else{
// formatter.dateFormat = @"yy-MM-dd HH:mm";
formatter.dateFormat = @"yyyy-MM-dd";
return [formatter stringFromDate:date];
}
}
return nil;
}
//- (BOOL)isInWeek{
// NSTimeInterval *time = [self ]
//}
//
- (BOOL)isSameWeek
{
NSCalendar *calendar = [NSCalendar currentCalendar];
int unit = NSCalendarUnitWeekday | NSCalendarUnitMonth | NSCalendarUnitYear ;
//1.
NSDateComponents *nowCmps = [calendar components:unit fromDate:[NSDate date]];
//2.self
NSDateComponents *selfCmps = [calendar components:unit fromDate:self];
return (selfCmps.year == nowCmps.year) && (selfCmps.month == nowCmps.month) && (selfCmps.day == nowCmps.day);
}
//
- (NSString *)weekdayStringFromDate{
NSArray *weekdays = [NSArray arrayWithObjects: [NSNull null], @"星期天", @"星期一", @"星期二", @"星期三", @"星期四", @"星期五", @"星期六", nil];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSTimeZone *timeZone = [[NSTimeZone alloc] initWithName:@"Asia/Shanghai"];
[calendar setTimeZone: timeZone];
NSCalendarUnit calendarUnit = NSCalendarUnitWeekday;
NSDateComponents *theComponents = [calendar components:calendarUnit fromDate:self];
return [weekdays objectAtIndex:theComponents.weekday];
}
//
- (BOOL)isInWeak
{
//2014-05-01
NSDate *nowDate = [[NSDate date] dateWithYMD];
//2014-04-30
NSDate *selfDate = [self dateWithYMD];
//nowDateselfDate
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *cmps = [calendar components:NSCalendarUnitDay fromDate:selfDate toDate:nowDate options:0];
return ((cmps.day > 1) && (cmps.day < 7));
}
//
- (BOOL)isToday
{
//now: 2015-09-05 11:23:00
//self
NSCalendar *calendar = [NSCalendar currentCalendar];
int unit = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear ;
//1.
NSDateComponents *nowCmps = [calendar components:unit fromDate:[NSDate date]];
//2.self
NSDateComponents *selfCmps = [calendar components:unit fromDate:self];
return (selfCmps.year == nowCmps.year) && (selfCmps.month == nowCmps.month) && (selfCmps.day == nowCmps.day);
}
//
- (BOOL)isYesterday
{
//2014-05-01
NSDate *nowDate = [[NSDate date] dateWithYMD];
//2014-04-30
NSDate *selfDate = [self dateWithYMD];
//nowDateselfDate
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *cmps = [calendar components:NSCalendarUnitDay fromDate:selfDate toDate:nowDate options:0];
return cmps.day == 1;
}
//
- (NSDate *)dateWithYMD
{
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd";
NSString *selfStr = [fmt stringFromDate:self];
return [fmt dateFromString:selfStr];
}
@end

View File

@@ -0,0 +1,183 @@
//
// NSString+QX.h
// QXLive
//
// Created by 启星 on 2025/5/7.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (QX)
/**
* 检查是否是有效字符串
**/
- (BOOL)isExist;
/**
有效数字控制
@param number 原始数据
@return 返回字符串
*/
+ (NSString *)effectiveNum:(double)number;
/// 当前字符串是否是数字
- (BOOL)isNumber;
/**
获得富文本字符串
@param attriFont 字体大小
@param attriColor 字体颜色
@param attriRange 富文本区域
@return 富文本字符串
*/
- (NSMutableAttributedString *)getNSMutableAttributedStringWithAttriFont:(UIFont *)attriFont attriColor:(UIColor *)attriColor isline:(BOOL)isline attriBackgroundColor:(nullable UIColor *)attriBackgroundColor lineSpacing:(CGFloat)lineSpacing attriRange:(NSRange)attriRange;
/**
删除线
@param textColor 文本颜色
@param lineColor 删除线颜色
@param range 删除范围
@return 富文本字符串
*/
- (NSAttributedString *)deleteLineWithTextColor: (nullable UIColor *)textColor lineColor: (nullable UIColor *)lineColor range: (NSRange)range;
- (NSAttributedString *)deleteLineWithTextColor: (nullable UIColor *)textColor lineColor: (nullable UIColor *)lineColor;
- (NSAttributedString *)deleteLineWithTextColor: (nullable UIColor *)textColor;
- (NSAttributedString *)deleteLine;
/**
验证有效手机号
@param phoneNum 手机号
@return 是否有效
*/
+ (BOOL)effectivePhoneNum:(NSString *)phoneNum;
+ (BOOL)effectivePhoneNum:(NSString *)phoneNum validLength:(NSInteger)length;
/**
生成uuid
追加字符串
*/
//+ (instancetype)effectivePhoneNumeffectivePhoneNum;
/**
* 获取时间
[@"y"]; // 2017
[@"yy"]; // 17
[@"yyy"]; // 2017
[@"yyyy"]; // 2017
[@"M"]; // 8
[@"MM"]; // 08
[@"MMM"]; // 8月
[@"MMMM"]; // 八月
[@"d"]; // 3
[@"dd"]; // 03
[@"D"]; // 215,一年中的第几天
[@"h"]; // 4
[@"hh"]; // 04
[@"H"]; // 16 24小时制
[@"HH"]; // 16
[@"m"]; // 28
[@"mm"]; // 28
[@"s"]; // 57
[@"ss"]; // 04
[@"E"]; // 周四
[@"EEEE"]; // 星期四
[@"EEEEE"]; // 四
[@"e"]; // 5 (显示的是一周的第几天weekday1为周日。)
[@"ee"]; // 05
[@"eee"]; // 周四
[@"eeee"]; // 星期四
[@"eeeee"]; // 四
[@"z"]; // GMT+8
[@"zzzz"]; // 中国标准时间
[@"ah"]; // 下午5
[@"aH"]; // 下午17
[@"am"]; // 下午53
[@"as"]; // 下午52
*/
//+ (NSString *)transformTimeInterval:(NSTimeInterval)sec byFormatter:(NSString *)formatter;
//
///// 今天显示9:00 昨日显示(昨天 时:分)(昨天 10:00) 其余显示(年/月/日)(2019/11/06)
///// @param sec 时间戳
//+ (NSString *)transformTodayYesterdayAndOtherTimeInterval:(NSTimeInterval)sec;
/**
转换为升序key排列的URL参数格式的key=Value形式的字符串
@param dict 参数列表
@return 格式化后的字符串
*/
+ (NSString *)transformByAscendingWithDict:(NSDictionary *)dict;
/**
判断data的类型
@return content-Type
*/
+ (NSString *)contentTypeWithImageData:(NSData *)data;
/// 手机号脱敏
- (NSString *)showMoblePhoneNumber;
- (NSDictionary<NSString *,NSString *> *)parseParameters;
/// 格式化字符串的长短
/// @param limit 限制显示几个字符
/// @param suffix 超出部分的显示字符
- (NSString *)formatterToLimitNumStrWith:(NSUInteger)limit suffixStr:(nullable NSString *)suffix;
- (NSString *)formatterToLimitNumStrWith:(NSUInteger)limit;
/**
显示热度值
@param count 热度值
@return 返回字符串
*/
+ (NSString *)qx_showHotCountNum:(int64_t)count;
/// 保留两位
+ (NSString *)qx_showHotCountNumDouble:(int64_t)count ;
/**
* 显示房间名字
*/
- (NSString *)qx_showRoomName;
/**
订单倒计时
type == 1 返回 00:00:00
type == 2 返回 00时00分00秒
*/
+ (NSString *)timeStrFromInterval:(long)lastTime type:(NSInteger)type;
+ (BOOL)inputShouldLetterOrNum:(NSString *)inputString;
+ (NSString *)safeString:(NSString *)string ByAppendingString:(NSString *)aString;
/**
超过9999数量用w显示并保留1位小数(如14500 = 1.5w)
*/
- (NSString *)tenThousandFormatString;
- (NSInteger)ageWithDateOfBirth;
/// 传入秒 得到 几天 几小时
+ (NSString*)getTimeWithSecond:(long long)second;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,405 @@
//
// NSString+QX.m
// QXLive
//
// Created by on 2025/5/7.
//
#import "NSString+QX.h"
#import "NSDate+BRPickerView.h"
@implementation NSString (QX)
- (BOOL)isExist {
if (!self) {
return NO;
}
if ([self isKindOfClass:[NSNull class]]) {
return NO;
}
NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSString *trimmedStr = [self stringByTrimmingCharactersInSet:set];
if (trimmedStr.length == 0 || trimmedStr.length == NSNotFound) {
return NO;
}
return YES;
}
/**
@param number
@return
*/
+ (NSString *)effectiveNum:(double)number {
if (fmodf(number, 1) == 0 || fmodf(number * 10, 1) == 0) {
return [NSString notRounding:number afterPoint:1];
}else{
return [NSString notRounding:number afterPoint:2];
}
}
//
+ (NSString *)notRounding:(double)price afterPoint:(int)position{
NSDecimalNumberHandler* roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:position raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
NSDecimalNumber *ouncesDecimal;
NSDecimalNumber *roundedOunces;
ouncesDecimal = [[NSDecimalNumber alloc] initWithDouble:price];
roundedOunces = [ouncesDecimal decimalNumberByRoundingAccordingToBehavior:roundingBehavior];
return [NSString stringWithFormat:@"%@",roundedOunces];
}
- (BOOL)isNumber {
if (self.length ==0 ) {
return NO;
}
unichar c;
for (int i=0; i<self.length; i++) {
c=[self characterAtIndex:i];
if (!isdigit(c)) {
return NO;
}
}
return YES;
}
- (NSMutableAttributedString *)getNSMutableAttributedStringWithAttriFont:(UIFont *)attriFont attriColor:(UIColor *)attriColor isline:(BOOL)isline attriBackgroundColor:(UIColor *)attriBackgroundColor lineSpacing:(CGFloat)lineSpacing attriRange:(NSRange)attriRange {
NSMutableAttributedString *getStr = [[NSMutableAttributedString alloc]initWithString:self];
NSMutableDictionary <NSAttributedStringKey, id>*dict = [NSMutableDictionary dictionaryWithCapacity:1];
dict[NSFontAttributeName] = attriFont;
dict[NSForegroundColorAttributeName] = attriColor;
if (isline) {
dict[NSStrikethroughStyleAttributeName] = [NSNumber numberWithInteger:NSUnderlineStyleSingle];
}
if (attriBackgroundColor) {
dict[NSBackgroundColorAttributeName] = attriBackgroundColor;
}
if (lineSpacing > 0) {//
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = lineSpacing;
dict[NSParagraphStyleAttributeName] = paragraphStyle;
}
[getStr addAttributes:dict range:attriRange];
return getStr;
}
- (NSAttributedString *)deleteLineWithTextColor:(UIColor *)textColor lineColor:(UIColor *)lineColor range:(NSRange)range {
if (!self || self.length == 0) {
return nil;
}
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:self
attributes:@{NSStrikethroughStyleAttributeName: @(NSUnderlineStyleNone)}];
[attrStr setAttributes:@{NSStrikethroughStyleAttributeName: @(NSUnderlineStyleSingle),
NSBaselineOffsetAttributeName: @0}
range:range];
if (textColor) {
[attrStr addAttribute:NSForegroundColorAttributeName value:textColor range: range];
}
if (lineColor) {
[attrStr addAttribute:NSStrikethroughColorAttributeName value:lineColor range:range];
}
return attrStr;
}
- (NSAttributedString *)deleteLineWithTextColor:(UIColor *)textColor lineColor:(UIColor *)lineColor {
return [self deleteLineWithTextColor:textColor lineColor:lineColor range:NSMakeRange(0, self.length)];
}
- (NSAttributedString *)deleteLineWithTextColor:(UIColor *)textColor {
return [self deleteLineWithTextColor:textColor lineColor:textColor range:NSMakeRange(0, self.length)];
}
- (NSAttributedString *)deleteLine {
return [self deleteLineWithTextColor:nil lineColor:nil range:NSMakeRange(0, self.length)];
}
+ (BOOL)effectivePhoneNum:(NSString *)phoneNum {
return [self effectivePhoneNum:phoneNum validLength:11];
}
+ (BOOL)effectivePhoneNum:(NSString *)phoneNum validLength:(NSInteger)length {
NSScanner* scan = [NSScanner scannerWithString:phoneNum];
int val;
return [scan scanInt:&val] && [scan isAtEnd] && phoneNum.length == length;
}
+ (instancetype)generateUUIDString {
CFUUIDRef puuid = CFUUIDCreate(nil);
CFStringRef uuidString = CFUUIDCreateString(nil, puuid);
NSString * result = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString));
CFRelease(puuid);
CFRelease(uuidString);
return result;
}
//+ (NSString *)transformTimeInterval:(NSTimeInterval)sec byFormatter:(NSString *)formatter {
// NSDate * dt = [NSDate dateWithTimeIntervalSince1970:sec];
// NSDateFormatter * df = [NSDateFormatter shared];
// [df setDateFormat:formatter];
// NSString *regStr = [df stringFromDate:dt];
// return regStr;
//}
//
//+ (NSString *)transformTodayYesterdayAndOtherTimeInterval:(NSTimeInterval)sec {
// NSDate *dt = [NSDate dateWithTimeIntervalSince1970:sec];
// NSCalendar *calendar =[NSCalendar currentCalendar];
// NSDateFormatter * df = [NSDateFormatter shared];
// NSString *prefix = @"";
// if ([calendar isDateInToday:dt]) {
// df.dateFormat = @"HH:mm";
// }else if ([calendar isDateInYesterday:dt]) {
// prefix = @"昨天 ";
// df.dateFormat = @"HH:mm";
// }else {
// df.dateFormat = @"yyyy/MM/dd";
// }
// return [NSString stringWithFormat:@"%@%@",prefix,[df stringFromDate:dt]];
//}
+ (NSString *)transformByAscendingWithDict:(NSDictionary *)dict {
NSArray*keys = [dict allKeys];
NSArray*sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1,id obj2) {
return[obj1 compare:obj2 options:NSNumericSearch];//
}];
NSString*str =@"";
for(NSString*key in sortedArray) {
id value = [dict objectForKey:key];
if([value isKindOfClass:[NSDictionary class]]) {
value = [self transformByAscendingWithDict:value];
}
if([str length] !=0) {
str = [str stringByAppendingString:@"&"];
}
str = [str stringByAppendingFormat:@"%@=%@",key,value];
}
return str;
}
+ (NSString *)contentTypeWithImageData:(NSData *)data {
if (!data) {
return @"jpeg";
}
// File signatures table: http://www.garykessler.net/library/file_sigs.html
uint8_t c;
[data getBytes:&c length:1];
switch (c) {
case 0xFF:
return @"jpeg";
case 0x89:
return @"png";
case 0x47:
return @"gif";
case 0x49:
case 0x4D:
return @"tiff";
case 0x52: {
if (data.length >= 12) {
//RIFF....WEBP
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return @"webp";
}
}
break;
}
case 0x00: {
if (data.length >= 12) {
//....ftypheic ....ftypheix ....ftyphevc ....ftyphevx
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(4, 8)] encoding:NSASCIIStringEncoding];
if ([testString isEqualToString:@"ftypheic"]
|| [testString isEqualToString:@"ftypheix"]
|| [testString isEqualToString:@"ftyphevc"]
|| [testString isEqualToString:@"ftyphevx"]) {
return @"HEIC";
}
//....ftypmif1 ....ftypmsf1
if ([testString isEqualToString:@"ftypmif1"] || [testString isEqualToString:@"ftypmsf1"]) {
return @"HEIF";
}
}
break;
}
}
return @"jpeg";
}
- (NSString *)showMoblePhoneNumber {
if (self.length >= 7) {
return [self stringByReplacingCharactersInRange:NSMakeRange(self.length-8, 4) withString:@"****"];
}
return self;
}
- (NSDictionary<NSString *,NSString *> *)parseParameters{
NSMutableDictionary *parm = [NSMutableDictionary dictionary];
NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithString:self];
//
[urlComponents.queryItems enumerateObjectsUsingBlock:^(NSURLQueryItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
parm[obj.name] = obj.value;
}];
return parm;
}
- (NSString *)formatterToLimitNumStrWith:(NSUInteger)limit suffixStr:(NSString *)suffix {
if (self.length > limit) {
return [NSString stringWithFormat:@"%@%@",[self substringToIndex:limit],suffix ?: @""];
}else{
return self;
}
}
- (NSString *)formatterToLimitNumStrWith:(NSUInteger)limit {
return [self formatterToLimitNumStrWith:limit suffixStr:nil];
}
+ (NSString *)qx_showHotCountNum:(int64_t)count {
if (count > 9999 || count < -9999) {
// return [NSString stringWithFormat:@"%@w",[self effectiveNum:(double)count/10000.0]];
return [NSString stringWithFormat:@"%.1fw",(double)count/10000.0];
}else {
return [NSString stringWithFormat:@"%lld",count];
}
}
+ (NSString *)qx_showHotCountNumDouble:(int64_t)count {
if (count > 9999 || count < -9999) {
// return [NSString stringWithFormat:@"%@w",[self effectiveNum:(double)count/10000.0]];
return [NSString stringWithFormat:@"%.2fw",(double)count/10000.0];
}else {
return [NSString stringWithFormat:@"%lld",count];
}
}
- (NSString *)qx_showRoomName {
if (self.length > 10) {
return [NSString stringWithFormat:@"%@...",[self formatterToLimitNumStrWith:10]];
}else {
return self;
}
}
+ (NSString *)timeStrFromInterval:(long)lastTime type:(NSInteger)type{
if (lastTime < 60) {
NSString *secondStr = [NSString stringWithFormat:@"%ld",lastTime];
if (lastTime < 10) {
secondStr = [NSString stringWithFormat:@"0%@",secondStr];
}
if (type == 1) {
return [NSString stringWithFormat:@"00:%@",secondStr];
}
return [NSString stringWithFormat:@"%ld秒",lastTime];
}
if (lastTime < 3600) {
NSString *minuteStr = [NSString stringWithFormat:@"%ld",lastTime / 60];
NSString *secondStr = [NSString stringWithFormat:@"%ld",lastTime % 60];
if (minuteStr.length == 1) {
minuteStr = [NSString stringWithFormat:@"0%@",minuteStr];
}
if (secondStr.length == 1) {
secondStr = [NSString stringWithFormat:@"0%@",secondStr];
}
if (type == 1) {
return [NSString stringWithFormat:@"%@:%@",minuteStr,secondStr];
}
return [NSString stringWithFormat:@"%ld分%ld秒",lastTime / 60,lastTime % 60];
}
NSString *hourStr = [NSString stringWithFormat:@"%ld",lastTime / 3600];
NSString *minuteStr = [NSString stringWithFormat:@"%ld",(lastTime % 3600) / 60];
if (minuteStr.length == 1) {
minuteStr = [NSString stringWithFormat:@"0%@",minuteStr];
}
if (type == 1) {
return [NSString stringWithFormat:@"%@:%@",hourStr,minuteStr];
}
return [NSString stringWithFormat:@"%ld时%ld分",lastTime / 3600,(lastTime % 3600) / 60];
}
+ (BOOL)inputShouldLetterOrNum:(NSString *)inputString {
if (inputString.length == 0) return NO;
NSString *regex =@"[a-zA-Z0-9]*";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
return [pred evaluateWithObject:inputString];
}
+ (NSString *)safeString:(NSString *)string ByAppendingString:(NSString *)aString{
if ([string isKindOfClass:[NSString class]]) {
if (![string isExist]) {
string = @"";
}
}else {
string = @"";
}
if ([aString isKindOfClass:[NSString class]]) {
if (![aString isExist]) {
aString = @"";
}
}else {
aString = @"";
}
return [NSString stringWithFormat:@"%@%@",string,aString];
}
- (NSString *)tenThousandFormatString {
NSInteger number = [self integerValue];
if (number < 10000) {
return number < 0 ? @"0" : [NSString stringWithFormat:@"%ld",(long)number];
}else {
double temp = number / 10000.0;
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:1 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
NSDecimalNumber *decimal = [[NSDecimalNumber alloc] initWithDouble:temp];
NSNumber *ratio = [decimal decimalNumberByRoundingAccordingToBehavior:roundingBehavior];
return [[NSNumberFormatter localizedStringFromNumber:ratio numberStyle:NSNumberFormatterDecimalStyle] stringByAppendingString:@"w"];
}
}
- (NSInteger)ageWithDateOfBirth{
NSDate *date = [NSDate br_dateFromString:self dateFormat:@"yyyy-MM-dd"];
//
NSDateComponents *components1 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
NSInteger brithDateYear = [components1 year];
NSInteger brithDateDay = [components1 day];
NSInteger brithDateMonth = [components1 month];
//
NSDateComponents *components2 = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
NSInteger currentDateYear = [components2 year];
NSInteger currentDateDay = [components2 day];
NSInteger currentDateMonth = [components2 month];
//
NSInteger iAge = currentDateYear - brithDateYear - 1;
if ((currentDateMonth > brithDateMonth) || (currentDateMonth == brithDateMonth && currentDateDay >= brithDateDay)) {
iAge++;
}
return iAge;
}
+(NSString *)getTimeWithSecond:(long long)second{
NSInteger day = second/(60*60*24);
NSInteger hour = second%(60*60*24)/(60*60);
return [NSString stringWithFormat:@"%ld天%ld小时",day,hour];
}
@end

View File

@@ -0,0 +1,34 @@
//
// UIButton+QX.h
// QXLive
//
// Created by 启星 on 2025/4/28.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, QXButtonEdgeInsetsStyle) {
QXButtonEdgeInsetsStyleTop, ///< image在上label在下
QXButtonEdgeInsetsStyleLeft, ///< image在左label在右
QXButtonEdgeInsetsStyleBottom, ///< image在下label在上
QXButtonEdgeInsetsStyleRight ///< image在右label在左
};
@interface UIButton (QX)
/**
设置button的titleLabel和imageView的布局样式及间距
@param style titleLabel和imageView的布局样式
@param space titleLabel和imageView的b间距
*/
- (void)qx_layoutButtonWithEdgeInsetsStyle:(QXButtonEdgeInsetsStyle)style
imageTitleSpace:(CGFloat)space;
- (void)qx_layoutButtonNOSizeToFitWithEdgeInsetsStyle:(QXButtonEdgeInsetsStyle)style
imageTitleSpace:(CGFloat)space;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,127 @@
//
// UIButton+QX.m
// QXLive
//
// Created by on 2025/4/28.
//
#import "UIButton+QX.h"
@implementation UIButton (QX)
- (void)qx_layoutButtonWithEdgeInsetsStyle:(QXButtonEdgeInsetsStyle)style
imageTitleSpace:(CGFloat)space{
[self sizeToFit];
[self qx_layoutButtonNOSizeToFitWithEdgeInsetsStyle:style imageTitleSpace:space];
}
- (void)qx_layoutButtonNOSizeToFitWithEdgeInsetsStyle:(QXButtonEdgeInsetsStyle)style
imageTitleSpace:(CGFloat)space {
/**
* titleEdgeInsetstitleinsettableViewcontentInset
* titlebuttonimage
* imagelabelimagebuttonlabeltitlebuttonimage
*/
CGFloat spacef = ceilf(space);
// 1.imageViewtitleLabel
CGFloat imageWidth = self.imageView.frame.size.width;
CGFloat imageHeight = self.imageView.frame.size.height;
CGFloat labelWidth = 0.0;
CGFloat labelHeight = 0.0;
if (@available(iOS 8.0, *)) {
// iOS8titleLabelsize0
labelWidth = self.titleLabel.intrinsicContentSize.width;
labelHeight = self.titleLabel.intrinsicContentSize.height;
}else {
labelWidth = self.titleLabel.frame.size.width;
labelHeight = self.titleLabel.frame.size.height;
}
// 2.imageEdgeInsetslabelEdgeInsets
UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero;
UIEdgeInsets labelEdgeInsets = UIEdgeInsetsZero;
UIEdgeInsets contentEdgeInsets = UIEdgeInsetsZero;
CGFloat imageOffSetX = labelWidth / 2.0;
CGFloat labelOffSetX = imageWidth / 2.0;
CGFloat maxWidth = MAX(imageWidth,labelWidth); //
CGFloat changeWidth = imageWidth + labelWidth - maxWidth; //
CGFloat maxHeight = MAX(imageHeight,labelHeight); //
// 3.stylespacefimageEdgeInsetslabelEdgeInsets
switch (style) {
case QXButtonEdgeInsetsStyleTop:
{
CGFloat gap = (maxHeight - MIN(imageHeight, labelHeight))/2.0;
if (imageHeight >= labelHeight) {
imageEdgeInsets = UIEdgeInsetsMake(0, imageOffSetX, 0, -imageOffSetX);
labelEdgeInsets = UIEdgeInsetsMake(labelHeight + gap + spacef, -labelOffSetX, -(labelHeight + gap + spacef), labelOffSetX);
contentEdgeInsets = UIEdgeInsetsMake(0, - changeWidth / 2.0, spacef + labelHeight, -changeWidth / 2.0);
}else{
imageEdgeInsets = UIEdgeInsetsMake(-(gap + imageHeight + spacef), imageOffSetX, gap + imageHeight + spacef, -imageOffSetX);
labelEdgeInsets = UIEdgeInsetsMake(0, -labelOffSetX, 0, labelOffSetX);
contentEdgeInsets = UIEdgeInsetsMake(spacef + imageHeight, - changeWidth / 2.0, 0, -changeWidth / 2.0);
}
}
break;
case QXButtonEdgeInsetsStyleLeft:
{
imageEdgeInsets = UIEdgeInsetsMake(0, -spacef/2.0, 0, spacef/2.0);
labelEdgeInsets = UIEdgeInsetsMake(0, spacef/2.0, 0, -spacef/2.0);
contentEdgeInsets = UIEdgeInsetsMake(0, spacef/2.0, 0, spacef/2.0);
}
break;
case QXButtonEdgeInsetsStyleBottom:
{
CGFloat gap = (maxHeight - MIN(imageHeight, labelHeight))/2.0;
if (imageHeight >= labelHeight) {
imageEdgeInsets = UIEdgeInsetsMake(0,
imageOffSetX,
0,
-imageOffSetX);
labelEdgeInsets = UIEdgeInsetsMake(-(labelHeight + gap + spacef),
-labelOffSetX,
labelHeight + gap + spacef,
labelOffSetX);
contentEdgeInsets = UIEdgeInsetsMake(spacef + labelHeight,
- changeWidth / 2.0,
0,
-changeWidth / 2.0);
}else{
imageEdgeInsets = UIEdgeInsetsMake(gap + imageHeight + spacef,
imageOffSetX,
-(gap + imageHeight + spacef),
-imageOffSetX);
labelEdgeInsets = UIEdgeInsetsMake(0,
-labelOffSetX,
0,
labelOffSetX);
contentEdgeInsets = UIEdgeInsetsMake(0,
- changeWidth / 2.0,
spacef + imageHeight,
-changeWidth / 2.0);
}
}
break;
case QXButtonEdgeInsetsStyleRight:
{
imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth+spacef/2.0, 0, -labelWidth-spacef/2.0);
labelEdgeInsets = UIEdgeInsetsMake(0, -imageWidth-spacef/2.0, 0, imageWidth+spacef/2.0);
contentEdgeInsets = UIEdgeInsetsMake(0, spacef/2.0, 0, spacef/2.0);
}
break;
default:
break;
}
// 4.
self.titleEdgeInsets = labelEdgeInsets;
self.imageEdgeInsets = imageEdgeInsets;
self.contentEdgeInsets = contentEdgeInsets;
}
@end

View File

@@ -0,0 +1,25 @@
//
// UIColor+Hex.h
// OCThemeDemo
//
// Created by 阿飞 on 2019/5/7.
// Copyright © 2020 阿飞. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIColor (QX)
//随机色
+ (UIColor *)sh_colorArc4random;
//从十六进制字符串获取颜色,
+ (UIColor *)sh_colorWithHexString:(NSString *)color;
//color:支持@“#123456”、 @“0X123456”、 @“123456”三种格式
+ (UIColor *)sh_colorWithHexString:(NSString *)color alpha:(CGFloat)alpha;
//渐变色
+ (UIColor *)sh_getColorOfPercent:(CGFloat)percent between:(UIColor *)color1 and:(UIColor *)color2;
@end

View File

@@ -0,0 +1,94 @@
//
// UIColor+Hex.m
// OCThemeDemo
//
// Created by on 2019/5/7.
// Copyright © 2020 . All rights reserved.
//
#import "UIColor+QX.h"
@implementation UIColor (QX)
+ (UIColor *)sh_colorWithHexString:(NSString *)color alpha:(CGFloat)alpha {
//
NSString *cString = [[color stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
// String should be 6 or 8 characters
if ([cString length] < 6)
{
return [UIColor clearColor];
}
// strip 0X if it appears
//0x2
if ([cString hasPrefix:@"0X"])
{
cString = [cString substringFromIndex:2];
}
//#1
if ([cString hasPrefix:@"#"])
{
cString = [cString substringFromIndex:1];
}
if ([cString length] != 6)
{
return [UIColor clearColor];
}
// Separate into r, g, b substrings
NSRange range;
range.location = 0;
range.length = 2;
//r
NSString *rString = [cString substringWithRange:range];
//g
range.location = 2;
NSString *gString = [cString substringWithRange:range];
//b
range.location = 4;
NSString *bString = [cString substringWithRange:range];
// Scan values
unsigned int r, g, b;
[[NSScanner scannerWithString:rString] scanHexInt:&r];
[[NSScanner scannerWithString:gString] scanHexInt:&g];
[[NSScanner scannerWithString:bString] scanHexInt:&b];
return [UIColor colorWithRed:((float)r / 255.0f) green:((float)g / 255.0f) blue:((float)b / 255.0f) alpha:alpha];
}
//alpha1
+ (UIColor *)sh_colorWithHexString:(NSString *)color {
return [self sh_colorWithHexString:color alpha:1.0f];
}
+ (UIColor *)sh_colorArc4random {
float red = arc4random()%256 / 255.0;
float bule = arc4random()%256 / 255.0;
float green = arc4random()%256 / 255.0;
return [UIColor colorWithRed:red green:green blue:bule alpha:1.0];
}
#pragma mark -
/**
*
*
* @param percent
* @param color1 1()
* @param color2 2
*
*/
+ (UIColor *)sh_getColorOfPercent:(CGFloat)percent between:(UIColor *)color1 and:(UIColor *)color2{
CGFloat red1, green1, blue1, alpha1;
[color1 getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1];
CGFloat red2, green2, blue2, alpha2;
[color2 getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2];
CGFloat p1 = percent;
CGFloat p2 = 1.0 - percent;
UIColor *mid = [UIColor colorWithRed:red1*p1+red2*p2 green:green1*p1+green2*p2 blue:blue1*p1+blue2*p2 alpha:1.0f];
return mid;
}
@end

View File

@@ -0,0 +1,24 @@
//
// UIControl+QX.h
// QXLive
//
// Created by 启星 on 2025/5/19.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
static const void *BandNameKey = &BandNameKey;
@interface UIControl (QX)
@property (nonatomic, assign)NSTimeInterval needEventInterval; /* 多少秒后再次响应 */
@property (nonatomic, assign, readonly)BOOL ignoreEvent; /*查看当前是否已经停止响应 如果停止响应为YES, 可以再次交互响应为NO; 不是固定的, 取到的值是动态变化的 和needEventIntervaly有关*/
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,86 @@
//
// UIControl+QX.m
// QXLive
//
// Created by on 2025/5/19.
//
#import "UIControl+QX.h"
static inline void swizzling_exchangeMethodWithSelector(Class clazz, SEL originalSelector, SEL exchangeSelector) {
//
Method originalMethod = class_getInstanceMethod(clazz, originalSelector);
//
Method exchangeMethod = class_getInstanceMethod(clazz, exchangeSelector);
if (!originalMethod || !exchangeMethod) {
return;
}
if (class_addMethod(clazz, originalSelector, method_getImplementation(exchangeMethod), method_getTypeEncoding(exchangeMethod))) {
class_replaceMethod(clazz, exchangeSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}else{
method_exchangeImplementations(originalMethod, exchangeMethod);
}
}
static inline void swizzling_exchangeMethodWithMethod(Method originalMethod, Method exchangeMethod) {
method_exchangeImplementations(originalMethod, exchangeMethod);
}
@implementation UIControl (QX)
- (NSTimeInterval)needEventInterval
{
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}
- (void)setNeedEventInterval:(NSTimeInterval)needEventInterval
{
objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(needEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)ignoreEvent
{
return [objc_getAssociatedObject(self, BandNameKey) boolValue];
}
- (void)setIgnoreEvent:(BOOL)ignoreEvent
{
objc_setAssociatedObject(self, BandNameKey, [NSNumber numberWithBool:ignoreEvent], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+(void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
swizzling_exchangeMethodWithSelector([self class],
@selector(sendAction:to:forEvent:),
@selector(__uxy_sendAction:to:forEvent:));
});
}
- (void)__uxy_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
if (self.ignoreEvent) return; /*ignoreEventno, */
if (self.needEventInterval > 0)
{
self.ignoreEvent = YES;
[self performSelector:@selector(changeIgnoreEvent) withObject:@(NO) afterDelay:self.needEventInterval];
}
[self __uxy_sendAction:action to:target forEvent:event]; //;
}
- (void)changeIgnoreEvent
{
self.ignoreEvent = NO;
}
@end

View File

@@ -0,0 +1,80 @@
//
// UIImage+QX.h
// QXLive
//
// Created by 启星 on 2025/4/28.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImage (QX)
typedef NS_ENUM(NSUInteger, GradientType) {
GradientTypeTopToBottom = 0,//从上到小
GradientTypeLeftToRight = 1,//从左到右
GradientTypeUpleftToLowright = 2,//左上到右下
GradientTypeUprightToLowleft = 3,//右上到左下
};
// 指定尺寸 进行图片压缩
- (NSData *)qx_compressImageQualityWithToByte:(NSInteger)maxLength;
/**
把view生成UIImage图片
@param view 传入view
@return 生成的UIImage
*/
+ (UIImage *)qx_convertViewToImageWith:(UIView *)view;
+ (UIImage *)qx_gradientColorImageFromColors:(NSArray*)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize;
/**
根据颜色生成UIImage对象
@param color color对象
@return UIImage 实例对象
*/
+ (instancetype)qx_imageWithColor:(UIColor *)color;
/**
把图片image对象的size 缩放到控件的实际大小
@param size 控件实际尺寸
@param fillColor 周围颜色
@return 新的image对象
*/
- (instancetype)qx_imageFitWithSize:(CGSize)size fillColor:(UIColor *)fillColor;
/**
把图片image对象处理成圆角
@param radius 圆角半径
@param corners 控制圆角的位置
@param fillColor 被裁减掉区域的颜色
@param zoomSize 缩放尺寸,应等于控件的尺寸
@return 新的image对象
*/
- (instancetype)qx_imageCornerWithRadius:(CGFloat)radius byRoundingCorners:(UIRectCorner)corners fillColor:(UIColor *)fillColor zoomSize:(CGSize)zoomSize;
/**
设置图片圆角
@param radius 圆角半径
@param fillColor 被裁减掉区域的颜色
@param zoomSize 缩放尺寸,应等于控件的尺寸
@return 新的image对象
*/
- (instancetype)qx_imageCornerWithRadius:(CGFloat)radius fillColor:(UIColor *)fillColor zoomSize:(CGSize)zoomSize;
/*
获取系统启动页的图片
*/
+ (instancetype)qx_getAppLauchImage;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,139 @@
//
// UIImage+QX.m
// QXLive
//
// Created by on 2025/4/28.
//
#import "UIImage+QX.h"
@implementation UIImage (QX)
//
- (NSData *)qx_compressImageQualityWithToByte:(NSInteger)maxLength {
CGFloat compression = 1;
NSData *data = UIImageJPEGRepresentation(self, compression);
if (data.length <= maxLength) {
return data;
}
compression = (CGFloat)maxLength / data.length;
return UIImageJPEGRepresentation(self, compression);
}
+ (UIImage *)qx_convertViewToImageWith:(UIView *)view {
//UIGraphicsBeginImageContextWithOptions(, , );
UIGraphicsBeginImageContextWithOptions(view.frame.size, YES, [UIScreen mainScreen].scale);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *imageRet = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageRet;
}
+ (UIImage *)qx_imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
+ (UIImage *)qx_gradientColorImageFromColors:(NSArray *)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize {
NSMutableArray *ar = [NSMutableArray array];
for (UIColor *c in colors) {
[ar addObject:(id)c.CGColor];
}
UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]);
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)ar, NULL);
CGPoint start;
CGPoint end;
switch (gradientType) {
case GradientTypeTopToBottom:
start = CGPointMake(0.0, 0.0);
end = CGPointMake(0.0, imgSize.height);
break;
case GradientTypeLeftToRight:
start = CGPointMake(0.0, 0.0);
end = CGPointMake(imgSize.width, 0.0);
break;
case GradientTypeUpleftToLowright:
start = CGPointMake(0.0, 0.0);
end = CGPointMake(imgSize.width, imgSize.height);
break;
case GradientTypeUprightToLowleft:
start = CGPointMake(imgSize.width, 0.0);
end = CGPointMake(0.0, imgSize.height);
break;
default: break;
}
CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
CGGradientRelease(gradient);
CGContextRestoreGState(context);
CGColorSpaceRelease(colorSpace);
UIGraphicsEndImageContext();
return image;
}
- (instancetype)qx_imageFitWithSize:(CGSize)size fillColor:(UIColor *)fillColor {
UIGraphicsBeginImageContextWithOptions(size, YES, 0);
CGRect rect = (CGRect) { CGPointZero, size };
[fillColor setFill];
UIRectFill(rect);
[self drawInRect:rect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (instancetype)qx_imageCornerWithRadius:(CGFloat)radius byRoundingCorners:(UIRectCorner)corners fillColor:(UIColor *)fillColor zoomSize:(CGSize)zoomSize {
UIGraphicsBeginImageContextWithOptions(zoomSize, YES, 0);
CGRect rect = (CGRect) { CGPointZero, zoomSize };
[fillColor setFill];
UIRectFill(rect);
CGSize size = CGSizeMake(radius, radius);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners cornerRadii:size];
[path addClip];
[self drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
return img;
}
- (instancetype)qx_imageCornerWithRadius:(CGFloat)radius fillColor:(UIColor *)fillColor zoomSize:(CGSize)zoomSize {
return [self qx_imageCornerWithRadius:radius byRoundingCorners:UIRectCornerAllCorners fillColor:fillColor zoomSize:zoomSize];
}
+ (instancetype)qx_getAppLauchImage {
CGSize viewSize = [UIScreen mainScreen].bounds.size;
NSString *viewOrienttation = @"Portrait";
NSString *launchImage = nil;
NSArray *imageDict = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"];
for (NSDictionary *dict in imageDict) {
if (launchImage) {
return [UIImage imageNamed:launchImage];
}
CGSize imageSize = CGSizeFromString(dict[@"UILaunchImageSize"]);
if (CGSizeEqualToSize(imageSize, viewSize) && [viewOrienttation isEqualToString:dict[@"UILaunchImageOrientation"]]) {
launchImage = dict[@"UILaunchImageName"];
}
}
if (!launchImage) {
// 6s
return [UIImage imageNamed:@"LaunchImage-800-667h"];
}
return [UIImage imageNamed:launchImage];
}
@end

View File

@@ -0,0 +1,158 @@
//
// UIView+QX.h
// QXLive
//
// Created by 启星 on 2025/4/27.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger , ShadowPathType) {
ShadowPathTop = 1,
ShadowPathBottom = 2,
ShadowPathLeft = 3,
ShadowPathRight = 4,
ShadowPathCommon = 5,
ShadowPathAround = 6,
};
typedef NS_ENUM(NSUInteger, SRGradientDirection) {
SRGradientDirectionTopToBottom, // 渐变色从上到下
SRGradientDirectionLeftToRight, // 渐变色从左到右
};
@interface UIView (QX)
/** 起点x坐标 */
@property (nonatomic, assign) CGFloat x;
/** 起点y坐标 */
@property (nonatomic, assign) CGFloat y;
/** 中心点x坐标 */
@property (nonatomic, assign) CGFloat centerX;
/** 中心点y坐标 */
@property (nonatomic, assign) CGFloat centerY;
/** 宽度 */
@property (nonatomic, assign) CGFloat width;
/** 高度 */
@property (nonatomic, assign) CGFloat height;
/** 顶部 */
@property (nonatomic, assign) CGFloat top;
/** 底部 */
@property (nonatomic, assign) CGFloat bottom;
/** 左边 */
@property (nonatomic, assign) CGFloat left;
/** 右边 */
@property (nonatomic, assign) CGFloat right;
/** size */
@property (nonatomic, assign) CGSize size;
/** origin */
@property (nonatomic, assign) CGPoint origin;
/**
快速给View添加4边阴影
参数:阴影透明度默认0
*/
- (void)addProjectionWithShadowOpacity:(CGFloat)shadowOpacity;
/**
快速给View添加4边阴影
*/
- (void)addShadowWithColor:(UIColor*)color radius:(CGFloat)radius;
- (void)addShadowWithColor:(UIColor*)color radius:(CGFloat)radius frame:(CGRect)frame;
/**
快速给View添加4边框
参数:边框宽度
*/
- (void)addBorderWithWidth:(CGFloat)width;
/**
快速给View添加4边框
width:边框宽度
borderColor:边框颜色
*/
- (void)addBorderWithWidth:(CGFloat)width borderColor:(UIColor *)borderColor;
/**
快速给View添加圆角
参数:圆角半径
*/
- (void)addRoundedCornersWithRadius:(CGFloat)radius;
/**
快速给View添加圆角
radius:圆角半径
corners:且那几个角
类型共有以下几种:
typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
UIRectCornerTopLeft,
UIRectCornerTopRight ,
UIRectCornerBottomLeft,
UIRectCornerBottomRight,
UIRectCornerAllCorners
};
使用案例:[self.mainView addRoundedCornersWithRadius:10 byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight]; // 切除了左下 右下
*/
- (void)addRoundedCornersWithRadius:(CGFloat)radius byRoundingCorners:(UIRectCorner)corners;
/************** 按自身Bounds计算 *************/
- (void)setTopToBottomGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors;
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors;
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint;
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors roundedCorners:(CGFloat)radius;
- (void)setAroundRoundedCorners:(CGFloat)radius;
- (void)setTopRoundedCorners:(CGFloat)radius;
- (void)setBottomRoundedCorners:(CGFloat)radius;
- (void)setLeftRoundedCorners:(CGFloat)radius;
/************* 按Frame计算 *************/
/** 设置渐变色 */
- (void)setViewBackgroundColorWithColorArray:(NSArray *)colorArray scaleArray:(NSArray * __nullable)scaleArray direction:(SRGradientDirection)direction;
/** 仅设置由上至下的渐变色 */
- (void)setTopToBottomGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors frame:(CGRect)frame;
/** 仅设置由左至右的渐变色 */
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors frame:(CGRect)frame;
/** 仅设置自定义起始和结束位置的渐变色 */
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint frame:(CGRect)frame;
/** 设置由左至右的圆角渐变色 */
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors roundedCorners:(CGFloat)radius frame:(CGRect)frame;
/** 仅设置裁剪 */
- (void)setAroundRoundedCorners:(CGFloat)radius frame:(CGRect)frame;
/** 仅设置顶部角裁剪 */
- (void)setTopRoundedCorners:(CGFloat)radius frame:(CGRect)frame;
/** 仅设置底部角裁剪 */
- (void)setBottomRoundedCorners:(CGFloat)radius frame:(CGRect)frame;
/** 仅设置左侧角裁剪 */
- (void)setLeftRoundedCorners:(CGFloat)radius frame:(CGRect)frame;
/**
给UIView添加阴影
@param shadowColor 阴影颜色
@param shadowOpacity 阴影透明度 默认0
@param shadowRadius 阴影半径 也就是阴影放射程度 默认3
@param shadowPathType 阴影方向
@param shadowPathWidth 阴影放射g宽度
*/
- (void)setViewShadowPathWithColor:(UIColor *)shadowColor shadowOpacity:(CGFloat)shadowOpacity shadowRadius:(CGFloat)shadowRadius shadowPathType:(ShadowPathType)shadowPathType shadowPathWidth:(CGFloat)shadowPathWidth;
- (void)addTapBlock:(void(^)(id obj))tapAction;
- (UIViewController *)viewController;
- (UINavigationController *)navigationController;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,508 @@
//
// UIView+QX.m
// QXLive
//
// Created by on 2025/4/27.
//
#import "UIView+QX.h"
static const void* tagValue = &tagValue;
@implementation UIView (QX)
- (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;
}
- (CGFloat)x {
return self.frame.origin.x;
}
- (CGFloat)y {
return self.frame.origin.y;
}
- (void)setCenterX:(CGFloat)centerX {
CGPoint center = self.center;
center.x = centerX;
self.center = center;
}
- (CGFloat)centerX {
return self.center.x;
}
- (void)setCenterY:(CGFloat)centerY{
CGPoint center = self.center;
center.y = centerY;
self.center = center;
}
- (CGFloat)centerY {
return self.center.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;
}
- (CGFloat)height {
return self.frame.size.height;
}
- (CGFloat)width {
return self.frame.size.width;
}
- (void)setSize:(CGSize)size {
CGRect frame = self.frame;
frame.size = size;
self.frame = frame;
}
- (CGSize)size {
return self.frame.size;
}
- (void)setOrigin:(CGPoint)origin {
CGRect frame = self.frame;
frame.origin = origin;
self.frame = frame;
}
- (CGPoint)origin {
return self.frame.origin;
}
- (CGFloat)top {
return self.frame.origin.y;
}
- (void)setTop:(CGFloat)top {
CGRect frame = self.frame;
frame.origin.y = top;
self.frame = frame;
}
- (CGFloat)left {
return self.frame.origin.x;
}
- (void)setLeft:(CGFloat)left {
CGRect frame = self.frame;
frame.origin.x = left;
self.frame = frame;
}
- (CGFloat)bottom {
return self.frame.size.height + self.frame.origin.y;
}
- (void)setBottom:(CGFloat)bottom {
CGRect frame = self.frame;
frame.origin.y = bottom - frame.size.height;
self.frame = frame;
}
- (CGFloat)right {
return self.frame.size.width + self.frame.origin.x;
}
- (void)setRight:(CGFloat)right {
CGRect frame = self.frame;
frame.origin.x = right - frame.size.width;
self.frame = frame;
}
#pragma mark -
- (void)addProjectionWithShadowOpacity:(CGFloat)shadowOpacity {
self.layer.shadowColor = [UIColor blackColor].CGColor;//shadowColor
self.layer.shadowOffset = CGSizeMake(0,0);//shadowOffset,x2y6(0, -3),shadowRadius使
self.layer.shadowOpacity = shadowOpacity;//0
self.layer.shadowRadius = 3;//3
}
- (void)addShadowWithColor:(UIColor*)color radius:(CGFloat)radius{
CALayer *subLayer = [CALayer layer];
subLayer.frame = self.frame;
subLayer.cornerRadius = radius;
subLayer.masksToBounds = NO;
subLayer.backgroundColor = color.CGColor;
subLayer.shadowColor = color.CGColor;//shadowColor
subLayer.shadowOffset = CGSizeMake(0,2);
subLayer.shadowOpacity = 0.5;//0
subLayer.shadowRadius = radius;//3
[self.layer insertSublayer:subLayer below:self.layer];
}
- (void)addShadowWithColor:(UIColor*)color radius:(CGFloat)radius frame:(CGRect)frame{
CALayer *subLayer = [CALayer layer];
subLayer.frame = frame;
subLayer.cornerRadius = radius;
subLayer.masksToBounds = YES;
subLayer.backgroundColor = color.CGColor;
subLayer.shadowColor = color.CGColor;//shadowColor
subLayer.shadowOffset = CGSizeMake(0,-3);
subLayer.shadowOpacity = 0.5;//0
subLayer.shadowRadius = radius;//3
[self.layer insertSublayer:subLayer below:self.layer];
}
- (void)addBorderWithWidth:(CGFloat)width {
self.layer.borderWidth = width;
self.layer.borderColor = [UIColor blackColor].CGColor;
}
- (void)addBorderWithWidth:(CGFloat)width borderColor:(UIColor *)borderColor {
self.layer.borderWidth = width;
self.layer.borderColor = borderColor.CGColor;
}
- (void)addRoundedCornersWithRadius:(CGFloat)radius {
self.layer.cornerRadius = radius;
self.layer.masksToBounds = YES;
}
- (void)addRoundedCornersWithRadius:(CGFloat)radius byRoundingCorners:(UIRectCorner)corners{
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setTopToBottomGradientBackgroundWithColors:(NSArray<UIColor *> *)colors {
[self setGradientBackgroundWithColors:colors startPoint:CGPointMake(0.5, 0) endPoint:CGPointMake(0.5, 1)];
}
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *)colors {
[self setGradientBackgroundWithColors:colors startPoint:CGPointMake(0, 0.5) endPoint:CGPointMake(1, 0.5)];
}
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colorsM;
gradientLayer.locations = @[@0, @1];
gradientLayer.startPoint = startPoint;
gradientLayer.endPoint = endPoint;
gradientLayer.frame = self.bounds;
// [self.layer addSublayer:gradientLayer];
//layoutCAGradientLayer
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAGradientLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *)colors roundedCorners:(CGFloat)radius {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colorsM;
gradientLayer.locations = @[@0, @1];
gradientLayer.startPoint = CGPointMake(0, 0.5);
gradientLayer.endPoint = CGPointMake(1, 0.5);
gradientLayer.frame = self.bounds;
gradientLayer.cornerRadius = radius;
gradientLayer.masksToBounds = YES;
//layoutCAGradientLayer
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAGradientLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)setAroundRoundedCorners:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setTopRoundedCorners:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setBottomRoundedCorners:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setLeftRoundedCorners:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
#pragma mark - Frame
- (void)setTopToBottomGradientBackgroundWithColors:(NSArray<UIColor *> *)colors frame:(CGRect)frame {
[self setGradientBackgroundWithColors:colors startPoint:CGPointMake(0.5, 0) endPoint:CGPointMake(0.5, 1) frame:frame];
}
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *)colors frame:(CGRect)frame {
[self setGradientBackgroundWithColors:colors startPoint:CGPointMake(0, 0.5) endPoint:CGPointMake(1, 0.5) frame:frame];
}
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint frame:(CGRect)frame {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colorsM;
gradientLayer.locations = @[@0, @1];
gradientLayer.startPoint = startPoint;
gradientLayer.endPoint = endPoint;
gradientLayer.frame = frame;
// [self.layer addSublayer:gradientLayer];
//layoutCAGradientLayer
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAGradientLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *)colors roundedCorners:(CGFloat)radius frame:(CGRect)frame {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colorsM;
gradientLayer.locations = @[@0, @1];
gradientLayer.startPoint = CGPointMake(0, 0.5);
gradientLayer.endPoint = CGPointMake(1, 0.5);
gradientLayer.frame = frame;
gradientLayer.cornerRadius = radius;
gradientLayer.masksToBounds = YES;
//layoutCAGradientLayer
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAGradientLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)setAroundRoundedCorners:(CGFloat)radius frame:(CGRect)frame {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = frame;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setTopRoundedCorners:(CGFloat)radius frame:(CGRect)frame {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = frame;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setBottomRoundedCorners:(CGFloat)radius frame:(CGRect)frame {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = frame;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setLeftRoundedCorners:(CGFloat)radius frame:(CGRect)frame {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = frame;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setViewShadowPathWithColor:(UIColor *)shadowColor shadowOpacity:(CGFloat)shadowOpacity shadowRadius:(CGFloat)shadowRadius shadowPathType:(ShadowPathType)shadowPathType shadowPathWidth:(CGFloat)shadowPathWidth {
self.layer.masksToBounds = NO;//NO
self.layer.shadowColor = shadowColor.CGColor;//
self.layer.shadowOpacity = shadowOpacity;// 0
self.layer.shadowOffset = CGSizeZero;//shadowOffset(0, -3),shadowRadius使
self.layer.shadowRadius = shadowRadius;//3
CGRect shadowRect = CGRectZero;
CGFloat originX,originY,sizeWith,sizeHeight;
originX = 0;
originY = 0;
sizeWith = self.bounds.size.width;
sizeHeight = self.bounds.size.height;
if (shadowPathType == ShadowPathTop) {
shadowRect = CGRectMake(originX, originY-shadowPathWidth/2, sizeWith, shadowPathWidth);
}else if (shadowPathType == ShadowPathBottom){
shadowRect = CGRectMake(originY, sizeHeight-shadowPathWidth/2, sizeWith, shadowPathWidth);
}else if (shadowPathType == ShadowPathLeft){
shadowRect = CGRectMake(originX-shadowPathWidth/2, originY, shadowPathWidth, sizeHeight);
}else if (shadowPathType == ShadowPathRight){
shadowRect = CGRectMake(sizeWith-shadowPathWidth/2, originY, shadowPathWidth, sizeHeight);
}else if (shadowPathType == ShadowPathCommon){
shadowRect = CGRectMake(originX-shadowPathWidth/2, 2, sizeWith+shadowPathWidth, sizeHeight+shadowPathWidth/2);
}else if (shadowPathType == ShadowPathAround){
shadowRect = CGRectMake(originX-shadowPathWidth/2, originY-shadowPathWidth/2, sizeWith+shadowPathWidth, sizeHeight+shadowPathWidth);
}
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:shadowRect];
self.layer.shadowPath = bezierPath.CGPath;//
}
- (void)setViewBackgroundColorWithColorArray:(NSArray *)colorArray scaleArray:(NSArray * __nullable)scaleArray direction:(SRGradientDirection)direction {
/*
layoutIfNeededlayoutSubviews
setNeedsLayoutlayoutSubviewsrunloop
runloop:
[self setNeedsLayout];
[self layoutIfNeeded];
*/
[self setNeedsLayout];
[self layoutIfNeeded];
CAGradientLayer *gradinentlayer = [CAGradientLayer layer];
if (direction == SRGradientDirectionLeftToRight) {
gradinentlayer.startPoint = CGPointMake(0, 0);
gradinentlayer.endPoint = CGPointMake(1.0, 0);
}else {
gradinentlayer.startPoint = CGPointMake(0, 0);
gradinentlayer.endPoint = CGPointMake(0, 1.0);
}
NSMutableArray *CGColorArray = [NSMutableArray new];
for (UIColor *color in colorArray) {
[CGColorArray addObject:(__bridge id)color.CGColor];
}
if (!scaleArray) {
}else {
gradinentlayer.locations = scaleArray;
}
gradinentlayer.colors = CGColorArray;
gradinentlayer.frame = self.bounds;
[self.layer addSublayer:gradinentlayer];
}
- (void)tap{
if (self.tapAction) {
self.tapAction(self);
}
}
- (void)addTapBlock:(void(^)(id obj))tapAction{
self.tapAction = tapAction;
if (![self gestureRecognizers]) {
self.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
[self addGestureRecognizer:tap];
}
}
-(void)setTapAction:(void (^)(id))tapAction {
objc_setAssociatedObject(self, tagValue, tapAction, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(void (^)(id))tapAction {
return objc_getAssociatedObject(self, tagValue);
}
- (UIViewController *)viewController {
id nextResponder = [self nextResponder];
while (nextResponder != nil) {
if ([nextResponder isKindOfClass:[UIViewController class]]) {
UIViewController *vc = (UIViewController *)nextResponder;
return vc;
}
nextResponder = [nextResponder nextResponder];
}
return nil;
}
- (UINavigationController *)navigationController {
id nextResponder = [self nextResponder];
while (nextResponder != nil) {
if ([nextResponder isKindOfClass:[UINavigationController class]]) {
UINavigationController *vc = (UINavigationController *)nextResponder;
return vc;
}
nextResponder = [nextResponder nextResponder];
}
return nil;
}
@end