diff --git a/.jazzy.yaml b/.jazzy.yaml
index bf8b32fe..b77ba069 100644
--- a/.jazzy.yaml
+++ b/.jazzy.yaml
@@ -4,11 +4,11 @@ source_directory: XCDYouTubeKit
framework_root: .
umbrella_header: XCDYouTubeKit/XCDYouTubeKit.h
module: XCDYouTubeKit
-module_version: 2.8.1
+module_version: 2.8.2
author: Cédric Luthi
author_url: https://twitter.com/0xced
readme: README.md
github_url: https://github.com/0xced/XCDYouTubeKit
-github_file_prefix: https://github.com/0xced/XCDYouTubeKit/tree/2.8.1/XCDYouTubeKit
+github_file_prefix: https://github.com/0xced/XCDYouTubeKit/tree/2.8.2/XCDYouTubeKit
diff --git a/.swiftpm/xcode/xcuserdata/soneejohn.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/soneejohn.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 00000000..d1054dc4
--- /dev/null
+++ b/.swiftpm/xcode/xcuserdata/soneejohn.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ SchemeUserState
+
+ XCDYouTubeKit.xcscheme_^#shared#^_
+
+ orderHint
+ 0
+
+
+ SuppressBuildableAutocreation
+
+ XCDYouTubeKit
+
+ primary
+
+
+
+
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 866cf696..ab2fccfe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+#### Version 2.8.2
+
+* Add new `streamURL` property on `XCDYouTubeVideo`
+* Fixed Swift Package Manager (#441)
+* Support iOS 13 in Demo Projects
+ * Support background playback (#427, #442)
+
#### Version 2.8.1
* Adaptation to YouTube API change. (#447, #448, #449)
diff --git a/Package.swift b/Package.swift
index c3a522fa..6cd408e1 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,16 +1,22 @@
-// swift-tools-version:4.2
+// swift-tools-version:5.1
import PackageDescription
let package = Package(
name: "XCDYouTubeKit",
- // platforms: [.iOS("8.0"), .macOS("10.10"), tvOS("9.0")],
+ platforms: [
+ .iOS(.v8),
+ .tvOS(.v9),
+ .macOS(.v10_10)
+ ],
products: [
- .library(name: "XCDYouTubeKit", targets: ["XCDYouTubeKit"])
+ .library(name: "XCDYouTubeKit" , targets: ["XCDYouTubeKit"])
],
targets: [
.target(
name: "XCDYouTubeKit",
- path: "XCDYouTubeKit"
+ path: ".",
+ sources: ["XCDYouTubeKit"],
+ publicHeadersPath: "XCDYouTubeKit"
)
]
)
diff --git a/README.md b/README.md
index dafe05cc..5934df22 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[![Platform](https://img.shields.io/cocoapods/p/XCDYouTubeKit.svg?style=flat)](http://cocoadocs.org/docsets/XCDYouTubeKit/)
[![Pod Version](https://img.shields.io/cocoapods/v/XCDYouTubeKit.svg?style=flat)](https://cocoapods.org/pods/XCDYouTubeKit)
[![Carthage Compatibility](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage/)
-[![Accio supported](https://img.shields.io/badge/Accio-supported-0A7CF5.svg?style=flat)](https://github.com/JamitLabs/Accio)
+[![Swift Package Manager Compatibility](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen)](ttps://swift.org/package-manager/)
[![License](https://img.shields.io/cocoapods/l/XCDYouTubeKit.svg?style=flat)](LICENSE)
**XCDYouTubeKit** is a YouTube video player for iOS, tvOS and macOS.
@@ -28,7 +28,7 @@ XCDYouTubeKit is against the YouTube [Terms of Service](https://www.youtube.com/
## Installation
-XCDYouTubeKit is available through [CocoaPods](https://cocoapods.org/), [Carthage](https://github.com/Carthage/Carthage) and [Accio](https://github.com/JamitLabs/Accio).
+XCDYouTubeKit is available through [CocoaPods](https://cocoapods.org/), [Carthage](https://github.com/Carthage/Carthage) and [Swift Package Manager](https://swift.org/package-manager/).
CocoaPods:
@@ -42,10 +42,14 @@ Carthage:
github "0xced/XCDYouTubeKit" ~> 2.8
```
-Accio:
+Swift Package Manager:
+
+Add `XCDYouTubeKit` to the dependencies value of your `Package.swift`
```swift
-.package(url: "https://github.com/0xced/XCDYouTubeKit.git", .upToNextMajor(from: "2.7.3")),
+dependencies: [
+ .package(url: "https://github.com/0xced/XCDYouTubeKit.git", from: "2.8.0")
+]
```
Alternatively, you can manually use the provided static library or dynamic framework. In order to use the static library, you must:
diff --git a/XCDYouTubeKit Demo/XCDYouTubeKit Demo.xcodeproj/project.pbxproj b/XCDYouTubeKit Demo/XCDYouTubeKit Demo.xcodeproj/project.pbxproj
index ea93b3e9..7d386775 100644
--- a/XCDYouTubeKit Demo/XCDYouTubeKit Demo.xcodeproj/project.pbxproj
+++ b/XCDYouTubeKit Demo/XCDYouTubeKit Demo.xcodeproj/project.pbxproj
@@ -7,6 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
+ 019AFA1E2361E9CD00B03F57 /* DemoFullScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019AFA1D2361E9CC00B03F57 /* DemoFullScreenViewController.swift */; };
+ 019AFA202361F10D00B03F57 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019AFA1F2361F10D00B03F57 /* Utilities.swift */; };
+ 01E88BD523690B75002523D1 /* AVPlayerViewControllerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01E88BD423690B75002523D1 /* AVPlayerViewControllerManager.swift */; };
0ADD88CC5EC5E9D286D8A8E0 /* libPods-XCDYouTubeKit iOS Demo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B3DDE49D0638521AD03AA01 /* libPods-XCDYouTubeKit iOS Demo.a */; };
6941B80FC7AE87BA698FDD61 /* libPods-XCDYouTubeKit OS X Demo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CF61ADAFAE5A8C5F8C082438 /* libPods-XCDYouTubeKit OS X Demo.a */; };
C232DA831C00BCEB00E26E3A /* GradientMaskView.m in Sources */ = {isa = PBXBuildFile; fileRef = C232DA821C00BCEB00E26E3A /* GradientMaskView.m */; };
@@ -17,7 +20,6 @@
C2428AEA191C3C1400065504 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C2428AE9191C3C1400065504 /* Images.xcassets */; };
C2428B07191C3DE400065504 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2428B04191C3DE400065504 /* main.m */; };
C2428B0C191C415300065504 /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2428B0B191C415300065504 /* AVKit.framework */; };
- C2570B861A02415F00127127 /* NowPlayingInfoCenterProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = C2570B851A02415F00127127 /* NowPlayingInfoCenterProvider.m */; };
C2597EA21B0CB90C0030E9F2 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2FB52DF1918F89A00B2CBE6 /* JavaScriptCore.framework */; };
C25A0CA51C06884000C644E0 /* XCDYouTubeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2A1E7461BD1AE0F001EAC91 /* XCDYouTubeKit.framework */; };
C25A0CA61C06884100C644E0 /* XCDYouTubeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2A1E7461BD1AE0F001EAC91 /* XCDYouTubeKit.framework */; };
@@ -29,7 +31,6 @@
C27415A617F491230026834B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C27415A517F491230026834B /* CoreGraphics.framework */; };
C27415D217F4CDD80026834B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C27415C017F4CDD80026834B /* AppDelegate.m */; };
C27415D317F4CDD80026834B /* DemoAsynchronousViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C27415C217F4CDD80026834B /* DemoAsynchronousViewController.m */; };
- C27415D417F4CDD80026834B /* DemoFullScreenViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C27415C417F4CDD80026834B /* DemoFullScreenViewController.m */; };
C27415D517F4CDD80026834B /* DemoInlineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C27415C617F4CDD80026834B /* DemoInlineViewController.m */; };
C27415D617F4CDD80026834B /* DemoThumbnailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C27415C817F4CDD80026834B /* DemoThumbnailViewController.m */; };
C27415D717F4CDD80026834B /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C27415C917F4CDD80026834B /* MainStoryboard.storyboard */; };
@@ -39,7 +40,6 @@
C27AD2A11A0791F000866050 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C27AD2A01A0791F000866050 /* Images.xcassets */; };
C2A1E7471BD1AE0F001EAC91 /* XCDYouTubeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2A1E7461BD1AE0F001EAC91 /* XCDYouTubeKit.framework */; };
C2ADD72D1BE6AC3100B182ED /* VideoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C2ADD72C1BE6AC3100B182ED /* VideoCell.m */; };
- C2BA376D192AB32200B27FAD /* MPMoviePlayerController+BackgroundPlayback.m in Sources */ = {isa = PBXBuildFile; fileRef = C2BA376C192AB32200B27FAD /* MPMoviePlayerController+BackgroundPlayback.m */; };
C2C5D2981A6E5AB900F2B3F8 /* VideoPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = C2C5D2971A6E5AB900F2B3F8 /* VideoPickerController.m */; };
C2CF7CEE1B17737400C356EA /* ContextLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = C2CF7CED1B17737400C356EA /* ContextLogFormatter.m */; };
C2D627601BE3C648005367FF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D6275F1BE3C648005367FF /* AppDelegate.m */; };
@@ -90,6 +90,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 019AFA1C2361E9CC00B03F57 /* XCDYouTubeKit iOS Demo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCDYouTubeKit iOS Demo-Bridging-Header.h"; sourceTree = ""; };
+ 019AFA1D2361E9CC00B03F57 /* DemoFullScreenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DemoFullScreenViewController.swift; sourceTree = ""; };
+ 019AFA1F2361F10D00B03F57 /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = ""; };
+ 01E88BD423690B75002523D1 /* AVPlayerViewControllerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVPlayerViewControllerManager.swift; sourceTree = ""; };
044E71F373F947A64C774319 /* Pods-XCDYouTubeKit iOS Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XCDYouTubeKit iOS Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-XCDYouTubeKit iOS Demo/Pods-XCDYouTubeKit iOS Demo.debug.xcconfig"; sourceTree = ""; };
4805F31947DAD8E88035A44A /* Pods-XCDYouTubeKit OS X Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XCDYouTubeKit OS X Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-XCDYouTubeKit OS X Demo/Pods-XCDYouTubeKit OS X Demo.release.xcconfig"; sourceTree = ""; };
5B3DDE49D0638521AD03AA01 /* libPods-XCDYouTubeKit iOS Demo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-XCDYouTubeKit iOS Demo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -106,8 +110,6 @@
C2428B04191C3DE400065504 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
C2428B05191C3DE400065504 /* XCDYouTubeKit OS X Demo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "XCDYouTubeKit OS X Demo-Info.plist"; sourceTree = ""; };
C2428B0B191C415300065504 /* AVKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = System/Library/Frameworks/AVKit.framework; sourceTree = SDKROOT; };
- C2570B841A02415F00127127 /* NowPlayingInfoCenterProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NowPlayingInfoCenterProvider.h; sourceTree = ""; };
- C2570B851A02415F00127127 /* NowPlayingInfoCenterProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NowPlayingInfoCenterProvider.m; sourceTree = ""; };
C2630D3D1935C449000D3917 /* PlayerEventLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayerEventLogger.h; sourceTree = ""; };
C2630D3E1935C449000D3917 /* PlayerEventLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayerEventLogger.m; sourceTree = ""; };
C274159E17F491230026834B /* XCDYouTubeKit iOS Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "XCDYouTubeKit iOS Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -118,8 +120,6 @@
C27415C017F4CDD80026834B /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
C27415C117F4CDD80026834B /* DemoAsynchronousViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoAsynchronousViewController.h; sourceTree = ""; };
C27415C217F4CDD80026834B /* DemoAsynchronousViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoAsynchronousViewController.m; sourceTree = ""; };
- C27415C317F4CDD80026834B /* DemoFullScreenViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoFullScreenViewController.h; sourceTree = ""; };
- C27415C417F4CDD80026834B /* DemoFullScreenViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoFullScreenViewController.m; sourceTree = ""; };
C27415C517F4CDD80026834B /* DemoInlineViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoInlineViewController.h; sourceTree = ""; };
C27415C617F4CDD80026834B /* DemoInlineViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoInlineViewController.m; sourceTree = ""; };
C27415C717F4CDD80026834B /* DemoThumbnailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoThumbnailViewController.h; sourceTree = ""; };
@@ -133,8 +133,6 @@
C2A1E7461BD1AE0F001EAC91 /* XCDYouTubeKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = XCDYouTubeKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C2ADD72B1BE6AC3100B182ED /* VideoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoCell.h; sourceTree = ""; };
C2ADD72C1BE6AC3100B182ED /* VideoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoCell.m; sourceTree = ""; };
- C2BA376B192AB32200B27FAD /* MPMoviePlayerController+BackgroundPlayback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPMoviePlayerController+BackgroundPlayback.h"; sourceTree = ""; };
- C2BA376C192AB32200B27FAD /* MPMoviePlayerController+BackgroundPlayback.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPMoviePlayerController+BackgroundPlayback.m"; sourceTree = ""; };
C2C5D2961A6E5AB900F2B3F8 /* VideoPickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoPickerController.h; sourceTree = ""; };
C2C5D2971A6E5AB900F2B3F8 /* VideoPickerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoPickerController.m; sourceTree = ""; };
C2CEABA61C0EFBE80077C5CA /* Playground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground.playground; sourceTree = ""; };
@@ -272,12 +270,11 @@
C2CF7CED1B17737400C356EA /* ContextLogFormatter.m */,
C2630D3D1935C449000D3917 /* PlayerEventLogger.h */,
C2630D3E1935C449000D3917 /* PlayerEventLogger.m */,
- C2570B841A02415F00127127 /* NowPlayingInfoCenterProvider.h */,
- C2570B851A02415F00127127 /* NowPlayingInfoCenterProvider.m */,
- C27415C317F4CDD80026834B /* DemoFullScreenViewController.h */,
- C27415C417F4CDD80026834B /* DemoFullScreenViewController.m */,
C2C5D2961A6E5AB900F2B3F8 /* VideoPickerController.h */,
C2C5D2971A6E5AB900F2B3F8 /* VideoPickerController.m */,
+ 019AFA1F2361F10D00B03F57 /* Utilities.swift */,
+ 01E88BD423690B75002523D1 /* AVPlayerViewControllerManager.swift */,
+ 019AFA1D2361E9CC00B03F57 /* DemoFullScreenViewController.swift */,
C27415C517F4CDD80026834B /* DemoInlineViewController.h */,
C27415C617F4CDD80026834B /* DemoInlineViewController.m */,
C27415C717F4CDD80026834B /* DemoThumbnailViewController.h */,
@@ -286,10 +283,9 @@
C27415C217F4CDD80026834B /* DemoAsynchronousViewController.m */,
C2EFB48518730A2B0046B1FE /* SettingsViewController.h */,
C2EFB48618730A2B0046B1FE /* SettingsViewController.m */,
- C2BA376B192AB32200B27FAD /* MPMoviePlayerController+BackgroundPlayback.h */,
- C2BA376C192AB32200B27FAD /* MPMoviePlayerController+BackgroundPlayback.m */,
C27415C917F4CDD80026834B /* MainStoryboard.storyboard */,
C27415CB17F4CDD80026834B /* Supporting Files */,
+ 019AFA1C2361E9CC00B03F57 /* XCDYouTubeKit iOS Demo-Bridging-Header.h */,
);
path = "iOS Demo";
sourceTree = "";
@@ -422,6 +418,9 @@
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = "Cédric Luthi";
TargetAttributes = {
+ C274159D17F491230026834B = {
+ LastSwiftMigration = 1110;
+ };
C2D627581BE3C648005367FF = {
CreatedOnToolsVersion = 7.1;
};
@@ -432,6 +431,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
+ English,
en,
Base,
);
@@ -632,18 +632,18 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 01E88BD523690B75002523D1 /* AVPlayerViewControllerManager.swift in Sources */,
C27415D217F4CDD80026834B /* AppDelegate.m in Sources */,
- C2570B861A02415F00127127 /* NowPlayingInfoCenterProvider.m in Sources */,
C27415D317F4CDD80026834B /* DemoAsynchronousViewController.m in Sources */,
C2630D3F1935C449000D3917 /* PlayerEventLogger.m in Sources */,
+ 019AFA202361F10D00B03F57 /* Utilities.swift in Sources */,
C2CF7CEE1B17737400C356EA /* ContextLogFormatter.m in Sources */,
- C27415D417F4CDD80026834B /* DemoFullScreenViewController.m in Sources */,
C2C5D2981A6E5AB900F2B3F8 /* VideoPickerController.m in Sources */,
C27415D517F4CDD80026834B /* DemoInlineViewController.m in Sources */,
C27415D617F4CDD80026834B /* DemoThumbnailViewController.m in Sources */,
+ 019AFA1E2361E9CD00B03F57 /* DemoFullScreenViewController.swift in Sources */,
C27415DC17F4CDD80026834B /* main.m in Sources */,
C2EFB48718730A2B0046B1FE /* SettingsViewController.m in Sources */,
- C2BA376D192AB32200B27FAD /* MPMoviePlayerController+BackgroundPlayback.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -760,7 +760,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 2.8.1;
+ CURRENT_PROJECT_VERSION = 2.8.2;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
@@ -804,7 +804,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 2.8.1;
+ CURRENT_PROJECT_VERSION = 2.8.2;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
@@ -833,10 +833,14 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = "iOS Demo/Supporting Files/XCDYouTubeKit iOS Demo-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = ch.pitaya.xcdyoutubekit.demo.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "iOS Demo/XCDYouTubeKit iOS Demo-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
@@ -848,10 +852,13 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = "iOS Demo/Supporting Files/XCDYouTubeKit iOS Demo-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = ch.pitaya.xcdyoutubekit.demo.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "iOS Demo/XCDYouTubeKit iOS Demo-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
diff --git a/XCDYouTubeKit Demo/iOS Demo/AVPlayerViewControllerManager.swift b/XCDYouTubeKit Demo/iOS Demo/AVPlayerViewControllerManager.swift
new file mode 100644
index 00000000..041a24a1
--- /dev/null
+++ b/XCDYouTubeKit Demo/iOS Demo/AVPlayerViewControllerManager.swift
@@ -0,0 +1,214 @@
+//
+// AVPlayerViewControllerManager.swift
+// XCDYouTubeKit iOS Demo
+//
+// Created by Soneé John on 10/29/19.
+// Copyright © 2019 Cédric Luthi. All rights reserved.
+//
+
+import Foundation
+import AVKit
+import MediaPlayer
+
+extension UIViewController {
+ func topMostViewController() -> UIViewController {
+ if self.presentedViewController == nil {
+ return self
+ }
+ if let navigation = self.presentedViewController as? UINavigationController {
+ return navigation.visibleViewController!.topMostViewController()
+ }
+ if let tab = self.presentedViewController as? UITabBarController {
+ if let selectedTab = tab.selectedViewController {
+ return selectedTab.topMostViewController()
+ }
+ return tab.topMostViewController()
+ }
+ return self.presentedViewController!.topMostViewController()
+ }
+}
+
+extension UIView {
+ var parentViewController: UIViewController? {
+ var parentResponder: UIResponder? = self
+ while parentResponder != nil {
+ parentResponder = parentResponder!.next
+ if let viewController = parentResponder as? UIViewController {
+ return viewController
+ }
+ }
+ return nil
+ }
+}
+
+@objcMembers class AVPlayerViewControllerManager: NSObject {
+ //MARK: - Public
+ public static let shared = AVPlayerViewControllerManager()
+ public var lowQualityMode = false
+ public dynamic var duration: Float = 0
+
+ public var video: XCDYouTubeVideo? {
+ didSet {
+ guard let video = video else { return }
+ guard lowQualityMode == false else {
+ guard let streamURL = video.streamURLs[XCDYouTubeVideoQualityHTTPLiveStreaming] ?? video.streamURLs[XCDYouTubeVideoQuality.medium360.rawValue] ?? video.streamURLs[XCDYouTubeVideoQuality.small240.rawValue] else { fatalError("No stream URL") }
+
+ self.player = AVPlayer(url: streamURL)
+ self.controller.player = self.player
+ return
+ }
+ self.player = AVPlayer(url: video.streamURL)
+ self.controller.player = self.player
+ }
+ }
+
+ public var player: AVPlayer? {
+ didSet {
+ if let playerRateObserverToken = playerRateObserverToken {
+ playerRateObserverToken.invalidate()
+ self.playerRateObserverToken = nil
+ }
+
+ self.playerRateObserverToken = player?.observe(\.rate, changeHandler: { (item, value) in
+ self.updatePlaybackRateMetadata()
+ })
+
+ guard let video = self.video else { return }
+ if let token = timeObserverToken {
+ oldValue?.removeTimeObserver(token)
+ timeObserverToken = nil
+ }
+ self.setupRemoteTransportControls()
+ self.updateGeneralMetadata(video: video)
+ self.updatePlaybackDuration()
+ }
+ }
+
+ public lazy var controller: AVPlayerViewController = {
+ let controller = AVPlayerViewController()
+ if #available(iOS 10.0, *) {
+ controller.updatesNowPlayingInfoCenter = false
+ }
+ return controller
+ }()
+
+ override init() {
+ super.init()
+
+ NotificationCenter.default.addObserver(forName: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance(), queue: .main) { (notification) in
+
+ guard let userInfo = notification.userInfo,
+ let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
+ let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
+ return
+ }
+
+ if type == .began {
+ self.player?.pause()
+ } else if type == .ended {
+ guard ((try? AVAudioSession.sharedInstance().setActive(true)) != nil) else { return }
+ guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else { return }
+ let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
+ guard options.contains(.shouldResume) else { return }
+ self.player?.play()
+ }
+ }
+ }
+
+ public func disconnectPlayer() {
+ self.controller.player = nil
+ }
+
+ public func reconnectPlayer(rootViewController: UIViewController) {
+ let viewController = rootViewController.topMostViewController()
+ guard let playerViewController = viewController as? AVPlayerViewController else {
+ if rootViewController is UINavigationController {
+ guard let vc = (rootViewController as! UINavigationController).visibleViewController else { return }
+ for childVC in vc.children {
+ guard let playerViewController = childVC as? AVPlayerViewController else { continue }
+ playerViewController.player = self.player
+ break
+ }
+ }
+ return
+ }
+ playerViewController.player = self.player
+ }
+
+ //MARK: Private
+
+ fileprivate var playerRateObserverToken: NSKeyValueObservation?
+ fileprivate var timeObserverToken: Any?
+ fileprivate let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
+
+ fileprivate func setupRemoteTransportControls() {
+ let commandCenter = MPRemoteCommandCenter.shared()
+ commandCenter.playCommand.addTarget { [unowned self] event in
+ if self.player?.rate == 0.0 {
+ self.player?.play()
+ return .success
+ }
+ return .commandFailed
+ }
+
+ commandCenter.pauseCommand.addTarget { event in
+ if self.player?.rate == 1.0 {
+ self.player?.pause()
+ return .success
+ }
+ return .commandFailed
+ }
+ }
+
+ fileprivate func updateGeneralMetadata(video: XCDYouTubeVideo) {
+ guard player?.currentItem != nil else {
+ nowPlayingInfoCenter.nowPlayingInfo = nil
+ return
+ }
+
+ var nowPlayingInfo = nowPlayingInfoCenter.nowPlayingInfo ?? [String: Any]()
+ let title = video.title
+
+ if let thumbnailURL = video.thumbnailURL {
+ URLSession.shared.dataTask(with: thumbnailURL) { (data, _, error) in
+ guard error == nil else { return }
+ guard data != nil else { return }
+ guard let image = UIImage(data: data!) else { return }
+
+ let artwork = MPMediaItemArtwork(image: image)
+ nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork
+ self.nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo
+ }.resume()
+ }
+
+ nowPlayingInfo[MPMediaItemPropertyTitle] = title
+ nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo
+ }
+
+ fileprivate func updatePlaybackDuration() {
+ let interval = CMTime(seconds: 1.0, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
+
+ timeObserverToken = self.player?.addPeriodicTimeObserver(forInterval: interval, queue: .main, using: { [weak self] (time) in
+ guard let player = self?.player else { return }
+ guard player.currentItem != nil else { return }
+
+ var nowPlayingInfo = self!.nowPlayingInfoCenter.nowPlayingInfo ?? [String: Any]()
+ self!.duration = Float(CMTimeGetSeconds(player.currentItem!.duration))
+ nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = self!.duration
+ nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = CMTimeGetSeconds(player.currentItem!.currentTime())
+ self!.nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo
+ })
+ }
+
+ fileprivate func updatePlaybackRateMetadata() {
+ guard player?.currentItem != nil else {
+ duration = 0
+ nowPlayingInfoCenter.nowPlayingInfo = nil
+ return
+ }
+
+ var nowPlayingInfo = nowPlayingInfoCenter.nowPlayingInfo ?? [String: Any]()
+ nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player!.rate
+ nowPlayingInfo[MPNowPlayingInfoPropertyDefaultPlaybackRate] = player!.rate
+ }
+}
diff --git a/XCDYouTubeKit Demo/iOS Demo/AppDelegate.m b/XCDYouTubeKit Demo/iOS Demo/AppDelegate.m
index 4451e322..b6620944 100644
--- a/XCDYouTubeKit Demo/iOS Demo/AppDelegate.m
+++ b/XCDYouTubeKit Demo/iOS Demo/AppDelegate.m
@@ -9,6 +9,7 @@
#import
#import "ContextLogFormatter.h"
+#import "XCDYouTubeKit_iOS_Demo-Swift.h"
@implementation AppDelegate
@@ -19,9 +20,6 @@ - (instancetype) init
if (!(self = [super init]))
return nil;
- _playerEventLogger = [PlayerEventLogger new];
- _nowPlayingInfoCenterProvider = [NowPlayingInfoCenterProvider new];
-
return self;
}
@@ -80,4 +78,13 @@ - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:
return YES;
}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ [[AVPlayerViewControllerManager shared]disconnectPlayer];
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ [[AVPlayerViewControllerManager shared]reconnectPlayerWithRootViewController:self.window.rootViewController];
+}
+
@end
diff --git a/XCDYouTubeKit Demo/iOS Demo/DemoAsynchronousViewController.m b/XCDYouTubeKit Demo/iOS Demo/DemoAsynchronousViewController.m
index 33f2989f..405b0f06 100644
--- a/XCDYouTubeKit Demo/iOS Demo/DemoAsynchronousViewController.m
+++ b/XCDYouTubeKit Demo/iOS Demo/DemoAsynchronousViewController.m
@@ -6,7 +6,9 @@
#import
-#import "MPMoviePlayerController+BackgroundPlayback.h"
+#import
+
+#import "XCDYouTubeKit_iOS_Demo-Swift.h"
@implementation DemoAsynchronousViewController
@@ -21,18 +23,38 @@ - (IBAction) play:(id)sender
{
NSString *apiKey = self.apiKeyTextField.text;
[[NSUserDefaults standardUserDefaults] setObject:apiKey forKey:@"YouTubeAPIKey"];
-
- XCDYouTubeVideoPlayerViewController *videoPlayerViewController = [XCDYouTubeVideoPlayerViewController new];
- videoPlayerViewController.moviePlayer.backgroundPlaybackEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"PlayVideoInBackground"];
- [self presentMoviePlayerViewControllerAnimated:videoPlayerViewController];
-
+
// https://developers.google.com/youtube/v3/docs/videos/list
NSURL *mostPopularURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://www.googleapis.com/youtube/v3/videos?key=%@&chart=mostPopular&part=id", apiKey]];
- [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:mostPopularURL] queue:[NSOperationQueue new] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
- {
+
+ [[[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]]dataTaskWithURL:mostPopularURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
+ {
+ if (error) {
+ [[Utilities shared]displayError:error originViewController:self];
+ return;
+ }
+
id json = [NSJSONSerialization JSONObjectWithData:data ?: [NSData new] options:0 error:NULL];
NSString *videoIdentifier = [[[json valueForKeyPath:@"items.id"] firstObject] description];
- videoPlayerViewController.videoIdentifier = videoIdentifier;
+ [self displayVideoIdentifier:videoIdentifier];
+ }] resume];
+}
+
+- (void) displayVideoIdentifier:(NSString *)videoIdentifier
+{
+
+ [[XCDYouTubeClient defaultClient]getVideoWithIdentifier:videoIdentifier completionHandler:^(XCDYouTubeVideo * _Nullable video, NSError * _Nullable error)
+ {
+ if (error) {
+ [[Utilities shared]displayError:error originViewController:self];
+ return;
+ }
+
+ [AVPlayerViewControllerManager shared].video = video;
+ AVPlayerViewController *playerViewController = [AVPlayerViewControllerManager shared].controller;
+ [self presentViewController:playerViewController animated:YES completion:nil];
+ [playerViewController.player play];
+
}];
}
diff --git a/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.h b/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.h
deleted file mode 100644
index 2085880d..00000000
--- a/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-// Copyright (c) 2013-2016 Cédric Luthi. All rights reserved.
-//
-
-@import UIKit;
-
-#import "VideoPickerController.h"
-
-@interface DemoFullScreenViewController : UIViewController
-
-@property (nonatomic, weak) IBOutlet UITextField *videoIdentifierTextField;
-@property (nonatomic, weak) IBOutlet UISwitch *lowQualitySwitch;
-
-- (IBAction) play:(id)sender;
-
-@end
diff --git a/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.m b/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.m
deleted file mode 100644
index 92438df4..00000000
--- a/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.m
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// Copyright (c) 2013-2016 Cédric Luthi. All rights reserved.
-//
-
-#import "DemoFullScreenViewController.h"
-
-#import
-
-#import "MPMoviePlayerController+BackgroundPlayback.h"
-
-@implementation DemoFullScreenViewController
-
-- (void) viewDidLoad
-{
- [super viewDidLoad];
-
- [self restoreVideoIdentifier];
-}
-
-- (void) saveVideoIdentifier
-{
- [[NSUserDefaults standardUserDefaults] setObject:self.videoIdentifierTextField.text forKey:@"VideoIdentifier"];
-}
-
-- (void) restoreVideoIdentifier
-{
- self.videoIdentifierTextField.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"VideoIdentifier"];
-}
-
-- (IBAction) endEditing:(id)sender
-{
- [self.view endEditing:YES];
-}
-
-- (IBAction) play:(id)sender
-{
- XCDYouTubeVideoPlayerViewController *videoPlayerViewController = [[XCDYouTubeVideoPlayerViewController alloc] initWithVideoIdentifier:self.videoIdentifierTextField.text];
- videoPlayerViewController.moviePlayer.backgroundPlaybackEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"PlayVideoInBackground"];
- videoPlayerViewController.preferredVideoQualities = self.lowQualitySwitch.on ? @[ @(XCDYouTubeVideoQualitySmall240), @(XCDYouTubeVideoQualityMedium360) ] : nil;
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerPlaybackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:videoPlayerViewController.moviePlayer];
- [self presentMoviePlayerViewControllerAnimated:videoPlayerViewController];
-}
-
-#pragma mark - Notifications
-
-- (void) moviePlayerPlaybackDidFinish:(NSNotification *)notification
-{
- [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:notification.object];
- MPMovieFinishReason finishReason = [notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] integerValue];
- if (finishReason == MPMovieFinishReasonPlaybackError)
- {
- NSString *title = NSLocalizedString(@"Video Playback Error", @"Full screen video error alert - title");
- NSError *error = notification.userInfo[XCDMoviePlayerPlaybackDidFinishErrorUserInfoKey];
- NSString *message = [NSString stringWithFormat:@"%@\n%@ (%@)", error.localizedDescription, error.domain, @(error.code)];
- NSString *cancelButtonTitle = NSLocalizedString(@"OK", @"Full screen video error alert - cancel button");
- UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil];
- [alertView show];
- }
-}
-
-
-#pragma mark - UITextFieldDelegate
-
-- (BOOL) textFieldShouldReturn:(UITextField *)textField
-{
- [self play:textField];
- return YES;
-}
-
-- (void) textFieldDidEndEditing:(UITextField *)textField
-{
- [self saveVideoIdentifier];
-}
-
-#pragma mark - VideoPickerControllerDelegate
-
-- (void) videoPickerController:(VideoPickerController *)videoPickerController didSelectVideoWithIdentifier:(NSString *)videoIdentifier
-{
- self.videoIdentifierTextField.text = videoIdentifier;
- [self saveVideoIdentifier];
-}
-
-@end
diff --git a/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.swift b/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.swift
new file mode 100644
index 00000000..0a42b55b
--- /dev/null
+++ b/XCDYouTubeKit Demo/iOS Demo/DemoFullScreenViewController.swift
@@ -0,0 +1,60 @@
+//
+// DemoFullScreenViewController.swift
+// XCDYouTubeKit iOS Demo
+//
+// Created by Soneé John on 10/17/19.
+// Copyright © 2019 Cédric Luthi. All rights reserved.
+//
+
+import UIKit
+import AVKit
+import XCDYouTubeKit
+
+extension DemoFullScreenViewController: VideoPickerControllerDelegate {
+ func videoPickerController(_ videoPickerController: VideoPickerController!, didSelectVideoWithIdentifier videoIdentifier: String!) {
+ self.videoIdentifierTextField.text = videoIdentifier
+ UserDefaults.standard.set(videoIdentifier, forKey: "VideoIdentifier")
+ }
+}
+
+extension DemoFullScreenViewController: UITextFieldDelegate {
+ func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+ self.play(textField)
+ return true
+ }
+
+ func textFieldDidEndEditing(_ textField: UITextField) {
+ UserDefaults.standard.set(self.videoIdentifierTextField.text, forKey: "VideoIdentifier")
+ }
+}
+
+class DemoFullScreenViewController: UIViewController {
+
+ @IBOutlet weak open var lowQualitySwitch: UISwitch!
+ @IBOutlet weak open var videoIdentifierTextField: UITextField!
+ var ob: NSKeyValueObservation?
+ private var timeObserverToken: Any?
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ self.videoIdentifierTextField.text = UserDefaults.standard.string(forKey: "VideoIdentifier")
+ }
+
+ @IBAction open func endEditing(_ sender: Any!) {
+ self.view.endEditing(true)
+ }
+
+ @IBAction open func play(_ sender: Any!) {
+ XCDYouTubeClient.default().getVideoWithIdentifier(self.videoIdentifierTextField.text) { (video, error) in
+ guard error == nil else {
+ Utilities.shared.displayError(error! as NSError, originViewController: self)
+ return
+ }
+ AVPlayerViewControllerManager.shared.lowQualityMode = self.lowQualitySwitch.isOn
+ AVPlayerViewControllerManager.shared.video = video
+ self.present(AVPlayerViewControllerManager.shared.controller, animated: true) {
+ AVPlayerViewControllerManager.shared.controller.player?.play()
+ }
+ }
+ }
+}
diff --git a/XCDYouTubeKit Demo/iOS Demo/DemoInlineViewController.h b/XCDYouTubeKit Demo/iOS Demo/DemoInlineViewController.h
index cc4596bc..3531a67b 100644
--- a/XCDYouTubeKit Demo/iOS Demo/DemoInlineViewController.h
+++ b/XCDYouTubeKit Demo/iOS Demo/DemoInlineViewController.h
@@ -7,10 +7,8 @@
@interface DemoInlineViewController : UIViewController
@property (nonatomic, weak) IBOutlet UIView *videoContainerView;
-@property (nonatomic, weak) IBOutlet UISwitch *prepareToPlaySwitch;
@property (nonatomic, weak) IBOutlet UISwitch *shouldAutoplaySwitch;
- (IBAction) load:(id)sender;
-- (IBAction) prepareToPlay:(UISwitch *)sender;
@end
diff --git a/XCDYouTubeKit Demo/iOS Demo/DemoInlineViewController.m b/XCDYouTubeKit Demo/iOS Demo/DemoInlineViewController.m
index 6c2d7e03..df910489 100644
--- a/XCDYouTubeKit Demo/iOS Demo/DemoInlineViewController.m
+++ b/XCDYouTubeKit Demo/iOS Demo/DemoInlineViewController.m
@@ -6,44 +6,40 @@
#import
-#import "MPMoviePlayerController+BackgroundPlayback.h"
+#import
-@interface DemoInlineViewController ()
-
-@property (nonatomic, strong) XCDYouTubeVideoPlayerViewController *videoPlayerViewController;
-
-@end
+#import "XCDYouTubeKit_iOS_Demo-Swift.h"
@implementation DemoInlineViewController
-- (void) viewWillDisappear:(BOOL)animated
-{
+
+- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
- // Beware, viewWillDisappear: is called when the player view enters full screen on iOS 6+
- if ([self isMovingFromParentViewController])
- [self.videoPlayerViewController.moviePlayer stop];
+ [[AVPlayerViewControllerManager shared].controller.player pause];
}
-
- (IBAction) load:(id)sender
{
- [self.videoContainerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
-
NSString *videoIdentifier = [[NSUserDefaults standardUserDefaults] objectForKey:@"VideoIdentifier"];
- self.videoPlayerViewController = [[XCDYouTubeVideoPlayerViewController alloc] initWithVideoIdentifier:videoIdentifier];
- self.videoPlayerViewController.moviePlayer.backgroundPlaybackEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"PlayVideoInBackground"];
- [self.videoPlayerViewController presentInView:self.videoContainerView];
-
- if (self.prepareToPlaySwitch.on)
- [self.videoPlayerViewController.moviePlayer prepareToPlay];
-
- self.videoPlayerViewController.moviePlayer.shouldAutoplay = self.shouldAutoplaySwitch.on;
-}
-- (IBAction) prepareToPlay:(UISwitch *)sender
-{
- if (sender.on)
- [self.videoPlayerViewController.moviePlayer prepareToPlay];
+ [[XCDYouTubeClient defaultClient] getVideoWithIdentifier:videoIdentifier completionHandler:^(XCDYouTubeVideo * _Nullable video, NSError * _Nullable error) {
+ if (video)
+ {
+ [AVPlayerViewControllerManager shared].video = video;
+ AVPlayerViewController *playerViewController = [AVPlayerViewControllerManager shared].controller;
+ playerViewController.view.frame = self.videoContainerView.bounds;
+ [self addChildViewController:playerViewController];
+ [self.videoContainerView addSubview:playerViewController.view];
+ [playerViewController didMoveToParentViewController:self];
+
+ if (self.shouldAutoplaySwitch.on)
+ [playerViewController.player play];
+ }
+ else
+ {
+ [[Utilities shared]displayError:error originViewController:self];
+ }
+ }];
}
@end
diff --git a/XCDYouTubeKit Demo/iOS Demo/DemoThumbnailViewController.m b/XCDYouTubeKit Demo/iOS Demo/DemoThumbnailViewController.m
index 588d19d9..de66659e 100644
--- a/XCDYouTubeKit Demo/iOS Demo/DemoThumbnailViewController.m
+++ b/XCDYouTubeKit Demo/iOS Demo/DemoThumbnailViewController.m
@@ -6,11 +6,13 @@
#import
-#import "MPMoviePlayerController+BackgroundPlayback.h"
+#import
+
+#import "XCDYouTubeKit_iOS_Demo-Swift.h"
@interface DemoThumbnailViewController ()
-@property (nonatomic, strong) XCDYouTubeVideoPlayerViewController *videoPlayerViewController;
+@property (nonatomic, strong) XCDYouTubeVideo *video;
@end
@@ -19,46 +21,48 @@ @implementation DemoThumbnailViewController
- (IBAction) loadThumbnail:(id)sender
{
NSString *videoIdentifier = [[NSUserDefaults standardUserDefaults] objectForKey:@"VideoIdentifier"];
- self.videoPlayerViewController = [[XCDYouTubeVideoPlayerViewController alloc] initWithVideoIdentifier:videoIdentifier];
- self.videoPlayerViewController.moviePlayer.backgroundPlaybackEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"PlayVideoInBackground"];
- NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
- [defaultCenter addObserver:self selector:@selector(videoPlayerViewControllerDidReceiveVideo:) name:XCDYouTubeVideoPlayerViewControllerDidReceiveVideoNotification object:self.videoPlayerViewController];
- [defaultCenter addObserver:self selector:@selector(moviePlayerPlaybackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:self.videoPlayerViewController.moviePlayer];
+ [[XCDYouTubeClient defaultClient]getVideoWithIdentifier:videoIdentifier completionHandler:^(XCDYouTubeVideo * _Nullable video, NSError * _Nullable error)
+ {
+ if (error) {
+ [[Utilities shared]displayError:error originViewController:self];
+ return;
+ }
+
+ [self displayThumbnailWithVideo:video];
+
+ }];
}
- (IBAction) play:(id)sender
{
- [self.videoPlayerViewController presentInView:self.videoContainerView];
- [self.videoPlayerViewController.moviePlayer play];
+ [AVPlayerViewControllerManager shared].video = self.video;
+ AVPlayerViewController *playerViewController = [AVPlayerViewControllerManager shared].controller;
+ [self presentViewController:playerViewController animated:YES completion:nil];
+ [playerViewController.player play];
}
-#pragma mark - Notifications
-
-- (void) videoPlayerViewControllerDidReceiveVideo:(NSNotification *)notification
+- (void) displayThumbnailWithVideo:(XCDYouTubeVideo *)video
{
- XCDYouTubeVideo *video = notification.userInfo[XCDYouTubeVideoUserInfoKey];
+ self.video = video;
self.titleLabel.text = video.title;
-
- NSURL *thumbnailURL = video.mediumThumbnailURL ?: video.smallThumbnailURL;
- [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:thumbnailURL] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
- {
- self.thumbnailImageView.image = [UIImage imageWithData:data];
-
- [self.actionButton setTitle:NSLocalizedString(@"Play Video", nil) forState:UIControlStateNormal];
- [self.actionButton removeTarget:self action:NULL forControlEvents:UIControlEventAllEvents];
- [self.actionButton addTarget:self action:@selector(play:) forControlEvents:UIControlEventTouchUpInside];
- }];
-}
+ NSURL *thumbnailURL = video.thumbnailURL;
-- (void) moviePlayerPlaybackDidFinish:(NSNotification *)notification
-{
- NSError *error = notification.userInfo[XCDMoviePlayerPlaybackDidFinishErrorUserInfoKey];
- if (error)
- {
- UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:error.localizedDescription delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil];
- [alertView show];
- }
+ [[[NSURLSession sharedSession]dataTaskWithURL:thumbnailURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
+ {
+ if (error) {
+ [[Utilities shared]displayError:error originViewController:self];
+ return;
+ }
+
+ [[NSOperationQueue mainQueue]addOperationWithBlock:^{
+ self.thumbnailImageView.image = [UIImage imageWithData:data];
+ [self.actionButton setTitle:NSLocalizedString(@"Play Video", nil) forState:UIControlStateNormal];
+ [self.actionButton removeTarget:self action:NULL forControlEvents:UIControlEventAllEvents];
+ [self.actionButton addTarget:self action:@selector(play:) forControlEvents:UIControlEventTouchUpInside];
+ }];
+
+ }] resume];
}
@end
diff --git a/XCDYouTubeKit Demo/iOS Demo/MPMoviePlayerController+BackgroundPlayback.h b/XCDYouTubeKit Demo/iOS Demo/MPMoviePlayerController+BackgroundPlayback.h
deleted file mode 100644
index 30c6b242..00000000
--- a/XCDYouTubeKit Demo/iOS Demo/MPMoviePlayerController+BackgroundPlayback.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Copyright (c) 2013-2016 Cédric Luthi. All rights reserved.
-//
-
-@import MediaPlayer;
-
-@interface MPMoviePlayerController (BackgroundPlayback)
-
-/**
- * When enabling background playback:
- * - The `UIBackgroundModes` array (Required background modes) in the application Info.plist file must contain the `audio` element (App plays audio or streams audio/video using AirPlay).
- * - The audio session category must be set to `AVAudioSessionCategoryPlayback`.
- *
- * @discussion On iOS < 7, the `backgroundPlaybackEnabled` property does nothing. Instead, you must set the `PlayVideoInBackground` boolean user default used by the MediaPlayer framework. The `PlayVideoInBackground` user default must be set before a `MPMoviePlayerController` object is created.
- */
-@property (nonatomic, assign, getter = isBackgroundPlaybackEnabled) BOOL backgroundPlaybackEnabled;
-
-@end
diff --git a/XCDYouTubeKit Demo/iOS Demo/MPMoviePlayerController+BackgroundPlayback.m b/XCDYouTubeKit Demo/iOS Demo/MPMoviePlayerController+BackgroundPlayback.m
deleted file mode 100644
index 510d0fa3..00000000
--- a/XCDYouTubeKit Demo/iOS Demo/MPMoviePlayerController+BackgroundPlayback.m
+++ /dev/null
@@ -1,119 +0,0 @@
-//
-// Copyright (c) 2013-2016 Cédric Luthi. All rights reserved.
-//
-
-#import "MPMoviePlayerController+BackgroundPlayback.h"
-
-@import AVFoundation;
-@import ObjectiveC;
-
-#ifndef NSFoundationVersionNumber_iOS_7_0
-#define NSFoundationVersionNumber_iOS_7_0 1047.2
-#endif
-
-@implementation MPMoviePlayerController (BackgroundPlayback)
-
-+ (void) load
-{
- // On iOS 7, working with playerLayer.player as documented in Technical Q&A QA1668 works fine.
- // On iOS 5 and 6, setting playerLayer.player to nil is not enough for background playback when locking the device, the `PlayVideoInBackground` user default must be used instead.
- if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_7_0)
- return;
-
- dispatch_async(dispatch_get_main_queue(), ^{
- // Register for these notifications as early as possible in order to be called before -[MPAVController _applicationWillResignActive:] which calls `_pausePlaybackIfNecessary`.
- NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
- [defaultCenter addObserver:self selector:@selector(backgroundPlayback_moviePlayerNowPlayingMovieDidChange:) name:MPMoviePlayerNowPlayingMovieDidChangeNotification object:nil];
- [defaultCenter addObserver:self selector:@selector(backgroundPlayback_moviePlayerPlaybackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
- [defaultCenter addObserver:self selector:@selector(backgroundPlayback_applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
- [defaultCenter addObserver:self selector:@selector(backgroundPlayback_applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
- });
-}
-
-static const void * const BackgroundPlaybackEnabledKey = &BackgroundPlaybackEnabledKey;
-
-- (BOOL) isBackgroundPlaybackEnabled
-{
- return [objc_getAssociatedObject(self, BackgroundPlaybackEnabledKey) boolValue];
-}
-
-- (void) setBackgroundPlaybackEnabled:(BOOL)backgroundPlaybackEnabled
-{
- if (backgroundPlaybackEnabled)
- {
- NSArray *backgroundModes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIBackgroundModes"];
- if (!backgroundModes || ([backgroundModes isKindOfClass:[NSArray class]] && ![backgroundModes containsObject:@"audio"]))
- NSLog(@"ERROR: The `UIBackgroundModes` array in the application Info.plist file must contain the `audio` element for background playback.");
- }
-
- objc_setAssociatedObject(self, BackgroundPlaybackEnabledKey, @(backgroundPlaybackEnabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-}
-
-static __weak MPMoviePlayerController *currentMoviePlayerController;
-
-+ (void) backgroundPlayback_moviePlayerNowPlayingMovieDidChange:(NSNotification *)notification
-{
- currentMoviePlayerController = notification.object;
-}
-
-+ (void) backgroundPlayback_moviePlayerPlaybackDidFinish:(NSNotification *)notification
-{
- currentMoviePlayerController = nil;
-}
-
-__attribute__((overloadable))
-static AVPlayerLayer * PlayerLayer(void)
-{
- // When an inline movie player controller goes fullscreen, its view is somehow transferred to the key window.
- return PlayerLayer(currentMoviePlayerController.view) ?: PlayerLayer([[UIApplication sharedApplication] keyWindow]);
-}
-
-// Since MPMoviePlayerController doesn't expose its AVFoundation internals, traversing its subviews is the least worst solution to access its AVPlayerLayer.
-// See Technical Q&A QA1668 - Playing media while in the background using AV Foundation on iOS https://developer.apple.com/library/ios/qa/qa1668/_index.html
-__attribute__((overloadable))
-static AVPlayerLayer * PlayerLayer(UIView *view)
-{
- AVPlayerLayer *playerLayer = nil;
- if ([view.layer isKindOfClass:[AVPlayerLayer class]])
- {
- playerLayer = (AVPlayerLayer *)view.layer;
- }
- else
- {
- for (UIView *subview in view.subviews)
- {
- playerLayer = PlayerLayer(subview);
- if (playerLayer)
- break;
- }
- }
- return playerLayer;
-}
-
-static const void * const PlayerKey = &PlayerKey;
-
-+ (void) backgroundPlayback_applicationWillResignActive:(NSNotification *)notification
-{
- if (!currentMoviePlayerController)
- return;
-
- AVPlayerLayer *playerLayer = PlayerLayer();
- objc_setAssociatedObject(currentMoviePlayerController, PlayerKey, playerLayer.player, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- if (currentMoviePlayerController.isBackgroundPlaybackEnabled)
- {
- if (![[[AVAudioSession sharedInstance] category] isEqualToString:AVAudioSessionCategoryPlayback])
- NSLog(@"ERROR: The audio session category must be `AVAudioSessionCategoryPlayback` when background playback is enabled.");
-
- playerLayer.player = nil;
- }
-}
-
-+ (void) backgroundPlayback_applicationDidBecomeActive:(NSNotification *)notification
-{
- AVPlayerLayer *playerLayer = PlayerLayer();
- AVPlayer *player = objc_getAssociatedObject(currentMoviePlayerController, PlayerKey);
- if (player)
- playerLayer.player = player;
-}
-
-@end
diff --git a/XCDYouTubeKit Demo/iOS Demo/SettingsViewController.m b/XCDYouTubeKit Demo/iOS Demo/SettingsViewController.m
index a0234fe2..a63f2d58 100644
--- a/XCDYouTubeKit Demo/iOS Demo/SettingsViewController.m
+++ b/XCDYouTubeKit Demo/iOS Demo/SettingsViewController.m
@@ -8,7 +8,6 @@
@interface SettingsViewController ()
-@property (nonatomic, weak) IBOutlet UISwitch *playVideoInBackgroundSwitch;
@property (nonatomic, weak) IBOutlet UILabel *audioSessionCategoryLabel;
@property (nonatomic, weak) IBOutlet UILabel *versionLabel;
@@ -20,29 +19,17 @@ - (void) viewDidLoad
{
[super viewDidLoad];
- self.playVideoInBackgroundSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"PlayVideoInBackground"];
- self.audioSessionCategoryLabel.text = [[AVAudioSession sharedInstance] category];
+ if (@available(iOS 13.0, *)) {
+ self.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
+ }
+ self.audioSessionCategoryLabel.text = [[AVAudioSession sharedInstance] category];
NSBundle *bundle = [NSBundle bundleWithIdentifier:@"ch.pitaya.xcdyoutubekit"];
self.versionLabel.text = [NSString stringWithFormat:@"Version %@ (%@)", [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"], [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]];
}
#pragma mark - Actions
-- (IBAction) togglePlayVideoInBackground:(UISwitch *)sender
-{
- /**
- * `PlayVideoInBackground` is a user default used by the MediaPlayer framework which controls whether a `MPMoviePlayerController` continues playing videos while in the background.
- *
- * In addition to the `PlayVideoInBackground` user default, background playback requires:
- * - The `UIBackgroundModes` array (Required background modes) in the application Info.plist file must contain the `audio` element (App plays audio or streams audio/video using AirPlay).
- * - The audio session category must be set to `AVAudioSessionCategoryPlayback`.
- *
- * On iOS 7, changing the `PlayVideoInBackground` user default has no effect. See MPMoviePlayerController+BackgroundPlayback for a solution.
- */
- [[NSUserDefaults standardUserDefaults] setBool:self.playVideoInBackgroundSwitch.on forKey:@"PlayVideoInBackground"];
-}
-
- (IBAction) selectAudioSessionCategory:(UIButton *)sender
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"Audio Session Category", nil) delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel", nil) destructiveButtonTitle:nil otherButtonTitles:NSLocalizedString(@"Solo Ambient", nil), NSLocalizedString(@"Playback", nil), nil];
diff --git a/XCDYouTubeKit Demo/iOS Demo/Utilities.swift b/XCDYouTubeKit Demo/iOS Demo/Utilities.swift
new file mode 100644
index 00000000..a4393929
--- /dev/null
+++ b/XCDYouTubeKit Demo/iOS Demo/Utilities.swift
@@ -0,0 +1,23 @@
+//
+// Utilities.swift
+// XCDYouTubeKit iOS Demo
+//
+// Created by Soneé John on 10/24/19.
+// Copyright © 2019 Cédric Luthi. All rights reserved.
+//
+
+import UIKit
+
+@objcMembers class Utilities: NSObject {
+ static let shared = Utilities()
+
+ func displayError(_ error: NSError, originViewController: UIViewController) {
+ OperationQueue.main.addOperation {
+ originViewController.dismiss(animated: true) {
+ let alert = UIAlertController(title: NSLocalizedString("Error", comment: ""), message: error.localizedDescription, preferredStyle: .alert)
+ alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
+ originViewController.present(alert, animated: true, completion: nil)
+ }
+ }
+ }
+}
diff --git a/XCDYouTubeKit Demo/iOS Demo/XCDYouTubeKit iOS Demo-Bridging-Header.h b/XCDYouTubeKit Demo/iOS Demo/XCDYouTubeKit iOS Demo-Bridging-Header.h
new file mode 100644
index 00000000..76d1cafe
--- /dev/null
+++ b/XCDYouTubeKit Demo/iOS Demo/XCDYouTubeKit iOS Demo-Bridging-Header.h
@@ -0,0 +1,6 @@
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import "VideoPickerController.h"
+#import
diff --git a/XCDYouTubeKit Demo/iOS Demo/en.lproj/MainStoryboard.storyboard b/XCDYouTubeKit Demo/iOS Demo/en.lproj/MainStoryboard.storyboard
index bdae45be..c31579cd 100644
--- a/XCDYouTubeKit Demo/iOS Demo/en.lproj/MainStoryboard.storyboard
+++ b/XCDYouTubeKit Demo/iOS Demo/en.lproj/MainStoryboard.storyboard
@@ -1,8 +1,10 @@
-
-
+
+
+
-
+
+
@@ -11,8 +13,8 @@
+
-
@@ -20,86 +22,60 @@
-
+
+
+
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
-
-
+
-
-
+
@@ -110,114 +86,104 @@
-
-
+
-
+
-
-
+
-
+
-
+
-
+
-
-
-
+
+
-
-
+
-
+
-
+
-
+
-
-
-
+
+
-
-
+
-
+
-
+
-
+
-
-
-
+
+
-
-
+
-
+
-
+
-
+
-
-
-
+
+
-
-
+
@@ -236,59 +202,57 @@
-
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
+
-
+
-
+
-
-
-
+
-
+
-
-
-
+
-
-
+
@@ -300,45 +264,45 @@
-
+
+
+
+
+
-
+
-
-
+
+
-
-
+
-
-
+
+
-
-
-
+
+
-
-
+
-
-
+
@@ -347,78 +311,73 @@
-
+
-
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
+
-
+
-
-
+
-
-
+
-
+
-
-
+
-
-
-
-
-
+
+
-
-
-
+
@@ -449,91 +408,73 @@
-
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
+
-
+
-
-
+
-
-
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+
+
-
@@ -541,7 +482,7 @@
-
+
diff --git a/XCDYouTubeKit.podspec b/XCDYouTubeKit.podspec
index fc0c8c64..3636cc32 100644
--- a/XCDYouTubeKit.podspec
+++ b/XCDYouTubeKit.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "XCDYouTubeKit"
- s.version = "2.8.1"
+ s.version = "2.8.2"
s.summary = "YouTube video player for iOS and OS X."
s.homepage = "https://github.com/0xced/XCDYouTubeKit"
s.screenshot = "https://raw.github.com/0xced/XCDYouTubeKit/#{s.version}/Screenshots/XCDYouTubeVideoPlayerViewController.png"
diff --git a/XCDYouTubeKit.xcodeproj/project.pbxproj b/XCDYouTubeKit.xcodeproj/project.pbxproj
index 9412e4d1..9e5a0946 100644
--- a/XCDYouTubeKit.xcodeproj/project.pbxproj
+++ b/XCDYouTubeKit.xcodeproj/project.pbxproj
@@ -613,10 +613,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 40;
+ CURRENT_PROJECT_VERSION = 41;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 2.0.0;
- DYLIB_CURRENT_VERSION = 2.8.1;
+ DYLIB_CURRENT_VERSION = 2.8.2;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -691,10 +691,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 40;
+ CURRENT_PROJECT_VERSION = 41;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 2.0.0;
- DYLIB_CURRENT_VERSION = 2.8.1;
+ DYLIB_CURRENT_VERSION = 2.8.2;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
diff --git a/XCDYouTubeKit/XCDYouTubeClient.h b/XCDYouTubeKit/XCDYouTubeClient.h
index 2b89201c..e9a2778a 100644
--- a/XCDYouTubeKit/XCDYouTubeClient.h
+++ b/XCDYouTubeKit/XCDYouTubeClient.h
@@ -11,9 +11,9 @@
#import
-#import
-#import
-#import
+#import "XCDYouTubeOperation.h"
+#import "XCDYouTubeVideo.h"
+#import "XCDYouTubeError.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/XCDYouTubeKit/XCDYouTubeKit.h b/XCDYouTubeKit/XCDYouTubeKit.h
index 250ef88f..bff607ef 100644
--- a/XCDYouTubeKit/XCDYouTubeKit.h
+++ b/XCDYouTubeKit/XCDYouTubeKit.h
@@ -4,13 +4,14 @@
#import
-#import
-#import
-#import
-#import
-#import
-#import
+#import "XCDYouTubeClient.h"
+#import "XCDYouTubeError.h"
+#import "XCDYouTubeLogger.h"
+#import "XCDYouTubeOperation.h"
+#import "XCDYouTubeVideo.h"
+#import "XCDYouTubeVideoOperation.h"
+
#if TARGET_OS_IOS || (!defined(TARGET_OS_IOS) && TARGET_OS_IPHONE)
-#import
+#import "XCDYouTubeVideoPlayerViewController.h"
#endif
diff --git a/XCDYouTubeKit/XCDYouTubeVideo+Private.h b/XCDYouTubeKit/XCDYouTubeVideo+Private.h
index 3f1c196c..54c0c3cd 100644
--- a/XCDYouTubeKit/XCDYouTubeVideo+Private.h
+++ b/XCDYouTubeKit/XCDYouTubeVideo+Private.h
@@ -2,7 +2,7 @@
// Copyright (c) 2013-2016 Cédric Luthi. All rights reserved.
//
-#import
+#import "XCDYouTubeVideo.h"
#import "XCDYouTubePlayerScript.h"
diff --git a/XCDYouTubeKit/XCDYouTubeVideo.h b/XCDYouTubeKit/XCDYouTubeVideo.h
index 7668a930..4cd09143 100644
--- a/XCDYouTubeKit/XCDYouTubeVideo.h
+++ b/XCDYouTubeKit/XCDYouTubeVideo.h
@@ -106,6 +106,13 @@ extern NSString *const XCDYouTubeVideoQualityHTTPLiveStreaming;
@property (nonatomic, readonly) NSDictionary *streamURLs;
#endif
+/**
+
+* A streamURL that is compatible on Apple devices.
+* The `streamURLs` may contain both video and audio streams, some video streams do not contain any audio. This property will return a video stream that contains both audio and video with a maximum video quality of 720p in the case of videos that aren't live. Also, this properly will return the URL to a live stream in the case of live videos.
+*/
+@property (nonatomic, readonly) NSURL *streamURL;
+
/**
* A dictionary of caption URLs (XML).
diff --git a/XCDYouTubeKit/XCDYouTubeVideo.m b/XCDYouTubeKit/XCDYouTubeVideo.m
index 02cd7f33..8769b753 100644
--- a/XCDYouTubeKit/XCDYouTubeVideo.m
+++ b/XCDYouTubeKit/XCDYouTubeVideo.m
@@ -280,6 +280,8 @@ - (instancetype) initWithIdentifier:(NSString *)identifier info:(NSDictionary *)
}
}
+ _streamURL = _streamURLs[XCDYouTubeVideoQualityHTTPLiveStreaming] ?: _streamURLs[@(XCDYouTubeVideoQualityHD720)] ?: _streamURLs[@(XCDYouTubeVideoQualityMedium360)] ?: _streamURLs[@(XCDYouTubeVideoQualitySmall240)];
+
return self;
}
else
diff --git a/XCDYouTubeKit/XCDYouTubeVideoOperation.h b/XCDYouTubeKit/XCDYouTubeVideoOperation.h
index 4ee8b7b0..644aa4ef 100644
--- a/XCDYouTubeKit/XCDYouTubeVideoOperation.h
+++ b/XCDYouTubeKit/XCDYouTubeVideoOperation.h
@@ -10,8 +10,8 @@
#import
-#import
-#import
+#import "XCDYouTubeOperation.h"
+#import "XCDYouTubeVideo.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/XCDYouTubeKit/XCDYouTubeVideoPlayerViewController.h b/XCDYouTubeKit/XCDYouTubeVideoPlayerViewController.h
index 812ee9c1..c4c3a4f6 100644
--- a/XCDYouTubeKit/XCDYouTubeVideoPlayerViewController.h
+++ b/XCDYouTubeKit/XCDYouTubeVideoPlayerViewController.h
@@ -9,6 +9,10 @@
#define null_resettable
#endif
+#import
+
+#if TARGET_OS_IOS
+
#import
NS_ASSUME_NONNULL_BEGIN
@@ -124,3 +128,5 @@ MP_EXTERN NSString *const XCDMetadataKeyMediumThumbnailURL DEPRECATED_MSG_ATTRIB
MP_EXTERN NSString *const XCDMetadataKeyLargeThumbnailURL DEPRECATED_MSG_ATTRIBUTE("Use XCDYouTubeVideoUserInfoKey instead.");
NS_ASSUME_NONNULL_END
+
+#endif
diff --git a/XCDYouTubeKit/XCDYouTubeVideoPlayerViewController.m b/XCDYouTubeKit/XCDYouTubeVideoPlayerViewController.m
index ebec6c3c..54a77fe8 100644
--- a/XCDYouTubeKit/XCDYouTubeVideoPlayerViewController.m
+++ b/XCDYouTubeKit/XCDYouTubeVideoPlayerViewController.m
@@ -8,6 +8,8 @@
#import
+#if TARGET_OS_IOS
+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSString *const XCDMoviePlayerPlaybackDidFinishErrorUserInfoKey = @"error"; // documented in -[MPMoviePlayerController initWithContentURL:]
@@ -207,3 +209,4 @@ - (void) viewWillDisappear:(BOOL)animated
}
@end
+#endif