Url

URL

Intro

All things URL related in Swift.

Syntax

guard let url = URL(string: playable.uri),
              (url.host != nil) else {
            throw CustomError(uri: playable.uri)
}

URL Components

Constructing URLs using URL Components is much nicer and lets us have preconditionFailure in guard statements.

public func createSignUpURL(matching clientID: String = "clientID") -> URL {
    var components = URLComponents()
    components.scheme = "https"
    components.host = "qa1.qa.drive.com"
    components.path = "/#/sync"
    components.queryItems = [
    URLQueryItem(name: "client_id", value: clientID)
    ]
    let finalURL = components.string?.removingPercentEncoding ?? "https://qa1.qa.drive.com/#/sync?client_id=clientID"
    
    return URL(string: finalURL)!
}

Source swift by sundell

var url: URL {
    var components = URLComponents()
    components.scheme = "https"
    components.host = "api.myapp.com"
    components.path = "/" + path
    components.queryItems = queryItems

    guard let url = components.url else {
        preconditionFailure(
            "Invalid URL components: \(components)"
        )
    }

    return url
}

URLQueryItem

let searchTerm = "obi wan kenobi"
let format = "wookiee"

var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "swapi.co"
urlComponents.path = "/api/people"
urlComponents.queryItems = [
   URLQueryItem(name: "search", value: searchTerm),
   URLQueryItem(name: "format", value: format)
]

print(urlComponents.url?.absoluteString) 
// https://swapi.co/api/people?search=obi%20wan%20kenobi&format=wookie

Reference code from this link
building-safe-url-in-swift-using-urlcomponents-and-urlqueryitem

building-urls-with-urlqueryitem-in-swift

URL Encoding

Spaces -> percent encoding -> %20

let urlEncoded = value.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
let url = "http://www.example.com/?name=\(urlEncoded!)"

Adding base path

let category = "swift"
let baseURL = URL(string: "https://www.avanderlee.com")!
let blogURL = URL(string: category, relativeTo: baseURL)!
print(blogURL) // Prints: swift -- https://www.avanderlee.com
print(blogURL.absoluteString) 
// Prints: https://www.avanderlee.com/swift

ASCII to URL encoding
eso org table

File Path | FileManager API

Path of the file on system.

let url = URL(fileURLWithPath: path)

FileManager API

let folderURL = try FileManager.default.url(
            for: .documentDirectory,
            in: .userDomainMask,
            appropriateFor: nil,
            create: false
        )

apple doc | File system programming guide

Validation

Checking if URL is valid form

// Swift 5
func verifyUrl (urlString: String?) -> Bool {
    if let urlString = urlString {
        if let url = NSURL(string: urlString) {
            return UIApplication.shared.canOpenURL(url as URL)
        }
    }
    return false
}

SO | how-to-check-validity-of-url-in-swift

guard let url = URL(string: "http://www.google.com") else {
  return //be safe
}

if #available(iOS 10.0, *) {
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
    UIApplication.shared.openURL(url)
}

SO | how-to-open-an-url-in-swift

apple dev | url open

Caveats

One of the Trakt TV Api I needed to use addValue instead of setValue Spent like 20 mins wondering why it is failing for me on VisionOS & Xcode 15 Beta 6.

Stack overflow and internet was not helpful stating to restart the simulator and Xcode beta issues of some kind.

var urlRequest = URLRequest(url: url)

urlRequest.setValue("Content-Type", forHTTPHeaderField: "application/json")

urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")

Probably something related to adding it incrementally ? with addValue it works. Is it a Trakt TV API issue ? or maybe the async await API for URLSession.shared.data(urlRequest:) recommends this way of adding them content headers values to URLRequest.

Download Task

let config = URLSessionConfiguration.background(withIdentifier: "com.example.DownloadTaskExample.background")

let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())

let url = URL(string: "https://example.com/example.pdf")!
let task = session.downloadTask(with: url)
task.resume()

Downloading files in background with URLSessionDownloadTask

Diff between URI URN URL

A URI can be further classified as a locator, a name, or both. The term "Uniform Resource Locator" (URL) refers to the subset of URIs that, in addition to identifying a resource, provide a means of locating the resource by describing its primary access mechanism (e.g., its network "location"). The term "Uniform Resource Name" (URN) has been used historically to refer to both URIs under the "urn" scheme [RFC2141], which are required to remain globally unique and persistent even when the resource ceases to exist or becomes unavailable, and to any other URI with the properties of a name.

So all URLs are URIs, and all URNs are URIs - but URNs and URLs are different, so you can't say that all URIs are URLs.

SO | reference ^

Reference

A Comprehensive Guide to URLs in Swift and SwiftUI

apple dev | url components

avanderlee | URL components

swift by sundell | Managing URLs and endpoints

swift by sundell | constructing-urls-in-swift