You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何预加载AVPlayerViewController并动态切换视频源以避免黑屏?

Solution: Reuse AVPlayerViewController for Multiple Videos (No Black Screen Flash)

Absolutely! Preinitializing your AVPlayerViewController and reusing it with different video sources is not only possible but also the ideal fix for the black screen flash you're encountering. The root cause of the flash is the overhead of creating a new AVPlayer and AVPlayerViewController every time you present—reusing these objects eliminates that delay entirely.

Step-by-Step Implementation

1. Declare Global Properties

Keep your player and view controller as instance properties (you already have this, but we'll initialize them upfront):

@interface YourViewController ()
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) AVPlayerViewController *playerViewController;
@property (nonatomic, strong) AVPlayerLooper *currentLooper; // Optional: For looping animations
@end

2. Preinitialize in viewDidLoad

Set up the player and view controller once when your page loads—this avoids repeated initialization overhead:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Initialize player with a placeholder URL (we'll replace this later)
    self.player = [AVPlayer playerWithURL:[NSURL URLWithString:@""]];
    
    // Preconfigure the player view controller
    self.playerViewController = [[AVPlayerViewController alloc] init];
    self.playerViewController.player = self.player;
    self.playerViewController.showsPlaybackControls = NO;
    // Optional: Set presentation style if needed
    self.playerViewController.modalPresentationStyle = UIModalPresentationFullScreen;
}

3. Modify playAnimation to Reuse Objects

Instead of creating new player and controller instances, just swap out the AVPlayerItem when a new video is requested:

- (void)playAnimation:(NSString *)filePath {
    NSURL *videoURL = [NSURL fileURLWithPath:filePath];
    AVPlayerItem *newPlayerItem = [AVPlayerItem playerItemWithURL:videoURL];
    
    // Remove existing observer to avoid memory leaks
    if (self.player.currentItem) {
        [self.player.currentItem removeObserver:self forKeyPath:@"status"];
    }
    
    // Replace the current player item
    [self.player replaceCurrentItemWithPlayerItem:newPlayerItem];
    
    // Observe the item's status to ensure it's ready before playing
    __weak typeof(self) weakSelf = self;
    [newPlayerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    
    // Present or reuse the view controller
    if (self.presentedViewController != self.playerViewController) {
        [self presentViewController:self.playerViewController animated:NO completion:^{
            [weakSelf checkAndPlayIfReady:newPlayerItem];
        }];
    } else {
        [self checkAndPlayIfReady:newPlayerItem];
    }
    
    // Optional: Set up looping if your animation needs to repeat
    self.currentLooper = [AVPlayerLooper playerLooperWithPlayer:self.player templateItem:newPlayerItem];
}

4. Helper Methods for Status Checking & Cleanup

Add these methods to handle playback readiness and avoid memory leaks:

- (void)checkAndPlayIfReady:(AVPlayerItem *)item {
    switch (item.status) {
        case AVPlayerItemStatusReadyToPlay:
            [self.player play];
            break;
        case AVPlayerItemStatusFailed:
            NSLog(@"Failed to load video: %@", item.error.localizedDescription);
            // Add error handling here (e.g., alert the user)
            break;
        case AVPlayerItemStatusUnknown:
            // Still loading—wait for KVO update
            break;
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"status"]) {
        AVPlayerItem *item = (AVPlayerItem *)object;
        [self checkAndPlayIfReady:item];
        [item removeObserver:self forKeyPath:@"status"];
    }
}

- (void)dealloc {
    // Clean up remaining observers
    if (self.player.currentItem) {
        [self.player.currentItem removeObserver:self forKeyPath:@"status"];
    }
}

Key Notes

  • No More Black Screens: By reusing the preinitialized view controller and player, the video's first frame loads before presentation, eliminating the flash.
  • Local Video Optimization: Since your videos are stored locally (Bundle or sandbox), load times are already fast—this approach makes them virtually instant.
  • Looping Support: The AVPlayerLooper ensures your animation repeats seamlessly (remove this if you don't need looping).
  • Memory Safety: Always remove KVO observers to prevent crashes and memory leaks.

内容的提问来源于stack exchange,提问作者Niall Kiddle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:43:28