Почему UIView не остается в центре, пока он вращается?

Я пытаюсь откалибровать UIView, чтобы оставаться в центре, когда он вращается. Это следует за проблемой, выявленной наилучшими ответами на мой предыдущий вопрос . С тех пор я разработал код, основанный на одном ответе, предлагающем использовать viewWillAppear или viewDidLayoutSubviews вместо viewDidLoad .

Поскольку я новичок в Swift, мне пришлось вернуться к учебнику Swift. Внедрение пользовательского элемента управления, в котором описывается, как сделать subClass из UIView . Мой код может рисовать круг, используя любую из трех функций: viewWillAppear , viewDidLayoutSubviews или viewDidLoad .

Однако, когда я визуализую код, круг не всегда остается в центре, когда экран вращается. Ниже приведены последовательные вращения, которые происходят с использованием viewDidLoad или viewWillAppear viewDidLoad или viewWillAppear Когда приложение запускается на экране в портретной ориентации, проблема возникает сразу же после первого поворота, независимо от того, влево или вправо. Если запустить в альбомной ориентации, можно пропустить проблему, если вы не пробовали хотя бы четыре последовательных вращения.

Ниже приведены последовательные повороты, которые происходят с использованием viewDidLayoutSubviews где поворот иногда приводит к тому, что viewDidLayoutSubviews круг накладывается на нецентральный круг. viewDidLayoutSubviews Это может произойти после нескольких поворотов, но для того, чтобы заметить проблему, нужно выполнить по крайней мере четыре оборота.

Вот код для CircleView – моя попытка создать подкласс UIView

 import UIKit class CircleView: UIView { let radius = CGFloat(200) let x: CGFloat = 0 let y: CGFloat = 0 // MARK: Initialization required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override init(frame: CGRect) { super.init(frame: frame) setup() } func setup() { // Create a CAShapeLayer let shapeLayer = CAShapeLayer() // The Bezier path that we made needs to be converted // to a CGPath before it can be used on a layer. shapeLayer.path = createBezierPath().cgPath // apply other properties related to the path shapeLayer.strokeColor = UIColor.red.cgColor shapeLayer.fillColor = UIColor.white.cgColor shapeLayer.lineWidth = 8.0 // add the new layer to our custom view self.layer.addSublayer(shapeLayer) } func createBezierPath() -> UIBezierPath { // create a new path let path = UIBezierPath(arcCenter: CGPoint(x: x, y: y), radius: radius, startAngle: CGFloat(M_PI * -0.5), endAngle:CGFloat(M_PI * 1.5), clockwise: true) path.fill() path.stroke() return path } } 

и вот код для ViewController

 import UIKit class ViewController: UIViewController { var circle: CircleView? var x: CGFloat? var y: CGFloat? override func viewDidLoad() { super.viewDidLoad() let centre = centreCircle() // create a new UIView and add it to the view controller let circleView = CircleView() circleView.frame = CGRect(x: centre.x, y: centre.y, width: 0, height: 0) view.addSubview(circleView) } func centreCircle() -> CGPoint { circle?.bounds = UIScreen.main.bounds return CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY) } } 

И вот код для расширения UIScreen, который возвращает центральную точку экрана

 import UIKit extension UIScreen { var centre: CGPoint { return CGPoint(x: bounds.midX, y: bounds.midY) } } 

Чтобы произвести вышеупомянутые вращения, я заменил функцию viewWillAppear

  override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) let centre = centreCircle() // create a new UIView and add it to the view controller let circleView = CircleView() circleView.frame = CGRect(x: centre.x, y: centre.y, width: 0, height: 0) view.addSubview(circleView) } 

или viewDidLayoutSubviews

  override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let centre = centreCircle() // create a new UIView and add it to the view controller let circleView = CircleView() circleView.frame = CGRect(x: centre.x, y: centre.y, width: 0, height: 0) view.addSubview(circleView) } 

Может ли кто-нибудь увидеть проблему в моем коде, которая может остановить работу от работы?

Прежде всего, представление не выложено должным образом в viewdidload и viewwillappear, и вы явно определяете фрейм со значениями, что я считаю крайне расстраивающим, как новый программист. Это все еще раздражает меня, особенно когда речь заходит об изменении размеров меток. Таким образом, ваш взгляд и центральное окно centreX и centreY означают, что ваш взгляд будет придерживаться в тот момент, когда вы вращаетесь.

Исправьте это, изучив автозапуск. Сначала это отстой, но в конечном итоге это облегчит вашу жизнь. Взгляните на метод в этом расширении. Я использую его, когда хочу сосредоточить взгляд на другом представлении

 extension UIView { func constrainAndCenter(in view: UIView, withRelativeHeight: CGFloat, withRelativeWidth: CGFloat) -> [NSLayoutConstraint] { self.translatesAutoresizingMaskIntoConstraints = false let x = NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1, constant: 0) let w = NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: withRelativeWidth, constant: 0) let h = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: withRelativeHeight, constant: 0) let y = NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0) return ([x,w,h,y]) } } // then in viewdidload or whereever let circleView = CircleView() let circleViewConstraints = circleView.constrainAndCenter(in: view,....) view.addSubview(circleView) NSLayoutConstraint.activate(circleViewConstraints) 

Это приколот к середине. Вы также можете сделать это в построителе интерфейса.

вы должны заменить frame.bounds на frame.center чтобы центр был рассчитан правильно.

  • Как получить первый символ каждого слова в строке?
  • В Swift, как ivalidate NSTimer в AppDelegate при запуске приложения?
  • Не удается получить доступ к NSUserDefaults, используя группы приложений друг к другу
  • IOS 8 Swift AVAudioPlayer воспроизводит удаленный звук (wowza server)
  • Swift: как извлечь имя файла изображения из массива UIImage
  • UIImagePickerController падает на iOS10
  • UISnamator UISnapBehavior возможно с UIScrollview?
  • TableView округлые углы и тени
  • Swift: получение «неоднозначного выражения» при попытке передать кортеж функции обратного вызова
  • Реализация 3D touch / Force touch
  • iOS Swift Сохранить файл изображения в папку Temp
  • Interesting Posts

    Как отправить промо-коды для бета-тестирования, не делая приложение доступным в App Store?

    Во время каскадирования 2 аудиофайлов trackWithMediaType всегда возвращает пустой массив

    Предотвращение автоматического поворота AlertView

    Технические различия между mach_override и рыболовным крючком?

    Многоэтапная анимация с использованием блоков

    Определите, когда заканчивается MKRoutestep

    Почему ячейки таблицы просмотра исчезают при перезагрузке с помощью reloadRowsAtIndexPaths?

    Проверить приложение на ошибку архива магазина iOS

    Автоматическое сохранение сетей автосохранения

    Графики: получение выбранных данных бара только при нажатии на панель

    Знание разрешения предварительных настроек сеанса AVCaptureSession

    Как рассчитать количество дней с этого момента до NSDate?

    Отправить Email с помощью React Native iOS

    Сбой сборки AppStore при запуске на iPhone 3g и iPod Touch

    iOS AVAudioSession с применением фильтра верхних частот

    Давайте будем гением компьютера.