【问题标题】:iOS 7 UIWebView keyboard issueiOS 7 UIWebView 键盘问题
【发布时间】:2013-10-02 17:16:37
【问题描述】:

我必须像这里 link 一样删除此栏,但对于 iOS 7,此代码不起作用。

【问题讨论】:

    标签: ios ios7 uiwebview


    【解决方案1】:

    我们使用一些 Objective C 运行时技巧来移除这个栏。

    我们有一个类有一个方法:

    @interface _SwizzleHelper : NSObject @end
    
    @implementation _SwizzleHelper
    
        -(id)inputAccessoryView
        {
            return nil;
        }
    
    @end
    

    一旦我们有了一个想要从中删除栏的 web 视图,我们就迭代它的滚动视图的子视图并采用 UIWebDocumentView 类。然后,我们动态地将上面创建的类的超类设为子视图的类(UIWebDocumentView - 但我们不能提前说,因为这是私有 API),并将子视图的类替换为我们的类。

    #import "objc/runtime.h"    
    
    -(void)__removeInputAccessoryView
    {
        UIView* subview;
    
        for (UIView* view in self.scrollView.subviews) {
            if([[view.class description] hasPrefix:@"UIWeb"])
                subview = view;
        }
    
        if(subview == nil) return;
    
        NSString* name = [NSString stringWithFormat:@"%@_SwizzleHelper", subview.class.superclass];
        Class newClass = NSClassFromString(name);
    
        if(newClass == nil)
        {
            newClass = objc_allocateClassPair(subview.class, [name cStringUsingEncoding:NSASCIIStringEncoding], 0);
            if(!newClass) return;
    
            Method method = class_getInstanceMethod([_SwizzleHelper class], @selector(inputAccessoryView));
            class_addMethod(newClass, @selector(inputAccessoryView), method_getImplementation(method), method_getTypeEncoding(method));
    
            objc_registerClassPair(newClass);
        }
    
        object_setClass(subview, newClass);
    }
    

    Swift 3.0 中的等价物:

    import UIKit
    import ObjectiveC
    
    var swizzledClassMapping = [AnyClass]()
    
    extension UIWebView {
        func noInputAccessoryView() -> UIView? {
            return nil
        }
    
        public func removeInputAccessoryView() {
            var subview: AnyObject?
    
            for (_, view) in scrollView.subviews.enumerated() {
                if NSStringFromClass(type(of: view)).hasPrefix("UIWeb") {
                    subview = view
                }
            }
    
            guard subview != nil else {
                return
            }
    
            //Guard in case this method is called twice on the same webview.
            guard !(swizzledClassMapping as NSArray).contains(type(of: subview!)) else {
                return;
            }
    
            let className = "\type(of: subview!)_SwizzleHelper"
            var newClass : AnyClass? = NSClassFromString(className)
    
            if newClass == nil {
                newClass = objc_allocateClassPair(type(of: subview!), className, 0)
    
                guard newClass != nil else {
                    return;
                }
    
                let method = class_getInstanceMethod(type(of: self), #selector(UIWebView.noInputAccessoryView))
                class_addMethod(newClass!, #selector(getter: UIResponder.inputAccessoryView), method_getImplementation(method), method_getTypeEncoding(method))
    
                objc_registerClassPair(newClass!)
    
                swizzledClassMapping += [newClass!]
            }
    
            object_setClass(subview!, newClass!)
        }
    }
    

    【讨论】:

    • App Store 审批流程的解决方案如何?您是否已批准具有此代码的应用程序?
    • 是的,我们的应用程序的代码与此类似,并且已获得批准。
    • 把它放在你的 UIWebView 子类中。此外,您还需要在文件顶部 #import "objc/runtime.h"
    • @iDhaval 我们的应用已经获得批准多年。
    • @LeoNatan 我添加了一个 swift 3 版本 - 如果你不想要它,可以随意回滚
    【解决方案2】:

    我遇到了这个很棒的解决方案,但我还需要找回 inputAccessoryView。我添加了这个方法:

    - (void)__addInputAccessoryView {
    
        UIView* subview;
    
        for (UIView* view in self.scrollView.subviews) {
    
            if([[view.class description] hasSuffix:@"SwizzleHelper"])
                subview = view;
        }
    
        if(subview == nil) return;
    
        Class newClass = subview.superclass;
    
        object_setClass(subview, newClass);
    }
    

    它似乎确实按预期工作,没有副作用,但我无法摆脱裤子着火的感觉。

    如果您希望 Leo Natan 的解决方案使用 WKWebView 而不是 UIWebView,只需将前缀从“UIWeb”更改为“WKContent”。

    【讨论】:

    • 嗨,谢谢你的回答,但这是个老问题)但我会回到那个任务我会检查它
    【解决方案3】:

    我已经根据来自@bjhomer 的blog post 制作了一个cocoapod。

    您可以替换 inputaccessoryview 而不仅仅是隐藏它。我希望这会帮助有同样问题的人。

    https://github.com/lauracpierre/FA_InputAccessoryViewWebView

    你可以找到cocoapod页面right here

    【讨论】:

      【解决方案4】:

      我创建了一个要点来完成此操作: https://gist.github.com/kgaidis/5f9a8c7063b687cc3946fad6379c1a66

      这是一个UIWebView 类别,您只需更改customInputAccessoryView 属性:

      @interface UIWebView (CustomInputAccessoryView)
      
      @property (strong, nonatomic) UIView *customInputAccessoryView;
      
      @end
      

      您可以将其设置为 nil 以将其删除,也可以设置一个新视图以对其进行更改。

      请记住,这也使用私有 API,因此使用风险自负,但似乎很多应用都在做类似的事情。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多