How to know UIWebView won't load anymore? - iphone

I know that there are delegate methods.
In my case, the scenario is little bit different. When I load my request, there are subsequent calls that happens. So the page get loaded back to back with 3 urls. After that, it stops.
When it is done loading everything, after that actually I wanted to do something like 'autosubmit', which is not possible for mobile browsers. I am looking for a work around. But for that too, I need to make sure that the webView has done loading.
So my question here is, is there any proper way to find out that the web view has finally stopped loading, and then I can try something to do my 'autosubmit' part?

I have an answer to the detecting when the web view is done loading part of your question... Unfortunately, the most reliable method I have found is to increment a counter whenever webViewDidBeginLoad: is called and decrementing it whenever webViewDidFinishLoading: and webViewDidFailWithError: is called. Whenever the counter is equal to 0 you know that the web view is not loading.
Placing this check in the webViewDidFinishLoading: and webViewDidFailWithError: methods will allow you to determine when the web has completed or stopped loading (in the case of a failure).

Related

Where can I found documentation about page lifecycle events?

I am using cdp (https://github.com/mafredri/cdp) in order to use devtools protocol to generate a pdf of a page. But first I need to know when the page is completely loaded. I found that the networkIdle event can help me to know when this occurs. But, I have troubles because the networkIdle event sometimes fired twice. Then I need to know when this one is fired
There are two parts for what you're looking for.
First of all, the reason the event is fired twice. When a new tab (target) is created, the first page it loads is about:blank. You get lifecycle events for this page as well. The second time the load event is fired is the one you're looking for (if you're using Page.lifecycleEvent).
Now, to handle the second matter - there are also other events you can use. The basic one for page loading is Page.loadEventFired, which, as far as I recall, will only be fired for the actual page (but I could be wrong about this one).
Important note: If you're using lifecycle events, they are fired for each frame separately, meaning that the main frame might finish loading before the sub frames are loaded. Page.loadEventFired has a different behavior and waits for all frames to fire their load event.
Here is a good article on the page lifecycle api.
Another possible solution could be:
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
run the screenshot code...
}
}

Process page, or be notified that elements are present even if page not fully loaded

The page I'm using watir-webdriver on will often not load completely for maybe like a minute because of the many external scripts I'm loading/using. This of course means that I have to wait needlessly for a minute when I could have performed the checks I wanted to in 10 seconds after the browser I'm controlling (Firefox) started loading the page.
I noticed that even though my target elements become immediately available in the page, the browser.div(:id => 'some_id').present? method hangs until the page is fully loaded. I noticed that if I press on the stop button in the browser window, watir will immediately continue successfully with my tests (the present? method un-hangs). Is there a way to avoid this behavior of the present? method and be able to tell that my target elements are present without having to wait for the page to fully load?
I've experienced this issue before as well. The method I employed, which rides on the idea you mentioned about hitting the stop button, is as follows:
begin
browser.wait_until{browser.div(:id => 'some_id').present?}
rescue
browser.send_keys :escape
end
expect(browser.div(:id=> 'some_id').present?).to be true
This, by default, gives that div 30 seconds to appear (you can insert a smaller value then 30 if you prefer), otherwise it causes watir to hit 'escape' which will stop any remaining background page loading and resume the test.
.present?
As I understand it checks to see if an element exists AND is visible.
What I would suggest you try, is
.exists?
This will simply check that the element exists, and doesnt care if its visible or not.
Just for reference, there is also a
.visible?
Which just makes sure the item is visible, though I dont ever use that one.

Forcing a view to unload when another tabButton is hit. (iPhone)

My iPhone app has a tabBar at the bottom.
The 5th tab is rarely used... but pretty memory-intensive... so I want to make it UNLOAD each time it is exited (by the user clicking on a different tab).
But how?
I thought I just needed to call "[self viewDidUnload]" but that doesn't seem to do it.
Where is the "forceThisViewToUnload" and where should I put it?
i think you can call didReceiveMemoryWarning but its bit hacky way :)
just make sure it's not referenced anywhere.
so remomve it from the view-stack, and if you own it, send it a release message.

Prevent cached iPhone webapp from reloading (scrolling to top)

I have an iPhone webapp that uses a cache manifest to work offline. I add the webapp to my home screen, use it (say scroll to a certain location on a page), then go back to homescreen.
When I open the app again, for a brief moment I see where I used to be (at that scrolled location on that page), but then the app "reloads" and I get scrolled to the top of the mainpage. Is there a way to prevent this "reloading"? This happens even in airplane mode (ie everything is working off the cache).
You're just seeing the default startup image, which is just a screenshot of the last place you were at. It's not "reloading"; the app wasn't loaded to begin with.
Search for "apple-touch-startup-image" to set a real loading image.
What I'm struggling with here is that the app actually seems to stay "in memory" longer if I use regular Safari as opposed to running in "apple-mobile-web-app-capable" mode. In the later case something as simple as pressing the home button, then task-switching back to the app causes a reload. Doing the same thing just in Safari often does not reload. So I'm worse off by using "apple-mobile-web-app-capable".
I don't believe there is a real 'reload' event. onload and onunload are all we get.
the onload handler starts up as if it is your first time coming to the page.
the onunload handler is the key to clearing out old content.
I like to provide alternate content for people who are coming back to my web app.
window.onunload=function(){
document.getElementsByTagName('body')[0].className+=' unloading'
}
And let the CSS do the dirty work to hide most of the body and show alternate content.
(this answer does not rely on jQuery or other frameworks)
// on load
window.scroll(0,0);
To ensure no old content is displayed while launching I use this in my page:
window.addEventListener('unload', function() { $('body').hide(); } );
Thus the last state of the page is empty and is what is shown to the user when the page is opened again.

How to detect page change in UIWebView and do something before it starts loading?

I need to do something on each page change, before that page starts loading/executing.
First, I tried using -webView:shouldStartLoadWithRequest: but that won't work, because it's also called for XHR requests and iframe requests.
Second, I tried using -webViewDidStartLoad: and comparing webView.request to it's previous value, to see if it changed. This doesn't work, because webView.request is updated only some time after the call.
Any more ideas?
The request object in webView:shouldStartLoadWithRequest: has two properties,
BOOL iframe = ![request.URL isEqual:request.mainDocumentURL];
If the URL to load is not equal to the mainDocumentURL you are loading something other than main doc (probably an iFrame).
Have you tried using KVO to observe UIWebView.request?
Make a Category or extend UIWebview that overrides loadRequest, doing your operation first and then doing the standard loadRequest.