2015-11-29 20 views
10

私は着信データに基づいて複数の画像ビューのサブビューを積み重ねています。基本的に、これらのすべてのサブビューは、受信データに基づいてイメージまたはビデオレイヤーに設定されます。私が持っている問題はビデオを再生することです。私はスタックの最初のビデオを再生することができますが、それ以降のすべてのビデオは最初のビデオの音だけです。それに応じてそれぞれをどのようにプレイできますか?スタックされたビデオを再生する

スナップショットのようなタップイベントでビューがナビゲートされます。以下を参照してください。

@interface SceneImageViewController() 

@property (strong, nonatomic) NSURL *videoUrl; 
@property (strong, nonatomic) AVPlayer *avPlayer; 
@property (strong, nonatomic) AVPlayerLayer *avPlayerLayer; 

@end 

@implementation SceneImageViewController 

- (void)viewDidLoad { 

[super viewDidLoad]; 

self.mySubviews = [[NSMutableArray alloc] init]; 
self.videoCounterTags = [[NSMutableArray alloc] init]; 

int c = (int)[self.scenes count]; 
c--; 
NSLog(@"int c = %d", c); 
self.myCounter = [NSNumber numberWithInt:c]; 


for (int i=0; i<=c; i++) { 

    //create imageView 
    UIImageView *imageView =[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)]; 
    [imageView setUserInteractionEnabled:YES]; // <--- This is very important 
    imageView.tag = i;      // <--- Add tag to track this subview in the view stack 
    [self.view addSubview:imageView]; 
    NSLog(@"added image view %d", i); 


    //get scene object 
    PFObject *sceneObject = self.scenes[i]; 


    //get the PFFile and filetype 
    PFFile *file = [sceneObject objectForKey:@"file"]; 
    NSString *fileType = [sceneObject objectForKey:@"fileType"]; 



    //check the filetype 
    if ([fileType isEqual: @"image"]) 
    { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
     //get image 
     NSURL *imageFileUrl = [[NSURL alloc] initWithString:file.url]; 
     NSData *imageData = [NSData dataWithContentsOfURL:imageFileUrl]; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
     imageView.image = [UIImage imageWithData:imageData]; 
      }); 
     }); 

    } 

    //its a video 
    else 
    { 
     // the video player 
     NSURL *fileUrl = [NSURL URLWithString:file.url]; 

     self.avPlayer = [AVPlayer playerWithURL:fileUrl]; 
     self.avPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 

     self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; 
     //self.avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 

     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(playerItemDidReachEnd:) 
                name:AVPlayerItemDidPlayToEndTimeNotification 
                object:[self.avPlayer currentItem]]; 

     CGRect screenRect = [[UIScreen mainScreen] bounds]; 

     self.avPlayerLayer.frame = CGRectMake(0, 0, screenRect.size.width, screenRect.size.height); 
     [imageView.layer addSublayer:self.avPlayerLayer]; 

     NSNumber *tag = [NSNumber numberWithInt:i+1]; 

     NSLog(@"tag = %@", tag); 

     [self.videoCounterTags addObject:tag]; 

     //[self.avPlayer play]; 
    } 



} 



UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewTapped:)]; 

[self.view bringSubviewToFront:self.screen]; 

[self.screen addGestureRecognizer:tapGesture]; 


} 


- (void)viewTapped:(UIGestureRecognizer *)gesture{ 

NSLog(@"touch!"); 

[self.avPlayer pause]; 

int i = [self.myCounter intValue]; 
NSLog(@"counter = %d", i); 



for(UIImageView *subview in [self.view subviews]) { 

    if(subview.tag== i) { 

     [subview removeFromSuperview]; 
    } 
} 

if ([self.videoCounterTags containsObject:self.myCounter]) { 
    NSLog(@"play video!!!"); 
    [self.avPlayer play]; 
} 

if (i == 0) { 
    [self.avPlayer pause]; 
    [self.navigationController popViewControllerAnimated:NO]; 
} 


i--; 
self.myCounter = [NSNumber numberWithInt:i]; 


NSLog(@"counter after = %d", i); 





} 

答えて

1

Brooks Hanesが言ったことは、あなたがavplayerを上書きし続けるということです。

  1. が(代わりにクリーンなアプローチを使用UIButtonのためか)の代わりに、画面のImageViewのにタップジェスチャーを追加します: これはあなたがするために私が提案するものです

    UIImageView *imageView =[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)]; 
    [imageView setUserInteractionEnabled:YES]; // <--- This is very important 
    imageView.tag = i;      // <--- Add tag to track this subview in the view stack 
    [self.view addSubview:imageView]; 
    NSLog(@"added image view %d", i); 
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:imageView action:@selector(viewTapped:)]; 
    [imageView addGestureRecognizer:tapGesture]; 
    

このようにしてviewTapped:メソッドでは、myCounterの代わりにgesture.view.tagのように、押された画像のタグを取得できます。

  1. 動画を制作するには、動画ごとに新しいAVPlayerを作成することができますが、それは非常に高価なメモリになる可能性があります。より良い方法は、AVPlayerItemを使用して、ビデオを変更するときにAVPlayerAVPlayerItemを切り替えることです。あなたのviewTappedで今

      // the video player 
          NSNumber *tag = [NSNumber numberWithInt:i+1]; 
          NSURL *fileUrl = [NSURL URLWithString:file.url]; 
          //save your video file url paired with the ImageView it belongs to. 
          [self.videosFiles setObject:fileUrl forKey:tag]; 
    // you only need to initialize the player once. 
          if(self.avPlayer == nil){ 
           AVAsset *asset = [AVAsset assetWithURL:fileUrl]; 
           AVPlayerItem *item = [[AVPlayerItem alloc] initWithAsset:asset]; 
           self.avPlayer = [[AVPlayer alloc] initWithPlayerItem:item]; 
           self.avPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 
           [[NSNotificationCenter defaultCenter] addObserver:self 
            selector:@selector(playerItemDidReachEnd:) 
           name:AVPlayerItemDidPlayToEndTimeNotification 
           object:[self.avPlayer currentItem]]; 
          } 
          // you don't need to keep the layer as a property 
          // (unless you need it for some reason 
          AVPlayerLayer* avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; 
          avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
    
          CGRect screenRect = [[UIScreen mainScreen] bounds];     
          avPlayerLayer.frame = CGRectMake(0, 0, screenRect.size.width, screenRect.size.height); 
          [imageView.layer addSublayer:avPlayerLayer]; 
          NSLog(@"tag = %@", tag);     
          [self.videoCounterTags addObject:tag]; 
    

    forループでそう

self.videoFilesNSMutableDictionary財産であるこのような何か

if ([self.videoCounterTags containsObject:gesture.view.tag]) { 

    NSLog(@"play video!!!"); 
    AVAsset *asset = [AVAsset assetWithURL:[self.videoFiles objectForKey:gesture.view.tag]]; 
    AVPlayerItem *item = [[AVPlayerItem alloc] initWithAsset:asset]; 
    self.avPlayer replaceCurrentItemWithPlayerItem: item]; 
    [self.avLayer play]; 
} 

をそれともドン、代わりにself.videoFilesを使用し、 self.videoCounterTagsがまったく必要ありません。

NSURL* fileURL = [self.videoFiles objectForKey:gesture.view.tag]; 
if (fileURL!=nil) {  
    NSLog(@"play video!!!"); 
    AVAsset *asset = [AVAsset assetWithURL:fileURL]; 
    AVPlayerItem *item = [[AVPlayerItem alloc] initWithAsset:asset]; 
    self.avPlayer replaceCurrentItemWithPlayerItem: item]; 
    [self.avLayer play]; 
} 

それはそれの要点です。

+0

これは唯一のことです。唯一のことは、タップジェスチャーが前回のようにすべての画像ビューに追加しようとしました – ian

+0

あなたはそれを行いました!驚くばかり!私はAVAssetの使用も考えていませんでした。有効期限が切れても恩恵をあげる方法はありますか? – ian

1

myCounter変数の設定方法を見てください。これは一度設定され、ビューがタップされるまで変更されず、シーン数-1に設定されます。

さらに、_avPlayerポインタvarに設定する方法を調べてみてください。それは常に設定されており、forループでは、シーンのコレクションの最新の値に同じポインタを単に更新するのではなく、参照を格納したがっているようです。 Appleのdocumentationからも

、:

あなたは同じAVPlayerオブジェクトにプレイヤー層の任意の数を作成することができます。最も最近作成されたプレイヤーレイヤーだけが実際に画面にビデオコンテンツを表示します。

だから、それはあなたが同じAVPlayerオブジェクトを使用しているので、あなたは決して任意の複数の実際のビデオ層の仕事を見に行くんだということ、これらすべてAVPlayerレイヤーを作成することが可能です。

+0

あなたがこのコードで解決策を見つけたら、私はあなたにその恩恵を与えます – ian

関連する問題