怎么在iOS中使用CIFilter生成一个二维码-创新互联

这篇文章给大家介绍怎么在iOS中使用CIFilter生成一个二维码,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

成都创新互联2013年开创至今,是专业互联网技术服务公司,拥有项目成都网站建设、成都网站制作网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元海伦做网站,已为上家服务,为海伦各地企业和个人服务,联系电话:18982081108

1 二维码的生成

生成一个二维码也就是根据提供的数据内容转换成一张二维码图像。从iOS 7开始,我们只需要使用CIFilter中的CIQRCodeGenerator就可以轻易实现。只不过这样生成的二维码图像是一个CIImage对象,如果要在图像视图中显示,需要将其转换为UIImage对象。具体步骤如下:

①、使用名为CIQRCodeGenerator的过滤器创建一个CIFilter对象。

CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"]

②、为CIFilter对象设置inputMessageinputCorrectionLevel参数。

  1. inputMessage:是一个NSData对象,用于表示被编码的数据。对于字符串或者URL,需要使用NSISOLatin1StringEncoding字符串编码将其转换为NSData对象。要注意的是,NSISOLatin1StringEncoding编码对于中文或表情无法生成,需要的话可以使用NSUTF8StringEncoding 替换。

  2. inputCorrectionLevel:是一个NSString对象,通常使用单个字母来指定纠错率,默认值是M。该参数控制输出图像中编码的附加数据量以提供纠错。其纠错率越高,输出的图像越大,同时也允许代码的更大区域被破坏或模糊。通常有LMQH这四种可能的纠正模式,分别代表了7%、15%、25%、30%的错误恢复能力。

③、使用CIFilter对象的outputImage属性获取生成的二维码图像

CIImage *outputImage = filter.outputImage;

④、对生成的二维码图像进行缩放。

由于生成的二维码图像尺寸一般都比较小,为了避免模糊,通常需要对它进行缩放以适应图像视图的大小。其缩放比例一般为图像视图宽度(或高度)与二维码图像宽度(或高度)的比值。

CGFloat scaleX = imageView.bounds.size.width / qrcodeImage.extent.size.width;
CGFloat scaleY = imageView.bounds.size.height / qrcodeImage.extent.size.height;
CIImage *transformedImage = [qrcodeImage imageByApplyingTransform:CGAffineTransformMakeScale(scaleX, scaleY)];

⑤、将二维码图像转换为UIImage对象。

imageView.image = [UIImage imageWithCIImage:transformedImage];

2 应用示例

下面,我们就做一个如下图所示的二维码生成器:

怎么在iOS中使用CIFilter生成一个二维码

其中主要实现的功能有:

  1. 生成和删除二维码。

  2. 通过滑动条对二维码图像进行缩放。

  3. 将二维码保存到相册。

2.1 创建项目

打开Xcode,创建一个新的项目(File\New\Project...),选择iOS一栏下的Application中的Single View Application模版,然后点击Next,填写项目选项。在Product Name中填写QRCodeGeneratorDemo,选择Objective-C语言,点击Next,选择文件位置,并单击Create创建项目。

怎么在iOS中使用CIFilter生成一个二维码

2.2 构建界面

打开Main.storyboard文件,在当前控制器中嵌入导航控制器,并添加标题QR Code Generator

怎么在iOS中使用CIFilter生成一个二维码

在视图控制器中添加文本框、按钮、图像视图等,布局如下:

怎么在iOS中使用CIFilter生成一个二维码

其中各元素及作用:

  1. Text Field:用于输入想要转换为二维码的数据内容,包括文本或URL字符串。

  2. Button:在这里具有双重作用,用于生成和清除二维码。

  3. Image View:用于显示生成的二维码图像。

  4. Slider:用来缩放生成的二维码图像。

打开辅助编辑器,将storyboard中的元素连接到代码中:

怎么在iOS中使用CIFilter生成一个二维码

2.3 添加代码

2.3.1 生成二维码图像

由于使用CIFilter对象生成的二维码图像将是一个CIImage对象,所以需要先在ViewController.m文件的接口部分声明一个CIImage对象的属性:

@property (strong, nonatomic) CIImage *qrcodeImage;

然后在实现部分添加generateQRCodeImage方法及代码:

- (void)generateQRCodeImage
{
  NSData *data = [self.textField.text dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:NO];
  
  // 创建并设置CIFilter对象
  CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
  [filter setValue:data forKey:@"inputMessage"];
  [filter setValue:@"Q" forKey:@"inputCorrectionLevel"];
  
  // 获取生成的CIImage对象
  self.qrcodeImage = filter.outputImage;
  
  // 转换成UIImage对象,并显示在图像视图中
  self.imageView.image = [UIImage imageWithCIImage:self.qrcodeImage];
}

clickButton:方法中调用该方法:

- (IBAction)clickButton:(id)sender
{
  [self generateQRCodeImage];
}

此时,运行程序,在文本框中输入内容,点击按钮就可以看到生成的二维码:

怎么在iOS中使用CIFilter生成一个二维码

仔细的话你会发现这里的二维码比较模糊,这是由于生成的二维码尺寸较小,在imageView中显示时被拉伸导致的。下面我们就通过调整二维码的缩放来解决图像模糊的问题。

修改generateQRCodeImage方法中的代码如下:

- (void)generateQRCodeImage
{
  ...  
  // 获取生成的CIImage对象
  self.qrcodeImage = filter.outputImage;
  
  // 缩放CIImage对象
  CGFloat scaleX = self.imageView.bounds.size.width / self.qrcodeImage.extent.size.width;
  CGFloat scaleY = self.imageView.bounds.size.height / self.qrcodeImage.extent.size.height;
  CIImage *transformedImage = [self.qrcodeImage imageByApplyingTransform:CGAffineTransformMakeScale(scaleX, scaleY)];
  
  // 将调整后的CIImage对象转换成UIImage对象,并显示在图像视图中
  self.imageView.image = [UIImage imageWithCIImage:transformedImage];
}

再次运行,你会看到一张清晰的二维码:

怎么在iOS中使用CIFilter生成一个二维码

2.3.2 删除二维码图像

在这个demo中,按钮具有双重作用:即生成二维码和删除二维码。因此需要在clickButton:方法中先判断二维码图像是否存在:

  1. 如果不存在,点击按钮生成一张二维码图像,按钮的标题变为"Clear"。

  2. 如果存在,点击按钮删除二维码图像,按钮的标题变为"Generate"。

修改clickButton:方法中的代码如下:

- (IBAction)clickButton:(id)sender
{
  if (self.qrcodeImage == nil) {
    [self generateQRCodeImage];
    [self.button setTitle:@"Clear" forState:UIControlStateNormal];
  }
  else {
    [self clearQRCodeImage];
    [self.button setTitle:@"Generate" forState:UIControlStateNormal];
  }
}

下面我们就添加clearQRCodeImage方法并实现它:

- (void)clearQRCodeImage
{
  self.imageView.image = nil;
  self.qrcodeImage = nil;
  self.textField.text = nil;
}

至此,二维码的生成和删除已基本完成,但为了有良好的体验,我们还需要考虑下面的情况:

  1. 在文本框未输入的情况下点击按钮是否生成二维码。

  2. 切换按钮时文本框的响应状态以及键盘出现与消失。

  3. 滑动条的显示和隐藏。

于是,在clickButton:方法中添加下面的代码:

- (IBAction)clickButton:(id)sender
{
  if (self.qrcodeImage == nil) {
    if ([self.textField.text isEqualToString:@""]) {
      return;
    }
    [self generateQRCodeImage];
    
    [self.textField resignFirstResponder];
    [self.button setTitle:@"Clear" forState:UIControlStateNormal];
  }
  else {
    [self clearQRCodeImage];
    
    [self.button setTitle:@"Generate" forState:UIControlStateNormal];
  }
  
  self.textField.enabled = !self.textField.enabled;
  self.slider.hidden = !self.slider.hidden;
}

最后,考虑到程序启动时滑动条不应该显示(滑动条只在生成二维码时出现),还需要在viewDidLoad方法中设置其hidden属性:

- (void)viewDidLoad
{
  [super viewDidLoad];
  
  self.slider.hidden = YES;
}

可以再次运行试下。

2.3.3 缩放二维码图像

缩放显示的二维码主要是通过拖动滑动条缩放image View来完成的。在实现部分找到changeScale:方法,并添加代码下面的代码即可:

- (IBAction)changeScale:(id)sender
{
  self.imageView.transform = CGAffineTransformMakeScale((CGFloat)self.slider.value, (CGFloat)self.slider.value);
}

需要注意的是,self.slider.valuefloat类型,而CGAffineTransformMakeScale方法的参数是CGFloat类型,因此在上面的代码中进行了类型转换。

2.3.4 保存二维码图像

将生成的二维码图片保存到相机胶卷相册主要是使用 UIImageWriteToSavedPhotosAlbum 函数来实现的。其完整声明如下:

复制代码 代码如下:


void UIImageWriteToSavedPhotosAlbum(UIImage *image, id completionTarget, SEL completionSelector, void *contextInfo);

其中各参数及含义:

image:表示要保存到相册的图像。

completionTarget:可选的参数,表示图片保存后,调用完成选择器(completionSelector)的对象。

completionSelector:可选的方法,表示图片保存后,completionTarget对象要调用的方法(即回调方法)。该方法应符合以下签名:

- (void)image:(UIImage *)image
  didFinishSavingWithError:(NSError *)error
         contextInfo:(void *)contextInfo;

contextInfo:可选的参数,用于提供一个上下文信息以通过参数传递给completionSelector。

在这里我们的大致思路是:首先在imageView中添加单击手势,当用户点击二维码图像时会弹出一个提示框询问是否保存,如果用户点击保存按钮,那么就将二维码保存到相册中。下面是具体实现:

打开Main.storyboard文件,从对象库中找到点击手势(Tap Gesture Recognizer),将其添加到视图控制器的Image View上,完成之后会在控制器的顶部看到它:

怎么在iOS中使用CIFilter生成一个二维码

打开辅助编辑器,将其连接到代码中:

怎么在iOS中使用CIFilter生成一个二维码

为了使image View能响应手势操作,需要在viewDidLoad中设置image View的userInteractionEnabled属性:

- (void)viewDidLoad
{
  ...
  self.imageView.userInteractionEnabled = YES;
}

然后在实现部分找到tap:方法,并添加下面的代码:

- (IBAction)tap:(id)sender
{
  // 添加提示框
  UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Save QRCode?" message:@"The QRCode will be saved in Camera Roll album." preferredStyle:UIAlertControllerStyleAlert];
  
  UIAlertAction *saveAction = [UIAlertAction actionWithTitle:@"Save" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    // 保存二维码图像
    [self saveQRCodeImage];
  }];
  UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
  
  [alertController addAction:saveAction];
  [alertController addAction:cancelAction];
  
  [self presentViewController:alertController animated:YES completion:nil];
}

这时编译器会有红色警告提示saveQRCodeImage方法未声明。接下来我们就在实现部分添加该方法来实现二维码的保存:

- (void)saveQRCodeImage
{
  // 绘制图像
  UIGraphicsBeginImageContext(self.imageView.image.size);
  [self.imageView.image drawInRect:self.imageView.bounds];
  self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  
  // 保存图像
  UIImageWriteToSavedPhotosAlbum(self.imageView.image, nil, nil, nil);
}

值得说明的是,这里的self.imageView.image是从CIImage对象转换来的,是保存不到相册的,需要先在图形上下文中绘制一下,生成一个新的图像,然后才能保存。

此时,运行程序,点击生成的二维码图像你会看到下面的效果:

怎么在iOS中使用CIFilter生成一个二维码

但是点击Save按钮时,程序会崩溃,在控制台会看到下面的消息:

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.

这是因为iOS要求应用程序开发者在允许访问相册之前要先获得用户的许可。为此,我们必须在Info.plist文件中添加名为NSPhotoLibraryAddUsageDescription的键,并为其添加相应的描述:

怎么在iOS中使用CIFilter生成一个二维码

问题修复完成!再次运行,点击保存按钮,打开相册应用,你会看到刚才保存的二维码:

怎么在iOS中使用CIFilter生成一个二维码

到目前为止,我们的工作已基本完成,但是为了更完美一些,最好是在点击保存按钮之后能够收到是否保存成功的反馈。所以需要在saveQRCodeImage方法中更改UIImageWriteToSavedPhotosAlbum函数的参数:

- (void)saveQRCodeImage
{
  ...
  
  // 保存图像
  UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}

然后添加image:didFinishSavingWithError:contextInfo:方法,并在该方法内创建alert View来显示二维码的保存状态:

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
  NSString *title;
  NSString *message;
  
  if (!error) {
    title = @"Success!";
    message = @"The QRCode image saved successfully.";
  }
  else {
    title = @"Failed!";
    message = @"The QRCode image saved unsuccessfully, please try again later.";
  }
  
  // 使用alert view显示二维码保存状态
  UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
  UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
  [alert addAction:action];
  
  [self presentViewController:alert animated:YES completion:nil];
}

关于怎么在iOS中使用CIFilter生成一个二维码就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

另外有需要云服务器可以了解下创新互联建站www.cdcxhl.com,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


网站栏目:怎么在iOS中使用CIFilter生成一个二维码-创新互联
链接URL:http://scyanting.com/article/hsjdo.html