How To Mark Or Get The Highlighted String Inside UIWebView

本文提供了一个iOS应用教程,详细解释了如何使用JavaScript在UIWebView中高亮选中文本并获取高亮内容。通过下载配套的JavaScript和HTML文件,开发者可以轻松实现对UIWebView中选中文本的高亮显示与提取。

Before we go over with this tutorial, I would like to thank everyone for reading my posts, for asking questions and for giving suggestions. Because of that, I will continue writing tutorials that might help other developers get rid of headaches and frustrations.

This tutorial is a follow up tutorial from my previous post. Someone find it simple yet helpful and ohers have questions if it is possible to mark/stylize and get those strings inside UIWebView that are selected or highlighted. So I created this tutorial to support that question.

Let's get started!

Since we are still manipulating UIWebView, we need to gain access to its contents. In order to do this, we have to use Javascripts.

With Javascript, we can access UIWebViews contents like normal browsers do.

In this tutorial, we will use UIWebViews method (stringByEvaluatingJavaScriptFromString) to access javascript files and execute its functions.

Download the javascript and html file here. After downloading the zip file, extract the file and you should have two files (HighlightedString.js and index.html).

What are these files?

The html file (index.html) handles the UIWebView content.

That javascript file (HighlightedString.js) handles all the job of getting or marking highlighted strings inside UIWebView.

Inside that javascript file, we have variable to store the selected text.

var selectedText = "";

We also have a function to get the highlighted strings.

function getHighlightedString() {
    var text        = window.getSelection();
    selectedText    = text.anchorNode.textContent.substr(text.anchorOffset, text.focusOffset - text.anchorOffset);

}

This function above will access the window and perform the getSelection() operation to access of UIWebViews contents.

Then, we parse UIWebView's contents using the anchorOffset and focusOffset.

  • anchorOffset() - returns the first index position of the highlighted strings. For example if my UIWebView has content "My name is Zaldy", and you highlighted Zaldy. You're anchorOffset is 11 which is the character "Z". Because it counts all characters from the beginning of the content as index 0.
  • focusOffset() - returns the last index position of the highlighted strings. With the latter example, our focusOffset is 15 which refers to the last character of the highlighted string,  the character "y".

Now, in order to acquire the highlighted strings, we parse the UIWebView contents and scan the content using the operation text.anchorNode.textContent.substr(int startingIndex, int length). This operation takes two paramters, the first one is the starting position of the character to parse, the second one is the length of the string to end the parsing.

So if our UIWebView has content "My name is Zaldy" and we have anchorOffset() = 11 with focusOffset() = 15. Our string length would be 15 - 11 = 4. Remember that 4 means we have 0,1,2,3,4 characters, a total of 5characters. The parser now scan's the content from index 11 with string length 4, so it will end scanning to character "y".

Hope that sounds clear to you guys.

Another function is to stylize/mark any highlighted string inside UIWebView content.

function stylizeHighlightedString() {
    
    var range               = window.getSelection().getRangeAt(0);
    var selectionContents   = range.extractContents();
    var span                = document.createElement("span");
    
    span.appendChild(selectionContents);
    
    span.setAttribute("class","uiWebviewHighlight");
    span.style.backgroundColor  = "black";
    span.style.color            = "white";
    
    range.insertNode(span);
}

That function above captures the range of our selection and put a <span> element before the first character of the highlighted string and put the </span> after the last character of the highlighted string. After that, we add a class attribute named "uiWebviewHighlight" with defined style backgroundColor to black and font color style to white. Then insert the changes to the highlighted strings and update the UIWebView content.

Note: You can always change the colors of marker's background and text.

We also have a function to remove all highlights. This function is also used on my previous post to mark/highlight a searched string.

// helper function, recursively removes the highlights in elements and their childs
function uiWebview_RemoveAllHighlightsForElement(element) {
    if (element) {
        if (element.nodeType == 1) {
            if (element.getAttribute("class") == "uiWebviewHighlight") {
                var text = element.removeChild(element.firstChild);
                element.parentNode.insertBefore(text,element);
                element.parentNode.removeChild(element);
                return true;
            } else {
                var normalize = false;
                for (var i=element.childNodes.length-1; i>=0; i--) {
                    if (uiWebview_RemoveAllHighlightsForElement(element.childNodes[i])) {
                        normalize = true;
                    }
                }
                if (normalize) {
                    element.normalize();
                }
            }
        }
    }
    return false;
}

That function above recursively removes all element occurence that has class attribute named "uiWebviewHighlight". This will remove all marks/highlights defined to that class attribute.

.Let's do this!

This tutorial project is using an iOS5 SDK with Storyboards and ARC.

1. Create an XCode project named (WebViewHighlight) as a single view applciation. Check the Use Of Storyboard and the Use of Automatic Reference Counting.

2. Add the javascript and html file to your XCode.

3. Note: once you have added a javascript file to your XCode. XCode will displays a warning:

warning: no rule to process file '$(PROJECT_DIR)/.../HighlightedString.js' of type sourcecode.javascript for architecture i386

This happens because it compiles a javascript file and will find it weird. So that our XCode will not compile our javascript file, go to your TARGET and select the BUILD PHASES tab and expand the COMPILE SOURCES then  remove the HighlightedString.js by selecting it and click the minus (-) button.

Add HighlightedString.js to the COPY BUNDLE RESOURCES by clicking the plus (+) button and select the jabascript fileSee below screen-shot.

Remove js file from Compile Sources.

Add js file to the Copy Bundle Resources.

This will add the javascript file to your project's bundle resources without compiling it.

4. Update your ViewController header file (ViewController.h) with the code below.

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property(nonatomic, retain) IBOutlet UIWebView *webView;
- (IBAction)removeAllHighlights;
- (IBAction)markHighlightedString:(id)sender;
- (IBAction)getHighlightedString:(id)sender;
@end

We have an IBOutlet UIWebView variable and functions to mark, get and remove highlighted strings.

5. Update your @implementation file (ViewController.m).

Add these below @implementation.

{
    UIWebView *_webView;
}

@synthesize webView = _webView;

Add this method.

- (IBAction)markHighlightedString:(id)sender {
    
    // The JS File   
    NSString *filePath  = [[NSBundle mainBundle] pathForResource:@"HighlightedString" ofType:@"js" inDirectory:@""];
    NSData *fileData    = [NSData dataWithContentsOfFile:filePath];
    NSString *jsString  = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];
    [_webView stringByEvaluatingJavaScriptFromString:jsString];
    
    // The JS Function
    NSString *startSearch   = [NSString stringWithFormat:@"stylizeHighlightedString()"];
    [_webView stringByEvaluatingJavaScriptFromString:startSearch];
    
}

Above code will call the javascript file and execute the function to mark any highlighted strings inside your webview content.

Add this method.

- (IBAction)getHighlightedString:(id)sender {
    
    // The JS File   
    NSString *filePath  = [[NSBundle mainBundle] pathForResource:@"HighlightedString" ofType:@"js" inDirectory:@""];
    NSData *fileData    = [NSData dataWithContentsOfFile:filePath];
    NSString *jsString  = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];
    [_webView stringByEvaluatingJavaScriptFromString:jsString];
    
    // The JS Function
    NSString *startSearch   = [NSString stringWithFormat:@"getHighlightedString()"];
    [_webView stringByEvaluatingJavaScriptFromString:startSearch];
    
    NSString *selectedText   = [NSString stringWithFormat:@"selectedText"];
    NSString * highlightedString = [_webView stringByEvaluatingJavaScriptFromString:selectedText];
    
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Highlighted String" 
                                                    message:highlightedString
                                                   delegate:nil 
                                          cancelButtonTitle:@"Oh Yeah" 
                                          otherButtonTitles:nil];
    [alert show];
    //[alert release]; // not required anymore because of ARC
}

Above code will call the javascript file and execute the function to get any highlighted strings inside webview content and push an alert view.

Add this method.

- (IBAction)removeAllHighlights
{
    // calls the javascript function to remove html highlights
    [_webView stringByEvaluatingJavaScriptFromString:@"uiWebview_RemoveAllHighlights()"];
}

Above code will call the javascript function to remove string highlights.

Update your - (void)viewDidUnload with this code:

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    _webView = nil;
}

Update your - (void)viewDidLoad with this code:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // Load index.html to our webview
    NSString *urlAddress        = [[NSBundle mainBundle] pathForResource:@"index" 
                                                                  ofType:@"html"]; //you can also use PDF files
    NSURL *url                  = [NSURL fileURLWithPath:urlAddress];
    NSURLRequest *requestObj    = [NSURLRequest requestWithURL:url];
    [_webView loadRequest:requestObj];
    
    // Menu Controller
    UIMenuController *menuController = [UIMenuController sharedMenuController];
    UIMenuItem *getHighlightString = [[UIMenuItem alloc] initWithTitle: @"Get String" action: @selector(getHighlightString:)];
    UIMenuItem *markHighlightedString = [[UIMenuItem alloc] initWithTitle: @"Mark String" action: @selector(markHighlightedString:)];
    [menuController setMenuItems: [NSArray arrayWithObjects:getHighlightString, markHighlightedString, nil]];

}

Above code will load the HTML file index.html file to our webview by the time our view is loaded. There is a UIMenuController object added there as well, which will add two popup menu options when you highlight a string inside UIWebView with targets pointing to our IBAction methods. See screenshot below.

Screen_shot_2011-11-04_at_1

Add this method.

- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
{
    
    if (action == @selector(getHighlightString:)) {
        return YES;
    } else if (action == @selector(markHighlightedString:)) {
        return YES;
    }
    
    return NO;
}

Above code will disable other popup menu items and show our newly added popup menu items.

6. Now, add the UIWebView and UIButton components to your storyboard file (MainStoryboard.storyboard). Then link UIWebView outlet and UIButton actions . See screen-shot below.

link UIWebView outlet reference:

link UIButton action events (Do this also with the rest of the buttons Get Highlighted String and Remove Highlights to action events getHighlightedString: and removeAllHighlights)
: Compile and Run!

Go ahead, compile and run. You should see something like this:

Screen_shot_2011-11-04_at_1
Marking a highlighted string.

Screen_shot_2011-11-04_at_1
Get the highlighted string.

Screen_shot_2011-11-04_at_1
The Code Please!

You can download the full source code here.

Inside that javascript file, we have variable to store the selected text.


原帖地址:https://zaldzbugz.posterous.com/how-to-mark-or-get-the-highlighted-string-ins

COCA: http://www.cocoachina.com/bbs/read.php?tid=124376

cnblogs: http://www.cnblogs.com/lifuqing/archive/2012/04/16/2451838.html

在代码高亮渲染过程中,避免调用高开销方法是提升性能的重要策略。这通常涉及对渲染逻辑的优化,确保在不需要执行复杂计算或资源密集型操作时,这些操作不会被触发。以下是一些可行的优化方法: - **延迟加载(Lazy Loading)**:只有在需要时才加载高亮所需的资源,例如特定语言的语法定义文件。这种方式可以减少初始化阶段的开销,避免在渲染开始前就加载不必要的资源[^2]。例如: ```python def load_syntax_definition(language): # 模拟高开销操作 print(f"Loading syntax definition for {language}") return f"{language}_syntax" class CodeHighlighter: def __init__(self): self.syntax_definitions = {} def highlight(self, code, language): if language not in self.syntax_definitions: self.syntax_definitions[language] = load_syntax_definition(language) # 模拟代码高亮过程 print(f"Highlighting code using {self.syntax_definitions[language]}") ``` - **缓存机制(Caching)**:对于已经执行过的高亮操作,可以将结果缓存起来,避免重复计算。这种策略特别适用于静态代码内容,因为其高亮结果不会发生变化。缓存机制可以通过简单的字典或更复杂的LRU(Least Recently Used)缓存实现[^1]。 ```python from functools import lru_cache @lru_cache(maxsize=128) def highlight_code(code, language): # 模拟高开销的代码高亮操作 print(f"Highlighting {language} code") return f"Highlighted {language} code: {code}" # 示例调用 print(highlight_code("function example() {}", "JavaScript")) ``` - **异步处理(Asynchronous Processing)**:将高亮处理移到后台线程或使用异步函数,确保用户界面不会因等待高亮完成而冻结。这种方式特别适用于Web应用或大型桌面应用,可以显著提升用户体验[^3]。 ```python import asyncio async def async_highlight(code, language): # 模拟异步高亮处理 print(f"Starting async highlighting for {language}") await asyncio.sleep(1) # 模拟耗时操作 print(f"Finished highlighting {language}") return f"Async highlighted {language}: {code}" # 在异步环境中调用 asyncio.run(async_highlight("def example(): pass", "Python")) ``` - **预处理与静态分析(Preprocessing and Static Analysis)**:在代码实际需要渲染之前,进行一定程度的预处理,提取出可以复用的信息。例如,分析代码结构,提前确定哪些部分不需要复杂的高亮逻辑[^2]。 通过这些方法,可以在很大程度上减少或完全避免在代码高亮渲染过程中调用高开销方法,从而提高应用程序的整体性能和响应速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值