I'm hitting an iOS assertion when dismissing a UIViewController. The UIViewController has a UIView, to which I've added a WKWebView. Into that WKWebView I've loaded a PDF file. The PDF displays and functions fine. When I dismiss the window, Xcode reports an assertion:
-[PDFExtensionTopView _accessibilityUnregisterRemoteView]: unrecognized selector sent to instance
If I have my All Objective-C Exceptions breakpoint on, execution is stopped. I can continue, but this is rather disruptive. Users never see any issue, so this is purely a development-time problem. I work around the issue by disabling breakpoints when using this view, but would prefer to find a real fix. I'm on Xcode 11.3.1, using ObjC in this class.
I've created a simplified dummy project. The entire UIViewController's code is below. It is presented from a simple UIButton that passes nothing to this UIViewController.
Moving the displayPDF method call is in viewWillAppear, but no change if in DidAppear, DidLoad, etc. It isn't related to the specific PDF (I've tried files from multiple sources).
If I use displayHTML (which puts dummy HTML into the webView), I do not experience the problem.
I might just be rusty in ObjC and missing something obvious. Any thoughts?
#import "MyPDFViewController.h"
#import <WebKit/WebKit.h>
#interface MyPDFViewController ()
#property (strong, nonatomic) IBOutlet UIView *pdfContainerView;
- (IBAction)closeButtonPressed:(id)sender;
#property (nonatomic, strong) WKWebView *webView;
#end
#implementation MyPDFViewController
-(void)viewWillAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self displayPDF];
}
-(void)displayPDF {
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyPDFFile" ofType:#"pdf"];
NSData *data = [NSData dataWithContentsOfFile:path];
self.webView = [[WKWebView alloc] initWithFrame:self.pdfContainerView.frame configuration:[[WKWebViewConfiguration alloc] init]];
[self.webView loadData:data MIMEType:#"application/pdf" characterEncodingName:#"utf-8" baseURL:[NSURL URLWithString:#""]];
[self.pdfContainerView addSubview:self.webView];
}
-(void)displayHTML {
[self.webView loadHTMLString:#"<html><body>Hi.</body></html>" baseURL:nil];
}
- (IBAction)closeButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
//
}];
}
#end
Related
I am pretty new to Objective-C and iOS programming.
I have a SummaryUITableViewCell (a custom class inheriting from UITableViewCell) which contains an Activity Indicator (loadingSpinner) and a UIWebView (webView).
My app gets a list of URLs to load, then presents the table view, one cell per URL.
In cellForRowAtIndexPath I start the animation for the loading spinner and call cell.webView loadRequest:URL.
Everything works fine and webViewDidFinishLoad gets called once per URL (it has just an NSLog statement in it for now). What I can't figure out is how to find the appropriate loadingSpinner so that I can stop the animation and hide it.
You want each of your SummaryUITableViewCell to implement UIWebViewDelegate and handle the webViewDidFinishLoad call themselves. Then you can easily hide the spinners each time the UIWebView loads. Here is one way you could implement the SummaryUITableViewCell.
SummaryTableViewCell.h
#import <UIKit/UIKit.h>
#interface SummaryTableViewCell : UITableViewCell <UIWebViewDelegate>
#end
SummaryTableViewCell.m
#import "SummaryTableViewCell.h"
#interface SummaryTableViewCell ()
// Keep references to our spinner and webview here
#property (nonatomic, strong) UIActivityIndicatorView *spinner;
#property (nonatomic, strong) UIWebView *webView;
#end
#implementation SummaryTableViewCell
- (instancetype)initWithUrl:(NSString *)url {
self = [super init];
if (self) {
[self setup:url];
}
return self;
}
- (void)setup:(NSString *)url {
// Add Webview
self.webView = [[UIWebView alloc] initWithFrame:[self frame]];
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
[self.webView setAlpha:0];
// Set the cell as the delegate of the webview
[self.webView setDelegate:self];
[self addSubview:self.webView];
// Add Spinner
self.spinner = [[UIActivityIndicatorView alloc] init];
[self addSubview:self.spinner];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// The web view loaded the url so we can now hide the spinner and show the web view
[self.spinner setAlpha:0];
[self.webView setAlpha:1];
}
#end
Still having some trouble with Webkit. After sorting out my error from yesterday morning, I have encountered a whole new slue of them ranging from 113 to straight up crashes (really new to iOS dev, formally trained in C++ and very rusty haha).
I've finally got some code that doesn't crash and I feel like I'm definitely getting a better grasp on Objective-C/iOS Dev in general - there's just one issue... It doesn't load.
WebView.h
#ifndef WebView_h
#define WebView_h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <Webkit/Webkit.h>
#interface ViewController: UIViewController;
#property (nonatomic, strong) IBOutlet WKWebView *webView;
#property (nonatomic, strong) IBOutlet UIView *view;
#end
#endif WebView_h
WebView.m
#implementation ViewController
#synthesize webView;
-(void) viewDidLoad {
[super viewDidLoad];
webView = [[WKWebView alloc] initWithFrame:[[self view] bounds]];
NSURL *url = [NSURL URLWithString:#"http://www.penelopeperu.com/"];
NSURLRequest *urlReq = [NSURLRequest requestWithURL:url];
[webView loadRequest:urlReq];
self.view = webView;
}
#end
I suspect it has something to do with the view / UIView and loading? I'm just not sure how to pinpoint what I'm doing wrong exactly.
Your url is not using "https" security protocol, so you need to add following key in Info.plist file to allow load your url in web view.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Also you are doing one more wrong thing with webview.
This doesen't proper way to add webview in self.view.
self.view = webView;
updated this line with;
[self.view addSubview:webView];
I have my ViewController, MyWebViewController where I use a webView, created in xib. .h file has
#interface MyWebViewController : UIViewController
#property (nonatomic,strong) IBOutlet UIWebView* webView;
in .m file,
- (void)viewDidLoad {
[super viewDidLoad];
[self.webView loadRequest:[NSURLRequest requestWithURL:[[NSURL alloc] initWithString:#"http://www.google.com"]]];
}
Here is my xib
It works perfect for me.
Later I create another ViewController, RootViewController of type MyWebViewController.
#import "MyWebViewController.h"
#interface RootViewController : MyWebViewController
The xib of MyViewViewController is loaded as expected, but the webView is not loaded to the xib. I spent more time in debugging.
Later, I removed the webView from xib and created it programmatically.
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 441)];
self.webView.delegate = self;
[self.webView loadRequest:[NSURLRequest requestWithURL:[[NSURL alloc] initWithString:#"http://www.google.com"]]];
[self.view addSubview:self.webView];
Creating the webView programmatically gives the expected output.
I need a little clarification that, why was my webView not loaded, when it was created in xib, and, works fine when it was created programmatically?
In your RootViewController, did you call:
- (void)viewDidLoad {
[super viewDidLoad];
}
This way it will trigger the base class function and webView will load expectedly. You forget to put this in MyWebViewController as well.
EDIT :
The reason self.webView is not getting load in derived class is because it is marked IBOutlet so it needs a reference of pre-allocated element from UIView or xib and in the derived class we are not instatiating base view file e.g., MyWebViewController.xib. So self.webView appears nil and function call on nil getting ignored silently. So, once you do it by code it is independent of xib file and works.
Hope it helps!
This was due to change in iOS9 view loading behavior. Developer is supposed to update the UI elements in -viewWillLayoutSubviews or -viewDidAppear.
I have a viewcontroller that loads a webView in the view did load
#synthesize webView = _webView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.webView = [[UIWebView alloc] init];
[self.webView setDelegate:self];
NSString *string = #"http://www.google.com";
NSURL *url = [NSURL URLWithString:string];
NSLog(#"The URL is %#", url);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSLog(#"The request is %#", request);
NSLog(#"webview delegate is %#", self.webView.delegate);
NSLog(#"webview is %#", self.webView);
[self.webView loadRequest:request];
}
Everything is working fine when i debug meaning that nothing is returning nil. I declared the property in the .h file like this
#property (nonatomic, retain) IBOutlet UIWebView *webView;
I have also tried
#property (nonatomic, strong) IBOutlet UIWebView *webView;
and the WebView in IB is hooked up to delegate and this property. The problem is that no matter what url I try (I have tried them all in the browser), the web view only returns a white screen. All the delegate methods have been called, I know because I logged to the console. Does anyone know how to fix this or what I am doing wrong.
From your code -
#property (nonatomic, retain) IBOutlet UIWebView *webView;
Since you are connected webview to an outlet, the instance of webview is created after the unarchiving of your Nib.
So no need to instantiate webview again -
self.webView = [[UIWebView alloc] init];
Remove the above line from your code and test it. Should work!
Well, the fix for this issue seems to me pretty straightforward.
You're not setting any frame for your web view. Try the following:
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,500,500)];
Of course, the actual dimensions for your web view may vary. You'll have to adjust it yourself.
Update
I'm seeing that you're not adding the web view as a subview. Add the following line after the call to loadRequest:
[self.view addSubview:self.webView];
Hope this helps!
I'm relatively new to programming in general, but I've attempted to find the answer to this and have failed to no end.
So basically I am attempting to create an application that has a map view scene, and that works fine. I then have another scene that is for web view. So when you go to the mapview scene there is a button that takes you to the webview scene.
The webview scene, however is not loading the web page at all, although when I create the webview part of the application in a different project with no other coding involved, it works just fine.
Here is the coding I have so far:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface ViewController : UIViewController {
MKMapView * mapview; IBOutlet UIWebView *webview;
}
#property (nonatomic, retain) IBOutlet UIWebView*webview;
#property (nonatomic, retain) IBOutlet MKMapView *mapview;
-(IBAction)setMap:(id)sender;
-(IBAction)getlocation;
#end
--------
#implementation ViewController
#synthesize webview;
#synthesize mapview;
-(IBAction) getlocation {
mapview.showsUserLocation= YES;
}
-(IBAction)setMap:(id)sender {
switch(((UISegmentedControl *) sender).selectedSegmentIndex) {
case 0:
mapview.mapType= MKMapTypeStandard;
break;
case 1:
mapview.mapType= MKMapTypeSatellite;
break;
case 2:
mapview.mapType= MKMapTypeHybrid;
break;
default:
break;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
[webview loadRequest:[NSURLRequest requestWithURL: [NSURL URLWithString: #"http://www.google.com"]]];
// Do any additional setup after loading the view, typically from a nib.
}
If you could help, would be greatly appreciated. Let me know if elaboration is required.
First make sure viewDidLoad is executing. There are some situations where it will not be executed.
Then check if webview is nil inside viewDidLoad. Most likely this is your problem. You probably aren't setting it properly, or you're setting it after viewDidLoad executes.
Best way to debug this is just to stick a breakpoint on the loadRequest line in your code, and have a look to see if:
it gets to your breakpoint at all
that the webview variable is not 0x00000000000
PS: you should delete these lines of code:
MKMapView * mapview; IBOutlet UIWebView *webview;
-(IBAction)setMap:(id)sender;
#synthesize webview;
#synthesize mapview;
They are not needed anymore in the latest version of Xcode and wherever you learned it from is outdated.
Also, use self.webview instead of just webview. Accessing it directly is dangerous and can cause bugs.
Create webView programmatically:
add in viewDidLoad:
UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://google.co.uk"]]];
[self.view addSubview:webView];
please check web view delegate method
[webview setDelegate:self];