Потеря ссылки на transitioningDelegate перед презентацией presetentation

У меня был рабочий пользовательский UIPresentationController до Xcode beta 2 и iOS 10 beta 2. Я не менял никакого кода, но теперь презентация представлена ​​в стандартном модальном представлении.

В примере кода Apple для UIPresentationController есть примечание:

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

transitioningDelegate не содержит сильной ссылки на свой целевой объект. Чтобы предотвратить выпуск PresentViewController до вызова -presentViewController: animated: completion: к объявлению добавляется атрибут NS_VALID_UNTIL_END_OF_SCOPE.

Я проверил transitioningDelegate на представленном контроллере представления до и после презентации. Раньше это мой пользовательский UIPresentationController, а после - ноль. Я предполагаю, что ссылка выпущена, но я не могу найти эквивалент NS_VALID_UNTIL_END_OF_SCOPE в Swift. РЕДАКТИРОВАТЬ: Я проверил, что transitioningDelegate настроено непосредственно перед презентацией, а затем равно нулю, когда пора представить.

Мой код в контроллере представления представления:

@IBAction func buttonAction(_ sender: UIButton) {
    let secondViewController = storyboard!.instantiateViewController(withIdentifier: "NewViewController") as! NewViewController
    let presentationController = MyPresentationController(presentedViewController: secondViewController, presenting: self)
    presentationController.initialFrame = button.frame
    secondViewController.transitioningDelegate = presentationController

    // Move map
    let pixelsToMove: CGFloat = mapView.frame.height / 4
    let region = self.mapView.region

    self.mapView.setRegion(region, offsetBy: pixelsToMove, animated: true)

    // Delegate to NewViewController
    secondViewController.mapView = mapView
    mapView.delegate = secondViewController

    print(secondViewController.transitioningDelegate)
    UIView.animate(withDuration: 0.3, animations: {
        let tabBar = self.tabBarController!.tabBar
        tabBar.frame.origin.y += tabBar.frame.height

        self.present(secondViewController, animated: true, completion: nil)
    })
}

И мой код в UIPresentationController:

override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
    super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
    presentedViewController.modalPresentationStyle = .custom
}

person jjatie    schedule 22.07.2016    source источник
comment
попробуйте объявить PresentationController перед тем, как выйти за пределы метода.   -  person Deepak Kumar    schedule 01.08.2016
comment
Пробовал, но проблема не исчезла.   -  person jjatie    schedule 01.08.2016
comment
попробуйте это self.presentViewController.transitioningDelegate   -  person Deepak Kumar    schedule 01.08.2016
comment
Как я уже сказал, устанавливается transitioningDelegate, но непосредственно перед тем, как происходит переход, ссылка теряется.   -  person jjatie    schedule 01.08.2016


Ответы (2)


Свойство transitioningDelegate - это weak var. См. Документы здесь. Это означает, что счетчик удержания для presentationController не увеличивается при установке secondViewController.transitioningDelegate = presentationController. Поскольку вы создаете экземпляр presentationController в этом методе, и ничто другое не имеет сильной ссылки на этот объект, его счетчик сохранений будет равен 0, и он будет равен нулю, как только управление будет возвращено из этой функции (сразу после print(secondViewController.transitioningDelegate), поскольку UIView.animate(...) является асинхронным) .

Вам понадобится что-то, чтобы постоянно ссылаться на presentationController на протяжении всей презентации контроллера представления. Если что-то сильно привязано к ссылке, его счетчик удержаний не опустится ниже 1, пока вы специально не установите для этой ссылки значение nil. Одно из решений - сохранить его как свойство текущего класса или свойство secondViewController.

person keithbhunter    schedule 01.08.2016
comment
Я попробую это сегодня. Почему он работал бы в iOS 10 beta 1 и 9.3.x без ссылки на него? - person jjatie; 02.08.2016
comment
К сожалению, я не уверен. Я бы предположил, что раньше это не сработало бы. - person keithbhunter; 02.08.2016
comment
Я попытался сохранить его с сильной ссылкой в ​​контроллерах презентации, презентации и презентации, и transitioningDelegate все еще становится нулевым, когда происходит презентация - person jjatie; 03.08.2016
comment
Голосую за этот ответ. Я должен иметь сильную ссылку на переходный делегат в моем представлении viewcontroller. Он не будет выпущен, когда представленный контроллер представления будет закрыт и анимация перехода при увольнении будет воспроизведена безупречно. - person fans3210; 09.09.2017

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

person jjatie    schedule 07.08.2016
comment
Это была моя проблема. Протокол делегата имеет все необязательные функции, поэтому мои функции с некорректными подписями игнорировались. Для получения дополнительной информации см .: stackoverflow.com/a/39513247/959896 - person Mathieu Frenette; 10.03.2017