События движения
Пользователи генерируют события движения, когда они перемещают, встряхивают или наклоняют устройство. Эти события движения обнаруживаются оборудованием устройства, в частности, акселерометром и гироскопом.
Акселерометр фактически составлен из трех акселерометров, один для каждой оси — x, y, и z. Каждый измеряет изменения в скорости в течение долгого времени вдоль линейного контура. Объединение всех трех акселерометров позволяет Вам обнаружить перемещение устройств в любом направлении и получить текущую ориентацию устройства. Несмотря на то, что существует три акселерометра, остаток от этого документа именует их как единственный объект. Гироскоп измеряет уровень вращения вокруг этих трех осей.
Все события движения происходят из тех же аппаратных средств. Существует несколько различных способов, которыми можно получить доступ к тем аппаратным данным, в зависимости от потребностей приложения:
Если необходимо обнаружить общую ориентацию устройства, но Вы не должны знать вектор ориентации, используйте
UIDevice
класс. Посмотрите Получение Текущей Ориентации Устройства с UIDevice для получения дополнительной информации.Если Вы хотите, чтобы Ваше приложение ответило, когда пользователь встряхивает устройство, можно использовать методы обработки событий движения UIKit для получения информации от переданного - в
UIEvent
объект. Посмотрите События Движения встряски Обнаружения с UIEvent для получения дополнительной информации.Если ни один
UIDevice
ниUIEvent
классы достаточны, вероятно, что Вы захотите использовать Базовую платформу Движения для доступа к акселерометру, гироскопу и классам движения устройства. Посмотрите Перемещение устройств Получения с Базовым Движением для получения дополнительной информации.
Получение текущей ориентации устройства с UIDevice
Используйте методы UIDevice
класс, когда необходимо знать только общую ориентацию устройства а не точного вектора ориентации. Используя UIDevice
просто и не требует, чтобы Вы вычислили вектор ориентации сами.
Прежде чем можно будет получить текущую ориентацию, необходимо сказать UIDevice
класс, чтобы начать генерировать уведомления ориентации устройства путем вызова beginGeneratingDeviceOrientationNotifications
метод. Это включает аппаратные средства акселерометра, которые могут быть прочь для сохранения заряда батареи. Перечисление 4-1 демонстрирует это в viewDidLoad
метод.
После включения уведомлений ориентации получите текущую ориентацию от ориентация
свойство из UIDevice
объект. Когда ориентация устройства изменяется, регистр для получения, если Вы хотите быть уведомленными UIDeviceOrientationDidChangeNotification
уведомления. С помощью ориентация устройства сообщают UIDeviceOrientation
константы, указывая, является ли устройство в альбомном режиме, режиме портрета, экранная сторона, экранная сторона вниз, и т.д. Эти константы указывают физическую ориентацию устройства и не обязательно соответствуют ориентации пользовательского интерфейса Вашего приложения.
Когда Вы больше не должны будете знать ориентацию устройства, всегда отключайте уведомления ориентации путем вызова UIDevice
метод, endGeneratingDeviceOrientationNotifications
. Это дает системе возможность отключить аппаратные средства акселерометра, если это не используется в другом месте, который сохраняет заряд батареи.
Перечисление 4-1 , Реагирующее на изменения в ориентации устройства
-(void) viewDidLoad { |
// Request to turn on accelerometer and begin receiving accelerometer events |
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; |
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; |
} |
- (void)orientationChanged:(NSNotification *)notification { |
// Respond to changes in device orientation |
} |
-(void) viewDidDisappear { |
// Request to stop receiving accelerometer events and turn off accelerometer |
[[NSNotificationCenter defaultCenter] removeObserver:self]; |
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; |
} |
Для другого примера ответа к UIDevice
изменения ориентации, см. Альтернативный проект примера кода Представлений.
Обнаружение событий движения встряски с UIEvent
Когда пользователи встряхивают устройство, iOS оценивает данные акселерометра. Если данные удовлетворяют определенные критерии, iOS интерпретирует дрожащий жест и создает a UIEvent
объект представлять его. Затем это отправляет объект-событие в в настоящее время активное приложение для обработки. Обратите внимание на то, что Ваше приложение может реагировать на события движения встряски и изменения ориентации устройства одновременно.
События движения более просты, чем сенсорные события. Система говорит приложение, когда движение запускается и останавливается, но не, когда происходит каждое отдельное движение. И, события движения включают только тип события (UIEventTypeMotion
), подтип события (UIEventSubtypeMotionShake
), и метка времени.
Обозначение первого респондента для событий движения
Для получения событий движения определяйте объект респондента как первого респондента. Это - объект респондента, что Вы хотите обработать события движения. Перечисление 4-2 показывает, как респондент может сделать себя первым респондентом.
Перечисление 4-2 , Становящееся первым респондентом
- (BOOL)canBecomeFirstResponder { |
return YES; |
} |
- (void)viewDidAppear:(BOOL)animated { |
[self becomeFirstResponder]; |
} |
События движения используют цепочку респондента для нахождения объекта, который может обработать событие. Когда пользователь начинает встряхивать устройство, iOS отправляет первое событие движения первому респонденту. Если первый респондент не обрабатывает событие, оно развивается цепочка респондента. Посмотрите, что Цепочка Респондента Следует за Определенным Путем Поставки для получения дополнительной информации. Если событие встряхивающего движения перемещается цепочка респондента в окно, не будучи обработанным и applicationSupportsShakeToEdit
свойство UIApplication
установлен в YES
(значение по умолчанию), iOS выводит на экран лист с командами Undo и Redo.
Реализация методов обработки движения
Существует три метода обработки движения: motionBegan:withEvent:
, motionEnded:withEvent:
, и motionCancelled:withEvent:
. Для обработки событий движения необходимо реализовать любого motionBegan:withEvent:
метод или motionEnded:withEvent:
метод, и иногда оба. Респондент должен также реализовать motionCancelled:withEvent:
метод для ответа, когда iOS отменяет событие движения. Событие отменяется, если движение встряски прервано или если iOS решает, что движение не допустимо, в конце концов —, например, если сотрясение длится слишком долго.
Перечисление 4-3 извлечено из проекта примера кода, GLPaint. В этом приложении пользователь подрисовывает экран, и затем встряхивает устройство для стирания рисования. Этот код обнаруживает, произошла ли встряска в motionEnded:withEvent:
метод, и если это имеет, отправляет уведомление для выполнения функциональности встряски к стиранию.
Перечисление 4-3 , Обрабатывающее событие движения
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { |
if (motion == UIEventSubtypeMotionShake) |
{ |
// User was shaking the device. Post a notification named "shake." |
[[NSNotificationCenter defaultCenter] postNotificationName:@"shake" object:self]; |
} |
} |
Установка и проверка требуемых возможностей оборудования для событий движения
Прежде чем Ваше приложение может связанные с устройством доступа функции, такие как данные акселерометра, необходимо добавить список требуемых возможностей к приложению. В частности Вы добавляете ключи к своему приложению Info.plist
файл. Во время выполнения iOS запускает Ваше приложение, только если устройство имеет требуемые возможности. Например, если Ваше приложение полагается на данные гироскопа, перечислите гироскоп как требуется так, чтобы Ваше приложение не запускалось на устройствах без гироскопа. App Store также использует этот список для информирования пользователей так, чтобы они могли избежать загружать приложения, которые они не могут выполнить.
Объявите требуемые возможности своего приложения путем добавления ключей к списку свойств приложения. Существуют два UIRequiredDeviceCapabilities
ключи для событий движения, на основе аппаратного источника:
accelerometer
gyroscope
Можно использовать или массив или словарь для указания значений ключа. Если Вы используете массив, перечисляете каждую требуемую функцию как ключ в массиве. При использовании словаря укажите булево значение для каждого требуемого ключа в словаре. В обоих случаях перечисление ключа для функции указывает, что не требуется функция. Для получения дополнительной информации посмотрите UIRequiredDeviceCapabilities.
Если функции Вашего приложения, использующие данные гироскопа, не являются неотъемлемой частью пользовательского опыта, Вы могли бы хотеть позволить пользователям с устройствами негироскопа загружать Ваше приложение. Если Вы не делаете гироскоп требуемой возможностью оборудования, но все еще имеете код, запрашивающий данные гироскопа, необходимо проверить, доступен ли гироскоп во время выполнения. Вы делаете это с gyroAvailable
свойство CMMotionManager
класс.
Получение перемещения устройств с базовым движением
Базовая платформа Движения прежде всего ответственна за доступ к необработанному акселерометру и данным гироскопа и передаче тех данных к приложению для обработки. Базовое Движение использует уникальные алгоритмы для обработки необработанных данных, которые оно собирает, так, чтобы оно могло представить более усовершенствованную информацию. Эта обработка происходит на собственном потоке платформы.
Базовое Движение отлично от UIKit. Это не соединяется с UIEvent
модель и не использует цепочку респондента. Вместо этого Базовое Движение просто поставляет события движения непосредственно приложениям, запрашивающим их.
Базовые события Motion представлены тремя объектами данных, каждый инкапсулирующий одно или более измерений:
A
CMAccelerometerData
возразите получает ускорение вдоль каждой из пространственных осей.A
CMGyroData
возразите получает уровень вращения вокруг каждой из трех пространственных осей.A
CMDeviceMotion
объект инкапсулирует несколько различных измерений, включая отношение и более полезные измерения скорости вращения и ускорения.
CMMotionManager
класс является центральной точкой доступа для Базового Движения. Вы создаете экземпляр класса, указываете интервал обновления, запрашиваете, чтобы обновления запустились и обработали события движения, когда они поставлены. Приложение должно создать только единственный экземпляр CMMotionManager
класс. Многократные экземпляры этого класса могут влиять на уровень, на котором приложение получает данные от акселерометра и гироскопа.
Все инкапсулирующие данные классы Базового Движения являются подклассами CMLogItem
, который определяет метку времени так, чтобы данные движения могли тегироваться со временем и регистрироваться к файлу. Приложение может сравнить метку времени событий движения с более ранними событиями движения для определения истинного интервала обновления между событиями.
Для каждого из описанных типов движения данных, CMMotionManager
класс предлагает два подхода для получения данных движения:
Вытянуть. Запросы приложения, которые обновления запускают и затем периодически выбирают новое измерение данных движения.
Продвинуть. Приложение указывает интервал обновления и реализует блок для обработки данных. Затем это запрашивает, чтобы обновления запустились, и Ядро передач Показывает жестом очередь работы и блок. Базовое Движение поставляет каждое обновление блоку, выполняющемуся как задача в очереди работы.
Получение по запросу является рекомендуемым подходом для большинства приложений, особенно игры. Это обычно более эффективно и требует меньшего количества кода. Нажатие является подходящим для приложений сбора данных и подобных приложений, которые не могут пропустить единственное демонстрационное измерение. Оба подхода имеют мягкие эффекты потокобезопасности; с нажатием Ваш блок выполняется на потоке очереди работы, тогда как с получением по запросу, Базовое Движение никогда не прерывает Ваши потоки.
Всегда останавливайте обновления движения, как только Ваше приложение заканчивает обрабатывать необходимые данные. В результате Базовое Движение может выключить датчики движения, который сохраняет заряд батареи.
Выбор интервала обновления события движения
Когда Вы запрашиваете данные движения с Базовым Движением, Вы указываете интервал обновления. Необходимо выбрать самый большой интервал, удовлетворяющий потребности приложения. Чем больше интервал, тем меньше событий поставлено Вашему приложению, улучшающему время работы от батареи. Таблица 4-1 перечисляет некоторые общие частоты обновления и объясняет, что можно сделать с данными, сгенерированными в той частоте. Для немногих приложений нужны ускоряющие события, поставленные 100 раз в секунду.
Частота события (Гц) | Использование |
---|---|
10–20 | Подходящий для определения текущего вектора ориентации устройства. |
30–60 | Подходящий для игр и других приложений, использующих акселерометр для ввода данных пользователем в реальном времени. |
70–100 | Подходящий для приложений, которые должны обнаружить высокочастотное движение. Например, Вы могли бы использовать этот интервал для обнаружения пользователя, поражающего устройство или встряхивающего его очень быстро. |
Можно установить интервал создания отчетов, чтобы быть всего 10 миллисекундами (мс), соответствующий частоте обновления на 100 Гц, но большая часть приложения работает достаточно с большим интервалом.
Обработка событий акселерометра Используя базовое движение
Акселерометр измеряет скорость в течение долгого времени вдоль трех осей, как показано на рисунке 4-1. С Базовым Движением каждое перемещение получено в a CMAccelerometerData
объект, инкапсулирующий структуру типа CMAcceleration
.
Чтобы начать получать и обрабатывать данные акселерометра, создайте экземпляр CMMotionManager
класс и вызов один из следующих методов:
startAccelerometerUpdates
— подход получения по запросуПосле вызова этого метода Базовое Движение постоянно обновляет
accelerometerData
свойствоCMMotionManager
с последним измерением действия акселерометра. Затем Вы периодически выбираете это свойство, обычно в цикле рендеринга, который распространен в играх. Если Вы принимаете этот подход опроса, устанавливаете свойство интервала обновления (accelerometerUpdateInterval
) к максимальному интервалу, в котором Базовое Движение выполняет обновления.startAccelerometerUpdatesToQueue:withHandler:
— подход нажатияПрежде чем Вы вызовете этот метод, присвоите интервал обновления
accelerometerUpdateInterval
свойство, создайте экземплярNSOperationQueue
и реализуйте блок типаCMAccelerometerHandler
это обрабатывает обновления акселерометра. Затем вызовитеstartAccelerometerUpdatesToQueue:withHandler:
метод на объекте менеджера движения, передающем в очереди работы и блоке. В указанном интервале обновления Базовое Движение передает последнюю выборку действия акселерометра к блоку, выполняющемуся как задача в очереди.Перечисление 4-4 иллюстрирует этот подход.
Перечисление 4-4 извлечено из проекта примера кода MotionGraphs, который можно исследовать на большее количество контекста. В этом приложении пользователь перемещает ползунок для указания интервала обновления. startUpdatesWithSliderValue:
метод использует значение ползунка для вычислений нового интервала обновления. Затем это создает экземпляр CMMotionManager
класс, проверки, чтобы удостовериться, что устройство имеет акселерометр и присваивает интервал обновления менеджеру по движению. Это приложение использует подход нажатия, чтобы получить данные акселерометра и графически изобразить его на графике. Обратите внимание на то, что это останавливает обновления акселерометра в stopUpdates
метод.
Перечисление 4-4 , Получающее доступ к данным акселерометра в MotionGraphs
static const NSTimeInterval accelerometerMin = 0.01; |
- (void)startUpdatesWithSliderValue:(int)sliderValue { |
// Determine the update interval |
NSTimeInterval delta = 0.005; |
NSTimeInterval updateInterval = accelerometerMin + delta * sliderValue; |
// Create a CMMotionManager |
CMMotionManager *mManager = [(APLAppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager]; |
APLAccelerometerGraphViewController * __weak weakSelf = self; |
// Check whether the accelerometer is available |
if ([mManager isAccelerometerAvailable] == YES) { |
// Assign the update interval to the motion manager |
[mManager setAccelerometerUpdateInterval:updateInterval]; |
[mManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { |
[weakSelf.graphView addX:accelerometerData.acceleration.x y:accelerometerData.acceleration.y z:accelerometerData.acceleration.z]; |
[weakSelf setLabelValueX:accelerometerData.acceleration.x y:accelerometerData.acceleration.y z:accelerometerData.acceleration.z]; |
}]; |
} |
self.updateIntervalLabel.text = [NSString stringWithFormat:@"%f", updateInterval]; |
} |
- (void)stopUpdates { |
CMMotionManager *mManager = [(APLAppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager]; |
if ([mManager isAccelerometerActive] == YES) { |
[mManager stopAccelerometerUpdates]; |
} |
} |
Обработка данных скорости вращения
Гироскоп измеряет уровень, на котором устройство вращается вокруг каждой из трех пространственных осей, как показано на рисунке 4-2.
Каждый раз, когда Вы запрашиваете обновление гироскопа, Базовое Движение берет смещенную оценку уровня вращения и возвращает эту информацию в a CMGyroData
объект. CMGyroData
имеет a rotationRate
свойство, хранящее a CMRotationRate
структура, получающая скорость вращения для каждой из этих трех осей в радианах в секунду. Обратите внимание на то, что скорость вращения, измеренная a CMGyroData
объект смещается. Можно получить намного более точное, несмещенное измерение при помощи CMDeviceMotion
класс. Посмотрите Обработку Обработанные Данные Движения Устройства для получения дополнительной информации.
При анализе данных скорости вращения — в частности, при анализе полей CMRotationMatrix
структура — следует за «правилом правой руки» для определения направления вращения, как показано на рисунке 4-2. Например, при обертывании правой руки вокруг оси X, таким образом, что подсказка точек ползунка к положительному x, положительное вращение один к подсказкам других четырех пальцев. Отрицательное вращение уходит от подсказок тех пальцев.
Чтобы начать получать и обрабатывать данные скорости вращения, создайте экземпляр CMMotionManager
класс и вызов один из следующих методов:
startGyroUpdates
— подход получения по запросуПосле вызова этого метода Базовое Движение постоянно обновляет
gyroData
свойствоCMMotionManager
с последним измерением действия гироскопа. Затем Вы периодически выбираете это свойство. Если Вы принимаете этот подход опроса, устанавливаете свойство интервала обновления (gyroUpdateInterval
) к максимальному интервалу, в котором Базовое Движение выполняет обновления.startGyroUpdatesToQueue:withHandler:
— подход нажатияПрежде чем Вы вызовете этот метод, присвоите интервал обновления
gyroUpdateInterval
свойство, создайте экземплярNSOperationQueue
, и реализуйте блок типаCMGyroHandler
это обрабатывает обновления гироскопа. Затем вызовитеstartGyroUpdatesToQueue:withHandler:
метод на объекте менеджера движения, передающем в очереди работы и блоке. В указанном интервале обновления Базовое Движение передает последнюю выборку действия гироскопа к блоку, выполняющемуся как задача в очереди.Перечисление 4-5 демонстрирует этот подход.
Перечисление 4-5 также извлечено из проекта примера кода MotionGraphs и почти идентично Перечислению 4-4. Приложение использует подход нажатия для получения данных гироскопа так, чтобы это могло графически изобразить данных на экране.
Перечисление 4-5 , Получающее доступ к данным гироскопа в MotionGraphs
static const NSTimeInterval gyroMin = 0.01; |
- (void)startUpdatesWithSliderValue:(int)sliderValue { |
// Determine the update interval |
NSTimeInterval delta = 0.005; |
NSTimeInterval updateInterval = gyroMin + delta * sliderValue; |
// Create a CMMotionManager |
CMMotionManager *mManager = [(APLAppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager]; |
APLGyroGraphViewController * __weak weakSelf = self; |
// Check whether the gyroscope is available |
if ([mManager isGyroAvailable] == YES) { |
// Assign the update interval to the motion manager |
[mManager setGyroUpdateInterval:updateInterval]; |
[mManager startGyroUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMGyroData *gyroData, NSError *error) { |
[weakSelf.graphView addX:gyroData.rotationRate.x y:gyroData.rotationRate.y z:gyroData.rotationRate.z]; |
[weakSelf setLabelValueX:gyroData.rotationRate.x y:gyroData.rotationRate.y z:gyroData.rotationRate.z]; |
}]; |
} |
self.updateIntervalLabel.text = [NSString stringWithFormat:@"%f", updateInterval]; |
} |
- (void)stopUpdates{ |
CMMotionManager *mManager = [(APLAppDelegate *)[[UIApplication sharedApplication] delegate] sharedManager]; |
if ([mManager isGyroActive] == YES) { |
[mManager stopGyroUpdates]; |
} |
} |
Обработка обработанных данных движения устройства
Если устройство имеет и акселерометр и гироскоп, Базовое Движение предлагает услугу движения устройства, обрабатывающую необработанные данные движения от обоих датчиков. Движение устройства использует алгоритмы слияния датчика, чтобы совершенствовать необработанные данные и генерировать информацию для отношения устройства, его несмещенной скорости вращения, направления силы тяжести на устройстве и сгенерированного пользователями ускорения. Экземпляр CMDeviceMotion
класс инкапсулирует все эти данные. Кроме того, Вы не должны фильтровать ускоряющие данные, потому что движение устройства разделяет пользовательское ускорение и сила тяжести.
Можно получить доступ к данным отношения через a CMDeviceMotion
объект attitude
свойство, инкапсулирующее a CMAttitude
объект. Каждый экземпляр CMAttitude
класс инкапсулирует три математических представления отношения:
кватернион
матрица вращения
три Эйлеровых угла (рулон, подача и отклонение от курса)
Чтобы начать получать и обрабатывать обновления движения устройства, создайте экземпляр CMMotionManager
класс и вызов один из следующих двух методов на нем:
startDeviceMotionUpdates
— подход получения по запросуПосле вызова этого метода Базовое Движение постоянно обновляет
deviceMotion
свойствоCMMotionManager
с последними усовершенствованными измерениями акселерометра и действием гироскопа, как инкапсулируется в aCMDeviceMotion
объект. Затем Вы периодически выбираете это свойство. Если Вы принимаете этот подход опроса, устанавливаете свойство интервала обновления (deviceMotionUpdateInterval
) к максимальному интервалу, в котором Базовое Движение выполняет обновления.Перечисление 4-6 иллюстрирует этот подход.
startDeviceMotionUpdatesToQueue:withHandler:
— подход нажатияПрежде чем Вы вызовете этот метод, присвоите интервал обновления
deviceMotionUpdateInterval
свойство, создайте экземплярNSOperationQueue
, и реализуйте блокCMDeviceMotionHandler
введите, который обрабатывает обновления акселерометра. Затем вызовитеstartDeviceMotionUpdatesToQueue:withHandler:
метод на объекте менеджера движения, передающем в очереди работы и блоке. В указанном интервале обновления Базовое Движение передает последнюю выборку объединенного акселерометра и действие гироскопа, как представлено aCMDeviceMotion
объект, к блоку, выполняющемуся как задача в очереди.
Перечисление 4-6 использует код из проекта примера кода парка продемонстрировать, как запустить и остановить обновления движения устройства. startDeviceMotion
метод использует подход получения по запросу для запуска обновлений устройств со ссылочного кадра. Посмотрите Отношение Устройства и Ссылочный Кадр для больше о ссылочных кадрах движения устройства.
Перечисление 4-6 Стартовые и останавливающиеся обновления движения устройства
- (void)startDeviceMotion { |
// Create a CMMotionManager |
motionManager = [[CMMotionManager alloc] init]; |
// Tell CoreMotion to show the compass calibration HUD when required |
// to provide true north-referenced attitude |
motionManager.showsDeviceMovementDisplay = YES; |
motionManager.deviceMotionUpdateInterval = 1.0 / 60.0; |
// Attitude that is referenced to true north |
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical]; |
} |
- (void)stopDeviceMotion { |
[motionManager stopDeviceMotionUpdates]; |
} |
Отношение устройства и ссылочный кадр
A CMDeviceMotion
объект содержит информацию об отношении устройства или ориентацию в пространстве. Отношение устройства всегда измеряется в связи со ссылочным кадром. Когда Ваше приложение запускает обновления движения устройства, базовое Движение устанавливает ссылочный кадр. Затем CMAttitude
дает вращение от того начального ссылочного кадра до текущего ссылочного кадра устройства.
В Базовом ссылочном кадре Движения ось z является всегда вертикальной, и x-и ось y являются всегда ортогональными к силе тяжести, делающей вектор силы тяжести [0, 0,-1]. Это также известно как ссылка силы тяжести. Если Вы умножаетесь, матрица вращения получила из a CMAttitude
объект ссылкой силы тяжести, Вы получаете силу тяжести в кадре устройства. Или, математически:
Можно изменить ссылочный кадр это CMAttitude
использование. Чтобы сделать это, кэшируйте объект отношения, содержащий ссылочный кадр, и передайте его как параметр multiplyByInverseOfAttitude:
. Параметр отношения, получающий сообщение, изменяется так, чтобы это представляло изменение в отношении от переданного - в ссылочном кадре.
Большинство приложений интересуется изменением в отношении устройства. Чтобы видеть, как это могло бы быть полезно, рассмотрите бейсбольный матч, где пользователь поворачивает устройство для покачивания. Обычно, в начале подачи, летучая мышь была бы при некоторой покоящейся ориентации. После этого летучая мышь представляется на основе того, как отношение устройства изменилось от запуска подачи. Перечисление 4-7 иллюстрирует, как Вы могли бы сделать это.
Перечисление 4-7 , Получающее изменение в отношении до рендеринга
-(void) startPitch { |
// referenceAttitude is a property |
self.referenceAttitude = self.motionManager.deviceMotion.attitude; |
} |
- (void)drawView { |
CMAttitude *currentAttitude = self.motionManager.deviceMotion.attitude; |
[currentAttitude multiplyByInverseOfAttitude: self.referenceAttitude]; |
// Render bat using currentAttitude |
[self updateModelsWithAttitude:currentAttitude]; |
[renderer render]; |
} |
В этом примере, после multiplyByInverseOfAttitude:
возвраты метода, currentAttitude
представляет изменение в отношении от referenceAttitude
к последний раз выбранному CMAttitude
экземпляр.