有一个开锁的功能,具体的需求就类似于微信的“摇一摇”功能:摇动手机,手机震动,手机上的锁的图片摇动一下,然后发送开锁指令。需求简单,但用到了许多方面的知识。

1.摇一摇

  相对这是最简单的功能了。

  在viewController的viewDidLoad中加这两句代码,或者在你想开始监听“摇一摇”这个功能的时候,添加这两句代码:

         // 允许摇一摇功能
UIApplication.shared.applicationSupportsShakeToEdit = true
// 并让自己成为第一响应者
self.becomeFirstResponder()

  其中的 self 自然指的是需要监听“摇一摇”的视图控制器了。

  然后,重写下面三个方法,就可以了:

 // MARK: 摇一摇相关方法
override func motionBegan(_ motion: UIEventSubtype, with event: UIEvent?) { super.motionBegan(motion, with: event) print("开始摇动")
} override func motionCancelled(_ motion: UIEventSubtype, with event: UIEvent?) { super.motionCancelled(motion, with: event) print("取消摇动")
} override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) { super.motionEnded(motion, with: event) // 判断是否摇动结束
if event?.subtype == UIEventSubtype.motionShake { print("摇动结束")
}
}

  实测:

  1.“开始摇动”方法最为灵敏,在“摇一摇”动作开始的一瞬间就会调用;

  2.“摇动结束”方法不一定灵敏,时灵时不灵,但是如果“开始摇动”方法已调用,那必须调用“摇动结束”方法后才可以调用下一次“开始摇动”方法。也就是说,方法的调用顺序是下面这样的(每个方法之调用一次):

  “开始摇动” -> “摇动结束” -> (第二次摇动)“开始摇动” -> ···

  3.“取消摇动”是在这样的情况下会被调用:当系统调用了“开始摇动”过后,并没有监测到摇动已经结束,也就是没有调用“摇动结束”的方法;但不能无限在这儿卡下去,系统就设置了几秒钟为超时时间。若过了这几秒仍然没有监听到调用“摇动结束”的时机,那么就会调用“取消摇动”方法并开启“开始摇动”的响应链。

  关闭自然就是关了监测就可以了:

 UIApplication.shared.applicationSupportsShakeToEdit = false

2.手机震动

  这个功能也比较简单,直接调用系统的震动函数就可以了。两步。

2.1 导入FrameWork

  如下位置,导入系统框架AudioToolbox.framework:

  这个框架的好多函数,负责手机震动与声音等等。

2.2 震动函数

  就一句话,参数也不用变,自动提供一个大概半秒到一秒的震动(复杂的震动也可以通过这个框架自定义,这里只提供一次性的短的震动的函数):

         // 震动
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)

3.摇动动画

  这个算是这里面最难实现的功能了。涉及到CoreAnimation框架下的CABasicAnimation这个类型。 

         // 开始动画
let momAnimation = CABasicAnimation.init(keyPath: "transform.rotation.z")
// 从哪里开始
momAnimation.fromValue = NSNumber.init(value: -0.3)
momAnimation.toValue = NSNumber.init(value: 0.3)
// 动画持续时间(单次)
momAnimation.duration = 0.2
// 重复次数
momAnimation.repeatCount = // 这是重复时间,也就是无视重复次数,按照动画单次持续时间无限循环,直到到了repeatDuration规定的时间。与上面都是动画重复,一个规定次数一个规定时间,并且repeatDuration优先级高
// momAnimation.repeatDuration = 0.6 // 动画结束时是否执行逆动画
momAnimation.autoreverses = true
momAnimation.delegate = self
self.lockImageView.layer.add(momAnimation, forKey: "animateLayer") DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.6) { self.lockImageView.layer.removeAllAnimations()
}

  唯一可能需要解释的就是keyPath中的x、y、z三轴究竟是什么。它是手机的三个轴线。x表示水平,也就是左右方向;y表示竖直,也就是上下方向;z表示垂直手机屏幕的方向。具体最好自己试一试,非常直观。

  补充一些其他方面的功能。

4.生成二维码

  利用系统的CoreImage框架下的CIFilter类型,将字符串转换成二维码图片。需要一个参数,也就是想战士的信息 字符串:String

             // 1.创建过滤器
let filter = CIFilter.init(name: "CIQRCodeGenerator")
// 2.恢复默认
filter?.setDefaults()
// 3.给过滤器添加数据
filter?.setValue(String.data(using: String.Encoding.utf8), forKeyPath: "inputMessage")
// 4.获取输出的二维码
8        UIImage.init(ciImage: filter?.outputImage)

  其中,filter?.outputImage返回的是CIImage类型的图片,需要转化成UIImage类型才可赋值到UIImageView上。

  但是这样其实存在问题,那就是生成的二维码过于模糊。于是需要这样的方式进行处理:

 /**
* 根据CIImage生成指定大小的UIImage
*
* @param image CIImage
* @param size 图片宽度
*/
+ (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat)size { CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
// 1.创建bitmap;
size_t width = CGRectGetWidth(extent) * scale;
size_t height = CGRectGetHeight(extent) * scale;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, , , cs, (CGBitmapInfo)kCGImageAlphaNone);
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
CGContextScaleCTM(bitmapRef, scale, scale);
CGContextDrawImage(bitmapRef, extent, bitmapImage);
// 2.保存bitmap到图片
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
return [UIImage imageWithCGImage:scaledImage];
}

  参数与返回值类型都介绍的很详细。这样就能获得一张高清晰度的二维码UIImage了。

5.发送短信

  有两种实现方式。

5.1 跳转到系统的发送短信的界面发送短信 

         UIApplication.shared.openURL("sms://10000")

  类似于跳转拨打电话、打开网页等等,区别在于“冒号双斜线”之前的代号。

  不过区别很明显:能提供给外界的信息很少,只有一个电话号码。不能提供短信群发、短信内容等功能;不能再发送结束后返回App。

5.2 使用系统内部框架

  据说有审核被拒的危险。不过目前我没有遇到,我想苹果官方提供的框架应该也不至于太那啥。

5.2.1 添加MessageUI.framework

  不多描述。添加苹果官方提供的发短信的框架。

5.2.2 导入头文件

  导入头文件:

 // 发送短信
#import <MessageUI/MessageUI.h>

  注意不要导错。

5.2.3 发送短信

  遵守协议MFMessageComposeViewControllerDelegate,之后在需要发送短信的地方实现代码:

     func sharedButtonDidPress(sender: UIButton) {

         // 判断能否发短信(模拟器不可以发短信)
if MFMessageComposeViewController.canSendText() { // 创建发送短信控制器
let controller = MFMessageComposeViewController.init()
controller.messageComposeDelegate = self
controller.recipients = [] // 短信接收者
controller.body = self.dataArr[][] // 短信内容
self.present(controller, animated: true, completion: nil)
}
else { print("模拟器不可以发短信")
}
}

  实现协议内容:

     // MRAK: <MFMessageComposeViewControllerDelegate>
/// 协议方法,在信息界面处理完信息结果是调用(比如点击发送、取消发送、发送失败)
///
/// - Parameters:
/// - controller: 信息控制器
/// - result: 返回的信息发送成功与否
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { // 发送完消息就回原程序
self.dismiss(animated: true, completion: nil) switch result {
case MessageComposeResult.sent:
HTTPRequest().showHUDMessage("发送成功")
break
case MessageComposeResult.failed:
HTTPRequest().showHUDMessage("发送失败")
break
case MessageComposeResult.cancelled:
HTTPRequest().showHUDMessage("取消发送")
break
}
}

6.播放网络音频

  这个没啥好解释的,就是给你个URL你放歌呗。URL一般是这个格式的:

  后面的 .mp3 标注了格式。就这样。

  接下来先来介绍一下 AVAudioPlayer 这个播放器。

6.1  AVAudioPlayer

  6.1.1 简单的使用

  AVAudioPlayer 是 AVFoudation 框架中的一个类,主要功能就是播放音频。

  首先,我们需要先导入 AVFoudation 框架:

 #import <AVFoundation/AVFoundation.h>

  然后初始化 AVAudioPlayer 实例。这里有两种方法初始化:

    /** 0.NSError
这里可以传一个 NSError 类型的指针地址进去。如果解析音频过程中出现了错误,那么这个 NSError * 类型的实例指针就会指向一个 NSError 类型的对象,从而实现多返回值的效果。
这里利用的是指针技术。
*/
NSError *error = nil; /** 1.通过 NSData 初始化 AVAudioPlayer */
AVAudioPlayer *player1 = [[AVAudioPlayer alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://wvoice.spriteapp.cn/voice/2017/0119/5880af3c1ea81.mp3"]] error:&error]; /**
2.通过 NSURL 初始化 AVAudioPlayer
这个URL只能是本地的文件,例如
*/
AVAudioPlayer *player2 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:@"123.mp3"] error:&error];

  两种初始化方式是这样的。第二种通过本地文件生成的 NSURL 初始化 AVAudioPlayer 没什么好说的,主要讲一下第一种方式。我在代码中直接使用 NSData的 dataWithContentsOfURL: 方法请求网络数据并且赋值给 player1。这样做是有问题的。问题很明显,网络请求是耗时操作,应该放在子线程中进行。我们先不考虑线程问题,先看下能否实现我们的需求。

  我通过第一种方式初始化了player,那么怎么让它播放暂停呢?

     /** 1.播放 */
[player1 play]; /** 2.暂停 */
[player1 pause]; /** 3.停止 */
[player1 stop];

  就是字面意思。可以看下官方介绍,不过其实绕来绕去也还就是 播放 暂停 停止。

  这样,最基本的功能我们就实现了。

  但是,这样虽然可以播放了(先不考虑先成问题),但是控制台却在不停的打印这条消息:

 [aqme] : AQDefaultDevice (): skipping input stream   0x0

  这其实是Xcode8之后出现的问题。原因不明,解决方法:

  解决。

  6.1.2 AVAudioPlayer的一些属性和代理方法

  值得留意的属性有这些:

 // 1.音量
player1.volume =0.8;//0.0-1.0之间 // 2.循环次数
player1.numberOfLoops =;//默认只播放一次 // 3.播放位置
player1.currentTime =15.0;//可以指定从任意位置开始播放 // 4.声道数
NSUInteger channels = player1.numberOfChannels; // 只读属性 // 5.持续时间
NSTimeInterval duration = player1.duration; // 获取持续时间 // 6.仪表计数
player1.meteringEnabled =YES; // 开启仪表计数功能
[player1 updateMeters]; // 更新仪表计数

  需要遵守的协议是这个:<AVAudioPlayerDelegate>

  协议方法:

 #pragma mark - <AVAudioPlayerDelegate>
/** 1.播放结束 */
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { NSLog(@"播放音频结束了");
} /** 2.解析音频出错 */
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error { NSLog(@"解析音频出错");
} /** 3.播放(开始)被中断
原因:例如接电话等导致播放被中断
*/
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player { NSLog(@"播放音频中断");
} /** 4.播放中断结束
*/
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player { [self.player play];
}

  其中3和4被废弃了:

6.2 AVPlayer



iOS几个功能:1.摇一摇;2.震动;3.简单的摇动动画;4.生成二维码图片;5.发送短信;6.播放网络音频等的更多相关文章

  1. iOS摇一摇功能、震动功能、简单的摇动动画、生成二维码图片与发送短信等几个功能

    有一个开锁的功能,具体的需求就类似于微信的"摇一摇"功能:摇动手机,手机震动,手机上的锁的图片摇动一下,然后发送开锁指令.需求简单,但用到了许多方面的知识. 1.摇一摇 相对这是最 ...

  2. iOS 根据url生成二维码贴到底图上

    根据url 生成指定尺寸的二维码图片 UIImage * createBinaryCodeImg(const char * url ,CGFloat size) { //create binary c ...

  3. iOS开发——生成二维码——工具类

    啥也不说,直接上源码,拷过去就能用.生成二维码的工具类使用方法在ProduceQRCode.h里有示例说明 分别将下面的ProduceQRCode.h和ProduceQRCode.m对应的代码考到自己 ...

  4. java生成二维码扫码网页自动登录功能

    找了很多资料,七七八八都试了一遍,最终写出来了这个功能. 菜鸟一枚,此文只为做笔记. 简单的一个生成二维码,通过网页确认登录,实现二维码页面跳转到主页面. 有三个servlet: CodeServle ...

  5. IOS开发技巧快速生成二维码

    随着移动互联网的发展,二维码应用非常普遍,各大商场,饭店,水果店 基本都有二维码的身影,那么ios中怎么生成二维码呢? 下面的的程序演示了快速生成二维码的方法: 在ios里面要生成二维码,需要借助一个 ...

  6. iOS开发之生成二维码

    一.二维码的生成 从iOS7开始集成了二维码的生成和读取功能 此前被广泛使用的zbarsdk目前不支持64位处理器   1.二维码的内容(传统的条形码只能放数字) 纯文本 名片 URL   2.生成二 ...

  7. iOS开发——高级技术&生成二维码

      生成二维码 因为项目里需要新增个功能,该功能用到了二维码技术.于是我便查阅了资料,先学习了二维码的生成. 我们使用libqrencode库来生成二维码.下载地址http://download.cs ...

  8. iOS中 扫描二维码/生成二维码详解 韩俊强的博客

    最近大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 指示根视图: se ...

  9. iOS - 原生的CIFilter生成二维码和条形码

    使用CIFilter可以不引入任何第三方库,就可以生成想要的二维码和条形码,今天简单的介绍一下使用CIFilter生成二维码和条形码.系统CIFilter生成的二维码和条形码的大小有时并不能满足需求, ...

随机推荐

  1. N 秒打开一个新窗口

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  2. c语言技术课第一次作业

    读邹欣老师博客关于师生关系有感 1)大学和高中最大的不同是没有人天天看着你,请看大学理想的师生关系是?有何感想? 答:    在邹欣老师博客中我看到邹欣老师列举了很多师生关系的类型,把这种关系比喻成很 ...

  3. python进行数据清理之pandas中的drop用法

    好久好久没有更新博客了,之前自学的估计也都忘记差不多了.由于毕业选择从事的行业与自己的兴趣爱好完全两条路,心情也难过了很久,既然入职了就要好好干,仍要保持自己的兴趣,利用业余时间重拾之前的乐趣. 从基 ...

  4. tp5和gateworer集成

    第一步:安装thinkpph程序包 第二步:切换到根目录,使用composer require workerman/gateway-worker 安装Linux版本的gateway.(前提是你服务器安 ...

  5. 常见gcc编译问题解决方法集

    除非明确说明,本文内容仅针对x86/x86_64的Linux开发环境,有朋友说baidu不到,开个贴记录一下(加粗字体是关键词):用"-Wl,-Bstatic"指定链接静态库,使用 ...

  6. 设置UITextField键盘上return key不可点击

    今天在做搜索栏时候,发现系统软键盘有下角的“搜索”按钮在输入框无论有没有文字的情况下都是可以点击的状态,记得其他软件在无文字的状态下是不可点击的状态,起初还以为要对textfield的内容做一个判断, ...

  7. Linux 基础教程 26-基础网络配置

    基本配置     要想上网,计算机需要有专门的网络连接设备,即网络接口卡或者网卡.网卡按照与计算机主机的连接方式可以分为PCI网卡.ISA网卡及无线网卡(USB网卡)等.在Linux中可以使用命令ls ...

  8. Java Float类型 减法运算时精度丢失问题

    package test1; public class Test2 { /*** @param args*/public static void main(String[] args) {   Flo ...

  9. 自我介绍和Github初次使用心得

    姓名:许洪科 班级:网络工程142 学号:1413042047 爱好:足球 编写过的程序:0 编写过的代码:几乎为0(大多数为网上直接复制的) Github注册过程:. 1:进入Github网站后点击 ...

  10. 一个例子教你理解java回调机制

    网上很多例子都写的很难理解,笔者刚开始都已经弄晕菜了. 这个例子,应该是再简单,再简洁不过的了,例子目的是测试某个方法的执行时间.这里就写三个java类,一个接口,一个实现,还有一个用于测试时间的类. ...