New to the site and Obj C. Attempting to get a pitch value from Device Motion (working), put into an array with the most recent 60 values (not working) and select the maximum value within the array. With each new pitch value from the device, new pitch value is added to the array and the 61st value is dropped. When I hook up my phone and run, I get the log values for the pitch and maxPitch; however, I am not getting the array of 60 values so I don't believe it is working properly. Any help is greatly appreciated.
I believe the problem may be in the line : if (pitchArray.count <= 60) {
[pitchArray addObject:[NSString stringWithFormat:#"%.2gº", motion.attitude.pitch * kRadToDeg]];
Here is the full code:
#import "ViewController.h"
#import <CoreMotion/CoreMotion.h>
#define kRadToDeg 57.2957795
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UILabel *pitchLabel;
#property (nonatomic, strong) CMMotionManager *motionManager;
#end
#implementation ViewController
- (CMMotionManager *)motionManager
{
if (!_motionManager) {
_motionManager = [CMMotionManager new];
[_motionManager setDeviceMotionUpdateInterval:1/60];
}
return _motionManager;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
self.pitchLabel.text = [NSString stringWithFormat:#"%.2gº", motion.attitude.pitch * kRadToDeg];
NSMutableArray *pitchArray = [NSMutableArray array];
pitchArray = [[NSMutableArray alloc] initWithCapacity:60];
if (pitchArray.count <= 60) {
[pitchArray addObject:[NSString stringWithFormat:#"%.2gº", motion.attitude.pitch * kRadToDeg]];
}
else {
[pitchArray removeObjectAtIndex:0];
}
NSNumber *maxPitch = [pitchArray valueForKeyPath:#"#max.intValue"];
NSLog(#"%#",pitchArray);
NSLog(#"Max Pitch Value = %d",[maxPitch intValue]);
}];
}
#end
You keep allocating a new array every time you get a new pitch value. So you shall define the pitch array as a property and allocate it before your motion update handler. Your code would be:
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UILabel *pitchLabel;
#property (nonatomic, strong) CMMotionManager *motionManager;
#property (nonatomic, strong) NSMutableArray *pitchArray;
#end
#implementation ViewController
- (CMMotionManager *)motionManager
{
if (!_motionManager) {
_motionManager = [CMMotionManager new];
[_motionManager setDeviceMotionUpdateInterval:1/60];
}
return _motionManager;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.pitchArray = [[NSMutableArray alloc] initWithCapacity:60];
[self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
self.pitchLabel.text = [NSString stringWithFormat:#"%.2gº", motion.attitude.pitch * kRadToDeg];
if (self.pitchArray.count <= 60) {
[self.pitchArray addObject:[NSString stringWithFormat:#"%.2gº", motion.attitude.pitch * kRadToDeg]];
}
else {
[self.pitchArray removeObjectAtIndex:0];
}
NSNumber *maxPitch = [self.pitchArray valueForKeyPath:#"#max.intValue"];
NSLog(#"%#",self.pitchArray);
NSLog(#"Max Pitch Value = %d",[maxPitch intValue]);
}];
}
Ah, simple error. It wasn't looping so I changed the if/else statement to while. The code works now and outputs the 60 item array and max value.
Related
I've found very limited resources on this topic (CMPedometer). I was wondering if anyone here has managed to get this to work properly. My code is fairly simple, and has more than what I'm trying to do. Basically, the step counter does not increment EVERY step a user takes.
It actually is tracking every step the user takes but it updates so slowly and I can't figure out why. I even tried using NSTimer to make a request to update the labels every half a second. I want to try to get the step counter to update as a user takes a step. Here is my code...
#import "ViewController.h"
#import <CoreMotion/CoreMotion.h>
#interface ViewController ()
#property (nonatomic, strong) CMPedometer *pedometer;
#property (nonatomic, weak) IBOutlet UILabel *startDateLabel;
#property (nonatomic, weak) IBOutlet UILabel *endDateLabel;
#property (nonatomic, weak) IBOutlet UILabel *stepsLabel;
#property (nonatomic, weak) IBOutlet UILabel *distanceLabel;
#property (nonatomic, weak) IBOutlet UILabel *ascendedLabel;
#property (nonatomic, weak) IBOutlet UILabel *descendedLabel;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
if ([CMPedometer isStepCountingAvailable]) {
self.pedometer = [[CMPedometer alloc] init];
[NSTimer scheduledTimerWithTimeInterval:0.5f
target:self
selector:#selector(recursiveQuery)
userInfo:nil
repeats:YES];
} else {
NSLog(#"Nothing available");
self.startDateLabel.text = #"";
self.endDateLabel.text = #"";
self.stepsLabel.text = #"";
self.distanceLabel.text = #"";
self.ascendedLabel.text = #"";
self.descendedLabel.text = #"";
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.pedometer startPedometerUpdatesFromDate:[NSDate date]
withHandler:^(CMPedometerData *pedometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"data:%#, error:%#", pedometerData, error);
});
}];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.pedometer stopPedometerUpdates];
}
- (NSString *)stringWithObject:(id)obj {
return [NSString stringWithFormat:#"%#", obj];
}
- (NSString *)stringForDate:(NSDate *)date {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateStyle = NSDateFormatterShortStyle;
formatter.timeStyle = NSDateFormatterShortStyle;
return [formatter stringFromDate:date];
}
- (void)queryDataFrom:(NSDate *)startDate toDate:(NSDate *)endDate {
[self.pedometer queryPedometerDataFromDate:startDate
toDate:endDate
withHandler:
^(CMPedometerData *pedometerData, NSError *error) {
NSLog(#"data:%#, error:%#", pedometerData, error);
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(#"Error = %#",error.userInfo);
self.startDateLabel.text = #"";
self.endDateLabel.text = #"";
self.stepsLabel.text = #"";
self.distanceLabel.text = #"";
self.ascendedLabel.text = #"";
self.descendedLabel.text = #"";
} else {
self.startDateLabel.text = [self stringForDate:pedometerData.startDate];
self.endDateLabel.text = [self stringForDate:pedometerData.endDate];
self.stepsLabel.text = [self stringWithObject:pedometerData.numberOfSteps];
self.distanceLabel.text = [NSString stringWithFormat:#"%.1f[m]", [pedometerData.distance floatValue]];
self.ascendedLabel.text = [self stringWithObject:pedometerData.floorsAscended];
self.descendedLabel.text = [self stringWithObject:pedometerData.floorsDescended];
}
});
}];
}
- (void)recursiveQuery {
NSDate *to = [NSDate date];
NSDate *from = [to dateByAddingTimeInterval:-(24. * 3600.)];
[self queryDataFrom:from toDate:to];
}
Thanks in advance for any feedback!
EDIT
It seems the appropriate method to use for live updates is the following..
- (void)liveSteps {
[self.pedometer startPedometerUpdatesFromDate:[NSDate date]
withHandler:^(CMPedometerData *pedometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Steps %#",pedometerData.numberOfSteps);
});
}];
}
However, even this is severely delayed. Does anyone have any idea how to use this properly to essentially update as the user takes a step?
I can only confirm your findings. I also wanted to get "true" realtime information. As it seems at this point, the API is not capable of this; even by forcing the updates into a queue, sync, async, etc.
For references and others with this question, here is the code I use based on Swift 3 and Xcode 8.2. I simply apply this portion of code in the concerned viewcontroller, after checking the CMPedometer.isStepCountingAvailable().
As you can see, I've included a small animation to update the UILabel in a more fluid manner.
// Steps update in near realtime - UILabel
self.pedoMeter.startUpdates(from: midnightOfToday) { (data: CMPedometerData?, error) -> Void in
DispatchQueue.main.async(execute: { () -> Void in
if(error == nil){
self.todaySteps.text = "\(data!.numberOfSteps)"
// Animate the changes of numbers in the UILabel
UILabel.transition(with: self.todaySteps,
duration: 0.50,
options: .transitionCrossDissolve,
animations: nil,
completion: nil)
}
})
}
I've found very limited resources on this topic (CMPedometer). I was wondering if anyone here has managed to get this to work properly. My code is fairly simple, and has more than what I'm trying to do. Basically, the step counter does not increment EVERY step a user takes.
It actually is tracking every step the user takes but it updates so slowly and I can't figure out why. I even tried using NSTimer to make a request to update the labels every half a second. I want to try to get the step counter to update as a user takes a step. Here is my code...
#import "ViewController.h"
#import <CoreMotion/CoreMotion.h>
#interface ViewController ()
#property (nonatomic, strong) CMPedometer *pedometer;
#property (nonatomic, weak) IBOutlet UILabel *startDateLabel;
#property (nonatomic, weak) IBOutlet UILabel *endDateLabel;
#property (nonatomic, weak) IBOutlet UILabel *stepsLabel;
#property (nonatomic, weak) IBOutlet UILabel *distanceLabel;
#property (nonatomic, weak) IBOutlet UILabel *ascendedLabel;
#property (nonatomic, weak) IBOutlet UILabel *descendedLabel;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
if ([CMPedometer isStepCountingAvailable]) {
self.pedometer = [[CMPedometer alloc] init];
[NSTimer scheduledTimerWithTimeInterval:0.5f
target:self
selector:#selector(recursiveQuery)
userInfo:nil
repeats:YES];
} else {
NSLog(#"Nothing available");
self.startDateLabel.text = #"";
self.endDateLabel.text = #"";
self.stepsLabel.text = #"";
self.distanceLabel.text = #"";
self.ascendedLabel.text = #"";
self.descendedLabel.text = #"";
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.pedometer startPedometerUpdatesFromDate:[NSDate date]
withHandler:^(CMPedometerData *pedometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"data:%#, error:%#", pedometerData, error);
});
}];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.pedometer stopPedometerUpdates];
}
- (NSString *)stringWithObject:(id)obj {
return [NSString stringWithFormat:#"%#", obj];
}
- (NSString *)stringForDate:(NSDate *)date {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateStyle = NSDateFormatterShortStyle;
formatter.timeStyle = NSDateFormatterShortStyle;
return [formatter stringFromDate:date];
}
- (void)queryDataFrom:(NSDate *)startDate toDate:(NSDate *)endDate {
[self.pedometer queryPedometerDataFromDate:startDate
toDate:endDate
withHandler:
^(CMPedometerData *pedometerData, NSError *error) {
NSLog(#"data:%#, error:%#", pedometerData, error);
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(#"Error = %#",error.userInfo);
self.startDateLabel.text = #"";
self.endDateLabel.text = #"";
self.stepsLabel.text = #"";
self.distanceLabel.text = #"";
self.ascendedLabel.text = #"";
self.descendedLabel.text = #"";
} else {
self.startDateLabel.text = [self stringForDate:pedometerData.startDate];
self.endDateLabel.text = [self stringForDate:pedometerData.endDate];
self.stepsLabel.text = [self stringWithObject:pedometerData.numberOfSteps];
self.distanceLabel.text = [NSString stringWithFormat:#"%.1f[m]", [pedometerData.distance floatValue]];
self.ascendedLabel.text = [self stringWithObject:pedometerData.floorsAscended];
self.descendedLabel.text = [self stringWithObject:pedometerData.floorsDescended];
}
});
}];
}
- (void)recursiveQuery {
NSDate *to = [NSDate date];
NSDate *from = [to dateByAddingTimeInterval:-(24. * 3600.)];
[self queryDataFrom:from toDate:to];
}
Thanks in advance for any feedback!
EDIT
It seems the appropriate method to use for live updates is the following..
- (void)liveSteps {
[self.pedometer startPedometerUpdatesFromDate:[NSDate date]
withHandler:^(CMPedometerData *pedometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Steps %#",pedometerData.numberOfSteps);
});
}];
}
However, even this is severely delayed. Does anyone have any idea how to use this properly to essentially update as the user takes a step?
I can only confirm your findings. I also wanted to get "true" realtime information. As it seems at this point, the API is not capable of this; even by forcing the updates into a queue, sync, async, etc.
For references and others with this question, here is the code I use based on Swift 3 and Xcode 8.2. I simply apply this portion of code in the concerned viewcontroller, after checking the CMPedometer.isStepCountingAvailable().
As you can see, I've included a small animation to update the UILabel in a more fluid manner.
// Steps update in near realtime - UILabel
self.pedoMeter.startUpdates(from: midnightOfToday) { (data: CMPedometerData?, error) -> Void in
DispatchQueue.main.async(execute: { () -> Void in
if(error == nil){
self.todaySteps.text = "\(data!.numberOfSteps)"
// Animate the changes of numbers in the UILabel
UILabel.transition(with: self.todaySteps,
duration: 0.50,
options: .transitionCrossDissolve,
animations: nil,
completion: nil)
}
})
}
I'm working on the following code, which has the steps of a person walking. but every time I step from one view to another the counter stops. I am working with SOMotionDetector.
NOTE: when printing to console the steps that continues to function even changing views.
#import "SOMotionDetector.h"
#import "SOStepDetector.h"
#interface ContarPasos ()<SOMotionDetectorDelegate>
{
int stepCount;
}
#property (weak, nonatomic) IBOutlet UILabel *speedLabel;
#property (weak, nonatomic) IBOutlet UILabel *stepCountLabel;
#property (weak, nonatomic) IBOutlet UILabel *motionTypeLabel;
#property (weak, nonatomic) IBOutlet UILabel *isShakingLabel;
#end
#implementation ContarPasos
- (void)viewDidLoad
{
[super viewDidLoad];
__strong ContarPasos *weakSelf = self;
[SOMotionDetector sharedInstance].motionTypeChangedBlock = ^(SOMotionType motionType) {
NSString *type = #"";
switch (motionType) {
case MotionTypeNotMoving:
type = #"No estas moviendote";
break;
case MotionTypeWalking:
type = #"Caminando";
break;
case MotionTypeRunning:
type = #"Corriendo";
break;
case MotionTypeAutomotive:
type = #"Automotive";
break;
}
weakSelf.motionTypeLabel.text = type;
};
[SOMotionDetector sharedInstance].locationChangedBlock = ^(CLLocation *location) {
weakSelf.speedLabel.text = [NSString stringWithFormat:#"%.2f km/h", [SOMotionDetector sharedInstance].currentSpeed * 3.6f];
};
[SOMotionDetector sharedInstance].accelerationChangedBlock = ^(CMAcceleration acceleration) {
BOOL isShaking = [SOMotionDetector sharedInstance].isShaking;
weakSelf.isShakingLabel.text = isShaking ? #"Corriendo":#"No corriendo";
};
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
[SOMotionDetector sharedInstance].useM7IfAvailable = YES; //Use M7 chip if available, otherwise use lib's algorithm
}
[[SOMotionDetector sharedInstance] startDetection];
[[SOStepDetector sharedInstance] startDetectionWithUpdateBlock:^(NSError *error) {
if (error) {
NSLog(#"%#", error.localizedDescription);
return;
}
stepCount++;
weakSelf.stepCountLabel.text = [NSString stringWithFormat:#"Pasos: %d", stepCount];
NSLog(#"always printed on console but not in the view: %d", stepCount);
}];
}
I'm trying to write a calculator program, but I'm running into this error when pressing a particular key that is linked to the function expressionEvaluation. My calculator works fine, but I am trying to add in the ability to use/store variables. For this, I use the expressionEvaluation button. However, as soon as I press the button linked to that method, the whole app crashes, and xcode gives me the error EXC_BAD_ACCESS code=2. I'm new to objective-c, so I'm not sure how to debug this error. As far as I can tell, though, the issue is with the line
double result = [CalculatorBrain evaluateExpression:self.brain.expression usingVariableValues:testValues];
...in my view controller. I set a break point before this line and it didn't crash, but setting it at this line resulted in the crash I'm experiencing.
I tried to cut the code down below, and have included only the things directly linked to the expressionEvaluation button. Thank you for your help!
Here's the .h for my brain method:
// CalculatorBrain.h
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
- (void) pushOperand:(double)operand;
- (void) setVariableAsOperand:(NSString *)variableName;
- (void) performWaitingOperation;
- (double) performOperation:(NSString *)operation;
#property (readonly) id expression;
+ (double)evaluateExpression: (id)anExpression
usingVariableValues: (NSDictionary *)variables;
+ (NSSet *)variablesInExpression:(id)anExpression;
+ (NSString *)descriptionOfExpression:(id)anExpression;
+ (id)propertyListForExpression:(id)anExpression;
+ (id)expressionForPropertyList:(id)propertyList;
#end
Here's the .m:
// CalculatorBrain.m
#import "CalculatorBrain.h"
#define VARIABLE_PREFIX #"^"
#interface CalculatorBrain()
#property (nonatomic) double operand;
#property (nonatomic, strong) NSString *waitingOperation;
#property (nonatomic) double waitingOperand;
#property (nonatomic) double storedOperand;
#property (nonatomic) NSMutableArray *internalExpression;
#end
#implementation CalculatorBrain
#synthesize operand = _operand; //operand in use
#synthesize waitingOperation = _waitingOperation; //waiting to be computed
#synthesize waitingOperand = _waitingOperand; //waiting to be used
#synthesize storedOperand = _storedOperand; //stored in memory
#synthesize internalExpression = _internalExpression; //private expression stored
#synthesize expression = _expression;
- (id) expression {;
return [NSMutableArray arrayWithArray:self.internalExpression];
}
//here I have instance methods that add objects to the array internalExpression
//these work fine as far as I can tell
+ (double) evaluateExpression:(id)anExpression usingVariableValues:(NSDictionary *)variables {
double result = 0;
int count = [anExpression count];
CalculatorBrain *brain;
for (int i = 0; i < count; i++) {
if([[anExpression objectAtIndex:i] isKindOfClass:[NSNumber class]]) {
double operand = [[anExpression objectAtIndex:i] doubleValue];
[brain pushOperand:operand];
}
if([[anExpression objectAtIndex:i] isKindOfClass:[NSString class]]) {
NSString *string = [anExpression objectAtIndex:i];
if([string characterAtIndex:0] == '^') {
NSString* variable = [NSString stringWithFormat:#"%c",[string characterAtIndex:1]];
double valueOfVariable = [[variables objectForKey:variable] doubleValue];
[brain pushOperand:valueOfVariable];
}
else {
NSString* operator = [anExpression objectAtIndex:i];
result = [brain performOperation:operator];
}
}
}
return result;
}
#end
Here's the .h for my view controller:
// CalcViewController.h
#import <UIKit/UIKit.h>
//view controller for calculator
#interface CalcViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *display; //real-time display
#property (strong, nonatomic) IBOutlet UILabel *miniDisplay; //past display
#property (strong, nonatomic) IBOutlet UILabel *memDisplay; //display stored digits
- (IBAction)digitPressed:(UIButton *)sender; //pressed number
- (IBAction)operandPressed:(UIButton *)sender; //pressed operation
- (IBAction)variablePressed:(UIButton *)sender; //pressed variable
- (IBAction)expressionEvaluation:(UIButton *)sender; //evaluate expression with variables
#end
Here's the .m:
// CalcViewController.m
#import "CalcViewController.h"
#import "CalculatorBrain.h"
#interface CalcViewController ()
#property (nonatomic, strong) CalculatorBrain *brain;
#property (nonatomic) BOOL userIsInTheMiddleOfTypingANumber;
#end
#implementation CalcViewController
- (CalculatorBrain *) brain {
if (!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}
- (IBAction)expressionEvaluation:(UIButton *)sender {
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", 2, #"y", 3, #"z", 4, nil];
double result = [CalculatorBrain evaluateExpression:self.brain.expression usingVariableValues:testValues];
NSString *resultString = [NSString stringWithFormat:#"%g", result];
self.display.text = resultString;
}
#end
EDIT: Just as a side note, I am not getting any errors, only one warning: incomplete implementation. This is because I haven't finished a couple class methods yet, but I don't think it is causing the crash.
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", 2, #"y", 3, #"z", 4, nil];
turned out to be the erroneous line. It should have been:
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", [NSNumber numberWithInt:2], #"y", [NSNumber numberWithInt:3], #"z", [NSNumber numberWithInt:4], nil];
Thanks to everyone who helped!
You will get more information on the code line raising the exception by adding an exception breakpoint in xCode.
I am using the UIAccelerotmeterDelegate method accelerometer:didAccelerate: but recently that method has been deprecated in iOS 5.0. So what is the alternative way to get the accelerometer data? The documentation does not mention the alternative we are supposed to use.
You should use the Core Motion framework (introduced in iOS 4.0) as a substitue. Create an instance of CMMotionManager and tell it to startAccelerometerUpdatesToQueue:withHandler:, passing it an NSOperationQueue and a block that will be executed on the specified queue whenever new accelerometer data is available.
It seems that UIAccelerometer and UIAccelerometerDelegate were replaced by the CoreMotion framework.
You can find the answer here:
Why is accelerometer:didAccelerate: deprecated in IOS5?
I Hope it helps.
Here is a useful sample code I found for CoreMotion from this link.
#interface ViewController ()
#property (nonatomic, strong) CMMotionManager *motionManager;
#property (nonatomic, strong) IBOutlet UILabel *xAxis;
#property (nonatomic, strong) IBOutlet UILabel *yAxis;
#property (nonatomic, strong) IBOutlet UILabel *zAxis;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.accelerometerUpdateInterval = 1;
if ([self.motionManager isAccelerometerAvailable])
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[self.motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
self.xAxis.text = [NSString stringWithFormat:#"%.2f",accelerometerData.acceleration.x];
self.yAxis.text = [NSString stringWithFormat:#"%.2f",accelerometerData.acceleration.y];
self.zAxis.text = [NSString stringWithFormat:#"%.2f",accelerometerData.acceleration.z];
});
}];
} else
NSLog(#"not active");
}
#end
Its replaced by CoreMotion. See Motion Events.
Add CoreMotion framework to the project first. Then:
#import <CoreMotion/CoreMotion.h>
#property (strong, nonatomic) CMMotionManager *motionManager;
- (void)viewDidLoad {
_motionManager = [CMMotionManager new];
_motionManager.accelerometerUpdateInterval = 0.01; // 0.01 = 1s/100 = 100Hz
if ([_motionManager isAccelerometerAvailable])
{
NSOperationQueue *queue = [NSOperationQueue new];
[_motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error){
NSLog(#"X = %0.4f, Y = %.04f, Z = %.04f",
accelerometerData.acceleration.x,
accelerometerData.acceleration.y,
accelerometerData.acceleration.z);
}];
}
}
I am answering this for Swift 5.x.
#available(iOS, introduced: 2.0, deprecated: 13.0, message: "UIAcceleration has been replaced by the CoreMotion framework") public protocol UIAccelerometerDelegate : NSObjectProtocol { }
Add CoreMotion framework only. Don't conform to UIAccelerometerDelegate.
import CoreMotion
If you want to show animation or create a game, you can start with the following code.
self.motionManager = CMMotionManager()
self.motionManager?.startAccelerometerUpdates()
if motionManager.isAccelerometerAvailable {
motionManager.startAccelerometerUpdates(to: .main) { (data, error) in
if let myData = data {
let x = String(format: "%.3f",myData.acceleration.x)
let y = String(format: "%.3f",myData.acceleration.y)
let z = String(format: "%.3f",myData.acceleration.z)
DispatchQueue.main.async {
var rect = self.anyObject.frame
let movetoX = rect.origin.x + CGFloat(myData.acceleration.x * stepMoveFactor)
let movetoY = rect.origin.y - CGFloat(myData.acceleration.y * stepMoveFactor)
if ( movetoX > 0 && movetoX < SCREEN_WIDTH ) {
rect.origin.x += CGFloat(myData.acceleration.x * stepMoveFactor)
}
if ( movetoY > 1 && movetoY < maxY ) {
rect.origin.y -= CGFloat(myData.acceleration.y * stepMoveFactor) }
}
}
}
}
use UIView.animate if you want. This method initiates a set of animations to perform on the view. The block object in the animations parameter contains the code for animating the properties of one or more views.
swift ios