WebView 長(zhǎng)按識(shí)別二維碼和點(diǎn)擊查看大圖

本地識(shí)別二維碼

文末有 Demo 地址, 挺簡(jiǎn)單的, 不想看字可以直接看 demo

CIDetecor

1, 首先要識(shí)別本地二維碼, webView 基本只是幾條 js 語(yǔ)句的問(wèn)題.
創(chuàng)建 QRCodeDetector 類(lèi):

#import "YNQRCodeDetector.h"

@implementation YNQRCodeDetector

+ (CIQRCodeFeature *)yn_detectQRCodeWithImage:(UIImage *)image {
    // 1. 創(chuàng)建上下文
    CIContext *context = [[CIContext alloc] init];
    
    // 2. 創(chuàng)建探測(cè)器
    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy: CIDetectorAccuracyLow}];
    
    // 3. 識(shí)別圖片獲取圖片特征
    CIImage *imageCI = [[CIImage alloc] initWithImage:image];
    NSArray<CIFeature *> *features = [detector featuresInImage:imageCI];
    CIQRCodeFeature *codeF = (CIQRCodeFeature *)features.firstObject;
    
    return codeF;
}

@end

2, 在本地 imageView 中添加手勢(shì), 處理二維碼識(shí)別的鏈接, 有二維碼顯示保存和識(shí)別, 沒(méi)有只顯示保存

- (void)imageLongPress {
    
    UIAlertController *ac = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    
    CIQRCodeFeature *codeF = [YNQRCodeDetector yn_detectQRCodeWithImage:self.imageView.image];
    
    [ac addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        
    }]];
    
    [ac addAction:[UIAlertAction actionWithTitle:@"保存圖片" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self savePicture];
    }]];
    
    if (codeF.messageString) {
        
        [ac addAction:[UIAlertAction actionWithTitle:@"識(shí)別二維碼" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            // 內(nèi)置瀏覽器打開(kāi)網(wǎng)頁(yè)
            SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:codeF.messageString]];
            [self presentViewController:safariVC animated:YES completion:nil];
        }]];
    }
    
    [self presentViewController:ac animated:YES completion:nil];
}

3, 保存圖片沒(méi)什么好說(shuō)的, 記得 iOS 10 以后手動(dòng)開(kāi)啟相冊(cè)權(quán)限

- (void)savePicture {
    if (self.imageView.image == nil) {
//        [SVProgressHUD showErrorWithStatus:@"圖片還未加載"];
    } else {
        UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    }
}

- (void)image:(UIImage *)image
didFinishSavingWithError:(NSError *)error
  contextInfo:(void *)contextInfo {
    
    if (error) {
        
//        [SVProgressHUD showErrorWithStatus:@"保存失敗"];
        
    } else {
        
//        [SVProgressHUD showSuccessWithStatus:@"保存成功"];
    }
    
}

WebView上的一些處理

WebView添加長(zhǎng)按手勢(shì)

因?yàn)轫?xiàng)目需求, 需要改的地方太多了, 我直接寫(xiě)在自定義 WebView 里面了, 直接替換 webView 即可. 因?yàn)楣拘枨蟮?web 沒(méi)有過(guò)于復(fù)雜的功能, 直接寫(xiě)在自定義 webView 就行.

自定義 webView 添加長(zhǎng)按手勢(shì):

- (instancetype)init {
    self = [super init];
    if (self) {
        [self basicConfigure];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self basicConfigure];
    }
    return self;
}

- (void)basicConfigure {
    self.delegate = self;
    
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressWebPic:)];
    longPress.delegate = self;
    [self addGestureRecognizer:longPress];
}

- (void)longPressWebPic:(UILongPressGestureRecognizer *)recognizer {
    
    if (recognizer.state != UIGestureRecognizerStateBegan) {
        return;
    }
    
    // 獲取點(diǎn)擊區(qū)域坐標(biāo), 通過(guò)坐標(biāo)得到圖片
    CGPoint touchPoint = [recognizer locationInView:self];
    NSString *imgURL = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", touchPoint.x, touchPoint.y];
    NSString *urlToSave = [self stringByEvaluatingJavaScriptFromString:imgURL];
    
    if (urlToSave.length == 0) {
        return;
    }
    
//    ENLog(@"%@", urlToSave);
    
    [self imageWithUrl:urlToSave];
    
}

下載圖片

// 因?yàn)樽隽藗€(gè) demo 不想引用三方, 可以用 sdImageDownloader 替代
- (void)imageWithUrl:(NSString *)imageUrl {

// 在子線程中下載圖片, 不在子線程中下載圖片會(huì)造成主線程阻塞, 導(dǎo)致 alertController 需要很久時(shí)間才彈出    
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURL *url = [NSURL URLWithString:imageUrl];
        
        NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        
        NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue new]];
        
        NSURLRequest *imgRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
        
        NSURLSessionDownloadTask  *task = [session downloadTaskWithRequest:imgRequest completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (error) {
                return ;
            }
            
            NSData *imageData = [NSData dataWithContentsOfURL:location];
            
            // 在主線程中配置 UI 顯示相關(guān)操作
            dispatch_async(dispatch_get_main_queue(), ^{
                
                UIImage *image = [UIImage imageWithData:imageData];
                
                UIAlertController *ac = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
                
                CIQRCodeFeature *codeF = [YNQRCodeDetector yn_detectQRCodeWithImage:image];
                
                [ac addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
                    
                }]];
                
                [ac addAction:[UIAlertAction actionWithTitle:@"保存圖片" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                    [self savePicture:image];
                }]];
                
                if (codeF.messageString) {
                    
                    [ac addAction:[UIAlertAction actionWithTitle:@"識(shí)別二維碼" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                        
                        SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:codeF.messageString]];
                        [[self currentViewController] presentViewController:safariVC animated:YES completion:nil];
                    }]];
                    
                }
                // 直接用 webView 模態(tài)出控制器
                [[self currentViewController] presentViewController:ac animated:YES completion:nil];
            });   
        }];
        
        [task resume];
    });
}

獲取最上層控制器

- (UIViewController *)currentViewController {
    UIWindow *keyWindow  = [UIApplication sharedApplication].keyWindow;
    UIViewController *vc = keyWindow.rootViewController;
    while (vc.presentedViewController) {
        vc = vc.presentedViewController;
        
        if ([vc isKindOfClass:[UINavigationController class]]) {
            vc = [(UINavigationController *)vc visibleViewController];
        } else if ([vc isKindOfClass:[UITabBarController class]]) {
            vc = [(UITabBarController *)vc selectedViewController];
        }
    }
    return vc;
}

- (UINavigationController *)currentNavigationController {
    return [self currentViewController].navigationController;
}

處理 WebView 代理方法 (js 處理)

- (void)webViewDidFinishLoad:(UIWebView *)webView {

// 屏蔽網(wǎng)頁(yè)自帶操作
    [self stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
    
    NSString * jsCallBack = @"window.getSelection().removeAllRanges();";
    [webView stringByEvaluatingJavaScriptFromString:jsCallBack];
    
    //js方法遍歷圖片添加點(diǎn)擊事件 返回圖片個(gè)數(shù)
    static  NSString * const jsGetImages =
    @"function getImages(){\
    var objs = document.getElementsByTagName(\"img\");\
    for(var i=0;i<objs.length;i++){\
    objs[i].onclick=function(){\
    document.location=\"myweb:imageClick:\"+this.src;\
    };\
    };\
    return objs.length;\
    };";
    
    // 獲取圖片鏈接
    [webView stringByEvaluatingJavaScriptFromString:jsGetImages];//注入js方法
    [webView stringByEvaluatingJavaScriptFromString:@"getImages()"];
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    // 將url轉(zhuǎn)換為string
    NSString *requestString = [[request URL] absoluteString];
    
    // 判斷創(chuàng)建的字符串內(nèi)容是否以pic:字符開(kāi)始
    if ([requestString hasPrefix:@"myweb:imageClick:"]) {
        NSString *imageUrl = [requestString substringFromIndex:@"myweb:imageClick:".length];
        ENLog(@"------%@", imageUrl);
        // 點(diǎn)擊網(wǎng)頁(yè)圖片查看大圖
        ShowBigPicController *sb = [[ShowBigPicController alloc] init];
        sb.imageURL = imageUrl;
        [[self currentViewController] presentViewController:sb animated:NO completion:nil];
        
        return NO;
    }
    return YES;
}

Demo 地址

YNQRCodeWebView

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屎篱,更是在濱河造成了極大的恐慌吨凑,老刑警劉巖袁勺,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儿子,死亡現(xiàn)場(chǎng)離奇詭異郑原,居然都是意外死亡腌紧,警方通過(guò)查閱死者的電腦和手機(jī)茸习,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)壁肋,“玉大人号胚,你說(shuō)我怎么就攤上這事〗牛” “怎么了猫胁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)跛锌。 經(jīng)常有香客問(wèn)我弃秆,道長(zhǎng),這世上最難降的妖魔是什么察净? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任驾茴,我火速辦了婚禮,結(jié)果婚禮上氢卡,老公的妹妹穿的比我還像新娘锈至。我一直安慰自己,他們只是感情好译秦,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布峡捡。 她就那樣靜靜地躺著,像睡著了一般筑悴。 火紅的嫁衣襯著肌膚如雪们拙。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,584評(píng)論 1 312
  • 那天阁吝,我揣著相機(jī)與錄音砚婆,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛装盯,可吹牛的內(nèi)容都是我干的坷虑。 我是一名探鬼主播,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼埂奈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼迄损!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起账磺,我...
    開(kāi)封第一講書(shū)人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤芹敌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后垮抗,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體氏捞,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年借宵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幌衣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壤玫,死狀恐怖豁护,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情欲间,我是刑警寧澤楚里,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站猎贴,受9級(jí)特大地震影響班缎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜她渴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一达址、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧趁耗,春花似錦沉唠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至罢屈,卻和暖如春嘀韧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缠捌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工锄贷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓谊却,卻偏偏與公主長(zhǎng)得像蹂随,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子因惭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件绩衷、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,124評(píng)論 4 61
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,319評(píng)論 25 707
  • 這是短書(shū)集第169篇文章咳燕,是講述愛(ài)的一種 解說(shuō)詞:自從打開(kāi)《人類(lèi)簡(jiǎn)史》這本書(shū)之后勿决,我才發(fā)現(xiàn)“觀測(cè)者的視角”這一命題...
    Andylee閱讀 401評(píng)論 0 0
  • 當(dāng)?shù)谝唤z光明照亮遠(yuǎn)方的路,踏上征程去往遠(yuǎn)方招盲。不知路有多遠(yuǎn)低缩,只有趕路的人在前方。相互交知的道路互相重疊曹货,命中的相...
    萬(wàn)變妖閱讀 160評(píng)論 0 0
  • css初體驗(yàn)咆繁,內(nèi)容包含以下幾點(diǎn): 標(biāo)簽選擇器(下); CSS三大特性顶籽; div和span; 塊級(jí)元素玩般、行內(nèi)元素、行...
    敲出天下閱讀 893評(píng)論 0 1