在iOS上使用Swift从短网址获取完整的URL

3

给定一个短网址 https://itun.es/us/JB7h_,如何将其扩展为完整的网址?例如 https://music.apple.com/us/album/blackstar/1059043043


2
你可能需要添加一些澄清,说明这是一个问答式的问题,以免被关闭为过于宽泛。 - Jojodmo
2个回答

9

Extension

extension URL {
   func getExpandedURL() async throws -> Result<URL, Error> {
       var request = URLRequest(url: self)
       request.httpMethod = "HEAD"
       
       let (_, response) = try await URLSession.shared.data(for: request)
       
       guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
           throw URLError.unableToExpand
       }
       
       if let expandedURL = response.url {
           return .success(expandedURL)
       } else {
           throw URLError.unableToExpand
       }
   }
    
    enum URLError: Error {
        case unableToExpand
    }
}

简陋的演示

struct ContentView: View {
    let shortURL = URL(string: "https://itun.es/us/JB7h_")
    @State var expandedURLResult: Result<URL, Error>?
    
    var body: some View {
        Form {
            Section("Short URL") {
                Text(shortURL?.description ?? "")
            }
            
            Section("Long URL") {
                switch expandedURLResult {
                    case .some(.success(let expandedURL)):
                        Text(expandedURL.description)
                    case .none:
                        Text("Waiting")
                    case .some(.failure(let error)):
                        Text(error.localizedDescription)
                }
            }
        }
        .task {
            do {
                expandedURLResult = try await shortURL?.getExpandedURL()
            } catch {
                expandedURLResult = .failure(error)
            }
        }
    }
}

enter image description here


1
这个完成处理程序的使用方式不正确,因为在错误情况下它从未被调用。 - Alexander
升级并添加了错误处理支持。 - Zelko

8
您将在NSURLResponse中收到最终解析的URL:response.URL
您还应该确保使用HTTP HEAD方法,以避免下载不必要的数据(因为您不关心资源主体)。

更新至Swift 4.2:

extension URL {
func resolveWithCompletionHandler(completion: @escaping (URL) -> Void) {
    let originalURL = self
    var req = URLRequest(url: originalURL)
    req.httpMethod = "HEAD"

    URLSession.shared.dataTask(with: req) { body, response, error in
        completion(response?.url ?? originalURL)
        }.resume()
}

旧版Swift:

extension NSURL
{
    func resolveWithCompletionHandler(completion: NSURL -> Void)
    {
        let originalURL = self
        let req = NSMutableURLRequest(URL: originalURL)
        req.HTTPMethod = "HEAD"

        NSURLSession.sharedSession().dataTaskWithRequest(req) { body, response, error in
            completion(response?.URL ?? originalURL)
        }.resume()
    }
}

// Example:
NSURL(string: "https://itun.es/us/JB7h_")!.resolveWithCompletionHandler {
    print("resolved to \($0)")  // prints https://itunes.apple.com/us/album/blackstar/id1059043043
}

好的,它可以工作,但是,你如何取消任务? - Kyle KIM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接