在 viewDidLoad 中运行 MPMoviePlayerController 的奇怪行为
一旦我的应用程序启动,我就会使用 MediaPlayer
框架播放一部相当大的电影(~200 MB)。当我尝试在 viewDidLoad 中播放视频时,断点表明视图已添加,但视频未显示在设备上。
然后,我设置了一个按钮来确认视频是否有效。从按钮运行 IBAction 没有显示任何问题。
然后我就被难住了。我想知道这是否与应用程序启动后立即调用视频有关。因此,我向 viewDidLoad 调用添加了一个延迟五秒的 NSTimer
。你瞧,效果很好。谁能解释一下为什么视频不会播放,除非有初始延迟?代码如下。
- (void)viewDidLoad {
NSTimer *currentTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(playMovie) userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:currentTimer forMode:NSRunLoopCommonModes];
[super viewDidLoad];
}
-(IBAction)playMovie
{
NSString *filepath = [[NSBundle mainBundle] pathForResource:@"Speed" ofType:@"mov"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlaybackComplete:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayerController];
[self.view addSubview:moviePlayerController.view];
moviePlayerController.fullscreen = YES;
[moviePlayerController play];
}
I'm using the MediaPlayer
framework to play a pretty sizeable movie (~200 MB) as soon as my application is launched. When I attempt to play the video in my viewDidLoad
, breakpoints indicated that the view was added however the video did not show up on the device.
I then set up a button to confirm that the video worked at all. Running the IBAction from the button showed no problems.
So then I was stumped. And I wondered if it had anything to do with the fact that the video was being called as soon as the application was launched. So I added a NSTimer
with a delay of five seconds to the viewDidLoad call. Lo and behold, it worked fine. Can anyone shed any light on to why the video won't play unless there is an initial delay? Code below.
- (void)viewDidLoad {
NSTimer *currentTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(playMovie) userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:currentTimer forMode:NSRunLoopCommonModes];
[super viewDidLoad];
}
-(IBAction)playMovie
{
NSString *filepath = [[NSBundle mainBundle] pathForResource:@"Speed" ofType:@"mov"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlaybackComplete:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayerController];
[self.view addSubview:moviePlayerController.view];
moviePlayerController.fullscreen = YES;
[moviePlayerController play];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
尝试在
viewDidAppear:
而不是viewDidLoad
中播放影片。在调用 viewDidLoad 时,视图尚未位于视图层次结构中。您仍然可以在viewDidLoad
中创建 MPMoviePlayerController,只是在视图实际出现之前不要播放它。Try playing the movie in
viewDidAppear:
instead ofviewDidLoad
. At the pointviewDidLoad
is called, the view is not yet in the view hierarchy. You could still create the MPMoviePlayerController inviewDidLoad
, just don't play it until the view actually appears.我认为视频的大小与这里有关。我尝试用较小的视频做同样的事情,效果很好。似乎视频是先加载然后播放的(请参阅此堆栈溢出问题:MPMoviePlayerController 在视频加载之前不显示控件)。显然,200 MB 的视频需要 4-5 秒才能预加载。尝试不适用于较小尺寸视频的代码。如果工作正常,那么肯定是尺寸问题。
编辑:我在 MPMoviePlayerController 类参考中找到了这个 “如果您知道电影的源类型,则在播放开始之前设置此属性的值可以缩短电影内容的加载时间。如果您不设置在播放之前显式指定源类型,电影播放器控制器必须收集此信息,这可能会延迟播放。”我注意到您尚未声明源类型。再加上视频的大小,您就需要 4 到 5 秒的加载时间。
在播放之前也可以尝试一下
[moviePlayerControllerprepareToPlay];
I think the size of the video has something to do here. I tried doing the same thing with a smaller video and it works fine. It seems the video is loaded first and then played ( see this stack over flow question: MPMoviePlayerController not showing controls until video is loaded). Apparently, the 200 MB video takes 4-5 seconds to preload. Try the code that was'nt working with a video of smaller size. If it works fine, then it's definitely the size problem.
Edit: I found this in MPMoviePlayerController Class Reference "If you know the source type of the movie, setting the value of this property before playback begins can improve the load times for the movie content. If you do not set the source type explicitly before playback, the movie player controller must gather this information, which might delay playback." I notice you haven't declared source type. Add to that the size of the video, and you've got yourself 4-5 seconds of load time.
Also try this before playing
[moviePlayerController prepareToPlay];
我有不同的经历,但移动
viewDidAppear:
中的代码也对我的情况有所帮助。我有从一个故事板连接到另一个故事板的 IOS 代码,一旦连接完成 - 在 viewDidLoad: 中,我正在初始化一个周期性计时器。计时器的代码如下 [I was 'calling' startTimer inviewDidLoad:
]:有趣的是,当我在 viewDidLoad 中调用 startTimer: 我永远无法观察到 iPhone 上的视图发生变化到下一个控制器 - 我可以看到 NSLog 语句显示控件已到达
,但控件未转到 ViewController。
此行为与周期性计时器的计时无关 - 设置低或高不会影响问题。当我将 startTimer 调用移至 viewDidAppear: 时,观察到的问题就消失了。
即使我将计时器代码移至 viewDidAppear:,也会出现另一组挑战。这段具有常规定时器的代码 - 我创建了这个代码,以便我可以获得蓝牙低功耗连接的 RSSI 值。我观察到我停止获取蓝牙委托的委托回调。
I had a different experience but moving the code in
viewDidAppear:
helped my case as well. I have IOS code that segues from one storyboard to another and once the segue is complete - in theviewDidLoad:
I was initializing a periodic timer. The code for the timer is below [I was 'calling' startTimer inviewDidLoad:
]:What is interesting is that the when I call the startTimer in viewDidLoad: I can never observe the view on the iPhone change to the next controller - I can see the NSLog statement that shows the control came to
but the control does not go to the ViewController.
This behavior is independent of the timing of the periodic timer - setting low or high does not impact the problem. The observed problem goes away when I move the startTimer invocation to
viewDidAppear:
This is followed by another set of challenge even when I move the timer code to
viewDidAppear:
. This code of having a regular timer - I have created this so that I can get the RSSI value for the Bluetooth Low Energy Connection. What I have observed is that I stop getting delegate callbacks for the Bluetooth delegate.