Мне нужно удалить этот бар, как здесь ссылка, но для iOS 7 этот код не работает.
Проблема с клавиатурой iOS 7 UIWebView
Ответ 1
Мы удаляем эту панель с некоторыми обходами Objective C.
У нас есть класс, который имеет один метод:
@interface _SwizzleHelper : NSObject @end
@implementation _SwizzleHelper
-(id)inputAccessoryView
{
return nil;
}
@end
Как только у нас появится веб-представление, с которого мы хотим удалить панель, мы перебираем его подпрограммы просмотра прокрутки и берем класс UIWebDocumentView
. Затем мы динамически делаем суперкласс класса, который мы создали выше, как класс subview (UIWebDocumentView - но мы не можем сказать, что это заранее, потому что это частный API), и замените класс subview на наш класс.
#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!)
}
}
Ответ 2
Я создал cocoapod на основе этого сообщения в блоге от @bjhomer.
Вы можете заменить inputaccessoryview, а не просто скрыть его. Надеюсь, это поможет людям с той же проблемой.
https://github.com/lauracpierre/FA_InputAccessoryViewWebView
Вы можете найти страницу cocoapod прямо здесь.
Ответ 3
Я столкнулся с этим замечательным решением, но мне также нужно было вернуть 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".
Ответ 4
Я создал суть, чтобы выполнить это: https://gist.github.com/kgaidis/5f9a8c7063b687cc3946fad6379c1a66
Это категория UIWebView
, где все, что вы делаете, это изменение свойства customInputAccessoryView
:
@interface UIWebView (CustomInputAccessoryView)
@property (strong, nonatomic) UIView *customInputAccessoryView;
@end
Вы можете установить его на nil
, чтобы удалить его, или вы можете установить для него новый вид, чтобы изменить его.
Имейте в виду, что это также использует частный API, поэтому используйте его на свой страх и риск, но, похоже, многие приложения делают подобные вещи, тем не менее.