Problème de keyboard iOS 7 UIWebView

Je dois enlever cette barre comme lien ici mais pour iOS 7 ce code ne fonctionne pas.

Nous supprimons cette barre avec une supercherie d'exécution Objective C.

Nous avons une class qui a une méthode:

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

Une fois que nous avons une vue web dont nous voulons retirer la barre, nous parcourons les sous-vues de la vue défilement et prenons la class UIWebDocumentView . Nous transformons ensuite dynamicment la super-class de la class que nous avons créée ci-dessus pour qu'elle soit la class de la sous-vue (UIWebDocumentView – mais nous ne pouvons pas dire cela d'avance car c'est une API privée), et remplacez la class subview par notre class.

 #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; NSSsortingng* name = [NSSsortingng ssortingngWithFormat:@"%@_SwizzleHelper", subview.class.superclass]; Class newClass = NSClassFromSsortingng(name); if(newClass == nil) { newClass = objc_allocateClassPair(subview.class, [name cSsortingngUsingEncoding:NSASCIISsortingngEncoding], 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); } 

L'équivalent de ce qui précède dans 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 NSSsortingngFromClass(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? = NSClassFromSsortingng(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!) } } 

J'ai fait un cocoapod basé sur ce blog de @bjhomer.

Vous pouvez replace la vue inputaccessory et ne pas la masquer. J'espère que cela aidera les gens avec le même problème.

https://github.com/lauracpierre/FA_InputAccessoryViewWebView

Vous pouvez find la page de cocoapod ici .

Je suis tombé sur cette solution géniale, mais je devais aussi récupérer l'inputAccessoryView. J'ai ajouté cette méthode:

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

Il semble fonctionner comme prévu sans effets secondaires, mais je ne peux pas me débarrasser du sentiment que mon pantalon est en feu.

Si vous voulez que la solution de Leo Natan fonctionne avec WKWebView au lieu de UIWebView, changez simplement le préfixe "UIWeb" en "WKContent".

J'ai créé une substance pour accomplir ceci: https://gist.github.com/kgaidis/5f9a8c7063b687cc3946fad6379c1a66

C'est une catégorie UIWebView où tout ce que vous faites est de changer la propriété customInputAccessoryView :

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

Vous pouvez le définir sur nil pour le supprimer ou vous pouvez définir une nouvelle vue pour le changer.

Gardez à l'esprit que cela utilise également des API privées, utilisez-les donc à vos risques et périls, mais il semble que beaucoup d'applications font des choses similaires.