How to safely shut down a loading UIWebView in viewWillDisappear?
I have a view containing a UIWebView which is loading a google map (so lots of javascript etc). The problem I have is that if the user hits the 'back' button on the nav bar before the web view has finished loading, it is not clear to me how to tidily tell the web view to stop loading and then release it, without getting messages sent to the deallocated instance. I'm also not sure that a web view likes its container view disappearing before it's done (but I've no choice if the user hits the back button before it's loaded). In my viewWillDisappear handler I have this
this seems to handle most cases OK, as nil'ing the delegate stops it sending the didFailLoadWithError to my view controller. However if I release the web view in my view's dealloc method, sometimes (intermittently) I will still get a message sent to the deallocated instance, which seems to be related to the javascript running in the actual page, e.g.:
If I simply don't release the webview, then I don't get these messages though I guess I'm then leaking the webview. If I don't send the 'stopLoading' message, and simply release the webview within viewWillDisappear, then I see messages like this:
Possibly related, I sometimes (again totally intermittent) get an ugly heisenbug where clicking the back button on some other view's navbar will pop the title, but not the view. In other words I get left with the title of view n on the stack, but the view showing is still view n+1 (the result is you're trapped on this screen and cannot get back to the root view - you can go the other direction, i.e. push more views and pop back to the view that didn't pop corrrectly, just not to the root view. The only way out is to quit the app). At other times the same sequence of pushes and pops on the same views works fine. This particular one is driving me nuts. I think it may be related to the view disappearing before the web view is loaded, i.e. in this case I suspect it may scribble on memory and confuse the view stack. Or, this could be completely unrelated and a bug somewhere else (i've never been able to reproduce it in debug build mode, it only happens with release build settings when I can't watch it with gdb :-). From my debug runs, I don't think I'm over-releasing anything. And I only seem to be able to trigger it if at some point I have hit the view that has the web view, and it doesn't happen immediately after that. |
|||||||||||||||||||||||||
add comment (requires 50 reputation) |
A variation on this should fix both the leaking and zombie issues:
|
|||||||||||||||||||||||||||||||
|
The UINavigationController bug you're describing in the second part of your post might be related to your handling of memory warnings. I've experienced this phenomenon and I"ve been able to reproduce it on view n in the stack by simulating a memory warning while viewing view (n+1) in the stack. UIWebView is a memory eater, so getting memory warnings wouldn't be surprising when it's used as part of a view hierarchy.
|
|||||||
add comment (requires 50 reputation) |
A simple Your second problem sounds like a prematurely deallocated view, but I can't say much without seeing some code. |
|||||||
add comment (requires 50 reputation) |
There's a few ways to handle it, but this should work. You want the didFailLoadWithError message, it's what tells you it's stopped. Set a flag isLeaving=YES; Send the Webview a stopLoading. In didFailLoadWithError:, check for the error you get when the webview stops: if ((thiserror.code == NSURLErrorCancelled) && (isLeaving==YES)) { [otherClass performSelector:@selector(shootWebview) withObject:nil withDelay:0] } release the webView in shootWebview: variations: if you want to be cavalier about it, you can do the performSelector:withObject:withDelay: with a delay of [fillintheblank], call it 10-30 seconds without the check and you'll almost certainly get away with it, though I don't recommend it. You can have the didFailLoadWithError set a flag and clean it up somewhere else. or my favorite, maybe you don't need to dealloc it all when you leave. Won't you ever display that view container again? why not keep it around reuse it? Your debug being different from release issue, you might want to check your configuration to make sure that it's exactly the same. Bounty was on the reproducible part of the question, right? ;-). -- Oh wait a second, you might be taking a whole View container down with the WebView. You can do a variation on the above and wait to release the whole container in shootWebView. |
|||||||||||||||||||
add comment (requires 50 reputation) |
I have the same problem, when I'm use navigation controller with view controllers in stack > 2 and current view controller index > 2, if an memoryWarning occurs in this momens, it raises the same problems. There is inly 1 solution, which I found after many experiments with overriding pop and push methods in NavigationController, with the stack of view controllers, with views and superviews for stacked ViewControllers, etc.
It works fine for 3 view controllers in stack. |
|||
add comment (requires 50 reputation) |
I had a similar problem to this using a UIWebView in OS3 - this description was a good starting point, however I found than simply nil'ing out the web view delegate before releasing the webView solved my problem. Reading the sample code (the accepted answer - above) - it seems like a lot of overkill. E.g. [webView release] and webView = nil lines do exactly the same thing given the way the author describes the variable is declared (so you don't need both). I'm also not fully convinced by all the retain and release lines either - but I guess your mileage will vary. |
|||
add comment (requires 50 reputation) |
How to safely shut down a loading UIWebView in viewWillDisappear?的更多相关文章
- 简单的使用ehcache
之前一直感觉缓存是高上大的东西,没有心思去研究.做了之后发现,简单的使用还是很容易的.这里记录ehcache在jfinal中的简单使用. 1.ehcahe简介 EhCache 是一个纯Java的进程内 ...
- leveldb
[LevelDB] LevelDB is a fast key-value storage library that provides an ordered mapping from string k ...
- ehcache历史变迁及常用API的使用(转)
ehcache是一个用Java实现的使用简单,高速,实现线程安全的缓存管理类库,ehcache提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案.同时ehcache作为开放源 ...
- iOS网络3—UIWebView与WKWebView使用详解
一.整体介绍 UIWebView自iOS2就有,WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView.通过简单的测试即可发现UIWebView占用过多内存,且 ...
- IOS UIWebView 下拉刷新功能的简单实现
1.运行效果图 2.swift 代码的实现 import UIKit class RefreshWebViewController: UIViewController,UIScrollViewDele ...
- 网络天荒地老之UIWebView&WebKit
UIWebView 是苹果提供的用来展示网页的UI控件,它也是最占内存的控件. iOS8.0之后出现了webkit框架,WKWebView相比UIWebView节省了1/4~1/3的内存,速度快,但是 ...
- UIWebView的使用
iOS中UIWebView的使用详解 一.初始化与三种加载方式 UIWebView继承与UIView,因此,其初始化方法和一般的view一样,通过alloc和init进行初始化,其加载数据的方式有三种 ...
- How to load a local .CSS file & JavaScript resources using iPhone UIWebView Class
This post will cover the basic setup and creation of an application with web content for iPhone that ...
- [iOS Hybrid实践:UIWebView中Html中用JS调用OC方法,OC执行JS代码]
原理: 1.JS调用OC 每次webview执行跳转时都会被iOS给拦截,执行下面函数获得系统允许. 因此可以根据跳转信息转给系统,执行相应功能,比如打开相册等. // 网页中的每一个请求都会被触发 ...
随机推荐
- 两种方式创建Maven项目【方式二】
1.不勾选Create a simple project,直接点击下一步 2.选择maven-archetype-webapp下一步 3.填写相关信息,点击下一步完成 4.此时会报一个jsp的错误.我 ...
- 在 windows7 中使用 vs2003 时,“在文件中查找”导致无响应的问题
解决 Win7 32bit/64bit环境下,在使用VS2003的查找功能时,会导致VS2003无响应. 解决方法:找到VS2003的安装目录,修改"...\Microsoft Visual ...
- mongodb数据操作(CRUD)
1.数据插入db.集合名.insert() 操作 > use hk switched to db hk > show collections > db.info.insert({&q ...
- 使用Spring和Tomcat发布CXF SOAP WebService
上一节中使用代理工厂JaxWsProxyFactoryBean来发布WebService, 这种方式必须指定运行的端口,如果端口被占用,就会发布失败. cxf的WebService也可利用Tomcat ...
- 根据当前日期算前一年、前一月、前一天(java基础)
问题的本身没有什么难度,但是要想一下子找到一个现成的方法还真不是那么容易,本来以为java.util.Date中会有方法结果找了半天没找到,最后还是在Calendar中找到了,记下别忘了!! 核心:使 ...
- mybatis foreach标签的解释 与常用之处
情景:查询数据库中文章的相关文章 文章为一个表 字段tags为相关文章字符串中间用','逗号进行啦分割 查询完一个文章后可以把tags字段构造为一个List<String> 然后利用这 ...
- python开发线程:死锁和递归锁&信号量&定时器&线程queue&事件evevt
一 死锁现象与递归锁 进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将 ...
- Java面向对象-Java类的继承及super关键字
Java面向对象-Java类的继承 1,继承定义以及基本使用 定义:子类能够继承父类的属性和方法: 注意点:Java中只支持单继承: 私有方法不能继承: 上代码: package com.java12 ...
- 预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)转
vs2010的mfc项目中编译c语言出现错误: "...预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)" 解决方法: 建工程时 建立空项目 ...
- Java虚拟机(三):垃圾收集器
一.串行(Serial)收集器 最古老,最稳定 效率高 可能会产生较长的停顿 -XX:+UseSerialGC 新生代.老年代使用串行回收 新生代复制算法 老年代标记-压缩 二.并行收集器 1. Pa ...