Mapping XML to Swift Types

This is all we need to do to download data from the network. Not bad, right? Problem is “data” is all we have. Literally, we’ve got a Data object that’s about 100 KB. How is this going to do us any good?

What we need to do now is to figure out what parts of this data are useful for our app, and then after that, we can figure out how to get those parts out.

If we look at that String we made from the data, we can clearly see a structure:

  • There are a number of tags at the beginning of the file that describe the podcast itself: its title; a link to the podcast’s home page; some iTunes-specific metadata like itunes:image and itunes:author; and so on.

  • After this, there is a series of item tags, each of which describes one episode. An item includes a title, more iTunes-unique tags like itunes:duration and itunes:explicit, and, most importantly, an enclosure tag that provides the URL of the audio, its MIME type (usually audio/mpeg), and a file duration.

Not everything in the feed is going to be useful to our app, even if we were making a really elaborate podcast client. Moreover, the current format—a single 100 KB Data object—is totally inconvenient for our application. We may be able to turn it into a String, but we’re not going to search through a monster string every time we want to do something with the data.

We need to figure out what parts of this data are useful to our app, and then parse the XML to provide us with just that data, as easier-to-use Swift types.

What would be good to have? Let’s start with the feed first, before we get individual episodes. The useful parts of the metadata—things we can imagine showing in a UI—include the title, description, author, artwork, and a link to the podcast’s home page.

OK, let’s make a Swift type for that. In the project navigator, use New File (N) to create another new file, using the plain “Swift File” template. Name the file PodcastFeed.swift. We will only need to set these values once, while we’re parsing them, so this type can be a struct, rather than a class that would be better suited for maintaining state.

Write the PodcastFeed type as follows:

 import​ ​Foundation
 
 struct​ ​PodcastFeed​ {
 
 var​ title : ​String​?
 var​ link : ​URL​?
 var​ description : ​String​?
 var​ iTunesAuthor : ​String​?
 var​ iTunesImageURL : ​URL​?
 
 }

We’ve made all the members optional. Parsing will take a while, and we wouldn’t want to have to hold on to all of these values somewhere else until we’re ready to do an “init everything all at once“ type of setup, which we’d have to do if they were concrete types. Besides, some podcasts might not populate some of these tags, particularly the iTunes-specific ones.

While we’re at it, let’s think of what we would want for a podcast episode. This will be both something we show in a list of episodes, and the object we pass to our player. So it obviously needs the URL from the enclosure, along with a title. Maybe the other fields will be useful later (like the publication date for sorting, or the duration if we’re going to show that in the player UI). But for now, let’s keep things really simple, and add more later if we need to. Create PodcastEpisode.swift, and write it like this:

 import​ ​Foundation
 
 struct​ ​PodcastEpisode​ {
 
 var​ title : ​String​?
 var​ enclosureURL : ​URL​?
 var​ iTunesDuration : ​String​?
 var​ iTunesImageURL : ​URL​?
 
 }

Now we know what we’re going to parse from the XML data. The big question is…how?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset