13

在我的应用程序中,我有一个按钮,按下该按钮后,您可以观看 youtube 视频(电影预告片)。在应用程序内,无需启动 safari。您可以在下面看到一个代码片段。此代码在 iOS5 下运行良好。但是,在 iOS 6 中,findButtonInView 中的 UIButton 始终为 nil。任何想法可能是什么原因?

youtubeWebView.delegate = self;
youtubeWebView.backgroundColor = [UIColor clearColor];

NSString* embedHTML = @" <html><head> <style type=\"text/css\"> body {background-color: transparent;  color: white; }</style></head><body style=\"margin:0\"><embed id=\"yt\" src=\"%@?version=3&app=youtube_gdata\" type=\"application/x-shockwave-flash\"width=\"%0.0f\" height=\"%0.0f\"></embed></body></html>";

NSURL *movieTrailer;

if(tmdbMovie) movieTrailer = tmdbMovie.trailer;

else movieTrailer = [NSURL URLWithString:movie.trailerURLString];

NSString *html = [NSString stringWithFormat:embedHTML,
                                            movieTrailer,
                                            youtubeWebView.frame.size.width,
                                            youtubeWebView.frame.size.height];

[youtubeWebView loadHTMLString:html baseURL:nil];

[self addSubview:youtubeWebView];


- (void)webViewDidFinishLoad:(UIWebView *)_webView {

    isWatchTrailerBusy = NO;

    [manager displayNetworkActivityIndicator:NO];

    //stop the activity indicator and enable the button

     UIButton *b = [self findButtonInView:_webView];

    //TODO this returns null in case of iOS 6, redirect to the youtube app

    if(b == nil) {

        NSURL *movieTrailer;

        if(tmdbMovie) {
            movieTrailer = tmdbMovie.trailer;
        } else {
            movieTrailer = [NSURL URLWithString:movie.trailerURLString];
        }

        [[UIApplication sharedApplication] openURL:movieTrailer];

    } else {
        [b sendActionsForControlEvents:UIControlEventTouchUpInside];
    }
}


- (UIButton *)findButtonInView:(UIView *)view {

    UIButton *button = nil;
    if ([view isMemberOfClass:[UIButton class]]) {
        return (UIButton *)view;
    }

    if (view.subviews && [view.subviews count] > 0) {

        for (UIView *subview in view.subviews) {
            button = [self findButtonInView:subview];
            if (button) return button;
        }
    }

     return button;
}
4

8 回答 8

11

Apple 改变了 iOS6 中处理 YouTube 视频的方式。我也在使用 findButtonInView 方法,但它不再有效。

我发现以下似乎可行(在 iOS < 6 中未经测试):

- (void)viewDidLoad 
{
    [super viewDidLoad];
    self.webView.mediaPlaybackRequiresUserAction = NO;
}

- (void)playVideo
{
    self.autoPlay = YES;
    // Replace @"y8Kyi0WNg40" with your YouTube video id
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@", @"http://www.youtube.com/embed/", @"y8Kyi0WNg40"]]]];
}

// UIWebView delegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (self.autoPlay) {
        self.autoPlay = NO;
        [self clickVideo];
    }
}

- (void)clickVideo {
    [self.webView stringByEvaluatingJavaScriptFromString:@"\
        function pollToPlay() {\
            var vph5 = document.getElementById(\"video-player\");\
            if (vph5) {\
                vph5.playVideo();\
            } else {\
                setTimeout(pollToPlay, 100);\
            }\
        }\
        pollToPlay();\
     "];
}
于 2012-09-20T01:12:54.623 回答
8

dharmabruce 解决方案在 iOS 6 上运行良好,但为了使其在 iOS 5.1 上运行,我不得不将 javascript click() 替换为 playVideo(),并且我必须将 UIWebView 的 mediaPlaybackRequiresUserAction 设置为 NO

这是修改后的代码:

- (void)viewDidLoad 
{
    [super viewDidLoad];
    self.webView.mediaPlaybackRequiresUserAction = NO;
}

- (void)playVideo
{
    self.autoPlay = YES;
    // Replace @"y8Kyi0WNg40" with your YouTube video id
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@", @"http://www.youtube.com/embed/", @"y8Kyi0WNg40"]]]];
}

// UIWebView delegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (self.autoPlay) {
        self.autoPlay = NO;
        [self clickVideo];
    }
}

- (void)clickVideo {
    [self.webView stringByEvaluatingJavaScriptFromString:@"\
        function pollToPlay() {\
            var vph5 = document.getElementById(\"video-player-html5\");\
            if (vph5) {\
                vph5.playVideo();\
            } else {\
                setTimeout(pollToPlay, 100);\
            }\
        }\
        pollToPlay();\
     "];
}
于 2012-11-05T15:24:23.770 回答
3

我已经解决了dharmabruceJimmY2K的问题。解决方案,事实上它只在第一次播放视频时才有效,正如Dee所提到的

这是代码(包括视频结束时的事件):

- (void)embedYouTube:(NSString *)urlString frame:(CGRect)frame {
    videoView = [[UIWebView alloc] init];
    videoView.frame = frame;
    videoView.delegate = self;

    [videoView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];// this format: http://www.youtube.com/embed/xxxxxx
    [self.view addSubview:videoView];

    //https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/MediaPlayer.framework/MPAVController.h
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playbackDidEnd:)
                                                 name:@"MPAVControllerItemPlaybackDidEndNotification"//@"MPAVControllerPlaybackStateChangedNotification"
                                               object:nil];

}


- (void)webViewDidFinishLoad:(UIWebView *)webView {
    //http://stackoverflow.com/a/12504918/860488
    [videoView stringByEvaluatingJavaScriptFromString:@"\
                                    var intervalId = setInterval(function() { \
                                        var vph5 = document.getElementById(\"video-player\");\
                                        if (vph5) {\
                                            vph5.playVideo();\
                                            clearInterval(intervalId);\
                                        } \
                                    }, 100);"];
}

- (void)playbackDidEnd:(NSNotification *)note
{
    [videoView removeFromSuperview];
    videoView.delegate = nil;
    videoView = nil;
}
于 2013-03-08T13:00:14.147 回答
1

未经测试,不确定这是否是问题所在,因为我不知道您使用的 URL。但是我偶然发现了以下内容:

从 iOS 6 开始,嵌入的 YouTube URLhttp://www.youtube.com/watch?v=oHg5SJYRHA0将不再有效。这些 URL 用于查看 YouTube 网站上的视频,而不是用于嵌入网页。相反,此处描述了应使用的格式:https ://developers.google.com/youtube/player_parameters 。

来自http://thetecherra.com/2012/09/12/ios-6-gm-released-full-changelog-inside/

于 2012-09-26T07:11:20.237 回答
0

我发现下面的代码适用于 iOS5 和 iOS6。在我的示例中,我有一个包含视频 url 的文本字段。我首先将格式转换为相同的起始字符串“http://m...”。然后我检查格式是否是带有 'watch?v=' 的旧格式,然后用新格式替换它. 我已经在 iOS5 的 iPhone 和 iOS5 和 iOS6 的模拟器中测试了这个:

-(IBAction)loadVideoAction {
    [activityIndicator startAnimating];

    NSString *urlString = textFieldView.text;
    urlString = [urlString stringByReplacingOccurrencesOfString:@"http://www.youtube" withString:@"http://m.youtube"];
    urlString = [urlString stringByReplacingOccurrencesOfString:@"http://m.youtube.com/watch?v=" withString:@""];
    urlString = [NSString stringWithFormat:@"%@%@", @"http://www.youtube.com/embed/", urlString];
    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    [activityIndicator stopAnimating];
}
于 2012-11-02T13:48:40.977 回答
0

我正在解决同样的一般问题,我将分享我提出的方法。对于我的特殊情况,我还有一些问题需要解决,但一般方法可能对您有用,具体取决于您的 UI 要求。

如果您构建 HTML 嵌入代码以使 YouTube 播放器覆盖 UIWebView 的整个边界,则 UIWebView 有效地成为一个大播放按钮 - 触摸它表面上的任何位置都会使视频启动到本机媒体播放器中。要创建您的按钮,只需使用将 userInteractionEnabled 设置为 NO 的 UIView 覆盖 UIWebView。在这种情况下 UIWebView 的大小是否重要?不是真的,因为无论如何视频都会在本机播放器中打开。

如果您希望用户将 UI 的某个区域视为视频将要“播放”的位置,那么您可以从 YouTube 获取视频的缩略图并将其放置在任何位置。如果需要,您可以在该视图后面放置第二个 UIWebView,因此如果用户触摸该视图,视频也会启动 - 或者只是将另一个 UIWebView 展开,使其位于这两个视图的“后面”。

如果您发布您的 UI 的屏幕截图,我可以提出一些更具体的建议,但基本想法是通过在 UIWebView 前面放置一个禁用用户交互的视图来将其变成一个按钮。

于 2012-10-01T17:52:01.423 回答
0

我相信问题是当 webViewDidFinishLoad 被触发时, UIButton 还没有添加到视图中。在回调返回后,我实现了一个小的延迟来找到按钮,它适用于我在 ios5 和 ios6 上。缺点是延迟后无法保证 UIButton 已准备好被找到。

- (void)autoplay {
    UIButton *b = [self findButtonInView:webView];
    [b sendActionsForControlEvents:UIControlEventTouchUpInside]; }

- (void)webViewDidFinishLoad:(UIWebView *)_webView {
    [self performSelector:@selector(autoplay) withObject:nil afterDelay:0.3]; }

我不得不使用网址http://www.youtube.com/watch?v=videoid这是它对我有用的唯一方法

于 2012-12-20T04:46:32.057 回答
-1
- (void) performTapInView: (UIView *) view {
    BOOL found = NO;
    if ([view gestureRecognizers] != nil) {
        for (UIGestureRecognizer *gesture in  [view gestureRecognizers]) {
            if ([gesture isKindOfClass: [UITapGestureRecognizer class]]) {
                if ([gesture.view respondsToSelector: @selector(_singleTapRecognized:)]) {
                    found = YES;
                    [gesture.view performSelector: @selector(_singleTapRecognized:) withObject: gesture afterDelay: 0.07];
                    break;
                }
            }
        }
    }

    if (!found) {
        for (UIView *v in view.subviews) {
            [self performTapInView: v];
        }
    }
}
#pragma mark - UIWebViewDelegate methods
- (void) webViewDidFinishLoad: (UIWebView *) webView {
    if (findWorking) {
        return;
    }
    findWorking = YES;
    [self performTapInView: webView];
}
于 2012-09-24T06:54:06.330 回答