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

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

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

怎么办呢?手上有一台 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 ,就可以了。

 

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

你可能感兴趣的:(ios)