Skip to content

Commit

Permalink
Merge branch 'release/2.12.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
SoneeJohn committed Feb 24, 2020
2 parents 1553a2b + 2a31f4d commit 50592e3
Show file tree
Hide file tree
Showing 15 changed files with 2,347 additions and 26 deletions.
4 changes: 2 additions & 2 deletions .jazzy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ source_directory: XCDYouTubeKit
framework_root: .
umbrella_header: XCDYouTubeKit/XCDYouTubeKit.h
module: XCDYouTubeKit
module_version: 2.11.0
module_version: 2.12.0

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.11.0/XCDYouTubeKit
github_file_prefix: https://github.com/0xced/XCDYouTubeKit/tree/2.12.0/XCDYouTubeKit
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#### Version 2.12.0

* Add the ability to specify which `streamURLs` to query via `-[XCDYouTubeClient queryVideo:video:streamURLsToQuery:options:cookies:completionHandler:]` & `XCDYouTubeVideoQueryOperation` class.
* `initWithVideo:streamURLsToQuery:options:cookies:` is now the designated initializer for `XCDYouTubeVideoQueryOperation`.
* Correctly annotate the `streamURLs` & `streamErrors` properties as `nullable`.

#### Version 2.11.0

* `-[XCDYouTubeClient queryVideo:video:cookies:completionHandler:]` completion handler is now correctly called on the main thread.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ XCDYouTubeKit is available through [CocoaPods](https://cocoapods.org/), [Carthag
CocoaPods:

```ruby
pod "XCDYouTubeKit", "~> 2.11"
pod "XCDYouTubeKit", "~> 2.12"
```

Carthage:

```objc
github "0xced/XCDYouTubeKit" ~> 2.11
github "0xced/XCDYouTubeKit" ~> 2.12
```

Swift Package Manager:
Expand All @@ -48,7 +48,7 @@ Add `XCDYouTubeKit` to the dependencies value of your `Package.swift`

```swift
dependencies: [
.package(url: "https://github.com/0xced/XCDYouTubeKit.git", from: "2.11.0")
.package(url: "https://github.com/0xced/XCDYouTubeKit.git", from: "2.12.0")
]
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.11.0;
CURRENT_PROJECT_VERSION = 2.12.0;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
Expand Down Expand Up @@ -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.11.0;
CURRENT_PROJECT_VERSION = 2.12.0;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

160 changes: 159 additions & 1 deletion XCDYouTubeKit Tests/XCDYouTubeClientTestCase.m
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,165 @@ - (void) testThatQueryingLiveVideoReturnsPlayableStreams
}];
}];

[self waitForExpectationsWithTimeout:900 handler:nil];
[self waitForExpectationsWithTimeout:5 handler:nil];
}

- (void) testQueryingWithSpecifiedStreamURLs
{
/**
* This video `NZzQQ1090wc` {itag 137 & 22) are reachable
* This test ensures that when specifying streamURLs that are in the `video` object that the operation returns only streamURLs that we specified when complete
*/
__weak XCTestExpectation *expectation = [self expectationWithDescription:@""];
[[XCDYouTubeClient defaultClient] getVideoWithIdentifier:@"NZzQQ1090wc" completionHandler:^(XCDYouTubeVideo *video, NSError *error)
{
XCTAssertNotNil(video);
XCTAssertNil(error);

NSArray<NSNumber *>*specifiedStreamiTags = @[@137, @22];
NSMutableDictionary *specifiedStreamURLs = [NSMutableDictionary new];

for (NSNumber *itag in specifiedStreamiTags)
{
if (video.streamURLs[itag])
{
specifiedStreamURLs[itag] = video.streamURLs[itag];
}
}

[[XCDYouTubeClient defaultClient] queryVideo:video streamURLsToQuery:specifiedStreamURLs options:nil cookies:nil completionHandler:^(NSDictionary * _Nullable streamURLs, NSError * _Nullable queryError, NSDictionary<id,NSError *> * _Nullable streamErrors)
{
XCTAssertNil(queryError);
XCTAssertNil(streamErrors);
XCTAssertNotNil(streamURLs);
XCTAssertTrue([NSThread isMainThread]);

for (id key in streamURLs.allKeys)
{
XCTAssertNotNil(streamURLs[key]);
}

XCTAssertEqual(specifiedStreamURLs.count, streamURLs.count, @"`streamURLs` count should be equal since we specified two streams that we know are reachable.");

[expectation fulfill];
}];
}];

[self waitForExpectationsWithTimeout:5 handler:nil];
}

- (void) testQueryingWithSpecifiedStreamURLsSomeNotBeingInVideoObject
{
/**
* This video `NZzQQ1090wc` {itag 137 & 22) are reachable
* This test ensures that when specifying streamURLs (with some not being in `video.streamURLs` that operation completes)
*/
__weak XCTestExpectation *expectation = [self expectationWithDescription:@""];
[[XCDYouTubeClient defaultClient] getVideoWithIdentifier:@"NZzQQ1090wc" completionHandler:^(XCDYouTubeVideo *video, NSError *error)
{
XCTAssertNotNil(video);
XCTAssertNil(error);

NSArray<NSNumber *>*specifiedStreamiTags = @[@137, @22, @1111111];
NSMutableDictionary *specifiedStreamURLs = [NSMutableDictionary new];

for (NSNumber *itag in specifiedStreamiTags)
{
if ([itag isEqual:@1111111] || [itag isEqual:@137])
{
//This will ensure the we do not query keys that are not in the `video` object's `streamURLs` and will ensure that the URL is the same was the value of specified key
specifiedStreamURLs[itag] = [NSURL URLWithString:@"https://www.youtube.com"];
continue;
}

specifiedStreamURLs[itag] = video.streamURLs[itag];
}

[[XCDYouTubeClient defaultClient] queryVideo:video streamURLsToQuery:specifiedStreamURLs options:nil cookies:nil completionHandler:^(NSDictionary * _Nullable streamURLs, NSError * _Nullable queryError, NSDictionary<id,NSError *> * _Nullable streamErrors)
{
XCTAssertNil(queryError);
XCTAssertNil(streamErrors);
XCTAssertNotNil(streamURLs);
XCTAssertTrue([NSThread isMainThread]);

for (id key in streamURLs.allKeys)
{
XCTAssertNotNil(streamURLs[key]);
}

XCTAssertEqual(1, streamURLs.count, @"`streamURLs` should be equal to 1 since we know only 1 of the specified streams would be queried.");
XCTAssertNotNil(streamURLs[@22]);

[expectation fulfill];
}];
}];

[self waitForExpectationsWithTimeout:5 handler:nil];
}

- (void) testQueryingWhenNoSpecifiedURLsAreInVideoObject
{
/**
* This video `NZzQQ1090wc` contains 24 streamURLs that are reachable ( all the URLs returned in `video.streamURLs` that are reachable)
* This test ensure that when none of the specified URLs are contained in `video.streamURLs` that we fallback to using `video.streamURLs` for querying.
*/
__weak XCTestExpectation *expectation = [self expectationWithDescription:@""];
[[XCDYouTubeClient defaultClient] getVideoWithIdentifier:@"NZzQQ1090wc" completionHandler:^(XCDYouTubeVideo *video, NSError *error)
{
XCTAssertNotNil(video);
XCTAssertNil(error);

NSMutableDictionary *specifiedStreamURLs = [NSMutableDictionary new];
specifiedStreamURLs[@1111111] = [NSURL URLWithString:@"https://www.youtube.com"];

[[XCDYouTubeClient defaultClient] queryVideo:video streamURLsToQuery:specifiedStreamURLs options:nil cookies:nil completionHandler:^(NSDictionary * _Nullable streamURLs, NSError * _Nullable queryError, NSDictionary<id,NSError *> * _Nullable streamErrors)
{
XCTAssertNil(queryError);
XCTAssertNil(streamErrors);
XCTAssertNotNil(streamURLs);
XCTAssertTrue([NSThread isMainThread]);

for (id key in streamURLs.allKeys)
{
XCTAssertNotNil(streamURLs[key]);
}

XCTAssertNotEqual(specifiedStreamURLs.count, streamURLs.count, @"`specifiedStreamURLs` should not be equal to `streamURLs` since when no streamURL is contained in `video.streamURLs` we use the `video.streamURLs` for querying. In this test we know `video.streamURLs` contains 24 objects.");

[expectation fulfill];
}];
}];

[self waitForExpectationsWithTimeout:5 handler:nil];
}

-(void) testQueryingWhenSpecifiedURLsAreEmpty
{
__weak XCTestExpectation *expectation = [self expectationWithDescription:@""];
[[XCDYouTubeClient defaultClient] getVideoWithIdentifier:@"NZzQQ1090wc" completionHandler:^(XCDYouTubeVideo *video, NSError *error)
{
XCTAssertNotNil(video);
XCTAssertNil(error);

[[XCDYouTubeClient defaultClient] queryVideo:video streamURLsToQuery:@{} options:nil cookies:nil completionHandler:^(NSDictionary * _Nullable streamURLs, NSError * _Nullable queryError, NSDictionary<id,NSError *> * _Nullable streamErrors)
{
XCTAssertNil(queryError);
XCTAssertNil(streamErrors);
XCTAssertNotNil(streamURLs);
XCTAssertTrue([NSThread isMainThread]);

for (id key in streamURLs.allKeys)
{
XCTAssertNotNil(streamURLs[key]);
}

XCTAssertEqual(video.streamURLs.count, streamURLs.count, @"`streamURLs` count should be equal to `video.streamURLs` since we specified an empty array and should fallback to the `video` object's `streamURLs`. We also, know all the streamsURLs are reachable.");

[expectation fulfill];
}];
}];

[self waitForExpectationsWithTimeout:5 handler:nil];
}

- (void) testExpiredLiveVideo
Expand Down
2 changes: 1 addition & 1 deletion XCDYouTubeKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "XCDYouTubeKit"
s.version = "2.11.0"
s.version = "2.12.0"
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"
Expand Down
8 changes: 4 additions & 4 deletions XCDYouTubeKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -649,10 +649,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 45;
CURRENT_PROJECT_VERSION = 46;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 2.0.0;
DYLIB_CURRENT_VERSION = 2.11.0;
DYLIB_CURRENT_VERSION = 2.12.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
Expand Down Expand Up @@ -727,10 +727,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 45;
CURRENT_PROJECT_VERSION = 46;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 2.0.0;
DYLIB_CURRENT_VERSION = 2.11.0;
DYLIB_CURRENT_VERSION = 2.12.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
Expand Down
19 changes: 18 additions & 1 deletion XCDYouTubeKit/XCDYouTubeClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,24 @@ NS_ASSUME_NONNULL_BEGIN
*
* @return A newly initialized`<XCDYouTubeVideoQueryOperation>` object for canceling the asynchronous query operation. If you call the `cancel` method before the operation is finished, the completion handler will not be called.
*/
- (XCDYouTubeVideoQueryOperation *) queryVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray <NSHTTPCookie *>*)cookies completionHandler:(void (^)(NSDictionary *streamURLs, NSError * __nullable error, NSDictionary<id, NSError *> *streamErrors))completionHandler;
- (XCDYouTubeVideoQueryOperation *) queryVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray <NSHTTPCookie *>*)cookies completionHandler:(void (^)(NSDictionary * __nullable streamURLs, NSError * __nullable error, NSDictionary<id, NSError *> * __nullable streamErrors))completionHandler;
/**
* Starts an asynchronous operation for the specified `XCDYouTubeVide` object`, stream URLs to query and cookies, then calls a handler upon completion.
*
* @param video The `<XCDYouTubeVideo>` object that this operation will query. Passing a `nil` video will throw an `NSInvalidArgumentException` exception.
* @param streamURLsToQuery The specific stream URLs to query, can be nil. These URLs and keys must be contained in the `streamURLs` property of the `video` object, if none of the values in `streamURLsToQuery` match then all of the `streamURLs` will be queried.
* @param options Options that are reserved for future use.
* @param cookies An array of `NSHTTPCookie` objects, can be nil. These cookies can be used for certain videos that require a login.
* @param completionHandler A block to execute when the client finishes the operation. The completion handler is executed on the main thread. If the completion handler is nil, this method throws an exception.
* @discussion If the query operation completes successfully (i.e. at least one URL stream is reachable), the `streamURLs` parameter of the completion handler block contains a `NSDictionary` object, and the error parameter is nil. If the operation fails, the `streamURLs` parameter is nil and the error parameter contains information about the failure. The error's domain is always `XCDYouTubeVideoErrorDomain`. The `streamErrors` does not indicate that the operation failed but can contain detailed information on why a specific stream failed.In addition, this parameter is dictionary of `NSError` objects. The keys are the YouTube [itag](https://en.wikipedia.org/wiki/YouTube#Quality_and_formats) values as `NSNumber` objects. In some cases the errors within this dictionary may contain `NSError` objects with the code `NSURLErrorNetworkConnectionLost`—this may indicate that the file stored on YouTube's server is incomplete—furthermore, the error will make this suggestion via the`NSLocalizedRecoverySuggestionErrorKey` key of the error's `userInfo`.
*
* @see XCDYouTubeVideoQueryOperation
*
*
* @return A newly initialized`<XCDYouTubeVideoQueryOperation>` object for canceling the asynchronous query operation. If you call the `cancel` method before the operation is finished, the completion handler will not be called.
*/
- (XCDYouTubeVideoQueryOperation *) queryVideo:(XCDYouTubeVideo *)video streamURLsToQuery:(NSDictionary<id, NSURL *> * __nullable)streamURLsToQuery options:(NSDictionary * __nullable)options cookies:(nullable NSArray <NSHTTPCookie *>*)cookies completionHandler:(void (^)(NSDictionary *__nullable streamURLs, NSError * __nullable error, NSDictionary<id, NSError *> *__nullable streamErrors))completionHandler;


@end

Expand Down
9 changes: 7 additions & 2 deletions XCDYouTubeKit/XCDYouTubeClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,17 @@ - (instancetype) initWithLanguageIdentifier:(NSString *)languageIdentifier
return [self getVideoWithIdentifier:videoIdentifier cookies:cookies customPatterns:nil completionHandler:completionHandler];
}

- (XCDYouTubeVideoQueryOperation *) queryVideo:(XCDYouTubeVideo *)video cookies:(NSArray<NSHTTPCookie *> *)cookies completionHandler:(void (^)(NSDictionary * _Nonnull, NSError * _Nullable, NSDictionary<id, NSError *> *streamErrors))completionHandler
- (XCDYouTubeVideoQueryOperation *)queryVideo:(XCDYouTubeVideo *)video cookies:(NSArray<NSHTTPCookie *> *)cookies completionHandler:(void (^)(NSDictionary * _Nonnull, NSError * _Nullable, NSDictionary<id,NSError *> * _Nonnull))completionHandler
{
return [self queryVideo:video streamURLsToQuery:nil options:nil cookies:cookies completionHandler:completionHandler];
}

- (XCDYouTubeVideoQueryOperation *)queryVideo:(XCDYouTubeVideo *)video streamURLsToQuery:(NSDictionary<id,NSURL *> *)streamURLsToQuery options:(NSDictionary *)options cookies:(NSArray<NSHTTPCookie *> *)cookies completionHandler:(void (^)(NSDictionary * _Nullable, NSError * _Nullable, NSDictionary<id,NSError *> * _Nullable))completionHandler
{
if (!completionHandler)
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"The `completionHandler` argument must not be nil." userInfo:nil];

XCDYouTubeVideoQueryOperation *operation = [[XCDYouTubeVideoQueryOperation alloc]initWithVideo:video cookies:cookies];
XCDYouTubeVideoQueryOperation *operation = [[XCDYouTubeVideoQueryOperation alloc]initWithVideo:video streamURLsToQuery:streamURLsToQuery options:options cookies:cookies];
operation.completionBlock = ^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
#pragma clang diagnostic push
Expand Down
15 changes: 12 additions & 3 deletions XCDYouTubeKit/XCDYouTubeVideoQueryOperation.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,28 @@ NS_ASSUME_NONNULL_BEGIN
/// Initializes a video query operation with the specified video and cookies.
/// @param video The `<XCDYouTubeVideo>` object that this operation will query. Passing a `nil` video will throw an `NSInvalidArgumentException` exception.
/// @param cookies An array of `NSHTTPCookie` objects, can be nil. These cookies can be used for certain videos that require a login.
- (instancetype) initWithVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray<NSHTTPCookie *> *)cookies NS_DESIGNATED_INITIALIZER;
- (instancetype) initWithVideo:(XCDYouTubeVideo *)video cookies:(nullable NSArray<NSHTTPCookie *> *)cookies;

/// Initializes a video query operation with the specified video, stream URLs to query and cookies.
/// @param video The `<XCDYouTubeVideo>` object that this operation will query. Passing a `nil` video will throw an `NSInvalidArgumentException` exception.
/// @param streamURLsToQuery The specific stream URLs to query, can be nil. These URLs and keys must be contained in the `streamURLs` property of the `video` object, if none of the values in `streamURLsToQuery` match then all of the `streamURLs` will be queried.
/// @param options Options that are reserved for future use.
/// @param cookies An array of `NSHTTPCookie` objects, can be nil. These cookies can be used for certain videos that require a login.
- (instancetype) initWithVideo:(XCDYouTubeVideo *)video streamURLsToQuery:(nullable NSDictionary<id, NSURL *>*)streamURLsToQuery options:(nullable NSDictionary *)options cookies:(nullable NSArray<NSHTTPCookie *> *)cookies NS_DESIGNATED_INITIALIZER;

/// The `video` object that the operation initialized initialized with.
@property (atomic, strong, readonly) XCDYouTubeVideo *video;

@property (atomic, strong, readonly, nullable) NSDictionary<id, NSURL *> *streamURLsToQuery;

/// The array of `NSHTTPCookie` objects passed during initialization.
@property (atomic, copy, readonly, nullable) NSArray<NSHTTPCookie *>*cookies;

/// A dictionary of video stream URLs that are reachable. The keys are the YouTube [itag](https://en.wikipedia.org/wiki/YouTube#Quality_and_formats) values as `NSNumber` objects. The values are the video URLs as `NSURL` objects. There is also the special `XCDYouTubeVideoQualityHTTPLiveStreaming` key for live videos.
#if __has_feature(objc_generics)
@property (atomic, readonly) NSDictionary<id, NSURL *> *streamURLs;
@property (atomic, readonly, nullable) NSDictionary<id, NSURL *> *streamURLs;
#else
@property (atomic, readonly) NSDictionary *streamURLs;
@property (atomic, readonly, nullable) NSDictionary *streamURLs;
#endif

/// Returns an error of the `XCDYouTubeVideoErrorDomain` domain if the operation failed or nil if it succeeded. The operation will only return an error if no stream URL is reachable (error code: `XCDYouTubeErrorNoStreamAvailable`). Also, this returns `nil` if the operation is not yet finished or if it was canceled.
Expand Down
Loading

0 comments on commit 50592e3

Please sign in to comment.