iOS7中的UIWebView如何播放Youtube视频?

12

我有一个 UIWebView 的子类,用于播放 YouTube 和本地视频,在 iOS6 下工作得非常完美。在升级到 iOS7 后,我遇到了一个问题,不知道从哪里开始解决。虽然在 iOS7 模拟器上似乎仍然可以正常播放 YouTube 和本地视频,但是在设备上播放 YouTube 时,我会在日志中看到以下信息:

Sep 26 10:17:27 JRR-IPad SVOx[558] <Error>: CGContextSaveGState: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

Sep 26 10:17:27 JRR-IPad SVOx[558] <Error>: CGContextSetBlendMode: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

Sep 26 10:17:27 JRR-IPad SVOx[558] <Error>: CGContextSetAlpha: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

Sep 26 10:17:27 JRR-IPad SVOx[558] <Error>: CGContextTranslateCTM: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

Sep 26 10:17:27 JRR-IPad SVOx[558] <Error>: CGContextScaleCTM: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update. 

Sep 26 10:17:27 JRR-IPad SVOx[558] <Error>: CGContextGetCTM: invalid context 0x0.
This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

Sep 26 10:17:27 JRR-IPad SVOx[558] <Error>: CGContextDrawImage: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

Sep 26 10:17:27 JRR-IPad SVOx[558] <Error>: CGContextGetCTM: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

这只发生在设备上,模拟器上没有出现过,在iOS6下也没有发生过。我在这里看到了一些关于测试版中各种类似问题的帖子,但是我没有看到有关iOS7正式版的评论。

我在代码中没有使用任何这些方法,所以这些消息都来自库。

有人知道吗?谢谢!


3
我刚刚提交了错误报告 #15106115。 - RegularExpression
你找到解决方案了吗?如果找到了,请分享一下。谢谢。 - iOS Monster
没有,没有解决方案。尽管如此,我还是按照现有情况继续前进。除了这些看起来无害的消息之外,我还有两个问题:(1)内存消耗似乎非常高,即使加载一个短的YouTube视频,内存使用量也会从大约10MB飙升到约40MB,(2)在单击YouTube上的播放按钮后,您必须在Webview上再次单击播放按钮。我已经在其他地方看到过这个问题。目前还没有花太多时间解决这些问题。 - RegularExpression
我也遇到了同样的问题。 - Grey Code
1
我已经提交了一个带有示例xCode项目的错误报告。# 15423020 - Yoga
显示剩余3条评论
5个回答

4

使用这个方法,你可以在你的视图中播放Youtube视频。

UIWebView *videoView = [[UIWebView alloc] initWithFrame:self.view.bounds];

    NSString *strparse = [NSString stringWithFormat:@"http://www.youtube.com/watch?v=%@",youtubeVideoId];
    NSRange rng = [strparse rangeOfString: @"watch?v="];
    strparse = [strparse substringFromIndex:rng.location];
    rng = [strparse rangeOfString:@"&feature="];


    if (rng.length >0)
    {
        strparse = [strparse substringToIndex:rng.location];
    }
    strparse = [strparse stringByReplacingOccurrencesOfString:@"watch?v=" withString:@""];
    //http://www.youtube.com/embed/FJkiwbqlSy0
    NSString *youTubeVideoHTML =[NSString stringWithFormat:@"<!DOCTYPE html><html><head><style>body{margin:0px 0px 0px 0px; background:#1111}</style></head> <body> <div id=\"player\"></div> <script> var tag = document.createElement('script'); tag.src = \"http://www.youtube.com/player_api\"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; function onYouTubePlayerAPIReady() { player = new YT.Player('player', { width:'%0.0f', height:'%0.0f', videoId:'%@', events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } });} function onPlayerReady(event) { event.target.playVideo(); } function onPlayerStateChange(event) {if(event.data === 0) {   event.target.destroy(); }}  </script> </body> </html>",0.0, 0.0,youtubeVideoId];


    videoView.scalesPageToFit=NO;
    videoView.mediaPlaybackRequiresUserAction=NO;
    videoView.backgroundColor = [UIColor clearColor];
    videoView.opaque= NO;


    [SharedObj showLoadingWithText:@""];

    [videoView loadHTMLString:youTubeVideoHTML baseURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.youtube.com/watch?v=%@",youtubeVideoId]]];


    [self.view addSubview:videoView];

1
这是在IOS7中经过测试的代码,它运行良好。
[self embedYouTube:[self getYTUrlStr:@"https://www.youtube.com/watch?v=Zq4o_Ca14aw"] frame:CGRectMake(0,40,self.view.frame.size.width, self.view.frame.size.height-40)];


- (NSString*)getYTUrlStr:(NSString*)url
{
    if (url == nil)
        return nil;

    NSString *retVal = [url stringByReplacingOccurrencesOfString:@"watch?v=" withString:@"v/"];

    NSRange pos=[retVal rangeOfString:@"version"];
    if(pos.location == NSNotFound)
    {
        retVal = [retVal stringByAppendingString:@"?version=3&hl=en_EN"];
    }
    return retVal;
}



- (void)embedYouTube:(NSString*)url frame:(CGRect)frame {

    NSString* embedHTML = @"\
    <html><head>\
    <style type=\"text/css\">\
    body {\
    background-color: transparent;\
    color: white;\
    }\
    </style>\
    </head><body style=\"margin:0\">\
    <embed id=\"yt\" src=\"%@\" type=\"application/x-shockwave-flash\" \
    width=\"%0.0f\" height=\"%0.0f\"></embed>\
    </body></html>";
    NSString* html = [NSString stringWithFormat:embedHTML, url, frame.size.width, frame.size.height];
    if(videoView == nil) {
        videoView = [[UIWebView alloc] initWithFrame:frame];
        videoView.delegate=self;
        [self.view addSubview:videoView];
    }


    videoView.mediaPlaybackAllowsAirPlay=YES;
    videoView.allowsInlineMediaPlayback=YES;
    [videoView loadHTMLString:html baseURL:nil];

}

对我来说不起作用。我创建了一个示例应用程序,只包含您的embedYouTube:frame:函数中的代码,并使用NSString url = @"http://images.apple.com/movies/us/hd_gallery/gl1800/480p/warren_miller_m480p.mov"作为URL。当它开始播放时,仍然出现相同的错误。 - Yoga

0

试试这个:

NSString* videoUrl = @"//www.youtube.com/embed/Of_hjbYCx4Y";
if([videoUrl hasPrefix:@"//"]) {
    videoUrl = [NSString stringWithFormat:@"https:%@", videoUrl]; // or http
    // if its a local file add proper scheme like "file:///"
}
NSString* iframeWidth = @"100%";
NSString* iframeHeight = @"240px";
NSString *iframeHTML =[NSString stringWithFormat:@"<iframe width=\"%@\" height=\"%@\" src=\"%@\" frameborder=\"0\" allowfullscreen></iframe>", iframeWidth, iframeHeight, videoUrl];
// you can directly use iframeHTML below or u can wrap it up in body and span tags and then use it if u need to add any extra stuff or customize the page itself
[videoWebView loadHTMLString:htmlString baseURL:nil];

确保两件事情: 视频网址以http(正确的协议)开头,并将/watch?v=替换为embed/,如果您的网址中还没有它。查看其他答案以了解如何操作。 希望能有所帮助。

0

YouTube提供了一个框架,使我们不必直接使用Web视图来保存。该框架可在以下链接中找到:https://github.com/youtube/youtube-ios-player-helper

您所需要做的就是创建一个YTPlayerView视图,将其添加到视图层次结构中,并使用您喜欢的约束加载视频。就像这样:

    youTubePlayer = YTPlayerView()
    youTubePlayer!.translatesAutoresizingMaskIntoConstraints = false
    contentView.addSubview(youTubePlayer!)
    youTubePlayer!.pinAllAnchors(to: contentView)
    youTubePlayer!.load(withVideoId: url.youTubeVideoId()!)

请注意,pinAllAnchors和youTubeVideoId是我创建的辅助工具。它们不是框架的一部分。

0

我在我的应用程序中使用了以下方法,它可以在iOS6和iOS7上工作。也许它适用于您。

NSString *youTubeID = [self extractYoutubeID:url];   // url is youtube url 
NSString *embedHTML =[NSString stringWithFormat:@"\
                          <html><head>\
                          <style type=\"text/css\">\
                          body {\
                          background-color: #666666;\
                          padding:%f %f %f %f;\
                          color: blue;\
                          }\
                          </style>\
                          </head><body style=\"margin:0\">\
                          <iframe height=\"%f\" width=\"%f\" title=\"YouTube Video\" class=\"youtube-player\" src=\"http://www.youtube.com/embed/%@\" ></iframe>\
                          </body></html>",paddingTop,paddingRight,paddingBottom,paddingLeft,videoHeight,videoWidth,youTubeID];
[self.webView loadHTMLString:embedHTML baseURL:nil];




- (NSString *)extractYoutubeID:(NSString *)youtubeURL
    {
        //NSLog(@"youtube  %@",youtubeURL);
        NSError *error = NULL;
        NSString *regexString = @"(?<=v(=|/))([-a-zA-Z0-9_]+)|(?<=youtu.be/)([-a-zA-Z0-9_]+)";
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:NSRegularExpressionCaseInsensitive error:&error];
        NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:youtubeURL options:0 range:NSMakeRange(0, [youtubeURL length])];
        if(!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0)))
        {
            NSString *substringForFirstMatch = [youtubeURL substringWithRange:rangeOfFirstMatch];
            return substringForFirstMatch;
        }
        return nil;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接