I noticed a weird behavior of UIWebview today.
When you open a Uiwebview in a modal view & play a video. Once the complete video is played, we dismiss the uiwebview and on calling it again, we get a crash.
Interesting point to note here is that this behavior is only present in iPad & works fine in iPhone.
On debugging & enabling zombies it pointed to
[MPTransportButton _isChargeEnabled]: message sent to deallocated instance 0x7530930.
The caller:
#import "POCViewController.h"
#import "POCWebViewController.h"
#interface POCViewController ()
#end
#implementation POCViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)displayWebview:(id)sender {
POCWebViewController *objPOCWebViewController = [[POCWebViewController alloc]init];
[self presentViewController:objPOCWebViewController animated:YES completion:nil];
[objPOCWebViewController release];
}
#end
The UIWebview containing viewcontroller
#import "POCWebViewController.h"
#interface POCWebViewController ()
#end
#implementation POCWebViewController
#synthesize webview;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSURL *usl = [NSURL URLWithString:#"Any Youtube url"];
NSURLRequest *urlReq = [NSURLRequest requestWithURL:usl];
[webview loadRequest:urlReq];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
if(webview != nil)
[webview release], webview = nil;
[super dealloc];
}
- (IBAction)dismissTapped:(id)sender {
[self dismissViewControllerAnimated:NO completion:nil];
}
#end
Any idea as to where I am going wrong?
EDIT 1: After playing with the code I observed that the defect was limited to 'jw-player' being used in HTML, i.e flash & other players were fine.
You can try to open the same POC with this link http://www.longtailvideo.com/jw-player/. This uses a jw-player.
When the complete video is played, if you dismiss the view controller containing the uiwebview & present it again, it will lead to a crash.
Use following code to play video in web view its working for me both youtube and vimeo video,if do you have any query let me know.
NSString *youTubeID = #"YOUR YOUTUBE ID";
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];
Related
I have this uiwebview code which on the main works except for the part that forces any links to not open with the uiwebview (basically I would like links to open in the browser)
Can anyone point me in the right direction or see what is wrong with my code
JGViewController.h
#import
#interface JGViewController : UIViewController <UIWebViewDelegate> {
IBOutlet UIWebView *customWebView;
}
#property (strong, nonatomic) IBOutlet UIWebView *customWebView;
#end
JGViewController.m
#import "JGViewController.h"
#interface JGViewController ()
#end
#implementation JGViewController
#synthesize customWebView;
//force any links to open in browser rather than in the uiwebview
-(BOOL) webView:(UIWebView *)customWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL* url = [request URL];
if (UIWebViewNavigationTypeLinkClicked == navigationType) {
[[UIApplication sharedApplication] openURL:url];
return NO;
}
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *httpSource = #"http://www.google.co.uk";
NSURL *fullUrl = [NSURL URLWithString:httpSource];
NSURLRequest *httpRequest = [NSURLRequest requestWithURL:fullUrl];
customWebView.scalesPageToFit = YES;
customWebView.frame=self.view.bounds;
[customWebView.scrollView setShowsHorizontalScrollIndicator:NO];
customWebView.scrollView.scrollEnabled = NO;
customWebView.scrollView.bounces = NO;
//actually call the page into the uiwebview
[customWebView loadRequest:httpRequest];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
fixed by adding
self.webview.delegate = self;
to viewDidLoad function
I'm working on the UIWebView and what I want is for the webView not to over rap the view.
so here is the question. I set the UIWebView ,and the status bar is overlaid over the content.
How can I handle this? I coded as when I made the UIImage view, but at that time there is the navigation bar, and it worked well.
Also I did setFrame:CGRectMake(0, 20).... but also doesn't work. why the [ setFrame]; method doesn't work? Any ideas please.
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIWebView *webView;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault];
[self.webView setFrame:CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height)];
NSURL *myURL = [NSURL URLWithString:#"http://www.amazon.com"];
NSURLRequest *myURLReq = [NSURLRequest requestWithURL:myURL];
[self.webView loadRequest:myURLReq];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)webViewDidStartLoad:(UIWebView *)webView{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
#end
UPDATE: I switched off the Auto-layout and change setFrame:CGRectMake(0, 20) and now they are not overlaid. But I wonder why we need to set this? If I set the status bar translucent , it makes sense. But I set it as the default, which is supposed to start to draw the screen right below the status bar at (0,20).
Try this one
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault];
[self.webView setFrame:CGRectMake(0.0, 20.0, self.view.frame.size.width, self.view.frame.size.height)];
NSURL *myURL = [NSURL URLWithString:#"http://www.amazon.com"];
NSURLRequest *myURLReq = [NSURLRequest requestWithURL:myURL];
[self.webView loadRequest:myURLReq];
}
Your autosize masks should look like this.
Final Output:
Add following code in your viewDidLoadMethod :
if( [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
{
self.edgesForExtendedLayout = UIRectEdgeNone;
}
I know this question has been asked a countless number of times, although I have not been able to get it to work at all, literally no answer has worked, maybe I'm not copying the code across correctly, but either way it wont work.
Anyway, my application's view controller layout is as follows, note that this is a Tabbed Application, NOT a single View Application:
Master Tab Bar Controller > Branches off into multiple Navigation Bar Controllers (all referencing to the same CustomNavigationController class) > Under each Nav Controller are a number of UIViewControllers, some of which are referencing custom view controller classes. (see pic for a visual representation of the hierarchy)
My question is: how can I lock the orientation of all pages in my application to portrait mode ONLY, however allow some pages (UIViewControllers) to be able to rotate to landscape if the user rotates the device? (The pages marked with a star, in the image above are the ones I would like to ALLOW rotation for)
Remember the view controllers that I want to allow rotation for are children to a Navigation controller which is also a child to a Tab Bar Controller. Also, note that one of the View controllers isn't under a Navigation controller, it is just under the Tab Bar controller, not sure how much this affects though.
Thank you so much
Code from the relevant classes of my app
Tab Bar Controller Code (note there is not meaningful code in here as I never used to have a class for this)
#interface TabBarController ()
#end
#implementation TabBarController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Navigation Controller Class (Also never had a class for this
#interface NavigationBar ()
#end
#implementation NavigationBar
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = #"NavigationController";
}
return self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Home Page Class (Must be locked in portrait)
#interface HomePage ()
#end
#implementation HomePage
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = #"HomePage";
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// If the condition is not true/not YES, than create and show alert.
if (![[NSUserDefaults standardUserDefaults]
boolForKey:#"didShowOneTimeAlert"]) {
//Define and Edit the Alert details.
UIAlertView *zoomTip = [[UIAlertView alloc] initWithTitle:#"Tips" message:#"On all web site and map pages, pinch in and out to zoom. \n \n On the 'Program' page, tap on a session to view more details." delegate:self cancelButtonTitle:#"Okay" otherButtonTitles:nil];
//Show the alert
[zoomTip show];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"didShowOneTimeAlert"];
[[NSUserDefaults standardUserDefaults] synchronize];
} // End if
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Map Class (A page that displays a map and MUST be able to rotate)
#interface MezzanineLevelMap ()
#end
#implementation MezzanineLevelMap
#synthesize scrollView, imageView;
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return imageView;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Mezzanine Level"]];
self.imageView = tempImageView;
scrollView.maximumZoomScale = 1;
scrollView.minimumZoomScale = .25;
scrollView.clipsToBounds = YES;
scrollView.delegate = self;
[scrollView addSubview:imageView];
scrollView.zoomScale = .25;
// Change scroll view sizes according to the screen size
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGSize result = [[UIScreen mainScreen] bounds].size;
if (result.height == 480) {
[scrollView setFrame:CGRectMake(0, 5, 320, 475)];
} else {
[scrollView setFrame:CGRectMake(0, 5, 320, 563)];
} // End if
} // End if
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Just implement the following in your view controller (iOS 6+):
- (BOOL)shouldAutorotate {
return NO;
}
In each viewcontroller you can write following code and return yes or no as per requirement.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES/NO;
}
Very good description of fixing this is at
http://koreyhinton.com/blog/lock-screen-rotation-in-ios8.html
I am fairly new to xcode and having an issue with a scrollview. The scrollview works fine...however when using storyboards and push combined i have a problem. When first viewing the scrollview it works fine however when you push to a new page then go back to the storyboard with the scrollview it no longer scrolls. Im thinking this has something to do with the didload and maybe i should be using willappear? The code is below. I think i need to change this code somehow so that it reloads the storyboard everytime go back to this storyboard... Has anyone else come across this issue or advise on how to fix?
//
// PrintViewController.m
//
//
#import "PrintViewController.h"
#interface PrintViewController ()
#end
#implementation PrintViewController
#synthesize PrintScroller, rememberContentOffset;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[PrintScroller setScrollEnabled:YES];
// Do any additional setup after loading the view.
}
- (void) viewDidAppear:(BOOL)animated {
[PrintScroller setContentSize:CGSizeMake(300, 595)];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
self.PrintScroller.contentOffset = CGPointMake(0, 0);
}
- (void)viewWillDisappear:(BOOL)animated {
self.rememberContentOffset = self.PrintScroller.contentOffset;
[super viewWillDisappear:animated];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.PrintScroller.contentOffset = CGPointMake(0, self.rememberContentOffset.y);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I suspect your problem is here:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.PrintScroller.contentOffset = CGPointMake(0, self.rememberContentOffset.y);
}
This method could be called by the system repeatedly when the user is scrolling. Since you're setting the content offset each time, the view won't move. You should only do this once and then, say, set self.rememberContentOffset to CGPointZero, and then avoid changing the content offset if the remembered offset is zero. Something like:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (self.rememberContentOffset.y > 0) {
self.PrintScroller.contentOffset = CGPointMake(0, self.rememberContentOffset.y);
self.rememberContentOffset = CGPointZero;
}
}
I have an app where I would like to push a button and have the user taken to a web view. However, I would like a particular page to load depending on the button that's pushed. Originally I thought about creating a separate web view for each button, but that only caused more issues, which I won't go into. So my question is: How can I load different URL's into a web view, based on whether a particular button is pushed?
I thought about using the prepareForSegue method, but thought that might be over complicating things. Any direction would be great.
so you must create new viewController with UIWebView inside it.
On newViewController create a NSString property named url or somethings like that
example:
#property (retain, nonatomic) NSString *url;
#property (weak, nonatomic) IBOutlet UIWebView *webView;
On buttonTouchUpInside event in oldViewController
UIStoryboard *mainStorybroad = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
newViewController *webViewController = [mainStorybroad instantiateViewControllerWithIdentifier:#"webviewIdentifier"];
webViewController.url = #"url string";
and final, in newViewController you just do:
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
Why don't you link the button in IB to just do a modal transition to the view controller page? Then, in the viewdidload on the new view controller, the code should look something like this:
NSString *fullURL = #"google.com";
NSURL *url = [NSURL URLWithString:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[_webView loadRequest:requestObj];
How many buttons do you have? If it's just a couple, then I would just create an extra couple view controllers. If it's a bunch, you could always create a global variable (I can already hear the cringing...) and set the variable equal to the desired URL depending on which button was pushed.
How can I load different URL's into a web view, based on whether a particular button is pushed?
There are two basic approaches to recognizing different buttons:
separate actions: You can create a separate action method for each button, and then just hook up each button to the corresponding action.
single action: You can create a single action for all the buttons, and use some property of the buttons to differentiate between them.
The first one looks like this:
- (IBAction)button1Action:(UIButton*)sender
{
[self.webView loadRequest:[NSURLRequest requestWithURL:url1]];
}
- (IBAction)button2Action:(UIButton*)sender
{
[self.webView loadRequest:[NSURLRequest requestWithURL:url2]];
}
The second looks like:
- (IBAction)buttonsAction:(UIButton*)sender
{
switch (sender.tag) {
case button1Tag:
[self.webView loadRequest:[NSURLRequest requestWithURL:url1]];
break;
case button2Tag:
[self.webView loadRequest:[NSURLRequest requestWithURL:url2]];
break;
}
}
Here is the code for .h and .m File
Create a XIB and Put UIWebView on it and bind it to the class.
For Header File
#import <UIKit/UIKit.h>
#interface NewWebViewController : UIViewController<UIWebViewDelegate> {
IBOutlet UIWebView *webView;
NSString *currentURL;
UIActivityIndicatorView *activityView;
}
#property (nonatomic, copy) NSString *currentURL;
#property (nonatomic, retain) UIActivityIndicatorView *activityView;
#end
For Implementation File (.m)
#import "NewWebViewController.h"
#interface NewWebViewController ()
#end
#implementation NewWebViewController
#synthesize currentURL;
#synthesize activityView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
webView.frame = self.view.frame;
[webView setScalesPageToFit:YES];
NSURL *url = [NSURL URLWithString:self.currentURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
self.activityView = [[[UIActivityIndicatorView alloc] init] autorelease];
self.activityView.tag = 1;
self.activityView.hidesWhenStopped = YES;
UIView *customView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)] autorelease];
self.activityView.center = customView.center;
[customView addSubview:self.activityView];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:customView] autorelease];
[self.activityView startAnimating];
}
#pragma mark UIWebView Delegate
- (void)webViewDidStartLoad:(UIWebView *)webView {
[self.activityView startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self.activityView stopAnimating];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(#"Error %#",[error description]);
[self.activityView stopAnimating];
}
- (void)viewDidUnload
{
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[webView stopLoading];
webView.delegate = nil;
webView = nil;
self.activityView = nil;
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
webView.frame = self.view.frame;
return YES;//(interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void) dealloc {
[currentURL release];
[webView release];
[super dealloc];
}
#end
Here how to use this
- (void) openWebViewControllerWithURL:(NSString*) url {
if (!url) {
return;
}
NewWebViewController *vController = [[NewWebViewController alloc] initWithNibName:#"NewWebViewController" bundle:nil];
vController.currentURL = url;
[self.navigationController pushViewController:vController animated:YES];
[vController release];
}
On click of button just pass the URL you want to load
like this
[self openWebViewControllerWithURL:#"http://www.google.com"];