2013-09-26 57 views
13

我必须删除此栏,如link,但对于iOS 7,此代码不起作用。iOS 7 UIWebView键盘问题

+0

我为这个惊人的高科技答案增加了一个小小的赏金,感谢大家给你,狮子座! – Fattie

+1

@JoeBlow感谢乔!刚在这里注意到你的评论。 –

回答

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); 
} 

以上的雨燕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!) 
    } 
} 
+0

这个App Store审批流程的解决方案如何?你有一个应用程序批准了这个代码? – Larry

+3

是的,我们的应用程序的代码与此类似,并且已获得批准。 –

+0

'subview'是如何定义的?我使用了'NSObject * subview = [[webView scrollView] subviews] [0];'(这实际上是一个'UIWebBrowserView'对象,并且是scrollView的子视图中的唯一子视图)和objc崩溃:[UIWebDocumentView_SwizzleHelper autoFillDelegate]:无法识别选择器发送到实例0xa8cba00'。 – Larry

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”即可。

+0

嗨男人谢谢你的回答,但这是个老问题),但我会回到那个任务,我会检查它 –

0

我创建了一个要点来实现: https://gist.github.com/kgaidis/5f9a8c7063b687cc3946fad6379c1a66

这是一个UIWebView类别,所有你要做的就是改变customInputAccessoryView属性:

@interface UIWebView (CustomInputAccessoryView) 

@property (strong, nonatomic) UIView *customInputAccessoryView; 

@end 

您可以将其设置为nil将其删除或你可以设置一个新的视图来改变它。

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