Reputation: 3541
I have a UIWebView subclass that I used to play both youtube and local videos. Worked perfectly under iOS6. In upgrading to iOS7 I've encountered a problem I don't really know where to start on. While the subclass seems to still work fine playing youtube and local video on the iOS7 simulator, when I play a youtube on the device I get the following messages logged:
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.
===
This happens only on the device, not on the simulator, and did not occur under iOS6. I've seen some posts here talking about similar problems with various classes on the beta, but I've not seen comments about the iOS7 release version.
I do not use any of these methods in my code, so these messages are originating within libraries.
Anyone? TIA.
Upvotes: 12
Views: 4226
Reputation: 606
YouTube has made available a framework to save us from the hassle of using a web view directly. The framework is available at: https://github.com/youtube/youtube-ios-player-helper
All you need to do is to create a YTPlayerView view, add it to the view hierarchy with the constraints you like and load the video. Like so:
youTubePlayer = YTPlayerView()
youTubePlayer!.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(youTubePlayer!)
youTubePlayer!.pinAllAnchors(to: contentView)
youTubePlayer!.load(withVideoId: url.youTubeVideoId()!)
Note that pinAllAnchors and youTubeVideoId are helpers I created. They are not part of the framework.
Upvotes: 0
Reputation: 69
Using this you can run youtube video in your view..
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];
Upvotes: 4
Reputation: 668
Try this:
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];
Make sure of two things: Video url starts with http (proper scheme) and replace the /watch?v= with embed/ if u don't have it already in url. Check other answers given here to see how to do this. Hope it helps.
Upvotes: 0
Reputation: 5064
I used following way in my app and its working in both iOS6 and iOS 7. May be its works for you.
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;
}
Upvotes: 0
Reputation: 206
This is the tested code in IOS7 , its working fine
[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];
}
Upvotes: 1