Objective-c OC录音 CoreData MagicalRecord

写在前面:

很久以前就有想法的整理一下自己的代码,写成简书或是放到Git上。可是懒惰势力猖獗,一直在安逸中混着,能力提升上感受到了瓶颈,心底自知应该做出改变,突破它。所以下定决心,开始行动起来了。


功能描述:

最近,着手的项目里有一个录音15S的需求。

这两天有些空闲时间,于是乎,现在得空封装的一个OC版的录音器。

用单例模式提供一个全局的录音helper,操作录音的开始、完成、暂停、继续功能。

录音完成后,通过MagicalRecord 保存录音对象到数据库。

写了一个简陋的录音场景,有录音进度条,开始、完成、暂停、继续按钮,录音进行时的小动画。

播放录音的场景,现在未能完成,本意是和录音场景用同一个效果来操作播放。

GitHub:SDRecorder

运行效果如下图:

image

使用:

第一次分享,功能没有覆盖得很全面,目前大家可以拿来用的工具,我自以为 SD_RecordHelper 还算能帮助减轻实现录音时的负担。

SD_RecordHelper.h 的功能列表:

#import <Foundation/Foundation.h>
#import "Record.h"

typedef enum : NSUInteger {
    ///正在录音
    SD_RHRecording,
    ///录音完成
    SD_RHDone,
    ///录音暂停
    SD_RHPause,
} SD_RHRecordStatus;

typedef void(^SD_RecordTimeBlock)(NSInteger );
typedef void(^SD_RecordDoneBlock)(void);

@interface SD_RecordHelper : NSObject
///录音时间计数block
@property (copy, nonatomic) SD_RecordTimeBlock SDRecordTimeBlock;
///录音保存成功block
@property (copy, nonatomic) SD_RecordDoneBlock SDRecordDoneBlock;

///录音时长
@property (assign , nonatomic) NSInteger recordTimeIndex;

///当前录音状态
@property (assign , nonatomic) SD_RHRecordStatus recordStatus;

///获取录音helper单例
+ (instancetype)share;

///开始录音
- (void)startRecord;
///暂停录音
- (void)pauseRecord;
///继续录音
- (void)resumeRecord;
//停止录音
- (void)finishRecord;

///播放录音
- (void)playRecord:(NSString *)path;

@end

功能实现:

1. 录音

我们可以引入AVFoundation框架,使用AVAudioRecorder和AVAudioPlayer可以实现语音的录制和播放功能。

我就不太介绍AVAudioRecorder太多的属性配置了,因为我自己也没研究很深(就是不懂~)。我们就先搞定录音吧。

用燕舞录音机、步步高复读机录音的经历,和我差不多大的朋友们应该都有类似经历吧。录音首先需要一个录音设备,在代码中我就需要初始化一个AVAudioRecorder作为我们的录音设备了:

///配置录音机
-(void)configAudioRecorder{
    
    //录音文件保存路径,我设置的路径是当前时间的字符串,注意路径不要有空格
    NSURL *url=[self getSavePath];
    //录音格式设置
    NSDictionary *setting=[self getAudioSetting];
    //录音机
    NSError *error=nil;
    _audioRecorder=[[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
    _audioRecorder.delegate=self;
    //这个设置为YES可以做音波的效果,我没有实现音波功能
    _audioRecorder.meteringEnabled=YES;
    if (error) {
        NSLog(@"创建录音机audioRecorder发生错误:%@",error.localizedDescription);
    }
    
}

在设置好录音的属性后,创建好的录音机就可以通过 record 方法开始录音。

[self.audioRecorder record];

通过 pause 方法,暂停录音。

[self.audioRecorder pause];

通过 stop 方法,结束录音。

[self.audioRecorder stop];

录音结束时有一个 delegate 方法,获取录音结束相应。我就在这个代理方法里面,通过 Block 处理了录音结束的操作。

-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{

    ///录音完成
    if (self.SDRecordDoneBlock) {
        self.SDRecordDoneBlock();
    }
    NSLog(@"录音完成!");
}


- 进度条变化效果
用一个定长View,和一个不同颜色的View实现,随着时间的推移,将深色View的长度变长来实现的:


- 录音图片变化效果
通过循环三张图片实现的效果。

因为我要实现的功能是开始录制后,每一条录制15S,所以我加了一个
Timer 计数15S,然后停止录音,保存录音,然后开始新的一条录音的录制。

同时这个 Timer 的计数,我通过 Block 传出,然后用Timer的计数做了录音的两个效果:

SD_RecordHelper *recordHelper = [SD_RecordHelper share];
    
    //录音计数回调
    recordHelper.SDRecordTimeBlock = ^(NSInteger timeCount) {
        [self setUpRecordViewStatus];
        _recordTimeIndex = timeCount;
        [weakSelf recordAnimationAction];
    };
    
    //录音结束回调
    recordHelper.SDRecordDoneBlock = ^{
        self.dataArray = [[[RecordDataAccessor getRecord]reverseObjectEnumerator] allObjects];
        
        [self zeroProcessAction];
        
        [self.tableView reloadData];
    };
    
    _tapeImgIndex = recordHelper.recordTimeIndex;

进度条效果:

///录音进度条显示动画
- (void)recordProcessAction{
    self.timerLab.text = [NSString stringWithFormat:@"00:%@",_recordTimeIndex < 10 ? [NSString stringWithFormat:@"0%ld",_recordTimeIndex] : [NSString stringWithFormat:@"%ld",_recordTimeIndex]];

    self.progressWi.constant = (MainScreenWidth - 194.5)/15 * _recordTimeIndex;
    
}

录音图片效果:

///录音效果图显示动画
- (void)tapeImvAnimationAction{
    
    self.tapeImv.image = [UIImage imageNamed:[NSString stringWithFormat:@"tape%ld",(long)_tapeImgIndex]];

    NSString *recordStatusLabStr = @"正在录音中";
    for (int i = 0; i < _tapeImgIndex; i ++) {
        recordStatusLabStr = [NSString stringWithFormat:@"%@.",recordStatusLabStr];
    }
    self.tapeStatusLab.text = recordStatusLabStr;

}

2. MagicalRecord 存取录音


MagicalRecord 是用来操作Core Data的一个第三方工具,使用起来比较方便。理论一点的东西,大家可以深入去研究一下,我这是实现了简单的存取。

MagicalRecord 的基本配置、使用方法,在简书里面就可以找到,我收藏夹里面也有一些写得清晰的简书。


CoreData 会根据数据库表的 Model 生成相应的文件,在 MagicalRecord 中需要 Model 继承于 NSManagedObject 就好了。

我这里有一个普通的 Record Model ,和与之对应的 DBRecord Model。

Record:

@interface Record : NSObject<NSCopying>

@property (strong, nonatomic)   NSString    *name;
@property (strong, nonatomic)   NSString    *path;
@property (assign, nonatomic)   NSInteger    duration;

@end

DBRecord:

@interface DBRecord : NSManagedObject

@property (nullable, nonatomic, retain)   NSString    *name;
@property (nullable, nonatomic, retain)   NSString    *path;
@property (nullable, nonatomic, retain)   NSNumber    *duration;

@end

然后通过 RecordDataAccessor 来操作录音数据得存取:

@interface RecordDataAccessor : NSObject

#pragma mark - 保存/查询
//==========================================================================================================================
/** 保存录音 */
+ (void)saveRecord:(Record *)record;

/** 删除录音 */
+ (void)deleteRecordByName:(NSString *)name;

+ (NSMutableArray *)getRecord;

@end

我这里的删除仅仅是删除了数据库录音的记录,如果你需要 MagicalRecord 在你项目中发挥作用,记得要在删除时,删掉本地的文件。

强行结束:

第一次写分享,发现代码并没有封装得顺手好用,只能算是勉强实现功能。但是这次之后,有了经验下次,应该能做好一点。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342