374 lines
12 KiB
Objective-C
374 lines
12 KiB
Objective-C
//
|
||
// XSHelper.m
|
||
// nochange
|
||
//
|
||
// Created by mac on 2024/10/15.
|
||
//
|
||
|
||
#import <Foundation/Foundation.h>
|
||
#import "XSHelper.h"
|
||
|
||
|
||
|
||
NSError* XSErrorFromException(NSException* exception) {
|
||
NSMutableDictionary* userInfo = [NSMutableDictionary dictionary];
|
||
|
||
[userInfo setObject:exception.name forKey:NSLocalizedFailureReasonErrorKey];
|
||
[userInfo setObject:exception.reason forKey:NSLocalizedDescriptionKey];
|
||
|
||
if (exception.userInfo) {
|
||
[userInfo addEntriesFromDictionary:exception.userInfo];
|
||
}
|
||
|
||
return [NSError errorWithDomain:@"ExceptionDomain" code:-1 userInfo:userInfo];
|
||
}
|
||
|
||
// mach_absolute_time()
|
||
double XSCalculateElapsedTime(uint64_t start, uint64_t end) {
|
||
static mach_timebase_info_data_t timebaseInfo;
|
||
if (timebaseInfo.denom == 0) {
|
||
mach_timebase_info(&timebaseInfo);
|
||
}
|
||
|
||
uint64_t elapsed = end - start;
|
||
uint64_t nanos = elapsed * timebaseInfo.numer / timebaseInfo.denom;
|
||
return (double)nanos / NSEC_PER_MSEC;
|
||
}
|
||
// 小数位保留
|
||
float XSRoundToDecimal(float value, int decimalPlaces) {
|
||
float multiplier = powf(10.0f, decimalPlaces);
|
||
return roundf(value * multiplier) / multiplier;
|
||
}
|
||
|
||
void XSAfterNext(int sec, NextCallback next) {
|
||
// 或使用GCD timer
|
||
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
|
||
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, sec * NSEC_PER_SEC, 0);
|
||
dispatch_source_set_event_handler(timer, ^{
|
||
// 延迟操作
|
||
next();
|
||
});
|
||
dispatch_resume(timer);
|
||
}
|
||
|
||
|
||
|
||
@interface XSHelper()
|
||
{
|
||
|
||
}
|
||
|
||
@end
|
||
|
||
|
||
@implementation XSHelper
|
||
|
||
+ (int)random:(int)min and:(int)max {
|
||
return min + arc4random_uniform(max - min + 1);
|
||
}
|
||
|
||
+ (NSData *)str2Data:(NSString *)str {
|
||
return [str dataUsingEncoding:NSUTF8StringEncoding];
|
||
}
|
||
+ (NSString *)data2str: (NSData *) data {
|
||
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];;
|
||
}
|
||
+ (BOOL) strIsEmpty: (NSString *)str {
|
||
if (str == nil) {
|
||
return YES;
|
||
}
|
||
if ([str isEqual:[NSNull null]]) {
|
||
return YES;
|
||
}
|
||
if ([str length] <=0) {
|
||
return YES;
|
||
}
|
||
return NO;
|
||
}
|
||
+ (bool) isMatch: (NSString *)pattern test:(NSString *)test {
|
||
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
|
||
options:0
|
||
error:nil];
|
||
NSUInteger numberOfMatches = [regex numberOfMatchesInString:test
|
||
options:0
|
||
range:NSMakeRange(0, [test length])];
|
||
return numberOfMatches > 0;
|
||
}
|
||
|
||
+ (NSDictionary *) json2Dictionary: (NSString *)json {
|
||
if(json == nil || [json isEqual:[NSNull null]] || [json isEqual:@""]) {
|
||
return @{};
|
||
}
|
||
return [XSHelper jsonData2Dictionary:[XSHelper str2Data:json]];
|
||
}
|
||
|
||
+ (NSDictionary *) jsonData2Dictionary: (NSData *)data {
|
||
NSError *jsonError;
|
||
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data
|
||
options:NSJSONReadingMutableContainers
|
||
error:&jsonError];
|
||
if (jsonError) {
|
||
NSLog(@"json2dic error: %@", jsonError);
|
||
}
|
||
return dic;
|
||
}
|
||
+ (NSData *)obj2JsonData:(id)obj {
|
||
NSError *error;
|
||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:obj
|
||
options:NSJSONWritingPrettyPrinted
|
||
error:&error];
|
||
|
||
return jsonData;
|
||
}
|
||
|
||
+ (NSString *)dic2Json: (NSDictionary *)dict {
|
||
NSData *jsonData = [XSHelper obj2JsonData:dict];
|
||
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||
}
|
||
|
||
+ (NSString *)readFileText:(NSString *)path {
|
||
NSError *error = nil;
|
||
NSString *content = [NSString stringWithContentsOfFile:path
|
||
encoding:NSUTF8StringEncoding
|
||
error:&error];
|
||
if (error) {
|
||
NSLog(@"XS- Helper readFileText Error: %@", error.localizedDescription);
|
||
return nil;
|
||
}
|
||
return content;
|
||
}
|
||
+ (BOOL) saveFile: (NSString *) path data: (NSData *)data {
|
||
return [data writeToFile:path atomically:YES];
|
||
}
|
||
|
||
+ (BOOL) saveFile: (NSString *) path text: (NSString *)text {
|
||
NSData *data = [XSHelper str2Data:text];
|
||
return [XSHelper saveFile:path data:data];
|
||
}
|
||
|
||
+ (void) rmFiles: (NSString *) path {
|
||
NSFileManager *man = [NSFileManager defaultManager];
|
||
if ([man fileExistsAtPath:path]) {
|
||
NSArray *dirArray = [man contentsOfDirectoryAtPath:path error:nil];
|
||
for (NSString * str in dirArray) {
|
||
NSString *subPath = [path stringByAppendingPathComponent:str];
|
||
NSLog(@"XS- del file:%@", subPath);
|
||
NSError *error;
|
||
[man removeItemAtPath:subPath error:&error];
|
||
if (error) {
|
||
NSLog(@"XS- Error clearing: %@,,%@", path, error.localizedDescription);
|
||
}
|
||
}
|
||
} else {
|
||
NSLog(@"XS- %@ not found", path);
|
||
}
|
||
|
||
}
|
||
|
||
+ (NSNumber *)str2num:(NSString *)str {
|
||
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
|
||
f.numberStyle = NSNumberFormatterDecimalStyle;
|
||
NSNumber *myNumber = [f numberFromString:str];
|
||
return myNumber;
|
||
}
|
||
+ (NSString *)replaceStr: (NSString *)text oldStr:(NSString *)oldStr newStr: (NSString *)newStr {
|
||
return [text stringByReplacingOccurrencesOfString:oldStr withString:newStr];
|
||
}
|
||
|
||
+ (void)replaceMulStr: (NSMutableString *)text oldStr:(NSString *)oldStr newStr: (NSString *)newStr {
|
||
[text replaceOccurrencesOfString:oldStr
|
||
withString:newStr
|
||
options:NSLiteralSearch
|
||
range:NSMakeRange(0, [text length])];
|
||
}
|
||
|
||
+ (NSString *)replaceStr: (NSString *)text regex:(NSString *)regex newStr:(NSString *)newStr {
|
||
NSError *error = nil;
|
||
NSRegularExpression *nsregex = [NSRegularExpression regularExpressionWithPattern:regex
|
||
options:0
|
||
error:&error];
|
||
if (!error) {
|
||
NSString *newString = [nsregex stringByReplacingMatchesInString:text
|
||
options:0
|
||
range:NSMakeRange(0, [text length])
|
||
withTemplate:@"YYYY-MM-DD"];
|
||
NSLog(@"%@", newString); // 输出: The date is YYYY-MM-DD
|
||
return newString;
|
||
}
|
||
return text;
|
||
}
|
||
|
||
/// 编码:A => QQ==
|
||
+ (NSString *)base64Encode:(NSString *)string {
|
||
// 1. 将字符串转换成二进制数据
|
||
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||
|
||
// 2. 利用 iOS 7.0 的方法,直接 base64 编码
|
||
return [data base64EncodedStringWithOptions:0];
|
||
}
|
||
|
||
/// 解码:QQ== => A
|
||
+ (NSString *)base64Decode:(NSString *)string {
|
||
// 1. 将base64编码后的字符串,解码成二进制数据
|
||
NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
|
||
|
||
// 2. 返回解码后的字符串
|
||
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||
}
|
||
|
||
//-- img
|
||
+ (UIImage *) imageFromFile:(NSString *) path {
|
||
return [UIImage imageWithContentsOfFile:path];
|
||
}
|
||
+ (NSString *)base64StringFromJpgImage:(UIImage *)image {
|
||
NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
|
||
NSString *base64String = [imageData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
|
||
return base64String;
|
||
}
|
||
|
||
+ (UIImage *)imageFromBase64String:(NSString *)base64String {
|
||
NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64String options:NSDataBase64DecodingIgnoreUnknownCharacters];
|
||
return [UIImage imageWithData:imageData];
|
||
}
|
||
+ (UIImage *)png2jpg:(UIImage *)png {
|
||
NSData *jpgdata = UIImageJPEGRepresentation(png, 0.8);
|
||
return [UIImage imageWithData:jpgdata];
|
||
}
|
||
|
||
|
||
|
||
|
||
+ (double) getCurTime {
|
||
// 获取当前日期和时间
|
||
NSDate *now = [NSDate date];
|
||
return [now timeIntervalSince1970];
|
||
}
|
||
|
||
|
||
// Vision
|
||
+ (void)performOCROnImage:(UIImage *)image callback:(MyOCRCallback)callback {
|
||
NSLog(@"XS- performOCROnImage");
|
||
if (!image) {
|
||
NSLog(@"XS- No image provided");
|
||
callback(@"");
|
||
return;
|
||
}
|
||
|
||
// 在后台队列中执行 OCR
|
||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
|
||
// 创建 VNImageRequestHandler
|
||
VNImageRequestHandler *imageRequestHandler = [[VNImageRequestHandler alloc] initWithCIImage:[CIImage imageWithCGImage:image.CGImage]
|
||
options:@{}];
|
||
|
||
// 创建文本识别请求
|
||
VNRecognizeTextRequest *textRecognitionRequest = [[VNRecognizeTextRequest alloc] initWithCompletionHandler:^(VNRequest * _Nonnull request, NSError * _Nullable error) {
|
||
if (error) {
|
||
NSLog(@"XS- Error: %@", error.localizedDescription);
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
callback(@"");
|
||
});
|
||
return;
|
||
}
|
||
|
||
NSMutableString *recognizedText = [NSMutableString string];
|
||
for (VNRecognizedTextObservation *observation in request.results) {
|
||
VNRecognizedText *topCandidate = [observation topCandidates:1].firstObject;
|
||
if (topCandidate) {
|
||
[recognizedText appendFormat:@"%@\n", topCandidate.string];
|
||
}
|
||
}
|
||
|
||
NSLog(@"XS- Recognized Text:\n%@", recognizedText);
|
||
|
||
// 在主线程上处理结果
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
callback(recognizedText);
|
||
});
|
||
}];
|
||
|
||
// 设置识别语言(可选)
|
||
textRecognitionRequest.recognitionLanguages = @[@"en-US", @"zh-Hans"];
|
||
|
||
// 执行请求
|
||
NSError *error;
|
||
[imageRequestHandler performRequests:@[textRecognitionRequest] error:&error];
|
||
if (error) {
|
||
NSLog(@"XS- Error performing OCR request: %@", error.localizedDescription);
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
callback(@"");
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
@end
|
||
|
||
|
||
|
||
@implementation NSData (AES)
|
||
|
||
- (NSData *)aesEncrypt: (NSString *)key iv:(NSString *)iv {
|
||
return [self AES128operation:kCCEncrypt key:key iv:iv];
|
||
}
|
||
|
||
- (NSData *)aesDecrypt: (NSString *)key iv:(NSString *)iv {
|
||
return [self AES128operation:kCCDecrypt key:key iv:iv];
|
||
}
|
||
|
||
- (NSData *)AES128operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv
|
||
{
|
||
char keyPtr[kCCKeySizeAES128 + 1];
|
||
bzero(keyPtr, sizeof(keyPtr));
|
||
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
|
||
|
||
// IV
|
||
char ivPtr[kCCBlockSizeAES128 + 1];
|
||
bzero(ivPtr, sizeof(ivPtr));
|
||
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
|
||
|
||
size_t bufferSize = [self length] + kCCBlockSizeAES128;
|
||
void *buffer = malloc(bufferSize);
|
||
size_t numBytesEncrypted = 0;
|
||
|
||
|
||
|
||
CCCryptorStatus cryptorStatus = CCCrypt(operation, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
|
||
keyPtr, kCCKeySizeAES128,
|
||
ivPtr,
|
||
self.bytes, self.length,
|
||
buffer, bufferSize,
|
||
&numBytesEncrypted);
|
||
|
||
if(cryptorStatus == kCCSuccess) {
|
||
NSLog(@"Success");
|
||
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
|
||
} else {
|
||
NSLog(@"Error");
|
||
}
|
||
|
||
free(buffer);
|
||
return nil;
|
||
}
|
||
|
||
@end
|
||
|
||
|
||
@implementation NSString (AES)
|
||
|
||
- (NSString *)aesEncrypt: (NSString *)key iv:(NSString *)iv {
|
||
NSData *data = [[XSHelper str2Data:self] aesEncrypt:key iv:iv];
|
||
return [data base64EncodedStringWithOptions:0];
|
||
}
|
||
|
||
- (NSString *)aesDecrypt: (NSString *)key iv:(NSString *)iv {
|
||
NSData *data = [[NSData alloc] initWithBase64EncodedString:self options:0];
|
||
NSData *dec = [data aesDecrypt:key iv:iv];
|
||
return [XSHelper data2str:dec];
|
||
}
|
||
|
||
@end
|
||
|
||
|
||
|