4

(XCode 6.3.2, Swift 1.2)
After researching the internet for the whole evening I already know that this can't be done that easily.
I simply want to get the video ID of a YouTube link. So the "ABCDE" in "https://www.youtube.com/watch?v=ABCDE"

What I got so far:

var url = "https://www.youtube.com/watch?v=ABCDE"
let characterToFind: Character = "="
let characterIndex = find(url, characterToFind)
println(characterIndex)
url.substringFromIndex(advance(url.startIndex, characterIndex))

Prinln outputs: Optional(31)
That's right but I can't use this because it's no index.

XCode also states for the last line: Missing argument for parameter #3 in call
I also don't know what the 3rd parameter of substringFromIndex should be.

Many thanks in advance!

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Pingu
  • 101
  • 2
  • 10

6 Answers6

4

You can use NSURL query property as follow:

Xcode 8.3.1 • Swift 3.1

let link = "https://www.youtube.com/watch?v=ABCDE"
if let videoID = URL(string: link)?.query?.components(separatedBy: "=").last {
    print(videoID) // "ABCDE"
}

Another option is to use URLComponents:

let link = "https://www.youtube.com/watch?v=ABCDE"
if let videoID = URLComponents(string: link)?.queryItems?.filter({$0.name == "v"}).first?.value {
    print(videoID) // "ABCDE"
}

Swift 1.x

let link = "https://www.youtube.com/watch?v=ABCDE"
if let videoID = NSURL(string: link)?.query?.componentsSeparatedByString("=").last {
    println(videoID) // "ABCDE"
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
4

In your case there is no need to create an NSURL as other answers do. Just use:

var url = "https://www.youtube.com/watch?v=ABCDE"
if let videoID = url.componentsSeparatedByString("=").last {
    print(videoID)
}
Fidel López
  • 1,022
  • 7
  • 7
4

Swift 3+ version:

var url = "https://www.youtube.com/watch?v=ABCDE"
if let videoID = url.components(separatedBy: "=").last {
    print(videoID)
}
Alien
  • 576
  • 1
  • 4
  • 16
0

You need to unwrap the optional to use the index:

var url = "https://www.youtube.com/watch?v=ABCDE"
let characterToFind: Character = "="
if let index = find(url, characterToFind) { // Unwrap the optional
  url.substringFromIndex(advance(index, 1)) // => "ABCDE"
}
0

With your url format, you can get the 'v' parameter's value by converting to NSURL then get parameters and separate it by '='.

var url: NSURL = NSURL(string: "https://www.youtube.com/watch?v=RAzOOfVA2_8")!
url.query?.componentsSeparatedByString("=").last

url.query returns v=RAzOOfVA2_8

If the link has more than 1 parameter, you can get all parameters then do a loop to verify each parameter:

var url: NSURL = NSURL(string: "https://www.youtube.com/watch?v=RAzOOfVA2_8")!
var params = url.query?.componentsSeparatedByString("&")
if let _params = params { //have parameters in URL
    for param in _params { //verify each pair of key & value in your parameters
        var _paramArray = param.componentsSeparatedByString("=") //separate by '=' to get key & value
        if (_paramArray.first?.compare("v", options: nil, range: nil, locale: nil) == NSComparisonResult.OrderedSame) {
            println(_paramArray.last)
        }
    }
} else {
    //url does not have any parameter
}
Duyen-Hoa
  • 15,384
  • 5
  • 35
  • 44
0

find returns an optional – because the character might not be found, in which case it will be nil. You need to unwrap it to check it isn’t and to get the actual value out.

You can also use a range-based subscript on the index directly, rather than using advance to turn it into an integer index:

let url = "https://www.youtube.com/watch?v=ABCDE"
if let let characterIndex = find(url, "=") {
    let value = url[characterIndex.successor()..<url.endIndex]  // ABCDE
}
else {
    // error handling, if you want it, here
}

You have more options if there is a reasonable default in the case of “not found” For example, if you just want an empty string in that case, this will work:

let idx = find(url, "=")?.successor() ?? url.endIndex
let value = url[idx..<url.endIndex]

Or, maybe you don’t even need to deal with the optionality right now, so you’re happy to leave the result optional as well:

// value will be Optional("ABCD")
let value = find(url, "=").map { url[$0.successor()..<url.endIndex] }

For a rundown on optionals, take a look here and here.

Also, rather than hand-parsing URL strings at all, you might find the info here useful.

Community
  • 1
  • 1
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118