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

[Mac OS] 如何为 WebView 内含的 NSScrollView 指定一个自定义的类呢?

  •  
  •   chenluois · 2012-09-10 15:17:58 +08:00 · 5993 次点击
    这是一个创建于 4451 天前的主题,其中的信息可能已经有所发展或是发生改变。
    subclass 了一个 NSScrollView,做了一些自定义的修改,命名为 CLScrollView。
    现在想把 WebView 内含的 NSScrollView 的类指定为 CLScrollView,请问要如何做到呢?

    由于 WebView 比较特殊,并不能直接在 IB 里为其包含的 view 指定类。其包含的 NSScrollView 也只能通过:
    (假设这个 WebView 名为 myWebView)

    [[[[myWebView mainFrame] frameView] documentView] enclosingScrollView]

    来访问。

    有没有办法能把其下的 enclosingScrollView 的类设为 CLScrollView 呢?
    22 条回复    1970-01-01 08:00:00 +08:00
    Veelian
        1
    Veelian  
       2012-09-10 15:54:59 +08:00   ❤️ 1
    **WebView 内含的 NSScrollView** 不是这样的,WebView是继承自NSScrollView,而不是内含的NSScrollView,你可以写个WebView继承CLScrollView,实现NSWebViewDelegate方法
    lldong
        2
    lldong  
       2012-09-10 16:26:35 +08:00   ❤️ 1
    或许可以用这个运行时API
    Class class_setSuperclass(Class cls, Class newSuper)
    tab
        3
    tab  
       2012-09-10 16:43:38 +08:00   ❤️ 1
    没做过Mac开发,@Veelian 说的在iOS SDK下是正确的。但总的思路应该是继承WebView重写一个吧?
    lldong
        4
    lldong  
       2012-09-10 17:07:45 +08:00
    @Veelian 不过WebView不是继承自NSSCrollView吧,继承自NSView。 scroll view应该是在WebFrameView里面。
    chenluois
        5
    chenluois  
    OP
       2012-09-10 17:30:59 +08:00
    @Veelian "写个WebView继承CLScrollView" - 这个让我头大了,可以给点儿提示吗?
    jjgod
        6
    jjgod  
       2012-09-10 18:32:14 +08:00   ❤️ 1
    ghawkgu
        7
    ghawkgu  
       2012-09-10 18:48:30 +08:00   ❤️ 1
    关键词:isa swizzling
    自己去搜吧〜
    lldong
        8
    lldong  
       2012-09-10 19:45:42 +08:00
    WebView里面的那个scrollview是个NSScrollView的子类对象,如果要体换的话应该要用WebDynamicScrollBarsView的子类对象才对。
    chenluois
        9
    chenluois  
    OP
       2012-09-11 15:55:41 +08:00
    先感谢各位的回答!昨天按各位提供的思路折腾了一晚上,虽然没有成功,但至少可以慢慢试了,今天继续学习。

    @Veelian 提供的思路我卡在 "写个WebView继承CLScrollView" 上了,WebView 继承自 NSView : NSResponder : NSObject,想了半天也没弄明白怎样才能 subclass 一个 WebView,并且让它继承 CLScrollView。Subclass 一个 WebView,它不只能是继承 WebView 么?

    @tab 关键问题就是,subclass 了一个 WebView 后,要重写哪个函数才能把 WebView 里面的 scrollView 的类替换为 CLScrollView 呢?

    @lldong @jjgod @ghawkgu 三位提供的思路,如果我没有理解错,你们说的是同一个东西,在运行时替换 NSScrollView 里面的某个方法。对运行时不了解,昨天看了几页 @lldong 分享的幻灯片,今天继续看。
    http://lldong.github.com/blog/2012/03/05/objective-c-runtime/
    virushuo
        10
    virushuo  
       2012-09-11 16:07:38 +08:00
    @lldong @jjgod 我一直想知道,runtime替换会导致不能上架吗?如果用runtime替换掉了一个苹果没公开的类的某个方法,这样会等同于私有api吗?(理论上虽然是一样的)。但runtime的操作很难察觉,那么用这办法调用私有api不是就很难被审核发现了吗? 你们有人试过吗?
    lldong
        11
    lldong  
       2012-09-11 16:09:02 +08:00   ❤️ 1
    @chenluois 可以直接看WebKit的源代码,这样就知道该往哪里下手了
    https://svn.webkit.org/repository/webkit/trunk/Source/WebKit/mac/WebView/
    jjgod
        12
    jjgod  
       2012-09-11 16:42:11 +08:00   ❤️ 1
    @virushuo: 调用私有 API 等于是用 Apple 的实现,运行时替换方法是用你自己的实现,这两者是有区别的吧。
    virushuo
        13
    virushuo  
       2012-09-11 16:45:25 +08:00
    @jjgod 如果我实现了一个苹果没公开的类中的一个方法的实现呢? 苹果不让用私有api的理由不就是他们随时会改动这些,但我现在问题是找到了一个他没实现的方法。虽然实际上我这么做没危险,因为就算苹果实现了也不会干扰我。
    lldong
        14
    lldong  
       2012-09-11 16:49:32 +08:00   ❤️ 1
    @virushuo 试过method swizzling替换NavigationBar的drawRect方法,并不影响上架,但是也听过替换非私有API被查出来的,也听过因为方法名和某私有API一样被reject的,所以蛮好奇苹果的审查的方法。我觉得如果要保险的话各种方法名也要在运行时拼凑出来,甚至不要过objc_msgSend()去调用。
    chenluois
        15
    chenluois  
    OP
       2012-09-11 19:37:53 +08:00   ❤️ 1
    @lldong 谢谢!我去看看
    nowa
        16
    nowa  
       2012-09-20 23:42:15 +08:00
    @chenluois 我也遇到了同样的问题,感觉如果改动比较大的话用method swizzling太繁琐了。WebDynamicScrollBarsView没有公开,也无法继承。

    不知最后采取了怎样的方案?
    chenluois
        17
    chenluois  
    OP
       2012-09-21 06:02:47 +08:00
    @nowa 最后,放弃了…
    nowa
        18
    nowa  
       2012-09-21 07:24:49 +08:00
    @chenluois 汗。我先一个个method exchange吧。。。
    clowwindy
        19
    clowwindy  
       2012-09-21 09:43:15 +08:00
    试过 method swizzling,替换过 NSURLRequest 的方法,对 WebView 做一些 header 过滤。不影响上架。
    jerry
        20
    jerry  
       2012-09-21 09:50:15 +08:00
    替换的目的是什么呢?如果是换滚动条,隐藏掉原来的,旁边再画一个
    chenluois
        21
    chenluois  
    OP
       2012-09-21 11:14:36 +08:00
    @jerry 不是换滚动条,而是换滚动条的父级 scrollView。换滚动条就很容易,subclass 一个 NSScroller,启动时初始化一个这个自定义的滚动条,再用 [[[[myWebView mainFrame] frameView] documentView] enclosingScrollView] 的 setVerticalScroller 和 setHorizontalScroller 方法直接设置就行了。
    jorakura
        22
    jorakura  
       2012-09-21 23:02:09 +08:00
    @chenluois 在 iOS 上,也碰到类似问题。考虑换掉 UIWebView 里的 UIScrollView。觉得非常麻烦。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2749 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:27 · PVG 19:27 · LAX 03:27 · JFK 06:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.