A very easy solution would be to add a - (UIKeyboardAppearance) keyboardAppearance
method via category extension to UIView
. In this method you could simply return UIKeyboardAppearanceDark
. This works because the method would magically be added to the internal UIWebView
view (UIWebBrowserView
) which becomes the first responder when the user taps into a HTML form input field. The main problem with this approach is that it will affect all UIView-derived views, which may not be desirable.
We can construct a more targeted solution which intercepts the first responder that is responsible for the keyboard and adds a keyboardAppearance
method to it if one doesn't exist. This will degrade gracefully if the internal implementation of UIWebBrowserView
changes in the future to include a keyboardAppearance
selector.
#import <objc/runtime.h>
@protocol TSPingPong <NSObject>
- (void) ts_pong: (id) sender;
@end
@interface NSObject (TSPingPong)
@end
@implementation NSObject (TSPingPong)
- (void) ts_ping: (id) sender
{
if ( [sender respondsToSelector: @selector(ts_pong:)] )
{
[sender performSelector: @selector( ts_pong: ) withObject: self ];
}
}
@end
@implementation TSViewController
{
IBOutlet UIWebView* _webView;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(keyboardWillAppear:)
name: UIKeyboardWillShowNotification
object: nil];
NSString* html = @"<br><br><br><form action=''> "
"First name: <input type='text'><br> "
"Last name: <input type='text'><br>"
"<input type='submit' value='Submit'> "
"</form>";
[_webView loadHTMLString: html
baseURL: nil];
}
- (void) keyboardWillAppear: (NSNotification*) n
{
// the keyboard is about to appear!
// play pingpong with the first responder so we can ensure it has a keyboardAppearance method:
[[UIApplication sharedApplication] sendAction: @selector( ts_ping:) // added via category extension
to: nil // to: the first responder
from: self // "sender"
forEvent: nil];
}
- (void) ts_pong: (id) sender
{
// sender is the first responder. Happens to be undocumented "UIWebBrowserView" in this case.
// if it doesn't have it's own keyboardAppearance method then let's add one:
if ( ![sender respondsToSelector: @selector(keyboardAppearance)] )
{
Method m = class_getInstanceMethod( [self class], @selector( keyboardAppearanceTemplateMethod ) );
IMP imp = method_getImplementation( m );
const char* typeEncoding = method_getTypeEncoding( m );
class_addMethod( [sender class], @selector(keyboardAppearance), imp, typeEncoding );
}
}
- (UIKeyboardAppearance) keyboardAppearanceTemplateMethod
{
return UIKeyboardAppearanceDark;
}
@end
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…