diff --git a/.travis.yml b/.travis.yml index 88e60c8..2a50755 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ language: objective-c -osx_image: xcode61 +osx_image: xcode8 xcodebuild: xctool -project youtube-parser.xcodeproj -scheme youtube-parser build xcode_scheme: youtube-parserTests diff --git a/AppDelegate.swift b/AppDelegate.swift index d8540ff..29530c5 100644 --- a/AppDelegate.swift +++ b/AppDelegate.swift @@ -12,12 +12,12 @@ import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - let testURL = NSURL(string: "https://www.youtube.com/watch?v=swZJwZeMesk")! + func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + let testURL = URL(string: "https://www.youtube.com/watch?v=swZJwZeMesk")! Youtube.h264videosWithYoutubeURL(testURL) { (videoInfo, error) -> Void in if let videoURLString = videoInfo?["url"] as? String, - videoTitle = videoInfo?["title"] as? String { + let videoTitle = videoInfo?["title"] as? String { print("\(videoTitle)") print("\(videoURLString)") } @@ -25,13 +25,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } - func applicationWillResignActive(application: UIApplication) { } + func applicationWillResignActive(_ application: UIApplication) { } - func applicationDidEnterBackground(application: UIApplication) { } + func applicationDidEnterBackground(_ application: UIApplication) { } - func applicationWillEnterForeground(application: UIApplication) { } + func applicationWillEnterForeground(_ application: UIApplication) { } - func applicationDidBecomeActive(application: UIApplication) { } + func applicationDidBecomeActive(_ application: UIApplication) { } - func applicationWillTerminate(application: UIApplication) { } + func applicationWillTerminate(_ application: UIApplication) { } } diff --git a/YoutubeSourceParserKit.xcodeproj/project.pbxproj b/YoutubeSourceParserKit.xcodeproj/project.pbxproj index 46460e7..a1c0b9b 100644 --- a/YoutubeSourceParserKit.xcodeproj/project.pbxproj +++ b/YoutubeSourceParserKit.xcodeproj/project.pbxproj @@ -33,7 +33,7 @@ B24965E31C3398310050DF64 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C3A838771BB746A0000C5D33 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; C3FC20CD1B4996150000E818 /* YoutubeSourceParserKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YoutubeSourceParserKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; - C3FC20E21B4996150000E818 /* YoutubeSourceParserKit.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = YoutubeSourceParserKit.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + C3FC20E21B4996150000E818 /* YoutubeSourceParserKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = YoutubeSourceParserKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -88,7 +88,7 @@ isa = PBXGroup; children = ( C3FC20CD1B4996150000E818 /* YoutubeSourceParserKit.app */, - C3FC20E21B4996150000E818 /* YoutubeSourceParserKit.xctest */, + C3FC20E21B4996150000E818 /* YoutubeSourceParserKitTests.xctest */, ); name = Products; sourceTree = ""; @@ -128,7 +128,7 @@ ); name = YoutubeSourceParserKitTests; productName = "youtube-parserTests"; - productReference = C3FC20E21B4996150000E818 /* YoutubeSourceParserKit.xctest */; + productReference = C3FC20E21B4996150000E818 /* YoutubeSourceParserKitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -139,14 +139,16 @@ attributes = { LastSwiftMigration = 0710; LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Toygar Dündaralp"; TargetAttributes = { C3FC20CC1B4996150000E818 = { CreatedOnToolsVersion = 6.4; + LastSwiftMigration = 0800; }; C3FC20E11B4996150000E818 = { CreatedOnToolsVersion = 6.4; + LastSwiftMigration = 0800; TestTargetID = C3FC20CC1B4996150000E818; }; }; @@ -231,13 +233,16 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -277,13 +282,16 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -297,6 +305,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -312,6 +321,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.dundaralp.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = YoutubeSourceParserKit; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -325,6 +335,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.dundaralp.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = YoutubeSourceParserKit; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -337,10 +348,11 @@ "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = "youtube-parserTests/Info.plist"; + INFOPLIST_FILE = YoutubeSourceParserKitTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.dundaralp.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = YoutubeSourceParserKit; + PRODUCT_NAME = YoutubeSourceParserKitTests; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/YoutubeSourceParserKit.app/YoutubeSourceParserKit"; }; name = Debug; @@ -350,10 +362,11 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ""; - INFOPLIST_FILE = "youtube-parserTests/Info.plist"; + INFOPLIST_FILE = YoutubeSourceParserKitTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.dundaralp.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = YoutubeSourceParserKit; + PRODUCT_NAME = YoutubeSourceParserKitTests; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/YoutubeSourceParserKit.app/YoutubeSourceParserKit"; }; name = Release; diff --git a/YoutubeSourceParserKit/Images.xcassets/AppIcon.appiconset/Contents.json b/YoutubeSourceParserKit/Images.xcassets/AppIcon.appiconset/Contents.json index eeea76c..1d060ed 100644 --- a/YoutubeSourceParserKit/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/YoutubeSourceParserKit/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -30,6 +40,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", diff --git a/YoutubeSourceParserKit/Youtube.swift b/YoutubeSourceParserKit/Youtube.swift index 15c57ad..d681535 100644 --- a/YoutubeSourceParserKit/Youtube.swift +++ b/YoutubeSourceParserKit/Youtube.swift @@ -6,166 +6,179 @@ // Copyright (c) 2015 Toygar Dündaralp. All rights reserved. // -import UIKit +import Foundation -public extension NSURL { - /** - Parses a query string of an NSURL - - @return key value dictionary with each parameter as an array - */ - func dictionaryForQueryString() -> [String: AnyObject]? { - if let query = self.query { - return query.dictionaryFromQueryStringComponents() - } - - // Note: find youtube ID in m.youtube.com "https://m.youtube.com/#/watch?v=1hZ98an9wjo" - let result = absoluteString.componentsSeparatedByString("?") - if result.count > 1 { - return result.last?.dictionaryFromQueryStringComponents() +public extension URL { + /** + Parses a query string of an NSURL + + @return key value dictionary with each parameter as an array + */ + func dictionaryForQueryString() -> [String: Any]? { + if let query = self.query { + return query.dictionaryFromQueryStringComponents() + } + + // Note: find youtube ID in m.youtube.com "https://m.youtube.com/#/watch?v=1hZ98an9wjo" + let result = absoluteString.components(separatedBy: "?") + if result.count > 1 { + return result.last?.dictionaryFromQueryStringComponents() + } + return nil } - return nil - } } -public extension NSString { - /** - Convenient method for decoding a html encoded string - */ - func stringByDecodingURLFormat() -> String { - let result = self.stringByReplacingOccurrencesOfString("+", withString:" ") - return result.stringByRemovingPercentEncoding! - } - - /** - Parses a query string - - @return key value dictionary with each parameter as an array - */ - func dictionaryFromQueryStringComponents() -> [String: AnyObject] { - var parameters = [String: AnyObject]() - for keyValue in componentsSeparatedByString("&") { - let keyValueArray = keyValue.componentsSeparatedByString("=") - if keyValueArray.count < 2 { - continue - } - let key = keyValueArray[0].stringByDecodingURLFormat() - let value = keyValueArray[1].stringByDecodingURLFormat() - parameters[key] = value +public extension String { + /** + Convenient method for decoding a html encoded string + */ + func stringByDecodingURLFormat() -> String { + let result = self.replacingOccurrences(of: "+", with:" ") + return result.removingPercentEncoding! + } + + /** + Parses a query string + + @return key value dictionary with each parameter as an array + */ + func dictionaryFromQueryStringComponents() -> [String: Any] { + var parameters = [String: Any]() + for keyValue in components(separatedBy: "&") { + let keyValueArray = keyValue.components(separatedBy: "=") + if keyValueArray.count < 2 { + continue + } + let key = keyValueArray[0].stringByDecodingURLFormat() + let value = keyValueArray[1].stringByDecodingURLFormat() + parameters[key] = value as Any? + } + return parameters } - return parameters - } } -public class Youtube: NSObject { - static let infoURL = "http://www.youtube.com/get_video_info?video_id=" - static var userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4" - /** - Method for retrieving the youtube ID from a youtube URL - - @param youtubeURL the the complete youtube video url, either youtu.be or youtube.com - @return string with desired youtube id - */ - public static func youtubeIDFromYoutubeURL(youtubeURL: NSURL) -> String? { - if let - youtubeHost = youtubeURL.host, - youtubePathComponents = youtubeURL.pathComponents { +open class Youtube: NSObject { + static let infoURL = "http://www.youtube.com/get_video_info?video_id=" + static var userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4" + /** + Method for retrieving the youtube ID from a youtube URL + + @param youtubeURL the the complete youtube video url, either youtu.be or youtube.com + @return string with desired youtube id + */ + open static func youtubeIDFromYoutubeURL(_ youtubeURL: URL) -> String? { + guard let youtubeHost = youtubeURL.host else { + return nil + } + + let youtubePathComponents = youtubeURL.pathComponents let youtubeAbsoluteString = youtubeURL.absoluteString if youtubeHost == "youtu.be" as String? { - return youtubePathComponents[1] - } else if youtubeAbsoluteString.rangeOfString("www.youtube.com/embed") != nil { - return youtubePathComponents[2] + return youtubePathComponents[1] + } else if youtubeAbsoluteString.range(of: "www.youtube.com/embed") != nil { + return youtubePathComponents[2] } else if youtubeHost == "youtube.googleapis.com" || - youtubeURL.pathComponents!.first == "www.youtube.com" as String? { + youtubeURL.pathComponents.first == "www.youtube.com" as String? { return youtubePathComponents[2] } else if let - queryString = youtubeURL.dictionaryForQueryString(), - searchParam = queryString["v"] as? String { + queryString = youtubeURL.dictionaryForQueryString(), + let searchParam = queryString["v"] as? String { return searchParam } + + return nil + } - return nil - } - /** - Method for retreiving a iOS supported video link - - @param youtubeURL the the complete youtube video url - @return dictionary with the available formats for the selected video - - */ - public static func h264videosWithYoutubeID(youtubeID: String) -> [String: AnyObject]? { - let urlString = String(format: "%@%@", infoURL, youtubeID) as String - let url = NSURL(string: urlString)! - let request = NSMutableURLRequest(URL: url) - request.timeoutInterval = 5.0 - request.setValue(userAgent, forHTTPHeaderField: "User-Agent") - request.HTTPMethod = "GET" - var responseString = NSString() - let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) - let group = dispatch_group_create() - dispatch_group_enter(group) - session.dataTaskWithRequest(request, completionHandler: { (data, response, _) -> Void in - if let data = data as NSData? { - responseString = NSString(data: data, encoding: NSUTF8StringEncoding)! - } - dispatch_group_leave(group) - }).resume() - dispatch_group_wait(group, DISPATCH_TIME_FOREVER) - let parts = responseString.dictionaryFromQueryStringComponents() - if parts.count > 0 { - var videoTitle: String = "" - var streamImage: String = "" - if let title = parts["title"] as? String { - videoTitle = title - } - if let image = parts["iurl"] as? String { - streamImage = image - } - if let fmtStreamMap = parts["url_encoded_fmt_stream_map"] as? String { + /** + Method for retreiving a iOS supported video link + + @param youtubeURL the the complete youtube video url + @return dictionary with the available formats for the selected video + + */ + open static func h264videosWithYoutubeID(_ youtubeID: String) -> [String: Any]? { + guard let parts = loadVideoInfos(youtubeID: youtubeID), parts.count > 0 else { + return nil + } + + let videoTitle = parts["title"] as? String ?? "" + let streamImage = parts["iurl"] as? String ?? "" + + guard let fmtStreamMap = parts["url_encoded_fmt_stream_map"] as? String else { + return nil + } // Live Stream - if let _: AnyObject = parts["live_playback"]{ - if let hlsvp = parts["hlsvp"] as? String { - return [ - "url": "\(hlsvp)", - "title": "\(videoTitle)", - "image": "\(streamImage)", - "isStream": true - ] - } + if parts["live_playback"] != nil { + if let hlsvp = parts["hlsvp"] as? String { + return [ + "url": "\(hlsvp)" as Any, + "title": "\(videoTitle)" as Any, + "image": "\(streamImage)" as Any, + "isStream": true as Any + ] + } } else { - let fmtStreamMapArray = fmtStreamMap.componentsSeparatedByString(",") - for videoEncodedString in fmtStreamMapArray { - var videoComponents = videoEncodedString.dictionaryFromQueryStringComponents() - videoComponents["title"] = videoTitle - videoComponents["isStream"] = false - return videoComponents as [String: AnyObject] - } + let fmtStreamMapArray = fmtStreamMap.components(separatedBy: ",") + for videoEncodedString in fmtStreamMapArray { + var videoComponents = videoEncodedString.dictionaryFromQueryStringComponents() + videoComponents["title"] = videoTitle as Any? + videoComponents["isStream"] = false as Any? + return videoComponents as [String: Any] + } } - } + + return nil } - return nil - } - - /** - Block based method for retreiving a iOS supported video link - - @param youtubeURL the the complete youtube video url - @param completeBlock the block which is called on completion - - */ - public static func h264videosWithYoutubeURL(youtubeURL: NSURL,completion: (( - videoInfo: [String: AnyObject]?, error: NSError?) -> Void)?) { - let priority = DISPATCH_QUEUE_PRIORITY_BACKGROUND - dispatch_async(dispatch_get_global_queue(priority, 0)) { - if let youtubeID = self.youtubeIDFromYoutubeURL(youtubeURL), videoInformation = self.h264videosWithYoutubeID(youtubeID) { - dispatch_async(dispatch_get_main_queue()) { - completion?(videoInfo: videoInformation, error: nil) - } - }else{ - dispatch_async(dispatch_get_main_queue()) { - completion?(videoInfo: nil, error: NSError(domain: "com.player.youtube.backgroundqueue", code: 1001, userInfo: ["error": "Invalid YouTube URL"])) - } + + private static func loadVideoInfos(youtubeID: String) -> [String: Any]? { + + var result: [String: Any]? + let urlString = String(format: "%@%@", infoURL, youtubeID) + + guard let url = URL(string: urlString) else { + return result } - } + + var request = URLRequest(url: url) + request.timeoutInterval = 5.0 + request.setValue(userAgent, forHTTPHeaderField: "User-Agent") + request.httpMethod = "GET" + + let session = URLSession(configuration: URLSessionConfiguration.default) + let group = DispatchGroup() + group.enter() + session.dataTask(with: request, completionHandler: { (data, response, _) -> Void in + if let data = data as Data?, + let resultString = String(data: data, encoding: String.Encoding.utf8) { + + result = resultString.dictionaryFromQueryStringComponents() + + } + group.leave() + }).resume() + _ = group.wait(timeout: DispatchTime.distantFuture) + return result } - } + + /** + Block based method for retreiving a iOS supported video link + + @param youtubeURL the the complete youtube video url + @param completeBlock the block which is called on completion + + */ + open static func h264videosWithYoutubeURL(_ youtubeURL: URL,completion: (( + _ videoInfo: [String: Any]?, _ error: NSError?) -> Void)?) { + DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async{ + if let youtubeID = self.youtubeIDFromYoutubeURL(youtubeURL), let videoInformation = self.h264videosWithYoutubeID(youtubeID) { + DispatchQueue.main.async { + completion?(videoInformation, nil) + } + } else { + DispatchQueue.main.async { + completion?(nil, NSError(domain: "com.player.youtube.backgroundqueue", code: 1001, userInfo: ["error": "Invalid YouTube URL"])) + } + } + } + } +} diff --git a/YoutubeSourceParserKitTests/YoutubeSourceParserKitTests.swift b/YoutubeSourceParserKitTests/YoutubeSourceParserKitTests.swift index f4fad58..13a8e1c 100644 --- a/YoutubeSourceParserKitTests/YoutubeSourceParserKitTests.swift +++ b/YoutubeSourceParserKitTests/YoutubeSourceParserKitTests.swift @@ -6,8 +6,10 @@ // Copyright (c) 2015 Toygar Dündaralp. All rights reserved. // -import UIKit +import Foundation import XCTest +@testable import YoutubeSourceParserKit + class YoutubeSourceParserKitTests: XCTestCase { @@ -29,7 +31,7 @@ class YoutubeSourceParserKitTests: XCTestCase { func testDictionaryFromQueryStringComponents() { let sampleLink = "https://www.youtube.com/watch?v=o0jJiB2Ygpg&list=RDo0jJiB2Ygpg" - let dictionary = sampleLink.dictionaryFromQueryStringComponents() as [String:AnyObject] + let dictionary = sampleLink.dictionaryFromQueryStringComponents() as [String:Any] XCTAssertNotNil(dictionary["list"], "url dictionary parse error") if let list = dictionary["list"] as? String { XCTAssertEqual(list, "RDo0jJiB2Ygpg", "list not equal value") @@ -40,7 +42,7 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testInvalidURLs1() { - let sampleLink = NSURL(string: "?v=1hZ98an9wjo")! + let sampleLink = URL(string: "?v=1hZ98an9wjo")! XCTAssertNil(Youtube.youtubeIDFromYoutubeURL(sampleLink), "Youtube ID is not nil") if let youtubeID = Youtube.youtubeIDFromYoutubeURL(sampleLink) { XCTAssertEqual(youtubeID, "1hZ98an9wjo", "Youtube ID not same") @@ -48,7 +50,7 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testInvalidURLs2() { - let sampleLink = NSURL(string: "?v=")! + let sampleLink = URL(string: "?v=")! XCTAssertNil(Youtube.youtubeIDFromYoutubeURL(sampleLink), "Youtube ID is not nil") if let youtubeID = Youtube.youtubeIDFromYoutubeURL(sampleLink) { XCTAssertEqual(youtubeID, "", "Youtube ID not same") @@ -56,7 +58,7 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testInvalidURLs3() { - let sampleLink = NSURL(string: "v=1hZ98an9wjo")! + let sampleLink = URL(string: "v=1hZ98an9wjo")! XCTAssertNil(Youtube.youtubeIDFromYoutubeURL(sampleLink), "Youtube ID is not nil") if let youtubeID = Youtube.youtubeIDFromYoutubeURL(sampleLink) { XCTAssertEqual(youtubeID, "v=1hZ98an9wjo", "Youtube ID not same") @@ -64,7 +66,7 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testInvalidURLs4() { - let sampleLink = NSURL(string: "v1hZ98an9wjo")! + let sampleLink = URL(string: "v1hZ98an9wjo")! XCTAssertNil(Youtube.youtubeIDFromYoutubeURL(sampleLink), "Youtube ID is not nil") if let youtubeID = Youtube.youtubeIDFromYoutubeURL(sampleLink) { XCTAssertEqual(youtubeID, "v1hZ98an9wjo", "Youtube ID not same") @@ -72,7 +74,7 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testYoutubeIDFromYoutubeURL() { - let sampleLink = NSURL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo")! + let sampleLink = URL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo")! XCTAssertNotNil(Youtube.youtubeIDFromYoutubeURL(sampleLink), "Youtube ID is nil") if let youtubeID = Youtube.youtubeIDFromYoutubeURL(sampleLink) { XCTAssertEqual(youtubeID, "1hZ98an9wjo", "Youtube ID not same") @@ -80,7 +82,7 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testYoutubeIDFromMobileYoutubeURL() { - let sampleLink = NSURL(string: "https://m.youtube.com/#/watch?v=1hZ98an9wjo")! + let sampleLink = URL(string: "https://m.youtube.com/#/watch?v=1hZ98an9wjo")! XCTAssertNotNil(Youtube.youtubeIDFromYoutubeURL(sampleLink), "Youtube ID is nil") if let youtubeID = Youtube.youtubeIDFromYoutubeURL(sampleLink) { XCTAssertEqual(youtubeID, "1hZ98an9wjo", "Youtube ID not same") @@ -106,10 +108,10 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testVideoQuality(){ - if let videoURL = NSURL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { + if let videoURL = URL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { Youtube.h264videosWithYoutubeURL(videoURL, completion: { (videoInfo, error) -> Void in XCTAssertNotNil(videoInfo, "video dictionary is nil") - if let info = videoInfo as [String:AnyObject]? { + if let info = videoInfo as [String:Any]? { if let quality = info["quality"] as? String { XCTAssertEqual(quality, "hd720", "quality not equal") } @@ -119,10 +121,10 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testItagControl(){ - if let videoURL = NSURL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { + if let videoURL = URL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { Youtube.h264videosWithYoutubeURL(videoURL, completion: { (videoInfo, error) -> Void in XCTAssertNotNil(videoInfo, "video dictionary is nil") - if let info = videoInfo as [String:AnyObject]? { + if let info = videoInfo as [String:Any]? { if let itag = info["itag"] as? String { XCTAssertEqual(itag, "22", "itag not equal") } @@ -132,10 +134,10 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testVideoTypeControl(){ - if let videoURL = NSURL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { + if let videoURL = URL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { Youtube.h264videosWithYoutubeURL(videoURL, completion: { (videoInfo, error) -> Void in XCTAssertNotNil(videoInfo, "video dictionary is nil") - if let info = videoInfo as [String:AnyObject]? { + if let info = videoInfo as [String:Any]? { if let type = info["type"] as? String { XCTAssertEqual(type, "video/mp4; codecs=\"avc1.64001F, mp4a.40.2\"", "type not equal") } @@ -145,10 +147,10 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testFallbackHostControl(){ - if let videoURL = NSURL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { + if let videoURL = URL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { Youtube.h264videosWithYoutubeURL(videoURL, completion: { (videoInfo, error) -> Void in XCTAssertNotNil(videoInfo, "video dictionary is nil") - if let info = videoInfo as [String:AnyObject]? { + if let info = videoInfo as [String:Any]? { if let fallback_host = info["fallback_host"] as? String { XCTAssertEqual(fallback_host, "tc.v7.cache1.googlevideo.com", "fallback_host not equal") } @@ -158,10 +160,10 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testIsLiveVideoTest() { - if let liveVideoURL = NSURL(string: "https://www.youtube.com/watch?v=rxGoGg7n77A"){ + if let liveVideoURL = URL(string: "https://www.youtube.com/watch?v=kMcL3Zr9iyQ"){ Youtube.h264videosWithYoutubeURL(liveVideoURL, completion: { (videoInfo, error) -> Void in XCTAssertNotNil(videoInfo, "video dictionary is nil") - if let info = videoInfo as [String:AnyObject]? { + if let info = videoInfo as [String:Any]? { XCTAssertNotNil(info["url"], "live stream url is nil") } }) @@ -177,17 +179,17 @@ class YoutubeSourceParserKitTests: XCTestCase { } func testH264videosWithYoutubeURLBlock(){ - let expectation: XCTestExpectation = self.expectationWithDescription("Handler called") - if let videoURL = NSURL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { + let expectation: XCTestExpectation = self.expectation(description: "Handler called") + if let videoURL = URL(string: "http://www.youtube.com/watch?v=1hZ98an9wjo") { Youtube.h264videosWithYoutubeURL(videoURL, completion: { (videoInfo, error) -> Void in expectation.fulfill() - if let info = videoInfo as [String:AnyObject]? { + if let info = videoInfo as [String:Any]? { if let quality = info["itag"] as? String { XCTAssertEqual(quality, "22", "itag not equal") } } }) - self.waitForExpectationsWithTimeout(2, handler: nil) + self.waitForExpectations(timeout: 2, handler: nil) } }