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
VichyChen
V2EX  ›  iDev

求 iOS 一个解决方案:关于在 TabelViewCell 中嵌套 UIWebView 加载 html,计算 UIWebView 高度的问题。

  •  1
     
  •   VichyChen · 2015-10-10 14:56:46 +08:00 · 9112 次点击
    这是一个创建于 3340 天前的主题,其中的信息可能已经有所发展或是发生改变。

    TabelViewCell 嵌套 UIWebView , UIWebView 加载 html , html 中偶尔包括有<img>、<a>。

    现在的问题是如何计算 UIWebView 的高度。
    因为 UIWebView 的高度得在 webViewDidFinishLoad:中才能正确获取到,在 cell 中我是直接用 setFrame 来做定位的,现在我迷茫的就是要怎么准确计算出高度?

    ps :如果用 setFrame 不好实现,用 autolayout 好实现吗?一直对 cell 中用 autolayout 来布局有点抗拒。。

    现在的情况是哪种能实现就用哪种!求解决方案,求一个准确的思路!

    36 条回复    2015-10-16 23:35:47 +08:00
    kenshinhu
        1
    kenshinhu  
       2015-10-10 15:00:52 +08:00
    可以通过 js 桥接的方法,当 HTML 在 WebView 渲染完成后通过 JS 调用 OBJC 的代码来传递内容高度后再 UI 里调用
    kenshinhu
        2
    kenshinhu  
       2015-10-10 15:03:55 +08:00
    其实 frame 或 layout 也一样,你得要知道 WEB 内容的高度才能展示,至于 IMG 标签的问题,可以通过 CSS 固定高度的方式解决,或能过先检测 HTML 内的图片地址并下载,再和内容一起计算高度
    当然 如果你的需求可以在 webview 里是有 SCOLLVIEW 的话,以上就是然并...
    VichyChen
        3
    VichyChen  
    OP
       2015-10-10 15:28:42 +08:00
    @kenshinhu T_T 完蛋听不懂,还是不晓得怎么处理。。

    我现在的流程是: cellForRowAtIndexPath 对 cell 里的 UIWebView 做赋值,在 cell 的 layoutSubviews 里面做 setFrame ,然后普通情况我的高度计算都放在网络请求回调之后先计算缓存在数组,然后现在知道 UIWebView 要在 webViewDidFinishLoad 中再获取高度再重新调整,就不晓得咋办了。。

    求解释清晰点,能不用 js 尽量别用到 js =。=
    ltfpeter
        4
    ltfpeter  
       2015-10-10 15:45:10 +08:00
    说个有点跑题的问题,你是每个 cell 都内嵌了一个 webview 么?如果 webview 太多容易运行效率很低吧
    VichyChen
        5
    VichyChen  
    OP
       2015-10-10 15:51:50 +08:00
    @ltfpeter
    我试了写好一定高度,跑起来没觉得有卡顿的情况呀。。

    好吧 那有一个可以显示 html ,显示<img>,能响应到超链接的轮子吗?
    attributedstring 不懂怎么响应超链接, RTLabel 显示不了<img>,其他一些轮子都有一两种实现不了。。
    至于什么用 textkit 自己写一个富文本。。这个先排除。。 T_T
    loveuqian
        6
    loveuqian  
       2015-10-10 16:05:39 +08:00
    你是在问网页的高度怎么计算吗?
    SniperX
        7
    SniperX  
       2015-10-10 16:10:33 +08:00
    @VichyChen 有个 DTCoreText 的轮子,功能很强大, HTML 标签里,除了表格支持不太好,其他都很不错。 img 便签甚至可以自己写 delegate 方法用 SDWebImage 来加载,所以也可以支持图片异步加载后 Cell 高度重新计算。看你的描述, DTCoreText 应该能满足你的需求,推荐你去跑下 DEMO 看看。
    newtonisaac
        8
    newtonisaac  
       2015-10-10 16:12:24 +08:00   ❤️ 1
    webViewDidFinishLoad 之后 reload 这个 cell
    CDuXZMAPgHp1q9ew
        9
    CDuXZMAPgHp1q9ew  
       2015-10-10 16:27:11 +08:00
    1 不要这么做 如果网页的高度不断变化的话, 意味着要不断 update tableview, cell 再多起来的话, 性能要恶化了
    2 只有一个 cell 里面是 webview 的话, 可以用 kvo observer webview.contentSize, contentSize.height 是高度
    主要这个值可能是随着网页加载不断变化的
    onevcat
        10
    onevcat  
       2015-10-10 16:53:42 +08:00   ❤️ 3
    为什么老想着把 webview 塞到 cell 里这种邪门歪道,而不去花哪怕那么一点点时间去了解一下 Text Kit 呢?
    给几个关键字吧
    1. 用 textview 做, subclass 一个 UITextView 是很好的 start point
    2. 超链接处理 -> characterIndexForPoint:inTextContainer:fractionOfDistanceBetweenInsertionPoints:
    3. 图片 -> NSTextAttachment

    当然你如果很赶工期的话直接用 DTCoreText 应该也不错,不过你就错过了一个尝试使用 Text Kit 的好机会,会比较可惜。
    wingyiu
        11
    wingyiu  
       2015-10-10 16:55:14 +08:00
    CoreText?
    xxppxiaowei
        12
    xxppxiaowei  
       2015-10-10 16:56:54 +08:00
    @onevcat
    @VichyChen 听猫大的。。 猫大 居然逛 v2ex
    xieguobihaha
        13
    xieguobihaha  
       2015-10-10 17:03:59 +08:00
    @onevcat 喵大萌萌哒~
    pljhonglu
        14
    pljhonglu  
       2015-10-10 18:05:40 +08:00
    喵神说得对,如果不赶工期的话建议还是学一下 TextKit ,否则的话建议把整个列表页面做成 web 形式,这样只需要一个 webview 就可以解决了~
    kobe1941
        15
    kobe1941  
       2015-10-10 18:15:32 +08:00
    @onevcat 喵神,什么时候用 Text Kit 什么时候用 CoreText ?感觉这种网页直接用 CoreText 有点大材小用啊
    MountainRain
        16
    MountainRain  
       2015-10-10 18:44:02 +08:00
    最好的方案,用原生哇。。。。哈哈哈哈
    VichyChen
        17
    VichyChen  
    OP
       2015-10-10 20:30:07 +08:00
    @newtonisaac @wujichao
    关键问题是 reload 之后要重新执行 cellForRowAtIndexPath ,然后又要对 UIWebView 加载 html 了吧?加载完又会调用到 webViewDidFinishLoad ,就变成无限循环调用了,这个可以如何处理?

    @SniperX 昨晚试了下 DTCoreText ,好惭愧,下了个 demo 居然不晓得怎么跑起来,一心烦就没仔细研究=。= 用 cocoapod 安装完后图片又显示不出来,不知道正确姿势,得仔细再研究下=。=

    @onevcat 感谢喵神回复=。=
    本来一开始是找轮子的,后来有人说用 UIWebView ,内容显示得好好的结果计算高度原来是坑 T_T
    简单的 text kit 倒是有用过。。。
    主要文本内容是 discuz 论坛的回复,夹杂着引用的 div 标签,论坛表情,还有一些超链接,要把这些标签解析匹配出来貌似也挺麻烦的啊。。难道要用类似 hpple 这种先把数据解析出来?

    @pljhonglu 是一个好办法,但是还是一样要解析 html ,而且做成 web 形式太考验前端功底, web 前端不太懂 T_T
    CDuXZMAPgHp1q9ew
        18
    CDuXZMAPgHp1q9ew  
       2015-10-10 21:32:21 +08:00
    @VichyChen 不 reloadcell, 在 heightForCell 里返回新的高度, 然后 [tableview beginUpdate]; [tableview endUpdate]; 即可

    如果你要做论坛客户端 你可以看下我的项目 hipda 论坛非官方客户端 https://github.com/wujichao/hipda_ios_client_v3/ 里面详细介绍了怎么展示帖子 各种技术的好处坏处, 还有代码, 虽然是我两年前写的, 但是一直有维护
    longaiwp
        19
    longaiwp  
       2015-10-10 21:45:28 +08:00
    @MountainRain 我支持原生,用 html 来代替的都是邪教(大雾
    VichyChen
        20
    VichyChen  
    OP
       2015-10-11 00:37:34 +08:00
    @wujichao 已 star ,有需要再向你请教,谢谢=。=
    newtonisaac
        21
    newtonisaac  
       2015-10-11 13:36:43 +08:00
    @VichyChen
    webViewDidFinishLoad 之后记住这个高度,然后 reload cell
    newtonisaac
        22
    newtonisaac  
       2015-10-11 13:46:31 +08:00
    @wujichao 恕我愚钝, heightforcell 是 delegate 吗?那我们不知道什么时候 call 这个 delegate ,也就没有“然后”了。
    newtonisaac
        23
    newtonisaac  
       2015-10-11 13:49:39 +08:00
    @VichyChen 忘说了一点, webViewDidFinishLoad 之后,如果之前已经记住了这个高度,什么也不做。如果没有记住这个高度,则记住这个高度然后 reload 。
    EggmanQ
        24
    EggmanQ  
       2015-10-13 16:34:49 +08:00
    http://stackoverflow.com/questions/19507639/uiwebview-doesnt-load-completely-height-varies

    CGFloat height = [[_web stringByEvaluatingJavaScriptFromString:@"document.height"] floatValue];

    然后通知 tableview 更新高度。

    ---------------------------------

    我也是 tableviewcell 嵌套 UIWebview ,只能吐槽一下,技术敌不过需求。
    ibcker
        25
    ibcker  
       2015-10-13 23:40:16 +08:00
    ibcker
        26
    ibcker  
       2015-10-13 23:43:03 +08:00
    webview 算高度不用那么费劲,调 sizeToFit 就出来了

    @EggmanQ
    @kenshinhu
    @VichyChen
    VichyChen
        27
    VichyChen  
    OP
       2015-10-14 09:04:51 +08:00
    @EggmanQ @ibcker @wujichao
    最终用了 @pljhonglu 的方案,把数据拼成一个 html 出来,这样就只需要一个 WebView 了。。实在是没办法的办法,能用原生谁想用 web 来写嘛=。=
    ibcker
        28
    ibcker  
       2015-10-14 10:47:31 +08:00
    @VichyChen 这个办法不错
    kenshinhu
        29
    kenshinhu  
       2015-10-14 11:14:42 +08:00
    @ibcker 不行的,这个方案试过,会有高度不一致的情况出现.这个取决于图片的数量及加载时间
    ibcker
        30
    ibcker  
       2015-10-14 11:19:05 +08:00
    @kenshinhu 你确定是在 webview 加载完后调用的?我记得是行的才对,以前就是这么玩的
    ibcker
        31
    ibcker  
       2015-10-14 11:19:45 +08:00
    @kenshinhu 以前好像我是直接取 webview 的 contentsize
    kenshinhu
        32
    kenshinhu  
       2015-10-14 11:29:07 +08:00
    @ibcker 是的,加载这个是指 URL 响应回来之后 HTML 的渲染,但 WEBKIT 这里就会先处理 HTML 之后再处理加载图片的,没有图片情况下这个处理还可以的,有图片的情况下尤其 WEBKIT 并发请求图片埸景下会有使用 sizeTofit 时会有部分内容显示不完整的情况出现
    lionyue
        33
    lionyue  
       2015-10-14 13:16:11 +08:00
    尽量别这么用, cell 多了,性能肯定是个问题。最好用 coretext 或者 textkit 来显示富文本吧
    EggmanQ
        34
    EggmanQ  
       2015-10-14 13:18:16 +08:00
    @kenshinhu 对的~
    WildCat
        35
    WildCat  
       2015-10-16 22:33:02 +08:00
    @onevcat 这两天闲暇的时候一直在思考您说的。
    但是 Text 和 Image 混排如何解决?

    UITextView 没有看到与异步加载 NSTextAttachment 相关的 method 。

    我目前的想法是,
    解析 HTML ,纯文字直接放 UITextView ,遇到 Image 再添加个 UIImage ?
    把 UITextView 和 UIImage 放在一个 View Container 里?
    onevcat
        36
    onevcat  
       2015-10-16 23:35:47 +08:00   ❤️ 1
    @WildCat 确实不容易做异步,如果有异步设置图片的需求的话是比较蛋疼...如果内容不多或者图片尺寸固定的话就怎么玩儿都可以了,否则的话还要再想办法。还是要具体情况具体分析,要是需求的排版再变态一点,比如各种 css 控制,那就很难有一个好的解法。

    其实在 cell 里直接显示可以各种变化的 web 的内容这种事情,本身就不是 cell 的设计意图,所以这样的需求在这里用 cell 来实现其实就是反模式的,自然也不会有特别成熟可以套用的方法。

    琢磨一下把要显示的内容解析并且建立一个好的 model ,然后复用地用 cell 来用比较统一的方式显示,可能会是比较 iOS 的解决方式。要是原来的 web 内容就非常复杂并且一定要原封不动地实现的话,那干脆整个直接上个 webview 会更好吧。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2658 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 07:03 · PVG 15:03 · LAX 23:03 · JFK 02:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.