//加速器的使用
@implementation HMViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.获得单例对象(过期:不再更新,并不一定代表不能用)
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
// 2.设置代理
accelerometer.delegate = self;
// 3.设置采样间隔(每隔多少秒采样一次数据)
accelerometer.updateInterval = 1 / 30.0;
}
#pragma mark - UIAccelerometerDelegate
/**
* 当采样到加速计数据时,就会调用一次(调用频率一般比较高)
*/
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
// 1.累加速度
// v = a * t = a1 + a2 + a3 + ...... + at
_velocity.x += acceleration.x;
_velocity.y -= acceleration.y;
// 2.累加位移
// s = v * t = v1 + v2 + v3 + ...... + vt
self.ball.x += _velocity.x;
self.ball.y += _velocity.y;
// 3.边界判断
if (self.ball.x <= 0) { // x超出屏幕左边
self.ball.x = 0;
// 速度取反,削弱速度
_velocity.x *= -0.5;
}
if (self.ball.maxX >= self.view.width) { // x超出屏幕右边
self.ball.maxX = self.view.width;
// 速度取反,削弱速度
_velocity.x *= -0.5;
}
if (self.ball.y <= 0) { // y超出屏幕上边
self.ball.y = 0;
// 速度取反,削弱速度
_velocity.y *= -0.5;
}
if (self.ball.maxY >= self.view.height) { // y超出屏幕下边
self.ball.maxY = self.view.height;
// 速度取反,削弱速度
_velocity.y *= -0.5;
}
}
@end
//距离传感器的使用
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// [UIApplication sharedApplication].proximitySensingEnabled = YES;
[UIDevice currentDevice].proximityMonitoringEnabled = YES;
// 监听距离改变
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(proximityStateDidChange:) name:UIDeviceProximityStateDidChangeNotification object:nil];
}
- (void)proximityStateDidChange:(NSNotification *)note
{
if ([UIDevice currentDevice].proximityState) {
NSLog(@"有物体靠近");
}else
{
NSLog(@"物理离开");
}
}
@end
//蓝牙连接代码
/*
> 讲解相片选择器
*先不设置代理,创建后直接运行
*从选择相片后需要关闭控制器引出代理
*实现代理方法展示数据
*PPT讲解蓝牙连接(不是所有应用都可以用蓝牙传输东西,必须相同应用事先写好如何处理. 苹果蓝牙传输非常满, 而且传输过程中没有进度)
*在storyboard中添加按钮, 点击按钮后创建对端选择控制器, 设置代理,显示视图控制器
*在代理方法中打印peerID, 讲解session用途查看头文件引出利用传递数据
*定义属性保存session , 在storyboard中添加按钮监听按钮点击利用session传递图片
*讲解传递数据方法两种模式区别
*设置数据处理者, 讲解如何找到数据处理方法,在数据处理方法中打印LOG运行验证
*将接收到的数据转换为图片后现实在界面上
*总结蓝牙传输
*/
#import "CZViewController.h"
#import <GameKit/GameKit.h>
@interface CZViewController ()<UIImagePickerControllerDelegate, UINavigationControllerDelegate, GKPeerPickerControllerDelegate>
/**
* 现实相片
*/
- (IBAction)selectPhoto;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
/**
* 蓝牙连接
*/
- (IBAction)connectBtnClick;
/**
* 会话对象
*/
@property (nonatomic, strong)GKSession *session;
/**
* 发送相片
*/
- (IBAction)sendPhoto;
@end
@implementation CZViewController
#pragma mark 选择照片
/*
照片源类型
UIImagePickerControllerSourceTypeCamera 照相机
UIImagePickerControllerSourceTypePhotoLibrary 照片库(通过同步存放的,用户不能删除)
UIImagePickerControllerSourceTypeSavedPhotosAlbum 保存的照片(通过拍照或者截屏保存的,用户可以删除)
*/
- (IBAction)selectPhoto
{
// 1.判断照片源是否可用
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
// 1.1实例化控制器
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
// 1.2设置照片源
[picker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
// 1.3设置允许修改
picker.allowsEditing = YES;
// 1.4设置代理
picker.delegate = self;
// 1.5显示控制器
[self presentViewController:picker animated:YES completion:^{
}];
}else
{
// 2.照片源不可用
NSLog(@"照片源不可用");
}
}
#pragma mark - imagePicker代理方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// NSLog(@"%@", info);
// 获取相片
UIImage *image = info[@"UIImagePickerControllerEditedImage"];
// 设置相片
self.imageView.image = image;
// 关闭相片选择器
[self dismissViewControllerAnimated:YES completion:^{
}];
}
#pragma mark - 蓝牙连接
- (IBAction)connectBtnClick
{
// 1.创建对端选择控制器
GKPeerPickerController *picker = [[GKPeerPickerController alloc] init];
// 2.设置代理
picker.delegate = self;
// 3.显示试图控制器
[picker show];
}
#pragma mark - GKPeerPickerControllerDelegate
// 完成对端连接
// GKSession对象用于表现两个蓝牙设备之间连接的一个会话,你也可以使用它在两个设备之间发送和接收数据。
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
NSLog(@"连接成功 %@", peerID);
// 保存会话
self.session = session;
// 设置数据处理对象,类似于delegate
[self.session setDataReceiveHandler:self withContext:nil];
// 关闭对端选择控制器
[picker dismiss];
}
// 取消对端选择控制器
- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
{
NSLog(@"取消蓝牙选择器");
}
// 发送相片
- (IBAction)sendPhoto {
NSData *imageData = UIImagePNGRepresentation(self.imageView.image);
// 利用session发送相片
// self.session sendData:<#(NSData *)#> toPeers:<#(NSArray *)#> withDataMode:<#(GKSendDataMode)#> error:<#(NSError *__autoreleasing *)#>
/*
TCP协议、UDP协议
1. 要发送的数据(二进制的)
2. 数据发送模式
GKSendDataReliable :确保数据发送成功(TCP协议,对网络压力大)
GKSendDataUnReliable :只管发送不管成功(UDP协议,对数据完整性要求不高,对网络压力下)
*/
[self.session sendDataToAllPeers:imageData withDataMode:GKSendDataReliable error:nil];
}
// 数据接受处理方法,此方法需要从文档中粘贴出来,没有智能提示
- (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
NSLog(@"接收到数据");
// 将NSData转换成UIImage
UIImage *image = [UIImage imageWithData:data];
self.imageView.image = image;
}
/*
关于蓝牙的数据传输
1. 一次性传送,没有中间方法,所谓中间方法值得是,传输进度比例
对于用户而言,选择了传输,就需要等待传输完成,或者传输以失败告终
这就意味着,在实际开发过程中,最好不要用蓝牙传输太大的文件
在实际应用中,蓝牙通常用于传递游戏数据模型,用于联机对战,譬如点对点的棋牌类游戏。
*/
@end
//加速器的使用方式
@implementation HMViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.创建motion管理者
self.mgr = [[CMMotionManager alloc] init];
// 2.判断加速计是否可用
if (self.mgr.isAccelerometerAvailable) {
[self pull];
} else {
NSLog(@"---加速计不可用-----");
}
}
/**
* ******* pull *******
*/
- (void)pull
{
[self.mgr startAccelerometerUpdates];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CMAcceleration acceleration = self.mgr.accelerometerData.acceleration;
NSLog(@"%f %f %f", acceleration.x, acceleration.y, acceleration.z);
}
/**
* ******* push *******
*/
- (void)push
{
// 3.设置采样间隔
self.mgr.accelerometerUpdateInterval = 1 / 30.0;
// 4.开始采样(采集加速度数据)
[self.mgr startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
// 如果在block中执行较好时的操作,queue最好不是主队列
// 如果在block中要刷新UI界面,queue最好是主队列
NSLog(@"%f %f %f", accelerometerData.acceleration.x, accelerometerData.acceleration.y, accelerometerData.acceleration.z);
}];
}
@end
//传统加速器的使用
/*
> 加速计
*PPT介绍加速计, 加速计属于传感器的范畴...
*新建项目讲解加速计的传统使用
*查看Accelerometer头文件, 讲解Accelerometer头文件中的属性引出为什么过时了还那么多人用(简单, 查看头文件)
*从代理方法参数引出定义属性保存小球加速度(CGPoint), 并在代理方法中设置小球的位置
*Vt = V0 + a * t (最终速度 = 初始速度 + 加速度 * 时间)
Vt = V0 + g * t (加速度是恒定的9.8)
Vt = V0 + g1 + g2 + g3 … (时间和加速度都是恒定的)
Vt = V0 + a1 + a2 + a3 … (手机中时间是恒定的, 加速度不是恒定的)
*从小球移除频幕看不到引出画图讲解边界检测(碰撞检测)
*从小球会贴在边框出不来引出画图讲解如何解决(移动小球的位置到边界再加速度)
*讲解为什么用两个if 不用else if, 小球在四个角的情况
*/
#import "CZViewController.h"
@interface CZViewController ()<UIAccelerometerDelegate>
/**
* 小球
*/
@property (nonatomic, weak)UIImageView *ballIv;
/**
* 保存x y方向加速度
*/
@property (nonatomic, assign)CGPoint ballVelocity;
@end
@implementation CZViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.添加小球
UIImage *image = [UIImage imageNamed:@"black"];
UIImageView *iv = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:iv];
self.ballIv = iv;
// 2.获得加速计单例
/**
updateInterval 更新间隔(采样,采集数据样本)
delegate 代理
*/
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
// 设置采样时间
accelerometer.updateInterval = 1 / 30.0;
// 设置代理
accelerometer.delegate = self;
}
#pragma mark - UIAccelerometerDelegate
// UIAcceleration 加速度
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
// 1. 记录小球加速度
_ballVelocity.x += acceleration.x;
// 加速计y轴方向和UIKit坐标相反
_ballVelocity.y -= acceleration.y;
// 2.更新小球位置
[self updateLocation];
}
- (void)updateLocation
{
// 设置小球的位置
CGPoint center = self.ballIv.center;
CGSize size = self.view.bounds.size;
// 解决小球出界问题,碰撞检测
// 水平方向:左边,右边
if (CGRectGetMinX(self.ballIv.frame) <= 0 || CGRectGetMaxX(self.ballIv.frame) >= size.width) {
// 修改小球的速度方向
_ballVelocity.x *= -1;
// 修复位置 < 0
if (CGRectGetMinX(self.ballIv.frame) <= 0) {
center.x = self.ballIv.bounds.size.width / 2.0;
} else {
center.x = size.width - self.ballIv.bounds.size.width / 2.0;
}
}
// 垂直方向
if (CGRectGetMinY(self.ballIv.frame) <= 0 || CGRectGetMaxY(self.ballIv.frame) >= size.height) {
// 修改小球的速度方向
_ballVelocity.y *= -1;
// 修复位置 < 0
if (CGRectGetMinY(self.ballIv.frame) <= 0) {
center.y = self.ballIv.bounds.size.height / 2.0;
} else {
center.y = size.height - self.ballIv.bounds.size.height / 2.0;
}
}
center.x += _ballVelocity.x;
center.y += _ballVelocity.y;
self.ballIv.center = center;
}
@end
#import "CZMotionManager.h"
/**
1. 静态的全局实例
2. allocWithZone
3. 定义一个shared方法,供全局使用
*/
// 保存当前类的实例
static CZMotionManager *_instance;
@implementation CZMotionManager
+ (instancetype)shareMotionManager
{
if (_instance == nil) {
_instance = [[[self class] alloc] init];
}
return _instance;
}
#pragma mark - 以下方法是为了保证对象在任何情况下都唯一
// 调用alloc的时候会调用这个方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
// 保证我们的block只能执行一次
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//会在调用copy的时候调用这个方法
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
//在调用mutableCopy的时候调用这个方法
- (id)mutableCopyWithZone:(NSZone *)zone
{
return self;
}
@end
//摇一摇
@implementation HMViewController
- (void)viewDidLoad
{
[super viewDidLoad];
Class c = NSClassFromString(@"UINavigationTransitionView");
UIView *view = [[c alloc] init];
NSLog(@"%@", view);
// UINavigationController *nav = [[UINavigationController alloc] init];
// NSLog(@"%@", nav.view.subviews);
}
#pragma mark - 实现相应的响应者方法
/** 开始摇一摇 */
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
NSLog(@"motionBegan");
}
/** 摇一摇结束(需要在这里处理结束后的代码) */
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
// 不是摇一摇运动事件
if (motion != UIEventSubtypeMotionShake) return;
NSLog(@"motionEnded");
}
/** 摇一摇取消(被中断,比如突然来电) */
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
NSLog(@"motionCancelled");
}
@end