[M] sync n3

This commit is contained in:
2024-12-09 16:54:19 +08:00
parent c90bbe86e7
commit 05331e6286
845 changed files with 6138 additions and 1307 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b37051d2565fd43dfba2108cdecdd66f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
#import <Foundation/Foundation.h>
@interface NSData (TDGzip)
+ (NSData *)td_gzipData:(NSData *)dataa;
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 10aa5f70d373b47bda4b3c6615c5beaf
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
#import "NSData+TDGzip.h"
#import "zlib.h"
#import "TDLogging.h"
@implementation NSData (TDGzip)
+ (NSData *)td_gzipData:(NSData *)dataa {
if (!dataa || [dataa length] == 0) {
TDLogDebug(@"gzip error, return nil ");
return nil;
}
z_stream zlibStreamStruct;
zlibStreamStruct.zalloc = Z_NULL;
zlibStreamStruct.zfree = Z_NULL;
zlibStreamStruct.opaque = Z_NULL;
zlibStreamStruct.total_out = 0;
zlibStreamStruct.next_in = (Bytef *)[dataa bytes];
zlibStreamStruct.avail_in = (uInt)[dataa length];
int initError = deflateInit2(&zlibStreamStruct, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY);
if (initError != Z_OK) return nil;
NSMutableData *gzipData = [NSMutableData dataWithLength:[dataa length] * 1.01 + 21];
int deflateStatus;
do {
zlibStreamStruct.next_out = [gzipData mutableBytes] + zlibStreamStruct.total_out;
zlibStreamStruct.avail_out = (uInt)([gzipData length] - zlibStreamStruct.total_out);
deflateStatus = deflate(&zlibStreamStruct, Z_FINISH);
} while (deflateStatus == Z_OK);
if (deflateStatus != Z_STREAM_END) return nil;
deflateEnd(&zlibStreamStruct);
[gzipData setLength:zlibStreamStruct.total_out];
return gzipData;
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 175f559a1edeb4a7f9409f67ea1aa491
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
//
// NSDate+TAFormat.h
// ThinkingSDK
//
// Created by Yangxiongon 2022/6/19.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDate (TAFormat)
/// input the time zone
/// @param timeZone timeZone
- (double)ta_timeZoneOffset:(NSTimeZone *)timeZone;
/// Format NSDate
/// @param timeZone timeZone
/// @param formatString formatString
- (NSString *)ta_formatWithTimeZone:(NSTimeZone *)timeZone formatString:(NSString *)formatString;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: ce52f25fa7ca74bc0b03fd1942b90c37
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
//
// NSDate+TAFormat.m
// ThinkingSDK
//
// Created by Yangxiongon 2022/6/19.
//
#import "NSDate+TAFormat.h"
@implementation NSDate (TAFormat)
- (double)ta_timeZoneOffset:(NSTimeZone *)timeZone {
if (!timeZone) {
return 0;
}
NSInteger sourceGMTOffset = [timeZone secondsFromGMTForDate:self];
return (double)(sourceGMTOffset/3600.0);
}
- (NSString *)ta_formatWithTimeZone:(NSTimeZone *)timeZone formatString:(NSString *)formatString {
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init];
timeFormatter.dateFormat = formatString;
timeFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
timeFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
timeFormatter.timeZone = timeZone;
return [timeFormatter stringFromDate:self];
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 52537316e66524679b1b24f6c6d62f99
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
//
// NSDictionary+TDJsonOutput.h
// ThinkingSDK
//
// Created by huangdiao on 2021/3/18.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDictionary (TDJsonOutput)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 6dcaf30c4b0eb430b8244e993dc551a4
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
//
// NSDictionary+TDJsonOutput.m
// ThinkingSDK
//
// Created by huangdiao on 2021/3/18.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import "NSDictionary+TDJsonOutput.h"
@implementation NSDictionary (TDJsonOutput)
- (NSString *)descriptionWithLocale:(nullable id)locale {
if ([NSJSONSerialization isValidJSONObject:self]) {
NSString *output = nil;
@try {
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:nil];
output = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
output = [output stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
}
@catch (NSException *exception) {
output = self.description;
}
return output;
} else {
return self.description;
}
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 53a00c2672fe24a528f94803871d160f
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
//
// NSObject+TDUtil.h
// ThinkingSDK
//
// Created by wwango on 2021/10/18.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSObject (TDUtil)
+ (id)performSelector:(SEL)selector onTarget:(id)target withArguments:(NSArray *)arguments;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 1ab5993d5baaf4457b1b7f166e9bbbe1
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,185 @@
//
// NSObject+TDUtil.m
// ThinkingSDK
//
// Created by wwango on 2021/10/18.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import "NSObject+TDUtil.h"
#import <CoreGraphics/CoreGraphics.h>
#if TARGET_OS_IOS
#import <UIKit/UIKit.h>
#endif
@implementation NSObject (TDUtil)
+ (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type
{
// CASE marcro inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html
#define CASE(ctype, selectorpart) \
if(strcmp(type, @encode(ctype)) == 0) { \
return [NSNumber numberWith ## selectorpart: *(ctype *)pointer]; \
}
CASE(BOOL, Bool);
CASE(unsigned char, UnsignedChar);
CASE(short, Short);
CASE(unsigned short, UnsignedShort);
CASE(int, Int);
CASE(unsigned int, UnsignedInt);
CASE(long, Long);
CASE(unsigned long, UnsignedLong);
CASE(long long, LongLong);
CASE(unsigned long long, UnsignedLongLong);
CASE(float, Float);
CASE(double, Double);
#undef CASE
NSValue *value = nil;
@try {
value = [NSValue valueWithBytes:pointer objCType:type];
} @catch (NSException *exception) {
// Certain type encodings are not supported by valueWithBytes:objCType:. Just fail silently if an exception is thrown.
}
return value;
}
+ (BOOL)isTollFreeBridgedValue:(id)value forCFType:(const char *)typeEncoding
{
// See https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/Toll-FreeBridgin/Toll-FreeBridgin.html
#define CASE(cftype, foundationClass) \
if(strcmp(typeEncoding, @encode(cftype)) == 0) { \
return [value isKindOfClass:[foundationClass class]]; \
}
CASE(CFArrayRef, NSArray);
CASE(CFAttributedStringRef, NSAttributedString);
CASE(CFCalendarRef, NSCalendar);
CASE(CFCharacterSetRef, NSCharacterSet);
CASE(CFDataRef, NSData);
CASE(CFDateRef, NSDate);
CASE(CFDictionaryRef, NSDictionary);
CASE(CFErrorRef, NSError);
CASE(CFLocaleRef, NSLocale);
CASE(CFMutableArrayRef, NSMutableArray);
CASE(CFMutableAttributedStringRef, NSMutableAttributedString);
CASE(CFMutableCharacterSetRef, NSMutableCharacterSet);
CASE(CFMutableDataRef, NSMutableData);
CASE(CFMutableDictionaryRef, NSMutableDictionary);
CASE(CFMutableSetRef, NSMutableSet);
CASE(CFMutableStringRef, NSMutableString);
CASE(CFNumberRef, NSNumber);
CASE(CFReadStreamRef, NSInputStream);
CASE(CFRunLoopTimerRef, NSTimer);
CASE(CFSetRef, NSSet);
CASE(CFStringRef, NSString);
CASE(CFTimeZoneRef, NSTimeZone);
CASE(CFURLRef, NSURL);
CASE(CFWriteStreamRef, NSOutputStream);
#undef CASE
return NO;
}
+ (id)performSelector:(SEL)selector onTarget:(id)target withArguments:(NSArray *)arguments{
if ([target respondsToSelector:selector]) {
NSMethodSignature *signature = [target methodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:target];
[invocation setSelector:selector];
[invocation retainArguments];
// Always self and _cmd
NSUInteger numberOfArguments = [signature numberOfArguments];
for (NSUInteger argumentIndex = 2; argumentIndex < numberOfArguments; argumentIndex++) {
NSUInteger argumentsArrayIndex = argumentIndex - 2;
id argumentObject = [arguments count] > argumentsArrayIndex ? [arguments objectAtIndex:argumentsArrayIndex] : nil;
// NSNull in the arguments array can be passed as a placeholder to indicate nil. We only need to set the argument if it will be non-nil.
if (argumentObject && ![argumentObject isKindOfClass:[NSNull class]]) {
const char *typeEncodingCString = [signature getArgumentTypeAtIndex:argumentIndex];
if (typeEncodingCString[0] == @encode(id)[0] || typeEncodingCString[0] == @encode(Class)[0] || [self isTollFreeBridgedValue:argumentObject forCFType:typeEncodingCString]) {
// Object
[invocation setArgument:&argumentObject atIndex:argumentIndex];
} else if (strcmp(typeEncodingCString, @encode(CGColorRef)) == 0
#if TARGET_OS_IOS
&& [argumentObject isKindOfClass:[UIColor class]]
#elif TARGET_OS_OSX
&& [argumentObject isKindOfClass:[NSColor class]]
#endif
) {
// Bridging UIColor to CGColorRef
CGColorRef colorRef = [argumentObject CGColor];
[invocation setArgument:&colorRef atIndex:argumentIndex];
} else if ([argumentObject isKindOfClass:[NSValue class]]) {
// Primitive boxed in NSValue
NSValue *argumentValue = (NSValue *)argumentObject;
// Ensure that the type encoding on the NSValue matches the type encoding of the argument in the method signature
if (strcmp([argumentValue objCType], typeEncodingCString) != 0) {
return nil;
}
NSUInteger bufferSize = 0;
@try {
// NSGetSizeAndAlignment barfs on type encoding for bitfields.
NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
} @catch (NSException *exception) { }
if (bufferSize > 0) {
void *buffer = calloc(bufferSize, 1);
[argumentValue getValue:buffer];
[invocation setArgument:buffer atIndex:argumentIndex];
free(buffer);
}
}
}
}
// Try to invoke the invocation but guard against an exception being thrown.
BOOL successfullyInvoked = NO;
@try {
// Some methods are not fit to be called...
// Looking at you -[UIResponder(UITextInputAdditions) _caretRect]
[invocation invoke];
successfullyInvoked = YES;
} @catch (NSException *exception) {
// Bummer...
}
// Retreive the return value and box if necessary.
id returnObject = nil;
if (successfullyInvoked) {
const char *returnType = [signature methodReturnType];
if (returnType[0] == @encode(id)[0] || returnType[0] == @encode(Class)[0]) {
__unsafe_unretained id objectReturnedFromMethod = nil;
[invocation getReturnValue:&objectReturnedFromMethod];
returnObject = objectReturnedFromMethod;
} else if (returnType[0] != @encode(void)[0]) {
void *returnValue = malloc([signature methodReturnLength]);
if (returnValue) {
[invocation getReturnValue:returnValue];
returnObject = [self valueForPrimitivePointer:returnValue objCType:returnType];
free(returnValue);
}
}
}
return returnObject;
}
return nil;
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 4bc8c4ead3507483e85343120a67c2cf
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
//
// NSString+TDString.h
// ThinkingSDK
//
// Created by wwango on 2021/10/11.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (TDString)
- (NSString *)td_trim;
- (NSString * _Nullable)ta_formatUrlString;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 001e956454f044758ab02322eac9c098
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
//
// NSString+TDString.m
// ThinkingSDK
//
// Created by wwango on 2021/10/11.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import "NSString+TDString.h"
@implementation NSString (TDString)
- (NSString *)td_trim {
NSString *string = [self stringByReplacingOccurrencesOfString:@" " withString:@""];
string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@""];
string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""];
return string;
}
- (NSString *)ta_formatUrlString {
NSString *urlString = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSURL *url = [NSURL URLWithString:urlString];
NSString *scheme = [url scheme];
NSString *host = [url host];
NSNumber *port = [url port];
if (scheme && scheme.length>0 && host && host.length>0) {
urlString = [NSString stringWithFormat:@"%@://%@", scheme, host];
if (port && [port stringValue]) {
urlString = [urlString stringByAppendingFormat:@":%@", [port stringValue]];
}
}
return urlString;
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 36ce4c8cee851492c9300c38f270d4b5
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
//
// TDCheck.h
// ThinkingSDK
//
// Created by wwango on 2021/9/10.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#define TD_CHECK_NIL(_object) (_object == nil || [_object isKindOfClass:[NSNull class]])
#define TD_CHECK_CLASS(_object, _class) (!TD_CHECK_NIL(_object) && [_object isKindOfClass:[_class class]])
#define TD_CHECK_CLASS_NSString(_object) TD_CHECK_CLASS(_object, [NSString class])
#define TD_CHECK_CLASS_NSNumber(_object) TD_CHECK_CLASS(_object, [NSNumber class])
#define TD_CHECK_CLASS_NSArray(_object) TD_CHECK_CLASS(_object, [NSArray class])
#define TD_CHECK_CLASS_NSData(_object) TD_CHECK_CLASS(_object, [NSData class])
#define TD_CHECK_CLASS_NSDate(_object) TD_CHECK_CLASS(_object, [NSDate class])
#define TD_CHECK_CLASS_NSDictionary(_object) TD_CHECK_CLASS(_object, [NSDictionary class])
#define TD_Valid_NSString(_object) (TD_CHECK_CLASS_NSString(_object) && (_object.length > 0))
#define TD_Valid_NSArray(_object) (TD_CHECK_CLASS_NSArray(_object) && (_object.count > 0))
#define TD_Valid_NSData(_object) (TD_CHECK_CLASS_NSData(_object) && (_object.length > 0))
#define TD_Valid_NSDictionary(_object) (TD_CHECK_CLASS_NSDictionary(_object) && (_object.allKeys.count > 0))
@interface TDCheck : NSObject
+ (NSDictionary *)td_checkToJSONObjectRecursive:(NSDictionary *)properties timeFormatter:(NSDateFormatter *)timeFormatter;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 3174e763d579e48f885f7bbf52454067
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
//
// TDCheck.m
// ThinkingSDK
//
// Created by wwango on 2021/9/10.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import "TDCheck.h"
#import "TDLogging.h"
@implementation TDCheck
+ (NSDictionary *)td_checkToJSONObjectRecursive:(NSDictionary *)properties timeFormatter:(NSDateFormatter *)timeFormatter {
return (NSDictionary *)[self td_checkToObjectRecursive:properties timeFormatter:timeFormatter];
}
// Five basic types: list, time, Boolean, value, text, list only supports basic data types
// Advanced data types: object, object group
+ (NSObject *)td_checkToObjectRecursive:(NSObject *)properties timeFormatter:(NSDateFormatter *)timeFormatter {
if (TD_CHECK_NIL(properties)) {
return properties;
} else if (TD_CHECK_CLASS_NSDictionary(properties)) {
NSDictionary *propertyDic = [(NSDictionary *)properties copy];
NSMutableDictionary<NSString *, id> *propertiesDic = [NSMutableDictionary dictionaryWithDictionary:propertyDic];
for (NSString *key in [propertyDic keyEnumerator]) {
NSObject *newValue = [self td_checkToJSONObjectRecursive:propertyDic[key] timeFormatter:timeFormatter];
propertiesDic[key] = newValue;
}
return propertiesDic;
} else if (TD_CHECK_CLASS_NSArray(properties)) {
NSMutableArray *arrayItem = [(NSArray *)properties mutableCopy];
for (int i = 0; i < arrayItem.count ; i++) {
id item = [self td_checkToJSONObjectRecursive:arrayItem[i] timeFormatter:timeFormatter];
if (item) arrayItem[i] = item;
}
return arrayItem;
} else if (TD_CHECK_CLASS_NSDate(properties)) {
NSString *dateStr = [timeFormatter stringFromDate:(NSDate *)properties];
return dateStr;
} else {
return properties;
}
}
// old method
//inline static NSDictionary *_td_old_checkToJSONObject(NSDictionary *properties, NSDateFormatter *timeFormatter) {
// NSMutableDictionary<NSString *, id> *propertiesDic = [NSMutableDictionary dictionaryWithDictionary:properties];
// for (NSString *key in [properties keyEnumerator]) {
// if ([properties[key] isKindOfClass:[NSDate class]]) {
// NSString *dateStr = [timeFormatter stringFromDate:(NSDate *)properties[key]];
// propertiesDic[key] = dateStr;
// } else if ([properties[key] isKindOfClass:[NSArray class]]) {
// NSMutableArray *arrayItem = [properties[key] mutableCopy];
// for (int i = 0; i < arrayItem.count ; i++) {
// if ([arrayItem[i] isKindOfClass:[NSDate class]]) {
// NSString *dateStr = [timeFormatter stringFromDate:(NSDate *)arrayItem[i]];
// arrayItem[i] = dateStr;
// }
// }
// propertiesDic[key] = arrayItem;
// }
// }
// return propertiesDic;
//}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 956605faf624745158ad0a460ca710b9
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
//
// TDCommonUtil.h
// ThinkingSDK
//
// Created by wwango on 2022/1/11.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TDCommonUtil : NSObject
+ (NSString *)string:(NSString *)string;
+ (NSDictionary *)dictionary:(NSDictionary *)dic;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: cdbf44bbd4cb144ff979af417b5774cf
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
//
// TDCommonUtil.m
// ThinkingSDK
//
// Created by wwango on 2022/1/11.
//
#import "TDCommonUtil.h"
@implementation TDCommonUtil
+ (NSString *)string:(NSString *)string {
if ([string isKindOfClass:[NSString class]] && string.length) {
return string;
} else {
return @"";
}
}
+ (NSDictionary *)dictionary:(NSDictionary *)dic {
if (dic && [dic isKindOfClass:[NSDictionary class]] && dic.allKeys.count) {
return dic;
} else {
return @{};
}
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 646b3aad38f76494ba9bbbb79ce88007
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TDJSONUtil : NSObject
+ (NSString *)JSONStringForObject:(id)object;
+ (NSData *)JSONSerializeForObject:(id)object;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: d2ad60173c70c49378862b12ee202ee6
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,87 @@
#import "TDJSONUtil.h"
//#import "TDLogging.h"
@implementation TDJSONUtil
+ (NSString *)JSONStringForObject:(id)obj {
NSData *data = [self JSONSerializeForObject:obj];
if (!data) {
return nil;
}
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
+ (NSData *)JSONSerializeForObject:(id)object {
id obj = [TDJSONUtil JSONSerializableObjectForObject:object];
NSData *data = nil;
@try {
if ([NSJSONSerialization isValidJSONObject:obj]) {
data = [NSJSONSerialization dataWithJSONObject:obj options:0 error:NULL];
}
}
@catch (NSException *exception) {
}
return data;
}
+ (id)JSONSerializableObjectForObject:(id)object {
if ([object isKindOfClass:[NSString class]]) {
return object;
} else if ([object isKindOfClass:[NSNumber class]]) {
if ([object stringValue] && [[object stringValue] rangeOfString:@"."].location != NSNotFound) {
return [NSDecimalNumber decimalNumberWithDecimal:((NSNumber *)object).decimalValue];
}
if ([object stringValue] && ([[object stringValue] rangeOfString:@"e"].location != NSNotFound ||
[[object stringValue] rangeOfString:@"E"].location != NSNotFound )) {
return [NSDecimalNumber decimalNumberWithDecimal:((NSNumber *)object).decimalValue];
}
return object;
} else if ([object isKindOfClass:[NSArray class]]) {
NSMutableArray<id> *array = [[NSMutableArray alloc] init];
for (id obj in (NSArray *)object) {
id convertedObj = [self JSONSerializableObjectForObject:obj];
[self array:array addObject:convertedObj];
}
return array;
} else if ([object isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary<NSString *, id> *dictionary = [[NSMutableDictionary alloc] init];
[(NSDictionary<id, id> *)object enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *dictionaryStop) {
[self dictionary:dictionary
setObject:[self JSONSerializableObjectForObject:obj]
forKey:key];
}];
return dictionary;
} else if ([object isKindOfClass:[NSArray class]]) {
NSMutableArray<id> *array = [[NSMutableArray alloc] init];
for (id obj in (NSArray *)object) {
id convertedObj = [self JSONSerializableObjectForObject:obj];
[self array:array addObject:convertedObj];
}
object = array;
}
NSString *s = [object description];
return s;
}
+ (void)array:(NSMutableArray *)array addObject:(id)object {
if (object) {
[array addObject:object];
}
}
+ (void)dictionary:(NSMutableDictionary<NSString *, id> *)dictionary setObject:(id)object forKey:(id<NSCopying>)key {
if (object && key) {
dictionary[key] = object;
}
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 8a9f967f5ccef4cfabe351bd702cc8cf
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
//
// TDUtil.h
// ThinkingSDK
//
// Created by LiHuanan on 2020/9/8.
// Copyright © 2020 thinkingdata. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TDSDKUtil : NSObject
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 4b3d4c8f9a5e94ad2a1cbc415bf27aef
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
//
// TDUtil.m
// ThinkingSDK
//
// Created by LiHuanan on 2020/9/8.
// Copyright © 2020 thinkingdata. All rights reserved.
//
#import "TDSDKUtil.h"
@implementation TDSDKUtil
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: a56c0e17f9b4643af98c0a4f64548a75
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
//
// TDWeakProxy.h
// ThinkingSDK
//
// Created by wwango on 2021/9/15.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TDWeakProxy : NSProxy
@property (nullable, nonatomic, weak, readonly) id target;
- (instancetype)initWithTarget:(id)target;
+ (instancetype)proxyWithTarget:(id)target;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 26287937f0ac74abeaed5f1da5b092ed
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,81 @@
//
// TDWeakProxy.m
// ThinkingSDK
//
// Created by wwango on 2021/9/15.
// Copyright © 2021 thinkingdata. All rights reserved.
//
#import "TDWeakProxy.h"
@implementation TDWeakProxy
- (instancetype)initWithTarget:(id)target {
_target = target;
return self;
}
+ (instancetype)proxyWithTarget:(id)target {
return [[TDWeakProxy alloc] initWithTarget:target];
}
- (id)forwardingTargetForSelector:(SEL)selector {
return _target;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
void *null = NULL;
[invocation setReturnValue:&null];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
return [NSObject instanceMethodSignatureForSelector:@selector(init)];
}
- (BOOL)respondsToSelector:(SEL)aSelector {
return [_target respondsToSelector:aSelector];
}
- (BOOL)isEqual:(id)object {
return [_target isEqual:object];
}
- (NSUInteger)hash {
return [_target hash];
}
- (Class)superclass {
return [_target superclass];
}
- (Class)class {
return [_target class];
}
- (BOOL)isKindOfClass:(Class)aClass {
return [_target isKindOfClass:aClass];
}
- (BOOL)isMemberOfClass:(Class)aClass {
return [_target isMemberOfClass:aClass];
}
- (BOOL)conformsToProtocol:(Protocol *)aProtocol {
return [_target conformsToProtocol:aProtocol];
}
- (BOOL)isProxy {
return YES;
}
- (NSString *)description {
return [_target description];
}
- (NSString *)debugDescription {
return [_target debugDescription];
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: a6edacb4206a84710b119b660398b43d
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d3b65b21752394ebb9fdbe302e35724c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface TDToastView : UIView
+ (instancetype)showInWindow:(UIWindow *)window text:(NSString *)text duration:(NSTimeInterval)duration;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 614c10a06303d446984eac9d03f7ba07
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,97 @@
#import "TDToastView.h"
@implementation TDToastView
{
UITextView *_textView;
}
#define TOAST_HORIZONTAL_PADDING 20.0
#define TOAST_VERTICAL_PADDING 15.0
- (instancetype)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
_textView = [[UITextView alloc] initWithFrame:CGRectZero];
_textView.opaque = NO;
_textView.editable = NO;
_textView.selectable = NO;
_textView.textColor = [UIColor whiteColor];
_textView.backgroundColor = [UIColor clearColor];
_textView.userInteractionEnabled = YES;
[self addSubview:_textView];
self.alpha = 0.9;
self.backgroundColor = [UIColor darkGrayColor];
self.layer.cornerRadius = 20.0;
self.opaque = NO;
self.userInteractionEnabled = YES;
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapHandler:)]];
}
return self;
}
+ (instancetype)showInWindow:(UIWindow *)window text:(NSString *)text duration:(NSTimeInterval)duration {
TDToastView *toast = [[self alloc] initWithFrame:CGRectZero];
toast.text = text;
[toast showInWindow:window duration:duration];
return toast;
}
- (void)showInWindow:(UIWindow *)window duration:(NSTimeInterval)duration {
if (window == nil) {
return;
}
CGRect windowBounds = CGRectInset(window.bounds, 20.0, 20.0);
CGRect toastBounds = CGRectZero;
toastBounds.size = [self sizeThatFits:windowBounds.size];
self.bounds = toastBounds;
self.center = CGPointMake(CGRectGetMidX(windowBounds), CGRectGetMidY(windowBounds));
CGFloat alpha = self.alpha;
self.alpha = 0.0;
[window addSubview:self];
[UIView animateWithDuration:0.3 animations:^{
self.alpha = alpha;
} completion:^(BOOL finishedShowing) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismiss];
});
}];
}
- (NSString *)text {
return _textView.text;
}
- (void)setText:(NSString *)text {
_textView.text = text;
}
- (void)dismiss {
if (!self.superview) {
return;
}
[UIView animateWithDuration:0.3 animations:^{
self.alpha = 0.0;
} completion:^(BOOL finishedHiding) {
[self removeFromSuperview];
}];
}
- (void)_tapHandler:(UITapGestureRecognizer *)tapGestureRecognizer {
[self dismiss];
}
- (void)layoutSubviews {
[super layoutSubviews];
_textView.frame = CGRectInset(self.bounds, TOAST_HORIZONTAL_PADDING, TOAST_VERTICAL_PADDING);
}
- (CGSize)sizeThatFits:(CGSize)size {
CGSize textConstrainedSize = CGSizeMake(size.width - 2 * TOAST_HORIZONTAL_PADDING,
size.height - 2 * TOAST_VERTICAL_PADDING);
CGSize textSize = [_textView sizeThatFits:textConstrainedSize];
CGFloat width = MIN(size.width, textSize.width + 2 * TOAST_HORIZONTAL_PADDING);
CGFloat height = MIN(size.height, textSize.height + 2 * TOAST_VERTICAL_PADDING);
return CGSizeMake(width, height);
}
@end

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 2fafada4f4d8d4cccbb91bb529d695a9
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
userData:
assetBundleName:
assetBundleVariant: