IOS的重力感應

     昨天寫了重力感應的例子,我覺得這個例子比較有用處,我分享出來:

1 )顯然ios4 之後可以使用coreMotion的framework 爲了向下兼容加上UIAccelerator,

#import <Foundation/Foundation.h>
#import <CoreMotion/CoreMotion.h>
@protocol  IFAccelerometerDelegate<NSObject>
- (void)accelerateWithX:(NSNumber*)x withY:(NSNumber*)y withZ:(NSNumber*)z withTimeInterval:(NSTimeInterval)timeInterval;
@end
@interface IFAccelerometer : NSObject<UIAccelerometerDelegate>
{
    UIAccelerometer *_accelerometer; 
    CMMotionManager *_motionManager;
    id<IFAccelerometerDelegate>  _delegate;
}
+ (id)shareAccelerometer;
- (void)addOberser:(id)oberserer;
- (void)removeObserver;

@end

CMMotionManager 將是我們使用的Object,可以用來監測重力!

同時,咱們不能在需要監測重力感應的地方直接使用這個類,這樣耦合比較嚴重,也不利於重用。所以抽離出來,在代碼中您可以看到,我將定義一個signleton,同時將重力變化的事件回調給其代理。

2.接着往下是定義其函數,這個很簡單,直接貼代碼。

#import "IFAccelerometer.h"
static IFAccelerometer *accelerometerInstance = nil;
@implementation IFAccelerometer
+ (id)shareAccelerometer
{
    if (!accelerometerInstance) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            accelerometerInstance = [[[self class]alloc]init];
        });
    }
    return accelerometerInstance;
}

- (id)init
{
    self = [super init];
    if (self) {
#ifdef __IPHONE_5_0
        _motionManager = [[CMMotionManager alloc]init];
        if (_motionManager.accelerometerAvailable) {
            [_motionManager setAccelerometerUpdateInterval:1/60.f];
            NSOperationQueue *operationQueue = [NSOperationQueue mainQueue];
            [_motionManager startAccelerometerUpdatesToQueue:operationQueue withHandler:^(CMAccelerometerData *data,NSError *error)
             {
                 if ([_delegate respondsToSelector:@selector(accelerateWithX:withY:withZ:withTimeInterval:)])
                 {
                     NSNumber *x  = [NSNumber numberWithDouble:data.acceleration.x];
                     NSNumber *y  = [NSNumber numberWithDouble:data.acceleration.y];
                     NSNumber *z  = [NSNumber numberWithDouble:data.acceleration.z];
                     [_delegate accelerateWithX:x withY:y withZ:z withTimeInterval:data.timestamp];
                 }
             }
             ];

        }
#else
#ifdef __IPHONE_4_0
               _accelerometer = [UIAccelerometer sharedAccelerometer];
               [_accelerometer setUpdateInterval:(1/60.0f)];
               _accelerometer.delegate = self;
#endif
#endif

    }
    return self;
}

- (void)addOberser:(id)oberserer
{
    _delegate = oberserer;
}

- (void)removeObserver
{
    _delegate = nil;
}

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
    if ([_delegate respondsToSelector:@selector(accelerateWithX:withY:withZ:withTimeInterval:)])
    {
        NSNumber *x  = [NSNumber numberWithDouble:acceleration.x];
        NSNumber *y  = [NSNumber numberWithDouble:acceleration.y];
        NSNumber *z  = [NSNumber numberWithDouble:acceleration.z];
        [_delegate accelerateWithX:x withY:y withZ:z withTimeInterval:acceleration.timestamp];
    }

}
3.以ViewController 爲例介紹如何使用重力感應

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[IFAccelerometer shareAccelerometer]addOberser:self];
    _imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"33.png"]];
    _imageView.frame = CGRectMake(0, 0, KIMAGEWIDTH, KIMAGEHEIGHT);
    _imageView.center = self.view.center;
    [self.view addSubview:_imageView];
    
}

_imageView 是一個UIImageView的成員,其寬高是一個分別是我定義的宏。

注意,我在頭文件添加了重力感應的代理,此時這行

[[IFAccelerometer shareAccelerometer]addOberser:self];

表明我在這個viewController中使用這個重力感應的數據。

好,現在是完成回調的時候了,繼續貼代碼

- (void)accelerateWithX:(NSNumber *)x withY:(NSNumber *)y withZ:(NSNumber *)z withTimeInterval:(NSTimeInterval)timeInterval
{

    float deceleration = 0.4f;
	float sensitivity  = 6.0f;
	float maxVelocity  = 100.0f;
    
	velocity.x = velocity.x * deceleration + [x doubleValue] * sensitivity;
    velocity.y = velocity.y * deceleration + [y doubleValue] * sensitivity;
	
    if(velocity.x > maxVelocity){
		velocity.x = maxVelocity;
	}else if(velocity.x < -maxVelocity){
		velocity.x = -maxVelocity;
	}
    
    if(velocity.y > maxVelocity){
        velocity.y = maxVelocity;
    }else if(velocity.y < -maxVelocity){
        velocity.y = -maxVelocity;
    }
    
    CGPoint pos = _imageView.center;
	pos.x += velocity.x;
    pos.y -= velocity.y;
	
	float imageWidthHalved =  KIMAGEWIDTH   * 0.5f;
    float leftBorderLimit  = 0.0f;
    float rightBorderLimit = 0.0f;
    if (imageWidthHalved>self.view.frame.size.width/2.0f) {
         leftBorderLimit  =   self.view.frame.size.width - imageWidthHalved;
         rightBorderLimit =  imageWidthHalved;
    }
    else
    {
        leftBorderLimit  =   imageWidthHalved ;
        rightBorderLimit =  self.view.frame.size.width - imageWidthHalved;
    }
	
    

    float imageHeightHalved = KIMAGEHEIGHT * 0.5f;
    float topBorderLimit    = 0.0f;
    float bottomBorderLimit = 0.0f;
    if (imageHeightHalved>self.view.frame.size.height/2.0f) {
         topBorderLimit    = self.view.frame.size.height - imageHeightHalved;
         bottomBorderLimit =  imageHeightHalved ;
    }
    else
    {
        topBorderLimit    = imageHeightHalved ;
        bottomBorderLimit = self.view.frame.size.height - imageHeightHalved  ;
    }
    
	
	if(pos.x < leftBorderLimit){
		pos.x = leftBorderLimit;
		velocity = CGPointZero;
	}else if(pos.x > rightBorderLimit){
		pos.x = rightBorderLimit;
		velocity = CGPointZero;
	}
    
    if(pos.y < topBorderLimit){
		pos.y = topBorderLimit;
		velocity = CGPointZero;
	}else if(pos.y > bottomBorderLimit){
		pos.y = bottomBorderLimit;
		velocity = CGPointZero;
	}
    
    _imageView.center = pos;
}

上面是對於邊界的處理等等操作,都很簡單,不一一介紹了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章