小说绘上架版本

This commit is contained in:
xtfei2011
2021-02-07 11:24:08 +08:00
commit ee5c1c8b12
1762 changed files with 115892 additions and 0 deletions
@@ -0,0 +1,19 @@
//
// CAGradientLayer+Crash.h
// WXReader
//
// Created by Andrew on 2019/6/25.
// Copyright © 2019 Andrew. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
NS_ASSUME_NONNULL_BEGIN
@interface CAGradientLayer (Crash)
- (void)_clearContents;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,18 @@
//
// CAGradientLayer+Crash.m
// WXReader
//
// Created by Andrew on 2019/6/25.
// Copyright © 2019 Andrew. All rights reserved.
//
#import "CAGradientLayer+Crash.h"
@implementation CAGradientLayer (Crash)
- (void)_clearContents
{
}
@end
@@ -0,0 +1,206 @@
#import <Foundation/Foundation.h>
#ifndef Release
@implementation NSSet(Log)
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
{
NSMutableString *desc = [NSMutableString string];
NSMutableString *tabString = [[NSMutableString alloc] initWithCapacity:level];
for (NSUInteger i = 0; i < level; ++i) {
[tabString appendString:@"\t"];
}
NSString *tab = @"\t";
if (level > 0) {
tab = tabString;
}
[desc appendString:@"\t{(\n"];
for (id obj in self) {
if ([obj isKindOfClass:[NSDictionary class]]
|| [obj isKindOfClass:[NSArray class]]
|| [obj isKindOfClass:[NSSet class]]) {
NSString *str = [((NSDictionary *)obj) descriptionWithLocale:locale indent:level + 1];
[desc appendFormat:@"%@\t%@,\n", tab, str];
} else if ([obj isKindOfClass:[NSString class]]) {
[desc appendFormat:@"%@\t\"%@\",\n", tab, obj];
} else if ([obj isKindOfClass:[NSData class]]) {
// if is NSDatatry parse
NSError *error = nil;
NSObject *result = [NSJSONSerialization JSONObjectWithData:obj
options:NSJSONReadingMutableContainers
error:&error];
if (error == nil && result != nil) {
if ([result isKindOfClass:[NSDictionary class]]
|| [result isKindOfClass:[NSArray class]]
|| [result isKindOfClass:[NSSet class]]) {
NSString *str = [((NSDictionary *)result) descriptionWithLocale:locale indent:level + 1];
[desc appendFormat:@"%@\t%@,\n", tab, str];
} else if ([obj isKindOfClass:[NSString class]]) {
[desc appendFormat:@"%@\t\"%@\",\n", tab, result];
}
} else {
@try {
NSString *str = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];
if (str != nil) {
[desc appendFormat:@"%@\t\"%@\",\n", tab, str];
} else {
[desc appendFormat:@"%@\t%@,\n", tab, obj];
}
}
@catch (NSException *exception) {
[desc appendFormat:@"%@\t%@,\n", tab, obj];
}
}
} else {
[desc appendFormat:@"%@\t%@,\n", tab, obj];
}
}
[desc appendFormat:@"%@)}", tab];
return desc;
}
@end
@implementation NSArray (Log)
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
{
NSMutableString *desc = [NSMutableString string];
NSMutableString *tabString = [[NSMutableString alloc] initWithCapacity:level];
for (NSUInteger i = 0; i < level; ++i) {
[tabString appendString:@"\t"];
}
NSString *tab = @"";
if (level > 0) {
tab = tabString;
}
[desc appendString:@"\t(\n"];
for (id obj in self) {
if ([obj isKindOfClass:[NSDictionary class]]
|| [obj isKindOfClass:[NSArray class]]
|| [obj isKindOfClass:[NSSet class]]) {
NSString *str = [((NSDictionary *)obj) descriptionWithLocale:locale indent:level + 1];
[desc appendFormat:@"%@\t%@,\n", tab, str];
} else if ([obj isKindOfClass:[NSString class]]) {
[desc appendFormat:@"%@\t\"%@\",\n", tab, obj];
} else if ([obj isKindOfClass:[NSData class]]) {
NSError *error = nil;
NSObject *result = [NSJSONSerialization JSONObjectWithData:obj
options:NSJSONReadingMutableContainers
error:&error];
if (error == nil && result != nil) {
if ([result isKindOfClass:[NSDictionary class]]
|| [result isKindOfClass:[NSArray class]]
|| [result isKindOfClass:[NSSet class]]) {
NSString *str = [((NSDictionary *)result) descriptionWithLocale:locale indent:level + 1];
[desc appendFormat:@"%@\t%@,\n", tab, str];
} else if ([obj isKindOfClass:[NSString class]]) {
[desc appendFormat:@"%@\t\"%@\",\n", tab, result];
}
} else {
@try {
NSString *str = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];
if (str != nil) {
[desc appendFormat:@"%@\t\"%@\",\n", tab, str];
} else {
[desc appendFormat:@"%@\t%@,\n", tab, obj];
}
}
@catch (NSException *exception) {
[desc appendFormat:@"%@\t%@,\n", tab, obj];
}
}
} else {
[desc appendFormat:@"%@\t%@,\n", tab, obj];
}
}
[desc appendFormat:@"%@)", tab];
return desc;
}
@end
@implementation NSDictionary (Log)
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
{
NSMutableString *desc = [NSMutableString string];
NSMutableString *tabString = [[NSMutableString alloc] initWithCapacity:level];
for (NSUInteger i = 0; i < level; ++i) {
[tabString appendString:@"\t"];
}
NSString *tab = @"";
if (level > 0) {
tab = tabString;
}
[desc appendString:@"\t{\n"];
// Through array, self is array
for (id key in self.allKeys) {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSString class]]) {
[desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, obj];
} else if ([obj isKindOfClass:[NSArray class]]
|| [obj isKindOfClass:[NSDictionary class]]
|| [obj isKindOfClass:[NSSet class]]) {
[desc appendFormat:@"%@\t%@ = %@,\n", tab, key, [obj descriptionWithLocale:locale indent:level + 1]];
} else if ([obj isKindOfClass:[NSData class]]) {
NSError *error = nil;
NSObject *result = [NSJSONSerialization JSONObjectWithData:obj
options:NSJSONReadingMutableContainers
error:&error];
if (error == nil && result != nil) {
if ([result isKindOfClass:[NSDictionary class]]
|| [result isKindOfClass:[NSArray class]]
|| [result isKindOfClass:[NSSet class]]) {
NSString *str = [((NSDictionary *)result) descriptionWithLocale:locale indent:level + 1];
[desc appendFormat:@"%@\t%@ = %@,\n", tab, key, str];
} else if ([obj isKindOfClass:[NSString class]]) {
[desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, result];
}
} else {
@try {
NSString *str = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];
if (str != nil) {
[desc appendFormat:@"%@\t%@ = \"%@\",\n", tab, key, str];
} else {
[desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];
}
}
@catch (NSException *exception) {
[desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];
}
}
} else {
[desc appendFormat:@"%@\t%@ = %@,\n", tab, key, obj];
}
}
[desc appendFormat:@"%@}", tab];
return desc;
}
@end
#endif
@@ -0,0 +1,16 @@
//
// NSAttributedString+TReaderPage.h
// Examda
//
// Created by tanyang on 16/1/26.
// Copyright © 2016年 tanyang. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface NSAttributedString (TReaderPage)
// 根据渲染图文大小分页,返回range数组
- (NSArray *)pageRangeArrayWithConstrainedToSize:(CGSize)size;
@end
@@ -0,0 +1,46 @@
//
// NSAttributedString+TReaderPage.m
// Examda
//
// Created by tanyang on 16/1/26.
// Copyright © 2016年 tanyang. All rights reserved.
//
#import "NSAttributedString+TReaderPage.h"
#import <CoreText/CoreText.h>
@implementation NSAttributedString (TReaderPage)
//根据指定的大小,对字符串进行分页,计算出每页显示的字符串区间(NSRange)
- (NSArray *)pageRangeArrayWithConstrainedToSize:(CGSize)size
{
NSAttributedString *attributedString = self;
NSMutableArray * resultRange = [NSMutableArray array];
CGRect rect = CGRectMake(0, 0, size.width, size.height);
NSInteger rangeIndex = 0;
do {
NSUInteger length = MIN(1500, attributedString.length - rangeIndex);
NSAttributedString * childString = [attributedString attributedSubstringFromRange:NSMakeRange(rangeIndex, length)];
CTFramesetterRef childFramesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef) childString);
UIBezierPath * bezierPath = [UIBezierPath bezierPathWithRect:rect];
CTFrameRef frame = CTFramesetterCreateFrame(childFramesetter, CFRangeMake(0, 0), bezierPath.CGPath, NULL);
CFRange range = CTFrameGetVisibleStringRange(frame);
NSRange r = {rangeIndex, range.length};
if (r.length > 0) {
[resultRange addObject:[NSValue valueWithRange:r]];
}
if (r.length == 0) {
rangeIndex ++;
} else {
rangeIndex += r.length;
}
CFRelease(frame);
CFRelease(childFramesetter);
} while (rangeIndex < attributedString.length && attributedString.length > 0);
return resultRange;
}
@end
@@ -0,0 +1,46 @@
//
// NSMutableArray+KVO.h
// iOSHelper
//
// Created by Chair on 2020/3/5.
// Copyright © 2020 Chair. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// 当数组的元素发生改变时回调
@interface NSMutableArray (KVO)
@property (nonatomic, copy) void(^changeBlock)(NSMutableArray *newVal);
- (void)KVO_addObject:(id)object;
- (void)KVO_insertObject:(id)anObject atIndex:(NSUInteger)index;
- (void)KVO_removeLastObject;
- (void)KVO_removeObjectAtIndex:(NSUInteger)index;
- (void)KVO_replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
- (void)KVO_addObjectsFromArray:(NSArray<id> *)otherArray;
- (void)KVO_exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2;
- (void)KVO_removeAllObjects;
- (void)KVO_removeObject:(id)anObject inRange:(NSRange)range;
- (void)KVO_removeObject:(id)anObject;
- (void)KVO_removeObjectIdenticalTo:(id)anObject inRange:(NSRange)range;
- (void)KVO_removeObjectIdenticalTo:(id)anObject;
- (void)KVO_removeObjectsFromIndices:(NSUInteger *)indices numIndices:(NSUInteger)cnt API_DEPRECATED("Not supported", macos(10.0,10.6), ios(2.0,4.0), watchos(2.0,2.0), tvos(9.0,9.0));
- (void)KVO_removeObjectsInArray:(NSArray<id> *)otherArray;
- (void)KVO_removeObjectsInRange:(NSRange)range;
- (void)KVO_replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray<id> *)otherArray range:(NSRange)otherRange;
- (void)KVO_replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray<id> *)otherArray;
- (void)KVO_setArray:(NSArray<id> *)otherArray;
- (void)KVO_insertObjects:(NSArray<id> *)objects atIndexes:(NSIndexSet *)indexes;
- (void)KVO_removeObjectsAtIndexes:(NSIndexSet *)indexes;
- (void)KVO_replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray<id> *)objects;
- (void)KVO_setObject:(id)obj atIndexedSubscript:(NSUInteger)idx API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0));
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,152 @@
//
// NSMutableArray+KVO.m
// iOSHelper
//
// Created by Chair on 2020/3/5.
// Copyright © 2020 Chair. All rights reserved.
//
#import "NSMutableArray+KVO.h"
#import <objc/runtime.h>
static const char * identifier = "identifier";
@implementation NSMutableArray (KVO)
- (void)setChangeBlock:(void (^)(NSMutableArray * _Nonnull))changeBlock {
if (!changeBlock) return ;
objc_setAssociatedObject(self, identifier, changeBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void (^)(NSMutableArray * _Nonnull))changeBlock {
return objc_getAssociatedObject(self, identifier);
}
- (void)KVO_addObject:(id)object {
if (object == nil || [object isKindOfClass:NSNull.class]) return ;
[self addObject:object];
self.changeBlock(self);
}
- (void)KVO_insertObject:(id)anObject atIndex:(NSUInteger)index {
if (anObject == nil || [anObject isKindOfClass:NSNull.class]) return ;
[self insertObject:anObject atIndex:index];
self.changeBlock(self);
}
- (void)KVO_removeLastObject {
[self removeLastObject];
self.changeBlock(self);
}
- (void)KVO_removeObjectAtIndex:(NSUInteger)index {
[self removeObjectAtIndex:index];
self.changeBlock(self);
}
- (void)KVO_replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {
if (anObject == nil || [anObject isKindOfClass:NSNull.class]) return ;
[self replaceObjectAtIndex:index withObject:anObject];
self.changeBlock(self);
}
- (void)KVO_addObjectsFromArray:(NSArray<id> *)otherArray {
if (![otherArray isKindOfClass:NSArray.class]) return ;
[self addObjectsFromArray:otherArray];
self.changeBlock(self);
}
- (void)KVO_exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2 {
[self exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2];
self.changeBlock(self);
}
- (void)KVO_removeAllObjects {
[self removeAllObjects];
self.changeBlock(self);
}
- (void)KVO_removeObject:(id)anObject inRange:(NSRange)range {
if (anObject == nil || [anObject isKindOfClass:NSNull.class]) return ;
[self removeObject:anObject inRange:range];
self.changeBlock(self);
}
- (void)KVO_removeObject:(id)anObject {
if (anObject == nil || [anObject isKindOfClass:NSNull.class]) return ;
[self removeObject:anObject];
self.changeBlock(self);
}
- (void)KVO_removeObjectIdenticalTo:(id)anObject inRange:(NSRange)range {
if (anObject == nil || [anObject isKindOfClass:NSNull.class]) return ;
[self removeObjectIdenticalTo:anObject inRange:range];
self.changeBlock(self);
}
- (void)KVO_removeObjectIdenticalTo:(id)anObject {
if (anObject == nil || [anObject isKindOfClass:NSNull.class]) return ;
[self removeObjectIdenticalTo:anObject];
self.changeBlock(self);
}
- (void)KVO_removeObjectsFromIndices:(NSUInteger *)indices numIndices:(NSUInteger)cnt {
[self removeObjectsFromIndices:indices numIndices:cnt];
self.changeBlock(self);
}
- (void)KVO_removeObjectsInArray:(NSArray<id> *)otherArray {
if (![otherArray isKindOfClass:NSArray.class]) return ;
[self removeObjectsInArray:otherArray];
self.changeBlock(self);
}
- (void)KVO_removeObjectsInRange:(NSRange)range {
[self removeObjectsInRange:range];
self.changeBlock(self);
}
- (void)KVO_replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray<id> *)otherArray range:(NSRange)otherRange {
if (![otherArray isKindOfClass:NSArray.class]) return ;
[self replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange];
self.changeBlock(self);
}
- (void)KVO_replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray<id> *)otherArray {
if (![otherArray isKindOfClass:NSArray.class]) return ;
[self replaceObjectsInRange:range withObjectsFromArray:otherArray];
self.changeBlock(self);
}
- (void)KVO_setArray:(NSArray<id> *)otherArray {
if (![otherArray isKindOfClass:NSArray.class]) return ;
[self setArray:otherArray];
self.changeBlock(self);
}
- (void)KVO_insertObjects:(NSArray<id> *)objects atIndexes:(NSIndexSet *)indexes {
if (![objects isKindOfClass:NSArray.class]) return ;
[self insertObjects:objects atIndexes:indexes];
self.changeBlock(self);
}
- (void)KVO_removeObjectsAtIndexes:(NSIndexSet *)indexes {
[self removeObjectsAtIndexes:indexes];
self.changeBlock(self);
}
- (void)KVO_replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray<id> *)objects {
if (![objects isKindOfClass:NSArray.class]) return ;
[self replaceObjectsAtIndexes:indexes withObjects:objects];
self.changeBlock(self);
}
- (void)KVO_setObject:(id)obj atIndexedSubscript:(NSUInteger)idx {
if (obj == nil || [obj isKindOfClass:NSNull.class]) return ;
[self setObject:obj atIndexedSubscript:idx];
self.changeBlock(self);
}
@end
+16
View File
@@ -0,0 +1,16 @@
//
// NSObject+DZM.h
// DZMAnimatedTransitioning
//
// Created by 邓泽淼 on 2017/12/22.
// Copyright © 2017年 邓泽淼. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface NSObject (DZM)
@property (nonatomic, weak, nullable) UIView *ATTarget;
@end
+26
View File
@@ -0,0 +1,26 @@
//
// NSObject+DZM.m
// DZMAnimatedTransitioning
//
// Created by 邓泽淼 on 2017/12/22.
// Copyright © 2017年 邓泽淼. All rights reserved.
//
#import "NSObject+DZM.h"
#import <objc/runtime.h>
static const NSString *isATTarget = @"isATTarget";
@implementation NSObject (DZM)
- (void)setATTarget:(UIView *)ATTarget {
objc_setAssociatedObject(self, &isATTarget, ATTarget, OBJC_ASSOCIATION_ASSIGN);
}
- (UIView *)ATTarget {
return objc_getAssociatedObject(self, &isATTarget);
}
@end
@@ -0,0 +1,17 @@
//
// NSObject+LSDefaults.h
// WXReader
//
// Created by Andrew on 2019/10/9.
// Copyright © 2019 Andrew. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSObject (LSDefaults)
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,37 @@
//
// NSObject+LSDefaults.m
// WXReader
//
// Created by Andrew on 2019/10/9.
// Copyright © 2019 Andrew. All rights reserved.
//
#import "NSObject+LSDefaults.h"
@implementation NSObject (LSDefaults)
+ (void)load{
SEL originalSelector = @selector(doesNotRecognizeSelector:);
SEL swizzledSelector = @selector(sw_doesNotRecognizeSelector:);
Method originalMethod = class_getClassMethod(self, originalSelector);
Method swizzledMethod = class_getClassMethod(self, swizzledSelector);
if(class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))){
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}else{
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
+ (void)sw_doesNotRecognizeSelector:(SEL)aSelector{
//处理 _LSDefaults 崩溃问题
if([[self description] isEqualToString:@"_LSDefaults"] && (aSelector == NSSelectorFromString(@"sharedInstance"))){
return;
}
[self sw_doesNotRecognizeSelector:aSelector];
}
@end
@@ -0,0 +1,23 @@
//
// NSObject+WXYZ_Observer.h
// BW_Video
//
// Created by Chair on 2019/11/29.
// Copyright © 2019 WXYZ. All rights reserved.
//
#import <Foundation/Foundation.h>
/** 启用KVO自动清除功能 */
#define ENABLE_SWIZZ_IN_SIMPLEKVO 1
NS_ASSUME_NONNULL_BEGIN
@interface NSObject (Observer)
/** 添加一个会自动释放的KVO */
- (void)addObserver:(NSString *)keyPath complete:(void(^)(id obj, id _Nullable oldVal, id _Nullable newVal))complte;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,51 @@
//
// NSObject+WXYZ_Observer.m
// BW_Video
//
// Created by Chair on 2019/11/29.
// Copyright © 2019 WXYZ. All rights reserved.
//
#import "NSObject+Observer.h"
#import <objc/runtime.h>
static NSString *helper;
@implementation NSObject (Observer)
- (void)addObserver:(NSString *)keyPath complete:(void (^)(id _Nonnull, id _Nullable, id _Nullable))complte {
if (keyPath.length == 0 || complte == nil) return ;
[self addObserverBlockForKeyPath:keyPath block:complte];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 11.0 && ENABLE_SWIZZ_IN_SIMPLEKVO) {
NSString *objHash = [NSString stringWithFormat:@"%zd", [self modelHash]];
NSString *pathHash = [NSString stringWithFormat:@"%zd", [keyPath modelHash]];
helper = [objHash stringByAppendingString:pathHash];
if (!objc_getAssociatedObject(self, &helper)) {
objc_setAssociatedObject(self, &helper, helper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
}
}
+ (void)load {
// 判断版本是否小于11.0并且开关打开,然后替换系统的dealloc方法
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 11.0 && ENABLE_SWIZZ_IN_SIMPLEKVO) {
NSString *dealloc = @"dealloc";
Method originalDealloc = class_getInstanceMethod(self, NSSelectorFromString(dealloc));
Method kvoDealloc = class_getInstanceMethod(self, @selector(customDealloc));
method_exchangeImplementations(originalDealloc, kvoDealloc);
}
}
- (void)customDealloc {
// 判断是否需要移除KVO
if (objc_getAssociatedObject(self, &helper) != nil) {
[self removeObserverBlocks];
objc_setAssociatedObject(self, &helper, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
[self customDealloc];
}
@end
@@ -0,0 +1,23 @@
//
// NSObject+Utils.h
// WXReader
//
// Created by LL on 2020/6/5.
// Copyright © 2020 Andrew. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSObject (Utils)
- (BOOL)modelisEmpty;
+ (NSDictionary<NSString *, NSString *> *)propertyDict;
+ (NSArray<NSString *> *)propertyArr;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,120 @@
//
// NSObject+Utils.m
// WXReader
//
// Created by LL on 2020/6/5.
// Copyright © 2020 Andrew. All rights reserved.
//
#import "NSObject+Utils.h"
#import "NSString+TFExtension.h"
@implementation NSObject (Utils)
/// 获取指定类中所有的属性信息(属性名-属性类型)
+ (NSDictionary<NSString *, NSString *> *)propertyDict {
// 属性数量
unsigned int count;
objc_property_t *properties = class_copyPropertyList(self, &count);
NSMutableDictionary<NSString *, NSString *> *dic = [NSMutableDictionary dictionary];
for (int i = 0; i < count; i++) {
// 获取属性名称
objc_property_t property = properties[i];
const char *cName = property_getName(property);
const char *cType = property_getAttributes(property);
// 属性名称
NSString *name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
// 属性类型
NSString *type = [NSString stringWithCString:cType encoding:NSUTF8StringEncoding];
NSError *error;
// 利用正则表达式获取正确类型
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=@\").*?(?=\")" options:NSRegularExpressionCaseInsensitive error:&error];
if (error) {
NSAssert(NO, error.localizedDescription ?: TFLocalizedString(@"动态获取属性类型错误"));
return @{};
}
NSTextCheckingResult *match = [regex firstMatchInString:type options:kNilOptions range:NSMakeRange(0, type.length)];
if (match) {
type = [type substringWithRange:match.range];
} else {
type = [self switchType:type];
}
[dic setObject:type forKey:name];
}
return dic;
}
/// 获取指定类中属性名数组
+ (NSArray<NSString *> *)propertyArr {
return [[self propertyDict] allKeys];
}
+ (NSString *)switchType:(NSString *)type {
NSString *sub = [type substringWithRange:NSMakeRange(1, 1)];
if ([sub isEqualToString:@"i"] ||
[sub isEqualToString:@"s"] ||
[sub isEqualToString:@"I"] ||
[sub isEqualToString:@"S"]) {
return @"int";
}
if ([sub isEqualToString:@"l"]) {
return @"long";
}
if ([sub isEqualToString:@"q"]) {
return @"NSInteger";
}
if ([sub isEqualToString:@"Q"]) {
return @"NSUInteger";
}
if ([sub isEqualToString:@"L"]) {
return @"long";// unsigned long
}
if ([sub isEqualToString:@"f"]) {
return @"float";
}
if ([sub isEqualToString:@"d"]) {
return @"CGFloat";
}
if ([sub isEqualToString:@"B"]) {
return @"BOOL";
}
return @"int";
}
/// 检查Model是否为空
- (BOOL)modelisEmpty {
for (NSString *name in [self.class propertyArr]) {
SEL sel = NSSelectorFromString(name);
if ([self respondsToSelector:sel]) {
id obj = [self performSelectorWithArgs:sel];
if (!kObjectIsEmpty(obj)) {
return NO;
}
} else {
SEL sel = NSSelectorFromString([NSString stringWithFormat:@"%@%@", @"is", [name firstCapitalized]]);
if ([self respondsToSelector:sel]) {
id obj = [self performSelectorWithArgs:sel];
if (!kObjectIsEmpty(obj)) {
return NO;
}
} else {
return YES;
}
}
}
return YES;
}
@end
@@ -0,0 +1,28 @@
//
// NSString+TFExtension.h
// WXReader
//
// Created by 谢腾飞 on 2020/12/3.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (TFExtension)
- (NSString *)fileSize;
- (NSString *)safeSubstringWithRange:(NSRange)range;
- (BOOL)containChinese;
/// 获取正确的网络URL地址
- (NSString *)networkUrl;
- (NSString *)firstCapitalized;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,114 @@
//
// NSString+TFExtension.m
// WXReader
//
// Created by 谢腾飞 on 2020/12/3.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#import "NSString+TFExtension.h"
@implementation NSString (TFExtension)
- (NSString *)fileSize
{
// 总大小
unsigned long long size = 0;
NSString *sizeText = @"";
// 文件管理者
NSFileManager *mgr = [NSFileManager defaultManager];
// 文件属性
NSDictionary *attrs = [mgr attributesOfItemAtPath:self error:nil];
// 如果这个文件或者文件夹不存在,或者路径不正确直接返回0;
if (attrs == nil) return @"";
if ([attrs.fileType isEqualToString:NSFileTypeDirectory]) { // 如果是文件夹
// 获得文件夹的大小 == 获得文件夹中所有文件的总大小
NSDirectoryEnumerator *enumerator = [mgr enumeratorAtPath:self];
for (NSString *subpath in enumerator) {
// 全路径
NSString *fullSubpath = [self stringByAppendingPathComponent:subpath];
// 累加文件大小
size += [mgr attributesOfItemAtPath:fullSubpath error:nil].fileSize;
if (size >= pow(10, 9)) { // size >= 1GB
sizeText = [NSString stringWithFormat:@"%.2fGB", size / pow(10, 9)];
} else if (size >= pow(10, 6)) { // 1GB > size >= 1MB
sizeText = [NSString stringWithFormat:@"%.2fMB", size / pow(10, 6)];
} else if (size >= pow(10, 3)) { // 1MB > size >= 1KB
sizeText = [NSString stringWithFormat:@"%.2fKB", size / pow(10, 3)];
} else { // 1KB > size
sizeText = [NSString stringWithFormat:@"%zdB", (long)size];
}
}
return sizeText;
} else { // 如果是文件
size = attrs.fileSize;
if (size >= pow(10, 9)) { // size >= 1GB
sizeText = [NSString stringWithFormat:@"%.2fGB", size / pow(10, 9)];
} else if (size >= pow(10, 6)) { // 1GB > size >= 1MB
sizeText = [NSString stringWithFormat:@"%.2fMB", size / pow(10, 6)];
} else if (size >= pow(10, 3)) { // 1MB > size >= 1KB
sizeText = [NSString stringWithFormat:@"%.2fKB", size / pow(10, 3)];
} else { // 1KB > size
sizeText = [NSString stringWithFormat:@"%zdB", (long)size];
}
}
return sizeText;
}
- (NSString *)safeSubstringWithRange:(NSRange)range
{
if (range.location > self.length) {
return @"";
}
if (range.length > self.length) {
return @"";
}
if ((range.location + range.length) > self.length) {
return @"";
}
return [self substringWithRange:range];
}
- (BOOL)containChinese
{
for (int i = 0; i < [self length]; i++) {
unichar t_char = [self characterAtIndex:i];
if (t_char >= 0x4E00 && t_char <= 0x9FA5) {
return YES;
}
}
return NO;
}
YYCache *_cache = nil;
- (NSString *)networkUrl
{
if (!_cache) {
_cache = [YYCache cacheWithName:@"networkingURL"];
}
if ([_cache containsObjectForKey:self]) {
return self;
} else {
BOOL status = [self containChinese];
if (status) {
NSString *t_url = [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[_cache setObject:t_url forKey:self];
return t_url;
} else {
[_cache setObject:self forKey:self];
return self;
}
}
}
- (NSString *)firstCapitalized
{
NSString *firstStirng = [self substringToIndex:1];
NSString *lastString = [self substringFromIndex:1];
return [firstStirng.capitalizedString stringByAppendingString:lastString];
}
@end
@@ -0,0 +1,17 @@
//
// NSURL+ImageURL.h
// WXReader
//
// Created by Andrew on 2020/7/2.
// Copyright © 2020 Andrew. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSURL (ImageURL)
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,37 @@
//
// NSURL+ImageURL.m
// WXReader
//
// Created by Andrew on 2020/7/2.
// Copyright © 2020 Andrew. All rights reserved.
//
#import "NSURL+ImageURL.h"
#import <objc/runtime.h>
@implementation NSURL (ImageURL)
+ (void)load
{
Method URLWithStringMethod = class_getClassMethod(self, @selector(URLWithString:));
Method sc_URLWithStringMethod = class_getClassMethod(self, @selector(wxyz_URLWithString:));
method_exchangeImplementations(URLWithStringMethod, sc_URLWithStringMethod);
}
// 处理网络图片地址带中文的问题
+ (NSURL *)wxyz_URLWithString:(NSString *)URLString
{
for (int i = 0; i < [URLString length]; i++) {
int character = [URLString characterAtIndex:i];
if (character > 0x4e00 && character < 0x9fff) { // 如果包含中文
// 转义中文内容
NSString *t_string = [[URLString substringWithRange:NSMakeRange(i, 1)] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
URLString = [URLString stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:t_string];
}
}
return [NSURL wxyz_URLWithString:URLString];
}
@end
@@ -0,0 +1,27 @@
//
// UIButton+LayoutCallback.h
// iOS_TEST
//
// Created by Chair on 2020/1/22.
// Copyright © 2020 Chair. All rights reserved.
//
#import <UIKit/UIKit.h>
/** 是否启用该功能 */
#define ENABLE_SWIZZ_IN_SIMPLEFrame 1
NS_ASSUME_NONNULL_BEGIN
@interface UIButton (LayoutCallback)
#if ENABLE_SWIZZ_IN_SIMPLEFrame
/** 子视图布局完成后返回自身 */
@property (nonatomic, copy) void(^frameBlock)(UIButton *button);
#endif
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,42 @@
//
// UIButton+LayoutCallback.m
// iOS_TEST
//
// Created by Chair on 2020/1/22.
// Copyright © 2020 Chair. All rights reserved.
//
#import "UIButton+LayoutCallback.h"
#import <objc/runtime.h>
static const char * identifier = "identifier";
@implementation UIButton (LayoutCallback)
#if ENABLE_SWIZZ_IN_SIMPLEFrame
+ (void)load {
Method method1 = class_getInstanceMethod(self, @selector(layoutSubviews));
Method method2 = class_getInstanceMethod(self, @selector(xl_Btn_layoutSubviews));
method_exchangeImplementations(method1, method2);
}
- (void)xl_Btn_layoutSubviews {
[self xl_Btn_layoutSubviews];
!self.frameBlock ?: self.frameBlock(self);
}
- (void)setFrameBlock:(void (^)(UIButton * _Nonnull))frameBlock {
if (frameBlock == nil) return ;
objc_setAssociatedObject(self, identifier, frameBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void (^)(UIButton * _Nonnull))frameBlock {
return objc_getAssociatedObject(self, identifier);
}
#endif
@end
@@ -0,0 +1,19 @@
//
// UIControl+EventInterval.h
// WXReader
//
// Created by Andrew on 2020/7/23.
// Copyright © 2020 Andrew. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIControl (EventInterval)
@property (nonatomic, assign) NSTimeInterval touchEventInterval;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,69 @@
//
// UIControl+EventInterval.m
// WXReader
//
// Created by Andrew on 2020/7/23.
// Copyright © 2020 Andrew. All rights reserved.
//
#import "UIControl+EventInterval.h"
#import <objc/runtime.h>
static char * const touchEventIntervalKey = "touchEventIntervalKey";
static char * const eventUnavailableKey = "eventUnavailableKey";
@interface UIControl ()
@property (nonatomic, assign) BOOL eventUnavailable;
@end
@implementation UIControl (EventInterval)
+ (void)load
{
Method method = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method qi_method = class_getInstanceMethod(self, @selector(qi_sendAction:to:forEvent:));
method_exchangeImplementations(method, qi_method);
}
#pragma mark - Action functions
- (void)qi_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
if ([self isMemberOfClass:[UIButton class]]) {
if (self.eventUnavailable == NO) {
self.eventUnavailable = YES;
[self qi_sendAction:action to:target forEvent:event];
[self performSelector:@selector(setEventUnavailable:) withObject:0 afterDelay:self.touchEventInterval];
}
} else {
[self qi_sendAction:action to:target forEvent:event];
}
}
#pragma mark - Setter & Getter functions
- (NSTimeInterval)touchEventInterval
{
return [objc_getAssociatedObject(self, touchEventIntervalKey) doubleValue];
}
- (void)setTouchEventInterval:(NSTimeInterval)touchEventInterval
{
objc_setAssociatedObject(self, touchEventIntervalKey, @(touchEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)eventUnavailable
{
return [objc_getAssociatedObject(self, eventUnavailableKey) boolValue];
}
- (void)setEventUnavailable:(BOOL)eventUnavailable
{
objc_setAssociatedObject(self, eventUnavailableKey, @(eventUnavailable), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
@@ -0,0 +1,28 @@
//
// UIImage+Blur.h
// WXReader
//
// Created by LL on 2020/5/20.
// Copyright © 2020 Andrew. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImage (Blur)
/*
1.白色,参数:
透明度 0~1, 0为白, 1为深灰色
半径:默认30,推荐值 3 半径值越大越模糊 ,值越小越清楚
色彩饱和度(浓度)因子: 0是黑白灰, 9是浓彩色, 1是原色 默认1.8
“彩度”,英文是称Saturation,即饱和度。将无彩色的黑白灰定为0,最鲜艳定为9s,这样大致分成十阶段,让数值和人的感官直觉一致。
*/
- (UIImage *)imgWithLightAlpha:(CGFloat)alpha radius:(CGFloat)radius colorSaturationFactor:(CGFloat)colorSaturationFactor;
- (UIImage *)imgWithBlur;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,129 @@
//
// UIImage+LightMode.m
// WXReader
//
// Created by LL on 2020/5/20.
// Copyright © 2020 Andrew. All rights reserved.
//
#import "UIImage+Blur.h"
#import <Accelerate/Accelerate.h>
@implementation UIImage (Blur)
- (UIImage *)imgWithLightAlpha:(CGFloat)alpha radius:(CGFloat)radius colorSaturationFactor:(CGFloat)colorSaturationFactor {
UIColor *tintColor = [UIColor colorWithRed:180 / 255.0 green:180 / 255.0 blue:180 / 255.0 alpha:alpha];
return [self imgBluredWithRadius:radius tintColor:tintColor saturationDeltaFactor:colorSaturationFactor maskImage:nil];
}
- (UIImage *)imgWithBlur {
return [self imgWithLightAlpha:0.1 radius:3 colorSaturationFactor:1];
}
// 内部方法,核心代码,封装了毛玻璃效果 参数:半径,颜色,色彩饱和度
- (UIImage *)imgBluredWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
{
CGRect imageRect = { CGPointZero, self.size };
UIImage *effectImage = self;
BOOL hasBlur = blurRadius > __FLT_EPSILON__;
BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
if (hasBlur || hasSaturationChange) {
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef effectInContext = UIGraphicsGetCurrentContext();
CGContextScaleCTM(effectInContext, 1.0, -1.0);
CGContextTranslateCTM(effectInContext, 0, -self.size.height);
CGContextDrawImage(effectInContext, imageRect, self.CGImage);
vImage_Buffer effectInBuffer;
effectInBuffer.data = CGBitmapContextGetData(effectInContext);
effectInBuffer.width = CGBitmapContextGetWidth(effectInContext);
effectInBuffer.height = CGBitmapContextGetHeight(effectInContext);
effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
vImage_Buffer effectOutBuffer;
effectOutBuffer.data = CGBitmapContextGetData(effectOutContext);
effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext);
effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext);
effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);
if (hasBlur) {
CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
if (radius % 2 != 1) {
radius += 1; // force radius to be odd so that the three box-blur methodology works.
}
vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, (int)radius, (int)radius, 0, kvImageEdgeExtend);
vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, (int)radius, (int)radius, 0, kvImageEdgeExtend);
vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, (int)radius, (int)radius, 0, kvImageEdgeExtend);
}
BOOL effectImageBuffersAreSwapped = NO;
if (hasSaturationChange) {
CGFloat s = saturationDeltaFactor;
CGFloat floatingPointSaturationMatrix[] = {
0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0,
0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0,
0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0,
0, 0, 0, 1,
};
const int32_t divisor = 256;
NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
int16_t saturationMatrix[matrixSize];
for (NSUInteger i = 0; i < matrixSize; ++i) {
saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
}
if (hasBlur) {
vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
effectImageBuffersAreSwapped = YES;
}
else {
vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
}
}
if (!effectImageBuffersAreSwapped)
effectImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (effectImageBuffersAreSwapped)
effectImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
// 开启上下文 用于输出图像
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef outputContext = UIGraphicsGetCurrentContext();
CGContextScaleCTM(outputContext, 1.0, -1.0);
CGContextTranslateCTM(outputContext, 0, -self.size.height);
// 开始画底图
CGContextDrawImage(outputContext, imageRect, self.CGImage);
// 开始画模糊效果
if (hasBlur) {
CGContextSaveGState(outputContext);
if (maskImage) {
CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
}
CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
CGContextRestoreGState(outputContext);
}
// 添加颜色渲染
if (tintColor) {
CGContextSaveGState(outputContext);
CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
CGContextFillRect(outputContext, imageRect);
CGContextRestoreGState(outputContext);
}
// 输出成品,并关闭上下文
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
@end
@@ -0,0 +1,19 @@
//
// UIImage+Color.h
// WXReader
//
// Created by LL on 2020/6/4.
// Copyright © 2020 Andrew. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImage (Color)
- (instancetype)imageWithColor:(UIColor *)color;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,28 @@
//
// UIImage+Color.m
// WXReader
//
// Created by LL on 2020/6/4.
// Copyright © 2020 Andrew. All rights reserved.
//
#import "UIImage+Color.h"
@implementation UIImage (Color)
- (instancetype)imageWithColor:(UIColor *)color {
UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextClipToMask(context, rect, self.CGImage);
[color setFill];
CGContextFillRect(context, rect);
UIImage *t_image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return t_image;
}
@end
@@ -0,0 +1,24 @@
//
// UIImageView+CornerRadius.h
// MyPractise
//
// Created by lzy on 16/3/1.
// Copyright © 2016年 lzy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface UIImageView (CornerRadius)
- (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType;
- (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType;
- (instancetype)initWithRoundingRectImageView;
- (void)zy_cornerRadiusRoundingRect;
- (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color;
@end
@@ -0,0 +1,300 @@
//
// UIImageView+CornerRadius.m
// MyPractise
//
// Created by lzy on 16/3/1.
// Copyright © 2016年 lzy. All rights reserved.
//
#import "UIImageView+CornerRadius.h"
#import "NSObject+Observer.h"
const char kProcessedImage;
@interface UIImageView ()
@property (assign, nonatomic) CGFloat zyRadius;
@property (assign, nonatomic) UIRectCorner roundingCorners;
@property (assign, nonatomic) CGFloat zyBorderWidth;
@property (strong, nonatomic) UIColor *zyBorderColor;
@property (assign, nonatomic) BOOL zyHadAddObserver;
@property (assign, nonatomic) BOOL zyIsRounding;
@end
@implementation UIImageView (CornerRadius)
/**
* @brief init the Rounding UIImageView, no off-screen-rendered
*/
- (instancetype)initWithRoundingRectImageView {
self = [super init];
if (self) {
[self zy_cornerRadiusRoundingRect];
}
return self;
}
/**
* @brief init the UIImageView with cornerRadius, no off-screen-rendered
*/
- (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
self = [super init];
if (self) {
[self zy_cornerRadiusAdvance:cornerRadius rectCornerType:rectCornerType];
}
return self;
}
/**
* @brief attach border for UIImageView with width & color
*/
- (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color {
self.zyBorderWidth = width;
self.zyBorderColor = color;
}
#pragma mark - Kernel
/**
* @brief clip the cornerRadius with image, UIImageView must be setFrame before, no off-screen-rendered
*/
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
CGSize size = self.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
if (nil == currentContext) {
return;
}
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
[cornerPath addClip];
[self.layer renderInContext:currentContext];
[self drawBorder:cornerPath];
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (processedImage) {
objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
self.image = processedImage;
}
/**
* @brief clip the cornerRadius with image, draw the backgroundColor you want, UIImageView must be setFrame before, no off-screen-rendered, no Color Blended layers
*/
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType backgroundColor:(UIColor *)backgroundColor {
CGSize size = self.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
UIGraphicsBeginImageContextWithOptions(size, YES, scale);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
if (nil == currentContext) {
return;
}
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
UIBezierPath *backgroundRect = [UIBezierPath bezierPathWithRect:self.bounds];
[backgroundColor setFill];
[backgroundRect fill];
[cornerPath addClip];
[self.layer renderInContext:currentContext];
[self drawBorder:cornerPath];
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (processedImage) {
objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
self.image = processedImage;
}
/**
* @brief set cornerRadius for UIImageView, no off-screen-rendered
*/
- (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
self.zyRadius = cornerRadius;
self.roundingCorners = rectCornerType;
self.zyIsRounding = NO;
if (!self.zyHadAddObserver) {
// [[self class] swizzleDealloc];
// [self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
[self addObserver:KEY_PATH(self, image) complete:^(UIImageView * _Nonnull obj, id _Nullable oldVal, UIImage * _Nullable newImage) {
if ([newImage isMemberOfClass:[NSNull class]]) {
return;
} else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) {
return;
}
[obj validateFrame];
if (obj.zyIsRounding) {
[obj zy_cornerRadiusWithImage:newImage cornerRadius:obj.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
} else if (0 != self.zyRadius && 0 != self.roundingCorners && nil != self.image) {
[obj zy_cornerRadiusWithImage:newImage cornerRadius:obj.zyRadius rectCornerType:obj.roundingCorners];
}
}];
self.zyHadAddObserver = YES;
}
//Xcode 8 xib 删除了控件的Frame信息,需要主动创造
[self layoutIfNeeded];
}
/**
* @brief become Rounding UIImageView, no off-screen-rendered
*/
- (void)zy_cornerRadiusRoundingRect {
self.zyIsRounding = YES;
if (!self.zyHadAddObserver) {
// [[self class] swizzleDealloc];
// [self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
[self addObserver:KEY_PATH(self, image) complete:^(UIImageView * _Nonnull obj, id _Nullable oldVal, UIImage * _Nullable newImage) {
if ([newImage isMemberOfClass:[NSNull class]]) {
return;
} else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) {
return;
}
[obj validateFrame];
if (obj.zyIsRounding) {
[obj zy_cornerRadiusWithImage:newImage cornerRadius:obj.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
} else if (0 != self.zyRadius && 0 != self.roundingCorners && nil != self.image) {
[obj zy_cornerRadiusWithImage:newImage cornerRadius:obj.zyRadius rectCornerType:obj.roundingCorners];
}
}];
self.zyHadAddObserver = YES;
}
//Xcode 8 xib 删除了控件的Frame信息,需要主动创造
[self layoutIfNeeded];
}
#pragma mark - Private
- (void)drawBorder:(UIBezierPath *)path {
if (0 != self.zyBorderWidth && nil != self.zyBorderColor) {
[path setLineWidth:2 * self.zyBorderWidth];
[self.zyBorderColor setStroke];
[path stroke];
}
}
//- (void)zy_dealloc {
// if (self.zyHadAddObserver) {
//// [self removeObserver:self forKeyPath:@"image"];
// }
// [self zy_dealloc];
//}
- (void)validateFrame {
if (self.frame.size.width == 0) {
[self.class swizzleLayoutSubviews];
}
}
+ (void)swizzleMethod:(SEL)oneSel anotherMethod:(SEL)anotherSel {
Method oneMethod = class_getInstanceMethod(self, oneSel);
Method anotherMethod = class_getInstanceMethod(self, anotherSel);
method_exchangeImplementations(oneMethod, anotherMethod);
}
//
//+ (void)swizzleDealloc {
// static dispatch_once_t onceToken;
// dispatch_once(&onceToken, ^{
// [self swizzleMethod:NSSelectorFromString(@"dealloc") anotherMethod:@selector(zy_dealloc)];
// });
//}
+ (void)swizzleLayoutSubviews {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swizzleMethod:@selector(layoutSubviews) anotherMethod:@selector(zy_LayoutSubviews)];
});
}
- (void)zy_LayoutSubviews {
[self zy_LayoutSubviews];
if (self.zyIsRounding) {
[self zy_cornerRadiusWithImage:self.image cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
} else if (0 != self.zyRadius && 0 != self.roundingCorners && nil != self.image) {
[self zy_cornerRadiusWithImage:self.image cornerRadius:self.zyRadius rectCornerType:self.roundingCorners];
}
}
#pragma mark - KVO for .image
//- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// if ([keyPath isEqualToString:@"image"]) {
// UIImage *newImage = change[NSKeyValueChangeNewKey];
// if ([newImage isMemberOfClass:[NSNull class]]) {
// return;
// } else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) {
// return;
// }
// [self validateFrame];
// if (self.zyIsRounding) {
// [self zy_cornerRadiusWithImage:newImage cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
// } else if (0 != self.zyRadius && 0 != self.roundingCorners && nil != self.image) {
// [self zy_cornerRadiusWithImage:newImage cornerRadius:self.zyRadius rectCornerType:self.roundingCorners];
// }
// }
//}
#pragma mark property
- (CGFloat)zyBorderWidth {
return [objc_getAssociatedObject(self, _cmd) floatValue];
}
- (void)setZyBorderWidth:(CGFloat)zyBorderWidth {
objc_setAssociatedObject(self, @selector(zyBorderWidth), @(zyBorderWidth), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)zyBorderColor {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setZyBorderColor:(UIColor *)zyBorderColor {
objc_setAssociatedObject(self, @selector(zyBorderColor), zyBorderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)zyHadAddObserver {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setZyHadAddObserver:(BOOL)zyHadAddObserver {
objc_setAssociatedObject(self, @selector(zyHadAddObserver), @(zyHadAddObserver), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)zyIsRounding {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setZyIsRounding:(BOOL)zyIsRounding {
objc_setAssociatedObject(self, @selector(zyIsRounding), @(zyIsRounding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIRectCorner)roundingCorners {
return [objc_getAssociatedObject(self, _cmd) unsignedLongValue];
}
- (void)setRoundingCorners:(UIRectCorner)roundingCorners {
objc_setAssociatedObject(self, @selector(roundingCorners), @(roundingCorners), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (CGFloat)zyRadius {
return [objc_getAssociatedObject(self, _cmd) floatValue];
}
- (void)setZyRadius:(CGFloat)zyRadius {
objc_setAssociatedObject(self, @selector(zyRadius), @(zyRadius), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
//ZYCornerRadius is available under the MIT license.
//Please visit https://github.com/liuzhiyi1992/ZYCornerRadius for details.
@@ -0,0 +1,19 @@
//
// YYLabel+LineBreak.h
// WXReader
//
// Created by Andrew on 2020/4/2.
// Copyright © 2020 Andrew. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@interface UILabel (LineBreak)
- (void)setLineBreakByTruncatingLastLineMiddle;
- (NSArray *)getSeparatedLinesArray;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,93 @@
//
// YYLabel+LineBreak.m
// WXReader
//
// Created by Andrew on 2020/4/2.
// Copyright © 2020 Andrew. All rights reserved.
//
#import "UILabel+LineBreak.h"
@implementation UILabel (LineBreak)
- (void)setLineBreakByTruncatingLastLineMiddle {
if ( self.numberOfLines <= 0 ) {
return;
}
NSMutableString *limitedText = [NSMutableString string];
NSArray *separatedLines = [self getSeparatedLinesArray];
if (separatedLines > 0) {
for (int i = 0; i < separatedLines.count; i ++) {
if (i == separatedLines.count - 1) {
UILabel *lastLineLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width / 2, MAXFLOAT)];
lastLineLabel.font = self.font;
lastLineLabel.text = [separatedLines lastObject];
NSArray *subSeparatedLines = [lastLineLabel getSeparatedLinesArray];
NSString *lastLineText = [subSeparatedLines firstObject];
NSInteger lastLineTextCount = lastLineText.length;
[limitedText appendString:[NSString stringWithFormat:@"%@...",[lastLineText substringToIndex:lastLineTextCount]]];
} else {
[limitedText appendString:[separatedLines objectOrNilAtIndex:i]];
}
}
}
[self setText:limitedText lineSpacing:5];
}
-(void)setText:(NSString*)text lineSpacing:(CGFloat)lineSpacing {
if (!text || lineSpacing < 0.01) {
self.text = text;
return;
}
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:lineSpacing]; //设置行间距
[paragraphStyle setLineBreakMode:self.lineBreakMode];
[paragraphStyle setAlignment:self.textAlignment];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [text length])];
self.attributedText = attributedString;
}
- (NSArray *)getSeparatedLinesArray {
NSString *text = [self text];
if (!text || text.length <= 0) {
return @[@""];
}
UIFont *font = [self font];
CGRect rect = [self frame];
CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL);
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
[attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)];
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000));
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
NSMutableArray *linesArray = [[NSMutableArray alloc] init];
for (id line in lines) {
CTLineRef lineRef = (__bridge CTLineRef )line;
CFRange lineRange = CTLineGetStringRange(lineRef);
NSRange range = NSMakeRange(lineRange.location, lineRange.length);
NSString *lineString = [text substringWithRange:range];
[linesArray addObject:lineString];
}
return (NSArray *)linesArray;
}
@end
@@ -0,0 +1,22 @@
//
// UINavigationController+TFExtension.h
// WXReader
//
// Created by 谢腾飞 on 2020/12/1.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UINavigationController (TFExtension)
@property (nonatomic ,assign) BOOL isTransition;
// 执行转场动画
- (void)jumpNextViewController:(UIViewController *)viewController animated:(BOOL)animated;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,36 @@
//
// UINavigationController+TFExtension.m
// WXReader
//
// Created by 谢腾飞 on 2020/12/1.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#import "UINavigationController+TFExtension.h"
#import <objc/runtime.h>
static const char *transitionKey = "transitionKey";
@implementation UINavigationController (TFExtension)
- (void)setIsTransition:(BOOL)isTransition
{
objc_setAssociatedObject(self, transitionKey, @(isTransition), OBJC_ASSOCIATION_ASSIGN);
}
- (BOOL)isTransition
{
NSNumber *number = objc_getAssociatedObject(self, transitionKey);
return [number boolValue];
}
- (void)jumpNextViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[viewController setValue:[NSNumber numberWithBool:YES] forKey:@"isAT"];
self.delegate = (id<UINavigationControllerDelegate>)viewController;
self.isTransition = YES;
[self pushViewController:viewController animated:animated];
}
@end
@@ -0,0 +1,13 @@
//
// UIPageViewController+DPGestureDeal.h
// WXReader
//
// Created by Andrew on 2018/5/30.
// Copyright © 2018年 Andrew. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIPageViewController (DPGestureDeal)
@end
@@ -0,0 +1,31 @@
//
// UIPageViewController+DPGestureDeal.m
// WXReader
//
// Created by Andrew on 2018/5/30.
// Copyright © 2018年 Andrew. All rights reserved.
//
#import "UIPageViewController+DPGestureDeal.h"
#import "NSObject+YYAdd.h"
@implementation UIPageViewController (DPGestureDeal)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
[otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
return NO;
}
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
return NO;
}
return YES;
}
@end
@@ -0,0 +1,13 @@
//
// UIScrollView+UITouch.h
// WXReader
//
// Created by Andrew on 2018/7/7.
// Copyright © 2018年 Andrew. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIScrollView (UITouch)
@end
@@ -0,0 +1,20 @@
//
// UIScrollView+UITouch.m
// WXReader
//
// Created by Andrew on 2018/7/7.
// Copyright © 2018年 Andrew. All rights reserved.
//
#import "UIScrollView+UITouch.h"
@implementation UIScrollView (UITouch)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 选其一即可
[super touchesBegan:touches withEvent:event];
// [[self nextResponder] touchesBegan:touches withEvent:event];
}
@end
@@ -0,0 +1,35 @@
// The MIT License (MIT)
//
// Copyright (c) 2014 Suyeol Jeon (http:xoul.kr)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
@import UIKit;
FOUNDATION_EXPORT double UITextView_PlaceholderVersionNumber;
FOUNDATION_EXPORT const unsigned char UITextView_PlaceholderVersionString[];
@interface UITextView (Placeholder)
/* 占位文字 */
@property (nonatomic, copy) NSString *placeholder;
/* 占位文字颜色 */
@property (nonatomic, strong) UIColor *placeholderColor;
@end
@@ -0,0 +1,163 @@
// The MIT License (MIT)
//
// Copyright (c) 2014 Suyeol Jeon (http:xoul.kr)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#import <objc/runtime.h>
#import "UITextView+Placeholder.h"
// 占位文字
static const void *PlaceholderViewKey = &PlaceholderViewKey;
// 占位文字颜色
static const void *PlaceholderColorKey = &PlaceholderColorKey;
@implementation UITextView (Placeholder)
#pragma mark - Swizzle Dealloc
#pragma mark - Swizzle Dealloc
+ (void)load {
// 交换dealoc
Method dealoc = class_getInstanceMethod(self.class, NSSelectorFromString(@"dealloc"));
Method myDealoc = class_getInstanceMethod(self.class, @selector(myDealoc));
method_exchangeImplementations(dealoc, myDealoc);
}
- (void)myDealoc {
// 移除监听
[[NSNotificationCenter defaultCenter] removeObserver:self];
UITextView *placeholderView = objc_getAssociatedObject(self, PlaceholderViewKey);
// 如果有值才去调用,这步很重要
if (placeholderView) {
NSArray *propertys = @[@"frame", @"bounds", @"font", @"text", @"textAlignment", @"textContainerInset"];
for (NSString *property in propertys) {
@try {
[self removeObserver:self forKeyPath:property];
} @catch (NSException *exception) {}
}
}
[self myDealoc];
}
#pragma mark - set && get
- (UITextView *)placeholderView {
// 为了让占位文字和textView的实际文字位置能够完全一致,这里用UITextView
UITextView *placeholderView = objc_getAssociatedObject(self, PlaceholderViewKey);
if (!placeholderView) {
placeholderView = [[UITextView alloc] init];
placeholderView.hidden = (self.text.length > 0 && self.text);
// 动态添加属性的本质是: 让对象的某个属性与值产生关联
objc_setAssociatedObject(self, PlaceholderViewKey, placeholderView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
placeholderView = placeholderView;
// 设置基本属性
self.scrollEnabled = placeholderView.scrollEnabled = placeholderView.showsHorizontalScrollIndicator = placeholderView.showsVerticalScrollIndicator = placeholderView.userInteractionEnabled = NO;
placeholderView.textColor = [UIColor lightGrayColor];
placeholderView.backgroundColor = [UIColor clearColor];
[self refreshPlaceholderView];
[self addSubview:placeholderView];
// 监听文字改变
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextChange) name:UITextViewTextDidChangeNotification object:self];
// 这些属性改变时,都要作出一定的改变,尽管已经监听了TextDidChange的通知,也要监听text属性,因为通知监听不到setText:
NSArray *propertys = @[@"frame", @"bounds", @"font", @"text", @"textAlignment", @"textContainerInset"];
// 监听属性
for (NSString *property in propertys) {
[self addObserver:self forKeyPath:property options:NSKeyValueObservingOptionNew context:nil];
}
}
return placeholderView;
}
- (void)setPlaceholder:(NSString *)placeholder
{
// 为placeholder赋值
[self placeholderView].text = placeholder;
}
- (NSString *)placeholder
{
// 如果有placeholder值才去调用,这步很重要
if (self.placeholderExist) {
return [self placeholderView].text;
}
return nil;
}
- (void)setPlaceholderColor:(UIColor *)placeholderColor
{
self.placeholderView.textColor = placeholderColor;
}
- (UIColor *)placeholderColor {
return self.placeholderView.textColor;
}
#pragma mark - KVO监听属性改变
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
[self refreshPlaceholderView];
if ([keyPath isEqualToString:@"text"]) [self textViewTextChange];
}
- (void)refreshPlaceholderView {
UITextView *placeholderView = objc_getAssociatedObject(self, PlaceholderViewKey);
// 如果有值才去调用,这步很重要
if (placeholderView) {
self.placeholderView.frame = self.bounds;
self.placeholderView.font = self.font;
self.placeholderView.textAlignment = self.textAlignment;
self.placeholderView.textContainerInset = self.textContainerInset;
}
}
- (void)textViewTextChange {
UITextView *placeholderView = objc_getAssociatedObject(self, PlaceholderViewKey);
// 如果有值才去调用,这步很重要
if (placeholderView) {
self.placeholderView.hidden = (self.text.length > 0 && self.text);
}
if (!self.isFirstResponder) [self becomeFirstResponder];
}
// 判断是否有placeholder值,这步很重要
- (BOOL)placeholderExist {
// 获取对应属性的值
UITextView *placeholderView = objc_getAssociatedObject(self, PlaceholderViewKey);
// 如果有placeholder值
if (placeholderView) return YES;
return NO;
}
@end
@@ -0,0 +1,42 @@
//
// UIView+AZGradient.h
// AZCategory
//
// Created by Alfred Zhang on 2017/6/29.
// Copyright © 2017年 Alfred Zhang. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (AZGradient)
/* The array of CGColorRef objects defining the color of each gradient
* stop. Defaults to nil. Animatable. */
@property(nullable, copy) NSArray *az_colors;
/* An optional array of NSNumber objects defining the location of each
* gradient stop as a value in the range [0,1]. The values must be
* monotonically increasing. If a nil array is given, the stops are
* assumed to spread uniformly across the [0,1] range. When rendered,
* the colors are mapped to the output colorspace before being
* interpolated. Defaults to nil. Animatable. */
@property(nullable, copy) NSArray<NSNumber *> *az_locations;
/* The start and end points of the gradient when drawn into the layer's
* coordinate space. The start point corresponds to the first gradient
* stop, the end point to the last gradient stop. Both points are
* defined in a unit coordinate space that is then mapped to the
* layer's bounds rectangle when drawn. (I.e. [0,0] is the bottom-left
* corner of the layer, [1,1] is the top-right corner.) The default values
* are [.5,0] and [.5,1] respectively. Both are animatable. */
@property CGPoint az_startPoint;
@property CGPoint az_endPoint;
+ (UIView *_Nullable)az_gradientViewWithColors:(NSArray<UIColor *> *_Nullable)colors locations:(NSArray<NSNumber *> *_Nullable)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint;
- (void)az_setGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors locations:(NSArray<NSNumber *> *_Nullable)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint;
@end
@@ -0,0 +1,93 @@
//
// UIView+AZGradient.m
// AZCategory
//
// Created by Alfred Zhang on 2017/6/29.
// Copyright © 2017年 Alfred Zhang. All rights reserved.
//
#import "UIView+AZGradient.h"
#import <objc/runtime.h>
@implementation UIView (AZGradient)
+ (Class)layerClass {
return [CAGradientLayer class];
}
+ (UIView *)az_gradientViewWithColors:(NSArray<UIColor *> *)colors locations:(NSArray<NSNumber *> *)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
UIView *view = [[self alloc] init];
[view az_setGradientBackgroundWithColors:colors locations:locations startPoint:startPoint endPoint:endPoint];
return view;
}
- (void)az_setGradientBackgroundWithColors:(NSArray<UIColor *> *)colors locations:(NSArray<NSNumber *> *)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
self.az_colors = [colorsM copy];
self.az_locations = locations;
self.az_startPoint = startPoint;
self.az_endPoint = endPoint;
}
#pragma mark- Getter&Setter
- (NSArray *)az_colors {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setAz_colors:(NSArray *)colors {
objc_setAssociatedObject(self, @selector(az_colors), colors, OBJC_ASSOCIATION_COPY_NONATOMIC);
if ([self.layer isKindOfClass:[CAGradientLayer class]]) {
[((CAGradientLayer *)self.layer) setColors:self.az_colors];
}
}
- (NSArray<NSNumber *> *)az_locations {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setAz_locations:(NSArray<NSNumber *> *)locations {
objc_setAssociatedObject(self, @selector(az_locations), locations, OBJC_ASSOCIATION_COPY_NONATOMIC);
if ([self.layer isKindOfClass:[CAGradientLayer class]]) {
[((CAGradientLayer *)self.layer) setLocations:self.az_locations];
}
}
- (CGPoint)az_startPoint {
return [objc_getAssociatedObject(self, _cmd) CGPointValue];
}
- (void)setAz_startPoint:(CGPoint)startPoint {
objc_setAssociatedObject(self, @selector(az_startPoint), [NSValue valueWithCGPoint:startPoint], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if ([self.layer isKindOfClass:[CAGradientLayer class]]) {
[((CAGradientLayer *)self.layer) setStartPoint:self.az_startPoint];
}
}
- (CGPoint)az_endPoint {
return [objc_getAssociatedObject(self, _cmd) CGPointValue];
}
- (void)setAz_endPoint:(CGPoint)endPoint {
objc_setAssociatedObject(self, @selector(az_endPoint), [NSValue valueWithCGPoint:endPoint], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if ([self.layer isKindOfClass:[CAGradientLayer class]]) {
[((CAGradientLayer *)self.layer) setEndPoint:self.az_endPoint];
}
}
@end
@implementation UILabel (AZGradient)
+ (Class)layerClass {
return [CAGradientLayer class];
}
@end
@@ -0,0 +1,72 @@
//
// UIView+BorderLine.h
// WXReader
//
// Created by Andrew on 2018/5/24.
// Copyright © 2018年 Andrew. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef NS_OPTIONS(NSUInteger, UIBorderSideType) {
UIBorderSideTypeAll = 0, // 全边框
UIBorderSideTypeTop = 1 << 0, // 上侧边框
UIBorderSideTypeBottom = 1 << 1, // 下侧边框
UIBorderSideTypeLeft = 1 << 2, // 左侧边框
UIBorderSideTypeRight = 1 << 3, // 右侧边框
};
typedef NS_OPTIONS(NSUInteger, UIBorderConnerType) {
UIBorderConnerTypeLeftTop = 0, // 左上
UIBorderConnerTypeLeftBottom = 1 << 0, // 左下
UIBorderConnerTypeRightTop = 1 << 1, // 右上
UIBorderConnerTypeRightBottom = 1 << 2, // 右下
UIBorderConnerTypeTopLeft = 1 << 3, // 上左
UIBorderConnerTypeTopRight = 1 << 4, // 上右
UIBorderConnerTypeBottomLeft = 1 << 5, // 下左
UIBorderConnerTypeBottomRight = 1 << 6, // 下右
};
@interface UIView (BorderLine)
/**
增加边框
@param borderWidth 边框宽度
@param borderColor 边框颜色
@param cornerRadius 边框圆角
*/
- (void)addBorderLineWithBorderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor cornerRadius:(CGFloat)cornerRadius;
/**
增加边框
@param borderWidth 边框宽度
@param borderColor 边框颜色
@param cornerRadius 边框圆角
@param borderType 边框类型
*/
- (void)addBorderLineWithBorderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor cornerRadius:(CGFloat)cornerRadius borderType:(UIBorderSideType)borderType;
/**
增加边框
@param borderWidth 边框宽度
@param borderColor 边框颜色
@param cornerRadius 边框圆角
@param borderType 边框类型
@param connerSpaceWidth 角边距离
@param connerType 角边类型
*/
- (void)addBorderLineWithBorderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor cornerRadius:(CGFloat)cornerRadius borderType:(UIBorderSideType)borderType connerSpaceWidth:(CGFloat)connerSpaceWidth connerType:(UIBorderConnerType)connerType;
// 设置正常背景色
- (void)normalBackgroundColor;
// 设置选中背景色
- (void)selectBackgroundColor;
// 添加圆角
- (void)addRoundingCornersWithRoundingCorners:(UIRectCorner)corners;
@end
@@ -0,0 +1,115 @@
//
// UIView+BorderLine.m
// WXReader
//
// Created by Andrew on 2018/5/24.
// Copyright © 2018年 Andrew. All rights reserved.
//
#import "UIView+BorderLine.h"
@implementation UIView (BorderLine)
- (void)addBorderLineWithBorderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor cornerRadius:(CGFloat)cornerRadius borderType:(UIBorderSideType)borderType connerSpaceWidth:(CGFloat)connerSpaceWidth connerType:(UIBorderConnerType)connerType
{
}
- (void)addBorderLineWithBorderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor cornerRadius:(CGFloat)cornerRadius borderType:(UIBorderSideType)borderType
{
CGFloat space = borderWidth / 2;
switch (borderType) {
case UIBorderSideTypeAll: {
CAShapeLayer *lineBorder = [[CAShapeLayer alloc] init];
lineBorder.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
[lineBorder setLineWidth:borderWidth];
[lineBorder setStrokeColor:borderColor.CGColor];
[lineBorder setFillColor:[UIColor clearColor].CGColor];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:lineBorder.frame byRoundingCorners:UIRectCornerAllCorners cornerRadii:(CGSizeMake(cornerRadius, cornerRadius))];
lineBorder.path = path.CGPath;
[self.layer addSublayer:lineBorder];
}
break;
case UIBorderSideTypeLeft: {
[self.layer addSublayer:[self addLineOriginPoint:CGPointMake(0.f, 0.f + space) toPoint:CGPointMake(0.0f, self.frame.size.height - space) color:borderColor borderWidth:borderWidth]];
}
break;
case UIBorderSideTypeRight: {
[self.layer addSublayer:[self addLineOriginPoint:CGPointMake(self.frame.size.width, 0.0f + space) toPoint:CGPointMake(self.frame.size.width, self.frame.size.height - space) color:borderColor borderWidth:borderWidth]];
}
break;
case UIBorderSideTypeTop: {
[self.layer addSublayer:[self addLineOriginPoint:CGPointMake(0.0f + space, 0.0f) toPoint:CGPointMake(self.frame.size.width - space, 0.0f) color:borderColor borderWidth:borderWidth]];
}
break;
case UIBorderSideTypeBottom: {
[self.layer addSublayer:[self addLineOriginPoint:CGPointMake(0.0f + space, self.frame.size.height) toPoint:CGPointMake(self.frame.size.width - space, self.frame.size.height) color:borderColor borderWidth:borderWidth]];
}
break;
default:
break;
}
}
- (void)addBorderLineWithBorderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor cornerRadius:(CGFloat)cornerRadius
{
[self addBorderLineWithBorderWidth:borderWidth borderColor:borderColor cornerRadius:cornerRadius borderType:UIBorderSideTypeAll];
}
- (CAShapeLayer *)addLineOriginPoint:(CGPoint)p0 toPoint:(CGPoint)p1 color:(UIColor *)color borderWidth:(CGFloat)borderWidth {
/// 线的路径
UIBezierPath * bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint:p0];
[bezierPath addLineToPoint:p1];
CAShapeLayer * shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = color.CGColor;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
/// 添加路径
shapeLayer.path = bezierPath.CGPath;
/// 线宽度
shapeLayer.lineWidth = borderWidth;
return shapeLayer;
}
- (void)normalBackgroundColor
{
//创建一个渐变的图层
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = @[(__bridge id)[UIColor colorWithHexString:@"#ffb084"].CGColor, (__bridge id)[UIColor colorWithHexString:@"#fd9a63"].CGColor];
gradientLayer.locations = @[@0, @1.0];
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(0, 1.0);
gradientLayer.frame = self.bounds;
gradientLayer.name = @"gradientLayer";
//生成一个image
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0.0);
[gradientLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//设置背景颜色
self.backgroundColor = [UIColor colorWithPatternImage:img];
}
- (void)selectBackgroundColor
{
self.backgroundColor = kColorRGBA(0, 0, 0, 0.2);
}
// 添加圆角
- (void)addRoundingCornersWithRoundingCorners:(UIRectCorner)corners
{
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(12, 12)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
@end
@@ -0,0 +1,29 @@
//
// UIView+LayoutSubviewsCallback.h
// iOS_TEST
//
// Created by Chair on 2019/11/24.
// Copyright © 2019 Chair. All rights reserved.
//
//#import <AppKit/AppKit.h>
#import <UIKit/UIKit.h>
#import "UIButton+LayoutCallback.h"
NS_ASSUME_NONNULL_BEGIN
@interface UIView (LayoutCallback)
#if ENABLE_SWIZZ_IN_SIMPLEFrame
/** 子视图布局完成后返回自身 */
@property (nonatomic, copy) void(^frameBlock)(UIView *view);
#endif
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,42 @@
//
// UIView+LayoutSubviewsCallback.m
// iOS_TEST
//
// Created by Chair on 2019/11/24.
// Copyright © 2019 Chair. All rights reserved.
//
#import "UIView+LayoutCallback.h"
#import <objc/runtime.h>
static const char * identifier = "identifier";
@implementation UIView (LayoutCallback)
#if ENABLE_SWIZZ_IN_SIMPLEFrame
+ (void)load {
Method method1 = class_getInstanceMethod(self, @selector(layoutSubviews));
Method method2 = class_getInstanceMethod(self, @selector(xl_layoutSubviews));
method_exchangeImplementations(method1, method2);
}
- (void)xl_layoutSubviews {
[self xl_layoutSubviews];
!self.frameBlock ?: self.frameBlock(self);
}
- (void)setFrameBlock:(void (^)(UIView * _Nonnull))frameBlock {
if (frameBlock == nil) return ;
objc_setAssociatedObject(self, identifier, frameBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void (^)(UIView * _Nonnull))frameBlock {
return objc_getAssociatedObject(self, identifier);
}
#endif
@end
@@ -0,0 +1,29 @@
//
// UIView+TFExtension.h
// EmotionFM
//
// Created by 谢腾飞 on 2018/10/27.
// Copyright © 2018 xtfei_2011@126.com. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (TFExtension)
@property (nonatomic ,assign) CGPoint xtfei_origin;
@property (nonatomic ,assign) CGSize xtfei_size;
@property (nonatomic ,assign) CGFloat xtfei_width;
@property (nonatomic ,assign) CGFloat xtfei_height;
@property (nonatomic ,assign) CGFloat xtfei_x;
@property (nonatomic ,assign) CGFloat xtfei_y;
@property (nonatomic ,assign) CGFloat xtfei_centerX;
@property (nonatomic ,assign) CGFloat xtfei_centerY;
@property (nonatomic ,assign) CGFloat xtfei_right;
@property (nonatomic ,assign) CGFloat xtfei_bottom;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,129 @@
//
// UIView+TFExtension.m
// EmotionFM
//
// Created by 谢腾飞 on 2018/10/27.
// Copyright © 2018 xtfei_2011@126.com. All rights reserved.
//
#import "UIView+TFExtension.h"
@implementation UIView (TFExtension)
- (CGPoint)xtfei_origin
{
return self.frame.origin;
}
- (void)setXtfei_origin:(CGPoint)point
{
CGRect rect = self.frame;
rect.origin = point;
self.frame = rect;
}
- (CGSize)xtfei_size
{
return self.frame.size;
}
- (void)setXtfei_size:(CGSize)xtfei_size
{
CGRect frame = self.frame;
frame.size = xtfei_size;
self.frame = frame;
}
- (CGFloat)xtfei_width
{
return self.frame.size.width;
}
- (CGFloat)xtfei_height
{
return self.frame.size.height;
}
- (void)setXtfei_width:(CGFloat)xtfei_width
{
CGRect frame = self.frame;
frame.size.width = xtfei_width;
self.frame = frame;
}
- (void)setXtfei_height:(CGFloat)xtfei_height
{
CGRect frame = self.frame;
frame.size.height = xtfei_height;
self.frame = frame;
}
- (CGFloat)xtfei_x
{
return self.frame.origin.x;
}
- (void)setXtfei_x:(CGFloat)xtfei_x
{
CGRect frame = self.frame;
frame.origin.x = xtfei_x;
self.frame = frame;
}
- (CGFloat)xtfei_y
{
return self.frame.origin.y;
}
- (void)setXtfei_y:(CGFloat)xtfei_y
{
CGRect frame = self.frame;
frame.origin.y = xtfei_y;
self.frame = frame;
}
- (CGFloat)xtfei_centerX
{
return self.center.x;
}
- (void)setXtfei_centerX:(CGFloat)xtfei_centerX
{
CGPoint center = self.center;
center.x = xtfei_centerX;
self.center = center;
}
- (CGFloat)xtfei_centerY
{
return self.center.y;
}
- (void)setXtfei_centerY:(CGFloat)xtfei_centerY
{
CGPoint center = self.center;
center.y = xtfei_centerY;
self.center = center;
}
- (CGFloat)xtfei_right
{
return CGRectGetMaxX(self.frame);
}
- (CGFloat)xtfei_bottom
{
return CGRectGetMaxY(self.frame);
}
- (void)setXtfei_right:(CGFloat)xtfei_right
{
self.xtfei_x = xtfei_right - self.xtfei_width;
}
- (void)setXtfei_bottom:(CGFloat)xtfei_bottom
{
self.xtfei_y = xtfei_bottom - self.xtfei_height;
}
@end
@@ -0,0 +1,21 @@
//
// UIViewController+Present.h
// WXReader
//
// Created by Andrew on 2019/10/9.
// Copyright © 2019 Andrew. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIViewController (Present)
@property (nonatomic, assign) BOOL LL_automaticallySetModalPresentationStyle;
+ (BOOL)LL_automaticallySetModalPresentationStyle;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,53 @@
//
// UIViewController+Present.m
// WXReader
//
// Created by Andrew on 2019/10/9.
// Copyright © 2019 Andrew. All rights reserved.
//
#import "UIViewController+Present.h"
#import <objc/runtime.h>
static const char *LL_automaticallySetModalPresentationStyleKey;
@implementation UIViewController (Present)
+ (void)load {
Method originAddObserverMethod = class_getInstanceMethod(self, @selector(presentViewController:animated:completion:));
Method swizzledAddObserverMethod = class_getInstanceMethod(self, @selector(LL_presentViewController:animated:completion:));
method_exchangeImplementations(originAddObserverMethod, swizzledAddObserverMethod);
}
- (void)setLL_automaticallySetModalPresentationStyle:(BOOL)LL_automaticallySetModalPresentationStyle {
objc_setAssociatedObject(self, LL_automaticallySetModalPresentationStyleKey, @(LL_automaticallySetModalPresentationStyle), OBJC_ASSOCIATION_ASSIGN);
}
- (BOOL)LL_automaticallySetModalPresentationStyle {
id obj = objc_getAssociatedObject(self, LL_automaticallySetModalPresentationStyleKey);
if (obj) {
return [obj boolValue];
}
return [self.class LL_automaticallySetModalPresentationStyle];
}
+ (BOOL)LL_automaticallySetModalPresentationStyle {
if ([self isKindOfClass:[UIImagePickerController class]] || [self isKindOfClass:[UIAlertController class]]) {
return NO;
}
return YES;
}
- (void)LL_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
if (@available(iOS 13.0, *)) {
if (viewControllerToPresent.LL_automaticallySetModalPresentationStyle && ![NSStringFromClass([viewControllerToPresent class]) isEqualToString:@"BUDislikeViewController"] && ![NSStringFromClass([viewControllerToPresent class]) isEqualToString:@"BUDislikeNewViewController"]) {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationFullScreen;
}
[self LL_presentViewController:viewControllerToPresent animated:flag completion:completion];
} else {
// Fallback on earlier versions
[self LL_presentViewController:viewControllerToPresent animated:flag completion:completion];
}
}
@end
@@ -0,0 +1,17 @@
//
// YYAnimatedImageView+Util.h
// WXReader
//
// Created by LL on 2020/10/9.
// Copyright © 2020 Andrew. All rights reserved.
//
#import "YYAnimatedImageView.h"
NS_ASSUME_NONNULL_BEGIN
@interface YYAnimatedImageView (Util)
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,37 @@
//
// YYAnimatedImageView+Util.m
// WXReader
//
// Created by LL on 2020/10/9.
// Copyright © 2020 Andrew. All rights reserved.
//
#import "YYAnimatedImageView+Util.h"
@implementation YYAnimatedImageView (Util)
+ (void)load {
// 获取系统的对象方法
Method displayLayerMethod = class_getInstanceMethod(self, @selector(displayLayer:));
// 获取自己定义的对象方法
Method displayLayerNewMethod = class_getInstanceMethod(self, @selector(displayLayerNew:));
// 方法交换
method_exchangeImplementations(displayLayerMethod, displayLayerNewMethod);
}
- (void)displayLayerNew:(CALayer *)layer {
Ivar imgIvar = class_getInstanceVariable([self class], "_curFrame");
UIImage *img = object_getIvar(self, imgIvar);
if (img) {
layer.contents = (__bridge id)img.CGImage;
} else {
if (@available(iOS 14.0, *)) {
[super displayLayer:layer];
}
}
}
@end
@@ -0,0 +1,68 @@
//
// TFColorConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFColorConfig_h
#define TFColorConfig_h
/*
颜色获取方法
*/
#define kColorRGBA(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)]
#define kColorRGB(r,g,b) kColorRGBA(r,g,b,1)
// 随机色
#define kRandomColor kColorRGBA(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256), 1)
#define kColorXRGB(rgbValue) [UIColor \
colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
blue:((float)(rgbValue & 0xFF))/255.0 alpha:1] //十六进制颜色(不带透明度)
/*
色调值 命名方式 k+颜色+Color
*/
// 主色调
#define kMainColorMagicAlpha(x) kColorRGBA(255, 153, 102, x)
#define kMainColor kMainColorAlpha(1)
#define kMainColorAlpha(x) ([TFUtilsHelper isInSafetyPeriod] ? kMainColorMagicAlpha(x) : kColorRGBA(255, 153, 102, x))
// 颜色管理
#define kBlackColor kColorRGBA(57, 56, 60, 1)
#define kWhiteColor kColorRGBA(255, 255, 255, 1)
#define kRedColor kColorRGBA(231, 85, 79, 1)
#define kGrayLineColor kColorRGBA(240, 238, 245, 1)
#define kGrayViewColor kColorRGBA(249, 249, 249, 1)
#define kGrayDeepViewColor kColorRGBA(241, 242, 241, 1)
#define kGrayTextColor kColorRGBA(176, 176, 176, 1)
#define kGrayTextLightColor kColorRGBA(153, 153, 153, 1)
#define KGrayTextMiddleColor kColorRGBA(102, 102, 102, 1)
#define kGrayTextDeepColor kColorRGBA(77, 77, 75, 1)
#define kBlackTransparentColor kColorRGBA(0, 0, 0, 0.5)
#define kBlackTransparentAlphaColor(x) kColorRGBA(0, 0, 0, x)
#define HoldImage [UIImage imageNamed:@"public_hold_image"]
#define HoldUserAvatar [UIImage imageNamed:@"hold_user_avatar_boy"]
#endif /* TFColorConfig_h */
@@ -0,0 +1,39 @@
//
// TFDefineConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFDefineConfig_h
#define TFDefineConfig_h
// 将属性转换为字符串(PS:不要在属性的get方法里调用自身)
#define KEY_PATH(objc, property) ((void)objc.property, @(#property))
// 随机整数
#define kRandom_Integer(from, to) ((NSInteger)(from + (arc4random() % (to - from + 1))))
// 随机小数
#define kRandom_Float(from, to) ({\
float result = 0.0;\
NSInteger precision = 100;\
CGFloat subtraction = to - from;\
subtraction = ABS(subtraction);\
subtraction *= precision;\
CGFloat randomNumber = arc4random() % ((int)subtraction + 1);\
randomNumber /= precision;\
result = MIN(from, to) + randomNumber;\
})
// NSInteger转NSString
#define NSStringFromInteger(x) [NSString stringWithFormat:@"%zd", x]
// 判断对象是否为空
#define kObjectIsEmpty(object) !( \
([object respondsToSelector:@selector(length)] && [(NSData *)object length] > 0) || \
([object respondsToSelector:@selector(count)] && [(NSArray *)object count] > 0) || \
([object respondsToSelector:@selector(floatValue)] && [(id)object floatValue] != 0.0))
#endif /* TFDefineConfig_h */
@@ -0,0 +1,198 @@
//
// TFFrameConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFFrameConfig_h
#define TFFrameConfig_h
// 屏幕宽高
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
#define SCREEN_WIDTH ([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)]?[UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale:[UIScreen mainScreen].bounds.size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)]?[UIScreen mainScreen].nativeBounds.size.height/[UIScreen mainScreen].nativeScale:[UIScreen mainScreen].bounds.size.height)
#else
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
#endif
// iPhone X 适配 Nav 和 Tabber 高度和偏移数
#define PUB_NAVBAR_HEIGHT (is_iPhoneX ? 88.0f : 64.0f)
#define PUB_NAVBAR_OFFSET (is_iPhoneX ? 24.0f : 0.0f)
#define PUB_TABBAR_HEIGHT (50.0f + PUB_TABBAR_OFFSET)
#define PUB_TABBAR_OFFSET ({\
CGFloat temp = 0.0;\
if (@available(iOS 11.0, *)) {\
temp = [kRCodeSync(@([[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom)) floatValue];\
} else {\
temp = 0.0;\
}\
temp;\
})
// 状态栏高度
#define kStatusBarHeight (([[UIApplication sharedApplication] isStatusBarHidden]) ? (is_iPhoneX ? 44.0 : 20.0) : [[UIApplication sharedApplication] statusBarFrame].size.height)
// 固定单位
#define kMargin 20.0f
#define kMoreHalfMargin 15.0f
#define kHalfMargin 10.0f
#define kQuarterMargin 5.0f
#define kCellLineHeight (is_iPhone6?0.5f:0.4f)
#define kLabelHeight 30.0f
#define KCellHeight 40.0f
#define kiPhone6W 375.0
#define kiPhone6H 667.0
#define kScaleX SCREEN_WIDTH / kiPhone6W
#define kScaleY SCREEN_HEIGHT / kiPhone6H
// 比例高度
#define kGeometricHeight(viewWidth, width, height) (((viewWidth) * (height)) / (width))
// 比例宽度
#define kGeometricWidth(viewHeight, width, height) (((viewHeight) * (width)) / (height))
// 比例X坐标
#define kLineX(x) x*kScaleX
// 比例Y坐标
#define kLineY(y) y*kScaleY
// 小尺寸书籍宽度
#define BOOK_WIDTH_SMALL (BOOK_WIDTH - 20)
// 小尺寸书籍高度
#define BOOK_HEIGHT_SMALL (kGeometricHeight(BOOK_WIDTH_SMALL, 3, 4))
// 书籍宽度
#define BOOK_WIDTH ((SCREEN_WIDTH - 4 * kHalfMargin) / 3)
// 书籍高度
#define BOOK_HEIGHT kGeometricHeight(BOOK_WIDTH, 3, 4)
// 标题高度
#define BOOK_CELL_TITLE_HEIGHT 40
/*
Font
*/
// 字体适配
#define kFont(value) [UIFont systemFontOfSize:value * kScaleX]
// 粗字体适配
#define kBoldFont(value) [UIFont boldSystemFontOfSize:value * kScaleX]
#define kMainFont [UIFont systemFontOfSize:kFontSize14]
#define kBoldMainFont kBoldFont14
// 字号偏移量
#define kFontOffset (is_iPhoneX_Max?2.0f:1.0f)
#define kFont5 [UIFont systemFontOfSize:kFontSize5]
#define kFont6 [UIFont systemFontOfSize:kFontSize6]
#define kFont7 [UIFont systemFontOfSize:kFontSize7]
#define kFont8 [UIFont systemFontOfSize:kFontSize8]
#define kFont9 [UIFont systemFontOfSize:kFontSize9]
#define kFont10 [UIFont systemFontOfSize:kFontSize10]
#define kFont11 [UIFont systemFontOfSize:kFontSize11]
#define kFont12 [UIFont systemFontOfSize:kFontSize12]
#define kFont13 [UIFont systemFontOfSize:kFontSize13]
#define kFont14 [UIFont systemFontOfSize:kFontSize14]
#define kFont15 [UIFont systemFontOfSize:kFontSize15]
#define kFont16 [UIFont systemFontOfSize:kFontSize16]
#define kFont17 [UIFont systemFontOfSize:kFontSize17]
#define kFont18 [UIFont systemFontOfSize:kFontSize18]
#define kFont19 [UIFont systemFontOfSize:kFontSize19]
#define kFont20 [UIFont systemFontOfSize:kFontSize20]
#define kFont21 [UIFont systemFontOfSize:kFontSize21]
#define kFont22 [UIFont systemFontOfSize:kFontSize22]
#define kFont23 [UIFont systemFontOfSize:kFontSize23]
#define kFont24 [UIFont systemFontOfSize:kFontSize24]
#define kFont25 [UIFont systemFontOfSize:kFontSize25]
#define kFont26 [UIFont systemFontOfSize:kFontSize26]
#define kFont27 [UIFont systemFontOfSize:kFontSize27]
#define kFont28 [UIFont systemFontOfSize:kFontSize28]
#define kFont29 [UIFont systemFontOfSize:kFontSize29]
#define kFont30 [UIFont systemFontOfSize:kFontSize30]
#define kBoldFont5 [UIFont boldSystemFontOfSize:kFontSize5]
#define kBoldFont6 [UIFont boldSystemFontOfSize:kFontSize6]
#define kBoldFont7 [UIFont boldSystemFontOfSize:kFontSize7]
#define kBoldFont8 [UIFont boldSystemFontOfSize:kFontSize8]
#define kBoldFont9 [UIFont boldSystemFontOfSize:kFontSize9]
#define kBoldFont10 [UIFont boldSystemFontOfSize:kFontSize10]
#define kBoldFont11 [UIFont boldSystemFontOfSize:kFontSize11]
#define kBoldFont12 [UIFont boldSystemFontOfSize:kFontSize12]
#define kBoldFont13 [UIFont boldSystemFontOfSize:kFontSize13]
#define kBoldFont14 [UIFont boldSystemFontOfSize:kFontSize14]
#define kBoldFont15 [UIFont boldSystemFontOfSize:kFontSize15]
#define kBoldFont16 [UIFont boldSystemFontOfSize:kFontSize16]
#define kBoldFont17 [UIFont boldSystemFontOfSize:kFontSize17]
#define kBoldFont18 [UIFont boldSystemFontOfSize:kFontSize18]
#define kBoldFont19 [UIFont boldSystemFontOfSize:kFontSize19]
#define kBoldFont20 [UIFont boldSystemFontOfSize:kFontSize20]
#define kBoldFont21 [UIFont boldSystemFontOfSize:kFontSize21]
#define kBoldFont22 [UIFont boldSystemFontOfSize:kFontSize22]
#define kBoldFont23 [UIFont boldSystemFontOfSize:kFontSize23]
#define kBoldFont24 [UIFont boldSystemFontOfSize:kFontSize24]
#define kBoldFont25 [UIFont boldSystemFontOfSize:kFontSize25]
#define kBoldFont26 [UIFont boldSystemFontOfSize:kFontSize26]
#define kBoldFont27 [UIFont boldSystemFontOfSize:kFontSize27]
#define kBoldFont28 [UIFont boldSystemFontOfSize:kFontSize28]
#define kBoldFont29 [UIFont boldSystemFontOfSize:kFontSize29]
#define kBoldFont30 [UIFont boldSystemFontOfSize:kFontSize30]
#define kFontSize5 5.0f + kFontOffset
#define kFontSize6 6.0f + kFontOffset
#define kFontSize7 7.0f + kFontOffset
#define kFontSize8 8.0f + kFontOffset
#define kFontSize9 9.0f + kFontOffset
#define kFontSize10 10.0f + kFontOffset
#define kFontSize11 11.0f + kFontOffset
#define kFontSize12 12.0f + kFontOffset
#define kFontSize13 13.0f + kFontOffset
#define kFontSize14 14.0f + kFontOffset
#define kFontSize15 15.0f + kFontOffset
#define kFontSize16 16.0f + kFontOffset
#define kFontSize17 17.0f + kFontOffset
#define kFontSize18 18.0f + kFontOffset
#define kFontSize19 19.0f + kFontOffset
#define kFontSize20 20.0f + kFontOffset
#define kFontSize21 21.0f + kFontOffset
#define kFontSize22 22.0f + kFontOffset
#define kFontSize23 23.0f + kFontOffset
#define kFontSize24 24.0f + kFontOffset
#define kFontSize25 25.0f + kFontOffset
#define kFontSize26 26.0f + kFontOffset
#define kFontSize27 27.0f + kFontOffset
#define kFontSize28 28.0f + kFontOffset
#define kFontSize29 29.0f + kFontOffset
#define kFontSize30 30.0f + kFontOffset
// ANIMATION_DURATION
#define kAnimatedDuration 0.4f
#define kAnimatedDurationFast 0.2f
#endif /* TFFrameConfig_h */
@@ -0,0 +1,71 @@
//
// TFImportConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFImportConfig_h
#define TFImportConfig_h
//工具类
#import "TFUtilsHelper.h"
#import "TFViewHelper.h"
#import "TFColorHelper.h"
#import "TFNetworkTools.h"
#import "TFUserInfoManager.h"
#import "TFSystemInfoManager.h"
#import "TFPromptManager.h"
#import "TFNetworkManager.h"
#import "TFLanguageManager.h"
// controller
#import "TFBasicViewController.h"
#import "TFNavigationController.h"
#import "TFNovelDetailViewController.h"
#import "TFComicDetailViewController.h"
#import "TFAudioDetailViewController.h"
#import "TFLoginOptionsViewController.h"
#import "TFBookStoreMoreViewController.h"
// view
#import "TFBasicTableViewCell.h"
// category
#import "UIView+BorderLine.h"
#import "NSObject+LSDefaults.h"
#import "UIViewController+Present.h"
#import "UIImageView+CornerRadius.h"
#pragma mark Category
#import "UIView+TFExtension.h"
#import "TFButton+TFExtension.h"
// Model
#import "TFBannerModel.h"
#import "TFBookRackModel.h"
#import "TFBookStoreModel.h"
#import "TFTagModel.h"
#import "TFProductionModel.h"
#import "TFProductionChapterModel.h"
#import "TFProductionListModel.h"
#import "TFCheckSettingModel.h"
#import "TFCommentsModel.h"
// 三方库
#import "YYKit.h"
#import <MJRefresh/MJRefresh.h>
#import "TFButton.h"
#import "TFProductionCoverView.h"
#import "TFAlertView.h"
#import "TFEmptyViewHeader.h"
#import "TFRefreshFooter.h"
#import "TFRefreshHeader.h"
#import <Masonry.h>
#import <SGPagingView/SGPagingView.h>
#import "UIScrollView+TFRefresh.h"
#endif /* TFImportConfig_h */
@@ -0,0 +1,58 @@
//
// TFMemoryConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFMemoryConfig_h
#define TFMemoryConfig_h
#define TF_READER_FONT @"xtfei_reader_font"
#define TF_READER_BACKVIEW @"xtfei_reader_backgroundView"
#define TF_READER_LINESPACING @"xtfei_reader_linespacing"
#define TF_READER_TRANSITION_STYLE @"xtfei_reader_transition_style"
#define TF_READER_NIGHT_MODE @"xtfei_reader_night_mode"
#define TF_READER_CHAPTER_INDEX @"xtfei_reader_chapter_index"
#define TF_READER_READ_SPEED @"xtfei_reader_read_speed"
#define TF_READER_PAGER_INDEX @"xtfei_reader_pager_index"
#define TF_TABBAR_SELECT_MEMORY @"xtfei_tabbar_select_memory"
#define TF_GUIDE_SHOW @"xtfei_guide_num"
#define TF_START_PAGE @"xtfei_start_page"
#define TF_SITE_STATE @"xtfei_site_state"
#define TF_Ai_Switch @"xtfei_ai_switch"
// 阅读器开始免广告的时间戳
#define TF_Reader_Ad_Start_Timestamp @"TF_Reader_Ad_Start_Timestamp"
// 阅读器广告当前时间戳
#define TF_Reader_Ad_Timestamp @"TF_Reader_Ad_Timestamp"
#define TF_DELETE_PHOTO @"xtfei_delete_photo"
// 兴趣选择页面
#define TF_Insterest_Switch @"xtfei_Insterest_Switch"
// 点击翻页
#define Enable_Click_Page @"enable_click_change_page_wx81818181881"
// 夜间模式
#define Enable_Click_Night @"enable_click_change_day_or_night_wx81818818181"
// 开启吐槽
#define Enable_Barrage @"Enable_Barrage_wx81818181881"
#endif /* TFMemoryConfig_h */
@@ -0,0 +1,136 @@
//
// TFNotificationConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFNotificationConfig_h
#define TFNotificationConfig_h
// 登录成功
#define Notification_Login_Success @"login_success_notification"
// 退出登录
#define Notification_Logout @"logout_notification"
#define NSNotification_Rack_JumpToMallCenter @"rack_jump_to_mall_center_notification"
#define NSNotification_Reader_Back @"reader_back_notification"
#define NSNotification_Reader_Push @"reader_push_notification"
#define NSNotification_Hidden_ToolNav @"hidden_tool_nav_notification"
#define NSNotification_Hidden_Bottom_ToolNav @"hidden_bottom_tool_nav_notification"
#define NSNotification_Retry_Chapter @"retry_chapter_notification"
#define NSNOtification_Book_Mark @"NSNOtification_Book_Mark"
#define NSNotification_EmptyView_Changed @"empty_view_changed_notification"
#define k_Chapter_RequstFail @"no_word_request"
#define Notification_beginDragging @"BeginDragging_notification"
#define NSNotification_WeChat_OnResp @"wechat_onResp_notification"
#define Notification_Reload_BookDetail @"reload_bookDetail_notification"
#define Notification_Avatar_Changed @"avatar_changed_notification"
#define Notification_NickName_Changed @"nickname_changed_notification"
#define Notification_Hidden_Tabbar @"hidden_tabbar_notification"
#define Notification_Show_Tabbar @"show_tabbar_notification"
#define Notification_Show_PayView @"show_pay_view_notification"
#define Notification_Review_State @"in_review_state_notification"
#define Notification_Insterest_Change @"insterest_state_change_notification"
#define Notification_Change_Tabbar_Index @"change_tabbar_index_notification"
#define Notification_Recharge_Success @"recharge_success_notification"
#define Notification_Show_Assistive @"show_assistive_touch_view_notification"
#define Notification_Push_UserInfo @"push_to_userInfo_notification"
#define Notification_Push_To_Book_Detail_Animation @"push_to_book_detail_animation_notification"
#define Notification_Push_To_Download @"push_to_download_notification"
#define Notification_Reload_Download_State @"reload_download_state_notification"
#define Notification_Channel_Change @"channel_change_notification"
#define Notification_Production_Pay_Success @"comic_pay_success_notification"
#define Notification_Reload_Rack_Production @"reload_book_rack_notification"
#define Notification_Reload_Mall_Hot_Word @"reload_mall_hot_word_notification"
#define Notification_Check_Setting_Update @"check_setting_upload_notification"
#define Notification_Change_Audio_Chapter @"xtfei_change_audio_chapter"
#define Notification_Change_AiBook_Chapter @"xtfei_change_aibook_chapter"
#define Notification_Audio_Check_Recommend @"xtfei_audio_check_recommend"
#define Notification_Restore_Network @"Notification_Restore_Network"
#define Notification_Can_Leave_Top @"xtfei_can_leave_top_notification"
#define Notification_Audio_Can_Leave_Top @"xtfei_audio_can_leave_top_notification"
#define Notification_Directory_Move @"xtfei_directiory_move_notification"
#define Notification_Switch_Chapter @"xtfei_switch_chapter_notification"
#define Notification_Pop_Comic_Reader @"xtfei_pop_comi_reader_notification"
#define Notification_Push_To_Comments @"xtfei_push_to_comments_notification"
#define Notification_Push_To_Directory @"xtfei_push_to_directory_notification"
#define Notification_Reader_Scroll_To_Top @"xtfei_reader_view_scroll_to_top_notification"
#define Notification_Push_To_Comic_Download @"xtfei_push_to_comic_download_notification"
#define Notification_Change_Barrage @"Notification_Change_Barrage"
#define NSNotification_Updata_Read_Record @"xtfei_updata_read_record_notification"
#define NSNotification_Auto_Buy_Audio_Chapter @"xtfei_auto_buy_audio_chapter_notification"
// 阅读器广告隐藏状态
#define Notification_Reader_Ad_Hidden @"Notification_Reader_Ad_Hidden"
// 广告页面全屏翻页
#define Notification_Reader_Ad_TurnThePage @"Notification_Reader_Ad_TurnThePage"
// 清空播放机缓存信息
#define Notification_Reset_Player_Inof @"xtfei_reset_player_info_notification"
// 分享成功
#define Notification_Share_Success @"Notification_Share_Success"
// 开启关闭弹幕功能
#define Notification_Switch_Barrage @"xtfei_switch_barrage_notification"
// 小说发现页面限时免费结束
#define Notification_EndOfTimeLimit @"Notification_EndOfTimeLimit"
// 更新目录锁按钮
#define Notification_ChangeLock @"Notification_ChangeLock"
// 切换APP语言
#define Notification_Switch_Language @"Notification_Switch_Language"
#endif /* TFNotificationConfig_h */
@@ -0,0 +1,38 @@
//
// TFPrefixHeader.pch
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFPrefixHeader_pch
#define TFPrefixHeader_pch
#ifdef __OBJC__
#import "TFSettingConfig.h"
#import "TFSwitchConfig.h"
#import "TFServerConfig.h"
#import "TFColorConfig.h"
#import "TFNotificationConfig.h"
#import "TFFrameConfig.h"
#import "TFImportConfig.h"
#import "TFSystemConfig.h"
#import "TFMemoryConfig.h"
#import "TFDefineConfig.h"
/*** 日志 ***/
#ifdef DEBUG
#define TFLog(...) NSLog(__VA_ARGS__)
#else
#define TFLog(...)
#endif
#define TFLogFunc TFLog(@"%s", __func__);
#endif
#endif /* TFPrefixHeader_pch */
@@ -0,0 +1,503 @@
//
// TFServerConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFServerConfig_h
#define TFServerConfig_h
/** 网络请求默认超时时间 */
#define kOvertime 30.0f
// 书城首页
#define Book_Mall_Center @"/book/store" // 频道 1-女频 2-男频
// 书籍详情
#define Book_Mall_Detail @"/book/info"
// 阅读器末尾推荐
#define Book_Endof_Recommend @"/book/end-of-recommend"
// 查看更多
#define Book_Recommend_More @"/book/recommend"
// 获取章节
#define Book_Chapter_Text @"/chapter/text"
// 下载多章节
#define Book_Download_Multiple_Chapters @"/chapter/down-url"
// 小说分类
#define Book_Category_List @"/book/category-index"
// 小说包月
#define Book_Member_Store @"/book/baoyue-index"
// 小说榜单
#define Book_Rank_List @"/rank/index" // 频道 1-男频 2-女频
// 小说榜单列表
#define Book_Rank_Detail_List @"/rank/book-list"
// 小说完本
#define Book_Finish @"/book/finish"
// 限免
#define Book_Free_Time @"/book/free-time"
// 免费
#define Book_Free @"/book/free"
// 发现首页
#define Book_Discover @"/book/new-featured"
// 目录
#define Book_Catalog @"/chapter/catalog"
// 新目录
#define Book_New_Catalog @"/chapter/new-catalog"
// 评论列表
#define Book_Comment_List @"/comment/list"
// 发送评论
#define Book_Comment_Post @"/comment/post"
// 添加书籍
#define Book_Add_Collect @"/user/collect-add"
// 删除书籍
#define Book_Delete_Collect @"/user/collect-del"
// 小说书架
#define Book_Rack @"/user/book-collect"
// 批量购买章节预览页
#define Book_Buy_Index @"/chapter/buy-index"
// 购买小说章节
#define Book_Buy_Chapter @"/chapter/buy"
// 章节下载预览
#define Book_Chapter_Download_Option @"/chapter/down-option"
// 我的评论
#define Book_Comments_List @"/user/comments"
// 删除小说阅读记录
#define Book_Readlog_Delete @"/user/del-read-log"
// 换一换
#define Book_Refresh @"/book/refresh"
// 猜你喜欢换一换
#define Book_Guess_Like @"/book/guess-like"
// 搜索首页
#define Book_Search @"/book/search-index"
// 搜索内容
#define Book_Search_List @"/book/search"
// 阅读记录
#define Book_Read_Log_List @"/user/read-log"
// 增加阅读记录
#define Book_Add_Read_log @"/user/add-read-log"
// 打赏礼物给作品
#define Book_Reward_Gift_Send @"/reward/gift-send"
// 投月票
#define Book_Reward_Ticket_Vote @"/reward/ticket-vote"
// 阅读器月票封面
#define Book_Gift_Montyly_Pass @"/reward/ticket-option"
// 月票记录
#define Book_Reward_Ticket_Log @"/reward/ticket-log"
// 打赏记录
#define Book_Reward_Gift_Log @"/reward/gift-log"
/*
漫画相关接口
*/
// 漫画查看更多
#define Comic_Recommend_More @"/comic/recommend"
// 漫画分类标签
#define Comic_Category_List @"/comic/list"
// 漫画包月
#define Comic_Member_Store @"/comic/baoyue-list"
// 漫画榜单首页
#define Comic_Rank_List @"/rank/comic-index"
// 漫画榜单作品列表
#define Comic_Rank_Detail_List @"/rank/comic-list"
// 漫画书架
#define Comic_Rack @"/fav/index"
// 漫画书城首页
#define Comic_Mall @"/comic/home-stock"
// 换一换
#define Comic_Refresh @"/comic/refresh"
// 漫画评论列表
#define Comic_Comment_List @"/comic/comment-list"
// 漫画详情
#define Comic_Detail @"/comic/info"
// 漫画详情目录
#define Comic_Catalog @"/comic/catalog"
// 漫画章节
#define Comic_Chapter @"/comic/chapter"
// 漫画弹幕
#define Comic_Barrage @"/comic/barrage"
// 发送吐槽
#define Comic_Send_Barrage @"/comic/tucao"
// 发送评论
#define Comic_Comment_Post @"/comic/post"
// 下载列表
#define Comic_DownloadOption @"/comic/down-option"
// 下载漫画
#define Comic_Download @"/comic/down"
// 发现
#define Comic_Discover @"/comic/featured"
// 书架
#define Comic_Rack @"/fav/index"
// 添加收藏
#define Comic_Collect_Add @"/fav/add"
// 删除收藏
#define Comic_Collect_Delete @"/fav/del"
// 漫画完本
#define Comic_Finish @"/comic/finish"
// 漫画限免
#define Comic_Free_Time @"/comic/free-time"
// 漫画免费
#define Comic_Free @"/comic/free"
// 我的评论
#define Comic_Comments_List @"/user/comic-comments"
// 评论详情
#define Comment_Detail @"/user/comment-info"
// 漫画搜索
#define Comic_Search @"/comic/search-index"
// 漫画搜索内容
#define Comic_Search_List @"/comic/search"
// 购买漫画章节
#define Comic_Buy_Chapter @"/comic-chapter/buy"
// 漫画章节购买预览页
#define Comic_Buy_Index @"/comic-chapter/buy-index"
// 章节下载
#define Chapter_Download @"/chapter/down"
// 漫画阅读记录
#define Comic_Read_Log_List @"/user/comic-read-log"
// 漫画添加阅读记录
#define Comic_Add_Read_Log @"/user/add-comic-read-log"
// 删除漫画阅读记录
#define Comic_Readlog_Delete @"/user/del-comic-read-log"
/*
有声相关接口
*/
// AI 详情页
#define Ai_Audio_Detail @"/book/detail"
// 有声详情页
#define Audio_Info @"/audio/info"
// 有声书城首页
#define Audio_Mall @"/audio/index"
// 有声目录
#define Audio_Catalog @"/audio/catalog"
// 有声详情页推荐
#define Audio_Info_Recommend @"/audio/info-recommend"
// 有声播放页
#define Audio_Chapter_Info @"/audio-chapter/info"
// 有声下载
#define Audio_Chapter_Download @"/audio-chapter/down"
// 有声播放页详情
#define Audio_Chapter_Detail @"/audio-chapter/detail"
// 有声评论列表
#define Audio_Comment_List @"/audio-chapter/comment-list"
// 我的评论列表
#define Audio_Comments_List @"/user/audio-comment"
// 有声免费列表
#define Audio_Free @"/audio/free"
// 有声完结
#define Audio_Finish @"/audio/finished"
// 有声分类
#define Audio_Category_Index @"/audio/category-index"
// 有声包月
#define Audio_Member_Store @"/audio/baoyue-list"
// 有声榜单首页
#define Audio_Rank_List @"/audio/top-index"
// 有声详情页
#define Audio_Rank_Detail_List @"/audio/top-list"
// 有声添加收藏
#define Audio_Collection_Add @"/audio-fav/add"
// 有声取消收藏
#define Audio_Collection_Delete @"/audio-fav/del"
// 有声发现页
#define Audio_Discover @"/audio/new-featured"
// 添加有声记录
#define Audio_Add_Read_Log @"/audio/add-read-log"
// 有声阅读记录
#define Audio_Read_Log_List @"/user/audio-read-log"
// 有声删除评论记录
#define Audio_Readlog_Delete @"/user/audio-del-read-log"
// 有声发送评论
#define Audio_Comment_Post @"/audio-chapter/comment-post"
// 有声书架
#define Audio_Rack @"/audio-fav/user-fav"
// 有声搜索首页
#define Audio_Search @"/audio/search-index"
// 有声搜索结果
#define Audio_Search_List @"/audio/search"
// 有声购买预览
#define Audio_Buy_Index @"/audio-chapter/buy-option"
// 有声章节购买
#define Audio_Buy_Chapter @"/audio-chapter/buy"
// 有声首页换一换
#define Audio_Refresh @"/audio/refresh"
// 有声查看更多
#define Audio_Recommend_More @"/audio/recommend"
/*
公共相关接口
*/
// 个人中心
#define User_Center @"/user/index"
// 首次启动书架增加推荐作品
#define Shelf_Recommend @"/novel/shelf-recommend"
// 会员包月
#define Member_Monthly @"/user/vip-center"
// 提交反馈
#define Sub_Feed_Back @"/answer/post-feedback"
// 阅读器礼物列表
#define Gift_List @"/reward/gift-option"
// 金币充值
#define Pay_Center @"/pay/center"
// 开通包月
#define Member_Center @"/pay/baoyue-center"
// 阅读器广告
#define Advert_Info @"/advert/info"
// 广告点击统计
#define AdVert_Click @"/advert/click"
// 会员服务协议
#define Membership_Service @"/site/membership-service"
// 软件服务协议
#define Notify_Note @"/site/notify"
// 隐私政策
#define Privacy_Policy @"/site/privacy-policy"
// 用户服务协议
#define User_Agreement @"/site/user-agreement"
// 注销协议
#define Log_Off @"/site/logoff-protocol"
// 注销账号
#define Cancel_Account @"/user/cancel-account"
// 推送提醒状态
#define User_Push_State @"/user/push-state"
// 用户修改推送提醒状态Ai_Audio_Detail
#define User_Update_Push_State @"/user/update-push-state"
// 帮助反馈
#define Answer_List @"/answer/list"
// 上传图片
#define Upload_Image @"/upload/image"
// 删除图片
#define Delete_Upload_Image @"/upload/delete-image"
// 用户反馈列表
#define Feed_Back_List @"/answer/feedback-list"
// 发送验证码
#define Send_Verification_Code @"/message/send"
// 发送邮箱验证码
#define Send_Email_Verification_Code @"/message/send-email"
// 手机号登录
#define Mobile_Login @"/user/mobile-login"
// 邮箱登录
#define Email_Login @"/user/email-login"
// 账号密码登录
#define Account_Login @"/user/account-login"
// 游客登录
#define Tourists_Login @"/user/device-login"
// 微信登录
#define WeChat_Login @"/user/app-login-wechat"
// QQ登录
#define QQ_Login @"/user/qq-login"
// 绑定微信
#define WeChat_Binding @"/user/app-bind-wechat"
// 绑定QQ
#define QQ_Binding @"/user/bind-qq"
// 绑定手机号
#define Phone_Binding @"/user/bind-mobile"
// 分享跳转
#define Site_Share @"/site/share"
// 分享App请求
#define App_Share @"/user/app-share"
// 分享书籍章节
#define App_Chapter_Share @"/novel/share-novel"
// 关于我们
#define About_Soft @"/service/about"
// 分享回调
#define Share_Back @"/user/share-reward"
// 签到
#define Sign_Click @"/user/sign"
// 任务中心
#define Task_Center @"/task/center"
// 消费充值记录
#define Consumption_Records @"/pay/gold-detail"
// 个人资料
#define User_Data @"/user/data"
// 上传头像
#define Set_Avatar @"/user/set-avatar"
// 上传性别
#define Set_Gender @"/user/set-gender"
// 修改昵称
#define Set_NickName @"/user/set-nickname"
// 推荐
#define Start_Recommend @"/user/start-recommend"
// 保存推荐
#define Save_Recommed @"/user/save-recommend"
// 完成任务两本书
#define Task_Read @"/user/task-read"
// 自动订阅下一章
#define Auto_Sub_Chapter @"/user/auto-sub"
// 苹果支付验证
#define Apple_Pay_Back @"/pay/applepay"
// 拉取系统配置
#define Check_Setting @"/service/check-setting"
// 上传设备号
#define Upload_Device_Info @"/user/sync-device"
// 切换语言
#define Switch_Language @"/user/set-lang"
// Facebook登录
#define Facebook_Login @"/user/facebook-login"
// Facebook绑定
#define Facebook_Bind @"/user/facebook-bind"
// Google登录
#define Google_Login @"/user/google-login"
// Google绑定
#define Google_Bind @"/user/google-bind"
#endif /* TFServerConfig_h */
@@ -0,0 +1,77 @@
//
// TFSettingConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFSettingConfig_h
#define TFSettingConfig_h
// APP默认语言(en:英语;zh-Hans:简体中文;zh-Hant:繁体中文;th:泰语)
#define TF_Default_Language @"en"
// 主货币名称
#define Main_Unit_Name TFLocalizedString(@"书币")
// 子货币名称
#define Sub_Unit_Name TFLocalizedString(@"书券")
// apple ID
#define Apple_ID @"1543830673"
// api服务器地址
#define APIURL [NSString stringWithFormat:@"http://%@", api_host]
// api域名
#define api_host @"api.kanshu116116.com"//@"192.168.10.111"
// api秘钥
#define app_key @"0c44876680d7a4e2"
// api签名
#define secret_key @"7de8a70d15d8fd198b8b53b53d58e110"
// 提交审核时间
#define Submission_Date @"2020-12-28 21:26:34"
/**
友盟
*/
#define UM_App_Key @""
// 穿山甲
#define BUA_App_Key @""
// 启动页默认Key
#define BUA_Splash_Key @""
// 激励视频默认Key
#define BUA_Incentive_Video_Key @""
// 讯飞语音
#define IFLY_App_ID @"5fddc7e5"
// 进入后台后返回App前台重新展示广告间隔时间(分钟)
#define TF_Launch_Interval 2.0f
// 好评页跳转地址
#define TF_EvaluationAddress [NSString stringWithFormat:@"https://itunes.apple.com/cn/app/id%@?mt=8", Apple_ID]
/**
微信
*/
#define TF_WeChat_APPID @"wx0193612ff6250f4c"
#define TF_WeChat_Secret @"f5d221c5da4c7c15fd5a319dbf7073e4"
/**
QQ
*/
#define Tencent_APPID @"101918139"
#define Tencent_APPKey @"a2db16ec7a1141db1d2e95c17d9c07ce"
#endif /* TFSettingConfig_h */
@@ -0,0 +1,111 @@
//
// TFSwitchConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFSwitchConfig_h
#define TFSwitchConfig_h
// 启用漫画模块
#define TF_Enable_Comic 1
// 启用小说模块
#define TF_Enable_Book 1
// 启用有声模块
#define TF_Enable_Audio 1
// 启用Ai听书模块
#define TF_Enable_Ai 1
// 启用礼物模块
#define TF_Enable_Gift 1
// 启动广告图
#define TF_Launch_Advertising 1
#define TF_Enable_Magic 1
// 是否开始选项卡标签
#define TF_Enable_PageControl 1
// 是否需要超级会员
#define TF_Super_Member_Mode 1
// 免费模块开关
#define TF_Free_Mode 1
// 是否需要货币充值
#define TF_Recharge_Mode 1
// 是否使用推送功能
#define TF_Enable_Push 1
/*
发现模块
*/
// 兴趣模块
#define TF_Insterest_View 1
// 3D Touch
#define TF_ShortcutTouch 1
// 应用内好评
#define TF_AppStore_Score 1
// 是否需要游客
#define TF_Tourists_Login_Mode 1
// Apple登录
#define TF_Apple_Login_Mode (1 || TF_QQ_Login_Mode || TF_WeChat_Login_Mode)
// 下载模块
#define TF_Download_Mode 1
// 微信登录
#define TF_WeChat_Login_Mode 0
// 微信分享
#define TF_WeChat_Share_Mode 0
// QQ登录
#define TF_QQ_Login_Mode 1
// QQ分享
#define TF_QQ_Share_Mode 1
/*
个人中心模块
*/
// 流水记录
#define TF_Records_Mode 1
// 签到功能
#define TF_Sign_Mode 1
// 福利任务
#define TF_Task_Mode 1
// 评论功能
#define TF_Comments_Mode 1
// 联系客服
#define TF_Aboutus_Mode 1
// 历史记录
#define TF_History_Mode 1
// 意见反馈
#define TF_Feedback_Mode 1
// 设置
#define TF_Settings_Mode 1
#endif /* TFSwitchConfig_h */
@@ -0,0 +1,124 @@
//
// TFSystemConfig.h
// TFReader
//
// Created by 谢腾飞 on 2020/12/21.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#ifndef TFSystemConfig_h
#define TFSystemConfig_h
#define WS(weakSelf) __weak __typeof(&*self)weakSelf = self;
#define SS(strongSelf)__strong __typeof(weakSelf)strongSelf = weakSelf;
// AppDelegate
#define KAppDelegate ((AppDelegate*)kRCodeSync([UIApplication sharedApplication].delegate))
// App版本
#define App_Ver [NSString stringWithString:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]]
// App名称
#define App_Name TFLocalizedString(@"小说绘")
// 系统信息文件名称
#define System_Info_Path @"systemInfo"
// 用户信息文件名称
#define User_Info_Path @"userInfo"
// 常用宏定义
#define kNotification [NSNotificationCenter defaultCenter]
//系统版本
#define is_ios7 [[[UIDevice currentDevice]systemVersion] floatValue] >= 7
#define is_ios8 [[[UIDevice currentDevice]systemVersion] floatValue] >= 8
#define is_ios9 [[[UIDevice currentDevice] systemVersion] floatValue] >= 9
#define is_ios10 [[[UIDevice currentDevice] systemVersion] floatValue] >= 10
#define is_ios11 [[[UIDevice currentDevice] systemVersion] floatValue] >= 11
#define is_ios13 [[[UIDevice currentDevice] systemVersion] floatValue] >= 13
//手机型号
#define is_iPad ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
#define is_iPhone4 ([UIScreen mainScreen].bounds.size.height == 480)
#define is_iPhone5 ([UIScreen mainScreen].bounds.size.height == 568)
#define is_iPhone6 ([UIScreen mainScreen].bounds.size.height == 667)
#define is_iPhone6P ([UIScreen mainScreen].bounds.size.height == 1104)
#define is_iPhoneX ((([[UIScreen mainScreen] bounds].size.width == 375.0 && \
[[UIScreen mainScreen] bounds].size.height == 812.0) || \
([[UIScreen mainScreen] bounds].size.width == 414.0 && \
[[UIScreen mainScreen] bounds].size.height == 896.0)) ? YES : NO)
#define is_iPhoneX_Max ((([[UIScreen mainScreen] bounds].size.width == 414.0 && \
[[UIScreen mainScreen] bounds].size.height == 896.0)) ? YES : NO)
//主窗口
#define kMainWindow (is_ios13?[[[UIApplication sharedApplication] windows] objectAtIndex:0]:[[UIApplication sharedApplication] keyWindow])
// 比对ErrorNo
#define Compare_Json_isEqualTo(A,B) (A == B)
#if __LP64__
#define MZNSI @"ld"
#define MZNSU @"lu"
#else
#define MZNSI @"d"
#define MZNSU @"u"
#endif //__LP64__
#define interface_singleton \
+ (instancetype)sharedManager;
// @implementation
#define implementation_singleton(className) \
static className *_instance_##className;\
+ (instancetype)allocWithZone:(struct _NSZone *)zone{\
static dispatch_once_t once_token_##className;\
dispatch_once(&once_token_##className, ^{\
_instance_##className = [super allocWithZone:zone];\
});\
return _instance_##className;\
}\
+ (instancetype)sharedManager{\
static dispatch_once_t once_token_##className;\
dispatch_once(&once_token_##className, ^{\
_instance_##className = [[self alloc] init];\
});\
return _instance_##className;\
}\
- (id)copyWithZone:(NSZone *)zone{\
return _instance_##className;\
}
// ???: 在主线程中执行一段代码并返回对象(返回和接收值都是id类型)
#define kRCodeSync(x) ({\
id __block temp;\
if ([NSThread isMainThread]) {\
temp = x;\
} else {\
dispatch_semaphore_t signal = dispatch_semaphore_create(0);\
dispatch_async(dispatch_get_main_queue(), ^{\
temp = x;\
dispatch_semaphore_signal(signal);\
});\
dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);\
}\
temp;\
})
// ???: 在主线程中执行一段代码
#define kCodeSync(x) ({\
if ([NSThread isMainThread]) {\
x;\
} else {\
dispatch_semaphore_t signal = dispatch_semaphore_create(0);\
dispatch_async(dispatch_get_main_queue(), ^{\
x;\
dispatch_semaphore_signal(signal);\
});\
dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);\
}\
})
#endif /* TFSystemConfig_h */
@@ -0,0 +1,35 @@
//
// IFlyAudioSession.h
// MSCDemo
//
// Created by AlexHHC on 1/9/14.
//
//
#import <Foundation/Foundation.h>
/**
* 音频环境初始化,设置AVAudioSession的Category属性。
*/
@interface IFlyAudioSession : NSObject
/**
* 初始化播音环境,主要用于合成播放器。
*
* 此接口主要根据原来的音频环境,重新优化设置AVAudioSession的Category属性值。<br>
* 若原来的Category属性值为AVAudioSessionCategoryPlayAndRecord,则添加AVAudioSessionCategoryOptionDefaultToSpeakerAVAudioSessionCategoryOptionAllowBluetooth选项;若为其他Category属性值且isMPCenter为NO,则设置Category属性值为AVAudioSessionCategoryPlayback,选项为AVAudioSessionCategoryOptionMixWithOthers;若为其他Category属性值且isMPCenter为YES,则保持原来的设置,不做任何更改。
*
* @param isMPCenter 是否初始化MPPlayerCenter:0不初始化,1初始化。此参数只在AVAudioSession的Category属性值不为AVAudioSessionCategoryPlayAndRecord时设置有效。
*/
+(void) initPlayingAudioSession:(BOOL)isMPCenter;
/**
* 初始化录音环境,主要用于识别录音器。
*
* 设置AVAudioSession的Category属性值为AVAudioSessionCategoryPlayAndRecord,选项为AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionAllowBluetooth。
*
* @return 成功返回YES,失败返回NO
*/
+(BOOL) initRecordingAudioSession;
@end
@@ -0,0 +1,24 @@
//
// IFlyContact.h
// msc
//
// Created by ypzhao on 13-3-1.
// Copyright (c) 2013年 IFLYTEK. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
* 此接口为获取通信录中的联系人。<br>
* 获取联系人是为了在进行语音识别时(sms)能更好的识别出您说的人名,联系人上传是属于个性化的一部分。
*/
@interface IFlyContact : NSObject
/*!
* 获取联系人。<br>
* 调用此方法需要添加 AddressBook.framework 和 Contacts.framework到工程中,调用此方法后可以直接将通信录中的联系人转化为语音云识别的数据结构。您可以将获取的数据通过IFlyDataUploader类,上传到语音云,我们只获取通信录中的人名。
*
* @return 返回联系人信息
*/
- (NSString *) contact;
@end
@@ -0,0 +1,54 @@
//
// IFlyDataUploader.h
// MSC
//
// Created by ypzhao on 13-4-8.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlySpeechError;
/*!
* 数据上传类,主要用于上传语法文件或上传联系人、词表等个性化数据。
*/
@interface IFlyDataUploader : NSObject
/*!
* 数据名称
*/
@property(nonatomic,copy) NSString *dataName;
/*!
* 数据
*/
@property(nonatomic,copy) NSString *data;
/*!
* 上传完成回调
*
* @param result 结果
* @param error 错误码
*/
typedef void(^IFlyUploadDataCompletionHandler)(NSString* result,IFlySpeechError * error);
/*!
* 上传数据
* 此函数用于上传数据,下载的过程是**异步**的。
*
* @param completionHandler -[in] 上传完成回调
* @param name -[in] 上传的内容名称,名称最好和你要上传的数据内容相关,不可以为nil
* @param data -[in] 上传的数据,以utf8编码,不可以为nil
*/
- (void) uploadDataWithCompletionHandler:(IFlyUploadDataCompletionHandler)completionHandler name:(NSString *)name data:(NSString *)data;
/*!
* 设置上传数据参数
*
* @param parameter 参数值
* @param key 参数名
*/
-(void) setParameter:(NSString*) parameter forKey:(NSString*) key;
@end
@@ -0,0 +1,37 @@
//
// IFlyDebugLog.h
// MSC
// description: 程序中的log处理类
// Created by ypzhao on 12-11-22.
// Copyright (c) 2012年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
* 调试信息
*/
@interface IFlyDebugLog : NSObject
/*!
* 打印调试信息
*
* @param format -[in] 要打印的内容格式
* @param ... -[in] 要打印的内容
*/
+ (void) showLog:(NSString *)format, ...;
/*!
* 将log写入文件中
*/
+ (void) writeLog;
/*!
* 设置是否显示log
*
* @param showLog YES:显示;NO:不显示
*/
+ (void) setShowLog:(BOOL) showLog;
@end
@@ -0,0 +1,48 @@
//
// IFlyISVDelegate.h
// msc_UI
//
// Created by admin on 14-9-15.
// Copyright (c) 2014年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlySpeechError;
/*!
* 声纹回调协议
*/
@protocol IFlyISVDelegate
/*!
* 声纹结果回调
*
* @param dic 结果
*/
-(void) onResult:(NSDictionary *)dic;
/*!
* 错误码回调
*
* @param errorCode 错误码
*/
-(void) onCompleted:(IFlySpeechError *) errorCode;
@optional
/*!
* 等待结果
*/
-(void) onRecognition;
/*!
* 音量改变回调
*
* @param volume 音量值
*/
-(void) onVolumeChanged: (int)volume;
@end
@@ -0,0 +1,132 @@
//
// IFlyISVRecognizer.h
// ISV
//
// Created by wangdan on 14-9-6.
// Copyright (c) 2014年 IFlyTEK. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IFlyISVDelegate.h"
/**
* 声纹接口类
*/
@interface IFlyISVRecognizer : NSObject
{
}
/*!
* The delegate of FlyISVRecognizer responsing to IFlyISVDelegate.
*/
@property (assign) id<IFlyISVDelegate> delegate;
/*!
* FlyISVRecognizer is a kind of Singleton calss.The function can be used as below:<br>
* IFLyISVRecognizer *recognizer=[IFlyISVRecognizer creteRecognizer: self];
*/
+(instancetype) sharedInstance;
/*!
* Genrerate a serial number password<br>
* Princeple:<br>
* 1.Number serial has no 1 in itself;<br>
* 2.The nuber serial has no same number("98765432"is right while "99876543" is wrong)
*
* @param length the serial number's length,length of "98765432" is 8,generally length is 8 and other value is forbidden
*/
-(NSString*) generatePassword:(int)length;
/*!
* Used to get password from server
*
* @param pwdt when pwdt is 1,the function will return chinese text;while pwdt is 2, the funciton will return number serial
*/
-(NSArray*) getPasswordList:(int)pwdt;
/*!
* Used to judge if the engine is running in listenning
*
* @return YES: the engine is listenning;<br>No : the engine is not listenning
*/
-(BOOL) isListening;
/*!
* Used to query or delete the voiceprint model in server
*
* @param cmd "del": delete model;<br>"que": query model;
* @param authid: user id ,can be @"tianxia" or other;
* @param pwdt voiceprint type<br>
* 1: fixed txt voiceprint code ,like @"我的地盘我做主";<br>
* 2: free voiceprint code , user can speek anything,but 5 times trainning the speech shall be same;<br>
* 3: number serial voiceprint code ,like @"98765432" and so on.
* @param ptxt voiceprint txt,only fixed voiceprint and number serial have this,in free voiceprint model this param shall be set nil.
* @param vid another voiceprint type model,user can use this to query or delete model in server can be @"jakillasdfasdjjjlajlsdfhdfdsadff",totally 32 bits;<br>
* NOTES:<br>
* when vid is not nil,then the server will judge the vid first; while the vid is nil, server can still query or delete the voiceprint model by other params.
*/
-(BOOL) sendRequest:(NSString*)cmd authid:(NSString *)auth_id pwdt:(int)pwdt ptxt:(NSString *)ptxt vid:(NSString *)vid err:(int *)err;
/*!
* Set the voiceprint params
*
* | key | value |
* |:---------------:|:-------------------------------------------------:|
* | sst | @"train" or @"verify" |
* | auth_id | @"tianxia" or other |
* | sub | @"ivp" |
* | ptxt | |
* | rgn | @"5" |
* | pwdt | @"1",or @"2", or @"3" |
* | auf | @"audio/L16;rate=16000" or @"audio/L16;rate=8000" |
* | vad_enable | @"1" or @"0" |
* | vad_timeout | @"3000" |
* | vad_speech_tail | @"100" |
*
* @param value 参数值
* @param key 参数类型
*
* @return 设置成功返回YES,失败返回NO
*/
-(BOOL) setParameter:(NSString *)value forKey:(NSString *)key;
/*!
* Get the voiceprint params used the same as function of setParameter
*/
-(NSString*) getParameter:(NSString *)key;
/*!
* Start recording
*/
-(void) startListening;
/*!
* Stop recording
*/
-(void) stopListening;
/*!
* Cancel recording,like function stopListening
*/
-(void) cancel; /* cancel recognization */
@end
@@ -0,0 +1,37 @@
//
// IFlyIdentityResult.h
// IFlyMSC
//
// Created by 张剑 on 15/5/14.
// Copyright (c) 2015年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
* 身份验证结果类
*/
@interface IFlyIdentityResult : NSObject
/**
* json字符串格式结果
*/
@property(nonatomic,retain)NSString* result;
/**
* 创建身份验证结果类实例
*
* @param jsonString json字符串
*
* @return 身份验证结果类实例
*/
+(instancetype)identityResultWithString:(NSString*)jsonString;
/**
* 返回字典格式的结果
*
* @return 字典格式的结果
*/
-(NSDictionary*)dictionaryResults;
@end
@@ -0,0 +1,176 @@
//
// IFlyIdentityVerifier.h
// IFlyMSC
//
// Created by 张剑 on 15/4/22.
// Copyright (c) 2015年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IFlyIdentityVerifierDelegate.h"
/**
* 身份验证功能类
*/
@interface IFlyIdentityVerifier : NSObject
/*!
* 设置委托对象
*/
@property (nonatomic, assign) id <IFlyIdentityVerifierDelegate> delegate;
/**
* 返回身份验证对象的单例
*
* @return 身份验证对象的单例
*/
+ (instancetype) sharedInstance;
/**
* 销毁身份验证对象单例。
*
* @return 成功返回YES,失败返回NO。
*/
+ (void)purgeSharedInstance;
/**
* 设置参数
*
* @param value 参数值
* @param key 参数名
*
* @return 设置的参数和取值正确返回YES,失败返回NO
*/
- (BOOL)setParameter:(NSString *)value forKey:(NSString *)key;
/**
* 开始会话
* 在这之后会开始各项业务。
*/
- (void)startWorking;
/*
* | ------------- |-----------------------------------------------------------
* | ifr 参数 | 描述
* | ------------- |-----------------------------------------------------------
* | data_format |数据格式:即图片格式,支持jpg(默认),gif
* | ------------- |-----------------------------------------------------------
* | data_encoding |数据压缩编码:即图片压缩编码,支持raw(不压缩,默认值)
* | ------------- |-----------------------------------------------------------
* | wtt |等待超时时间: 支持大于0的整数,默认为3000ms
* | ------------- |-----------------------------------------------------------
* | ivp 参数 | 描述
* | ------------- |-----------------------------------------------------------
* | rgn |训练次数:取值2~9.无默认值,必须明确指定。
* | ------------- |-----------------------------------------------------------
* | |声纹确认门限值,验证得分>=tsd验证通过,否则验证失败(该参数目前不支持,
* | tsd |作为保留参数。)却只范围:0~100.
* | ------------- |-----------------------------------------------------------
* | ptxt |密码文本。从服务端下载,比如数字密码所需要的数字串。
* | ------------- |-----------------------------------------------------------
* | pwdt |密码类型。取值:1(文本密码),2(自由说),3(数字密码).
* | ------------- |-----------------------------------------------------------
* | fin |取消注册。取值:0(不取消,即不生效),1(取消本次注册).
* | ------------- |-----------------------------------------------------------
* | wtt |等待超时时间:描述客户端等待结果的超时时间
* | ------------- |-----------------------------------------------------------
* | vad_enable |VAD功能开关。是否启用VAD处理,取值:1(开启,默认),0(不开启)。
* | ------------- |-----------------------------------------------------------
* | |头部静音最大长度。如果静音长度超过此值,则认为用户此次无有效音频输入。
* | vad_bos |此参数仅在打开VAD功能时生效。(云端暂时没有)。取值:0~30000ms,
* | |默认为10000ms
* | ------------- |-----------------------------------------------------------
* | |尾部静音长度。如果尾部静音长度超过了此值,则认为音频已经结束。
* | |此参数仅在打开VAD功能时生效。(云端暂时没有)。取值:0~30000ms,
* | vad_eos |默认为2000ms
* | ------------- |-----------------------------------------------------------
* | data_encoding |数据压缩编码,音频压缩编码。
* | ------------- |-----------------------------------------------------------
* | data_format |在声纹业务中为音频采样率,取值:16000(默认),8000
* | ------------- |-----------------------------------------------------------
* | ipt 参数 | 描述
* | ------------- |-----------------------------------------------------------
* | scope |操作范围 persongroup
* | ------------- |-----------------------------------------------------------
* | group_id |指定鉴别的组数字或者字符串,唯一值 不为空
* | ------------- |-----------------------------------------------------------
* | |组名称 “”或者不能包含^@,&=*'"等非法字符,且长度不得超过255.
* | group_name |此参数可以为空,对于group_name约束不在云端控制,由前段控制
* | ------------- |-----------------------------------------------------------
* | topc |[top candidates],返回得分最高的候选人数目 取值1-5 默认是1.
* | | 可以开放由用户设置,最大topc值为5
* | ------------- |-----------------------------------------------------------
*
*/
/**
* 写入子业务数据、或者进行模型操作、下载密码。
*
* @param ssub 子业务名
* @param data 数据
* @param offset 偏移量
* @param length 长度
* @param params 参数
* <table>
* <thead>
* <tr><th>*ifr参数</th><th><em>描述</em></th></tr>
* </thead>
* <tbody>
* <tr><td>data_format</td><td>数据格式:即图片格式,支持jpg(默认)gif</td></tr>
* <tr><td>data_encoding</td><td>数据压缩编码:即图片压缩编码,支持raw(不压缩,默认值)</td></tr>
* <tr><td>wtt</td><td>等待超时时间: 支持大于0的整数,默认为3000ms</td></tr>
* </tbody>
* <thead>
* <tr><th>*ivp参数</th><th><em>描述</em></th></tr>
* </thead>
* <tbody>
* <tr><td>rgn</td><td>训练次数:取值2~9.无默认值,必须明确指定。</td></tr>
* <tr><td>tsd</td><td>声纹确认门限值,验证得分>=tsd验证通过,否则验证失败(该参数目前不支持,作为保留参数。)却只范围:0~100.</td></tr>
* <tr><td>ptxt</td><td>密码文本。从服务端下载,比如数字密码所需要的数字串。</td></tr>
* <tr><td>pwdt</td><td>密码类型。取值:1(文本密码),2(自由说),3(数字密码).</td></tr>
* <tr><td>fin</td><td>取消注册。取值:0(不取消,即不生效),1(取消本次注册).</td></tr>
* <tr><td>wtt</td><td>等待超时时间:描述客户端等待结果的超时时间.</td></tr>
* <tr><td>vad_enable</td><td>VAD功能开关。是否启用VAD处理,取值:1(开启,默认),0(不开启)。</td></tr>
* <tr><td>vad_bos</td><td>头部静音最大长度。如果静音长度超过此值,则认为用户此次无有效音频输入。</br>此参数仅在打开VAD功能时生效。(云端暂时没有)。</br>取值:0~30000ms,默认为10000ms</td></tr>
* <tr><td>vad_eos</td><td>尾部静音长度。如果尾部静音长度超过了此值,则认为音频已经结束。</br>此参数仅在打开VAD功能时生效。(云端暂时没有)。</br>取值:0~30000ms,默认为2000ms</td></tr>
* <tr><td>data_encoding</td><td>数据压缩编码,音频压缩编码。</td></tr>
* <tr><td>data_format</td><td>在声纹业务中为音频采样率,取值:16000(默认)8000</td></tr>
* </tbody>
* <thead>
* <tr><th>*ipt参数</th><th><em>描述</em></th></tr>
* </thead>
* <tbody>
* <tr><td>scope</td><td>操作范围 persongroup</td></tr>
* <tr><td>group_id</td><td>指定鉴别的组数字或者字符串,唯一值 不为空</td></tr>
* <tr><td>group_name</td><td>组名称 “”或者不能包含^@,&=*'"等非法字符,且长度不得超过255.此参数可以为空,对于group_name约束不在云端控制,由前段控制</td></tr>
* <tr><td>topc</td><td>组名称[top candidates],返回得分最高的候选人数目 取值1-5 默认是1.可以开放由用户设置,最大topc值为5</td></tr>
* </tbody>
* </table>
*/
-(void)write:(NSString*)ssub data:(NSData*)data offset:(int)offset length:(int)length withParams:(NSString*)params;
/**
* 停止子业务数据写入
*
* @param ssub 子业务名:ivp,ifr,ipt
*/
-(void)stopWrite:(NSString*)ssub;
/**
* 执行模型查询、删除和声纹密码下载等操作
* *注意此方法不能与startWorking方法同时使用。
*
* @param ssub 子业务类型、可选值:ivp(声纹)、ifr(人脸)、ipt(鉴别)
* @param cmd 操作命令,可选值:query、delete、download、add
* @param params 子业务参数,参见write:data:offset:length:withParams:
*/
-(void)execute:(NSString*)ssub cmd:(NSString*)cmd params:(NSString*)params;
/**
* 取消本次会话
*/
- (void)cancel;
@end
@@ -0,0 +1,47 @@
//
// IFlyIdentityVerifierDelegate.h
// IFlyMSC
//
// Created by 张剑 on 15/4/22.
// Copyright (c) 2015年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlySpeechError;
@class IFlyIdentityResult;
/**
* 身份验证功能类回调
*/
@protocol IFlyIdentityVerifierDelegate <NSObject>
/*!
* 错误回调
*
* @param error 错误描述类
*/
- (void)onCompleted:(IFlySpeechError *)error;
/*!
* 结果回调
*
* @param results -[out] 结果。
* @param isLast -[out] 是否最后一条结果
*/
- (void)onResults:(IFlyIdentityResult *)results isLast:(BOOL)isLast;
/**
* 扩展接口,用于抛出音量和vad_eos消息
*
* @param eventType 消息类型
* @param arg1 eventType为 Event_volume 时 arg1为音量值
* @param arg2 参数2
* @param obj 扩展参数
*/
- (void)onEvent:(int)eventType arg1:(int)arg1 arg2:(int)arg2 extra:(id)obj;
@end
@@ -0,0 +1,40 @@
//
// IFlyMSC.h
// msc
//
// Created by 张剑 on 15/1/14.
// Copyright (c) 2015年 iflytek. All rights reserved.
//
#ifndef MSC_IFlyMSC_h
#define MSC_IFlyMSC_h
#import "IFlyAudioSession.h"
#import "IFlyDataUploader.h"
#import "IFlyDebugLog.h"
#import "IFlyIdentityVerifier.h"
#import "IFlyIdentityResult.h"
#import "IFlyIdentityVerifierDelegate.h"
#import "IFlyISVDelegate.h"
#import "IFlyISVRecognizer.h"
#import "IFlyRecognizerView.h"
#import "IFlyRecognizerViewDelegate.h"
#import "IFlyResourceUtil.h"
#import "IFlySetting.h"
#import "IFlySpeechConstant.h"
#import "IFlySpeechError.h"
#import "IFlySpeechEvaluator.h"
#import "IFlySpeechEvaluatorDelegate.h"
#import "IFlySpeechEvent.h"
#import "IFlySpeechRecognizer.h"
#import "IFlySpeechRecognizerDelegate.h"
#import "IFlySpeechSynthesizer.h"
#import "IFlySpeechSynthesizerDelegate.h"
#import "IFlySpeechUtility.h"
#import "IFlyUserWords.h"
#import "IFlyPcmRecorder.h"
#import "IFlyVerifierUtil.h"
#import "IFlyVoiceWakeuper.h"
#import "IFlyVoiceWakeuperDelegate.h"
#endif
@@ -0,0 +1,116 @@
//
// IFlyPcmRecorder.h
// MSC
// description:
// Created by ypzhao on 12-11-15.
// Copyright (c) 2012年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioQueue.h>
#import <AudioToolbox/AudioFile.h>
#import <AudioToolbox/AudioServices.h>
#import <AudioToolbox/AudioConverter.h>
#import <AVFoundation/AVFoundation.h>
@class IFlyPcmRecorder;
/*!
* 录音协议
*/
@protocol IFlyPcmRecorderDelegate<NSObject>
/*!
* 回调音频数据
*
* @param buffer 音频数据
* @param size 表示音频的长度
*/
- (void) onIFlyRecorderBuffer: (const void *)buffer bufferSize:(int)size;
/*!
* 回调音频的错误码
*
* @param recoder 录音器
* @param error 错误码
*/
- (void) onIFlyRecorderError:(IFlyPcmRecorder*)recoder theError:(int) error;
@optional
/*!
* 回调录音音量
*
* @param power 音量值
*/
- (void) onIFlyRecorderVolumeChanged:(int) power;
@end
/*!
* 录音器控件
*/
@interface IFlyPcmRecorder : NSObject<AVAudioSessionDelegate>
/*!
* 录音委托对象
*/
@property (nonatomic,assign) id<IFlyPcmRecorderDelegate> delegate;
/*!
* 用于设置是否在录音结束后发送Deactive通知,默认是YES:发送
*/
@property (nonatomic,assign) BOOL isNeedDeActive;
/*!
* 单例模式
*
* @return 返回录音对象单例
*/
+ (instancetype) sharedInstance;
/*!
* 开始录音
*
* @return 开启录音成功返回YES,否则返回NO
*/
- (BOOL) start;
/*!
* 停止录音
*/
- (void) stop;
/*!
* 设置音频采样率
*
* @param rate -[in] 采样率,8k/16k
*/
- (void) setSample:(NSString *) rate;
/*!
* 设置录音音量回调时间间隔参数
*/
- (void) setPowerCycle:(float) cycle;
/*!
* 保存录音
*
* @param savePath 音频保存路径
*/
-(void) setSaveAudioPath:(NSString *)savePath;
/*!
* 录音器是否完成
*
* @return 录音器完全结束返回YES,否则返回NO
*/
-(BOOL) isCompleted;
@end
@@ -0,0 +1,134 @@
//
// IFlyRecognizerView.h
// MSC
//
// Created by admin on 13-4-16.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol IFlyRecognizerViewDelegate ;
/*!
* 语音识别控件<br>
* 录音时触摸控件结束录音,开始识别(相当于旧版的停止);触摸其他位置,取消录音,结束会话(取消)<br>
* 出错时触摸控件,重新开启会话(相当于旧版的再说一次);触摸其他位置,取消录音,结束会话(取消)
*
*/
@interface IFlyRecognizerView : UIView<NSObject>
/*!
* 设置委托对象
*/
@property(nonatomic,assign)id<IFlyRecognizerViewDelegate> delegate;
/*!
* 初始化控件
*
* @param origin 控件左上角的坐标
*
* @return IFlyRecognizerView 对象
*/
- (id)initWithOrigin:(CGPoint)origin;
/*!
* 初始化控件
*
* @param center 控件中心的坐标
*
* @return IFlyRecognizerView 对象
*/
- (id) initWithCenter:(CGPoint)center;
/*!
* 设置横竖屏自适应
*
* @param autoRotate 默认值YES,横竖屏自适应
*/
- (void) setAutoRotate:(BOOL)autoRotate;
/*
* | ------------- |-----------------------------------------------------------
* | 参数 | 描述
* | ------------- |-----------------------------------------------------------
* | domain |应用的领域: 取值为:iat、search、video、poi、music、asr
* | | iat:普通文本听写;
* | | search:热词搜索;
* | | video:视频音乐搜索;
* | | asr:关键词识别;
* | ------------- |-----------------------------------------------------------
* | vad_bos |前端点检测: 静音超时时间,即用户多长时间不说话则当做超时处理; 单位:ms;
* | | engine指定iat识别默认值为5000
* | | 其他情况默认值为 4000,范围 0-10000。
* | ------------- |-----------------------------------------------------------
* | vad_eos |后断点检测: 后端点静音检测时间,即用户停止说话多长时间内即认为不再输入,
* | | 自动停止录音;单位:ms;
* | | sms 识别默认值为 1800;
* | | 其他默认值为 700,范围 0-10000。
* | ------------- |-----------------------------------------------------------
* | sample_rate |采样率:目前支持的采样率设置有 16000 和 8000。
* | ------------- |-----------------------------------------------------------
* | asr_ptt |标点符号设置: 默认为 1,当设置为 0 时,将返回无标点符号文本。
* | ------------- |-----------------------------------------------------------
* | result_type |返回结果的数据格式: 可设置为json,xmlplain,默认为json。
* | ------------- |-----------------------------------------------------------
* | grammarID |识别的语法id: 只针对 domain 设置为”asr”的应用。
* | ------------- |-----------------------------------------------------------
* | asr_audio_path|音频文件名: 设置此参数后,将会自动保存识别的录音文件。
* | | 路径为Documents/(指定值)。
* | | 不设置或者设置为nil,则不保存音频。
* | ------------- |-----------------------------------------------------------
* | params |扩展参数: 对于一些特殊的参数可在此设置,一般用于设置语义。
* | ------------- |-----------------------------------------------------------
*
*/
/*!
* 设置识别引擎的参数
*
* 识别的引擎参数(key)取值如下:<br>
*
* | 参数 | 描述 |
* |-----------------|-------------------------------------------------------|
* | domain | 应用的领域: 取值为:iat、search、video、poi、music、asr<br>iat:普通文本听写;<br>search:热词搜索;<br>video:视频音乐搜索;<br>asr:关键词识别;|
* | vad_bos | 前端点检测: 静音超时时间,即用户多长时间不说话则当做超时处理; 单位:ms;<br>engine指定iat识别默认值为5000<br>其他情况默认值为 4000,范围 0-10000。|
* | vad_eos | 后断点检测: 后端点静音检测时间,即用户停止说话多长时间内即认为不再输入,自动停止录音;单位:ms;<br>sms 识别默认值为 1800;<br>其他默认值为 700,范围 0-10000。|
* | sample_rate | 采样率:目前支持的采样率设置有 16000 和 8000。|
* | asr_ptt | 标点符号设置: 默认为 1,当设置为 0 时,将返回无标点符号文本。|
* | result_type | 返回结果的数据格式: 可设置为json,xmlplain,默认为json。|
* | grammarID | 识别的语法id: 只针对 domain 设置为”asr”的应用。|
* | asr_audio_path | 音频文件名: 设置此参数后,将会自动保存识别的录音文件。<br>路径为Documents/(指定值)。<br>不设置或者设置为nil,则不保存音频。|
* | params | 扩展参数: 对于一些特殊的参数可在此设置,一般用于设置语义。|
*
* @param value 参数对应的取值
* @param key 识别引擎参数
*
* @return 成功返回YES;失败返回NO
*/
-(BOOL) setParameter:(NSString *) value forKey:(NSString*)key;
/*!
* 获取识别引擎参数
*
* @param key 参数key
*
* @return 参数值
*/
-(NSString*) parameterForKey:(NSString *)key;
/*!
* 开始识别
*
* @return 成功返回YES;失败返回NO
*/
- (BOOL)start;
/*!
* 取消本次识别
*/
- (void)cancel;
@end
@@ -0,0 +1,36 @@
//
// IFlyRecognizerDelegate.h
// MSC
//
// Created by admin on 13-4-16.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlyRecognizerView;
@class IFlySpeechError;
/*!
* 识别回调委托
*/
@protocol IFlyRecognizerViewDelegate <NSObject>
/*!
* 回调返回识别结果
*
* @param resultArray 识别结果,NSArray的第一个元素为NSDictionaryNSDictionary的key为识别结果,sc为识别结果的置信度
* @param isLast -[out] 是否最后一个结果
*/
- (void)onResult:(NSArray *)resultArray isLast:(BOOL) isLast;
/*!
* 识别结束回调
*
* @param error 识别结束错误码
*/
- (void)onCompleted: (IFlySpeechError *) error;
@optional
@end
@@ -0,0 +1,90 @@
//
// IFlyResourceUtil.h
// MSCDemo
//
// Created by admin on 14-6-20.
// Copyright (c) 2014年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
* 资源工具类
*/
@interface IFlyResourceUtil : NSObject
/*!
* 获取通过MSPSetParam,启动引擎的标识
*
* @return 通过MSPSetParam,启动引擎的标识
*/
+(NSString*) ENGINE_START;
/*!
* 获取通过MSPSetParam,销毁引擎的标识
*
* @return 通过MSPSetParam,销毁引擎的标识
*/
+(NSString*) ENGINE_DESTROY;
/*!
* 获取识别引擎的资源目录标识
*
* @return 识别引擎的资源目录标识
*/
+(NSString*) ASR_RES_PATH;
/*!
* 得到语法构建目录
*
* @return 语法构建目录
*/
+(NSString*) GRM_BUILD_PATH;
/*!
* 获取合成引擎的资源目录标识,同时需要先传入voice_name方可生效
*
* @return 合成引擎的资源目录标识,同时需要先传入voice_name方可生效
*/
+(NSString*) TTS_RES_PATH;
/*!
* 获取唤醒资源的资源目录标识
*
* @return 唤醒资源的资源目录标识
*/
+(NSString*) IVW_RES_PATH;
/*!
* 语法类型
*
* @return 语法类型
*/
+(NSString*) GRAMMARTYPE;
/*!
* 语记SDK专用参数,用于设置本地默认资源路径
*
* @return 本地默认资源路径key字符串
*/
+(NSString*) PLUS_LOCAL_DEFAULT_RES_PATH;
#pragma mark -
/*!
* 资源存放路径
*
* @param path 设置的路径
*
* @return 资源目录
*/
+(NSString*) generateResourcePath:(NSString *)path;
/**
* 获得离线发音人对应的id
*
* @param voiceName 发音人名称
*
* @return 有,发音人对应的id;无,返回nil
*/
+(NSString*) identifierForVoiceName:(NSString*)voiceName;
@end
@@ -0,0 +1,88 @@
//
// IFlySetting.h
// MSC
//
// Created by iflytek on 13-4-12.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
* 日志打印等级
*/
typedef NS_OPTIONS(NSInteger, LOG_LEVEL){
/*!
* 全部打印
*/
LVL_ALL = -1,
/*!
* 高,异常分析需要的级别
*/
LVL_DETAIL = 31,
/*!
* 中,打印基本日志信息
*/
LVL_NORMAL = 15,
/*!
* 低,只打印主要日志信息
*/
LVL_LOW = 7,
/*!
* 不打印
*/
LVL_NONE = 0
};
/*!
* 此接口为iflyMSC sdk 配置接口。<br>
* 可以获取版本号,设置日志打印等级等
*/
@interface IFlySetting : NSObject
/*!
* 获取版本号
*
* @return 版本号
*/
+ (NSString *) getVersion;
/*!
* 获取日志等级
*
* @return 返回日志等级
*/
+ (LOG_LEVEL) logLvl;
/*!
* 是否打印控制台log<br>
* 在软件发布时,建议关闭此log。
*
* @param showLog -[in] YES,打印log;NO,不打印
*/
+ (void) showLogcat:(BOOL) showLog;
/*!
* 设置日志msc.log生成路径以及日志等级
*
* | 日志打印等级 | 描述 |
* |------------------------|-----------------------------------|
* | LVL_ALL | 全部打印 |
* | LVL_DETAIL | 高,异常分析需要的级别 |
* | LVL_NORMAL | 中,打印基本日志信息 |
* | LVL_LOW | 低,只打印主要日志信息 |
* | LVL_NONE | 不打印 |
*
* @param level -[in] 日志打印等级
*/
+ (void) setLogFile:(LOG_LEVEL) level;
/*!
* 设置日志文件的路径<br>
* 日志文件默认存放在Documents目录。
*
* @param path -[in] 日志文件的全路径
*/
+ (void) setLogFilePath:(NSString*) path;
@end
@@ -0,0 +1,945 @@
//
// IFlySpeechConstant.h
// MSCDemo
//
// Created by iflytek on 5/9/14.
// Copyright (c) 2014 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
* 公共常量类<br>
* 主要定义参数的key value值
*/
@interface IFlySpeechConstant : NSObject
#pragma mark - 通用参数key
/*!
* 语音应用ID<br>
* 通过开发者网站申请
*
* @return 语音应用IDkey
*/
+(NSString*)APPID;
/*!
* 语言区域。
*
* @return 语言区域key。
*/
+(NSString*)ACCENT;
/*!
* 语言区域。
*
* @return 普通话value。
*/
+(NSString*)ACCENT_MANDARIN;
/*!
* 语言区域。
*
* @return 河南话value。
*/
+(NSString*)ACCENT_HENANESE;
/*!
* 语言区域。
*
* @return 四川话value。
*/
+(NSString*)ACCENT_SICHUANESE;
/*!
* 语言区域。
*
* @return 粤语value。
*/
+(NSString*)ACCENT_CANTONESE;
/*!
* 语言<br>
* 支持:zh_cnzh_twen_us<br>
*
* @return 语言key
*/
+(NSString*)LANGUAGE;
/*!
* 语言
*
* @return 中文value
*/
+(NSString*)LANGUAGE_CHINESE;
/*!
* 语言
*
* @return 中文台湾value
*/
+(NSString*)LANGUAGE_CHINESE_TW;
/*!
* 语言
*
* @return 英文value
*/
+(NSString*)LANGUAGE_ENGLISH;
/*!
* 语言
*
* @return 俄语value
*/
+(NSString*)LANGUAGE_RUSSIAN;
/*!
* 语言
*
* @return 日语value
*/
+(NSString*)LANGUAGE_JAPANESE;
/*!
* 语言
*
* @return 法语value
*/
+(NSString*)LANGUAGE_FRENCH;
/*!
* 语言
*
* @return 西班牙语value
*/
+(NSString*)LANGUAGE_SPANISH;
/*!
* 语言
*
* @return 韩语value
*/
+(NSString*)LANGUAGE_KOREAN;
/*!
* 返回结果的数据格式,可设置为json,xml,plain,默认为json。
*
* @return 返回结果的数据格式key
*/
+(NSString*)RESULT_TYPE;
/*!
* 应用领域。
*
* @return 应用领域key
*/
+(NSString*)IFLY_DOMAIN;
/*!
* 个性化数据上传类型
*
* @return 个性化数据上传类型key
*/
+(NSString*)DATA_TYPE;
/*!
* 语音输入超时时间<br>
* 单位:ms,默认30000
*
* @return 语音输入超时时间key
*/
+(NSString*)SPEECH_TIMEOUT;
/*!
* 网络连接超时时间<br>
* 单位:ms,默认20000
*
* @return 网络连接超时时间key
*/
+(NSString*)NET_TIMEOUT;
/*!
* 业务类型。
*
* @return 业务类型key。
*/
+(NSString*)SUBJECT;
/*!
* 扩展参数。
*
* @return 扩展参数key。
*/
+(NSString*)PARAMS;
/*!
* 加密参数
*
* 支持类型:ssl 加密 tcp 非加密 默认:tcp<br>
* 建议对安全性要求较高时使用ssl。
*
* @return 加密参数key
*/
+(NSString*)PROT_TYPE;
/*!
* ssl证书内容
*
* @return ssl证书内容key
*/
+(NSString*)SSL_CERT;
/*!
* 录音音量返回时间间隔。
*
* @return 间隔key。
*/
+(NSString*)POWER_CYCLE;
/*!
* 合成、识别、唤醒、评测、声纹等业务采样率。
*
* @return 合成及识别采样率key。
*/
+(NSString*)SAMPLE_RATE;
/*!
* 合成、识别、唤醒、声纹等业务采样率。
*
* @return 合成及识别采样率8K Value。
*/
+(NSString*)SAMPLE_RATE_8K;
/*!
* 合成、识别、唤醒、评测、声纹等业务采样率。
*
* @return 合成及识别采样率16K Value。
*/
+(NSString*)SAMPLE_RATE_16K;
/*!
* 引擎类型。<br>
* 可选:localcloudauto<br>
* 默认:auto
*
* @return 引擎类型key。
*/
+(NSString*)ENGINE_TYPE;
/*!
* 本地xtts识别引擎。
*
* @return 本地识别引擎value。
*/
+(NSString*)TYPE_LOCAL_XTTS;
/*!
* 本地识别引擎。
*
* @return 本地识别引擎value。
*/
+(NSString*)TYPE_LOCAL;
/*!
* 云端识别引擎。
*
* @return 云端识别引擎value。
*/
+(NSString*)TYPE_CLOUD;
/*!
* 混合识别引擎。
*
* @return 混合识别引擎value。
*/
+(NSString*)TYPE_MIX;
/*!
* 引擎根据当前配置进行选择。
*
* @return 引擎根据当前配置进行选择value。
*/
+(NSString*)TYPE_AUTO;
/*!
* 输入文本编码格式。
*
* @return 编码格式key。
*/
+(NSString*)TEXT_ENCODING;
/*!
* 结果编码格式。
*
* @return 结果编码格式key。
*/
+(NSString*)RESULT_ENCODING;
/*!
* 是否初始化播放器<br>
* SDK内部播放器采用音频队列实现,有部分外部需求需要自定义音频队列,可以通过此开关控制<br>
* 0:不初始化,非0或者参数为空:初始化,默认初始化
*
* @return 是否初始化播放器参数key
*/
+(NSString*)PLAYER_INIT;
/*!
* 是否播放器结束后发送deactive系统通知<br>
* SDK内部播放器结束后可通过此开关发送deactive系统通知,使其他被中断的音频应用解除中断<br>
* 0:不发送,非0或者参数为空:发送,默认发送
*
* @return 是否播放器结束后发送deactive系统通知参数key
*/
+(NSString*)PLAYER_DEACTIVE;
/**
* 是否初始化录音器<br>
* SDK内部录音器采用音频队列实现,有部分外部需求需要自定义音频队列,可以通过此开关控制<br>
* 0:不初始化,非0或者参数为空:初始化,默认初始化
*
* @return 是否初始化录音器参数key
*/
+(NSString*)RECORDER_INIT;
/**
* 是否录音器结束后发送deactive系统通知<br>
* SDK内部录音器结束后可通过此开关发送deactive系统通知,使其他被中断的音频应用解除中断<br>
* 0:不发送,非0或者参数为空:发送,默认发送
*
* @return 是否录音器结束后发送deactive系统通知参数key
*/
+(NSString*)RECORDER_DEACTIVE;
#pragma mark - 合成相关设置key
/*!
* 语速<br>
* 范围 0~100 默认值:50
*
* @return 语速key
*/
+(NSString*)SPEED;
/*!
* 音调<br>
* 范围(0~100)默认值:50
*
* @return 音调key
*/
+(NSString*)PITCH;
/*!
* 合成录音保存路径
*
* 注意:只需要设置文件名则可,会自动拼接到[IFlySetting setLogFilePath]接口设置的目录后
*
* @return 合成录音保存路径key
*/
+(NSString*)TTS_AUDIO_PATH;
/**
* 启用VAD功能
*
* @return 启用VAD功能key
*/
+(NSString*)VAD_ENABLE;
/*!
* VAD前端点超时<br>
* 范围:0-10000(单位ms)
*
* @return VAD前端点超时key
*/
+(NSString*)VAD_BOS;
/*!
* VAD后端点超时。<br>
* 可选范围:0-10000(单位ms)
*
* @return VAD后端点超时key
*/
+(NSString*)VAD_EOS;
/*
* 云端支持如下发音人:
* 对于网络TTS的发音人角色,不同引擎类型支持的发音人不同,使用中请注意选择。
*
* |--------|----------------|
* | 发音人 | 参数 |
* |--------|----------------|
* | 小燕 | xiaoyan |
* |--------|----------------|
* | 小宇 | xiaoyu |
* |--------|----------------|
* | 凯瑟琳 | catherine |
* |--------|----------------|
* | 亨利 | henry |
* |--------|----------------|
* | 玛丽 | vimary |
* |--------|----------------|
* | 小研 | vixy |
* |--------|----------------|
* | 小琪 | vixq |
* |--------|----------------|
* | 小峰 | vixf |
* |--------|----------------|
* | 小梅 | vixl |
* |--------|----------------|
* | 小莉 | vixq |
* |--------|----------------|
* | 小蓉 | vixr |
* |--------|----------------|
* | 小芸 | vixyun |
* |--------|----------------|
* | 小坤 | vixk |
* |--------|----------------|
* | 小强 | vixqa |
* |--------|----------------|
* | 小莹 | vixyin |
* |--------|----------------|
* | 小新 | vixx |
* |--------|----------------|
* | 楠楠 | vinn |
* |--------|----------------|
* | 老孙 | vils |
* |--------|----------------|
*/
/*!
* 发音人
*
* 云端支持如下发音人:<br>
* 对于网络TTS的发音人角色,不同引擎类型支持的发音人不同,使用中请注意选择。<br>
*
* | 发音人 | 参数 |
* |:--------:|:----------------:|
* | 小燕 | xiaoyan |
* | 小宇 | xiaoyu |
* | 凯瑟琳 | catherine |
* | 亨利 | henry |
* | 玛丽 | vimary |
* | 小研 | vixy |
* | 小琪 | vixq |
* | 小峰 | vixf |
* | 小梅 | vixl |
* | 小莉 | vixq |
* | 小蓉 | vixr |
* | 小芸 | vixyun |
* | 小坤 | vixk |
* | 小强 | vixqa |
* | 小莹 | vixyin |
* | 小新 | vixx |
* | 楠楠 | vinn |
* | 老孙 | vils |
*
* @return 发音人key
*/
+(NSString*)VOICE_NAME;
/*!
* 发音人ID key。
*
* @return 发音人ID key
*/
+(NSString*)VOICE_ID;
/*!
* 发音人语种 key。
*
* 参数值:0:Auto 1:中文 2英文 ,默认 0.
*
* @return 发音人ID key
*/
+(NSString*)VOICE_LANG;
/*!
* 音量<br>
* 范围(0~100 默认值:50
*
* @return 音量key
*/
+(NSString*)VOLUME ;
/*!
* 合成音频播放缓冲时间<br>
* 即缓冲多少秒音频后开始播放,如tts_buffer_time=1000;<br>
* 默认缓冲1000ms毫秒后播放。
*
* @return 合成音频播放缓冲时间缓冲时间key
*/
+(NSString*)TTS_BUFFER_TIME ;
/*!
* 合成数据是否即时返回
*
* 是否需要数据回调,为1时,当合成一段音频会通过onEvent回调返回,直接合成结束;<br>
* 设置为1为即时返回;0为非即时返回;默认值为0;
*
* @return 合成数据即时返回key
*/
+(NSString*)TTS_DATA_NOTIFY;
/*!
* 预合成文本
*
* @return 预合成文本参数key
*/
+(NSString*)NEXT_TEXT;
/*!
* 是否需要打开MPPlayingInfocenter<br>
* 是否需要初始化MPPlayerCenter的属性;0:需要初始化,1:不初始化
*
* @return 是否需要打开MPPlayingInfocenter 参数key
*/
+(NSString*)MPPLAYINGINFOCENTER;
#pragma mark - 识别、听写、语义相关设置key
/*!
* 录音源<br>
* 录音时的录音方式,默认为麦克风,设置为1;<br>
* 如果需要外部送入音频,设置为-1,通过WriteAudio接口送入音频。
*
* @return 录音源key
*/
+(NSString*)AUDIO_SOURCE;
/*!
* 识别录音保存路径
*
* @return 识别录音保存路径key
*/
+(NSString*) ASR_AUDIO_PATH;
/*!
* 设置是否开启语义
*
* @return 设置是否开启语义key
*/
+(NSString*)ASR_SCH;
/*!
* 设置是否有标点符号
*
* @return 设置是否有标点符号key
*/
+(NSString*)ASR_PTT;
/*!
* ASR_PTT 参数值:设置带标点符号
*
* @return 设置是有标点符号Value
*/
+(NSString*)ASR_PTT_HAVEDOT;
/*!
* ASR_PTT 参数值:设置不带标点符号
*
* @return 设置是无标点符号Value
*/
+(NSString*)ASR_PTT_NODOT;
/*!
* 本地语法名称。<br>
* 本地语法名称,对应云端的有CLOUD_GRAMMAR
*
* @return 本地语法名称key。
*/
+(NSString*)LOCAL_GRAMMAR;
/*!
* 云端语法ID。<br>
* 云端编译语法返回的表示,早期版本使用GRAMMAR_ID,仍然兼容,但建议使用新的。
*
* @return 云端语法ID key。
*/
+(NSString*)CLOUD_GRAMMAR;
/*!
* 语法类型
*
* @return 语法类型key
*/
+(NSString*)GRAMMAR_TYPE;
/*!
* 语法内容。
*
* @return 语法内容key。
*/
+(NSString*)GRAMMAR_CONTENT;
/*!
* 字典内容。
*
* @return 字典内容key。
*/
+(NSString*)LEXICON_CONTENT;
/*!
* 字典名字。
*
* @return 字典名字key。
*/
+(NSString*)LEXICON_NAME;
/*!
* 语法名称列表。
*
* @return 语法名称列表key。
*/
+(NSString*)GRAMMAR_LIST;
/*!
* 开放语义协议版本号。<br>
* 如需使用请在http://osp.voicecloud.cn/上进行业务配置
*
* @return 开放语义协议版本号key。
*/
+(NSString*)NLP_VERSION;
#pragma mark - 唤醒相关设置key
/*!
* 唤醒门限值。
*
* @return 唤醒门限值key。
*/
+(NSString*)IVW_THRESHOLD;
/*!
* 唤醒服务类型。
*
* @return 唤醒服务类型key。
*/
+(NSString*)IVW_SST;
/*!
* 唤醒+识别。
*
* @return 唤醒+识别key。
*/
+(NSString*)IVW_ONESHOT;
/*!
* 唤醒工作方式<br>
* 1:表示唤醒成功后继续录音,0:表示唤醒成功后停止录音。
*
* @return 唤醒工作方式key
*/
+(NSString*)KEEP_ALIVE;
/*!
* 唤醒录音保存路径
*
* @return 唤醒录音保存路径key
*/
+(NSString*) IVW_AUDIO_PATH;
#pragma mark - 评测相关设置key
/*!
* 评测类型<br>
* 可选值:read_syllable(英文评测不支持):单字;read_word:词语;read_sentence:句子;read_chapter(待开放):篇章。
*
* @return 评测类型 key
*/
+(NSString*)ISE_CATEGORY;
/*!
* 评测结果等级<br>
* 可选值:complete:完整 plain:简单
*
* @return 评测结果等级 key
*/
+(NSString*)ISE_RESULT_LEVEL;
/*!
* 评测结果格式<br>
* 可选值:xml;plain
*
* @return 评测结果格式 key
*/
+(NSString*)ISE_RESULT_TYPE;
/*!
* 评测录音保存路径
*
* @return 评测录音保存路径key
*/
+(NSString*) ISE_AUDIO_PATH;
/*!
* 朗读跟踪,只对句子和篇章有效<br>
* 可选值:enable:开启;disable:关闭。
*
* @return 朗读跟踪 key
*/
+(NSString*)ISE_AUTO_TRACKING;
/*!
* 跟踪模式<br>
* 可选值:easy:简单;hard:复杂。
*
* @return 跟踪模式 key
*/
+(NSString*)ISE_TRACK_TYPE;
#pragma mark - 语记SDK业务key
/*!
* 本地所有资源
*
* @return 本地所有资源key
*/
+ (NSString *)PLUS_LOCAL_ALL;
/*!
* 本地合成资源
*
* @return 本地合成资源key
*/
+ (NSString *)PLUS_LOCAL_TTS;
/*!
* 本地识别资源
*
* @return 本地识别资源key
*/
+ (NSString *)PLUS_LOCAL_ASR;
/*!
* 本地唤醒资源
*
* @return 本地唤醒资源key
*/
+ (NSString *)PLUS_LOCAL_IVW;
#pragma mark - 身份验证业务key
/*!
* auth_id<br>
* 用于用户注册和登录、查询、删除等业务时标识用户身份
*
* @return 用户标识
*/
+ (NSString*)MFV_AUTH_ID;
/*!
* 请求业务类型,可选值:mfv(默认,融合验证),ivp(声纹),ifr(人脸)
*
* @return 请求业务类型key
*/
+ (NSString*)MFV_SUB;
/*!
* 会话类型,不同sub有不同的sst取值。<br>
* ifrenrollverifyidentifyreenrollquerydelete<br>
* ivpenrolltrain),verifyreenrollquerydeletedownload
*
* @return 会话类型key
*/
+ (NSString*)MFV_SST;
/*!
* 融合验证模式,仅在融合验证场景下使用。可选值:sin(单一生物特征数据验证),mix(混合生物特征数据验证),agi(灵活生物特征数据验证)
*
* @return 融合验证模式key
*/
+ (NSString*)MFV_VCM;
/*!
* 特征场景,用来说明本次验证将涉及的业务。可选值:ivp,ifr,ivp|ifr
*
* @return 特征场景 key
*/
+ (NSString*)MFV_SCENES;
/*!
* 确认周期(affirmance cycle,单位:s),用户设置的确认超时时间(生命周期),仅在灵活融合验证场景下使用
*
* @return 确认周期key
*/
+ (NSString*)MFV_AFC;
/*!
* 数据保存路径
*
* @return 数据保存路径key
*/
+ (NSString*)MFV_DATA_PATH;
/*!
* 训练次数:取值2~9.无默认值,必须明确指定。
*
* @return 训练次数key
*/
+ (NSString*)MFV_RGN;
/*!
* 声纹确认门限值,验证得分>=tsd验证通过,否则验证失败(该参数目前不支持,作为保留参数。)却只范围:0~100.
*
* @return 声纹确认门限值key
*/
+ (NSString*)MFV_TSD;
/*!
* 密码文本。从服务端下载,比如数字密码所需要的数字串。
*
* @return 密码文本key
*/
+ (NSString*)MFV_PTXT;
/*!
* 密码类型。取值:1(文本密码),2(自由说),3(数字密码).
*
* @return 密码类型key
*/
+ (NSString*)MFV_PWDT;
/*!
* 取消注册。取值:0(不取消,即不生效),1(取消本次注册).
*
* @return 取消注册key
*/
+ (NSString*)MFV_FIN;
/*!
* 等待超时时间:描述客户端等待结果的超时时间
*
* @return 等待超时时间:key
*/
+ (NSString*)MFV_WTT;
/*!
* 数据格式<br>
* 声纹为音频采样率支持:16000和8000;人脸为图片格式,支持jpg和gif
*
* @return 数据格式key
*/
+ (NSString*)MFV_DATA_FORMAT;
/*!
* 数据压缩编码<br>
* 声纹为;人脸支持raw,不对图片压缩
*
* @return 数据压缩编码key
*/
+ (NSString*)MFV_DATA_ENCODING;
#pragma mark - 人脸业务key
//1. sub 取值: wfr 用途: 用于区分业务类型,web访问方式中,nginx配置不用使用,但是在结构化日志和染色日志记录中使用。
//2. sst 取值: reg、verify、detect、align 用途: 指定本路会话是属于何种性质
// + 人脸图像注册(reg):上传图像,验证图像的有效性,然后存储起来,作为数据源。
// + 人脸图像验证(verify):通过与指定源图像比较,验证人脸相似性。
// + 人脸图像检测(detect):能够检测出不同姿态方位的人脸在图中的位置。
// + 人脸图像聚焦(align):在给定人脸框下自动标定出两眼、鼻尖、嘴角的坐标。
//3. aue 取值: raw 用途: 图像压缩格式,现在引擎不支持图像压缩,aue只能取值raw
//4. pset 取值: 整数 用途: 人脸识别验证阈值,取值可以是负数也可以是整数。
//5. skip 取值: true/false 用途: 后台图片处理是否进行过滤。true表示不过滤,false表示过滤
//6. gid 取值: *********** 用途: 图像模型id,如:4a6c124ed6b78436ee5aac4563f13eb5
//7. appid 取值:用户申请的appid 用途: 验证用户
/*!
* sub 默认值:wfr<br>
* 用于区分业务类型,web访问方式中,nginx配置不用使用,但是在结构化日志和染色日志记录中使用。
*/
+ (NSString*) FACE_SUB;
/*!
* WFR<br>
* sub参数的默认值
*/
+ (NSString*) FACE_WFR;
/*!
* sst<br>
* 指定本路会话是属于何种性质
*/
+ (NSString*) FACE_SST;
/*!
* REG<br>
* 人脸图像注册(reg):上传图像,验证图像的有效性,然后存储起来,作为数据源。
*/
+ (NSString*) FACE_REG;
/*!
* VERIFY<br>
* 人脸图像验证(verify):通过与指定源图像比较,验证人脸相似性。
*/
+ (NSString*) FACE_VERIFY;
/*!
* DETECT<br>
* 人脸图像检测(detect):能够检测出不同姿态方位的人脸在图中的位置。
*/
+ (NSString*) FACE_DETECT;
/*!
* ALIGN<br>
* 人脸图像聚焦(align):在给定人脸框下自动标定出两眼、鼻尖、嘴角的坐标。
*/
+ (NSString*) FACE_ALIGN;
/*!
* ATTR<br>
* 面部属性识别(attr):对面部属性进行识别:例如秃顶、刘海、大嘴、模糊、眼镜等。
*/
+ (NSString*) FACE_ATTR;
/*!
* AUE<br>
* 图像压缩格式,现在引擎不支持图像压缩,aue只能取值raw
*/
+ (NSString*) FACE_AUE;
/*!
* RAW<br>
* AUE参数的值
*/
+ (NSString*) FACE_RAW;
/*!
* PSET<br>
* 人脸识别验证阈值,取值可以是负数也可以是整数。
*/
+ (NSString*) FACE_PSET;
/*!
* SKIP<br>
* 后台图片处理是否进行过滤。true表示不过滤,false表示过滤,传入字符串@“true”或@“false”
*/
+ (NSString*) FACE_SKIP;
/*!
* GID<br>
* 图像模型id,如:4a6c124ed6b78436ee5aac4563f13eb5
*/
+ (NSString*) FACE_GID;
/*!
* auth_id<br>
* 用于用户注册和登录、查询、删除等业务时标识用户身份
*
* @return 用户标识
*/
+ (NSString*)FACE_AUTH_ID;
/*!
* DVC<br>
* 用户设备编号,用于验证用户
*/
+ (NSString*) FACE_DVC;
@end
@@ -0,0 +1,58 @@
//
// IFlySpeechError.h
// MSC
//
// Created by iflytek on 13-3-19.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#ifndef __IFlySpeechError__
#define __IFlySpeechError__
#import <Foundation/Foundation.h>
/*!
* 错误描述类
*/
@interface IFlySpeechError : NSObject
/*!
* 错误码
*/
@property(nonatomic,assign) int errorCode;
/*!
* 错误码类型
*/
@property(nonatomic,assign) int errorType;
/*!
* 错误描述
*/
@property(nonatomic,retain) NSString* errorDesc;
/*!
* 初始化
*
* @param errorCode -[in] 错误码
*
* @return IFlySpeechError对象
*/
+ (instancetype) initWithError:(int) errorCode;
/*!
* 获取错误码
*
* @return 错误码
*/
-(int) errorCode;
/*!
* 获取错误描述
*
* @return 错误描述
*/
- (NSString *) errorDesc;
@end
#endif
@@ -0,0 +1,101 @@
//
// IFlySpeechEvaluator.h
// msc
//
// Created by jianzhang on 14-1-13
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IFlySpeechEvaluatorDelegate.h"
#define IFLY_AUDIO_SOURCE_MIC @"1"
#define IFLY_AUDIO_SOURCE_STREAM @"-1"
/*!
* 语音评测类
*/
@interface IFlySpeechEvaluator : NSObject <IFlySpeechEvaluatorDelegate>
/*!
* 设置委托对象
*/
@property (assign) id <IFlySpeechEvaluatorDelegate> delegate;
/*!
* 返回评测对象的单例
*
* @return 别对象的单例
*/
+ (instancetype)sharedInstance;
/*!
* 销毁评测对象。
*
* @return 成功返回YES,失败返回NO。
*/
- (BOOL)destroy;
/*!
* 设置评测引擎的参数
*
* @param value 评测引擎参数值
* @param key 评测引擎参数
*
* @return 设置的参数和取值正确返回YES,失败返回NO
*/
- (BOOL)setParameter:(NSString *)value forKey:(NSString *)key;
/*!
* 获得评测引擎的参数
*
* @param key 评测引擎参数
*
* @return key对应的参数值
*/
- (NSString*)parameterForKey:(NSString *)key;
/*!
* 开始评测<br>
* 同时只能进行一路会话,这次会话没有结束不能进行下一路会话,否则会报错
*
* @param data 评测的试题
* @param params 评测的参数
* @return 成功返回YES,失败返回NO
*/
- (BOOL)startListening:(NSData *)data params:(NSString *)params;
/*!
* 停止录音<br>
* 调用此函数会停止录音,并开始进行语音识别
*/
- (void)stopListening;
/*!
* 取消本次会话
*/
- (void)cancel;
@end
/*!
* 音频流评测<br>
* 音频流评测可以将文件分段写入
*/
@interface IFlySpeechEvaluator(IFlyStreamISERecognizer)
/*!
* 写入音频流
*
* @param audioData 音频数据
*
* @return 写入成功返回YES,写入失败返回NO
*/
- (BOOL) writeAudio:(NSData *) audioData;
@end
@@ -0,0 +1,64 @@
//
// IFlySpeechEvaluatorDelegate.h
// msc
//
// Created by admin on 13-6-19.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlySpeechError;
/*!
* 评测协议
*/
@protocol IFlySpeechEvaluatorDelegate <NSObject>
/*!
* 音量和数据回调
*
* @param volume 音量
* @param buffer 音频数据
*/
- (void)onVolumeChanged:(int)volume buffer:(NSData *)buffer;
/*!
* 开始录音回调<br>
* 当调用了`startListening`函数之后,如果没有发生错误则会回调此函数。如果发生错误则回调onCompleted:函数
*/
- (void)onBeginOfSpeech;
/*!
* 停止录音回调<br>
* 当调用了`stopListening`函数或者引擎内部自动检测到断点,如果没有发生错误则回调此函数。<br>
* 如果发生错误则回调onCompleted:函数
*/
- (void)onEndOfSpeech;
/*!
* 正在取消
*/
- (void)onCancel;
/*!
* 评测错误回调
*
* 在进行语音评测过程中的任何时刻都有可能回调此函数,你可以根据errorCode进行相应的处理.当errorCode没有错误时,表示此次会话正常结束,否则,表示此次会话有错误发生。特别的当调用`cancel`函数时,引擎不会自动结束,需要等到回调此函数,才表示此次会话结束。在没有回调此函数之前如果重新调用了`startListenging`函数则会报错误。
*
* @param errorCode 错误描述类
*/
- (void)onCompleted:(IFlySpeechError *)errorCode;
/*!
* 评测结果回调<br>
* 在评测过程中可能会多次回调此函数,你最好不要在此回调函数中进行界面的更改等操作,只需要将回调的结果保存起来。
*
* @param results -[out] 评测结果。
* @param isLast -[out] 是否最后一条结果
*/
- (void)onResults:(NSData *)results isLast:(BOOL)isLast;
@end
@@ -0,0 +1,151 @@
//
// IFlySpeechEvent.h
// MSCDemo
//
// Created by admin on 14-8-12.
// Copyright (c) 2014年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
* 事件类型
*/
typedef NS_ENUM(NSUInteger,IFlySpeechEventType){
/*!
* 网络状态消息<br>
* 在消息到达时,可通过onEvent的第2个参数arg1,获取当前网络连接状态值
*/
IFlySpeechEventTypeNetPref = 10001,
/*!
* 转写音频文件消息<br>
* 在录音模式下,成功创建音频文件时返回。可通过onEvent第4个参数data,指定Key为[IFlySpeechConstant IST_AUDIO_PATH],获取音频文件绝对路径.或通过[IFlySpeechTranscripter getParameter:[IFlySpeechConstant IST_AUDIO_PATH]],获取音频文件绝对路径.
*/
IFlySpeechEventTypeISTAudioFile = 10004,
/*!
* 转写已上传字节消息<br>
* 在消息到达时,通过onEvent的第二个参数arg1,获取已确认上传到服务器的字节数.若当前音频源为非写音频模式,还可通过onEvent
* 的第三个参数arg2,获取当前所有音频的字节大小.录音模式时,由于所有音频字节大小会变。当停止音频输入后(等待录音时间超时[IFlySpeechConstant SPEECH_TIMEOUT],或调用[IFlySpeechTranscripter stopTranscripting]),且服务器收到所有音频时,第四个参数data,将包含完成标记的布尔值(true),可通过data调用指定KEY为KCIFlySpeechEventKeyISTUploadComplete获取。此消息可能多次返回.
*/
IFlySpeechEventTypeISTUploadBytes = 10006,
/*!
* 转写缓存剩余<br>
* 此消息仅在音频源为-1时需要关注,在调用[IFlySpeechTranscripter writeAudio]写音频时,应该关注此事件。<br>
* 此事件在调用写音频接口、及音频最后被写入底库库时分别回调一次。当事件回调时,通过onEvent的第二个参数arg1,获取当前剩余的缓存大小,当缓存小于要写入的音频时,应该先暂停写音频数据,直到下次缓存大小大于要写入的音频时.最大缓存为128KByte。
*/
IFlySpeechEventTypeISTCacheLeft = 10007,
/*!
* 转写结果等待时间消息<br>
* 在消息到达时,通过 onEvent的第二个参数arg1,获取当前结果需要的时间.<br>
* 此消息可能多次返回,返回时间不定,且不一定会返回.
*/
IFlySpeechEventTypeISTResultTime= 10008,
/*!
* 转写转写音频同步ID消息<br>
* 在消息到达时,通过 onEvent的第二个参数arg1,获取当前写音频同步ID.<br>
* 此消息可能多次返回.
*/
IFlySpeechEventTypeISTSyncID= 10009,
/*!
* 会话开始消息<br>
* 在会话开始成功后返回
*/
IFlySpeechEventTypeSessionBegin = 10010,
/*!
* 会话结束消息<br>
* 在会话结束前返回
*/
IFlySpeechEventTypeSessionEnd = 10011,
/*!
* 音量消息,在得到音量时抛出,暂时只有身份验证的声纹业务用到
*/
IFlySpeechEventTypeVolume = 10012,
/*!
* VAD后端点消息,在检测到VAD后端点时抛出,暂时只有身份验证的声纹业务用到
*/
IFlySpeechEventTypeVadEOS = 10013,
/*!
* 服务端会话id<br>
* 在消息到达时,可通过onEvent的第4个参数data(字典类型),指定key KCIFlySpeechEventKeySessionID,获取服务端会话id.
*/
IFlySpeechEventTypeSessionID = 20001,
/*!
* TTS合成数据消息<br>
* -(void)onEvent:(int)eventType arg0:(int)arg0 arg1:(int)arg1 data:(NSData *)eventData<br>
* 其中eventData中包含数据
*
*/
IFlySpeechEventTypeTTSBuffer = 21001,
/*!
* 通知cancel方法被调用的回调
*
*/
IFlySpeechEventTypeTTSCancel = 21002,
/*!
* IVW onshot 听写 or 识别结果<br>
* 在消息到达时,第2个参数arg1包含是否为最后一个结果:1为是,0为否;<br>
* 第4个参数data中包含数据,通过指定KEY为KCIFlySpeechEventKeyIVWResult获取.
*/
IFlySpeechEventTypeIVWResult = 22001,
/*!
* 开始处理录音数据
*
*/
IFlySpeechEventTypeSpeechStart= 22002,
/*!
* 录音停止
*
*/
IFlySpeechEventTypeRecordStop= 22003,
/*!
* 服务端音频url<br>
* 在消息到达时,第4个参数data,包含数据,通过指定KEY为KCIFlySpeechEventKeyAudioUrl获取.
*/
IFlySpeechEventTypeAudioUrl = 23001,
/*!
* 变声数据结果返回<br>
* 设置voice_change参数获取结果.
*/
IFlySpeechEventTypeVoiceChangeResult = 24001
};
#pragma mark - keys for event data
/**
* 转写是否已上传完标记key
*/
extern NSString* const KCIFlySpeechEventKeyISTUploadComplete;
/**
* 服务端会话key
*/
extern NSString* const KCIFlySpeechEventKeySessionID;
/**
* TTS取音频数据key
*/
extern NSString* const KCIFlySpeechEventKeyTTSBuffer;
/**
* IVW oneshot 听写 or 识别结果 key
*/
extern NSString* const KCIFlySpeechEventKeyIVWResult;
/**
* 服务端音频url key
*/
extern NSString* const KCIFlySpeechEventKeyAudioUrl;
@@ -0,0 +1,175 @@
//
// IFlySpeechRecognizer.h
// MSC
//
// Created by iflytek on 13-3-19.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IFlySpeechRecognizerDelegate.h"
#define IFLY_AUDIO_SOURCE_MIC @"1"
#define IFLY_AUDIO_SOURCE_STREAM @"-1"
/*!
* 语音识别类<br>
* 此类现在设计为单例,你在使用中只需要创建此对象,不能调用release/dealloc函数去释放此对象。所有关于语音识别的操作都在此类中。
*/
@interface IFlySpeechRecognizer : NSObject<IFlySpeechRecognizerDelegate>
/*!
* 设置委托对象
*/
@property(nonatomic,assign) id<IFlySpeechRecognizerDelegate> delegate ;
/*!
* 返回识别对象的单例
*
* @return 识别对象的单例
*/
+ (instancetype) sharedInstance;
/*!
* 销毁识别对象。
*
* @return 成功返回YES,失败返回NO
*/
- (BOOL) destroy;
/*
* | ------------- |-----------------------------------------------------------
* | 参数 | 描述
* | ------------- |-----------------------------------------------------------
* | domain |应用的领域: 取值为:iat、search、video、poi、music、asr
* | | iat:普通文本听写;
* | | search:热词搜索;
* | | video:视频音乐搜索;
* | | asr:关键词识别;
* | ------------- |-----------------------------------------------------------
* | vad_bos |前端点检测: 静音超时时间,即用户多长时间不说话则当做超时处理; 单位:ms;
* | | engine指定iat识别默认值为5000
* | | 其他情况默认值为 4000,范围 0-10000。
* | ------------- |-----------------------------------------------------------
* | vad_eos |后断点检测: 后端点静音检测时间,即用户停止说话多长时间内即认为不再输入,
* | | 自动停止录音;单位:ms;
* | | sms 识别默认值为 1800;
* | | 其他默认值为 700,范围 0-10000。
* | ------------- |-----------------------------------------------------------
* | sample_rate |采样率:目前支持的采样率设置有 16000 和 8000。
* | ------------- |-----------------------------------------------------------
* | asr_ptt |标点符号设置: 默认为 1,当设置为 0 时,将返回无标点符号文本。
* | ------------- |-----------------------------------------------------------
* | result_type |返回结果的数据格式: 可设置为json,xmlplain,默认为json。
* | ------------- |-----------------------------------------------------------
* | grammarID |识别的语法id: 只针对 domain 设置为”asr”的应用。
* | ------------- |-----------------------------------------------------------
* | asr_audio_path|音频文件名: 设置此参数后,将会自动保存识别的录音文件。
* | | 路径为Documents/(指定值)。
* | | 不设置或者设置为nil,则不保存音频。
* | ------------- |-----------------------------------------------------------
* | params |扩展参数: 对于一些特殊的参数可在此设置,一般用于设置语义。
* | ------------- |-----------------------------------------------------------
*
*/
/*!
* 设置识别引擎的参数
*
* 识别的引擎参数(key)取值如下:
*
* | 参数 | 描述 |
* |-----------------|-------------------------------------------------------|
* | domain | 应用的领域: 取值为:iat、search、video、poi、music、asr<br>iat:普通文本听写;<br>search:热词搜索;<br>video:视频音乐搜索;<br>asr:关键词识别;|
* | vad_bos | 前端点检测: 静音超时时间,即用户多长时间不说话则当做超时处理; 单位:ms;<br>engine指定iat识别默认值为5000<br>其他情况默认值为 4000,范围 0-10000。|
* | vad_eos | 后断点检测: 后端点静音检测时间,即用户停止说话多长时间内即认为不再输入,自动停止录音;单位:ms;<br>sms 识别默认值为 1800;<br>其他默认值为 700,范围 0-10000。|
* | sample_rate | 采样率:目前支持的采样率设置有 16000 和 8000。|
* | asr_ptt | 标点符号设置: 默认为 1,当设置为 0 时,将返回无标点符号文本。|
* | result_type | 返回结果的数据格式: 可设置为json,xmlplain,默认为json。|
* | grammarID | 识别的语法id: 只针对 domain 设置为”asr”的应用。|
* | asr_audio_path | 音频文件名: 设置此参数后,将会自动保存识别的录音文件。<br>路径为Documents/(指定值)。<br>不设置或者设置为nil,则不保存音频。|
* | params | 扩展参数: 对于一些特殊的参数可在此设置,一般用于设置语义。|
*
* @param value 参数对应的取值
* @param key 识别引擎参数
*
* @return 成功返回YES;失败返回NO
*/
-(BOOL) setParameter:(NSString *) value forKey:(NSString*)key;
/*!
* 获取识别引擎参数
*
* @param key 参数key
*
* @return 参数值
*/
-(NSString*) parameterForKey:(NSString *)key;
/*!
* 开始识别
*
* 同时只能进行一路会话,这次会话没有结束不能进行下一路会话,否则会报错。若有需要多次回话,请在onCompleted回调返回后请求下一路回话。
*
* @return 成功返回YES;失败返回NO
*/
- (BOOL) startListening;
/*!
* 停止录音<br>
* 调用此函数会停止录音,并开始进行语音识别
*/
- (void) stopListening;
/*!
* 取消本次会话
*/
- (void) cancel;
/*!
* 上传语法
*
* @param completionHandler 上传语法完成回调
* @param grammarType 语法类型
* @param grammarContent 语法内容
*
* @return 错误码
*/
- (int) buildGrammarCompletionHandler:(IFlyOnBuildFinishCompletionHandler)completionHandler
grammarType:(NSString *)grammarType
grammarContent:(NSString *)grammarContent;
/*!
* 是否正在识别
*/
@property (nonatomic, readonly) BOOL isListening;
@end
/*!
* 音频流识别<br>
* 音频流识别可以将文件分段写入
*/
@interface IFlySpeechRecognizer(IFlyStreamRecognizer)
/*!
* 写入音频流
*
* 此方法的使用示例如下:
* <pre><code>[_iFlySpeechRecognizer setParameter:@"-1" value:@"audio_source"];
* [_iFlySpeechRecognizer startListening];
* [_iFlySpeechRecognizer writeAudio:audioData1];
* [_iFlySpeechRecognizer writeAudio:audioData2];
* ...
* [_iFlySpeechRecognizer stopListening];
* </code></pre>
*
* @param audioData 音频数据
*
* @return 写入成功返回YES,写入失败返回NO
*/
- (BOOL) writeAudio:(NSData *) audioData;
@end
@@ -0,0 +1,111 @@
//
// IFlySpeechRecognizerDelegate.h
// MSC
//
// Created by ypzhao on 13-3-27.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlySpeechError;
/*!
* 构建语法结束回调
*
* @param grammarId 语法id
* @param error 错误描述
*/
typedef void(^IFlyOnBuildFinishCompletionHandler)(NSString* grammarId,IFlySpeechError * error);
/*!
* 语音识别协议<br>
* 在使用语音识别时,需要实现这个协议中的方法.
*/
@protocol IFlySpeechRecognizerDelegate <NSObject>
@required
/*!
* 识别结果回调
*
* 在进行语音识别过程中的任何时刻都有可能回调此函数,你可以根据errorCode进行相应的处理,当errorCode没有错误时,表示此次会话正常结束;否则,表示此次会话有错误发生。特别的当调用`cancel`函数时,引擎不会自动结束,需要等到回调此函数,才表示此次会话结束。在没有回调此函数之前如果重新调用了`startListenging`函数则会报错误。
*
* @param errorCode 错误描述
*/
- (void) onCompleted:(IFlySpeechError *) errorCode;
/*!
* 识别结果回调
*
* 在识别过程中可能会多次回调此函数,你最好不要在此回调函数中进行界面的更改等操作,只需要将回调的结果保存起来。<br>
* 使用results的示例如下:
* <pre><code>
* - (void) onResults:(NSArray *) results{
* NSMutableString *result = [[NSMutableString alloc] init];
* NSDictionary *dic = [results objectAtIndex:0];
* for (NSString *key in dic){
* [result appendFormat:@"%@",key];//合并结果
* }
* }
* </code></pre>
*
* @param results -[out] 识别结果,NSArray的第一个元素为NSDictionaryNSDictionary的key为识别结果,sc为识别结果的置信度。
* @param isLast -[out] 是否最后一个结果
*/
- (void) onResults:(NSArray *) results isLast:(BOOL)isLast;
@optional
/*!
* 音量变化回调<br>
* 在录音过程中,回调音频的音量。
*
* @param volume -[out] 音量,范围从0-30
*/
- (void) onVolumeChanged: (int)volume;
/*!
* 开始录音回调<br>
* 当调用了`startListening`函数之后,如果没有发生错误则会回调此函数。<br>
* 如果发生错误则回调onCompleted:函数
*/
- (void) onBeginOfSpeech;
/*!
* 停止录音回调<br>
* 当调用了`stopListening`函数或者引擎内部自动检测到断点,如果没有发生错误则回调此函数。<br>
* 如果发生错误则回调onCompleted:函数
*/
- (void) onEndOfSpeech;
/*!
* 取消识别回调<br>
* 当调用了`cancel`函数之后,会回调此函数,在调用了cancel函数和回调onCompleted之前会有一个<br>
* 短暂时间,您可以在此函数中实现对这段时间的界面显示。
*/
- (void) onCancel;
#ifdef _EDUCATION_
/*!
* 返回音频Key
*
* @param key 音频Key
*/
- (void) getAudioKey:(NSString *)key;
#endif
/*!
* 扩展事件回调<br>
* 根据事件类型返回额外的数据
*
* @param eventType 事件类型,具体参见IFlySpeechEventType的IFlySpeechEventTypeVoiceChangeResult枚举。
* @param arg0 arg0
* @param arg1 arg1
* @param eventData 事件数据
*/
- (void) onEvent:(int)eventType arg0:(int)arg0 arg1:(int)arg1 data:(NSData *)eventData;
@end
@@ -0,0 +1,123 @@
//
// IFlySpeechSynthesizer.h
// MSC
//
// Created by 侯效林 on 16-4-22.
// Copyright (c) 2016年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IFlySpeechSynthesizerDelegate.h"
/*!
* 语音合成
*/
@interface IFlySpeechSynthesizer : NSObject
/*!
* 设置识别的委托对象
*/
@property(nonatomic,assign) id<IFlySpeechSynthesizerDelegate> delegate;
/*!
* 返回合成对象的单例
*
* @return 合成对象
*/
+ (instancetype) sharedInstance;
/*!
* 销毁合成对象。
*
* @return 成功返回YES,失败返回NO.
*/
+ (BOOL) destroy;
/*
* | ------------- |-----------------------------------------------------------
* | 参数 | 描述
* | ------------- |-----------------------------------------------------------
* | speed |合成语速,取值范围 0~100
* | ------------- |-----------------------------------------------------------
* | volume |合成的音量,取值范围 0~100
* | ------------- |-----------------------------------------------------------
* | voice_name |默认为”xiaoyan”;可以设置的参数列表可参考个性化发音人列表
* | ------------- |-----------------------------------------------------------
* | sample_rate |采样率:目前支持的采样率设置有 16000 和 8000。
* | ------------- |-----------------------------------------------------------
* | tts_audio_path|音频文件名 设置此参数后,将会自动保存合成的音频文件。
* | |路径为Documents/(指定值)。不设置或者设置为nil,则不保存音频。
* | ------------- |-----------------------------------------------------------
* | params |扩展参数: 对于一些特殊的参数可在此设置。
* | ------------- |-----------------------------------------------------------
*
*/
/*!
* 设置合成参数
*
* | 参数 | 描述 |
* |-----------------|----------------------------------------------------|
* | speed | 合成语速,取值范围 0~100 |
* | volume | 合成的音量,取值范围 0~100 |
* | voice_name | 默认为”xiaoyan”;可以设置的参数列表可参考个性化发音人列表 |
* | sample_rate | 采样率:目前支持的采样率设置有 16000 和 8000。 |
* | tts_audio_path | 音频文件名 设置此参数后,将会自动保存合成的音频文件。<br>路径为Documents/(指定值)。不设置或者设置为nil,则不保存音频。|
* | params | 扩展参数: 对于一些特殊的参数可在此设置。 |
*
* @param value 参数取值
* @param key 合成参数
*
* @return 设置成功返回YES,失败返回NO
*/
-(BOOL) setParameter:(NSString *) value forKey:(NSString*)key;
/*!
* 获取合成参数
*
* @param key 参数key
*
* @return 参数值
*/
-(NSString*) parameterForKey:(NSString *)key;
/*!
* 开始合成(播放)<br>
* 调用此函数进行合成,如果发生错误会回调错误`onCompleted`
*
* @param text 合成的文本,最大的字节数为1k
*/
- (void) startSpeaking:(NSString *)text;
/*!
* 开始合成(不播放)<br>
* 调用此函数进行合成,如果发生错误会回调错误`onCompleted`
*
* @param text 合成的文本,最大的字节数为1k
* @param uri 合成后,保存再本地的音频路径
*/
-(void)synthesize:(NSString *)text toUri:(NSString*)uri;
/*!
* 暂停播放<br>
* 暂停播放之后,合成不会暂停,仍会继续,如果发生错误则会回调错误`onCompleted`
*/
- (void) pauseSpeaking;
/*!
* 恢复播放
*/
- (void) resumeSpeaking;
/*!
* 停止播放并停止合成
*/
- (void) stopSpeaking;
/*!
* 是否正在播放
*/
@property (nonatomic, readonly) BOOL isSpeaking;
@end
@@ -0,0 +1,81 @@
//
// IFlySpeechSynthesizerDelegate.h
// MSC
//
// Created by ypzhao on 13-3-20.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IFlySpeechEvent.h"
@class IFlySpeechError;
/*!
* 语音合成回调
*/
@protocol IFlySpeechSynthesizerDelegate <NSObject>
@required
/*!
* 结束回调<br>
* 当整个合成结束之后会回调此函数
*
* @param error 错误码
*/
- (void) onCompleted:(IFlySpeechError*) error;
@optional
/*!
* 开始合成回调
*/
- (void) onSpeakBegin;
/*!
* 缓冲进度回调
*
* @param progress 缓冲进度,0-100
* @param msg 附件信息,此版本为nil
*/
- (void) onBufferProgress:(int) progress message:(NSString *)msg;
/*!
* 播放进度回调
*
* @param progress 当前播放进度,0-100
* @param beginPos 当前播放文本的起始位置(按照字节计算),对于汉字(2字节)需/2处理
* @param endPos 当前播放文本的结束位置(按照字节计算),对于汉字(2字节)需/2处理
*/
- (void) onSpeakProgress:(int) progress beginPos:(int)beginPos endPos:(int)endPos;
/*!
* 暂停播放回调
*/
- (void) onSpeakPaused;
/*!
* 恢复播放回调<br>
* 注意:此回调方法SDK内部不执行,播放恢复全部在onSpeakBegin中执行
*/
- (void) onSpeakResumed;
/*!
* 正在取消回调<br>
* 注意:此回调方法SDK内部不执行
*/
- (void) onSpeakCancel;
/*!
* 扩展事件回调<br>
* 根据事件类型返回额外的数据
*
* @param eventType 事件类型,具体参见IFlySpeechEventType枚举。目前只支持EVENT_TTS_BUFFER也就是实时返回合成音频。
* @param arg0 arg0
* @param arg1 arg1
* @param eventData 事件数据
*/
- (void) onEvent:(int)eventType arg0:(int)arg0 arg1:(int)arg1 data:(NSData *)eventData;
@end
@@ -0,0 +1,132 @@
//
// IFlySpeechUnderstander.h
// MSC
//
// Created by iflytek on 2014-03-12.
// Copyright (c) 2014年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlySpeechError;
@protocol IFlySpeechRecognizerDelegate;
/*!
* 语义理解接口
*/
@interface IFlySpeechUnderstander : NSObject
/*!
* 是否正在语义理解
*/
@property (readonly) BOOL isUnderstanding;
/*!
* 设置委托对象
*/
@property(nonatomic,retain) id<IFlySpeechRecognizerDelegate> delegate ;
/*!
* 创建语义理解对象的单例
*
* @return 语义理解对象
*/
+(instancetype) sharedInstance;
/*!
* 开始义理解
*
* 同时只能进行一路会话,这次会话没有结束不能进行下一路会话,否则会报错。若有需要多次回话,请在onCompleted回调返回后请求下一路回话。
*
* @return 成功返回YES,失败返回NO
*/
- (BOOL) startListening;
/*!
* 停止录音<br>
* 调用此函数会停止录音,并开始进行语义理解
*/
- (void) stopListening;
/*!
* 取消本次会话
*/
- (void) cancel;
/*
* | ------------- |-----------------------------------------------------------
* | 参数 | 描述
* | ------------- |-----------------------------------------------------------
* | domain |应用的领域: 取值为:iat、search、video、poi、music、asr
* | | iat:普通文本听写;
* | | search:热词搜索;
* | | video:视频音乐搜索;
* | | asr:关键词识别;
* | ------------- |-----------------------------------------------------------
* | vad_bos |前端点检测: 静音超时时间,即用户多长时间不说话则当做超时处理; 单位:ms;
* | | engine指定iat识别默认值为5000
* | | 其他情况默认值为 4000,范围 0-10000。
* | ------------- |-----------------------------------------------------------
* | vad_eos |后断点检测: 后端点静音检测时间,即用户停止说话多长时间内即认为不再输入,
* | | 自动停止录音;单位:ms;
* | | sms 识别默认值为 1800;
* | | 其他默认值为 700,范围 0-10000。
* | ------------- |-----------------------------------------------------------
* | sample_rate |采样率:目前支持的采样率设置有 16000 和 8000。
* | ------------- |-----------------------------------------------------------
* | asr_ptt |标点符号设置: 默认为 1,当设置为 0 时,将返回无标点符号文本。
* | ------------- |-----------------------------------------------------------
* | result_type |返回结果的数据格式: 可设置为json,xmlplain,默认为json。
* | ------------- |-----------------------------------------------------------
* | grammarID |识别的语法id: 只针对 domain 设置为”asr”的应用。
* | ------------- |-----------------------------------------------------------
* | asr_audio_path|音频文件名: 设置此参数后,将会自动保存识别的录音文件。
* | | 路径为Documents/(指定值)。
* | | 不设置或者设置为nil,则不保存音频。
* | ------------- |-----------------------------------------------------------
* | params |扩展参数: 对于一些特殊的参数可在此设置,一般用于设置语义。
* | ------------- |-----------------------------------------------------------
*
*/
/*!
* 设置语义理解引擎的参数
*
* 语义理解的引擎参数(key)取值如下:
*
* | 参数 | 描述 |
* |-----------------|-------------------------------------------------------|
* | domain | 应用的领域: 取值为:iat、search、video、poi、music、asr<br>iat:普通文本听写;<br>search:热词搜索;<br>video:视频音乐搜索;<br>asr:关键词识别;|
* | vad_bos | 前端点检测: 静音超时时间,即用户多长时间不说话则当做超时处理; 单位:ms;<br>engine指定iat识别默认值为5000<br>其他情况默认值为 4000,范围 0-10000。|
* | vad_eos | 后断点检测: 后端点静音检测时间,即用户停止说话多长时间内即认为不再输入,自动停止录音;单位:ms;<br>sms 识别默认值为 1800;<br>其他默认值为 700,范围 0-10000。|
* | sample_rate | 采样率:目前支持的采样率设置有 16000 和 8000。|
* | asr_ptt | 标点符号设置: 默认为 1,当设置为 0 时,将返回无标点符号文本。|
* | result_type | 返回结果的数据格式: 可设置为json,xmlplain,默认为json。|
* | grammarID | 识别的语法id: 只针对 domain 设置为”asr”的应用。|
* | asr_audio_path | 音频文件名: 设置此参数后,将会自动保存识别的录音文件。<br>路径为Documents/(指定值)。<br>不设置或者设置为nil,则不保存音频。|
* | params | 扩展参数: 对于一些特殊的参数可在此设置,一般用于设置语义。|
*
* @param value 参数对应的取值
* @param key 语义理解引擎参数
*
* @return 成功返回YES;失败返回NO
*/
-(BOOL) setParameter:(NSString *) value forKey:(NSString*)key;
/*!
* 写入音频流
*
* @param audioData 音频数据
*
* @return 写入成功返回YES,写入失败返回NO
*/
- (BOOL) writeAudio:(NSData *) audioData;
/*!
* 销毁语义理解对象。
*
* @return 成功返回YES;失败返回NO
*/
- (BOOL) destroy;
@end
@@ -0,0 +1,184 @@
//
// IFlySpeechUtility.h
// MSCDemo
//
// Created by admin on 14-5-7.
// Copyright (c) 2014年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#define iOS_EXCLUSIVE //iOS平台独占API
@class IFlySpeechError;
/*!
* 引擎模式
*/
typedef NS_ENUM(NSUInteger,IFlyEngineMode){
/*!
* 云端使用MSC,本地优先使用语记
*/
IFlyEngineModeAuto = 0,
/*!
* 只使用MSC
*/
IFlyEngineModeMsc,
/*!
* 本地只使用语记(受平台限制,云端无法使用语记)
*/
IFlyEngineModePlus,
};
/*!
* 服务类型
*/
typedef NS_ENUM(NSUInteger,IFlySpeechPlusServiceType){
/*!
* 打开语记主界面
*/
IFlySpeechPlusServiceTypeNone=0,
/*!
* 获取合成资源
*/
IFlySpeechPlusServiceTypeTTS,
/*!
* 获取识别资源(未开放)
*/
IFlySpeechPlusServiceTypeISR,
/*!
* 获取唤醒资源(未开放)
*/
IFlySpeechPlusServiceTypeIVW,
} ;
/*! 语记返回回调
*/
@protocol IFlySpeechplusDelegate <NSObject>
/*!
* 发生错误
*
* @param errorCode 错误码
*/
- (void)onCompleted:(int)errorCode;
/*!
* 服务正常结束
*/
- (void)onCompleted;
@end
/*!
* 用户配置
*/
@interface IFlySpeechUtility : NSObject
/*!
* 创建用户语音配置<br>
* 注册应用请前往语音云开发者网站。<br>
* 网站:http://www.xfyun.cn
*
* @param params 启动参数,必须保证appid参数传入,示例:appid=123456
*
* @return 语音配置对象
*/
+ (IFlySpeechUtility*) createUtility:(NSString *) params;
/*!
* 销毁用户配置对象
*
* @return 成功返回YES,失败返回NO
*/
+(BOOL) destroy;
/*!
* 获取用户配置对象
*
* @return 用户配置对象
*/
+(IFlySpeechUtility *) getUtility;
/*!
* 设置MSC引擎的状态参数
*
* @param value 参数值
* @param key 参数名称
*
* @return 成功返回YES,失败返回NO
*/
-(BOOL) setParameter:(NSString *) value forKey:(NSString*)key;
/*!
* 获取MSC引擎状态参数
*
* @param key 参数名
*
* @return 参数值
*/
- (NSString *)parameterForKey:(NSString *)key;
/*!
* 引擎类型
*/
@property (nonatomic, readonly) IFlyEngineMode engineMode;
/*!
* 语记协议委托
*/
@property (nonatomic, assign) id<IFlySpeechplusDelegate> delegate;
@end
/*!
* 讯飞语记类别
*/
@interface IFlySpeechUtility (SpeechPlus)
/*!
* 检查讯飞语记是否安装
*
* @return 已安装返回YES,否则返回NO
*/
+ (BOOL)checkServiceInstalled;
/*!
* 获取讯飞语记下载地址进行下载,安装完成后即可使用服务。<br>
* 下载地址需要通过[[UIApplication sharedApplication] openUrl:]打开
*
* @return 讯飞语记在App Store下载地址
*/
+ (NSString *)componentUrl;
/*!
* 注意:此接口废弃,不再需要使用<br>
* 处理语记使用URL启动第三方应用程序时传递的数据<br>
* 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。
*
* @param url 语记启动第三方应用程序时传递过来的URL
*
* @return 成功返回YES,失败返回NO。
*/
- (BOOL)handleOpenURL:(NSURL *)url iOS_EXCLUSIVE;
/*!
* 打开讯飞语记获取相应类型服务,0表示打开主界面
*
* @param serviceType 服务类型
*
* @return 成功打开返回YES,否则返回NO
*/
- (BOOL)openSpeechPlus:(IFlySpeechPlusServiceType)serviceType iOS_EXCLUSIVE;
@end
@@ -0,0 +1,57 @@
//
// TextUnderstand.h
// MSCDemo
//
// Created by iflytek on 4/24/14.
// Copyright (c) 2014 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlySpeechError;
/*!
* 文本转语义完成回调函数
*
* @param result 成功,返回文本语义理解结果
* @param error 错误描述
*/
typedef void(^IFlyUnderstandTextCompletionHandler)(NSString* result, IFlySpeechError * error);
/*!
* 文本转语义类
*/
@interface IFlyTextUnderstander : NSObject
/*!
* 是否正在文本转语义
*/
@property (readonly, atomic) __block BOOL isUnderstanding;
/*!
* 文本转语义接口<br>
* 输入文本内容,获取语义理解结果
*
* @param text 输入的文本内容
* @param completionHandler 文本转语义完成回调函数
*
* @return 错误码
*/
-(int) understandText:(NSString*)text withCompletionHandler:(IFlyUnderstandTextCompletionHandler) completionHandler;
/*!
* 设置文本转语义参数
*
* @param value 参数对应的取值
* @param key 文本转语义参数参数
*
* @return 成功返回YES,失败返回NO
*/
-(BOOL) setParameter:(NSString *) value forKey:(NSString*)key;
/*!
* 取消本次会话
*/
-(void)cancel;
@end
@@ -0,0 +1,74 @@
//
// IFlyUserWords.h
// MSC
//
// Created by ypzhao on 13-2-26.
// Copyright (c) 2013年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
* 用户词表类
* 获取用户词表是为了更好的语音识别(iat),用户词表也属于个性化的一部分.
*/
@interface IFlyUserWords : NSObject
/*!
* 初始化对象
*
* 在进行初始化时,需要传入的格式如下:
* <pre><code>{\"userword\":[{\"name\":\"iflytek\",\"words\":[\"科大讯飞\",
* \"云平台\",\"用户词条\",\"开始上传词条\"]}]}</code></pre>
*
* @param json 初始化时传入的数据
*
* @return IFlyUserWords对象
*/
- (id) initWithJson:(NSString *)json;
/*!
* 将数据转化为上传的数据格式
*
* @return 没有数据或者格式不对时返回nil
*/
- (NSString *) toString;
/*!
* 返回key对应的数据
*
* @param key 在putword:value中设置的key
*
* @return key对应的数组
*/
- (NSArray *) getWords: (NSString *) key;
/*!
* 添加一条用户词数据
*
* @param key 用户词对应的key
* @param value 上传的用户词数据
*
* @return 成功返回YES,失败返回NO
*/
- (BOOL) putWord: (NSString *) key value:(NSString *)value;
/*!
* 添加一组数据
*
* @param key 用户词对应的key
* @param words 上传的用户词数据
*
* @return 成功返回YES,失败返回NO
*/
- (BOOL) putwords: (NSString *) key words:(NSArray *)words;
/*!
* 是否包含key对应的用户词数据
*
* @param key 用户词对应的key
*
* @return 成功返回YES,失败返回NO
*/
- (BOOL) containsKey: (NSString *) key;
@end
@@ -0,0 +1,39 @@
//
// IFlyVerifierUtil.h
// IFlyMSC
//
// Created by 张剑 on 15/4/28.
// Copyright (c) 2015年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/**
* 身份验证工具类
*/
@interface IFlyVerifierUtil : NSObject
#pragma mark - ISV
/**
* 返回定长的随机数字字符串(不包含数字1,而且2和5不邻接)
*
* @param length 随机字符串长度
*
* @return 随机字符串
*/
+(NSString*)generateNumberPassword:(int)length;
#pragma mark - Face
/**
* ARGB彩图转灰度图,Detector和Alignment需要灰度图的输入
*
* @param sourceImage ARGB彩图
*
* @return 灰度图
*/
+ (UIImage*)ARGBToGray:(UIImage*)sourceImage;
@end
@@ -0,0 +1,83 @@
//
// IFlyVoiceWakeuper.h
// wakeup
//
// Created by admin on 14-3-18.
// Copyright (c) 2014年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IFlyVoiceWakeuperDelegate.h"
#define IFLY_AUDIO_SOURCE_MIC @"1"
#define IFLY_AUDIO_SOURCE_STREAM @"-1"
/*!
* 语音唤醒
*/
@interface IFlyVoiceWakeuper : NSObject
/*!
* 代理
*/
@property (nonatomic, assign) id<IFlyVoiceWakeuperDelegate> delegate;
/*!
* 是否正在唤醒
*/
@property (nonatomic, readonly) BOOL isListening;
/*!
* 创建唤醒实例,采用单例模式
*/
+ (instancetype) sharedInstance;
/*!
* 启动唤醒
* 返回值:YES 成功,NO:失败
*/
-(BOOL) startListening;
/*!
* 停止录音
*/
-(BOOL) stopListening;
/*!
* 取消唤醒会话
*/
-(BOOL) cancel;
/*!
* 获取工作参数
*/
-(NSString*) getParameter:(NSString *)key;
/*!
* 设置工作参数<br>
* 注意服务正在运行中,不能设置参数
*/
-(BOOL) setParameter:(NSString *) value forKey:(NSString*)key;
@end
/*!
* 音频流唤醒<br>
* 音频流唤醒可以将文件分段写入
*/
@interface IFlyVoiceWakeuper(IFlyStreamVoiceWakeuper)
/*!
* 写入音频流
*
* @param audioData 音频数据
*
* @return 写入成功返回YES,写入失败返回NO
*/
- (BOOL) writeAudio:(NSData *) audioData;
@end
@@ -0,0 +1,60 @@
//
// IFlyVoiceWakeuperDel.h
// wakeup
//
// Created by admin on 14-3-18.
// Copyright (c) 2014年 iflytek. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IFlySpeechError;
@protocol IFlyVoiceWakeuperDelegate <NSObject>
@optional
/*!
* 录音开始
*/
-(void) onBeginOfSpeech;
/*!
* 录音结束
*/
-(void) onEndOfSpeech;
/*!
* 会话错误
*
* @param errorCode 错误描述类,
*/
- (void) onCompleted:(IFlySpeechError *) error;
/*!
* 唤醒结果
*
* @param resultDic 唤醒结果字典
*/
-(void) onResult:(NSMutableDictionary *)resultDic;
/*!
* 音量反馈,返回频率与录音数据返回回调频率一致
*
* @param volume 音量值
*/
- (void) onVolumeChanged: (int)volume;
/*!
* 扩展事件回调<br>
* 根据事件类型返回额外的数据
*
@param eventType 事件类型,具体参见IFlySpeechEvent枚举。
*/
- (void) onEvent:(int)eventType isLast:(BOOL)isLast arg1:(int)arg1 data:(NSMutableDictionary *)eventData;
@end
@@ -0,0 +1,16 @@
//
// CALayer+OCBarrage.h
// OCBarrage
//
// Created by QMTV on 2017/8/29.
// Copyright © 2017年 LFC. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
@interface CALayer (OCBarrage)
- (UIImage *)convertContentToImageWithSize:(CGSize)contentSize;
@end
@@ -0,0 +1,24 @@
//
// CALayer+OCBarrage.m
// OCBarrage
//
// Created by QMTV on 2017/8/29.
// Copyright © 2017年 LFC. All rights reserved.
//
#import "CALayer+OCBarrage.h"
@implementation CALayer (OCBarrage)
- (UIImage *)convertContentToImageWithSize:(CGSize)contentSize {
UIGraphicsBeginImageContextWithOptions(contentSize, 0.0, [UIScreen mainScreen].scale);
//self为需要截屏的UI控件 即通过改变此参数可以截取特定的UI控件
[self renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
@end
@@ -0,0 +1,20 @@
//
// OCBarrage.h
// OCBarrage
//
// Created by QMTV on 2017/8/25.
// Copyright © 2017年 LFC. All rights reserved.
//
#ifndef OCBarrage_h
#define OCBarrage_h
#import "OCBarrageHeader.h"
#import "OCBarrageManager.h"
#import "OCBarrageRenderView.h"
#import "OCBarrageDescriptor.h"
#import "OCBarrageCell.h"
#import "OCBarrageTextDescriptor.h"
#import "OCBarrageTextCell.h"
#endif /* OCBarrage_h */
@@ -0,0 +1,43 @@
//
// OCBarrageCell.h
// TestApp
//
// Created by QMTV on 2017/8/21.
// Copyright © 2017年 LFC. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "CALayer+OCBarrage.h"
#import "OCBarrageDescriptor.h"
NS_ASSUME_NONNULL_BEGIN
@protocol OCBarrageCellDelegate;
@interface OCBarrageCell : UIView
@property (nonatomic, assign, getter=isIdle) BOOL idle;//是否是空闲状态
@property (nonatomic, assign) NSTimeInterval idleTime;//开始闲置的时间, 闲置超过5秒的, 自动回收内存
@property (nonatomic, strong, nullable) OCBarrageDescriptor *barrageDescriptor;
@property (nonatomic, strong, readonly, nullable) CAAnimation *barrageAnimation;
@property (nonatomic, assign) int trackIndex;
- (void)addBarrageAnimationWithDelegate:(id<CAAnimationDelegate>)animationDelegate;
- (void)prepareForReuse;
- (void)clearContents;
- (void)updateSubviewsData;
- (void)layoutContentSubviews;
- (void)convertContentToImage;
- (void)sizeToFit;//设置好数据之后调用一下自动计算bounds
- (void)removeSubViewsAndSublayers;//默认删除所有的subview和sublayer; 如果需要选择性的删除可以重写这个方法.
- (void)addBorderAttributes;
@end
@protocol OCBarrageCellDelegate <NSObject, CAAnimationDelegate>
@optional
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,113 @@
//
// OCBarrageCell.m
// TestApp
//
// Created by QMTV on 2017/8/21.
// Copyright © 2017年 LFC. All rights reserved.
//
#import "OCBarrageCell.h"
@implementation OCBarrageCell
- (instancetype)init {
self = [super init];
if (self) {
_trackIndex = -1;
}
return self;
}
- (void)prepareForReuse {
[self.layer removeAnimationForKey:kBarrageAnimation];
_barrageDescriptor = nil;
if (!_idle) {
_idle = YES;
}
_trackIndex = -1;
}
- (void)setBarrageDescriptor:(OCBarrageDescriptor *)barrageDescriptor {
_barrageDescriptor = barrageDescriptor;
}
- (void)clearContents {
self.layer.contents = nil;
}
- (void)convertContentToImage {
}
- (void)sizeToFit {
CGFloat height = 0.0;
CGFloat width = 0.0;
for (CALayer *sublayer in self.layer.sublayers) {
CGFloat maxY = CGRectGetMaxY(sublayer.frame);
if (maxY > height) {
height = maxY;
}
CGFloat maxX = CGRectGetMaxX(sublayer.frame);
if (maxX > width) {
width = maxX;
}
}
if (width == 0 || height == 0) {
CGImageRef content = (__bridge CGImageRef)self.layer.contents;
if (content) {
UIImage *image = [UIImage imageWithCGImage:content];
width = image.size.width/[UIScreen mainScreen].scale;
height = image.size.height/[UIScreen mainScreen].scale;
}
}
self.bounds = CGRectMake(0.0, 0.0, width, height);
}
- (void)removeSubViewsAndSublayers {
NSEnumerator *viewEnumerator = [self.subviews reverseObjectEnumerator];
UIView *subView = nil;
while (subView = [viewEnumerator nextObject]){
[subView removeFromSuperview];
}
NSEnumerator *layerEnumerator = [self.layer.sublayers reverseObjectEnumerator];
CALayer *sublayer = nil;
while (sublayer = [layerEnumerator nextObject]){
[sublayer removeFromSuperlayer];
}
}
- (void)addBorderAttributes {
if (self.barrageDescriptor.borderColor) {
self.layer.borderColor = self.barrageDescriptor.borderColor.CGColor;
}
if (self.barrageDescriptor.borderWidth > 0) {
self.layer.borderWidth = self.barrageDescriptor.borderWidth;
}
if (self.barrageDescriptor.cornerRadius > 0) {
self.layer.cornerRadius = self.barrageDescriptor.cornerRadius;
}
}
- (void)addBarrageAnimationWithDelegate:(id<CAAnimationDelegate>)animationDelegate {
}
- (void)updateSubviewsData {
}
- (void)layoutContentSubviews {
}
- (CAAnimation *)barrageAnimation {
return [self.layer animationForKey:kBarrageAnimation];
}
@end
@@ -0,0 +1,34 @@
//
// OCBarrageDescriptor.h
// TestApp
//
// Created by QMTV on 2017/8/23.
// Copyright © 2017年 LFC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "OCBarrageHeader.h"
@class OCBarrageCell;
NS_ASSUME_NONNULL_BEGIN
@interface OCBarrageDescriptor : NSObject
@property (nonatomic, assign, nullable) Class barrageCellClass;
@property (nonatomic, assign) OCBarragePositionPriority positionPriority;//显示位置normal型的渲染在low型的上面, height型的渲染在normal上面
@property (nonatomic, assign) CGFloat animationDuration;//动画时间, 时间越长速度越慢, 时间越短速度越快
@property (nonatomic, assign) CGFloat fixedSpeed;//固定速度, 可以防止弹幕在有空闲轨道的情况下重叠, 取值0.0~100.0, animationDuration与fixedSpeed只能选择一个, fixedSpeed设置之后可以不用设置animationDuration
//@property (nonatomic, copy, nullable) OCBarrageTouchAction touchAction DEPRECATED_MSG_ATTRIBUTE("use OCBarrageCellTouchedAction instead");
@property (nonatomic, copy, nullable) OCBarrageTouchAction touchAction;
@property (nonatomic, copy, nullable) OCBarrageCellTouchedAction cellTouchedAction;//新属性里回传了被点击的cell, 可以在代码块里更改被点击的cell的属性, 比如之前有用户需要在弹幕被点击的时候修改被点击的弹幕的文字颜色等等. 用来替代旧版本的touchAction
@property (nonatomic, strong, nullable) UIColor *borderColor; // Default is no border
@property (nonatomic, assign) CGFloat borderWidth; // Default is 0
@property (nonatomic, assign) CGFloat cornerRadius; // Default is 8
@property (nonatomic, assign) NSRange renderRange;//渲染范围, 最终渲染出来的弹幕的Y坐标最小不小于renderRange.location, 最大不超过renderRange.length-barrageCell.height
@end
NS_ASSUME_NONNULL_END

Some files were not shown because too many files have changed in this diff Show More