Beginning Networking with URLSession

Sep 13 2022 · Swift 5.6, iOS 15, Xcode 13.4.1

Part 2: Download Data

11. Download Music

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 10. Priorities & Cache Policies Next episode: 12. Handle Errors

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 11. Download Music

URLSession - Apple Developer

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

URLSession contains many different tasks to preform a variety of functions.

import SwiftUI
class SongDownloader: ObservableObject {
  // MARK: Properties
  @Published var downloadLocation: URL?
  
  private let session: URLSession
  private let sessionConfiguration: URLSessionConfiguration
  
  // MARK: Initialization
  init() {

  }
  
  // MARK: Functions
}
self.sessionConfiguration = URLSessionConfiguration.default
self.session = URLSession(configuration: sessionConfiguration)
func downloadSong(at url: URL) async {
    
}
guard let (downloadURL, response) = try? await session.download(from: url) else {
  print("Error downloading song.")
  
  return
}
guard let httpResponse = response as? HTTPURLResponse,
    httpResponse.statusCode == 200
else {
  print("Invalid response code.")
  
  return
}
let fileManager = FileManager.default

guard let documentsPath = fileManager.urls(for: .documentDirectory,
                                           in: .userDomainMask).first
else {
  print("Song download failed.")
  
  return
}
let lastPathComponent = url.lastPathComponent
let destinationURL = documentsPath.appendingPathComponent(lastPathComponent)
do {
if fileManager.fileExists(atPath: destinationURL.path) {
  try fileManager.removeItem(at: destinationURL)
}
    
try fileManager.copyItem(at: downloadURL, to: destinationURL)
} catch {
  print("Failed to store the song.")
}
await MainActor.run {
  downloadLocation = destinationURL
}
@ObservedObject private var downloader: SongDownloader = SongDownloader()
private func downloadTapped() async {
  if downloader.downloadLocation == nil {
    guard let previewURL = musicItem.previewURL else {
      return
    }
      
    await downloader.downloadSong(at: previewURL)
  } else {
    playMusic = true
  }
}
Button(action: {
  Task {
    await downloadTapped()
  }
}) {
  Text(downloader.downloadLocation == nil ? "Download" : "Listen")
}
.sheet(isPresented: $playMusic) {
  AudioPlayer(songUrl: downloader.downloadLocation!)
}
@MainActor @State private var isDownloading: Bool = false
private func downloadTapped() async {
  if downloader.downloadLocation == nil {
    isDownloading = true        // THIS
      
    defer {                     // THIS
      isDownloading = false     // THIS
    }                           // THIS
      
    guard let previewURL = musicItem.previewURL else {
      return
    }
      
    await downloader.downloadSong(at: previewURL)
  } else {
    playMusic = true
  }
}
if isDownloading {
  Text("Downloading...")
} else {
  Text(downloader.downloadLocation == nil ? "Download" : "Listen")
}
.disabled(isDownloading)
if isDownloading {
  ProgressView()
}