UIWebView: saves images on the web page.

Source: Internet
Author: User

UIWebView: saves images (reprinted) on the webpage, and reprinted by uiwebview

Currently, H5 hybrid native development is becoming increasingly popular, and UIWenview controls are also required. During the development process, we may encounter a requirement that we save images on the web page. When users click images, they can choose whether to download images.

This function has been implemented in the Safari browser that comes with the system. However, if we call UIWebView to load images in iOS development, we will find that the Safari function cannot be used to save images. This requires us to implement it ourselves.

To save images on a webpage, the key is to obtain the url of the image at the point where the finger is clicked. This requires calling the oc method from js. The following two methods are used to save images. However, these two methods can only be obtained if the image address is expressed as follows:

1 ![](http://www.img0.bdstatic.com/img/image/meinvtoutu1242.png)

If images are dynamically generated using js, they cannot be obtained using the following method.

Method 1. Obtain the src attribute of the image at the click position.

Implementation principle:

This method is mainly used to obtain the position where the finger is clicked, and then obtain the src attribute of the label at this position. If it is an img tag, the url can be obtained. If it is another tag, the url attribute cannot be obtained.

Implementation Code:

1234567891011121314151617181920212223242526272829 @interface ViewController ()@property (weak, nonatomic) IBOutlet UIWebView *webView;@end@implementation ViewController- (void)viewDidLoad{self.webView.delegate = self;[self.webView  loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://image.baidu.com/wisebrowse/index?tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&tag3=&pn=0&rn=10&from=index&fmpage=index&pos=magic#/home"]]];UILongPressGestureRecognizer * longPressed = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];longPressed.delegate = self;[self.webView addGestureRecognizer:longPressed];}- (void)longPressed:(UITapGestureRecognizer*)recognizer{// Obtain the image url only when the long-pressed gesture starts.if (recognizer.state != UIGestureRecognizerStateBegan) {return;}CGPoint touchPoint = [recognizer locationInView:self.webView];NSString *js = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", touchPoint.x, touchPoint.y];NSString *urlToSave = [self.webView stringByEvaluatingJavaScriptFromString:js];if (urlToSave.length == 0) {return;}NSLog(@"Obtained image address: % @",urlToSave);}// Recognize multiple gestures-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{return YES;}

Analysis:

The core functions of the above Code are as follows:

12 NSString *js = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", touchPoint.x, touchPoint.y];NSString *urlToSave = [self.webView stringByEvaluatingJavaScriptFromString:js];

The first line of code is to get the src attribute of the tag at the click position through js. The second line of code is to accept the src attribute returned after the first line of js Code is injected into webview.

If the image is clicked, you can get the url of the image through img. src for a long time. If not, a null value is returned.

Effect display:

The webpage is as follows:

The output result is as follows:

The correct image address is displayed.

Method 2: retrieve the src attribute by traversing the Dom tree

The implementation of this method is more complex, but more flexible, not only suitable for saving images. It is applicable to any scenario where the oc method is called from js.

1. NSObject class Extension

First, we will add a class extension to nsobject to pass any parameter to the method, because the default system's performSelector method can only pass two parameters at most

123456789101112131415161718192021222324252627282930313233 #import "NSObject+Extension.h"@implementation NSObject (Extension)- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects{// Method signature (description of the method)NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];if (signature == nil) {[NSException raise:@"Severe error" format:@"(% @) Method not found", NSStringFromSelector(selector)];}/* NSInvocation: use an NSInvocation object to call a method by calling the method signature (method caller, method name, method parameter, and method return value)This step is no different from a common function call, but the key is that NSInvocation can encapsulate the passed selector, so that an unlimited number of parameters can be passed.Common method calls include: [self defined mselector: withObject:] at most, only two parameters can be passed to selector */NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];invocation.target = self; // The caller is the caller.invocation.selector = selector; // The called method is selector.// Set parameters. an unlimited number of parameters can be passed.NSInteger paramsCount = signature.numberOfArguments - 2; // Number of parameters except self and _ cmdparamsCount = MIN(paramsCount, objects.count); // Prevent the function from crashing when there are parameters but no parameters are passed.for (NSInteger i = 0; i < paramsCount; i++) {id object = objects[i];if ([object isKindOfClass:[NSNull class]]) continue// If the passed parameter is null, it will not be processed.[invocation setArgument:&object atIndex:i + 2]; // + 2 because the first and second parameters are self and _ cmd by default.}// Call Method[invocation invoke];// Obtain the returned valueid returnValue = nil;if (signature.methodReturnLength) { // Obtain the returned value only when there is a return value type.[invocation getReturnValue:&returnValue];}return returnValue;}@end

2. Inject js into webview

 

Inject the following js Code into the proxy method webViewDidFinishLoad of webview:

The above method is to traverse the Dom tree, locate the img tag, and add a click event to each img tag to change the image url.

In the format of "jscallbackoc: // saveImage _ * \" + this. src;, we will not worry about why we should do this first. Remember this. Here we will explain why we did this.

3. Cut the jump url

When you click an image, the injected js Code above will take effect. clicking an image triggers binding at the image time, starts the jump, and then runs the following js Code.

1 document.location.href=\"jscallbackoc://saveImage_*\"+this.src;\

In this case, a new image jump url is generated: jscallbackoc: // saveImage _ * www.baidu.com.

We can capture the url in the following proxy method of webview, and then cut the Processing

1 (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

After capturing the jump url, we start to cut the url and convert it to the oc method. Let's look at the code first.

Note that the url format must be as follows:

1 jscallbackoc://sendMessage_number2_number3_*100$100$99

Here, jscallbackoc enables us to customize the protocol name. You can change it to any one. However, the other formats must follow the preceding steps.

  • Protocol name format: protocol name ://

  • Method Name: Method signature 1: Method Signature 2: Method signature 3 (method signature is connected by a colon)

  • Parameter: parameter 1 $ parameter 2 $ parameter 3 (multiple parameters are connected by $)

The protocol name and method name are directly connected. The method name and parameter are connected *.

We do not recommend that you change the colon and $ in the preceding format to another symbol. For example, you can change it to question mark (?), If the original src url contains ?, Then an error occurs.

Suppose the src address of the image to be clicked is www.baidu.com. Then the js Code ''document. location. href = \ "jscallbackoc: // saveImage _ \" + this. src; ''generates an image jump url that is jscallbackoc: // saveImage_www.baidu.com

After the preceding method is cut, the method name saveImage and parameter www.baidu.com are obtained.

Then, pass the method name and parameter to the method in the last line to execute the oc code:

1 [viewController performSelector:NSSelectorFromString(methodName) withObjects:params];

In this case, you only need to implement the method-(void) saveImage :( NSString *) imageURL In the OC code to be executed.

4. Intercept jump URLs

In the proxy method of webview, we can capture the jump url after clicking an image and then process it.

In the above method, we made a judgment. If the jump url contains the prefix "jscallbackoc: //, it indicates the custom method. We need to intercept it, convert to oc method, but do not process other jump URLs.

5. Verification results

We click on different images on the webpage, and the output result is as follows:

You can see that the oc method-(void) saveImage :( NSString *) imageURL is executed.

6. complete code

Summary:

Method 1 is concise, but only images can be obtained.

Method 2 is cumbersome, but it is widely used. It can not only save images, but also execute arbitrary oc code.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.