|
@@ -0,0 +1,449 @@
|
|
|
|
+//
|
|
|
|
+// NYVoiceManager.m
|
|
|
|
+// jiaPei
|
|
|
|
+//
|
|
|
|
+// Created by Ning.ge on 2023/7/26.
|
|
|
|
+// Copyright © 2023 JCZ. All rights reserved.
|
|
|
|
+//
|
|
|
|
+
|
|
|
|
+#import "NYVoiceManager.h"
|
|
|
|
+#import "payRequsestHandler.h"
|
|
|
|
+
|
|
|
|
+static NYVoiceManager *vomanger = nil;
|
|
|
|
+static dispatch_once_t onceToken;
|
|
|
|
+
|
|
|
|
+@interface NYVoiceManager ()<QCloudTTSEngineDelegate,QCloudPlayerDelegate>
|
|
|
|
+{
|
|
|
|
+ NSMutableArray* _textArr;
|
|
|
|
+}
|
|
|
|
+//SDK 内置播放器
|
|
|
|
+@property(strong) QCloudMediaPlayer *player;
|
|
|
|
+// demo 层播放器,如SDK播放器不能满足需求 可以自定义播放器 如下只是一个例子
|
|
|
|
+//@property(strong) MediaPlayerDemo *player;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+@property (nonatomic,assign)float onlineSpeed;
|
|
|
|
+@property (nonatomic,assign)int onlineVoiceType;
|
|
|
|
+@property (nonatomic,assign)int onlineLanguage;
|
|
|
|
+@property (nonatomic,assign)float onlineVolume;
|
|
|
|
+
|
|
|
|
+@property (nonatomic,assign)float offlineSpeed;
|
|
|
|
+@property (nonatomic,copy)NSString *offlineVoiceType;
|
|
|
|
+@property (nonatomic,assign)int offlineLanguage;
|
|
|
|
+@property (nonatomic,assign)float offlineVolume;
|
|
|
|
+
|
|
|
|
+@property (nonatomic,assign)int responseTimeout;
|
|
|
|
+@property (nonatomic,assign)int requestTimeout;
|
|
|
|
+@property (nonatomic,assign)int checkTimeout;
|
|
|
|
+
|
|
|
|
+@property (nonatomic, copy) NSString* resource_dir;
|
|
|
|
+
|
|
|
|
+@property (nonatomic,assign)int cout; //统计合成句子数,当作utteranceId用于标记句子用
|
|
|
|
+
|
|
|
|
+@end
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+@implementation NYVoiceManager
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#pragma mark - SystemMethod
|
|
|
|
++ (NYVoiceManager *)sharedManager {
|
|
|
|
+ dispatch_once(&onceToken, ^{
|
|
|
|
+ vomanger = [[self alloc] init];
|
|
|
|
+ });
|
|
|
|
+ return vomanger;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (instancetype)init {
|
|
|
|
+ self = [super init];
|
|
|
|
+ if (self) {
|
|
|
|
+ [self initBaseData];
|
|
|
|
+ }
|
|
|
|
+ return self;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void)dealloc {
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#pragma mark - PublicMethods
|
|
|
|
+// 配置
|
|
|
|
+- (void)ny_configureTTSVoiceDK {
|
|
|
|
+ QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
|
|
|
|
+ [tts cancel];
|
|
|
|
+ [_player StopPlay];
|
|
|
|
+ [self setOnlineParam:tts];//在线
|
|
|
|
+}
|
|
|
|
+-(void)setOnlineParam:(QCloudTTSEngine*)ttsEngine {
|
|
|
|
+
|
|
|
|
+ //设置合成声音速度
|
|
|
|
+ [ttsEngine setOnlineVoiceSpeed:_onlineSpeed];
|
|
|
|
+ //设置合成声音类型
|
|
|
|
+ [ttsEngine setOnlineVoiceType:_onlineVoiceType];
|
|
|
|
+ //设置合成语种
|
|
|
|
+ [ttsEngine setOnlineVoiceLanguage:_onlineLanguage];
|
|
|
|
+ //设置合成声音大小默认值为0
|
|
|
|
+ [ttsEngine setOnlineVoiceVolume:_onlineVolume];
|
|
|
|
+ //设置响应超时时间
|
|
|
|
+ [ttsEngine setTimeoutIntervalForResource:_responseTimeout];
|
|
|
|
+ //设置请求超时时间
|
|
|
|
+ [ttsEngine setTimeoutIntervalForRequest:_requestTimeout];
|
|
|
|
+ //设置检测网络间隔时间
|
|
|
|
+ [ttsEngine setCheckNetworkIntervalTime:_checkTimeout];
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void)setOfflineParam:(QCloudTTSEngine*)ttsEngine{
|
|
|
|
+
|
|
|
|
+ [ttsEngine setOfflineVoiceType:_offlineVoiceType];
|
|
|
|
+ [ttsEngine setOfflineVoiceSpeed:_offlineSpeed];
|
|
|
|
+ [ttsEngine setOfflineVoiceVolume:_offlineVolume];
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//开播合成播放
|
|
|
|
+- (void)startPayVoiceActionText:(NSString *)text{
|
|
|
|
+ QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
|
|
|
|
+ [self setOnlineParam:tts];
|
|
|
|
+ //设置ProjectId 不设置默认使用0,说明:项目功能用于按项目管理云资源,可以对云资源进行分项目管理,详情见 https://console.cloud.tencent.com/project
|
|
|
|
+ //[tts setOnlineProjectId:0];
|
|
|
|
+ [self stopTTSBtnAction:nil];
|
|
|
|
+
|
|
|
|
+ _textArr = [self breakIntoSentencesFromString:text];
|
|
|
|
+ for (int i = 0; i < 10 - [_player getAudioQueueSize]; i++) {
|
|
|
|
+ if (_textArr.count > 0) {
|
|
|
|
+ [tts synthesize:_textArr[0] UtteranceId:[NSString stringWithFormat:@"%d",_cout++]];
|
|
|
|
+ [_textArr removeObjectAtIndex:0];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//暂停合成播放
|
|
|
|
+- (void)pausePayVoiceAction {
|
|
|
|
+ [self resumeTTSBtnAction:nil];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//停止合成播放
|
|
|
|
+- (void)stopPayVoiceAction {
|
|
|
|
+ [self stopTTSBtnAction:nil];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (IBAction)stopTTSBtnAction:(id)sender {
|
|
|
|
+
|
|
|
|
+ [_player StopPlay];
|
|
|
|
+ [_textArr removeAllObjects];
|
|
|
|
+ QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
|
|
|
|
+ [tts cancel];
|
|
|
|
+}
|
|
|
|
+- (IBAction)pauseTTSBtnAction:(id)sender {
|
|
|
|
+
|
|
|
|
+ [_player PausePlay];
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+- (IBAction)resumeTTSBtnAction:(id)sender {
|
|
|
|
+
|
|
|
|
+ [_player ResumePlay];
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+#pragma mark - PrivateMethods
|
|
|
|
+
|
|
|
|
+- (void)initBaseData {
|
|
|
|
+ _cout = 0;
|
|
|
|
+ _textArr = [NSMutableArray array];
|
|
|
|
+ QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
|
|
|
|
+ //如果使用STS临时证书鉴权时需要设置Token
|
|
|
|
+ [tts setOnlineAuthParam:QDApp_Id SecretId:QDSecret_ID SecretKey:QDSecret_Key Token:nil];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ [tts engineInit:0 Delegate:self];
|
|
|
|
+ [tts setEnableDebugLog:YES];
|
|
|
|
+
|
|
|
|
+ //SDK 内置播放器
|
|
|
|
+ _player = [[QCloudMediaPlayer alloc]init];
|
|
|
|
+
|
|
|
|
+ // demo 层播放器,如SDK播放器不能满足需求 可以自定义播放器 如下只是一个例子 源码在MediaPlayerDemo.m文件 可自行修改
|
|
|
|
+ //_player = [[MediaPlayerDemo alloc]init];
|
|
|
|
+
|
|
|
|
+ _player.playerDelegate = self;
|
|
|
|
+ //离线参数
|
|
|
|
+
|
|
|
|
+ //在线参数
|
|
|
|
+ _onlineSpeed = 0;
|
|
|
|
+ _onlineVoiceType = 1001;
|
|
|
|
+ //主语言类型:1-中文(默认)2-英文
|
|
|
|
+ _onlineLanguage = 1;
|
|
|
|
+ _onlineVolume = 0;
|
|
|
|
+
|
|
|
|
+ //连接超时默认15000ms(15s) 范围[500,30000] 单位ms , Mix模式下建议调小此值,以获得更好的体验
|
|
|
|
+ _responseTimeout = 15*1000;
|
|
|
|
+ //读取超时超时默认30000ms(30s) 范围[2200,60000] 单位ms, Mix模式下建议调小此值,以获得更好的体验
|
|
|
|
+ _requestTimeout = 30 * 1000;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //离线参数,如果您下载的是在线版SDK,以下参数不需要设置,请忽略
|
|
|
|
+ _offlineSpeed = 1.0;//离线语速[0.5,2.0]
|
|
|
|
+ //voiceType 离线音色名称,名称配置位于音色资源目录tts_resource\voices\config.json 中,可自行增删音色
|
|
|
|
+ _offlineVoiceType = @"pb";
|
|
|
|
+ _offlineVolume = 1.0;//离线音量 > 0
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /*_checkTimeout 大于等于0 单位s, 等于0时持续检测,直到成功
|
|
|
|
+ Mix模式下,已经连接网络,但出现网络错误后的检测间隔时间,用于从离线模式自动切换回在线模式,默认值5分钟
|
|
|
|
+ 注意:每次检测时将使用所入参的一句文本请求服务器,如果后端合成成功将会额外消耗该句字数的合成额度
|
|
|
|
+ */
|
|
|
|
+ _checkTimeout = 300;
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#pragma mark -- QCloudTTSEngineDelegate
|
|
|
|
+//合成结果返回
|
|
|
|
+//---------QCloudTTSEngineDelegate---------
|
|
|
|
+/// 合成回调
|
|
|
|
+/// @param data 语音数据
|
|
|
|
+/// @param utteranceId 语句id
|
|
|
|
+/// @param text 文本
|
|
|
|
+/// @param type 引擎类型 0:在线 1:离线
|
|
|
|
+///
|
|
|
|
+-(void) onSynthesizeData:(NSData *_Nullable)data UtteranceId:(NSString *_Nullable)utteranceId Text:(NSString *_Nullable)text EngineType:(NSInteger)type RequestId:(NSString*)requestId{
|
|
|
|
+
|
|
|
|
+ NSLog(@"text====%@,utteranceId ==%@,type==%ld,requestId=%@",text,utteranceId,(long)type,requestId);
|
|
|
|
+ [_player enqueueWithData:data Text:text UtteranceId:utteranceId];
|
|
|
|
+
|
|
|
|
+// //通过保存音频的URL播放
|
|
|
|
+// //NSString *str = [self filePathWithName:@"tmp.mp3"];
|
|
|
|
+// //NSURL * url = [NSURL URLWithString:str];
|
|
|
|
+// //[_player enqueueWithFile:url Text:text UtteranceId:utteranceId];
|
|
|
|
+//
|
|
|
|
+//
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n text=%@\n utteranceId=%@ requestId=%@",_messageTextView.text,text,utteranceId,requestId];
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+//
|
|
|
|
+// NSLog(@"onSynthesizeData %@",@(data.length));
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// 错误回调
|
|
|
|
+/// @param error 错误信息
|
|
|
|
+/// @param utteranceId utteranceId
|
|
|
|
+/// @param text text
|
|
|
|
+-(void) onError:(TtsError *_Nullable)error UtteranceId:(NSString *_Nullable)utteranceId Text:(NSString *_Nullable)text{
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// if (error.serviceError != nil && _ttsMode == TTS_MODE_MIX) {
|
|
|
|
+// //实际业务上判断一下,如果是混合模式下返回在线合成的后端错误码,应当忽略可不做处理
|
|
|
|
+// //SDK内会继续调用离线合成继续工作,如果没有日志需求,这里直接return忽略即可
|
|
|
|
+// //return;
|
|
|
|
+// }else{
|
|
|
|
+// QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
|
|
|
|
+// [tts cancel];
|
|
|
|
+// }
|
|
|
|
+//
|
|
|
|
+// NSString* msg = [NSString stringWithFormat:@"%@\n error=%@\n error.code=%@\n error.message=%@\n response = %@\n utteranceId=%@",_messageTextView.text,error.error,@(error.err_code),error.msg,error.serviceError.respose, utteranceId];
|
|
|
|
+// _messageTextView.text = msg;
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+// NSLog(@"onError %@",msg);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+//离线或者混合模式下,调用初始化后必须收到此回调,并且OfflineAuthInfo.err_code为0时,才可以调用合成接口,如果err_code不为0,请检查参数或者网络,重新init
|
|
|
|
+- (void)onOfflineAuthInfo:(QCloudOfflineAuthInfo * _Nonnull)OfflineAuthInfo {
|
|
|
|
+
|
|
|
|
+// NSString *msg = [NSString stringWithFormat:@"OfflineAuthInfo:err_code=%@,err_msg=%@\n,deviceId=%@\n,expireTime=%@\n,respose=%@\n,authVoiceList=%@",@(OfflineAuthInfo.err_code),OfflineAuthInfo.err_msg,OfflineAuthInfo.deviceId,OfflineAuthInfo.expireTime,OfflineAuthInfo.respose,OfflineAuthInfo.voiceAuthList];
|
|
|
|
+//
|
|
|
|
+// NSLog(@"%@",msg);
|
|
|
|
+// _messageTextView.text = msg;
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+//---------QCloudPlayerDelegate---------
|
|
|
|
+//播放开始
|
|
|
|
+-(void) onTTSPlayStart{
|
|
|
|
+
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayStart",_messageTextView.text];
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+ NSLog(@"onTTSPlayStart");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//队列所有音频播放完成,音频等待中
|
|
|
|
+-(void) onTTSPlayWait{
|
|
|
|
+
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayWait",_messageTextView.text];
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+ NSLog(@"onTTSPlayWait");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//恢复播放
|
|
|
|
+-(void) onTTSPlayResume{
|
|
|
|
+
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayResume",_messageTextView.text];
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+ NSLog(@"onTTSPlayResume");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//暂停播放
|
|
|
|
+-(void) onTTSPlayPause{
|
|
|
|
+
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayPause",_messageTextView.text];
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+ NSLog(@"onTTSPlayPause");
|
|
|
|
+}
|
|
|
|
+//播放中止
|
|
|
|
+-(void)onTTSPlayStop{
|
|
|
|
+
|
|
|
|
+ _cout = 0;
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n onTTSPlayStop",_messageTextView.text];
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+ NSLog(@"onTTSPlayStop");
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+//播放器异常
|
|
|
|
+-(void)onTTSPlayError:(QCPlayerError* _Nullable)playError{
|
|
|
|
+
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n playError.code==%@\n playError.massage==%@",_messageTextView.text,@(playError.mCode),playError.message];
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+ NSLog(@"playError.code==%@,playError.massage==%@",@(playError.mCode),playError.message);
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+//即将播放播放下一句,即将播放音频对应的句子,以及这句话utteranceId
|
|
|
|
+/// 即将播放播放下一句,即将播放音频对应的句子,以及这句话utteranceId
|
|
|
|
+/// @param text 当前播放句子的文本
|
|
|
|
+/// @param utteranceId 当前播放音频对应的ID
|
|
|
|
+-(void) onTTSPlayNextWithText:(NSString* _Nullable)text UtteranceId:(NSString* _Nullable)utteranceId{
|
|
|
|
+
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n text==%@\n utteranceId==%@",_messageTextView.text,text,utteranceId];
|
|
|
|
+// NSLog(@"text==%@,utteranceId==%@",text,utteranceId);
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+// QCloudTTSEngine *tts = [QCloudTTSEngine getShareInstance];
|
|
|
|
+// if ([_player getAudioQueueSize] < 10) {
|
|
|
|
+//
|
|
|
|
+// if (_textArr.count > 0) {
|
|
|
|
+//
|
|
|
|
+// NSLog(@"AudioQueueSize=%@",@([_player getAudioQueueSize]));
|
|
|
|
+// [tts synthesize:_textArr[0] UtteranceId:[NSString stringWithFormat:@"%d",_cout++]];
|
|
|
|
+// [_textArr removeObjectAtIndex:0];
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+}
|
|
|
|
+/// 当前播放的字符,当前播放的字符在所在的句子中的下标.
|
|
|
|
+/// @param currentWord 当前读到的单个字,是一个估算值不一定准确
|
|
|
|
+/// @param currentIdex 当前播放句子中读到文字的下标
|
|
|
|
+-(void)onTTSPlayProgressWithCurrentWord:(NSString*_Nullable)currentWord CurrentIndex:(NSInteger)currentIdex{
|
|
|
|
+
|
|
|
|
+// _messageTextView.text = [NSString stringWithFormat:@"%@\n CurrentWord==%@\n currentIdex==%@",_messageTextView.text,currentWord,@(currentIdex)];
|
|
|
|
+// NSLog(@"CurrentWord==%@,currentIdex==%@",currentWord,@(currentIdex));
|
|
|
|
+// [self scrollToBottom];
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*===============================使用自定义分割逻辑,以下为句子分割示例=====================*/
|
|
|
|
+#define Sentence_Count_Max 50 //单次最大请求字数,建议首句不要设置太长
|
|
|
|
+/*
|
|
|
|
+ API最大请求字数详见官网文档https://cloud.tencent.com/document/product/1073/37995
|
|
|
|
+
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+- (NSMutableArray *)breakIntoSentencesFromString:(NSString *)string
|
|
|
|
+{
|
|
|
|
+ NSMutableArray *stringsArr = [NSMutableArray array];
|
|
|
|
+
|
|
|
|
+ NSString *splitString = @",;,;";
|
|
|
|
+ //先按句子分割
|
|
|
|
+ [string enumerateSubstringsInRange:NSMakeRange(0, string.length) options:NSStringEnumerationBySentences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
|
|
|
|
+ //后台接收字符不能太长
|
|
|
|
+ const char *commitChar = [substring UTF8String];
|
|
|
|
+ if (strlen(commitChar) > Sentence_Count_Max * 3) { //UTF-8中文的字符长度一般是3个字节,英文的长度为1
|
|
|
|
+ //再按分号逗号分割
|
|
|
|
+ NSArray *textArr = [self separatedString:substring split:splitString];
|
|
|
|
+ for (NSString *object in textArr) {
|
|
|
|
+ //再按字数分割
|
|
|
|
+ const char *objectChar = [object UTF8String];
|
|
|
|
+ if (strlen(objectChar) > Sentence_Count_Max * 3) {
|
|
|
|
+ NSString *remainStr = object;
|
|
|
|
+ while (remainStr.length > Sentence_Count_Max) {
|
|
|
|
+ NSString *sentence = [remainStr substringToIndex:Sentence_Count_Max];
|
|
|
|
+ if (![self isAllSplitString:sentence split:splitString]
|
|
|
|
+ &&![self isPunct:sentence]) {
|
|
|
|
+ [stringsArr addObject:sentence];
|
|
|
|
+ }
|
|
|
|
+ remainStr = [remainStr substringFromIndex:Sentence_Count_Max];
|
|
|
|
+ }
|
|
|
|
+ if (![self isAllSplitString:remainStr split:splitString]
|
|
|
|
+ &&![self isPunct:remainStr]) {
|
|
|
|
+ [stringsArr addObject:remainStr];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ if (![self isAllSplitString:object split:splitString]
|
|
|
|
+ &&![self isPunct:object]) {
|
|
|
|
+ [stringsArr addObject:object];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }else{
|
|
|
|
+ if (![self isAllSplitString:substring split:splitString]
|
|
|
|
+ &&![self isPunct:substring]) {
|
|
|
|
+ [stringsArr addObject:substring];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }];
|
|
|
|
+
|
|
|
|
+ return stringsArr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+- (NSArray *)separatedString:(NSString *)text split:(NSString *)split {
|
|
|
|
+ NSMutableArray *mArray = [NSMutableArray array];
|
|
|
|
+ NSInteger loc = 0;
|
|
|
|
+ for (NSInteger i = 0; i < [text length]; i++) {
|
|
|
|
+ if ([split rangeOfString:[text substringWithRange:NSMakeRange(i, 1)]].location != NSNotFound) {
|
|
|
|
+ NSString *subString = [text substringWithRange:NSMakeRange(loc, i-loc+1)];
|
|
|
|
+ [mArray addObject:subString];
|
|
|
|
+ loc = i + 1;
|
|
|
|
+ }
|
|
|
|
+ if (i + 1 == [text length] && [split rangeOfString:[text substringWithRange:NSMakeRange(i, 1)]].location == NSNotFound) { //判断最后一个字符是否包含分隔符,如果不包含把最后一句添加到数组
|
|
|
|
+ NSString *subString = [text substringWithRange:NSMakeRange(loc, i-loc+1)];
|
|
|
|
+ [mArray addObject:subString];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return [mArray copy];
|
|
|
|
+}
|
|
|
|
+- (BOOL)isAllSplitString:(NSString *)text split:(NSString *)split
|
|
|
|
+{
|
|
|
|
+ split = @",;,;。";
|
|
|
|
+ if ([text length] && [split length]) {
|
|
|
|
+ BOOL all = YES;
|
|
|
|
+ for (NSInteger i = 0; i < [text length]; i++) {
|
|
|
|
+ if ([split rangeOfString:[text substringWithRange:NSMakeRange(i, 1)]].location == NSNotFound) {
|
|
|
|
+ all = NO;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return all;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ return NO;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+-(BOOL)isPunct:(NSString *)string //校验是否全为符号
|
|
|
|
+{
|
|
|
|
+ NSError *error = nil;
|
|
|
|
+ NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[\\p{P}~^<>]" options:NSRegularExpressionCaseInsensitive error:&error];
|
|
|
|
+
|
|
|
|
+ NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:@""];
|
|
|
|
+
|
|
|
|
+ NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
|
|
|
+ NSString *trimmedStr = [modifiedString stringByTrimmingCharactersInSet:set];
|
|
|
|
+ if (!trimmedStr.length) {
|
|
|
|
+ return YES;
|
|
|
|
+ }
|
|
|
|
+ return NO;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+@end
|