UIWebView儲存網頁中的圖片,uiwebview轉載

來源:互聯網
上載者:User

UIWebView儲存網頁中的圖片(轉載),uiwebview轉載

現在H5混合原生開發的方式越來越流行,也就要用到UIWenview控制項。在開發過程中,我們可能會遇到一個需求,要求我們儲存網頁上的圖片,當使用者點擊圖片的時候,就可以讓使用者選擇是否下載圖片。

在系統內建的Safari瀏覽器已經實現了該功能,但是iOS開發中我們如果調用UIWebView載入圖片,會發現無法使用Safari儲存圖片的功能的。這就需要我們自己去實現。

要儲存網頁中的圖片,關鍵是要擷取手指點擊位置的圖片的url地址,這就需要從js調用oc的方法。下面介紹兩種方法來實現圖片儲存功能,但是這兩種方法都只適用於圖片地址用如下形式表示才可以擷取:

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

如果圖片是通過js動態產生的,就無法使用下面的方法擷取。

方法1、擷取點擊位置的圖片的src屬性

實現原理:

該方法主要是擷取手指點擊的位置,然後擷取該位置的標籤的src屬性,如果是img標籤,那麼就可以擷取到url。如果是其他標籤,就無法擷取到url屬性。

實現代碼:

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{//只在長按手勢開始的時候才去擷取圖片的urlif (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(@"擷取到圖片地址:%@",urlToSave);}//可以識別多個手勢-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{return YES;}

分析:

上述代碼的核心功能實現就是如下兩行代碼:

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

第一行代碼是通過js擷取點擊位置的標籤的src屬性,第二行代碼是接受向webview注入第一行的js代碼後返回的src屬性。

如果點擊位置是圖片,那麼久可以通過img.src拿到圖片的url地址,如果不是就返回空值。

效果展示:

開啟的網頁如下所示:

長按不同圖片輸出結果如下:

可以看到擷取到了正確的圖片地址

方法二、遍曆Dom樹擷取src屬性

該方法的實現比較複雜,但是靈活性更高,不僅僅適用於儲存圖片。而是適用於任何從js調用oc方法的情境。

1、NSObject類擴充

首先我們來給nsobject加一個類擴充,是為了可以給方法傳遞任意個參數,因為預設系統的performSelector方法最多隻能傳遞兩個參數

123456789101112131415161718192021222324252627282930313233 #import "NSObject+Extension.h"@implementation NSObject (Extension)- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects{// 方法簽名(對方法的描述)NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];if (signature == nil) {[NSException raise:@"嚴重錯誤" format:@"(%@)方法找不到", NSStringFromSelector(selector)];}/*NSInvocation : 利用一個NSInvocation對象通過調用方法簽名來實現對方法的調用(方法調用者、方法名、方法參數、方法傳回值)如果僅僅完成這步,和普通的函數調用沒有區別,但是關鍵在於NSInvocation可以對傳遞進來的selector進行封裝,實現可以傳遞無限多個參數普通的方法調用比如:[self performSelector: withObject: withObject:]頂多隻能傳遞兩個參數給selector*/NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];invocation.target = self; //調用者是自己invocation.selector = selector; //調用的方法是selector// 設定參數,可以傳遞無限個參數NSInteger paramsCount = signature.numberOfArguments - 2; // 除self、_cmd以外的參數個數paramsCount = MIN(paramsCount, objects.count); //防止函數有參數但是不傳遞參數時,導致崩潰for (NSInteger i = 0; i < paramsCount; i++) {id object = objects[i];if ([object isKindOfClass:[NSNull class]]) continue//如果傳遞的參數為null,就不處理了[invocation setArgument:&object atIndex:i + 2]; // +2是因為第一個和第二個參數預設是self和_cmd}// 調用方法[invocation invoke];// 擷取傳回值id returnValue = nil;if (signature.methodReturnLength) { // 有傳回值類型,才去獲得傳回值[invocation getReturnValue:&returnValue];}return returnValue;}@end

2、向webview注入js

 

在webview的代理方法webViewDidFinishLoad注入如下js代碼

上面的方法是遍曆Dom樹,從中找到img標籤,然後給每個img標籤加上點擊事件,讓圖片的url變

為"jscallbackoc://saveImage_*\"+this.src;形式,我們先不著急為什麼這樣做,先記住這裡就好了,下面會給大家解釋為什麼這麼做。

3、切割跳轉url

在點擊圖片的時候,上面的注入的js代碼就會起作用了,那麼點擊圖片,就會觸發綁定在該圖片的時間,開始跳轉,然後執行如下js代碼

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

此時就會產生新的圖片跳轉url為:jscallbackoc://saveImage_*www.baidu.com

我們在webview的如下代理方法中,可以捕獲到該url,然後切割處理

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

我們捕獲到跳轉url後,就開始做切割處理,把他轉換成oc方法,先看代碼

需要注意的一點就是跳轉url的格式必須如下所示:

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

其中jscallbackoc使我們自訂的協議名字,你可以改成任意的。但是其他的部分格式必須按照上面所示

  • 協議名格式: 協議名://

  • 方法名: 方法簽名1:方法簽名2:方法簽名3(方法簽名用冒號串連)

  • 參數: 參數1$參數2$參數3(多個參數用$串連)

協議名和方法名直接連接,方法名和參數用*串連

不建議把上面的冒號和$改成其他符號,比如你改成問號(?),如果原來的src的url裡麵包括?,那麼就會出現錯誤。

假設被點擊的圖片的src地址是:www.baidu.com。那麼js代碼`` document.location.href=\"jscallbackoc://saveImage_\"+this.src;``產生的圖片跳轉url就是jscallbackoc://saveImage_www.baidu.com

經過上面的方法切割之後,得到了方法名:saveImage和參數:www.baidu.com。

然後把方法名和參數傳入最後一行的該方法,就可以執行oc代碼了:

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

此時只要在OC代碼裡面實現方法-(void)saveImage:(NSString *)imageURL就可以被執行了。

4、攔截跳轉url

我們在webview的代理方法中,可以捕獲到點擊圖片後的跳轉url,然後做處理

在如上方法中我們做了判斷,如果跳轉過來的url包含了首碼"jscallbackoc://,就說明使我們自訂的方法,我們需要做攔截處理,轉換為oc方法,但是其他跳轉url就不做任務處理。

5、驗證結果

我們分別點擊網頁上的不同圖片,輸出結果如下:

可以看到oc的方法-(void)saveImage:(NSString *)imageURL被執行了。

6、完整代碼

總結:

方法1比較簡潔,但是僅僅只能擷取圖片。

方法二比較繁瑣,但是使用範圍更廣,不光可以儲存圖片,還可以執行任意的oc代碼。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.