ios 条形码、二维码读取相关

原文地址:http://www.cnblogs.com/xling/archive/2013/03/21/2972640.html

 

目的只是要做一个能随时随地进行条形码扫描,并和某单号配对的小工具。

在淘宝上看了一下扫描枪的价格,便宜的,只能插在电脑上使用,这个不符合随时随地的条件。贵的,有显示屏,可编程,但是目前投入回报比太小,不值得付出。

怎么办呢?手上有一台 Mac Mini ,有一台 iPhone, 看过两个月的 ObjC 的基本语法和 ios 开发教程,不如就写个 app 吧。

一,越狱

首先,iphone 要越狱,网上大把,就不说了。

二,免证书真机调试

对于我这种初学者,花几百RMB去弄个开发者账号,然后真机调试,实在是浪费。但是条形码扫描又必须真机调试(摄像头无法模拟),所以,破解一下 Xcode ,弄免证书真机调式是必经之路:

http://kqwd.blog.163.com/blog/static/4122344820117191351263/

这遍博文写的很详细,各个主流版本的 Xcode 的都有讲,仔细对着做就成。当然iphone 必须先越狱。

 

三,ZBar

目前 ios 上有开源的扫描库 ZXing 和 ZBar, 我没有比较,对着网上搜到的博文就用了 ZBar,过程还算顺利。

但是如果有一堆条形码摆在那里,ZBar 的对焦框会飘来飘去。

ZBar 有个 scanCrop 属性,默认值是 (0,0,1,1)代表全屏,

the region of the image that will be scanned.  normalized coordinates.

这句注释看起来很费解。normalized coordinates 我不明白到底是什么意思。

在屏幕上画一个框,这个框代表可扫描区域,然后把这个区域的 CGRect 传给 scanCrop 显然是不能工作的。

几经周折,找到了如下解决方法:

View Code
1 -(CGRect)getScanCrop:(CGRect)rect readerViewBounds:(CGRect)rvBounds{
2     CGFloat x,y,width,height;
3     x = rect.origin.y / rvBounds.size.height;
4     y = 1 - (rect.origin.x + rect.size.width) / rvBounds.size.width;
5     width = (rect.origin.y + rect.size.height) / rvBounds.size.height;
6     height = 1 - rect.origin.x / rvBounds.size.width;
7     return CGRectMake(x, y, width, height);
8 }

很奇怪,x,y,width,height 好像都是翻的,不过,这个确实是可用的。

    self.readerView.scanCrop = [self getScanCrop:maskView.frame readerViewBounds:self.readerView.bounds];

 

四,对二维码加、解密

除了条形码,还有另外一个码需要扫描,并和条形码对应。这个码里还要附加一些另外信息,所以,我就用了二维码。

生成二维码,我用的是 ZXing.NET, 在 NuGet 里可以找到,这个没什么难度。

因为这要生成二维码的内容,涉及到隐私,不是随便拿个手机就可以扫扫的。所以,我用了AES加密。

在.NET里做AES加密是很简单的事情,但是在 ios 里做解密,对我来说,有些复杂。

因为加密后的内容可能为不能显示的字符,所以需要用 Base64 转一下。

网上提供的一些 Base64 代码不是缺胳膊就是少腿,用着非常虐人。用了GTM后,赶脚爽多了

http://google-toolbox-for-mac.googlecode.com/svn/trunk/

需要FQ,FQ我用GoAgent

提供一下 ios 下的AES加解密代码:

View Code
 1 #import <CommonCrypto/CommonCryptor.h>
 2 #import "AESCrypt.h"
 3 #import "GTMDefines.h"
 4 #import "GTMBase64.h"
 5 
 6 @implementation AESCrypt
 7 
 8 
 9 
10 +(NSString*) dencryptData:(NSString*)str key:(NSString *)key{
11     NSString *newKey = [key stringByPaddingToLength:32 withString:@"0" startingAtIndex:0 ];
12     NSString *iv = [key stringByPaddingToLength:16 withString:@"0" startingAtIndex:0];
13     
14     NSData *data = [GTMBase64 decodeString:str];
15     NSData *keyData = [newKey dataUsingEncoding:NSUTF8StringEncoding];
16     NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
17     
18     NSData *result = [self dencryptData:data :keyData :ivData];
19     
20     return [[NSString alloc ] initWithData:result encoding:NSUTF8StringEncoding ];
21 }
22 
23 + (NSData*)dencryptData:(NSData*)data :(NSData*)key :(NSData*)iv
24 {
25     size_t bufferSize = [data length] + kCCBlockSizeAES128;
26     void *buffer = malloc(bufferSize);
27     size_t encryptedSize = 0;
28     CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
29                                           kCCAlgorithmAES128,
30                                           kCCOptionPKCS7Padding,
31                                           [key bytes],
32                                           [key length],
33                                           [iv bytes],
34                                           [data bytes],
35                                           [data length],
36                                           buffer,
37                                           bufferSize,
38                                           &encryptedSize);
39     if (cryptStatus == kCCSuccess)
40         return [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
41     else
42         free(buffer);
43     
44     return NULL;
45 }
46 
47 
48 
49 
50 
51 +(NSString *)encrypt:(NSString *)str key:(NSString *)key{
52     NSString *newKey = [key stringByPaddingToLength:32 withString:@"0" startingAtIndex:0 ];
53     NSString *iv = [key stringByPaddingToLength:16 withString:@"0" startingAtIndex:0];
54     
55     NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
56     NSData *keyData = [newKey dataUsingEncoding:NSUTF8StringEncoding];
57     NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
58     
59     NSData *result = [self encryptData:data key:keyData iv:ivData];
60     result = [GTMBase64 encodeData:result];
61     
62     return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding ];
63 }
64 
65 + (NSData*)encryptData:(NSData*)data key:(NSData*)key iv:(NSData*)iv
66 {
67     size_t bufferSize = [data length] + kCCBlockSizeAES128;
68     void *buffer = malloc(bufferSize);
69     size_t encryptedSize = 0;
70     CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
71                                           kCCAlgorithmAES128,
72                                           kCCOptionPKCS7Padding,
73                                           [key bytes],
74                                           [key length],
75                                           [iv bytes],
76                                           [data bytes],
77                                           [data length],
78                                           buffer,
79                                           bufferSize,
80                                           &encryptedSize);
81     if (cryptStatus == kCCSuccess)
82         return [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
83     else
84         free(buffer);
85     
86     return NULL;
87 }
88 
89 @end

需要注意的是:IV 是 取KEY的前16个字符,不足的在后面补0,KEY取原KEY的前32个字符,不足的,在后面补0。

还有 PKCS7。要保证.NET里的和ios里的对应参数一至。

 

五,ARC

GTM 提供的代码有很多 retain,autorelease 等,对于ARC这些是不行的。一开始,我简单的把 autorelease 删了,但是 retain 不知道要怎么处理了。后来搜了一下:

在工程的 Build Phases -> Compile Sources 下选中不使用ARC的代码,双击,输入:-fno-objc-arc ,就可以了。

 

posted @ 2013-03-21 11:17  王世桢  阅读(358)  评论(0编辑  收藏  举报