iOS 7 UIWebView 键盘问题

13

我必须移除这个栏位,就像链接中所示,但对于iOS 7来说,这段代码无效。

4个回答

25
我们通过一些 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!)
    }
}

3
是的,我们的应用程序有类似于这样的代码,并且已经通过审核。 - Léo Natan
subview 是如何定义的?我使用了 NSObject *subview = [[webView scrollView] subviews][0];(实际上是一个 UIWebBrowserView 对象,也是 scrollView 的唯一子视图),但是 Objective-C 在运行时崩溃并显示:[UIWebDocumentView_SwizzleHelper autoFillDelegate]: unrecognized selector sent to instance 0xa8cba00 - Larry
2
把它放在你的 UIWebView 子类中。同时你需要在文件顶部 #import "objc/runtime.h". - Larry
2
@iDhaval 我们的应用程序已经使用它多年了。 - Léo Natan
1
@LeoNatan 我添加了一个 Swift 3 版本 - 如果您不想要它,请随意回滚。 - CupawnTae
显示剩余14条评论

1

0

我遇到了这个很棒的解决方案,但是我也需要获取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”即可。


嗨,伙计,谢谢回答,不过这是一个旧问题了)但我会回到那个任务上的,我会检查它。 - Matrosov Oleksandr

0
我创建了一个Gist来完成这个任务: https://gist.github.com/kgaidis/5f9a8c7063b687cc3946fad6379c1a66 这是一个UIWebView类别,你所要做的就是改变customInputAccessoryView属性:
@interface UIWebView (CustomInputAccessoryView)

@property (strong, nonatomic) UIView *customInputAccessoryView;

@end

您可以将其设置为 nil 以删除它,也可以在其上设置一个新视图来更改它。

请注意,这也使用了私有API,因此请自行承担风险,但似乎很多应用程序仍然会做类似的事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接