服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS模仿微信长按识别二维码的多种方式

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

2021-03-24 18:23liyubao160 IOS

这篇文章主要介绍了iOS模仿微信长按识别二维码的两种方式,文章第二种方式是识别网页中的二维码,具体思路详解大家参考下本文

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

方式一:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#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 获取图片,再解析。缺点:万一图片过大 需要下载,势必会影响用户体验。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@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模仿微信长按识别二维码的多种方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!

原文链接:http://blog.csdn.net/u011146511/article/details/75645272

延伸 · 阅读

精彩推荐
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25