だから私は解決策を見つけることができましたが、それはあまりきれいではありませんComponentKit
.Facebookの開発者がこのケースを処理する正しい方法がどのように見えるべきかを意図しているかどうかはわかりませんが、この解決策は機能します:
まず、実際のビデオ プレゼンテーションを処理する別のビューを作成する必要があります。これはAppleの例から引き出されたものです
#import "CDBVideoPlayerView.h"
@implementation CDBVideoPlayerView
+ (Class)layerClass {
return [AVPlayerLayer class];
}
- (AVPlayer*)player {
return [(AVPlayerLayer *)[self layer] player];
}
- (void)setPlayer:(AVPlayer *)player {
[(AVPlayerLayer *)[self layer] setPlayer:player];
}
@end
次に、コンポーネントとコントローラー:
#import "CDBVideoPlayerComponent.h"
#import "CDBVideoPlayerView.h"
#import <ComponentKit/CKStatefulViewComponent.h>
#import <ComponentKit/CKStatefulViewComponentController.h>
#import <AVFoundation/AVFoundation.h>
@interface CDBVideoStateComponent : CKStatefulViewComponent
@property (nonatomic, strong) AVPlayer *player;
+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size;
@end
@implementation CDBVideoStateComponent
+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size {
CKComponentScope scope(self, url);
CDBVideoStateComponent *component = [super newWithSize:size accessibility:{}];
component->_player = [[AVPlayer alloc] initWithURL:url];
component->_player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
return component;
}
@end
@interface CDBVideoStateComponentController : CKStatefulViewComponentController
@end
@implementation CDBVideoStateComponentController
+ (UIView *)newStatefulView:(id)context {
CDBVideoPlayerView *view = [[CDBVideoPlayerView alloc] init];
return view;
}
+ (void)configureStatefulView:(CDBVideoPlayerView *)statefulView forComponent:(CDBVideoStateComponent *)videoComponent {
statefulView.player = videoComponent.player;
}
@end
@interface CDBVideoPlayerComponent ()
@property (nonatomic, strong) AVPlayer *player;
@end
@implementation CDBVideoPlayerComponent
+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size {
CKComponentScope scope(self, url);
CDBVideoStateComponent *component = [CDBVideoStateComponent newWithVideoURL:url size:size];
CDBVideoPlayerComponent *playerComponent = [super newWithComponent:component
overlay:
[CKButtonComponent
newWithTitles:{}
titleColors:{}
images:{}
backgroundImages:{}
titleFont:{}
selected:NO
enabled:YES
action:@selector(handleButtonPress:)
size:{}
attributes:{}
accessibilityConfiguration:{}
]
];
playerComponent->_player = component.player;
return playerComponent;
}
- (void)handleButtonPress:(id)sender {
if (self.player.status == AVPlayerStatusReadyToPlay) {
if (self.player.timeControlStatus == AVPlayerTimeControlStatusPaused || self.player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) {
[self.player play];
} else {
[self.player pause];
}
}
}
@end
編集
また、ほとんどのコードを VideoPlayerView に移動することで、よりクリーンなソリューションを見つけたと思います
@implementation VideoPlayerView
- (instancetype)init {
if (self = [super init]) {
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]];
}
return self;
}
- (void)dealloc {
[self removeObserversForPlayer:self.player];
}
+ (Class)layerClass {
return [AVPlayerLayer class];
}
- (AVPlayer*)player {
return [(AVPlayerLayer *)[self layer] player];
}
- (void)setPlayer:(AVPlayer *)player {
[self removeObserversForPlayer:self.player];
[(AVPlayerLayer *)[self layer] setPlayer:player];
[self addObserverForPlayer:player];
}
- (void)addObserverForPlayer:(AVPlayer *)player {
if (player) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:player.currentItem];
}
}
- (void)removeObserversForPlayer:(AVPlayer *)player {
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:player.currentItem];
}
- (void)itemDidFinishPlaying:(NSNotification *)notification {
[self.player seekToTime:kCMTimeZero];
[self.player pause];
}
- (void)handleTap:(id)sender {
if (self.player.status == AVPlayerStatusReadyToPlay) {
if (self.player.timeControlStatus == AVPlayerTimeControlStatusPaused || self.player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) {
[self.player play];
} else {
[self.player pause];
}
}
}
@end
更新されたコンポーネント:
#import "VideoPlayerComponent.h"
#import "VideoPlayerView.h"
#import <ComponentKit/CKStatefulViewComponentController.h>
#import <AVFoundation/AVFoundation.h>
#import <ComponentKit/ComponentKit.h>
@interface VideoPlayerComponent ()
@property (nonatomic, strong) AVPlayer *player;
@end
@implementation VideoPlayerComponent
+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size {
CKComponentScope scope(self, url);
VideoPlayerComponent *component = [super newWithSize:size accessibility:{}];
component->_player = [[AVPlayer alloc] initWithURL:url];
component->_player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
return component;
}
@end
@interface VideoPlayerComponentController : CKStatefulViewComponentController
@end
@implementation VideoPlayerComponentController
+ (UIView *)newStatefulView:(id)context {
VideoPlayerView *view = [[VideoPlayerView alloc] init];
view.backgroundColor = [UIColor grayColor];
return view;
}
+ (void)configureStatefulView:(VideoPlayerView *)statefulView forComponent:(VideoPlayerComponent *)videoComponent {
statefulView.player = videoComponent.player;
}
@end