Reputation: 899
I am using a UIWebView in my app to load the contents of a website. I then use javascript to log into the website, and then I parse the contents of the page after I've logged in to grab the data I need. I do this every 5 minutes, which works fine in the foreground. However, when I background the app, I make a call to the UIViewController that holds the UIWebView and I hit the method that loads the URL into the UIWebView, but nothing happens after that.
I am fairly sure that the UIViewController must be active to update the UIWebView, but is there a way around this? Checking this data in the background is really the entire point of the app.
EDIT
jakepeterson - Based on your code, I tried to subclass a UIWebView starting in Swift. This is as far as I got:
class CustomWebView: UIWebView, UIWebViewDelegate
{
var webView: UIWebView
var requestURL: NSURL
var urlRequest: NSURLRequest
init()
{
webView = UIWebView()
requestURL = NSURL(string: "http://www.google.com")
urlRequest = NSURLRequest(URL: requestURL)
super.init(frame: CGRectMake(0, 0, 100, 100))
webView.delegate = self
webView.addSubview(webView.window)
webView.loadRequest(request)
}
func webViewDidFinishLoad(sender: UIWebViewDelegate)
{
//Do stuff
}
}
I am still not hitting the webViewDidFinishLoad delegate method. I think it has to do possibly with this line:
webView.addSubview(webView.window)
In your code you have self.view but that doesn't show up as an available option.
UPDATE
Here is what I am doing now and the delegates are now getting triggered:
import UIKit
class CustomWebView: UIWebView
{
var uiView = UIView()
init(frame: CGRect)
{
super.init(frame: frame)
self.delegate = self
}
convenience init(frame:CGRect, request:NSURLRequest)
{
self.init(frame: frame)
uiView.addSubview(self)
loadRequest(request)
}
}
extension CustomWebView: UIWebViewDelegate
{
func webViewDidStartLoad(webView: UIWebView!)
{
println("webViewDidStartLoad")
}
func webViewDidFinishLoad(webView: UIWebView)
{
println("webViewDidFinishLoad")
}
func webView(webView: UIWebView!, didFailLoadWithError error: NSError!)
{
println("An error occurred while loading the webview")
}
}
Upvotes: 2
Views: 4115
Reputation: 899
It appears that the trick I found of adding the control to a UIView to get the delegates to fire only works in the foreground. So for anyone checking this question there currently does not seem to be a way to do this in the background.
Upvotes: 0
Reputation: 2113
Here's an example of how the UIWebView
class can be used objectively with asynchronous logic:
- (id)init
{
self = [super init];
if (self)
{
self.webView = [[UIWebView alloc] init];
self.webView.delegate = self;
[self.view addSubview:self.webView];
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:self.activityIndicator];
}
return self;
}
- (id)initWithUrl:(NSURL *)url
{
self = [self init];
if (self)
{
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
[self.activityIndicator startAnimating];
}
return self;
}
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[self.activityIndicator stopAnimating];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
[self.activityIndicator stopAnimating];
NSLog(@"An error occurred while loading. (error: %@)", error);
// Alert the user
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops" message:@"Dude... we messed up. This web page can't be loaded at this time." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
Why does this work?
Because you are depending on the delegate methods of UIWebViewDelegate
to tell you when the UIWebView
has finished loading. I included the error delegate method as a bonus.
The example here is using a UIActivityIndicatorView
class, which is designed for use in asynchronous tasks. By following this same implementation style, you can replace the activityIndicator
with virtually anything you plan to act on the results of the UIWebView
pragmatically with.
Good luck
UPDATE
Swift is a whole other beast. Your swift class has a plethora of errors in it. This is how I would re-write what I originally gave you in ObjC in Swift:
import UIKit
class CustomWebView: UIWebView {
var activityIndicator:UIActivityIndicatorView
init(frame: CGRect) {
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
super.init(frame: frame)
self.delegate = self
}
convenience init(frame:CGRect, request:NSURLRequest) {
self.init(frame: frame)
loadRequest(request)
}
}
extension CustomWebView: UIWebViewDelegate {
func webViewDidFinishLoad(webView: UIWebView) {
self.activityIndicator.stopAnimating()
}
func webView(webView: UIWebView!, didFailLoadWithError error: NSError!) {
self.activityIndicator.stopAnimating()
println("An error occurred while loading the webview")
}
}
Upvotes: 2