官方例子--BubbleLevel

        NSBundle *mainBundle = [NSBundle mainBundle];
        farSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"farSound" ofType:@"caf"]];
        nearSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"nearSound" ofType:@"caf"]];
        levelSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"levelSound" ofType:@"caf"]];

一.简介

利用ios设备的重力加速感应,来测量平面的水平位置。有加速度分量,则说明表面有倾斜.

二.技术要点

1.AppDelegate中用+(void)initialize来初始化数据,但是里面不能给NSNotificationCenter addObserver,会报错

//initialize是个很好的初始化数据的地方
+ (void)initialize {
    if ([self class] == [LevelAppDelegate class]) {
        NSNumber *defaultCalibrationOffset = [NSNumber numberWithFloat:0.0];
        //为用户setting数据提供默认值
        NSDictionary *resourceDict = [NSDictionary dictionaryWithObject:defaultCalibrationOffset forKey:BubbleLevelCalibrationOffsetKey];
		[[NSUserDefaults standardUserDefaults] registerDefaults:resourceDict];
    }
}

在应用结束时,将其保存,这样下次打开时,在启动的时候就可以获取上次保存的数值

- (void)applicationWillTerminate:(UIApplication *)application {
    //退出程序前保存本次数据
    float calibrationOffset = levelViewController.calibrationOffset;
    NSNumber *offset = [NSNumber numberWithFloat:calibrationOffset];
    [[NSUserDefaults standardUserDefaults] setObject:offset forKey:BubbleLevelCalibrationOffsetKey];
}

2.重力感应

设置delegate,设置的对象需要实现UIAccelerometerDelegate接口

,设置部分参数,主要是更新的间隔,根据不同的应用需求,设置不一样的更新间隔,因为这个功能十分耗电

-(id) init {
	if (self = [super init]) {
		[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kUpdateFrequency)];
		[[UIAccelerometer sharedAccelerometer] setDelegate:self];
	}
	return self;
}
UIAccelerometerDelegate的方法

这个就是根据设置的间隔时间触发该方法,值得注意的是里面有个重力感应常用的方法,利用低通来实现一个重力感应缓慢变化的一个过程

// UIAccelerometer delegate method, which delivers the latest acceleration data.
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
        // Use a basic low-pass filter to only keep the gravity in the accelerometer values for the X and Y axes
        //个人感觉就是让动画影响缓慢点 kFilteringFactor=0.05
        accelerationX = acceleration.x * kFilteringFactor + accelerationX * (1.0 - kFilteringFactor);
        accelerationY = acceleration.y * kFilteringFactor + accelerationY * (1.0 - kFilteringFactor);
        
        // keep the raw reading, to use during calibrations
        currentRawReading = atan2(accelerationY, accelerationX);
        float calibratedAngle = [self calibratedAngleFromAngle:currentRawReading];
        
        [levelView updateToInclinationInRadians:calibratedAngle];
}

3.自定义UIView

代码种涉及到2个UIView界面,他们共同使用了同一个Controller,所以它自定义了一个初始化方法,我们可以看到,调用该初始化方法时,它还传入了一个Controller,例子中就是根控制器,这个我觉得在平时写代码种可以经常利用,是个相当不错的思路,此外注意的是,view中的Controller一般来说是assign的。

- (id)initWithFrame:(CGRect)frame viewController:(LevelViewController *)aController {
        self = [super initWithFrame:frame];
        if (self != nil) {
                self.viewController = aController;
        }
        return self;
}


4.切换界面

里面利用了判断2个view是否有superview来获得当前view是否在显示状态中,不错的方法!

- (void)flipAction:(id)sender {
	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:kTransitionDuration];
	[UIView setAnimationTransition:([levelView superview] ? UIViewAnimationTransitionFlipFromLeft : UIViewAnimationTransitionFlipFromRight) forView:self.view cache:YES];
	
	if ([calibrationView superview]) {
		[calibrationView removeFromSuperview];
		[self.view addSubview:levelView];
	} else {
		[levelView removeFromSuperview];
                [calibrationView resetToInitialState:self];
		[self.view addSubview:calibrationView];
	}
	[UIView commitAnimations];
}

5.音乐播放

初始化音乐文件,一共三种音效,分别代表水平偏离位置的远,近,中

        NSBundle *mainBundle = [NSBundle mainBundle];
        farSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"farSound" ofType:@"caf"]];
        nearSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"nearSound" ofType:@"caf"]];
        levelSound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:@"levelSound" ofType:@"caf"]];
调用方法,例子中根据一个参数,判断距离,从而决定播放的音效是哪个

- (void)updateLevelSoundForAngle:(float)angle {
        float absAngle = fabs(angle);
        
        if (absAngle <= kMaxVariationForLevelSound) {
                [levelSound play];
        } else if (absAngle <= kMaxVariationForNearSound) {
                [nearSound play];
        } else if (absAngle <= kMaxVariationForFarSound) {
                [farSound play];
        }
}
实际调用方法,可以看到增加了一个控制变量,每10次才调用以此音乐播放,否则太过频繁

  soundUpdateCounter++;
                
                if (soundUpdateCounter == 10) { // update sound at a tenth the rate of the animation
                        [self updateLevelSoundForAngle:rotation];
                        soundUpdateCounter = 0;
                }








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值