Bouw een iOS-muziekspeler spelerbesturing

Deze driedelige lessenreeks leert je hoe je een aangepaste muziekspeler kunt bouwen met de iOS SDK. Lees verder!


Reeksformaat:

  • Applicatie-instellingen
  • Muziekspelerbediening
  • UI Theming

Welkom bij het tweede deel van deze tutorialserie over het bouwen van een aangepaste muziekspeler met de iOS SDK. In dit deel gaan we verder met de albumssectie die we in de eerste aflevering begonnen en leren we de afzonderlijke tracks te spelen.


Stap 1: Het storyboard bijwerken

Open het storyboard en sleep een tabelweergavecontroller van de objectbibliotheek naar het canvas. We zullen deze Table View Controller gebruiken om een ​​enkel album te tonen. CTRL-sleep vanuit de cel in de Albums Table View Controller naar de nieuwe Table View Controller die we zojuist hebben toegevoegd en selecteer "push" onder de sectie "Selection Segue" in het pop-upmenu.

    

Nu gaan we onze cellen maken. De eerste cel in de tabelweergave bevat wat informatie over het album, zoals de illustratie, de albumartiest, de duur van het album en het aantal nummers op het album. De andere cel bevat de nummers van het album. Selecteer de cel en open de specificatie-infovenster. Stel de ID in op "Cell" en wijzig de stijl van "Aangepast" in "Subtitle".

    

Nu we de cel voor de nummers hebben gemaakt, sleept u een nieuwe tabelweergavecel vanuit de objectenbibliotheek bovenop de cel die we zojuist hebben bewerkt. Verander de selectiestijl van "Blauw" in "Geen" en stel de ID in op "InfoCell". Open daarna de Size Inspector en verander de rijhoogte in 120.

In deze cel hebben we een afbeeldingsweergave nodig voor de illustratie en twee labels voor de informatie. Dus sleep eerst een afbeeldingsweergave naar de cel en verander de grootte naar 100x100. Wijzig ook de X- en Y-eigenschappen in 10. Sleep daarna de twee labels in de cel en lijn ze uit, zoals de afbeelding hieronder:

    

Selecteer het eerste label, open de Attributen Inspector en wijzig het lettertype in "System Bold 17.0". Verwijder vervolgens de tekst uit beide labels en verander de tag van het eerste label in 101 en het label van het tweede label in 102. Selecteer ten slotte de afbeeldingsweergave en verander de tag in 100. We gebruiken deze tags om aan te passen de labels en afbeeldingen in de tableView: cellForRowAtIndexPath: methode.


Stap 2: een geselecteerd album weergeven

Ga naar "Bestand"> "Nieuw"> "Bestand ..." om een ​​nieuw bestand te maken. Selecteer "Objective-C klasse" en klik vervolgens op "Volgende". Voer "AlbumViewController" in voor de klasse en zorg ervoor dat dit een subklasse is van UITableViewController en dat beide selectievakjes niet zijn geselecteerd. Klik nogmaals op "Volgende" en klik vervolgens op "Maken".

Open AlbumViewController.h en pas de code als volgt aan:

 #importeren  #importeren  @face AlbumViewController: UITableViewController NSString * albumTitle;  @property NSString * albumTitle; @einde

Hier voegen we eigenlijk gewoon het MediaPlayer-framework toe aan onze table view-controller en we maken een NSString die de albumtitel zal bevatten. We zullen deze reeks bijwerken wanneer de gebruiker een album selecteert.

Open nu AlbumsViewController.m en voeg de volgende regel toe #import "AlbumsViewController.h":

 #import "AlbumViewController.h"

Voeg daarna de volgende methode toe:

 - (void) prepareForSegue: (UIStoryboardSegue *) segue verzender: (id) afzender AlbumViewController * detailViewController = [segue destinationViewController]; MPMediaQuery * albumsQuery = [MPMediaQuery albumsQuery]; NSArray * albums = [albumsQuery-collecties]; int selectedIndex = [[self.tableBekijk indexPathForSelectedRow] rij]; MPMediaItem * selectedItem = [[albums objectAtIndex: selectedIndex] representativeItem]; NSString * albumTitle = [selectedItem valueForProperty: MPMediaItemPropertyAlbumTitle]; [detailViewController setAlbumTitle: albumTitle]; 

Hier geven we de titel van het geselecteerde album door aan de detailViewController, wat de AlbumViewController is. Het storyboard roept deze methode tijdens runtime aan wanneer u een segue in de huidige scène activeert (dat wil zeggen wanneer de gebruiker een album selecteert).

Open nu AlbumViewController.m en voeg de volgende regel toe onder de @implementation:

 @synthetize albumTitel;

Ga daarna naar de viewDidLoad methode en verander het om het als volgt te lezen:

 - (void) viewDidLoad [super viewDidLoad]; self.title = albumTitel; 

Hier stellen we eenvoudigweg de titel van de navigatiebalk in op de geselecteerde albumtitel.

Nu we een nieuw scherm voor het geselecteerde album hebben gemaakt, denk ik dat het een goed idee is om de app te testen. Klik op Build and Run om de app te testen. Als je naar het tabblad albums gaat en een album selecteert, ga je naar een nieuw scherm met een lege tabelweergave, maar de titel van de navigatiebalk moet hetzelfde zijn als het geselecteerde album.


Stap 3: Toon de albumnummers en info

Ga naar de numberOfSectionsInTableView: en de tableView: numberOfRowsInSection: in AlbumViewController.m en pas ze als volgt aan:

 - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView return 1;  - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section MPMediaQuery * albumQuery = [MPMediaQuery albumsQuery]; MPMediaPropertyPredicate * albumPredicate = [MPMediaPropertyPredicate predicateWithValue: albumTitle forProperty: MPMediaItemPropertyAlbumTitle]; [albumQuery addFilterPredicate: albumPredicate]; NSArray * albumTracks = [albumQuery-items]; retourneer [telling van albumtracks] +1; 

Deze methoden zouden nu wel bekend moeten zijn, maar zoals je kunt zien hebben we iets nieuws gedaan in de tweede methode. We gebruikten een MPMediaPropertyPredicte. Met een MPMediaPropertyPredicte-object kunt u een query filteren. We gebruikten de albumtitel van het geselecteerde album voor de filterwaarde en we gebruikten MPMediaPropertyAlbumTitle als de eigenschap, dus onze zoekopdracht bevat alleen het album met de titel van het album dat de gebruiker heeft geselecteerd.

U kunt veel verschillende eigenschappen gebruiken voor een MPMediaPropertyPredicate. Je kunt ze allemaal bekijken in de Documenten van de iOS Developer Library.

We retourneren het aantal nummers, plus 1. De extra cel is voor de cel met de albuminformatie.

Omdat we twee verschillende soorten cellen hebben, met twee verschillende hoogten, moeten we ons tabeloverzicht laten zien welke hoogte we moeten gebruiken voor welke cel. Om dat te doen, voegt u de volgende methode toe onder de numberOfRowsInSection: methode:

 - (CGFloat) tableView: (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath if ([indexPath row] == 0) retourneer 120;  else terug 44; 

Hier vertellen we onze tableview dat onze eerste cel met de albuminformatie een hoogte van 120 pixels heeft en dat alle andere cellen met de nummers van het album een ​​hoogte van 44 pixels hebben.

Nu zullen we vier verschillende methoden maken om wat informatie over het album te krijgen. Bij de eerste methode krijgen we de albumillustraties van het geselecteerde album. In de tweede methode krijgen we de albumartiest. Bij de derde methode krijgen we de duur van het album en het aantal nummers in het album. En in de laatste methode zullen we controleren of de artiesten van de nummers in het album hetzelfde zijn. Soms hebben de nummers in een album dezelfde artiesten, maar niet altijd. Als de nummers verschillende artiesten hebben, laten we ze in de tabweergave zien, maar als alle artiesten hetzelfde zijn, zullen we ze niet laten zien omdat je ze al in de eerste cel kunt zien.

We beginnen met het maken van de eerste methode, dus voeg de volgende code toe onder de viewDidLoad methode:

 - (UIImage *) getAlbumArtworkWithSize: (CGSize) albumSize MPMediaQuery * albumQuery = [MPMediaQuery albumsQuery]; MPMediaPropertyPredicate * albumPredicate = [MPMediaPropertyPredicate predicateWithValue: albumTitle forProperty: MPMediaItemPropertyAlbumTitle]; [albumQuery addFilterPredicate: albumPredicate]; NSArray * albumTracks = [albumQuery-items]; voor (int i = 0; i < [albumTracks count]; i++)  MPMediaItem *mediaItem = [albumTracks objectAtIndex:i]; UIImage *artworkImage; MPMediaItemArtwork *artwork = [mediaItem valueForProperty: MPMediaItemPropertyArtwork]; artworkImage = [artwork imageWithSize: CGSizeMake (1, 1)]; if (artworkImage)  artworkImage = [artwork imageWithSize:albumSize]; return artworkImage;   return [UIImage imageNamed:@"No-artwork-album.png"]; 

Deze methode retourneert de illustratie van het album met een specifieke grootte. Eerst controleren we elk nummer om te zien of het een afbeelding van een kunstwerk heeft. We doen dit met een klein formaat, dus onze app zal snel zijn. Zodra we een afbeelding van een afbeelding vinden, krijgen we die afbeelding opnieuw met de juiste grootte en retourneren we de afbeelding. Hierna stopt de methode, dus als de eerste song een afbeelding van een illustratie bevat, wordt die afbeelding geretourneerd en stopt deze met de methode. We hebben deze methode toegevoegd omdat soms niet alle nummers in een album een ​​afbeelding van een illustratie bevatten. Als de methode geen afbeelding van een afbeelding heeft gevonden, retourneren we een standaardillustratiekopie.

We hebben die standaardillustratiekopie nog niet toegevoegd, dus laten we dit eerst doen. Download de broncode die aan dit project is gekoppeld en sleep de [email protected] en No-artwork-album.png afbeeldingen in het project. Zorg ervoor dat "Items in de map van de bestemmingsgroep kopiëren (indien nodig)" is aangevinkt en klik op "Finish".

Voeg nu de volgende code toe voor de tweede methode:

 - (NSString *) getAlbumArtist MPMediaQuery * albumQuery = [MPMediaQuery albumsQuery]; MPMediaPropertyPredicate * albumPredicate = [MPMediaPropertyPredicate predicateWithValue: albumTitle forProperty: MPMediaItemPropertyAlbumTitle]; [albumQuery addFilterPredicate: albumPredicate]; NSArray * albumTracks = [albumQuery-items]; voor (int i = 0; i < [albumTracks count]; i++)  NSString *albumArtist = [[[albumTracks objectAtIndex:0] representativeItem] valueForProperty:MPMediaItemPropertyAlbumArtist]; if (albumArtist)  return albumArtist;   return @"Unknown artist"; 

Hier doen we hetzelfde als in de vorige methode, maar deze keer voor de albumartiest. We controleren of elk nummer al een albumartiest heeft. Als het er een heeft, geven we het terug en stopt de methode. Als de methode geen albumartiest vindt, wordt de tekenreeks 'Onbekende artiest' geretourneerd.

Voeg nu de volgende code toe voor onze derde methode:

 - (NSString *) getAlbumInfo MPMediaQuery * albumQuery = [MPMediaQuery albumsQuery]; MPMediaPropertyPredicate * albumPredicate = [MPMediaPropertyPredicate predicateWithValue: albumTitle forProperty: MPMediaItemPropertyAlbumTitle]; [albumQuery addFilterPredicate: albumPredicate]; NSArray * albumTracks = [albumQuery-items]; NSString * trackCount; if ([aantal albetracks]> 1) trackCount = [NSString stringWithFormat: @ "% i Songs", [aantal albetracks]];  else trackCount = [NSString stringWithFormat: @ "1 Song"];  lange playbackDuration = 0; for (MPMediaItem * track in albumTracks) playbackDuration + = [[trackwaardeForProperty: MPMediaItemPropertyPlaybackDuration] longValue];  int albumMimutes = (playbackDuration / 60); NSString * albumDuration; if (albumMimutes> 1) albumDuration = [NSString stringWithFormat: @ "% i Mins.", albumMimutes];  else albumDuration = [NSString stringWithFormat: @ "1 Min."];  retourneer [NSString stringWithFormat: @ "% @,% @", trackCount, albumDuration]; 

In deze methode maken we een string met informatie over het aantal nummers in het geselecteerde album en over de duur van het album. Eerst maken we onze query en voegen we het filter toe voor de albumtitel. Vervolgens maken we een array met de items uit de query. Vervolgens controleren we of het album een ​​of meer nummers bevat. Als het een nummer heeft, stellen we de trackCount-reeks in op "1 song", anders stellen we die reeks in op het aantal nummers. Daarna maken we een variabele voor de duur van het album. We krijgen de duur in seconden, maar omdat we ze in minuten willen laten zien, delen we de variabele playbackDuration met 60. Als dat klaar is, controleren we of het album langer dan 1 minuut is. Als dit waar is, stellen we de duur van de albumreeks in op het aantal minuten, anders zeggen we dat deze gelijk is aan 1 minuut. Eindelijk retourneren we een string met het aantal tracks en de duur van het album.

Nu we onze eerste drie methoden hebben gemaakt, voegt u de volgende code toe voor de laatste methode:

 - (BOOL) sameArtists MPMediaQuery * albumQuery = [MPMediaQuery albumsQuery]; MPMediaPropertyPredicate * albumPredicate = [MPMediaPropertyPredicate predicateWithValue: albumTitle forProperty: MPMediaItemPropertyAlbumTitle]; [albumQuery addFilterPredicate: albumPredicate]; NSArray * albumTracks = [albumQuery-items]; voor (int i = 0; i < [albumTracks count]; i++)  if ([[[[albumTracks objectAtIndex:0] representativeItem] valueForProperty:MPMediaItemPropertyArtist] isEqualToString:[[[albumTracks objectAtIndex:i] representativeItem] valueForProperty:MPMediaItemPropertyArtist]])   else  return NO;   return YES; 

In deze methode controleren we of de artiest van de nummers hetzelfde is of niet. Het gebruikt een for-lus om te controleren of de artiest van de eerste song hetzelfde is als de artiest uit het huidige lusnummer. Als de artiestwaarden niet gelijk zijn, retourneert de methode de Boolean NO, maar als deze is voltooid met de lus en geen van de artiesten hetzelfde zijn, retourneert de methode de booleaanse waarde YES.

Dat was veel code, maar het zal onze app een betere ervaring geven, dus het is de moeite waard. Om de albuminformatie en liedjes daadwerkelijk te tonen, moeten we de tableView: cellForRowAtIndexPath: methode. Ga naar die methode en pas de code aan als volgt:

 - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath if ([indexPath row] == 0) static NSString * CellIdentifier = @ "InfoCell"; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier forIndexPath: indexPath]; UIImageView * albumArtworkImageView = (UIImageView *) [cell viewWithTag: 100]; albumArtworkImageView.image = [self getAlbumArtworkWithSize: albumArtworkImageView.frame.size]; UILabel * albumArtistLabel = (UILabel *) [cell viewWithTag: 101]; albumArtistLabel.text = [self getAlbumArtist]; UILabel * albumInfoLabel = (UILabel *) [cell viewWithTag: 102]; albumInfoLabel.text = [self getAlbumInfo]; terugkeer cel;  else static NSString * CellIdentifier = @ "Cell"; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier forIndexPath: indexPath]; MPMediaQuery * albumQuery = [MPMediaQuery albumsQuery]; MPMediaPropertyPredicate * albumPredicate = [MPMediaPropertyPredicate predicateWithValue: albumTitle forProperty: MPMediaItemPropertyAlbumTitle]; [albumQuery addFilterPredicate: albumPredicate]; NSArray * albumTracks = [albumQuery-items]; NSUInteger trackNumber = [[[albumTracks objectAtIndex: (indexPath.row-1)] valueForProperty: MPMediaItemPropertyAlbumTrackNumber] unsignedIntegerValue]; if (trackNumber) cell.textLabel.text = [NSString stringWithFormat: @ "% i.% @", trackNumber, [[[albumTracks objectAtIndex: (indexPath.row-1)] representativeItem] valueForProperty: MPMediaItemPropertyTitle]];  else cell.textLabel.text = [[[albumTracks objectAtIndex: (indexPath.row-1)] representativeItem] valueForProperty: MPMediaItemPropertyTitle];  if ([self sameArtists]) cell.detailTextLabel.text = @ "";  else if ([[[albumTracks objectAtIndex: (indexPath.row-1)] representativeItem] valueForProperty: MPMediaItemPropertyArtist]) cell.detailTextLabel.text = [[[albumTracks objectAtIndex: (indexPath.row-1)] representativeItem] valueForProperty : MPMediaItemPropertyArtist];  else cell.detailTextLabel.text = @ "";  cel retourneren; 

Dit is een zeer grote methode, maar de code is niet echt moeilijk. Laten we bij het begin beginnen.

Begin met het controleren van de rij die we gebruiken. Als we de eerste rij gebruiken, willen we de eerste cel weergeven die we in ons storyboard hebben gemaakt. Zoals je kunt zien, gebruiken we dezelfde CellIdentifier als we gebruikten voor de cel in ons storyboard. We hebben UIImageView gemaakt en deze aan de imageview in de cel toegewezen met de tag 100, wat natuurlijk hetzelfde is als we eerder gebruikten. Daarna noemen we de getAlbumArtworkWithSize: methode die we eerder hebben gemaakt om de albumillustraties te krijgen en de weergave van de afbeelding voor die illustratie bij te werken. We hebben de grootte van de afbeelding gebruikt voor de grootte van onze illustraties. Daarna doen we hetzelfde voor de twee labels. Voor de tekst van het eerste label noemen we het getAlbumArtist methode en voor het tweede label noemen we het getAlbumInfo methode.

Wanneer we de eerste rij niet gebruiken, maar een andere, willen we de nummers van het album laten zien. Hier maken we eerst een query en voegen we een filter toe aan die query. Vervolgens slaan we de items van die query op in een array. Daarna krijgen we het nummer van het nummer in het album en controleren of dit er is. Als er een tracknummer beschikbaar is, voegen we dat toe vóór de titel van het nummer, anders laten we alleen de titel van het nummer zien. Zoals je kunt zien, hebben we gebruikt (Indexpath.row-1) voor de index van de nummers. We doen dit omdat de eerste cel van de tabelweergave wordt gebruikt voor de albuminformatie.

Daarna controleren we of de nummers dezelfde artiesten hebben door de sameArtists methode die we eerder hebben gemaakt. Als de artiesten hetzelfde zijn, verwijderen we de tekst van het detailtolabel van de cel, maar als de artiesten anders zijn en de track een artiest bevat, stellen we de tekst van het detailTextLabel in op de artiest van die track.

Eindelijk moeten we de klasse van onze tabelweergave-controller bijwerken, dus open het storyboard, selecteer de tabelview-controller die we in deze tutorial hebben gemaakt, open Identity Inspector en verander de klasse in "AlbumViewController".

Nu we onze cellen hebben gevuld met de informatie en liedjes, denk ik dat dit een goed moment is om onze app te testen. Klik Build and Run om de app te testen. Als u naar het tabblad albums gaat en een album selecteert, ziet u een tabelweergave met een albumafbeelding, wat informatie over het album en natuurlijk de nummers in dat album.


Stap 4: speel wat muziek

Nu we een coole app hebben gemaakt die onze nummers en albums laat zien, zou het fijn zijn als onze muziekspeler deze nummers en albums daadwerkelijk zou kunnen spelen. Open het storyboard en sleep een weergavecontroller van de objectbibliotheek naar het canvas. We gaan deze View Controller gebruiken in de volgende tutorial om het nu spelende nummer te laten zien, maar we hebben de segues al nodig om de tracks af te spelen. CTRL-sleep vanuit de tweede cel in de Table View Controller die we in deze tutorial hebben gemaakt en selecteer "push" onder de sectie "Selection Segue" in het pop-upmenu. Doe nu hetzelfde voor de cel in de controller voor nummerweergave.

Open SongsViewController.m en voeg de volgende methode toe:

 - (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) afzender MPMediaQuery * songsQuery = [MPMediaQuery songsQuery]; NSArray * songs = [songsQuery items]; int selectedIndex = [[self.tableBekijk indexPathForSelectedRow] rij]; MPMediaItem * selectedItem = [[songs objectAtIndex: selectedIndex] representativeItem]; MPMusicPlayerController * musicPlayer = [MPMusicPlayerController iPodMusicPlayer]; [musicPlayer setQueueWithItemCollection: [MPMediaItemCollection collectionWithItems: [songsQuery items]]]; [musicPlayer setNowPlayingItem: selectedItem]; [musicPlayer play]; 

We hebben deze methode eerder in deze tutorial gebruikt, maar deze keer gebruiken we het om een ​​geselecteerde track af te spelen. Eerst maken we een vraag voor onze liedjes en plaatsen we de items in een array. Vervolgens krijgen we een MPMediaItem van de array die we hebben gemaakt. We gebruikten dezelfde index als de rij die we hebben geselecteerd, dus we kunnen dit MPMediaItem verderop in deze methode gebruiken om het nu spelende item bij te werken. Daarna maken we een MPMusicPlayerController-object en stellen dit in op een iPodMusicPlayer. Dit betekent dat onze app de iPod-status deelt en als we onze app afsluiten, zal de muziek blijven spelen. Vervolgens updaten we de wachtrij van de muziekspeler naar de items van de query en stellen we het nu afgespeelde item in op het MPMediaItem dat we eerder in deze methode hebben gemaakt. Eindelijk beginnen we de muziek te spelen.

Open nu AlbumViewController.m en voeg de volgende methode toe:

 - (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) afzender MPMediaQuery * albumQuery = [MPMediaQuery albumsQuery]; MPMediaPropertyPredicate * albumPredicate = [MPMediaPropertyPredicate predicateWithValue: albumTitle forProperty: MPMediaItemPropertyAlbumTitle]; [albumQuery addFilterPredicate: albumPredicate]; NSArray * albumTracks = [albumQuery-items]; int selectedIndex = [[self.tableBekijk indexPathForSelectedRow] rij]; MPMediaItem * selectedItem = [[albumTracks objectAtIndex: selectedIndex-1] representativeItem]; MPMusicPlayerController * musicPlayer = [MPMusicPlayerController iPodMusicPlayer]; [musicPlayer setQueueWithItemCollection: [MPMediaItemCollection collectionWithItems: [albumQuery items]]]; [musicPlayer setNowPlayingItem: selectedItem]; [musicPlayer play]; 

Hier doen we eigenlijk hetzelfde als in de methode die we hebben gemaakt in de SongsViewController.m, maar we hebben de wachtrij van de muziekspeler ingesteld op het geselecteerde album.

Nu kan onze app de nummers afspelen, klik op Build & Run om deze app te testen!


Conclusie

In dit tweede deel van de serie over het bouwen van een muziekspeler hebben we besproken hoe je een aangepaste cel kunt maken voor een tableview met een storyboard, hoe je een MPMediaPropertyPredicate kunt gebruiken en hoe je de nummers en albums kunt afspelen die we in onze app laten zien. In het volgende en laatste deel van de serie zullen we het nu spelende scherm maken en een aangepast interfaceontwerp maken voor onze app.