I do not know why suddenly want to write a music player, the feeling should be very good to play, their favorite songs to export, with the program load run
Get up, that song must sound very sense ah ... But I've heard that love story countless times ... I'm sick.
You crossing are interested to listen to. In fact, the early preparation is very pit dad, find lyrics really egg pain ah.
Don't say much nonsense, the usual, look at the finished product first:
This thing takes up too much space, can't record too much ...
Let me introduce you first.
First of all
Make a player interface come out, above is a tableview to load lyrics, the bottom two slider, a sound, a progress, the bottom three button.
This paper briefly introduces the realization of the requirement of using AutoLayout to realize the width and equal spacing of the bottom three buttons.
// bottom three buttons split the width of the screen procedure
//1. first fixed the left and right of the first button to the left of the constraint fixed, where the height can be given or not, so that text automatically filled
//2. then select the three buttons, check the vertical alignment and the two necessary conditions for equal width
//3. then the middle button just sets the constraint on the left button.
//4. finally let the right side of the button to the right of the constraint, the left side of the constraint is fixed, select three, press OPTION + COMMAND + = , the alignment can be
Simple to explode, no code needed at all
And then
Import songs and lyrics that need to be manipulated for path storage
First look at properties and controls
#import "ViewController.h" #import <AVFoundation/AVFoundation.h> #import "MKJParserLrc.h" #import "uiimage+ ImageEffects.h "@interface Viewcontroller () <uitableviewdatasource,uitableviewdelegate,avaudioplayerdelegate > @property (Weak, nonatomic) Iboutlet UITableView *tableview; @property (weak, nonatomic) Iboutlet UISlider *volslider ; @property (weak, nonatomic) Iboutlet uislider *progressslider; @property (nonatomic,strong) Avaudioplayer *audioplayer ; Avaudioplayer ----> audio local @property (nonatomic,strong) Nsarray *mp3arr;//MP3 Path @property (nonatomic, Strong) Nsarray *lrcarr; Lyrics path @property (nonatomic,assign) Nsinteger Mp3index; The current play below Table @property (nonatomic,assign) Nsuinteger CurrentRow; Which line is currently @property (Nonatomic,strong) MKJPARSERLRC *mkj; Parsing lyrics with @end
here my picture I did a simple Gaussian blur, here introduce a class to everyone, together with the code are given out, need to take to use the
-(void) viewdidload {[Super viewdidload]; Additional setup after loading the view, typically from a nib. Self.view.backgroundColor = [Uicolor colorwithred:193/255.4 green:193/255.0 blue:193/255.4 alpha:0.7]; [Self.tableview Registerclass:[uitableviewcell class] forcellreuseidentifier:@ "cell"]; Self.tableView.separatorStyle = Uitableviewcellseparatorstylenone; Self.tableView.rowHeight = 60; Picture Gaussian blur UIImage *image = [UIImage imagenamed:@ "436c1b64a2b6a4cbab09ee22db3851f4-1400x2100.jpg"]; image = [Image applyblurwithradius:15 Tintcolor:nil saturationdeltafactor:1.5 Maskimage:nil]; Self.tableView.backgroundView = [[Uiimageview alloc] initwithimage:image]; Storage path Self.mp3arr = @[[[nsbundle Mainbundle] pathforresource:@ "Love Story" oftype:@ "MP3"],[[nsbundle Mainbundle] Path forresource:@ "Joker Xue-Actor" oftype:@ "MP3"],[[nsbundle Mainbundle] pathforresource:@ "brilliance-Heterogeneous" oftype:@ "MP3"]; Self.lrcarr = @[[[nsbundle Mainbundle] Pathforresource:@ "Love story" oftype:@ "LRC"],[[nsbundle Mainbundle] pathforresource:@ "Joker Xue-Actor" oftype:@ "LRC"],[[nsbundle Mainbundle] pathforresource:@ "Brilliance-heterogeneous" oftype:@ "LRC"]; SELF.MKJ = [[MKJPARSERLRC alloc] init]; Load songs and lyrics by Path [self loadmp3:self.mp3arr[self.mp3index] lrcpath:self.lrcarr[self.mp3index]; Start timer, always updated [Nstimer scheduledtimerwithtimeinterval:0.1 target:self selector: @selector (changetime:) userinfo:nil Repeats:yes];}
After
We load MP3 songs and parse lyrics
#import <AVFoundation/AVFoundation.h>
Import this header file and use Avaudioplayer to play
Load lyrics and songs-(void) LOADMP3: (NSString *) mp3str Lrcpath: (NSString *) lrcstr{ //This method is to get online// self.audioplayer = [[ Avaudioplayer alloc] Initwithcontentsofurl:[nsurl urlwithstring:mp3str] error:nil]; The following is the local self.audioplayer = [[Avaudioplayer alloc] Initwithcontentsofurl:[nsurl fileurlwithpath:mp3str] Error: NIL]; Self.audioPlayer.delegate = self; Self.audioPlayer.volume = 0.5f; Analytic lyrics Method [self.mkj parserlrcwithfileurl:lrcstr]; Let the slider go in and the song maximum time consistent self.progressSlider.maximumValue = self.audioPlayer.duration; Ready to play [Self.audioplayer preparetoplay]; }
use the object you created to parse the lyrics and expose a method to pass in the local URL .
@interface Mkjparserlrc:nsobject@property (Nonatomic,strong) Nsmutablearray *timearr; @property (Nonatomic,strong) Nsmutablearray *lrcarr;-(void) Parserlrcwithfileurl: (NSString *) Lrcpath; @end
here's how to split the string thousands, we're just showing a
-(void) Parserlrcwithfileurl: (NSString *) lrcpath{ //Every time he comes in, it clears the previous [Self.lrcarr removeallobjects]; [Self.timearr removeallobjects]; String reading lyrics by path nsstring *lrcstr = [NSString stringwithcontentsoffile:lrcpath encoding:nsutf8stringencoding Error : nil]; Split Nsarray *lrcarr = [Lrcstr componentsseparatedbystring:@ "["]; Continue splitting for (NSString *sepstr in Lrcarr) { //No brain segmentation nsarray *separr = [Sepstr componentsseparatedbystring:@] "]; Three kinds of possible not, the first is the head lyrics, the second time there is no lyrics, the third is no lyrics wrapped if (! [Separr[0] isequaltostring:@ "" "| | [separr[1] isequaltostring:@ "\ n"] | | [separr[1] isequaltostring:@ "\ r \ n"])) { [Self.timearr addobject:separr[0]]; [Self.lrcarr addobject:separr[1];} }
Fourth Step
Implement the Click event and proxy method
Previous-(Ibaction) Previoussong: (ID) sender{[self.audioplayer stop]; self.mp3index--; if (_mp3index==-1) {self.mp3index = 2; } [self loadmp3:self.mp3arr[self.mp3index] lrcpath:self.lrcarr[self.mp3index]; [Self.audioplayer play]; }//Play or Pause-(ibaction) play: (ID) Sender {if (self.audioPlayer.playing) {[Self.audioplayer pause]; } else {[Self.audioplayer play]; }}//Next Song-(ibaction) Nextsong: (ID) sender{[self.audioplayer stop]; self.mp3index++; if (Self.mp3index = = 3) {self.mp3index = 0; } [self loadmp3:self.mp3arr[self.mp3index] lrcpath:self.lrcarr[self.mp3index]; [Self.audioplayer play];} Voice change-(Ibaction) Volchange: (UISlider *) Sender {self.audioPlayer.volume = Sender.value;} Progress change-(Ibaction) Ratechange: (UISlider *) Sender {self.audioPlayer.currentTime = Sender.value;} -(void) audioplayerdidfinishplaying: (Avaudioplayer *) player successfully: (BOOL) flag{[self nextsong:nil];}
finallyStart a timer, let the progress bar and lyrics in real-time update, so that lyrics and songs to match, this method is the most critical, the most critical
Updated Method-(void) Changetime: (Nstimer *) timer{//Let progress bar and current playback time always self.progressSlider.value = Self.audioPlayer.currentTi Me Traverse the lyrics to record which row is currently playing [SELF.MKJ.TIMEARR enumerateobjectsusingblock:^ (id _nonnull obj, nsuinteger idx, BOOL * _nonnull Stop) {NSString *timestr = Self.mkj.timearr[idx]; Nsarray *timearr = [Timestr componentsseparatedbystring:@ ":"]; CGFloat seconds = [timearr[0] floatvalue] * + [timearr[1] floatvalue]; if (seconds >= self.audioPlayer.currentTime) {if (idx = = 0) {Self.currentrow = i dx } else {self.currentrow = idx-1; } *stop = YES; } }]; Refresh [Self.tableview Reloaddata]; Scroll to the specified row realistic lyrics if (Self.currentrow < Self.mkj.lrcArr.count) {[Self.tableview Scrolltorowatindexpath:[nsind Expath IndexPathForRow:self.currentRow insection:0] Atscrollposition:uitableviewscrollpositioNmiddle Animated:yes]; }}
Naïve I thought this is finished, this broken thing can let you fall unprepared!!!
As fast as my hand, the moment is blown, for the following reasons
(LLDB) PO Indexpath
<nsindexpath: 0xc000000007a00016 > {length = 2 path = 0 - 61 }
$-: : 47.557 musicplayerdemo[5176:272368] * * * terminating app due to uncaught Exception ' nsrangeexception ', Reason:' * * *-[__nsarraym Objectatindex:]: Index 61 Beyond bounds [0 ...] '
First throw Call stack:
This is a good understanding, first of these three songs lyrics 52 46 81 lines, when we quickly slide the progress bar,
And then switch to the previous or next, the array out of bounds, ah, the lyrics are different, will definitely cross the border, find out the reason is good to run
Add this judgment to the load cell method and you're not going to jump.
UITableViewCell *cell = [TableView dequeuereusablecellwithidentifier:@ "Cell"]; if (Indexpath.row < Self.mkj.lrcArr.count) { cell.textLabel.text = Self.mkj.lrcarr[indexpath.row]; }
See here, a simple music player is done, I think you must be like this
But actually, you must be.
the lesson of blood, if you also want to write a demo, do not use your favorite songs to do, or the song will be destroyed by you
, you are interested to go to github download Listen, there are bugs remember to tell me Yo, love stories really nice,
But I was sick of it.
Demo Address: Https://github.com/DeftMKJ/MusicDemo
It's not too early, let's hear it again and sleep, everybody goodnight
IOS Simple and practical music player, teenager, make a song for yourself ...