IOS_加速计_CoreMotion框架_单例_时钟_Get+异步请求+Json

H:/1019/01_加速度accelerometer原始方法_AppDelegate.h
//
//  AppDelegate.h
//  加速计-01.传统用法
//
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

H:/1019/01_加速度accelerometer原始方法_AppDelegate.m
//  AppDelegate.m
//  加速计-01.传统用法
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "AppDelegate.h"
// 手动导入了MainViewController的头文件
#import "MainViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
	// 仅仅加了一句这个,实例化MainViewController
    MainViewController *controller = [[MainViewController alloc]init];
    [self.window setRootViewController:controller];
    [self.window makeKeyAndVisible];
    return YES;
}

@end

H:/1019/01_加速度accelerometer原始方法_MainViewController.h
//
//  MainViewController.h
//  加速计-01.传统用法
//
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface MainViewController : UIViewController

@end

H:/1019/01_加速度accelerometer原始方法_MainViewController.m
//  MainViewController.m
//  加速计-01.传统用法
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "MainViewController.h"
// 导入第3方框架QuartzCore
#import <QuartzCore/QuartzCore.h>
@interface MainViewController () <UIAccelerometerDelegate>
{
    // 小球图像
    UIImageView     *_ball;
    // 小球速度
    CGPoint         _ballVelocity;
    // 游戏时钟 CADisplayLink
    CADisplayLink   *_gameTimer;
}
@end
@implementation MainViewController
/*
 使用DEPRECATED描述符的方法和对象,是不推荐使用的,
 同时也是官方停止更新的方法
 
 提示:加速剂默认是不工作,因为工作会耗电,
 当设置了采样频率,加速剂开始工作,同时将采样获得的数据
 通过代理方法,发送给调用方
 UIAcceleration的四个成员说明
 * timestamp    数据采样发生的时间,很少用到
 * x            x 方向的加速度
 * y            y 方向的加速度
 * z            z 方向的加速度 
 */
- (void)viewDidLoad
{
    [super viewDidLoad];
    UIImage *image = [UIImage imageNamed:@"black.png"];
    _ball = [[UIImageView alloc]initWithImage:image];
    [_ball setCenter:self.view.center];
    [self.view addSubview:_ball];
    // 小球初始静止,速度为0
    _ballVelocity = CGPointZero;
    // 加速计,模板代码
    // 1. 实例化加速计,因为在手机上有且仅有一个芯片,因此使用单例来访问加速剂
    UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
    // 2. 设置更新频率(采样频率HZ)
    [accelerometer setUpdateInterval:1 / 30.0];
    // 3. 设置代理,为当前控制器
    [accelerometer setDelegate:self];
    // 游戏时钟 CADisplayLink
    // 1. 游戏时钟 实例化 CADisplayLink,同时设置Target对象的selector方法
    _gameTimer = [CADisplayLink displayLinkWithTarget:self
									selector:@selector(step)];
    // 2. 游戏时钟 添加到主运行循环,使用默认模式
    [_gameTimer addToRunLoop:[NSRunLoop mainRunLoop]
								forMode:NSDefaultRunLoopMode];
}
#pragma mark - 时钟监听方法
- (void)step
{	
	//调用自定义方法,更新小球坐标
    [self updateBallLocation];
}
#pragma mark - 自定义方法,更新小球位置
- (void)updateBallLocation
{
    // 根据小球位置调整中心点位置
    CGPoint center = _ball.center;
    // 判断小球的位置是否超出边界,如果超出边界,将小球的方向求反
    // 1) 水平方向
    // 如果小球的最小x值,小于0,表示左边出界
    // CGRectGetMinX(_ball.frame) = _ball.frame.origin.y
    // 如果小球的最大x值,大于viewW,表示右边边出界
    if (CGRectGetMinX(_ball.frame) < 0 ||
				CGRectGetMaxX(_ball.frame) > self.view.bounds.size.width) {
		// 0.8 模拟速度衰减系数
        _ballVelocity.x *= -0.8;
        // 修复小球位置,防止嵌入边框,贴在边框上,动不了
        if (CGRectGetMinX(_ball.frame) < 0) {
            center.x = _ball.bounds.size.width / 2;
        } else {
            center.x = self.view.bounds.size.width - _ball.bounds.size.width / 2;
        }
    }
    // 2)垂直方向
    if (CGRectGetMinY(_ball.frame) < 0 ||
			CGRectGetMaxY(_ball.frame) > self.view.bounds.size.height) {
        _ballVelocity.y *= -0.8;
        // 修复小球位置,防止嵌入边框,贴在边框上,动不了
        if (CGRectGetMinY(_ball.frame) < 0) {
            center.y = _ball.bounds.size.height / 2;
        } else {
            center.y = self.view.bounds.size.height - _ball.bounds.size.height / 2;
        }
    }
    center.x += _ballVelocity.x;
    center.y += _ballVelocity.y;
	// 由于时钟被添加到主运行循环中,故可以直接更新UI
    [_ball setCenter:center];
}
#pragma mark - 加速计代理方法
- (void)accelerometer:(UIAccelerometer *)accelerometer
				didAccelerate:(UIAcceleration *)acceleration
{
    // 使用加速度调整小球速度,开发中,v=v0+a*t,t是恒定的,a是变化的???
    _ballVelocity.x += acceleration.x;
	// 加速计的Y轴和UIKit的Y轴相反,故
    _ballVelocity.y -= acceleration.y;
    // 让加速剂仅负责采样数据,更新速度
//    [self updateBallLocation];
}
@end

H:/1019/02_CoreMotion框架_单例_时钟_AppDelegate.h
//  AppDelegate.h
//  加速计-CM Push
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import <UIKit/UIKit.h>
// CMMotionManager单例方式1:第1步:导入框架
#import <CoreMotion/CoreMotion.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
// CMMotionManager单例方式1:第2步:定义成员,只有getter
// 运动管理器的单例
@property (strong, nonatomic, readonly) CMMotionManager *sharedMotionManager;
@end

H:/1019/02_CoreMotion框架_单例_时钟_AppDelegate.m
//  AppDelegate.m
//  加速计-CM Push
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "AppDelegate.h"
#import "MainViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
	//加了这一句话,实例化MainViewController
    MainViewController *controller = [[MainViewController alloc]init];
    [self.window setRootViewController:controller];
    [self.window makeKeyAndVisible];
    return YES;
}

// CMMotionManager单例方式1:第3步:使用静态对象记录住第一次被初始化的实例
static CMMotionManager *montionManager;

// CMMotionManager单例方式1:第4步:实现getter方法
- (CMMotionManager *)sharedMotionManager
{
	// 使用dispatch_once GCD生成单例对象
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        montionManager = [[CMMotionManager alloc]init];
    });
    return montionManager;
}
@end

H:/1019/02_CoreMotion框架_单例_时钟_MainViewController.h
//
//  MainViewController.h
//  加速计-CM Push
//
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface MainViewController : UIViewController

@end

H:/1019/02_CoreMotion框架_单例_时钟_MainViewController.m
//  MainViewController.m
//  加速计-CM Push
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "MainViewController.h"
#import <CoreMotion/CoreMotion.h>
// 需求4:使用时钟更新,步骤1,导入QuartzCore
#import <QuartzCore/QuartzCore.h>
//#import "AppDelegate.h" 使用方式2,会产生嵌套引用问题,不推荐
#import "MyMotionManager.h"	// 推荐使用方式3
@interface MainViewController ()
{
    UIImageView         *_ball;             // 小球
    CGPoint             _ballVelocity;      // 小球速度
    CMMotionManager     *_montionManager;   // 运动管理器(单例)
	// 操作队列,耗时的操作不要放到主队列里面,新建一个操作队列
    NSOperationQueue    *_queue;            
	// 需求4:使用时钟更新,步骤2,成员变量:CADisplayLink
    CADisplayLink       *_gameTimer;        // 游戏时钟
}
@end
@implementation MainViewController
/*
 accelerometerAvailable         加速计计是否可用
 accelerometerUpdateInterval    加速计采样频率
 accelerometerActive            加速计是否正在采样数据
 accelerometerData              取回末次采样数据,pull方法使用
 startAccelerometerUpdates      开始加速计更新
 startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAccelerometerHandler)handler
                                使用多线程的加速计采样数据,push方法
 stopAccelerometerUpdates       停止采样
 */
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 实例化小球
    UIImage *image = [UIImage imageNamed:@"black.png"];
    _ball = [[UIImageView alloc]initWithImage:image];
    [_ball setCenter:self.view.center];
    [self.view addSubview:_ball];
	// 操作队列,耗时的操作不要放到主队列里面,新建一个操作队列
    _queue = [[NSOperationQueue alloc]init];
	// 调用自定义方法,加载加速计
    [self loadAccelerometerData];
    // 需求4:使用时钟更新,步骤3,实例化时钟,并加到主运行队列mainRunLoop
    _gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step)];
    [_gameTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

#pragma mark - 加速计采样数据
- (void)loadAccelerometerData
{
    // 运动管理器生成方式1: 直接实例化,
	// 缺点:如果应用程序中有多个视图控制器需要使用加速计,无法让加速计共享
		//_montionManager = [[CMMotionManager alloc]init];
		
		
	// 运动管理器生成方式2: 从AppDelegate中getter方法获取运动管理器的单例
    // 1> 只需要在AppDelegate中定义即可,因为UIApplication本身就是一个单例
    // 2> 缺点:会出现.h文件嵌套引用的问题,在实际开发中,应该尽量避免
    // 3.1> 先获取AppDelegate单例
		//AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
		// 3.2> 通过getter方法获得返回
	    //CMMotionManager *_montionManager = [appDelegate sharedMotionManager];
		
		
	// 运动管理器生成方式3: 自己定义一个类继承CMMotionManager,
	//从MyMotionManager的类方法中获取提供的运动管理器的单例
    _montionManager = [MyMotionManager sharedMontionManager];
    // 采样过程
    // 1) 判断加速计是否可用
    if ([_montionManager isAccelerometerAvailable]) {
        // 2) 指定加速计采样频率
        [_montionManager setAccelerometerUpdateInterval:1 / 30.0];
		// 调用自定义的方法,开始采样
        [self accelerometerUpdatesData];
    } else {
        NSLog(@"加速计不可用");
    }
}
// 需求4:使用时钟更新,步骤4,时钟任务,仅是更新小球位置
#pragma mark - 模板代码,直接剪切过来的,更新小球位置
- (void)step
{
    // 根据小球位置调整中心点位置
    CGPoint center = _ball.center;
    // 判断小球的位置是否超出边界,如果超出边界,将小球的方向求反
    // 1) 水平方向
    // 如果小球的最小x值,小于0,表示左边出界
    // CGRectGetMinX(_ball.frame) = _ball.frame.origin.y
    // 如果小球的最大x值,大于viewW,表示右边边出界
    if (CGRectGetMinX(_ball.frame) < 0 || CGRectGetMaxX(_ball.frame) > self.view.bounds.size.width) {
        _ballVelocity.x *= -0.8;
        
        // 修复小球位置
        if (CGRectGetMinX(_ball.frame) < 0) {
            center.x = _ball.bounds.size.width / 2;
        } else {
            center.x = self.view.bounds.size.width - _ball.bounds.size.width / 2;
        }
    }
    // 2)垂直方向
    if (CGRectGetMinY(_ball.frame) < 0 || CGRectGetMaxY(_ball.frame) > self.view.bounds.size.height) {
        _ballVelocity.y *= -0.8;
        
        // 修复小球位置
        if (CGRectGetMinY(_ball.frame) < 0) {
            center.y = _ball.bounds.size.height / 2;
        } else {
            center.y = self.view.bounds.size.height - _ball.bounds.size.height / 2;
        }
    }
    center.x += _ballVelocity.x;
    center.y += _ballVelocity.y;
    /* 如果这儿采用了多线程,则更新界面UI要在主线程中完成
    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
			[_ball setCenter:center];
    }];*/
	
	// 如果,这儿是时钟要在主线程中,执行的任务,可直接更新位置
	[_ball setCenter:center];
	
}

#pragma mark - 自定义方法,抽取出来的,开始采样数据
// 加速计更新数据
- (void)accelerometerUpdatesData
{
    // 3) 使用push方法,采样数据
	// 注意:参数1为操作队列,耗时的操作不要放到主队列里面,新建一个操作队列
    [_montionManager startAccelerometerUpdatesToQueue:_queue
		withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
        // 由于参数1,不是主线程,而是一个单独的操作队列,
		// 所以,这儿仅负责更新小球的速度,不提供更新小球位置UI
		// 而是由时钟的target 的selector方法中更新UI即小球位置
        _ballVelocity.x += accelerometerData.acceleration.x;
        _ballVelocity.y -= accelerometerData.acceleration.y;
        
    }];
}
#pragma mark - 触摸事件
// 点按屏幕停止数据更新,游戏中有暂停的需求
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 提示,加速计负责采样数据,游戏时钟负责更新界面
    // 因此,暂停游戏时,需要将二者同时暂停或启动
    // 根据加速计是否正在采样数据,停止或者开始采样数据
    if ([_montionManager isAccelerometerActive]) {
        // 停止采样
        [_montionManager stopAccelerometerUpdates];
        // 由于是时钟负责更新小球位置UI,故还需要停止游戏时钟
        // 停止时钟方式1:invalidate方法会销毁游戏时钟,
		// 下次启动时,需要重新实例化,不划算,高耗
        // [_gameTimer invalidate];
		
		
        // 停止时钟方式2:将游戏时钟从主运行循环中移除,对象没被销毁
		// 下次启动时,无需实例化gameTimer
        [_gameTimer removeFromRunLoop:[NSRunLoop mainRunLoop] 
								forMode:NSDefaultRunLoopMode];
    } else {
        // 开始采样
        [self accelerometerUpdatesData];
        // 重新开启游戏时钟方式1:再次实例化一个,再加到主运行循环中
		// _gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step)];
		// 如果前面停止时钟的时候,没有将时钟销毁,
		// 仅是从主运行循环中移除,则再次添加即可,无需重新实例化
        [_gameTimer addToRunLoop:[NSRunLoop mainRunLoop] 
							forMode:NSDefaultRunLoopMode];
    }
}
@end

H:/1019/02_CoreMotion框架_单例_时钟_MyMotionManager.h
//
//  MyMotionManager.h
//  加速计-CM Push
//
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
//
// CMMotionManager单例方式3:第1步:导入框架
#import <CoreMotion/CoreMotion.h>
// CMMotionManager单例方式3:第2步:继承CMMotionManager
@interface MyMotionManager : CMMotionManager

// CMMotionManager单例方式3:第3步:类方法,返回MyMotionManager对象
+ (MyMotionManager *)sharedMontionManager;

@end

H:/1019/02_CoreMotion框架_单例_时钟_MyMotionManager.m
//  MyMotionManager.m
//  加速计-CM Push
//  Created by apple on 13-10-19.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "MyMotionManager.h"

@implementation MyMotionManager
// CMMotionManager单例方式3:第4步:使用静态对象记录住第一次被初始化的实例
// 单例模式:标准步骤1:静态的对象记录住第一次被实例化的对象
static MyMotionManager *sharedInstance;
 

/*
重点!!!! OC中单例设计模式 标准三步曲
 1. 静态的对象记录住第一次被实例化的对象
 2. 重写allocWithZone类方法
 3. 提供一个shared方法,方便其他类调用
 */
 
// 单例模式:标准步骤2:重写父类的allocWithZone类方法,分配内存区块
+ (id)allocWithZone:(NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
		// 调用父类的allocWithZone方法,对象实例化
        sharedInstance = [super allocWithZone:zone];
    });
    return sharedInstance;
}


// CMMotionManager单例方式3:第5步:实现getter方法
// 单例模式:标准步骤3:提供一个shared方法,方便其他类调用
+ (MyMotionManager *)sharedMontionManager
{
	// 使用dispatch_once GCD生成单例对象,并返回
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
		// 调用父类的方法初始化,(内部自动调用上面的allocWithZone)
        sharedInstance = [[super alloc]init];
    });
    return sharedInstance;
}
@end

H:/1019/03_Get+异步请求+Json+AppDelegate.h
//
//  AppDelegate.h
//  蘑菇街JSON
//
//  Created by apple on 13-10-14.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

H:/1019/03_Get+异步请求+Json+AppDelegate.m
//  AppDelegate.m
//  蘑菇街JSON
//  Created by apple on 13-10-14.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
			didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    // 1. URL
    NSString *str = @"http://www.mogujie.com/app_mgj_v511_book/clothing?_adid=5503509D-800B-45EF-B767-F6586FFF165E&_did=0f607264fc6318a92b9e13c65db7cd3c&_atype=iPhone&_source=NIMAppStore511&_fs=NIMAppStore511&_swidth=640&_network=2&_mgj=8383caabf1c61a55a96c29262b7beff61381734506&title=最热&from=hot_element&login=false&fcid=6550&q=最热&track_id=1377824666&homeType=shopping";
    NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    // 2. Request
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    // 3. Connection异步
    [NSURLConnection sendAsynchronousRequest:request
			queue:[NSOperationQueue mainQueue]
			completionHandler:^(NSURLResponse *reponse, NSData *data, NSError *error) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
							options:NSJSONReadingAllowFragments error:nil];
        // 4. 保存数据
        [dict writeToFile:@"/Users/apple/Desktop/123.plist" atomically:YES];
    }];
	
	
    [self.window makeKeyAndVisible];
    return YES;
}

@end

你可能感兴趣的:(ios,单例模式,时钟,加速计,CoreMotion框架)