Files
featherVoice/QXLive/Tools/Category/NSString+QX.m
2025-11-21 16:17:05 +08:00

432 lines
15 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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:@"%.2fw",(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);
double hourT = second%(60*60*24)/3600.0;
NSInteger hour = (NSInteger)ceil(hourT);
return [NSString stringWithFormat:@"%ld天%ld小时",day,hour];
}
// 方法2更严谨的实现包含边界条件处理
+ (NSInteger)convertTimestampToHoursWithPrecision:(long long)endTime {
NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];
// 将秒转换为毫秒
long long milliseconds = (long long)(currentTime);
NSInteger timestamp = endTime - currentTime;
if (timestamp <= 0) {
return 0;
}
// 处理极小的时间值小于1秒
if (timestamp < 1) {
return 1; // 即使小于1秒也按1小时计算
}
// 计算小时数
double hours = timestamp / 3600.0;
// 使用ceil函数向上取整
NSInteger roundedHours = (NSInteger)ceil(hours);
// 确保至少为1小时
return MAX(1, roundedHours);
}
@end