怎样计算带有UIWebView的Cell的高度? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
11
V2EX    iDev

怎样计算带有UIWebView的Cell的高度?

  •  1
     
  •   11 2013-12-05 21:11:47 +08:00 6662 次点击
    这是一个创建于 4332 天前的主题,其中的信息可能已经有所发展或是发生改变。
    UIWebView在每个cell中的内容都不同,在 tableView:cellForRowAtIndexPath: 中 alloc 的,然后需要在 heightForRowAtIndexPath: 中计算高度。

    可是问题是,在创建这个cell之前没法知道UIWebView的高度呀,可是 heightForRowAtIndexPath 是需要在这之前提供高度的。也就说调用 UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 会出错。


    所以应该怎么办?如果在 heightForRowAtIndexPath 中 alloc 一个 UIWebView 再读取 htmlString 得到 height 这样速度会太慢了吧,而且会做两边同样的工作。。

    求解。
    16 条回复    1970-01-01 08:00:00 +08:00
    ultragtx
        1
    ultragtx  
       2013-12-05 21:34:43 +08:00   1
    一般tableview用label都嫌拖动的时候卡 用webview估计你早晚要改实现方式
    如果硬要这么整那只有你说这种 反正要先算出来 或者是你先给个大概的高度 然后等webview加载完了再更新
    11
        2
    11  
    OP
       2013-12-05 21:51:41 +08:00
    @ultragtx 但是如果做图文混排的那种,比如论坛客户端什么的,用UIWebView貌似是最理想的选择了吧。 用 CoreText 太折磨人了。。
    xuan_lengyue
        3
    xuan_lengyue  
       2013-12-05 22:15:11 +08:00
    @11 为什么不整体用UIWebView实现呢,UITableView 里面嵌 UIWebView 这个会很有问题。
    harrymoo
        4
    harrymoo  
       2013-12-05 22:38:02 +08:00   1
    1. heightForRowAtIndexPath:中返回你的uiwebview的height;
    2. uiwebview加载完后,在webViewDidFinishLoad:中计算出实际高度,调用:
    [self.tableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone];
    [self.tableView beginUpdates];
    [self.tableView endUpdates];
    完毕。
    11
        5
    11  
    OP
       2013-12-05 23:25:17 +08:00
    @harrymoo 所以在 1 中,这里的 height 是随便设的一个值么?不是真正的 height。
    chisj
        6
    chisj  
       2013-12-06 09:28:21 +08:00   1
    @11 不是的,这个就是cell的height,只是你的webView高度在内容load前和load后会变化,所以需要重新设置并reload tableView。
    so898
        7
    so898  
       2013-12-06 13:55:41 +08:00   1
    我曾经做过楼主你正在做的事情……

    首先,UITableView的heightForRowAtIndexPath:函数是在主线程中运行的,而且必须在reload的时候提供一个可以使用的值
    然后,UIWebView的高都计算需要在Web载入完成之后通过JS或者contentViewSize来计算,这个部分中Web载入是在独立的WebCore线程中进行的,载入完成之后通过Delegate回掉通知主线程

    所以说,要做的话就是得在heightForRowAtIndexPath:提供一个大概的高度值,然后在UIWebView载入完成算完高度之后refresh指定的Cell
    但这个实现有个问题,就是Cell不太好复用,而且后续Cell高度计算会导致所有内容全部被加载到UIWebView里面,在面对微博之类的内容的时候会导致内存占用过高
    如果要复用的话,就得建立很好的NSURLCache来缓存主要页面内容,然后祈祷UIWebView快点加载……

    对了,这里还要说一下注意的点,就是UIWebView的webViewDidFinishLoad:会被多次调用的,这里要做好处理
    11
        8
    11  
    OP
       2013-12-06 17:03:11 +08:00
    @so898 所以呢。。后来你还是用这个方案么?我昨天试了 @harrymoo 说的,然后果然就在 webViewDidFinishLoad: 这里卡死了。。这里应该怎么处理?我是用 superview 得到的 cell,然后得到 indexPath,再用的 [self.tableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone] 。就卡死了。。求个 example。 @chisj
    harrymoo
        9
    harrymoo  
       2013-12-06 19:06:03 +08:00   1
    @11 怎么个卡死? 其实@so898也已经提到了,你不应直接在 webViewDidFinishLoad:里面去refresh tableview,因为是不同的线程,建议Post一个Notification到界面主线程处理。
    chisj
        10
    chisj  
       2013-12-09 20:14:43 +08:00   1
    @11 因为没有看到你的代码,我猜测下看能不能帮你提供一点思路:你的程序卡死的原因可能是死循环?在webViewDidFinishLoad: 你调用了 [self.tableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone],然后在UITableView Datasource的 tableView:cellForRowAtIndexPath:里,你返回的cell里又重新init或者load了webView,导致了死循环?

    是否可以试试在viewDidLoad里就初始化好UIWebView,然后tableView:cellForRowAtIndexPath:里add到cell的contentView里。

    这样至少不会死循环导致你程序“卡死”。
    11
        11
    11  
    OP
       2013-12-09 22:04:09 +08:00
    @chisj Exactly! 如果在 viewDidLoad 里初始化 UIWebView 的话,也需要得到 cell 才能进行初始化?因为 UIWebView 是在每个 cell 中的。

    我觉得我现在的思路有问题,麻烦请教一下那些图文混排的微博客户端什么的都是怎么做 cell?
    chisj
        12
    chisj  
       2013-12-09 23:30:41 +08:00
    @11 图文混排的微博现在好像都不用UIWebView了,毕竟性能上不好,应该都是使用CoreText了,参考唐巧的博客: http://blog.devtang.com/blog/2013/10/21/the-tech-detail-of-ape-client-3/ 。你说的“得到cell才能进行初始化”我没有理解是什么意思啊~~~
    BB9z
        13
    BB9z  
       2013-12-11 09:54:36 +08:00
    如果 WebView 在顶部的话建议方到 table 的 header view 里。更新高度的话 headerView = headerView 就可以。
    dazuiba
        14
    dazuiba  
       2013-12-24 21:41:36 +08:00
    如果楼主你实在想这么干,我这里有个方案:

    UIWebView load完毕后,执行一段JS,拿到document的Height.再通过WebView的Delegate传递给Objective-C Code.

    然后再传递给TableViewController,告诉它这个Cell的高度已经拿到了,待所有Cell的高度都返回后,TableViewController开始显示TableView.

    貌似没别的好办法。
    CDuXZMAPgHp1q9ew
        15
    CDuXZMAPgHp1q9ew  
       2014-03-01 00:10:30 +08:00
    楼主啊
    富文本两个办法

    coretext
    自己实现起来要求较高
    开源库有 一些 比如说 rtlabel rclabel TTTAttributedLabel FTCoreText SECoreTextView

    webview
    注意哦 不是每个cell一个webview, 一个webview就够你受得了, 会卡死你的

    这里有一个绝佳的tableview里面加了两个webview的实践
    https://github.com/gaosboy/iOSSF/

    或者最好使用一个webview用html5搞得像原生的一样, 在复杂页面时效果最好
    比如说 我现在做的一个论坛的客户端中的帖子页面
    CDuXZMAPgHp1q9ew
        16
    CDuXZMAPgHp1q9ew  
       2014-03-01 00:12:11 +08:00
    另外
    https://github.com/gaosboy/iOSSF/
    里面的检测contentSize获得高是我见过最好最"原生"的方法
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5353 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 48ms UTC 01:16 PVG 09:16 LAX 18:16 JFK 21:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86