406 lines
14 KiB
Objective-C
406 lines
14 KiB
Objective-C
//
|
|
// 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);
|
|
NSInteger hour = second%(60*60*24)/(60*60);
|
|
return [NSString stringWithFormat:@"%ld天%ld小时",day,hour];
|
|
}
|
|
@end
|