当前位置: 移动技术网 > IT编程>移动开发>IOS > iOS模仿微信长按识别二维码的多种方式

iOS模仿微信长按识别二维码的多种方式

2019年07月24日  | 移动技术网IT编程  | 我要评论

油酸价格,巴洛克超级记忆音乐,邓卓棣 维基百科

 参考:https://github.com/nglszs/bcqrcode

方式一:

#import <uikit/uikit.h>
@interface viewcontroller : uiviewcontroller
@end
**************
#import "viewcontroller.h"
@interface viewcontroller ()
@end
@implementation viewcontroller
- (void)viewdidload {
  [super viewdidload];
  self.title = @"二维码";
  uibarbuttonitem *leftbtn = [[uibarbuttonitem alloc]
                initwithtitle:@"生成"
                style:uibarbuttonitemstyleplain
                target:self
                action:@selector(backview)];
  self.navigationitem.leftbarbuttonitem = leftbtn;
  uibarbuttonitem *rightbtn = [[uibarbuttonitem alloc]
                 initwithtitle:@"扫描"
                 style:uibarbuttonitemstyleplain
                 target:self
                 action:@selector(scanview)];
  self.navigationitem.rightbarbuttonitem = rightbtn;
  //长按识别图中的二维码,类似于微信里面的功能,前提是当前页面必须有二维码
  uilongpressgesturerecognizer *longpress = [[uilongpressgesturerecognizer alloc] initwithtarget:self action:@selector(readcode:)];
  [self.view addgesturerecognizer:longpress];
}
- (void)readcode:(uilongpressgesturerecognizer *)presssender {
  if (presssender.state == uigesturerecognizerstatebegan) {
    //截图 再读取
    uigraphicsbeginimagecontextwithoptions(self.view.bounds.size, yes, 0);
    cgcontextref context = uigraphicsgetcurrentcontext();
    [self.view.layer renderincontext:context];
    uiimage *image = uigraphicsgetimagefromcurrentimagecontext();
    uigraphicsendimagecontext();
   //识别二维码 
    ciimage *ciimage = [[ciimage alloc] initwithcgimage:image.cgimage options:nil];
    cicontext *cicontext = [cicontext contextwithoptions:@{kcicontextusesoftwarerenderer : @(yes)}]; // 软件渲染
    cidetector *detector = [cidetector detectoroftype:cidetectortypeqrcode context:cicontext options:@{cidetectoraccuracy : cidetectoraccuracyhigh}];// 二维码识别
    nsarray *features = [detector featuresinimage:ciimage];
    for (ciqrcodefeature *feature in features) {
      nslog(@"msg = %@",feature.messagestring); // 打印二维码中的信息
      //对结果进行处理
      resultviewcontroller *resultvc = [[resultviewcontroller alloc] init];
      resultvc.contentstring = feature.messagestring;
      [self.navigationcontroller pushviewcontroller:resultvc animated:no];
    }
  }
}
- (void)backview {
    uiimageview *codeimageview = [[uiimageview alloc] initwithframe:cgrectmake((bcwidth - 200)/2, 100, 200, 200)];
    codeimageview.layer.bordercolor = [uicolor orangecolor].cgcolor;
    codeimageview.layer.borderwidth = 1;
    [self.view addsubview:codeimageview];
  //有图片的时候,也可以不设置圆角
  [codeimageview creatcode:@"https://www.baidu.com" image:[uiimage imagenamed:@"bg"] andimagecorner:4];
  //没有图片的时候
  // [codeimageview creatcode:@"这波可以" image:nil andimagecorner:4];
}
- (void)scanview {
  [self.navigationcontroller pushviewcontroller:[scancodeviewcontroller new] animated:yes];
}
- (void)didreceivememorywarning {
  [super didreceivememorywarning];
  // dispose of any resources that can be recreated.
}
@end
************生成二维码
#import <uikit/uikit.h>
@interface uiimageview (creatcode)
/**
 这里传入二维码的信息,image是加载二维码上方的图片,如果不要图片直接codeimage为nil即可,后面是图片的圆角
 */
- (void)creatcode:(nsstring *)codecontent image:(uiimage *)codeimage andimagecorner:(cgfloat)imagecorner;
@end
**************
#import "uiimageview+creatcode.h"
#define imagesize self.bounds.size.width
@implementation uiimageview (creatcode)
- (void)creatcode:(nsstring *)codecontent image:(uiimage *)codeimage andimagecorner:(cgfloat)imagecorner {
  //用coreimage框架实现二维码的生成,下面方法最好异步调用
  dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{
    cifilter *codefilter = [cifilter filterwithname:@"ciqrcodegenerator"];
    //每次调用都恢复其默认属性
    [codefilter setdefaults];
    nsdata *codedata = [codecontent datausingencoding:nsutf8stringencoding];
    //设置滤镜数据
    [codefilter setvalue:codedata forkey:@"inputmessage"];
    //获得滤镜输出的图片
    ciimage *outputimage = [codefilter outputimage];
    //这里的图像必须经过位图转换,不然会很模糊
    uiimage *translateimage = [self creatuiimagefromciimage:outputimage andsize:imagesize];
    //这里如果不想设置圆角,直接传一个image就好了
    uiimage *resultimage = [self setsuperimage:translateimage andsubimage:[self imagecornerradius:imagecorner andimage:codeimage]];
    dispatch_async(dispatch_get_main_queue(), ^{
      self.image = resultimage;
    });
});
}
//这里的size我是用imageview的宽度来算的,你可以改为自己想要的size
- (uiimage *)creatuiimagefromciimage:(ciimage *)image andsize:(cgfloat)size {
  //下面是创建bitmao没什么好解释的,不懂得自行百度或者参考官方文档
  cgrect extent = cgrectintegral(image.extent);
  cgfloat scale = min(size/cgrectgetwidth(extent), size/cgrectgetheight(extent));
  size_t width = cgrectgetwidth(extent) * scale;
  size_t height = cgrectgetheight(extent) * scale;
  cgcolorspaceref colorref = cgcolorspacecreatedevicegray();
  cgcontextref contextref = cgbitmapcontextcreate(nil, width, height, 8, 0, colorref, (cgbitmapinfo)kcgimagealphanone);
  cicontext *context = [cicontext contextwithoptions:nil];
  cgimageref imageref = [context createcgimage:image fromrect:extent];
  cgcontextsetinterpolationquality(contextref, kcginterpolationnone);
  cgcontextscalectm(contextref, scale, scale);
  cgcontextdrawimage(contextref, extent, imageref);
  cgimageref newimage = cgbitmapcontextcreateimage(contextref);
  cgcontextrelease(contextref);
  cgimagerelease(imageref);
  return [uiimage imagewithcgimage:newimage];
}
//这里将二维码上方的图片设置圆角并缩放
- (uiimage *)imagecornerradius:(cgfloat)cornerradius andimage:(uiimage *)image {
  //这里是将图片进行处理,frame不能太大,否则会挡住二维码
  cgrect frame = cgrectmake(0, 0, imagesize/5, imagesize/5);
  uigraphicsbeginimagecontextwithoptions(frame.size, no, 0);
  [[uibezierpath bezierpathwithroundedrect:frame cornerradius:cornerradius] addclip];
  [image drawinrect:frame];
  uiimage *clipimage = uigraphicsgetimagefromcurrentimagecontext();
  uigraphicsendimagecontext();
  return clipimage;
}
- (uiimage *)setsuperimage:(uiimage *)superimage andsubimage:(uiimage *)subimage {
  //将两张图片绘制在一起
  uigraphicsbeginimagecontextwithoptions(superimage.size, yes, 0);
  [superimage drawinrect:cgrectmake(0, 0, superimage.size.width, superimage.size.height)];
  [subimage drawinrect:cgrectmake((imagesize - imagesize/5)/2, (imagesize - imagesize/5)/2, subimage.size.width, subimage.size.height)];
  uiimage *resultimage = uigraphicsgetimagefromcurrentimagecontext();
  uigraphicsendimagecontext();
  return resultimage;
}
@end
***************扫描二维码
#import <uikit/uikit.h>
#import <avfoundation/avfoundation.h>
@interface scancodeviewcontroller : uiviewcontroller<avcapturemetadataoutputobjectsdelegate>
{
  avcapturesession * session;
  avcapturemetadataoutput * output;
  nsinteger linenum;
  bool upordown;
  nstimer *linetimer;
}
@property (nonatomic, strong) uiimageview *lineimageview;
@property (nonatomic, strong) uiimageview *backimageview;
@end
******************
#import "scancodeviewcontroller.h"
@implementation scancodeviewcontroller
- (void)viewdidload {
  [super viewdidload];
  if ([[[uidevice currentdevice] systemversion] floatvalue] >= 7.0) {
        avauthorizationstatus authstatus = [avcapturedevice authorizationstatusformediatype:avmediatypevideo];
        if (authstatus == avauthorizationstatusdenied || authstatus == avauthorizationstatusrestricted)
        {
          [[[uialertview alloc] initwithtitle:nil message:@"本应用无访问相机的权限,如需访问,可在设置中修改" delegate:nil cancelbuttontitle:@"好的" otherbuttontitles:nil, nil] show];
          return;
        } else {
          //打开相机
          avcapturedevice * device = [avcapturedevice defaultdevicewithmediatype:avmediatypevideo];
          //创建输入流
          avcapturedeviceinput * input = [avcapturedeviceinput deviceinputwithdevice:device error:nil];
          //创建输出流
          output = [[avcapturemetadataoutput alloc]init];
          //设置代理 在主线程里刷新
          [output setmetadataobjectsdelegate:self queue:dispatch_get_main_queue()];
          //设置扫描区域,这个需要仔细调整
          [output setrectofinterest:cgrectmake(64/bcheight, (bcwidth - 320)/2/bcwidth, 320/bcheight, 320/bcwidth)];
          //初始化链接对象
          session = [[avcapturesession alloc]init];
          //高质量采集率
          [session setsessionpreset:avcapturesessionpresethigh];
          [session addinput:input];
          [session addoutput:output];
          //设置扫码支持的编码格式
          output.metadataobjecttypes=@[avmetadataobjecttypeqrcode,avmetadataobjecttypeean13code, avmetadataobjecttypeean8code, avmetadataobjecttypecode128code];
          avcapturevideopreviewlayer * layer = [avcapturevideopreviewlayer layerwithsession:session];
          layer.videogravity=avlayervideogravityresizeaspectfill;
          layer.frame=self.view.layer.bounds;
          [self.view.layer addsublayer:layer];
      }
  }
        [self _initview];
}
//里面所有的控件可以自己定制,这里只是简单的例子
- (void)_initview {
  //扫码框
  _backimageview = [[uiimageview alloc] initwithframe:cgrectmake(0, 64, bcwidth, bcheight - 64)];
  _backimageview.image = [uiimage imagenamed:@"camera_bg"];
  [self.view addsubview:_backimageview];
  _lineimageview = [[uiimageview alloc] initwithframe:cgrectmake(16, 15, bcwidth - 32, 1)];
  _lineimageview.backgroundcolor = [uicolor orangecolor];
  [_backimageview addsubview:_lineimageview];
  //各种参数设置
  linenum = 0;
  upordown = no;
  linetimer = [nstimer scheduledtimerwithtimeinterval:0.01 target:self selector:@selector(lineanimation) userinfo:nil repeats:yes];
}
-(void)lineanimation {
  if (upordown == no) {
    linenum ++;
    _lineimageview.frame = cgrectmake(cgrectgetminx(_lineimageview.frame), 15 + linenum, bcwidth - 32, 1);
    cgfloat tempheight = cgrectgetheight(_backimageview.frame) * 321/542;
    nsinteger height = (nsinteger)tempheight + 20;
    if (linenum == height) {
      upordown = yes;
    }
  }
  else {
    linenum --;
    _lineimageview.frame = cgrectmake(cgrectgetminx(_lineimageview.frame), 15 + linenum, bcwidth - 32, 1);
    if (linenum == 0) {
      upordown = no;
    }
  }
}
#pragma mark avcapturemetadataoutputobjectsdelegate
- (void)captureoutput:(avcaptureoutput *)captureoutput didoutputmetadataobjects:(nsarray *)metadataobjects fromconnection:(avcaptureconnection *)connection {
  if ([metadataobjects count] > 0) {
    [session stoprunning]; //停止扫码
    avmetadatamachinereadablecodeobject *metadataobject = [metadataobjects firstobject];
    resultviewcontroller *resultvc = [[resultviewcontroller alloc] init];
    resultvc.contentstring = metadataobject.stringvalue;
    [self.navigationcontroller pushviewcontroller:resultvc animated:no];
  }
}
- (void)viewwillappear:(bool)animated {
  [super viewwillappear:animated];
  [session startrunning];
  [linetimer setfiredate:[nsdate distantpast]];
}
- (void)viewwilldisappear:(bool)animated {
  [super viewwilldisappear:animated];
  [session stoprunning];
  [linetimer setfiredate:[nsdate distantfuture]];
  if (![self.navigationcontroller.viewcontrollers containsobject:self]) {//释放timer
    [linetimer invalidate];
    linetimer = nil;
  }
}
- (void)dealloc {
  nslog(@"已释放");
}
@end
*******吧识别的二维码信息传过来加载网页
#import <uikit/uikit.h>
@interface resultviewcontroller : uiviewcontroller
@property(nonatomic, retain)nsstring *contentstring;
@end
********
#import "resultviewcontroller.h"
#import <webkit/webkit.h>
@implementation resultviewcontroller
- (void)viewdidload {
  [super viewdidload];
  //这个界面我只是简单的处理一下,可以自己定制,实际应用中扫码跳转不可能就这两种逻辑
  if ([_contentstring hasprefix:@"http"]) {
    wkwebview *showview = [[wkwebview alloc] initwithframe:bcscreen];
    nsurlrequest *coderequest = [nsurlrequest requestwithurl:[nsurl urlwithstring:_contentstring]];
    [showview loadrequest:coderequest];
    [self.view addsubview:showview];
  } else {
    uilabel *showlabel = [[uilabel alloc] initwithframe:cgrectmake(0, 80, 200, 50)];
    showlabel.center = self.view.center;
    showlabel.font = [uifont boldsystemfontofsize:16];
    showlabel.text = [nsstring stringwithformat:@"扫描结果是---%@",_contentstring];
    showlabel.numberoflines = 0;
    [self.view addsubview:showlabel];
  }
}
@end

方式二:识别网页中的二维码

ios webview中 长按二维码的识别

思路:

长按webview 的过程中 截屏,再去解析是否有二维码,但是有个缺点 就是 万一截了一个 一半的二维码 那就无解了。

在webview中 注入获取点击图片的js 获取图片,再解析。缺点:万一图片过大 需要下载,势必会影响用户体验。

@interface cvwebviewcontroller ()<uigesturerecognizerdelegate>
@property (weak, nonatomic) iboutlet uiwebview *webview;
@end
@implementation cvwebviewcontroller
- (void)viewdidload
{
  [self.webview loadrequest:[nsurlrequest requestwithurl:[nsurl urlwithstring:@"http://mp.weixin.qq.com/s?__biz=mzi2odazodazmw==&mid=2650057120&idx=2&sn=c875f7d03ea3823e8dcb3dc4d0cff51d&scene=0#wechat_redirect"]]];
  uilongpressgesturerecognizer *longpressed = [[uilongpressgesturerecognizer alloc] initwithtarget:self action:@selector(longpressed:)];
  longpressed.delegate = self;
  [self.webview addgesturerecognizer:longpressed];
}
- (void)longpressed:(uitapgesturerecognizer*)recognizer
{
  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 *imageurl = [self.webview stringbyevaluatingjavascriptfromstring:js];
  if (imageurl.length == 0) {
    return;
  }
  nslog(@"image url:%@",imageurl);
  nsdata *data = [nsdata datawithcontentsofurl:[nsurl urlwithstring:imageurl]];
  uiimage *image = [uiimage imagewithdata:data];
  if (image) {
    //......
    //save image or extract qr code
  }
}
-(bool)gesturerecognizer:(uigesturerecognizer *)gesturerecognizer shouldrecognizesimultaneouslywithgesturerecognizer:(uigesturerecognizer *)othergesturerecognizer
{
  return yes;
}

以上所述是小编给大家介绍的ios模仿微信长按识别二维码的多种方式,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网