Образцы текстур

читал большинство вопросов наStackOverflow для автоматического воспроизведения видео, и я могу автоматически воспроизводить их вUITableView, но у меня есть несколько вопросов, как указано ниже

при запуске видео прокрутка на секунду зависаетВидео мигает перед воспроизведениемВидео не воспроизводится автоматически при прокрутке вверх

То, что я хочу, - это плавный опыт для автоматического воспроизведения видео, таких как Facebook, без использования сторонней библиотеки, такой какASYNCDisplayKit, Все видеоurls изAWSS3 облачные фронтальные URL. Я также выложил видео о проблеме на случай, если кто-то захочет посмотреть.

Видео автоигра икота

Вот мой полный код

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {



            PostViewModel* model = self.posts[indexPath.section];
            Post* post = model.post;

            PostItems* item = model.items[indexPath.row];
                if(item.itemType == nameAndPicture) {
                    //Removed code as it's not related to question
                }
                else if(item.itemType == textContent){
                    //Removed code as it's not related to question
                }
                else if(item.itemType == images){
                    //Removed code as it's not related to question
                }
                else if(item.itemType == videos){

                    VideoListCell *cell = nil;
                    cell = (VideoListCell*)[tableView dequeueReusableCellWithIdentifier:kFeedVideoListCellIdentifier forIndexPath:indexPath];
                    cell.delegate = self;
                    cell.indexPath = indexPath;
                    cell.selectionStyle = UITableViewCellSelectionStyleNone;
                    cell.backgroundColor = [UIColor clearColor];

                    cell.videoThumbnail.image = nil;

                    [cell setCounter:post.medias.count];

                    if (post.medias.count > 0) {
                        MediaItem* item = post.medias[0];
                        if ([item getMediaType] == VIDEO) {

                           NSString* thumbnailURL = item.thumbnailUrl;
                            [cell.videoThumbnail downloadImageWithURL:thumbnailURL andPlaceholderImage:self.timelinePlaceholder indicatorStyle:UIActivityIndicatorViewStyleWhiteLarge cachePolicy:NSURLRequestReturnCacheDataElseLoad andTimeOut:120];
                            [cell hideVideoAndShowThumbnail];

                            dispatch_async(dispatch_get_main_queue(), ^{
                                [cell setMediaItem:item withUserID:post.userId];
                            });
                        }
                    }
                    cell.clipsToBounds = YES;
                    return cell;
                }

}




 - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{

    //Check if the cell displayed is video cell then try to autoplay the video
    if([cell isKindOfClass:[VideoListCell class]]){
        VideoListCell* videoCell = (VideoListCell*)cell;
        dispatch_async(dispatch_get_main_queue(), ^{
            [videoCell hideVideoAndShowThumbnail];
        });
        PostViewModel* model = self.posts[indexPath.section];
        Post* post = model.post;
        PostItems* item = model.items[indexPath.row];
        if(item.itemType == videos){
            videoCell.videoThumbnail.image = nil;
            [videoCell setCounter:post.medias.count];

            if (post.medias.count > 0) {
                MediaItem* item = post.medias[0];
                if ([item getMediaType] == VIDEO) {
                    //dispatch_async(dispatch_get_main_queue(), ^{
                    NSString* profilePic = item.thumbnailUrl;
                    [videoCell.videoThumbnail downloadImageWithURL:profilePic andPlaceholderImage:self.timelinePlaceholder indicatorStyle:UIActivityIndicatorViewStyleWhiteLarge cachePolicy:NSURLRequestReturnCacheDataElseLoad andTimeOut:120];
                    [videoCell setMediaItem:item withUserID:post.userId];
                    [videoCell playVideo];
                }
            }
        }
    }
}

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath {

    if([cell isKindOfClass:[VideoListCell class]]){

        VideoListCell* videoCell = (VideoListCell*)cell;
        [videoCell stopVideo];
        videoCell.avLayer = nil;
        videoCell.videoPlayer = nil;
        [videoCell hideVideoAndShowThumbnail];
    }
}

// Список ячеек класса видео

#define kHeight 200

@implementation VideoListCell

- (void)awakeFromNib {
    [super awakeFromNib];

    UIImage* icon = [[UIImage imageNamed:@"play-icon"] imageTintedWithColor:kSliderDarkYellowColor];
    [self.btnPlay setImage:icon forState:UIControlStateNormal];

    UIImage* pauseIcon = [[UIImage imageNamed:@"pause-icon"] imageTintedWithColor:kSliderDarkYellowColor];

    [self.btnPlay setImage:icon forState:UIControlStateNormal];
    [self.btnPlay setImage:pauseIcon forState:UIControlStateSelected];


    UITapGestureRecognizer *viewTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapOnView)];
    viewTap.numberOfTapsRequired = 1;
    self.viewPlayer.userInteractionEnabled = YES;
    [self.viewPlayer addGestureRecognizer:viewTap];

    self.counterView.hidden = YES;
    self.counterView.layer.cornerRadius = 12.0f;
    self.counterView.layer.masksToBounds = YES;

    //Add Gesture to label
    UITapGestureRecognizer *countGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapOnCounterView)];
    countGesture.numberOfTapsRequired = 1;
    self.counterView.userInteractionEnabled = YES;
    [self.counterView addGestureRecognizer:countGesture];

    [self.btnFullScreen addTarget:self action:@selector(btnFSTapped:) forControlEvents:UIControlEventTouchUpInside];

    self.btnFullScreen.hidden = NO;
    UIImage* fullScreenImage = [[UIImage imageNamed:@"fullScreenIcon"] imageTintedWithColor:kSliderDarkYellowColor];
    [self.btnFullScreen setImage:fullScreenImage forState:UIControlStateNormal];

}

- (void)showThumbnail:(BOOL)yesOrNo {
    self.videoThumbnail.hidden = !yesOrNo;
    self.viewForVideo.hidden = yesOrNo;
}

- (void)hideVideoAndShowThumbnail {
    [self stopVideo];
    [self showThumbnail:YES];
    self.btnPlay.selected = NO;
    self.isPlaying = NO;
}

- (void)btnFSTapped:(UIButton*)sender {
    if (self.delegate && [self.delegate respondsToSelector:@selector(fullScreenButtonTapped:andURL:andPlayer:)]) {
        [self.delegate fullScreenButtonTapped:self.indexPath andURL:self.videoURL andPlayer:self.player.player];
    }
}

- (void)layoutSubviews
{
    [super layoutSubviews];
//     if (self.avLayer) {
//         [self.avLayer setFrame:CGRectMake(self.viewForVideo.frame.origin.x, self.viewForVideo.frame.origin.y, self.viewForVideo.frame.size.width,  self.viewForVideo.frame.size.height)];
//     }

}

- (void)initNewPlayerItem {
    // Pause the existing video (if there is one)
    //[self stopVideo];

    if(self.asset){
        [self.asset cancelLoading];
    }


    // First we need to make sure we have a valid URL
    if (!self.videoURL) {
        return;
    }

    // Create a new AVAsset from the URL
    self.asset = [AVAsset assetWithURL:self.videoURL];

    // Now we need an AVPlayerItem to pass to the AVPlayer
    AVPlayerItem* item  = [[AVPlayerItem alloc] initWithAsset:self.asset];

    if(item){
        [[NSNotificationCenter defaultCenter] addObserver:self

                                                 selector:@selector(playerItemDidReachEnd:)

                                                     name:AVPlayerItemDidPlayToEndTimeNotification

                                                   object:item];
    }
    //[self.player.player replaceCurrentItemWithPlayerItem:item];

    // Finally, we set this as the current AVPlayer item

    [self.asset loadValuesAsynchronouslyForKeys:@[@"duration"] completionHandler:^{

        NSError* error = nil;
        AVKeyValueStatus status = [self.asset statusOfValueForKey:@"duration" error:&error];
        if (status == AVKeyValueStatusFailed) {
            [self.playerSetupLoading stopAnimating];
            self.btnPlay.hidden = NO;
            self.btnPlay.selected = NO;
            return;
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.playerSetupLoading stopAnimating];
            [self.player.player replaceCurrentItemWithPlayerItem:item];
            self.btnPlay.selected = YES;
            self.btnPlay.hidden = YES;
            [self showThumbnail:NO];
            [self.player.player play];
            self.isPlaying = YES;
        });
    }];
}

- (void)playerItemDidReachEnd:(NSNotification*)notif {

    id object = [notif object];
    if (object && [object isKindOfClass:[AVPlayerItem class]]) {
        AVPlayerItem* item = (AVPlayerItem*)[notif object];
        [item seekToTime:kCMTimeZero];
    }
    //[self stopVideo];
    [self showThumbnail:YES];
    self.btnPlay.selected = NO;
    self.btnPlay.hidden = NO;

}

-(void)prepareForReuse {

//    self.videoURL = nil;
//    self.videoThumbnail.image = nil;
    //[self.player pauseContent];
    self.videoThumbnail.image = nil;
    if (self.avLayer.superlayer) {
        [self.avLayer removeFromSuperlayer];
    }

    if (self.viewForVideo.subviews.count > 0) {
        for (UIView* v in self.viewForVideo.subviews) {
            [v removeFromSuperview];
        }
    }

    self.videoURL = nil;
    self.player = nil;
    self.userID = nil;
    self.videoItem = nil;
    self.videoPlayer = nil;
    self.btnPlay.selected = NO;

    [super prepareForReuse];
}

- (void)tapOnView {

    //if(self.counterView.hidden){
        if (self.delegate && [self.delegate respondsToSelector:@selector(fullScreenButtonTapped:andURL:andPlayer:)]) {
            [self.delegate fullScreenButtonTapped:self.indexPath andURL:self.videoURL andPlayer:self.player.player];
        }
    //}
//    else
//    {
//            if (self.delegate && [self.delegate respondsToSelector:@selector(playVideo:withURL:)]) {
//                [self.delegate playVideo:self.indexPath withURL:nil];
//            }
//    }
}

-(void)tapOnCounterView {
    if (self.delegate && [self.delegate respondsToSelector:@selector(playVideo:withURL:)]) {
          [self.delegate playVideo:self.indexPath withURL:nil];
    }
}

- (void)setCounter:(NSUInteger)count {

    if (count > 1) {
        self.counterView.hidden = NO;
        self.lblCounter.text = [NSString stringWithFormat:@"+%lu more",(unsigned long)count-1];
    }
    else{
        self.counterView.hidden = YES;
    }
}

- (IBAction)btnPlayTapped:(id)sender {

    //[self playVideo];

     //if(self.counterView.hidden){
        if(self.btnPlay.selected){
            [self stopVideo];
            self.btnPlay.selected = NO;
        }else{
            [self playVideo];
            self.btnPlay.selected = YES;
        }
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    if(self.player.player.timeControlStatus == AVPlayerTimeControlStatusPlaying){
        if(self.btnPlay.hidden){
            self.btnPlay.hidden = NO;
        }
    }
}


- (void)playVideo {

    //if (!self.player) {
        if ([self.videoObject doesPreSignedURLExpired]) {

            //Call API here and update media item object URL
            dispatch_async(dispatch_get_main_queue(), ^{
                //Call API here
                //URL is expired then give a call to our server to generate a new URL
                [self generateNewPreSignedURL];
            });
        }
        else{
            if (!self.videoURL) {

                dispatch_async(dispatch_get_main_queue(), ^{
                    [self generatePreSignedURLWithVideoThumbnail];
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self setupPlayer];

                });
            }
        }
}

- (void)stopVideo {
    if (self.player) {
        self.isPlaying = NO;
        self.btnPlay.hidden = NO;
        [self.player.player pause];
    }
}

- (void)setMediaItem:(MediaItem*)item withUserID:(NSNumber*)userId {
    self.videoObject = item;
    self.userID = userId;
    [self showThumbnail:YES];
}

- (void)generatePreSignedURLWithVideoThumbnail {

    if (self.videoObject.mediaUrl && [self.videoObject hasPreSignedURL]) {
        //Already have pre signed url check if URL is expired
        //If URL expired then call our own server to generate a new presigned URL
        dispatch_async(dispatch_get_main_queue(), ^{
            self.videoURL = [NSURL URLWithString:self.videoObject.mediaUrl];
            [self setupPlayer];
        });
    }
    else if(self.videoObject.mediaUrl && [self.videoObject hasPlayListURL]){
        AppDelegate* delegate = [AppDelegate applicationDelegate];
        AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
        getPreSignedURLRequest.bucket = S3BucketName;
        getPreSignedURLRequest.key = kS3OutputVideoFileInternalPath(delegate.loggedInUser.userId,[self.videoObject getVideoFolderName],self.videoObject.mediaUrl);

        getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodGET;
        getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:Hour*24*5];

        [[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRequest]
         continueWithBlock:^id(AWSTask *task) {
             if (task.error) {
                 NSLog(@"Error: %@",task.error);
             } else {
                 dispatch_async(dispatch_get_main_queue(), ^{
                     self.videoURL = task.result;
                     [self setupPlayer];
                 });
             }
             return nil;
         }];
    }
    else{
        //Generate Pre signed URL
        AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
        getPreSignedURLRequest.bucket = S3BucketName;
        getPreSignedURLRequest.key = [kS3InputVideoFilePath(self.userID) stringByAppendingString:self.videoObject.mediaUrl];

        getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodGET;
        getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:Hour*24*5];

        [[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRequest]
         continueWithBlock:^id(AWSTask *task) {
             if (task.error) {
                 NSLog(@"Error: %@",task.error);
             } else {
                 dispatch_async(dispatch_get_main_queue(), ^{
                     self.videoURL = task.result;
                     [self setupPlayer];

                 });
             }
             return nil;
         }];
    }
}

- (void)setupPlayer {
    self.btnPlay.hidden = YES;

    self.videoItem = nil;
    self.videoPlayer = nil;

    self.videoItem = [[AVPlayerItem alloc] initWithURL:self.videoURL];

    if (self.avLayer.superlayer) {
        [self.avLayer removeFromSuperlayer];
    }

    if (self.viewForVideo.subviews.count > 0) {
        for (UIView* v in self.viewForVideo.subviews) {
            [v removeFromSuperview];
        }
    }

    self.videoPlayer = [[AVPlayer alloc] initWithPlayerItem:self.videoItem];

    self.avLayer = [AVPlayerLayer playerLayerWithPlayer:self.videoPlayer];
    self.avLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

    self.player = [[AVPlayerViewController alloc] init];
    self.player.player = self.videoPlayer;
    self.player.videoGravity = AVLayerVideoGravityResizeAspectFill;

    self.player.showsPlaybackControls = NO;

    // Insert the player into the cell view hierarchy and setup autolayout
    self.player.view.translatesAutoresizingMaskIntoConstraints = false;
    [self.viewForVideo insertSubview:self.player.view atIndex:0];

    //Trailing
    NSLayoutConstraint *trailing =[NSLayoutConstraint
                                   constraintWithItem:self.player.view
                                   attribute:NSLayoutAttributeTrailing
                                   relatedBy:NSLayoutRelationEqual
                                   toItem:self.viewForVideo
                                   attribute:NSLayoutAttributeTrailing
                                   multiplier:1.0f
                                   constant:0.f];

    //Leading

    NSLayoutConstraint *leading = [NSLayoutConstraint
                                   constraintWithItem:self.player.view
                                   attribute:NSLayoutAttributeLeading
                                   relatedBy:NSLayoutRelationEqual
                                   toItem:self.viewForVideo
                                   attribute:NSLayoutAttributeLeading
                                   multiplier:1.0f
                                   constant:0.f];

    //Bottom
    NSLayoutConstraint *bottom =[NSLayoutConstraint
                                 constraintWithItem:self.player.view
                                 attribute:NSLayoutAttributeBottom
                                 relatedBy:NSLayoutRelationEqual
                                 toItem:self.viewForVideo
                                 attribute:NSLayoutAttributeBottom
                                 multiplier:1.0f
                                 constant:0.f];

    //Height to be fixed for SubView same as AdHeight
    NSLayoutConstraint *height = [NSLayoutConstraint
                                  constraintWithItem:self.player.view
                                  attribute:NSLayoutAttributeHeight
                                  relatedBy:NSLayoutRelationEqual
                                  toItem:nil
                                  attribute:NSLayoutAttributeNotAnAttribute
                                  multiplier:0
                                  constant:kHeight];

    //Add constraints to the Parent
    [self.viewForVideo addConstraint:trailing];
    [self.viewForVideo addConstraint:bottom];
    [self.viewForVideo addConstraint:leading];

    //Add height constraint to the subview, as subview owns it.
    [self.player.view addConstraint:height];

    [self initNewPlayerItem];
}

- (void)generateNewPreSignedURL {

    if (self.videoObject) {
        NSDictionary* postParams = @{kMediaId:self.videoObject.mediaId};


        dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
            TBWebAPIConsumer *web = [TBWebAPIConsumer sharedWebAPIManager];
            [web generatePreSignedURL:postParams andCompletionBlock:^(NSError *error, id serverResponse) {

                // Do something...
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (error == nil){
                        //Parse user data here
                        NSDictionary* data = (NSDictionary*)serverResponse;

                        if (![data valueForKeyIsNull:@"mediaUrl"]) {
                            self.videoObject.mediaUrl = [data valueForKey:@"mediaUrl"];
                        }
                        if (![data valueForKeyIsNull:@"videoSignedUrlExpiry"]) {
                            self.videoObject.videoSignedUrlExpiry = [data valueForKey:@"videoSignedUrlExpiry"];
                        }
                        [self generatePreSignedURLWithVideoThumbnail];

                    }
                });

            }];

        });
    }


}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

Может ли кто-нибудь помочь мне в этом?

Ответы на вопрос(2)

Ваш ответ на вопрос