Currently, I want to write a APIEndpoint class with contains all of my APIs. I have a variable baseURL and I want to use it for the remains. But when I tried to write it as below, it comes to error.
class APIEndpoint {
static let shared = APIEndpoint()
static let baseURL = "https://13.251.102.94:5001/api/"
static let login = URL(string: baseURL + "auth/customer/login")!
}
My function
func performLogin () {
var request = URLRequest(url: APIEndpoint.shared.login)
request.httpMethod = "POST"
let json: [String: String] = ["username": self.name, "password": self.password]
request.httpBody = try? JSONSerialization.data(withJSONObject: json)
Network.shared.session.dataTask(with: request) { (data, response, err) in
guard let data = data else { return }
print(JSON(data)["data"])
}.resume()
}
Error:
Static member 'login' cannot be used on instance of type 'APIEndpoint'
in line: var request = URLRequest(url: APIEndpoint.shared.login)
login and baseURL are static members of class APIEndpoint. You're already could use them as APIEndpoint.login and APIEndpoint.baseURL. In your case you should write
var request = URLRequest(url: APIEndpoint.login)
I have a struct that I am using to call out to the iTunes API. But when ever I run it myURL variable is never getting set, it's always nil. Not sure what I am doing wrong:
let myDefaultSession = URLSession(configuration: .default)
var myURL: URL?
var myDataTask: URLSessionTask?
struct APIManager {
func getJSON(strURL: String) {
myURL = URL(string: strURL)
var dictReturn: Dictionary<String, Any> = [:]
//cancel data task if it is running
myDataTask?.cancel()
print(myURL!) //<----Always nil
}
}
Here's the string:
"https://itunes.apple.com/search?media=music&entity=song&term=The Chain"
You´re getting nil because the URL contains a space. You need to encode the string first and then convert it to an URL.
func getJSON(strURL: String) {
if let encoded = strURL.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed),
let myURL = URL(string: encoded) {
print(myURL)
}
var dictReturn:Dictionary<String, Any> = [:]
//cancel data task if it is running
myDataTask?.cancel()
}
URL will be:
https://itunes.apple.com/search?media=music&entity=song&term=The%20Chain
I have the following URL string:
eventid=VSl4WcedBNbjqgXe7bzQCw×tamp=1501047125&status=ok&ldpj=-23&author=Al+Jazeera+Arabic+قناة+الجزيرة&ptchn=fiwzLy-8yKzIbsmZTzxDgw&live_chunk_readahead=3&video_id=fN2sEo7hq-E&allow_ratings=0&allow_embed=1&token=vThp8hY3AuC-jibt_jf7TEzWnuqUY7oImICFXKxkWbM=&plid=AAVVMcSvP1Tr6SGM&partnerid=27&of=sjG7v9N-R2P9uySMx2Af7Q&live_default_broadcast=1&watermark=,https://s.ytimg.com/yts/img/watermark/youtube_watermark-vflHX6b6E.png,https://s.ytimg.com/yts/img/watermark/youtube_hd_watermark-vflAzLcD6.png&streaminglib_module=1&live_storyboard_spec=https://i.ytimg.com/sb/fN2sEo7hq-E/storyboard_live_60_3x3_b0/M$M.jpg?rs=AOn4CLBoEYL8Dt3Yf1HhjHlpNUAc4jqmSg#106#60#3#3&video_verticals=[881,+397]&csn=VSl4WcedBNbjqgXe7bzQCw&muted=0&length_seconds=1800&hlsdvr=1&videostats_playback_base_url=https://s.youtube.com&title=Al+Jazeera+Arabic+Live+Stream+HD-+البث+الحي+لقناة+الجزيرة+الإخبارية+بجودة+عالية&ptk=aljazeera&iurl=https://i.ytimg.com/vi/fN2sEo7hq-E/hqdefault_live.jpg&vm=CAEQARgE&hlsvp=https://manifest.googlevideo.com/api/manifest/hls_variant/gcr/us/signature/26ADA228BD5549EC76852E925945A6EDBD8A78A9.268E76E7A0831E0DB3C36670FCA24805B0F9AD94/requiressl/yes/source/yt_live_broadcast/key/yt6/ip/72.239.175.191/ipbits/0/maudio/1/playlist_type/DVR/itag/0/expire/1501068725/sparams/gcr,go,id,ip,ipbits,itag,maudio,playlist_type,requiressl,source,expire/go/1/id/fN2sEo7hq-E.0/file/index.m3u8&pltype=contentlive&cl=162900125&iurlmq=https://i.ytimg.com/vi/fN2sEo7hq-E/mqdefault_live.jpg&enable_cardio_before_playback=1&no_get_video_log=1&short_view_count_text=3M+views&avg_rating=4.24240619416&fexp=9422596,9431012,9434289,9441392,9446364,9449243,9457141,9460072,9461821,9463594,9464546,9465833,9466793,9466795,9466797,9466851,9467217,9468797,9468799,9468805,9471755,9475953,9477113,9477691,9478524,9478670,9480034,9480475,9480535,9480795,9481684,9482647,9483080,9484209,9484514,9484643,9484706,9485999&keywords=al+jazeera+tv,al+jazeera+Arabic,الجزيره,اخبار,خبر,free+tv+channels,aljazira,اخبار+الجزيرة,الاسكندرية,الجزيرة+مصر+مباشر,al+jazeera+english+live,aljazeera+tv+live,داعش,العراق,اخبار+العراق,اخبار+سوريا,دمشق,اخبار+مصر,سوريا,بشار+الاسد,عاجل+ليبيا,عاجل,الحصاد,النشرة,نشرة,الاخبار,الاهرام,الوفد,الجزيرة+مباشر,الجمهورية,syria+news,البث+الحي,البث+الحي+لقناة+الجزيرة,جودة+عالية,hd&idpj=-4&c=WEB&innertube_client_version=1.20170718&account_playback_token=QUFFLUhqa3NJenBCUUNnZnBtMHdOb3FLSWE0cG9qQkZBZ3xBQ3Jtc0ttYkdZeEI0TExmQWo1RldLQlFZSGtLTE1wcEJGamNNZnE4UlhDaUpfRGtvSG5WbG1KUHNvbk44T2dtM2NRb0NwWmNZaU9sdGc2MTY3QUg3SldKTmtxOWNzMjVfZ0R5VDYwM1E3RDVQQnNHTU12OVphSQ==&iv3_module=1&iurlhq=https://i.ytimg.com/vi/fN2sEo7hq-E/hqdefault_live.jpg&dashmpd=https://manifest.googlevideo.com/api/manifest/dash/hfr/1/as/fmp4_audio_clear,fmp4_sd_hd_clear/source/yt_live_broadcast/key/yt6/ip/72.239.175.191/expire/1501068725/ipbits/0/signature/D9AC8668BF9CF6B884B618938C9823515B17D8F2.1FDA7E07B2B55FBCCF80C654BA9E0A1F9A48F589/playlist_type/DVR/itag/0/requiressl/yes/sparams/as,gcr,hfr,id,ip,ipbits,itag,playlist_type,requiressl,source,expire/gcr/us/id/fN2sEo7hq-E.0&ypc_ad_indicator=4&ucid=UCfiwzLy-8yKzIbsmZTzxDgw&iv_load_policy=1&iurlmaxres=https://i.ytimg.com/vi/fN2sEo7hq-E/maxresdefault_live.jpg&oid=o0grDQo8XcVLrPz5jByaaQ&iv_invideo_url=https://www.youtube.com/annotations_invideo?cap_hist=1&video_id=fN2sEo7hq-E&ei=VSl4WcedBNbjqgXe7bzQCw&cver=1.20170724&live_playback=1&fmt_list=&auth_timeout=21600000&thumbnail_url=https://i.ytimg.com/vi/fN2sEo7hq-E/default.jpg&root_ve_type=&has_cc=False&is_listed=1&url_encoded_fmt_stream_map=&fresca_module=1&enable_cardio=1&fresca_preroll=1&ypc_license_checker_module=1&iurlsd=https://i.ytimg.com/vi/fN2sEo7hq-E/sddefault_live.jpg&remarketing_url=https://googleads.g.doubleclick.net/pagead/viewthroughconversion/962985656/?backend=player_vars&cname=1&cver=AS3&data=backend%3Dplayer_vars%3Bcname%3D1%3Bcver%3DAS3%3Bptype%3Dview%3Btype%3Dview%3Butuid%3DfiwzLy-8yKzIbsmZTzxDgw%3Butvid%3DfN2sEo7hq-E&foc_id=fiwzLy-8yKzIbsmZTzxDgw&label=followon_view&ptype=view&delay=5&tmi=1&view_count=3025044&use_cipher_signature=False
How do I go about extracting the m3u8 url from the above string? I want it to look like this once done:
hlsvp=https://manifest.googlevideo.com/api/manifest/hls_variant/gcr/us/signature/26ADA228BD5549EC76852E925945A6EDBD8A78A9.268E76E7A0831E0DB3C36670FCA24805B0F9AD94/requiressl/yes/source/yt_live_broadcast/key/yt6/ip/72.239.175.191/ipbits/0/maudio/1/playlist_type/DVR/itag/0/expire/1501068725/sparams/gcr,go,id,ip,ipbits,itag,maudio,playlist_type,requiressl,source,expire/go/1/id/fN2sEo7hq-E.0/file/index.m3u8
I have the following code that stops at this point, as below:
extension ViewController {
/*https://stackoverflow.com/questions/35608686/how-can-i-get-the-actual-video-url-of-a-youtube-live-stream*/
func get_youtube_link(videoID: String) {
let url: URL = URL(string: "https://www.youtube.com/get_video_info?&video_id=fN2sEo7hq-E&el=info&ps=default&eurl=&gl=US&hl=en")!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
// grab the URL returned by YouTube, which is a URL with many parameters
let feedback = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
// convert NSString to String
var newString = String(feedback!)
//https://www.uraimo.com/swiftbites/swift-url-encoding/
newString = newString.removingPercentEncoding!
newString = newString.replacingOccurrences(of: "%2C", with: ",")
print(newString)
})
task.resume()
}
}
This is YouTube's web query data received in RAW format:
partnerid=27&root_ve_type=&c=WEB&iurl=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fhqdefault_live.jpg&of=GC6OCn1lTVgpgJyrp2hYjw&hlsdvr=1&eventid=FEx5We_CJMut4QSH_5OYCw&ypc_license_checker_module=1&auth_timeout=21600000&videostats_playback_base_url=https%3A%2F%2Fs.youtube.com&token=WIs368zOOjdA6jb7Wo5HIeCUIjDqF6aTm40Qf9Lm8xY%3D&csn=FEx5We_CJMut4QSH_5OYCw&plid=AAVVQxkmPLDdDSm-&allow_ratings=1&live_playback=1&live_default_broadcast=1&fexp=9422596%2C9431012%2C9434289%2C9441386%2C9446364%2C9449243%2C9457141%2C9460072%2C9461821%2C9463594%2C9464546%2C9465833%2C9466793%2C9466795%2C9466797%2C9466851%2C9467217%2C9468797%2C9468799%2C9468805%2C9471755%2C9475953%2C9477113%2C9477691%2C9478524%2C9478670%2C9480034%2C9480475%2C9480535%2C9480795%2C9481684%2C9482647%2C9483080%2C9483701%2C9484209%2C9484514%2C9484643%2C9484706%2C9485999&fresca_module=1&idpj=-7&delay=5&iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fmqdefault_live.jpg&avg_rating=4.53108348135&ypc_ad_indicator=4&remarketing_url=https%3A%2F%2Fgoogleads.g.doubleclick.net%2Fpagead%2Fviewthroughconversion%2F962985656%2F%3Fbackend%3Dplayer_vars%26cname%3D1%26cver%3DAS3%26foc_id%3DSrZ3UV4jOidv8ppoVuvW9Q%26label%3Dfollowon_view%26ptype%3Dno_rmkt&innertube_client_version=1.20170718&video_verticals=%5B16%2C+396%5D&ldpj=-27&title=euronews+LIVE&tmi=1&watermark=%2Chttps%3A%2F%2Fs.ytimg.com%2Fyts%2Fimg%2Fwatermark%2Fyoutube_watermark-vflHX6b6E.png%2Chttps%3A%2F%2Fs.ytimg.com%2Fyts%2Fimg%2Fwatermark%2Fyoutube_hd_watermark-vflAzLcD6.png&cver=1.20170725&iv3_module=1&no_get_video_log=1&has_cc=False&thumbnail_url=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fdefault.jpg&iv_invideo_url=https%3A%2F%2Fwww.youtube.com%2Fannotations_invideo%3Fcap_hist%3D1%26video_id%3DVmxIA8L3Xz8%26ei%3DFEx5We_CJMut4QSH_5OYCw&author=euronews+%28in+English%29&status=ok&ptk=youtube_none&fresca_preroll=1&iurlsd=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fsddefault_live.jpg&length_seconds=1800&view_count=159557&is_listed=1&vm=CAEQABgE&enable_cardio_before_playback=1&dashmpd=https%3A%2F%2Fmanifest.googlevideo.com%2Fapi%2Fmanifest%2Fdash%2Fas%2Ffmp4_audio_clear%252Cfmp4_sd_hd_clear%2Fgcr%2Fus%2Fexpire%2F1501143156%2Fsignature%2F7779193FA964EC075A94C62E6720B2380AEE39A0.B546BFA286574BA5D7BE116159ACC45130650938%2Fkey%2Fyt6%2Fip%2F72.239.175.191%2Fplaylist_type%2FDVR%2Fitag%2F0%2Fipbits%2F0%2Fsource%2Fyt_live_broadcast%2Frequiressl%2Fyes%2Fhfr%2F1%2Fsparams%2Fas%252Cgcr%252Chfr%252Cid%252Cip%252Cipbits%252Citag%252Cplaylist_type%252Crequiressl%252Csource%252Cexpire%2Fid%2FVmxIA8L3Xz8.0&hlsvp=https%3A%2F%2Fmanifest.googlevideo.com%2Fapi%2Fmanifest%2Fhls_variant%2Fgcr%2Fus%2Fkey%2Fyt6%2Fip%2F72.239.175.191%2Fplaylist_type%2FDVR%2Fexpire%2F1501143156%2Fitag%2F0%2Fsource%2Fyt_live_broadcast%2Fmaudio%2F1%2Fid%2FVmxIA8L3Xz8.0%2Fsparams%2Fgcr%252Cgo%252Cid%252Cip%252Cipbits%252Citag%252Cmaudio%252Cplaylist_type%252Crequiressl%252Csource%252Cexpire%2Fipbits%2F0%2Fgo%2F1%2Frequiressl%2Fyes%2Fsignature%2FB225396C754E6783728F71F0C1AD4CFE9AFC3839.B2C6E2FFCB07B136D4AECFA5A8F001DFEC084543%2Ffile%2Findex.m3u8×tamp=1501121556&iurlmaxres=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fmaxresdefault_live.jpg&use_cipher_signature=False&live_chunk_readahead=3&iv_load_policy=1&live_storyboard_spec=https%3A%2F%2Fi.ytimg.com%2Fsb%2FVmxIA8L3Xz8%2Fstoryboard_live_60_3x3_b0%2FM%24M.jpg%3Frs%3DAOn4CLBjUwFPDoNQCv904oDJpmFEM5xg7g%23106%2360%233%233&ucid=UCSrZ3UV4jOidv8ppoVuvW9Q&allow_embed=1&pltype=contentugclive&short_view_count_text=159K+views&fmt_list=&keywords=&enable_cardio=1&video_id=VmxIA8L3Xz8&streaminglib_module=1&url_encoded_fmt_stream_map=&cl=162900125&account_playback_token=QUFFLUhqbl9LME8tdzdIT1VJaG1qRk1VZ3U1OFNnMW1PZ3xBQ3Jtc0ttY0dMZWZJdGtkUVNqTjlFWHpubjE2Rjg5OGxlU21fUndLa3Y0THoyMWpGa3ZXWDN2R3JkR1JHS2tEcm51OXhTbTFqYlNGTHVKY1hrOWllcFlHRU9NNHFZTjZNNGRZQjZ1eFc2VGxjMHpScWFDWnUxdw%3D%3D&muted=0&iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fhqdefault_live.jpg
So, I found the answer. I'll post it just incase someone needs it.
Here you go: Extract the M3U8 video link from a YouTube live channel in Swift 3
I'd like to point out that Code Different's answer is more elequent than mine. Give them both a try and see what fits your project needs :)
//
// EXT_youtube_JSON.swift
// YoutubeStreamURL
//
// Created by Haitham Alkibsi on 7/25/17.
// Copyright © 2017 Haitham Al-Kibsi. All rights reserved.
//
import Foundation
extension ViewController {
/* https://stackoverflow.com/questions/35608686/how-can-i-get-the-actual-video-url-of-a-youtube-live-stream */
func downloadJSON_youtube(videoID: String) {
let url: URL = URL(string: "https://www.youtube.com/get_video_info?&video_id=\(videoID)&el=info&ps=default&eurl=&gl=US&hl=en")!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
// grab the URL returned by YouTube, which has many parameters
var youtubeReply = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!
// remove percent encoding
//https://www.uraimo.com/swiftbites/swift-url-encoding/
youtubeReply = youtubeReply.removingPercentEncoding!
youtubeReply = youtubeReply.replacingOccurrences(of: "%2C", with: ",")
//https://www.dotnetperls.com/find-swift
let firstResult = youtubeReply.range(of: "hlsvp=", options: NSString.CompareOptions.literal, range: youtubeReply.startIndex..<youtubeReply.endIndex, locale: nil)
if let range = firstResult {
// Start of range of found string.
let start = range.lowerBound
// Display string starting at first index.
var firstExtraction = youtubeReply[start..<youtubeReply.endIndex]
firstExtraction = firstExtraction.chopPrefix(6)
let secondResult = firstExtraction.range(of: ".m3u8", options: NSString.CompareOptions.literal, range: firstExtraction.startIndex..<firstExtraction.endIndex, locale: nil)
if let range2 = secondResult {
let start = range2.lowerBound
let secondExtraction = firstExtraction[firstExtraction.startIndex..<start]
let m3u8_URL = secondExtraction + ".m3u8"
print(m3u8_URL)
}
}
})
task.resume()
}
}
//https://stackoverflow.com/questions/28445917/what-is-the-most-succinct-way-to-remove-the-first-character-from-a-string-in-swi
extension String {
func chopPrefix(_ count: Int = 1) -> String {
return substring(from: index(startIndex, offsetBy: count))
}
func chopSuffix(_ count: Int = 1) -> String {
return substring(to: index(endIndex, offsetBy: -count))
}
}
Your sample data is tortuously long but did not help clarify your question in any way. It's better to come up with Minimum, Complete and Verifiable example.
Now to your question, use URLComponents to extract data from the URL:
// Assuming feedback is what you get back from YouTube
let feedback = "partnerid=27&root_ve_type=&c=WEB&iurl=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fhqdefault_live.jpg&of=GC6OCn1lTVgpgJyrp2hYjw&hlsdvr=1&eventid=FEx5We_CJMut4QSH_5OYCw&ypc_license_checker_module=1&auth_timeout=21600000&videostats_playback_base_url=https%3A%2F%2Fs.youtube.com&token=WIs368zOOjdA6jb7Wo5HIeCUIjDqF6aTm40Qf9Lm8xY%3D&csn=FEx5We_CJMut4QSH_5OYCw&plid=AAVVQxkmPLDdDSm-&allow_ratings=1&live_playback=1&live_default_broadcast=1&fexp=9422596%2C9431012%2C9434289%2C9441386%2C9446364%2C9449243%2C9457141%2C9460072%2C9461821%2C9463594%2C9464546%2C9465833%2C9466793%2C9466795%2C9466797%2C9466851%2C9467217%2C9468797%2C9468799%2C9468805%2C9471755%2C9475953%2C9477113%2C9477691%2C9478524%2C9478670%2C9480034%2C9480475%2C9480535%2C9480795%2C9481684%2C9482647%2C9483080%2C9483701%2C9484209%2C9484514%2C9484643%2C9484706%2C9485999&fresca_module=1&idpj=-7&delay=5&iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fmqdefault_live.jpg&avg_rating=4.53108348135&ypc_ad_indicator=4&remarketing_url=https%3A%2F%2Fgoogleads.g.doubleclick.net%2Fpagead%2Fviewthroughconversion%2F962985656%2F%3Fbackend%3Dplayer_vars%26cname%3D1%26cver%3DAS3%26foc_id%3DSrZ3UV4jOidv8ppoVuvW9Q%26label%3Dfollowon_view%26ptype%3Dno_rmkt&innertube_client_version=1.20170718&video_verticals=%5B16%2C+396%5D&ldpj=-27&title=euronews+LIVE&tmi=1&watermark=%2Chttps%3A%2F%2Fs.ytimg.com%2Fyts%2Fimg%2Fwatermark%2Fyoutube_watermark-vflHX6b6E.png%2Chttps%3A%2F%2Fs.ytimg.com%2Fyts%2Fimg%2Fwatermark%2Fyoutube_hd_watermark-vflAzLcD6.png&cver=1.20170725&iv3_module=1&no_get_video_log=1&has_cc=False&thumbnail_url=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fdefault.jpg&iv_invideo_url=https%3A%2F%2Fwww.youtube.com%2Fannotations_invideo%3Fcap_hist%3D1%26video_id%3DVmxIA8L3Xz8%26ei%3DFEx5We_CJMut4QSH_5OYCw&author=euronews+%28in+English%29&status=ok&ptk=youtube_none&fresca_preroll=1&iurlsd=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fsddefault_live.jpg&length_seconds=1800&view_count=159557&is_listed=1&vm=CAEQABgE&enable_cardio_before_playback=1&dashmpd=https%3A%2F%2Fmanifest.googlevideo.com%2Fapi%2Fmanifest%2Fdash%2Fas%2Ffmp4_audio_clear%252Cfmp4_sd_hd_clear%2Fgcr%2Fus%2Fexpire%2F1501143156%2Fsignature%2F7779193FA964EC075A94C62E6720B2380AEE39A0.B546BFA286574BA5D7BE116159ACC45130650938%2Fkey%2Fyt6%2Fip%2F72.239.175.191%2Fplaylist_type%2FDVR%2Fitag%2F0%2Fipbits%2F0%2Fsource%2Fyt_live_broadcast%2Frequiressl%2Fyes%2Fhfr%2F1%2Fsparams%2Fas%252Cgcr%252Chfr%252Cid%252Cip%252Cipbits%252Citag%252Cplaylist_type%252Crequiressl%252Csource%252Cexpire%2Fid%2FVmxIA8L3Xz8.0&hlsvp=https%3A%2F%2Fmanifest.googlevideo.com%2Fapi%2Fmanifest%2Fhls_variant%2Fgcr%2Fus%2Fkey%2Fyt6%2Fip%2F72.239.175.191%2Fplaylist_type%2FDVR%2Fexpire%2F1501143156%2Fitag%2F0%2Fsource%2Fyt_live_broadcast%2Fmaudio%2F1%2Fid%2FVmxIA8L3Xz8.0%2Fsparams%2Fgcr%252Cgo%252Cid%252Cip%252Cipbits%252Citag%252Cmaudio%252Cplaylist_type%252Crequiressl%252Csource%252Cexpire%2Fipbits%2F0%2Fgo%2F1%2Frequiressl%2Fyes%2Fsignature%2FB225396C754E6783728F71F0C1AD4CFE9AFC3839.B2C6E2FFCB07B136D4AECFA5A8F001DFEC084543%2Ffile%2Findex.m3u8×tamp=1501121556&iurlmaxres=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fmaxresdefault_live.jpg&use_cipher_signature=False&live_chunk_readahead=3&iv_load_policy=1&live_storyboard_spec=https%3A%2F%2Fi.ytimg.com%2Fsb%2FVmxIA8L3Xz8%2Fstoryboard_live_60_3x3_b0%2FM%24M.jpg%3Frs%3DAOn4CLBjUwFPDoNQCv904oDJpmFEM5xg7g%23106%2360%233%233&ucid=UCSrZ3UV4jOidv8ppoVuvW9Q&allow_embed=1&pltype=contentugclive&short_view_count_text=159K+views&fmt_list=&keywords=&enable_cardio=1&video_id=VmxIA8L3Xz8&streaminglib_module=1&url_encoded_fmt_stream_map=&cl=162900125&account_playback_token=QUFFLUhqbl9LME8tdzdIT1VJaG1qRk1VZ3U1OFNnMW1PZ3xBQ3Jtc0ttY0dMZWZJdGtkUVNqTjlFWHpubjE2Rjg5OGxlU21fUndLa3Y0THoyMWpGa3ZXWDN2R3JkR1JHS2tEcm51OXhTbTFqYlNGTHVKY1hrOWllcFlHRU9NNHFZTjZNNGRZQjZ1eFc2VGxjMHpScWFDWnUxdw%3D%3D&muted=0&iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FVmxIA8L3Xz8%2Fhqdefault_live.jpg"
let urlString = "https://www.youtube.com?" + feedback
let components = URLComponents(string: urlString)!
if let queryItems = components.queryItems,
let hlsvp = queryItems.first(where: { $0.name == "hlsvp" })
{
print(hlsvp.value!)
} else {
print("hlsvp not found")
}
So I have converted an NSURL to a String.
So if I println it looks like file:///Users/... etc.
Later I want this back as an NSURL so I try and convert it back as seen below, but I lose two of the forward slashes that appear in the string version above, that in turn breaks the code as the url is invalid.
Why is my conversion back to NSURL removing two forward slashes from the String I give it, and how can I convert back to the NSURL containing three forward slashes?
var urlstring: String = recordingsDictionaryArray[selectedRow]["path"] as String
println("the url string = \(urlstring)")
// looks like file:///Users/........etc
var url = NSURL.fileURLWithPath(urlstring)
println("the url = \(url!)")
// looks like file:/Users/......etc
In Swift 5, Swift 4 and Swift 3
To convert String to URL:
URL(string: String)
or,
URL.init(string: "yourURLString")
And to convert URL to String:
URL.absoluteString
The one below converts the 'contents' of the url to string
String(contentsOf: URL)
fileURLWithPath() is used to convert a plain file path (e.g. "/path/to/file") to an URL. Your urlString is a full URL string including the scheme, so you should use
let url = NSURL(string: urlstring)
to convert it back to NSURL. Example:
let urlstring = "file:///Users/Me/Desktop/Doc.txt"
let url = NSURL(string: urlstring)
println("the url = \(url!)")
// the url = file:///Users/Me/Desktop/Doc.txt
There is a nicer way of getting the string version of the path from the NSURL in Swift:
let path:String = url.path
2021 | SWIFT 5.1:
FOR LOCAL PATHS
String --> URL :
let url1 = URL(fileURLWithPath: "//Users/Me/Desktop/Doc.txt")
let url2 = URL(fileURLWithPath: "//Users/Me/Desktop", isDirectory: true)
// !!!!!NEVER DO THIS!!!!!!
let url3 = URL(string: "file:///Users/Me/Desktop/Doc.txt")!
// !!!!!NEVER DO THIS!!!!!!
URL --> String :
let a = String(describing: url1) // "file:////Users/Me/Desktop/Doc.txt"
let b = "\(url1)" // "file:////Users/Me/Desktop/Doc.txt"
let c = url1.absoluteString // "file:////Users/Me/Desktop/Doc.txt"
// Best solution in most cases
let d = url1.path // "/Users/Me/Desktop/Doc.txt"
FOR INTERNET URLs
String --> URL :
let url = URL(string: "https://stackoverflow.com/questions/27062454/converting-url-to-string-and-back-again")!
URL --> String :
url.absoluteString // https://stackoverflow.com/questions/27062454/converting-url-to-string-and-back-again
url.path // /questions/27062454/converting-url-to-string-and-back-again
NOTICE: pay attention to the url, it's optional and it can be nil.
You can wrap your url in the quote to convert it to a string. You can test it in the playground.
Update for Swift 5, Xcode 11:
import Foundation
let urlString = "http://ifconfig.me"
// string to url
let url = URL(string: urlString)
//url to string
let string = "\(url)"
// if you want the path without `file` schema
// let string = url.path
let url = URL(string: "URLSTRING HERE")
let anyvar = String(describing: url)
Swift 3 (forget about NSURL).
let fileName = "20-01-2017 22:47"
let folderString = "file:///var/mobile/someLongPath"
To make a URL out of a string:
let folder: URL? = Foundation.URL(string: folderString)
// Optional<URL>
// ▿ some : file:///var/mobile/someLongPath
If we want to add the filename. Note, that appendingPathComponent() adds the percent encoding automatically:
let folderWithFilename: URL? = folder?.appendingPathComponent(fileName)
// Optional<URL>
// ▿ some : file:///var/mobile/someLongPath/20-01-2017%2022:47
When we want to have String but without the root part (pay attention that percent encoding is removed automatically):
let folderWithFilename: String? = folderWithFilename.path
// ▿ Optional<String>
// - some : "/var/mobile/someLongPath/20-01-2017 22:47"
If we want to keep the root part we do this (but mind the percent encoding - it is not removed):
let folderWithFilenameAbsoluteString: String? = folderWithFilenameURL.absoluteString
// ▿ Optional<String>
// - some : "file:///var/mobile/someLongPath/20-01-2017%2022:47"
To manually add the percent encoding for a string:
let folderWithFilenameAndEncoding: String? = folderWithFilename.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
// ▿ Optional<String>
// - some : "/var/mobile/someLongPath/20-01-2017%2022:47"
To remove the percent encoding:
let folderWithFilenameAbsoluteStringNoEncodig: String? = folderWithFilenameAbsoluteString.removingPercentEncoding
// ▿ Optional<String>
// - some : "file:///var/mobile/someLongPath/20-01-2017 22:47"
The percent-encoding is important because URLs for network requests need them, while URLs to file system won't always work - it depends on the actual method that uses them. The caveat here is that they may be removed or added automatically, so better debug these conversions carefully.
Swift 3 version code:
let urlString = "file:///Users/Documents/Book/Note.txt"
let pathURL = URL(string: urlString)!
print("the url = " + pathURL.path)
Swift 5.
To convert a String to a URL:
let stringToURL = URL(string: "your-string")
To convert a URL to a String:
let urlToString = stringToURL?.absoluteString
Swift 3 used with UIWebViewDelegate shouldStartLoadWith
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let urlPath: String = (request.url?.absoluteString)!
print(urlPath)
if urlPath.characters.last == "#" {
return false
}else{
return true
}
}