I have to remove this bar as here link but for iOS 7 this code does not work.
4 Answers
We remove this bar with some Objective C runtime trickery.
We have a class which has one method:
@interface _SwizzleHelper : NSObject @end
@implementation _SwizzleHelper
-(id)inputAccessoryView
{
return nil;
}
@end
Once we have a web view which we want to remove the bar from, we iterate its scroll view's subviews and take the UIWebDocumentView
class. We then dynamically make the superclass of the class we created above to be the subview's class (UIWebDocumentView - but we cannot say that upfront because this is private API), and replace the subview's class to our 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;
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);
}
The equivalent of the above in 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!)
}
}
-
how is this solution for the App Store approval process? have you had an app approved that has this code? – Larry Sep 27 '13 at 04:29
-
3Yes, we have our app with a code similar to this and it has been approved. – Léo Natan Sep 27 '13 at 04:35
-
how is `subview` defined? i used `NSObject *subview = [[webView scrollView] subviews][0];` (which is actually a `UIWebBrowserView` object, and the only subview in scrollView's subviews) and objc is crashing with: `[UIWebDocumentView_SwizzleHelper autoFillDelegate]: unrecognized selector sent to instance 0xa8cba00`. – Larry Sep 27 '13 at 05:49
-
It seems your `UIWebDocumentView_SwizzleHelper` class is not a subclass of `UIWebBrowserView`. Did you pass the correct superclass to `objc_allocateClassPair`? – Léo Natan Sep 27 '13 at 05:52
-
To define `subview`, I did something a little better than going straight for the jugular - I looked for a subview under the scroll view, whose class name starts with `UIWeb`. – Léo Natan Sep 27 '13 at 06:05
-
got it! the allocateClassPair line should be: `newClass = objc_allocateClassPair(subview.class, [name cStringUsingEncoding:NSASCIIStringEncoding], 0);`. specifically `subview.class` instead of `subview.class.subclass`. so the method definition and first line i used is: `- (void) removeInputAccessoryViewFromUIWebView:(UIWebView*)webView { NSObject *subview = [[webView scrollView] subviews][0]; ` thanks! – Larry Sep 27 '13 at 06:42
-
Doh! I'll fix, thansk – Léo Natan Sep 27 '13 at 06:43
-
When can I put __removeInputAccessoryView method. I put it in ViewController have UIWebView and there're some error: conflicting type for objc_allocateClassPair – LE SANG Sep 27 '13 at 07:46
-
2put that in your `UIWebView` subclass. Also you'll need to `#import "objc/runtime.h"` at the top of your file – Larry Sep 27 '13 at 08:10
-
Note: just used this, and it worked quite well. A note for the call tree challenged (like myself): I ended up calling `[self __removeAccessoryView]` from inside the `- (id)initWithCoder:(NSCoder *)aDecoder` method (which worked since my UIWebView subclass is instantiated from a storyboard). – Femi Feb 28 '14 at 22:24
-
Do you not have to import `_SwizzleHelper` ? – Maximus S Sep 08 '15 at 05:46
-
@LeoNatan How does `Method method = class_getInstanceMethod` have reference to `_SwizzleHelper`? Also, for me `subview` is always nil. The subviews of scrollView are `WKContentView`, `UIView`. Do you have an idea why? – Maximus S Sep 08 '15 at 06:02
-
Read the answer. It's part of the solution. – Léo Natan Sep 08 '15 at 06:02
-
Hm.. I am still confused. So do you mean where `_removeInput..` is defined, you don't have to import `_SwizzleHelper.h`? Also, my second question was `view.class description` never has UIWeb. The only available descriptions are `WKContentView` and `UIView`. – Maximus S Sep 08 '15 at 06:05
-
You can define in same file. I won't hand hold you here, the solution is very simple. If you do not understand it, I suggest staying away from swizzling. – Léo Natan Sep 08 '15 at 06:07
-
Thank you so much @LeoNatan. One questions more still this code is approved for app submission? – iDhaval Sep 09 '15 at 08:59
-
2@iDhaval Our app has been approved with it for years. – Léo Natan Sep 09 '15 at 08:59
-
1@LeoNatan I added a swift 3 version - feel free to roll back if you don't want it there – CupawnTae Nov 16 '16 at 13:53
-
@CupawnTae Thanks! I suggest a further edit, removing Swift 2.0. – Léo Natan Nov 16 '16 at 15:06
I've made a cocoapod based on this blog post from @bjhomer.
You can replace the inputaccessoryview and not just hide it. I hope this will help people with the same issue.
https://github.com/lauracpierre/FA_InputAccessoryViewWebView
You can find the cocoapod page right here.

- 1,053
- 7
- 17
I've came across this awesome solution, but I needed to get the inputAccessoryView back as well. I added this method:
- (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);
}
It does seem to work as intended with no side effects, but I can't get rid of the feeling that my pants are on fire.
If you want Leo Natan's solution to work with WKWebView instead of UIWebView just change prefix from "UIWeb" to "WKContent".

- 3,591
- 1
- 24
- 38
-
hi man thanks for answer but it's old question ) but I will come back to that task I will check it – Matrosov Oleksandr May 12 '15 at 17:56
I created a gist to accomplish this: https://gist.github.com/kgaidis/5f9a8c7063b687cc3946fad6379c1a66
It's a UIWebView
category where all you do is change the customInputAccessoryView
property:
@interface UIWebView (CustomInputAccessoryView)
@property (strong, nonatomic) UIView *customInputAccessoryView;
@end
You can either set it to nil
to remove it or you can set a new view on it to change it.
Keep in mind, this also uses private API's, so use at your own risk, but it seems like a lot of apps do similar things nonetheless.

- 14,259
- 4
- 79
- 93