CGAffineTransformMakeRotation вращается в 3D

У меня никогда такого не было, и я не могу понять, что происходит. Я подозреваю, что это может быть автоматический макет, но я не понимаю, как это сделать. У меня есть представление «Компас», в котором есть несколько подпредставлений, которыми оно управляет (не является частью автоматического макета). Вот пример их настройки:

- (ITMView *) compass {
    if (!_compass){
        _compass = [ITMView new];
        _compass.backgroundColor = [UIColor blueColor];
        _compass.layer.anchorPoint = CGPointMake(.5,    .5);
        _compass.translatesAutoresizingMaskIntoConstraints = NO;
        _compass.frame = self.bounds;
        __weak ITMCompassView *_self = self;
        _compass.onDraw = ^(CGContextRef ref, CGRect frame) { [_self drawCompassWithFrame:frame]; };
        [self addSubview:_compass];
    }
    return _compass;
}

Мне нужно повернуть компас в ответ на изменение направления:

- (void) setCurrentHeading:(double)currentHeading{
    _currentHeading = fmod(currentHeading, 360);
    double rad = (M_PI / 180) * _currentHeading;
    self.compass.transform = CGAffineTransformMakeRotation(rad);
}

Проблема в том, что по какой-то причине он вращается вокруг оси Z:

введите здесь описание изображения

Я не манипулирую преобразованиями слоев в любых других представлениях. Кто-нибудь знает, почему это происходит?

Обновлять

Я проверил преобразование для всех супервизоров. Каждое суперпредставление имеет преобразование идентичности.

Я зарегистрировал преобразование вида компаса до и после того, как он был установлен в первый раз. До того, как он был установлен, преобразование имело идентичность, что и ожидалось. После того, как я установил преобразование для поворота на 242.81 градуса (4.24 рад), я получаю:

[
  -0.47700124155378526, -0.87890262006444575, 
  0.87890262006444575, -0.47700124155378526, 
  0, 0
]

Обновление 2

Я проверил CATransform3DIsAffine, и он всегда возвращает YES. Я дважды проверил преобразование слоя и для поворота на 159.7 (градусов) получил:

[
 -0.935,  0.356,   0, 0, 
 -0.356, -0.935,   0, 0, 
  0,      0,       1, 0, 
  0,      0,       0, 1
]

Это выглядит правильно для меня.

Все преобразования правильные, но они все еще неправильно отображаются на экране.

Обновление 3

Я удалил свой код рисования из вида и установил синий фон вида. Вид определенно поворачивается, сжимается или что-то в этом роде:

введите здесь описание изображения

Некоторые вещи, которые следует отметить:

  • Вид отображается корректно при 90, 180, 270 и 0 градусах.
  • Вид исчезает (включен на край) при 45, 135, 225 и 315 градусах.
  • Представление выглядит так, как будто оно вращается в 3D с изменением угла от 0 до 360 градусов.

person Aaron Hayman    schedule 07.02.2015    source источник
comment
Я бы тоже так подумал, за исключением того, что я больше нигде в этом приложении не использую никаких преобразований. Более того, я установил это как IB_Desgniable в IB и вручную установил значения. Там делают то же самое.   -  person Aaron Hayman    schedule 07.02.2015
comment
Я только что добавил обновление. Не уверен, что полученные числа верны или нет.   -  person Aaron Hayman    schedule 07.02.2015
comment
Я запускал CATransform3DIsAffine как до, так и после установки преобразования, и оба раза он возвращал YES.   -  person Aaron Hayman    schedule 07.02.2015
comment
Так что это не 3D-вращение (по крайней мере, не на этом виде). Это хорошо. Теперь вам нужно выяснить, что вы на самом деле видите. Как я уже говорил, возможно, представление просто сжимается внутрь и перерисовывается, чтобы соответствовать его сжатому размеру. Возможно, в каком-то супервизоре есть 3D-вращение (хотя вы, кажется, уже исключили это). Как бы то ни было, мы доказали, что в результате преобразования представления, которое вы применяете, не происходит ничего смешного.   -  person matt    schedule 07.02.2015


Ответы (1)


Я не уверен, почему @matt отозвал свой ответ, но он был прав: представление компаса сбрасывало кадр каждый раз, когда я делал поворот в методе layoutSubviews в моем содержащем суперпредставлении. Я не ожидал этого, думая, что ротация не вызовет layoutSubviews. Кадр никогда не менялся, но примененное преобразование искажало результаты, поскольку кадр был повторно применен к виду. Что меня поразило, так это то, что результаты действительно выглядели так, как будто вид вращался в 3D, что привело меня в эту конкретную кроличью нору. По крайней мере, теперь я знаю, что искать.

Кое-что, что я хочу отметить: кажущееся трехмерное вращение было очень особенным. Он вращался вокруг каждой диагональной комбинации {x,Y} последовательно между каждым квадрантом 90° единичного круга. Это имеет смысл, если вы думаете о том, как кадр будет искажаться в течение этих периодов.

Решение достаточно простое: сохраните и удалите преобразование перед установкой кадра подпредставления, а затем повторно примените преобразование. Однако, поскольку вращение применяется очень и очень часто (внутри блока анимации не реже), я добавил escape, чтобы уменьшить нагрузку:

- (void) layoutSubviews{
    [super layoutSubviews];
    if (!CGRectEqualToRect(_lastLayout, self.bounds)){
        CGRect frame = SquareRectAndPosition(self.bounds, CGRectXCenter, CGRectYCenter);
        CGAffineTransform t;

        t = self.compass.transform;
        self.compass.transform = CGAffineTransformIdentity;
        self.compass.frame = frame;
        self.compass.transform = t;
        t = self.target.transform;
        self.target.transform = CGAffineTransformIdentity;
        self.target.frame = frame;
        self.target.transform = t;
    }
    _lastLayout = self.bounds;
}
person Aaron Hayman    schedule 08.02.2015