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've reached locked video content where the transcript will be shown as obfuscated text.

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()
}