开发者

How to enable "select all" in UIWebView in an IPhone App?

I am writing an IPhone application which embeds a UIWebView. There are various safari like features like navigation, etc. One of the tasks I am looking for is to present a "select all" option when the user selects on a piece of text on the web view. Currently, I only see a "copy" option. Is there an easy way to enable the "select all" menu item? I have ofcourse tried adding a menu item to the shared menu controller but that doesn't necessarily implement the original safari "select all" functionality. Any help and pointers will be very usefu开发者_运维百科l.

Thanks in advance.


The short answer is no, this is not possible.

You could do this by subclassing UIWebView and overriding (without adding anythings to the menu controller yourself):

-(BOOL) canPerformAction:(SEL)action withSender:(id)sender 

And checking if the selector is selectAll:

Like this:

-(BOOL) canPerformAction:(SEL)action withSender:(id)sender {
    if (action == @selector(selectAll:)) {
        return YES;
    } else {
        return [super canPerformAction:action withSender:sender];
    }
}

This will show the Select All option on the Hold Menu. However this isn't default behaviour of a webView, and while the app won't crash when you press Select All, pressing it will just do nothing.

You can't even create a selectAll method, and then select everything in webview, because the javascript method .select() doesn't work on Mobile Safari/UIWebView.


You can implement selectAll behavior for non-editable webView (equivalent to behavior at Apple's Mail.app) at runtime using the following category for UIWebView.

The main idea is to use the hint that UIWebBrowserView being the subview of UIWebView is the subclass of UIWebDocumentView which conforms to UITextInputPrivate protocol which is equivalent to public UITextInput protocol

//  UIWebView+SelectAll.h
//  Created by Alexey Matveev on 28.03.15.
//  Copyright (c) 2015 Alexey Matveev. All rights reserved.

@interface UIWebView (SelectAll)
+ (void)setEnableSelectAll:(BOOL)enabled;
@end


#import "UIWebView+SelectAll.h"
#import <objc/runtime.h>

/*
 UIWebDocumentView is the superclass for UIWebBrowserView.
 UIWebDocumentView conforms UITextInputPrivate protocol which is identival to UITextInput
*/

static IMP canPerformActionWithSenderImp;

@implementation UIWebView (SelectAll)

@dynamic enableSelectAll;

- (BOOL)customCanPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(selectAll:)) {
        return ! self.isSelectedAll;
    }
    else {
        BOOL(*imp)(id, SEL, SEL, id) = (BOOL(*)(id, SEL, SEL, id))canPerformActionWithSenderImp;
        return imp(self, @selector(canPerformAction:withSender:),  action, sender);
    }
}

- (void)selectAll:(id)sender
{
    [self.browserView selectAll:sender];
}

- (UIView<UITextInput> *)browserView
{
    UIView *browserView;
    for (UIView *subview in self.scrollView.subviews) {
        if ([subview isKindOfClass:NSClassFromString(@"UIWebBrowserView")]) {
            browserView = subview;
            break;
        }
    }

    return (UIView<UITextInput> *)browserView;
}

- (BOOL)isSelectedAll
{
    UITextRange *currentRange = self.browserView.selectedTextRange;
    if ([self.browserView comparePosition:currentRange.start toPosition:self.browserView.beginningOfDocument] == NSOrderedSame) {
        if ([self.browserView comparePosition:currentRange.end toPosition:self.browserView.endOfDocument] == NSOrderedSame) {
            return YES;
        }
    }
    return NO;
}

+ (void)setEnableSelectAll:(BOOL)enabled
{
    SEL canPerformActionSelector = @selector(canPerformAction:withSender:);

    if (!canPerformActionWithSenderImp) {
        canPerformActionWithSenderImp = [self instanceMethodForSelector:canPerformActionSelector];
    }

    IMP newCanPerformActionWithSenderImp = enabled ? [self instanceMethodForSelector:@selector(customCanPerformAction:withSender:)] : canPerformActionWithSenderImp;

    Method canPerformActionMethod = class_getInstanceMethod([self class], canPerformActionSelector);
    class_replaceMethod([self class], canPerformActionSelector, newCanPerformActionWithSenderImp, method_getTypeEncoding(canPerformActionMethod));
}

@end

Of course, you can use global method swizzling for

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender;

in the standard way but it will affect all webViews in your project irreversably.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜