iPhone - How to have a custom browser be able to detect if back/forward buttons need to be enabled/disabled - iphone

Hey guys! I have a tumblr app that I am developing, and I have a button that pushes a modal view that contains a webview and a toolbar on the bottom with refresh, back, forward and done buttons. The back forward and refresh buttons work, however I want to be able to tell if the webview can actually go back/forward and if not, disable the button..I have tried the code below, and the image nor the enable/disable changes.
- (IBAction)refreshPage {
[signUpWebView reload];
}
- (IBAction)goBack {
[signUpWebView goBack];
}
- (IBAction)goForward {
[signUpWebView goForward];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
// Enable or disable back
if ([signUpWebView canGoBack]) {
[backOnePage setEnabled:YES];
backOnePage.image = [UIImage imageNamed:#"backButton"];
} else {
[backOnePage setEnabled:NO];
backOnePage.image = [UIImage imageNamed:#"backButtonDisabled"];
}
// Enable or disable forward
if ([signUpWebView canGoForward]) {
[forwardOnePage setEnabled:YES];
forwardOnePage.image = [UIImage imageNamed:#"forwardButton"];
} else {
[forwardOnePage setEnabled:NO];
forwardOnePage.image = [UIImage imageNamed:#"forwardButtonDisabled"];
}
}
Any recommendations would be greatly appreciated!

I recommend binding the forward and backward button directly to the UIWebview.
Automatically enable and disable like this:
- (void)webViewDidStartLoad:(UIWebView *)mwebView {
backButton.enabled = (webView.canGoBack);
forwardButton.enabled = (webView.canGoForward);
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
backButton.enabled = (webView.canGoBack);
forwardButton.enabled = (webView.canGoForward);
}

When you first initialize your webView, try starting it with a request, like this:
[signUpWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"]]];
So you're initializing the webView with loadRequest: instead of loadHTMLString:, or something similar.

Related

how to hide progressview when webview load

hi I want to ask a simple question how I can hide or disable progress bar when UIWebView load, I add ProgressBar as subview of webview . I did it by using this way in the method below, but it can't help me because every site take different time to load because of their content size so kindly tell me how I can hide or remove the ProgressBar when any site load in webview
- (void)makeMyProgressBarMoving {
float actual = [threadProgressView progress];
if (actual < 1) {
threadProgressView.progress = actual + 0.2;
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(makeMyProgressBarMoving) userInfo:nil repeats:NO];
}
else
{
threadProgressView.hidden = YES;
threadValueLabel.hidden = YES;
}
}
First add delegate to UIWebView
For adding progress bar :-
Web view delegate method :-
- (void)webViewDidStartLoad:(UIWebView *)webView
{
threadProgressView.hidden = NO;
}
For Removing progress bar :-
Web view delegate method :-
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
threadProgressView.hidden = YES;
}
Hope this helps you
Check your webview is loaded completly or not.
if(!yourWebView.loading)
{
[yourProgress removeFromSuperView];
}
loading
A Boolean value indicating whether the receiver is done loading
content. (read-only) #property(nonatomic, readonly, getter=isLoading) BOOL loading >
Discussion
If YES, the receiver is still loading content; otherwise, NO.
Availability
Available in iOS 2.0 and later.
or
You can implement the webViewDidFinishLoad delegate method of UIWebView.
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[yourProgress removeFromSuperView];
}
webViewDidFinishLoad:
Sent after a web view finishes loading a frame.
- (void)webViewDidFinishLoad:(UIWebView *)webView
Parameters
webView
The web view has finished loading.
Availability
Available in iOS 2.0 and later.
Refer UIWebViewDelegate,UIWebView for more details

YouTube video playback broken on iOS6 (works fine on iOS5)

In my app, I have a button which, when pressed, lets you watch a youtube video (a movie trailer). Within the app, without launching safari. Below you can see a code snippet. This code works pefrectly fine under iOS5. However, in iOS 6, the UIButton in findButtonInView is always nil. Any ideas what might be the reason?
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;
}
Apple changed how YouTube videos are handled in iOS6. I also was using the findButtonInView method but that no longer works.
I've discovered the following seems to work (untested in 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();\
"];
}
dharmabruce solution works great on iOS 6, but in order to make it work on iOS 5.1, I had to substitute the javascript click() with playVideo(), and I had to set UIWebView's mediaPlaybackRequiresUserAction to NO
Here's the modified code:
- (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();\
"];
}
I have solved the problems with dharmabruce and JimmY2K. solutions, with the fact that it only works the first time a video is played, as mentioned by Dee
Here is the code(including event when a video ends):
- (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;
}
Untested and not sure if that is the problem here, becasue I don't know the URL you're using. But I stumbled right about following:
As of iOS 6, embedded YouTube URLs in the form of http://www.youtube.com/watch?v=oHg5SJYRHA0 will no longer work. These URLs are for viewing the video on the YouTube site, not for embedding in web pages. Instead, the format that should be used is described here: https://developers.google.com/youtube/player_parameters.
from http://thetecherra.com/2012/09/12/ios-6-gm-released-full-changelog-inside/
I'm working on this same general problem and I'll share the approach I've come up with. I have some remaining kinks to work out for my particular situation, but the general approach may work for you, depending on your UI requirements.
If you structure your HTML embed code so that the YouTube player covers the entire bounds of the UIWebView, that UIWebView effectively becomes a big play button - a touch anywhere on it's surface will make the video launch into the native media player. To create your button, simply cover the UIWebView with a UIView that has userInteractionEnabled set to NO. Does it matter what the size the UIWebView is in this situation? Not really, since the video will open into the native player anyway.
If you want the user to perceive an area of your UI as being where the video is going to "play", then you can grab the thumbnail for the video from YouTube and position that wherever. If need be, you could put a second UIWebView behind that view, so if the user touches that view, the video would also launch - or just spread the other UIWebView out so that it is "behind" both of these views.
If you post a screenshot of your UI, I can make some more specific suggestions, but the basic idea is to turn the UIWebView into a button by putting a view in front of it that has user interaction disabled.
I've found that the code below works for both iOS5 & iOS6. In my example, I have a text field that contains the url to the video. I first convert the formats to the same starting string 'http://m...". Then I check to see if the the format is the old format with the 'watch?v=' and then replace it with the new format. I've tested this on an iPhone with iOS5 and in the simulators in 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];
}
I believe the problem is that when webViewDidFinishLoad was triggered, the UIButton was not added to the view yet. I implemented a small delay to find the button after the callback is returned and it works for me on ios5 and ios6. drawback is that there is no guarantee the UIButton is ready to be found after the delay.
- (void)autoplay {
UIButton *b = [self findButtonInView:webView];
[b sendActionsForControlEvents:UIControlEventTouchUpInside]; }
- (void)webViewDidFinishLoad:(UIWebView *)_webView {
[self performSelector:#selector(autoplay) withObject:nil afterDelay:0.3]; }
I had to use the url http://www.youtube.com/watch?v=videoid this is the only way it will work for me
- (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];
}

exit fullscreen embeded youtube in webview

I am using embeded youtube in my webview for making a iPhone app. But I have couple of issues. First is, When I start playing video, it automatically goes to full screen. I want it to remain on the same frame while playing. Another issue is, I want it to run automatically. I mean I dont want to manually click run, I want, as soon as the app gets loaded, it should RUN AUTOMATICALLY without manually running, plus it should not run on FULLSCREEN.
Thanks
Akansha
I think you are loading embeded html string for youtube but it's not going to play automatically.
for that you need to put logic like bellow code
- (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;
}
- (void)webViewDidFinishLoad:(UIWebView *)theWebView
{
self.playButton = [self findButtonInView:theWebView];
[self.playButton sendActionsForControlEvents:UIControlEventTouchUpInside];
}
This will play video automatically as loading finished...

Stop animation of multiple UIActivityIndicatorView

I have some dynamic webview and activity indicator.
All is working fine when webview is loaded. But if i tried to stop the activity indicator after the loading is completed, only one indicator is stop spinning not all.
So how can i solve this problem :
I am using following code
-(void)myMethod{
for (int i=0; i<count; i++)
{
//Create webview one by one
webView.tag=i;
//Create a activityindicator
activityIndicatorView.tag=i;
[activityIndicatorView startAnimating];
[webView addSubView: activityIndicatorView];
[self.view addSubView:webView];
}
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
if(webView.tag==0)
{
[activityIndicatorView setHidden:YES];
}
else if (webView.tag==1)
{
[activityIndicatorView setHidden:YES];
}
else if (webView.tag==2)
{
[activityIndicatorView setHidden:YES];
}
else if (webView.tag==3)
{
[activityIndicatorView setHidden:YES];
}
}
Because you are actually only loading data on one single web view instance. Your initial loop always uses the very same web view. And, likewise, you keep using and starting the very same activity-indicator instance. Just because you assign a new tag to it, it will not create a new instance for you.

What is the problem with the back button in my UIWebView?

I have an issue in my application that i wrote coding for the back button in my webView setEnabled = NO, but when the application is launched and webViewDidFinishLoad the back button setEnabled = YES. I tried all possibility to set the back button enabled is equal false but it not works.
-(IBAction) backButton : (id) sender{
backTapped = YES;
[webView goBack];
}
-(IBAction) fwdButton : (id) sender{
forwardTapped = YES;
[webView goForward];
}
- (void)webViewDidStartLoad:(UIWebView *)thisWebView{
NSLog(#"webViewDidStartLoad");
[progressWheel startAnimating];
progressWheel.hidden = NO;
if(!backTapped){
back.enabled = NO;
}
if (!forwardTapped) {
forward.enabled = NO;
}
}
- (void)webViewDidFinishLoad:(UIWebView *)thisWebView
{
[progressWheel stopAnimating];
progressWheel.hidden = YES;
if (!backTapped) {
[back setEnabled:thisWebView.canGoBack];
back.showsTouchWhenHighlighted = YES;
}
if (!forwardTapped) {
[forward setEnabled:thisWebView.canGoForward];
forward.showsTouchWhenHighlighted = YES;
}
}
I can't actually quite understand the problem you are having, but I can see two potential issues:
1) You set backTapped and forwardTapped to YES, but never set them to NO anywhere.
2) Perhaps you don't have "back" or "forward" buttons wired in you xib - if they are nil then back.enabled = NO will do nothing.
Edit:
This logic seems backwards:
if (!backTapped)
back.enabled = NO;
In your code you set backTapped to YES, then this code is hit so !backTapped is ! YES which is NO.
Try
if (backTapped)
back.enabled = NO;