Changing playerItem of AVPlayer in UITableView

前端 未结 3 1859
我寻月下人不归
我寻月下人不归 2020-12-23 19:47

I have a UITableView containing a number of videos to play when scrolling. As the cells in the tableView are being re-used, I only instantiate one AVPlaye

相关标签:
3条回答
  • 2020-12-23 20:33

    In your CustomCell.m you should use thumbnails to display an image for the specific cell video, you could add the thumbnail to a button inside your cell, then build a custom delegate in CustomCell.h that will be called when you tap on the newly created button something like:

    @class CustomCell;
    
    @protocol CustomCellDelegate <NSObject>
    
    - (void)userTappedPlayButtonOnCell:(CustomCell *)cell;
    
    @end
    

    also in your your .h add the action for the button:

    @interface CustomCell : UITableViewCell
    
    @property (strong, nonatomic) IBOutlet UIButton *playVideoButton;
    
     - (IBAction)didTappedPlayVideo;
     - (void)settupVideoWithURL:(NSString *)stringURL;
     - (void)removeVideoAndShowPlaceholderImage:(UIImage *)placeholder;
    
    @end
    

    also in "didTappedPlayVideo" you do the next:

    - (void)didTappedPlayVideo{
    
    [self.delegate userTappedPlayButtonOnCell:self];
    
    }
    

    the method: settupVideoWithURL is used to init you player and the method: removeVideoAndShowPlaceholderImagewill stop the video and make the AVPlayerItem and AVPlayer nil.

    Now when the user taps a cell you send the call back to the UIViewController where you have the tableView, and in the delegate method you should do the next:

        - (void)userTappedPlayButtonOnCell:(CustomCell *)cell{
    
        //check if this is the first time when the user plays a video
        if(self.previousPlayedVideoIndexPath){
              CustomCell *previousCell = (CustomCell *)[tableView cellForRowAtIndexPath:self.previousPlayedVideoIndexPath];
              [previousCell removeVideoAndShowPlaceholderImage: [UIImage imageNamed:@"img.png"]];
        }
        [cell settupVideoWithURL:@"YOURvideoURL"];
        self.previousPlayedVideoIndexPath = cell.indexPath;
        }
    

    P.S.:

    On older devices(almost all of them until the new iPad Pro) is not indicated to have multiple instances of AVPlayer. Also hope that this chunks of code can guide or help you in your quest :)

    0 讨论(0)
  • 2020-12-23 20:49

    If you do some basic level of profiling, I think you can narrow down the problem. For me, I had a similar issue where replaceCurrentItemWithPlayerItem was blocking the UI thread. I resolved it by examining my code to find out which line was taking time. For me the AVAsset loading was taking time. So I used the loadValuesAsynchronouslyForKeys method of AVAsset to resolve my issue.

    Hence can you try the following:

    -(void)initializeNewObject:(CustomObject*)o
    {
        //If this cell is being dequeued/re-used, its player might still be playing the old file
        [self.player pause];
        self.currentObject = o;
        /*
        //Setting text-variables for title etc. Removed from this post, but by commenting them out in the code, nothing improves.
        */
    
        //Replace the old playerItem in the cell's player
        NSURL *url = [NSURL URLWithString:self.currentObject.url];
        AVAsset *newAsset = [AVAsset assetWithURL:url];
        [newAsset loadValuesAsynchronouslyForKeys:@[@"duration"] completionHandler:^{
            AVPlayerItem *newItem = [AVPlayerItem playerItemWithAsset:newAsset];
            [self.player replaceCurrentItemWithPlayerItem:newItem];
        }];
    
    
        //The last line above, replaceCurrentItemWithPlayerItem:, is the 'bad guy'.
        //When commenting that one out, all lag is gone (of course, no videos will be playing either)
        //The lag still occurs even if I never call [self.player play], which leads me
        //to believe that nothing after this function can cause the lag
    
        self.isPlaying = NO;
    }
    
    0 讨论(0)
  • 2020-12-23 20:49

    You should profile your app using the time profiler to see where the lagging is actually occurring.

    The documentation for replaceCurrentItemWithPlayerItem: clearly states that it executes asynchronously, so it shouldn't be the source of your main queue jumpiness.

    The item replacement occurs asynchronously; observe the currentItem property to find out when the replacement will/did occur.

    Documentation here

    If you still can't figure it out, post more code, and in particular at least your cellForRowAtIndexPath method.

    UPDATE

    As per @joey's comment below, the previous content of this answer is no longer valid. The documentation no longer states that the method is asynchronous, so it may not be.

    0 讨论(0)
提交回复
热议问题