iOS开发实用技术之二维码
一. 二维码生成和扫描
1. 二维码概念
二维码, 是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;
2. 二维码的使用场景
● 信息获取(名片、地图、WIFI密码、资料)● 网站跳转(跳转到微博、手机网站、网站)● 广告推送(用户扫码,直接浏览商家推送的视频、音频广告)● 手机电商(用户扫码、手机直接购物下单)● 防伪溯源(用户扫码、即可查看生产地;同时后台可以获取最终消费地)● 优惠促销(用户扫码,下载电子优惠券,抽奖)● 会员管理(用户手机上获取电子会员信息、VIP服务)● 手机支付(扫描商品二维码,通过银行或第三方支付提供的手机端通道完成支付)
3. 二维码生成方式
> 从iOS7开始集成了二维码的生成和读取功能> 此前被广泛使用的zbarsdk目前不支持64位处理器
4. 生成二维码步骤
导入CoreImage框架
#import <CoreImage/CoreImage.h>
通过滤镜CIFilter生成二维码
> 1. 实例化二维码滤镜CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];> 2. 恢复滤镜的默认属性[filter setDefaults];> 3. 将字符串转换成NSDataNSData *data = [@"小码哥" dataUsingEncoding:NSUTF8StringEncoding];> 4. 通过KVC设置滤镜inputMessage数据[filter setValue:data forKey:@"inputMessage"];> 5. 获得滤镜输出的图像CIImage *outputImage = [filter outputImage];> 6. 将CIImage转换成UIImage,并放大显示return [UIImage imageWithCIImage:outputImage scale:20.0 orientation:UIImageOrientationUp];
5. 读取二维码
读取二维码需要导入AVFoundation框架
利用摄像头识别二维码中的内容(模拟器不行)
实例化拍摄设备
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
设置输入设备
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
设置元数据输出
3.1 实例化拍摄元数据输出AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];3.2 设置输出数据代理[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];3.3 设置扫描取景范围(rectOfInterest 都是按照横屏来计算的 所以当竖屏的情况下 x轴和y轴要交换一下)CGFloat screenW = [UIScreen mainScreen].bounds.size.width;CGFloat screenH = [UIScreen mainScreen].bounds.size.height;CGFloat scanW = screenW * 0.6;CGRect scanRect = CGRectMake((screenW - scanW) * 0.5, (screenH - scanW) * 0.5, scanW, scanW);output.rectOfInterest = CGRectMake(scanRect.origin.y / screenH, scanRect.origin.x / screenW, scanRect.size.height / screenH, scanRect.size.width / screenW);3.4 设置扫描区域的边框UIView *scanV = [[UIView alloc] initWithFrame:scanRect];[self.view addSubview:scanV];scanV.layer.borderWidth = 2;scanV.layer.borderColor = [UIColor redColor].CGColor;
添加拍摄会话
4.1 实例化拍摄会话AVCaptureSession *session = [[AVCaptureSession alloc] init];4.2 添加会话输入[session addInput:input];4.3 添加会话输出[session addOutput:output];4.3 设置输出数据类型,需要将元数据输出添加到会话后,才能指定元数据类型,否则会报错[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
视频预览图层
5.1 实例化预览图层AVCaptureVideoPreviewLayer *preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];preview.videoGravity = AVLayerVideoGravityResizeAspectFill;preview.frame = self.view.bounds;5.2 将图层插入当前视图[self.view.layer addSublayer:preview];self.previewLayer = preview;
启动会话
[_session startRunning];
二. 内存分析
主要目的就是为了检测程序是否存在内存泄露
1. 静态内存分析(Analyze)
作用: > 逻辑错误:访问未初始化的变量, 野指针等;> 声明错误:从未使用过的对象;> 内存管理错误:如内存泄漏等;
分析方法:> 静态内存分析是不运行程序,直接对代码进行分析.> 根据代码的上下文的语法结构,来分析是否有内存泄露
缺点:> 不一定准确,但是如果发现有提示,那么去结合上下文看一下,这里的代码是否有问题场景演练:> MRC 下桥接 - Foundation 和 CoreFoundation框架的数据类型转换> ARC 下桥接 - Foundation 和 CoreFoundation框架的数据类型转换
2. 内存分配
作用:> 查看是内存的分配情况> 查看内存是否有释放
场景演示:> UIImage 的两种创建方法测试> imageNamed:> imageWithContentOfFile:
3. 动态内存分析
作用:> 检测程序在运行过程中是否存在内存泄露
场景演示:> 模拟循环引用, 测试内存泄露
三. 通讯录获取
1. 通讯录应用场景
1. 最常见的是一些即时通讯APP, 关联联系人;
2. 通讯录获取方案
AddressBookUI.framework 框架
> 提供了联系人列表界面、联系人详情界面、添加联系人界面等> 一般用于选择联系人
AddressBook.framework 框架
> 纯C语言的API,仅仅是获得联系人数据> 没有提供UI界面展示,需要自己搭建联系人展示界面> 里面的数据类型大部分基于Core Foundation框架,使用起来极其蛋疼
ContactsUI.framework (iOS9.0最新框架)
> 方案1/方案2 的替代品
第三方框架 RHAddressBook
> 对AddressBook.framework框架的封装
3. 获取通讯录-AddressBookUI
1. 实现步骤
- 创建选择联系人的控制器
- 设置代理(用来接收用户选择的联系人信息)
- 弹出联系人控制器
- 实现代理
- 在对应的代理方法中获取联系人信息
2. 具体代码实现
创建选择联系人的控制器
ABPeoplePickerNavigationController *ppnc = [[ABPeoplePickerNavigationController alloc] init];
设置代理(用来接收用户选择的联系人信息)
ppnc.peoplePickerDelegate = self;
弹出联系人控制器
[self presentViewController:ppnc animated:YES completion:nil];
实现代理
// 1. 选中某个联系人时调用- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person{}// 2. 选中某个联系人某个属性时调用- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{}// 3. 点击了取消按钮会执行该方法- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{}
在对应的代理方法中获取联系人信息
// 1. 获取选中联系人的姓名(姓lastname和名firstname)CFStringRef firstname = ABRecordCopyValue(person, kABPersonFirstNameProperty);CFStringRef lastname = ABRecordCopyValue(person, kABPersonLastNameProperty);NSString *firstName = (__bridge_transfer NSString *)(firstname);NSString *lastName = (__bridge_transfer NSString *)(lastname);NSLog(@"%@ %@", firstName, lastName);// 2. 获取联系人的电话号码ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);CFIndex count = ABMultiValueGetCount(phones);for (CFIndex i = 0; i < count; i++) {NSString *phoneLabel = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex(phones, i);NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, i);NSLog(@"label : %@ value : %@", phoneLabel, phoneValue);}// 3. 释放不再使用的对象CFRelease(phones);
4. 获取通讯录-AddressBook
1. 实现步骤
- 请求授权
- 判断授权状态, 如果已授权, 则继续; 未授权, 则提示用户, 并返回;
- 创建通讯录对象
- 从通信录对象中, 获取所有的联系人
- 遍历所有的联系人
- 释放不再使用的对象
2. 代码实现
请求授权
// 1.获取授权的状态ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();// 2.判断授权状态,如果是未决定状态,才需要请求if (status == kABAuthorizationStatusNotDetermined) {// 2.1.创建通信录对象ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);// 2.2.请求授权ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {if (granted) {NSLog(@"授权成功");} else {NSLog(@"授权失败");}});}
判断授权状态, 如果已授权, 则继续; 未授权, 则提示用户, 并返回;
// 1.获取授权的状态ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();// 2.如果用户已经授权if (status != kABAuthorizationStatusAuthorized) return;
创建通讯录对象
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
从通信录对象中, 获取所有的联系人
CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
遍历所有的联系人
// 5.遍历所有的联系人(每一个联系人都是一条记录)CFIndex peopleCount = CFArrayGetCount(peopleArray);for (CFIndex i = 0; i < peopleCount; i++) {// 6.获取到联系人ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);// 7.获取姓名NSString *lastname = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);NSLog(@"%@ %@", lastname, firstName);}
释放不再使用的对象
CFRelease(peopleArray);CFRelease(addressBook);
5. 获取通讯录-第三方框架RHAddressBook
1. 实现步骤
- 集成框架
- 使用框架获取所有联系人信息
2. 具体实现
集成框架
> 1. 将整个工程拖入项目> 2. 添加工程依赖Build Phases -> Target Dependencies -> + > 3. 添加链接项Build Settings -> Other Linker Flags -> -ObjC -all_load> 4. 导入框架头文件#import <RHAddressBook/AddressBoook.h>
使用框架获取所有联系人信息
> 请求授权 // 1. 获取授权状态RHAuthorizationStatus status = [RHAddressBook authorizationStatus];if (status == RHAuthorizationStatusNotDetermined){// 2. 创建通讯录对象RHAddressBook *addressBook = [[RHAddressBook alloc] init];// 3. 请求授权[addressBook requestAuthorizationWithCompletion:^(bool granted, NSError *error) {if (granted){NSLog(@"授权成功!");}else{NSLog(@"授权失败");}}];}> 获取联系人信息// 1. 判断当前授权状态RHAuthorizationStatus status = [RHAddressBook authorizationStatus];if (status != RHAuthorizationStatusAuthorized) {return;}// 2. 创建通讯录对象RHAddressBook *addressBook = [[RHAddressBook alloc] init];// 3. 获取所有联系人NSArray *peoples = addressBook.people;// 4. 遍历所有联系人for (RHPerson *person in peoples){// 4.1 获取联系人姓名NSString *firstName = person.firstName;NSString *lastName = person.lastName;NSLog(@"%@---%@", firstName, lastName);// 4.2 获取联系人电话RHMultiStringValue *mv = person.phoneNumbers;for (int i = 0; i < mv.count; i ++){// 4.2.1 获取电话标签NSString *label = [mv labelAtIndex:i];// 4.2.2 获取电话号码NSString *phone = [mv valueAtIndex:i];NSLog(@"%@--%@", label, phone);}}
四. 换肤
1. 换肤的应用场景?
一般应用在某些APP , 在节假日更换主题, 或者切换白天或者夜间模式时使用.
2. 换肤的实现方案
1. 方案1
1. 将图片以及颜色按照主题命名,使用虚拟文件夹, 直接在各个控制器针对不同主题单独设置缺点 : 1. 扩展性差, 增加一个主题非常复杂2. 代码分散, 可维护性差3. 使用虚拟文件夹保存资源, 容易与其他资源容易产生冲突
2. 方案2
2. 抽取公共的切换主题类, 使用物理文件夹, 并将图片按照应用场景命名, 不按照主题命名, 但是按照主题划分文件夹
优点:1. 扩展性好, 增加主题简单2. 功能代码集中, 方便维护3. 资源包单独管理, 不会产生资源冲突
演练步骤
1. 实现基本的换肤功能
2. 使用用户偏好记录当前皮肤主题
3. 抽取公共的皮肤管理类, 简化控制器逻辑
4. 验证多处加载主题情景
5. 加载主题文字颜色功能实现
五. 硬件信息的获取
1. 应用场景
例如QQ空间APP 发说说时, 出现的什么什么型号的手机;迅雷APP 下载文件时提示剩余空间,已用空间
2. 实现方案
直接通过第三方工具类(UIDevice的分类), 进行获取对应信息
原因: 自己写起来比较复杂, 很多C语言的东西, 而且没有必要;
3. 框架完善
框架存在问题: 该第三方框架从2012年就停止更新了,意味着12年之后的手机型号都没有, 需要手动添加, 修改框架
解决方案: 找到对应的实现方法, 使用真机进行测试, 手动新增手机型号
转载于:https://www.cnblogs.com/Xfsrn/p/5001479.html
iOS开发实用技术之二维码相关推荐
- iOS开发-定制多样式二维码
iOS开发-定制多样式二维码 二维码/条形码是按照某种特定的几何图形按一定规律在平台(一维/二维方向上)分布的黑白相间的图形纪录符号信息.使用若干个与二进制对应的几何形体来表示文字数值信息. 最常 ...
- iOS开发——高级篇——二维码的生产和读取
一.二维码的生成 从iOS7开始集成了二维码的生成和读取功能 此前被广泛使用的zbarsdk目前不支持64位处理器 生成二维码的步骤: 导入CoreImage框架 通过滤镜CIFilter生成二维码 ...
- iOS开发 - 微信扫描二维码登录网页的原理
转自: http://daily.zhihu.com/story/3783725 我个人开发过程一般是和产品说,『你们提业务要求.交互方式.性能要求等就好,技术方案我们会综合开发时间.系统架构等因素考 ...
- IOS抖音短视频APP开发关于扫描二维码,并根据文本生成二维码
IOS抖音短视频APP开发关于扫描二维码,(根据光线强弱显示隐藏闪光灯)并根据文本生成二维码. WeakSelf; //IOS抖音短视频APP开发构建扫描样式视图 _scanView = [[WSLS ...
- 抖音短视频APP开发如何生成二维码?
授权转载自云豹网络科技的CSDN博客 原文链接:https://blog.csdn.net/yb1314111/article/details/101283985 IOS抖音短视频APP开发关于扫描二 ...
- flutter开发实战-flutter二维码条形码扫一扫功能实现
flutter开发实战-flutter二维码条形码扫一扫功能实现 flutter开发实战-flutter二维码扫一扫功能实现,要使用到摄像头的原生的功能,使用的是插件:scan 效果图如下 一.扫一扫 ...
- 微信小程序 - 二维码数据解析,如何扫码进入开发版测试二维码数据
1.生成二维码 在小程序开发中,经常需要用到通过分享小程序二维码,进行扫码进入小程序. 官方文档 生成小程序二维码接口,这个生成接口可以放置服务器使用. page:是扫码之后需要打开的小程序页面 sc ...
- 微信网页开发-长按二维码无法识别问题解决
微信网页开发-长按二维码无法识别问题解决 参考文章: (1)微信网页开发-长按二维码无法识别问题解决 (2)https://www.cnblogs.com/Tylerrrkd/p/9153949.ht ...
- 分享:Java 开发精美艺术二维码
博客地址:https://ainyi.com/58 Java 开发精美艺术二维码 看到网络上各种各样的二维码层出不穷,好像很炫酷的样子,一时兴起,我也要制作这种炫酷二维码效果 例如: 根据以往例子 根 ...
最新文章
- java float x=26f_东软java笔试题
- docker快速入门01——docker安装与简单应用
- java 编写代码_Java 7:如何编写非常快速的Java代码
- jquery $.fn $.fx $.extend
- 零基础学python用哪本书好-零基础想要学习Python编程 ,不知道看哪本书?
- SQL Server 函数的使用(转换函数)
- Python多人聊天室
- android -------- 打开本地浏览器或指定浏览器加载,打电话,打开第三方app
- linux系统有界面么,linux系统界面详情介绍
- token与refresh token
- 省钱兄同城跑腿小程序源码uniapp前端模版源码(小程序+APP+H5)
- windows2003 升级sp1,sp2 产品密匙无效
- LANDESK8.8版本操作说明书之服务器安装
- HA 高可用软件系统保养指南
- linux系统tar命令慢,Linux系统下tar命令的使用技巧
- GreenPlum-6 最简步骤安装
- Leetcode 1218. 最长定差子序列(DAY 47) ---- 动态规划学习期(昨天又没有看书捏 懒狗biss)
- go项目杀进程并重启shell
- 【日常】C盘及电脑内存清理
- Paper:LIME之《Why Should I Trust You? Explaining the Predictions of Any Classifier为什么要相信你?解释任何分类器的预测》翻