MusicDataManager.m 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. //
  2. // MusicDataManager.m
  3. // BuguLive
  4. //
  5. // Created by 岳克奎 on 16/12/16.
  6. // Copyright © 2016年 xfg. All rights reserved.
  7. //
  8. #import "MusicDataManager.h"
  9. @implementation MusicDataManager
  10. #pragma mark -life cycle ------------------------------ 生 命 周 期 管 控 区 域 ------------------------------------------
  11. /**
  12. * @brief: 单利
  13. *
  14. * @discussion:我的想法是,用单利管理,以后把DataModel里面的操作都移除出来、、关于music的数据层单独成模块。放在msuic大分类里。这样看着就合理
  15. */
  16. static MusicDataManager *signleton = nil;
  17. + (instancetype)allocWithZone:(struct _NSZone *)zone
  18. {
  19. static dispatch_once_t onceToken;
  20. dispatch_once(&onceToken, ^{
  21. signleton = [super allocWithZone:zone];
  22. });
  23. return signleton;
  24. }
  25. + (MusicDataManager *)shareManager
  26. {
  27. static dispatch_once_t onceToken;
  28. dispatch_once(&onceToken, ^{
  29. signleton = [[self alloc] init];
  30. });
  31. return signleton;
  32. }
  33. + (id)copyWithZone:(struct _NSZone *)zone
  34. {
  35. return signleton;
  36. }
  37. + (id)mutableCopyWithZone:(struct _NSZone *)zone
  38. {
  39. return signleton;
  40. }
  41. #pragma mark ----------------------------------------------- 音 乐 部 分 --------------------------------------------
  42. #pragma mark - 音乐 歌词 处理(Data)(Public)
  43. /**
  44. * @brief: 音乐歌词处理
  45. *
  46. * @pram: lrcDataStr 音乐歌词数据(字符串)
  47. * @prama:musicInfoMDic 歌词信息
  48. *
  49. *@discussion: 音乐model下发数据,通过contentStr(作为数据源),一行读取数据,每行形成一个新的mdoel(LRCMdoel) 每行要分割取数据
  50. *
  51. *@use:在选择音乐后,调用,原本想传musicModel 但是考虑日后其他SDK 传入,还是传str,省心省事
  52. *
  53. */
  54. - (void)analysisLrcStrOfMusicLRCDataStr:(NSString *)lrcDataStr musicNameStr:(NSString *)musicNameStr musicSingerStr:(NSString *)musicSingerStr complete:(void(^)(BOOL finished,NSMutableArray *lrcModelMArray,NSMutableArray *lrcPointTimeStrArray))block
  55. {
  56. //歌曲 信息
  57. NSString *musicInfoStr = [NSString stringWithFormat:ASLocalizedString(@"歌曲:%@ 演唱:%@"),musicNameStr, musicSingerStr];
  58. //临时存每行歌词
  59. // 因为分割后 只有时间str+歌词内容str 需要扩展mdoel功能,让model变得很强大才对
  60. NSMutableArray *tempMArray =[@[]mutableCopy];
  61. //存歌词model 数据源 存每行歌词对应的 mdoel
  62. NSMutableArray *lrcDataSoureMArray =[@[]mutableCopy];
  63. //存歌词时间
  64. //主要是 因为。C++代理每次来判断歌词时间点,如果直接判断,下一次也就是+1,
  65. //但是index直接取数据总是那么不令人放心。所以通过时间点区域 获得index而不是简单的index++,这样代码更加安全
  66. NSMutableArray *lrcPointTimeStrArray =[@[]mutableCopy];
  67. if (lrcDataStr.length<10)
  68. {
  69. if (block)
  70. {
  71. block(YES,lrcDataSoureMArray,lrcPointTimeStrArray);
  72. }
  73. return;
  74. }
  75. __weak typeof(self)weak_Self = self;
  76. //调 enumerateLinesUsingBlock 一行一行的读取数据
  77. [lrcDataStr enumerateLinesUsingBlock:^(NSString * _Nonnull line, BOOL * _Nonnull stop) {
  78. //拿到每一行
  79. //判断是否 包含 []
  80. if ([lrcDataStr containsString:@"["]&&[lrcDataStr containsString:@"]"])
  81. {
  82. //分割 如果里面是数字 (歌词很多种,特别给出前几行 很多种,看着不爽,直接不要了。前期时间就直接显示歌手+歌名)
  83. NSString *regex = @"[0-9]+:[0-9]+\\.[0-9]+";
  84. NSRange r = [line rangeOfString:regex options:NSRegularExpressionSearch];
  85. //存在数字
  86. if(r.location !=NSNotFound)
  87. {
  88. NSArray *lrcArray = [line componentsSeparatedByString:@"]"];
  89. // NSLog(@"--- array -------%lu",(unsigned long)lrcArray.count);
  90. //[00:11.35]我躲在车里 lrcArray.count = 2 1+1
  91. //[01:33.22][00:35.75]我应该在车底 lrcArray.count = 3 2+1
  92. //[02:23.65][02:11.47][01:13.79]不会像我这样孩子气 lrcArray.count = 4 3+1
  93. if (lrcArray.count>1)
  94. {
  95. for (int i = 0; i<lrcArray.count-1; i++)
  96. {
  97. //时间在前 内容 在后,
  98. NSDictionary *tempDic =@{@"lrcStartTimeStr":[weak_Self timeWithString:[lrcArray[i] substringFromIndex:1]],
  99. @"lrcContentStr":[[lrcArray lastObject] isEmpty]?@" ":[lrcArray lastObject]};
  100. //临时存每行先别MJ去转mdoel
  101. [tempMArray addObject:tempDic];
  102. }
  103. }
  104. }
  105. }
  106. }];
  107. // 临时歌词数据排序
  108. tempMArray = [[tempMArray.copy sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
  109. int number1 =(int)[obj1[@"lrcStartTimeStr"] integerValue];
  110. int number2 =(int) [obj2[@"lrcStartTimeStr"] integerValue];
  111. //按照降序排列,如果升序就返回结果对换
  112. if (number1 > number2)
  113. {
  114. return NSOrderedDescending;
  115. }
  116. else
  117. {
  118. return NSOrderedAscending;
  119. }
  120. }]mutableCopy];
  121. //数据model的扩展成完美nmodle
  122. //存歌词时间//
  123. for(int i = 0;i<tempMArray.count;i++)
  124. {
  125. [lrcPointTimeStrArray addObject:tempMArray[i][@"lrcStartTimeStr"]];
  126. }
  127. // 至少有10行吧。。才算有歌词的歌曲 数组里就存歌曲得信息而已 最后一行时间统一设置10086s
  128. if(tempMArray.count<5)
  129. {
  130. //歌词小于5的。。去一次就够了。。获取歌曲信息:歌手+歌曲名
  131. NSDictionary *modelDic =@{@"lrcStartTimeStr":@"10086",
  132. @"lrcEndTimeStr":@"10086",
  133. @"lrcContentStr":musicInfoStr,
  134. @"lrcLineNumStr":@"10086",
  135. @"lrcNextContentStr":musicInfoStr};
  136. //返回数据源
  137. [lrcDataSoureMArray addObject:[LrcModel mj_objectWithKeyValues:modelDic]];
  138. return;
  139. }
  140. // tempMArray 存 临时的每行数据 的数据要+1 我要增加1个
  141. //目的:让mdoel 不仅装下自己的信息。还装有下一行的信息
  142. for (int i = 0 ;i<tempMArray.count+1;i++)
  143. {
  144. //某一行对应的 临时dic(包含 时间起点+这行歌词)
  145. NSDictionary *firstLrcDic;
  146. if (i<tempMArray.count)
  147. {
  148. firstLrcDic = tempMArray[i];
  149. }
  150. //歌词上最后一行 不是数组里加的最后一行
  151. if (i == tempMArray.count-1)
  152. {//52
  153. NSDictionary *modelDic =@{@"lrcStartTimeStr":firstLrcDic[@"lrcStartTimeStr"],
  154. @"lrcEndTimeStr":@"10086",
  155. @"lrcContentStr":firstLrcDic[@"lrcContentStr"],
  156. @"lrcLineNumStr":[NSString stringWithFormat:@"%d",i],
  157. @"lrcNextContentStr":musicInfoStr};
  158. [lrcDataSoureMArray addObject:[LrcModel mj_objectWithKeyValues:modelDic]];
  159. }
  160. else if (i == tempMArray.count)
  161. {//53
  162. // 最后 多加一行
  163. NSDictionary *modelDic =@{@"lrcStartTimeStr":@"10086",
  164. @"lrcEndTimeStr":@"10086",
  165. @"lrcContentStr":musicInfoStr,
  166. @"lrcLineNumStr":[NSString stringWithFormat:@"%d",i],
  167. @"lrcNextContentStr":musicInfoStr};
  168. [lrcDataSoureMArray addObject:[LrcModel mj_objectWithKeyValues:modelDic]];
  169. }
  170. else
  171. {//50
  172. //注意i+2 因为当前这行 歌词走完了。那么他应该显示的是 下 下一行歌词 对不对!但是,如果下一行为空呢。这都要考虑
  173. NSDictionary *secondLrcDic = tempMArray[i+1];
  174. NSString *nextStr = @"";
  175. if ([secondLrcDic[@"lrcContentStr"] isEmpty])
  176. {
  177. if (i+2 >= tempMArray.count-1)
  178. {
  179. nextStr = @"";
  180. }
  181. else
  182. {
  183. nextStr = [secondLrcDic[@"lrcContentStr"] isEmpty]?tempMArray[i+2][@"lrcContentStr"]:secondLrcDic[@"lrcContentStr"];
  184. }
  185. }
  186. NSDictionary *modelDic =@{@"lrcStartTimeStr":firstLrcDic[@"lrcStartTimeStr"],
  187. @"lrcEndTimeStr":secondLrcDic[@"lrcStartTimeStr"],
  188. @"lrcContentStr":firstLrcDic[@"lrcContentStr"],
  189. @"lrcLineNumStr":[NSString stringWithFormat:@"%d",i],
  190. @"lrcNextContentStr":nextStr};
  191. [lrcDataSoureMArray addObject:[LrcModel mj_objectWithKeyValues:modelDic]];
  192. }
  193. }
  194. if (block)
  195. {
  196. //返回 强大lrcMdoel 和 装有每行时间点的 数组
  197. block(YES,lrcDataSoureMArray,lrcPointTimeStrArray);
  198. }
  199. }
  200. #pragma mark - 时间转S处理(Data)
  201. /**
  202. * @brief: 时间转S处理(
  203. *
  204. * @use:将 01:07.45 转为 秒
  205. */
  206. - (NSString *)timeWithString:(NSString *)timeString
  207. {
  208. // 01:02.38
  209. NSInteger min = [[timeString componentsSeparatedByString:@":"][0] integerValue];
  210. NSInteger sec = [[timeString substringWithRange:NSMakeRange(3, 2)] integerValue];
  211. NSInteger hs = [[timeString componentsSeparatedByString:@"."][1] integerValue];
  212. return [NSString stringWithFormat:@"%f",(min * 60 + sec + hs * 0.01)];
  213. }
  214. @end