在预设演示之前丢失对 transitioningDelegate 的引用
Losing reference to transitioningDelegate before presetentation presentation
在 Xcode beta 2 和 iOS 10 beta 2 之前,我有一个可用的自定义 UIPresentationController。我没有更改任何代码,但演示文稿现在以标准模式演示文稿呈现.
UIPresentationController 的 Apple 示例代码中有一条说明:
For presentations which will use a custom presentation controller,
it is possible for that presentation controller to also be the
transitioningDelegate. This avoids introducing another object or
implementing in the source
view controller.
transitioningDelegate does not hold a strong reference to its destination object.To prevent presentationController from being
released prior to calling -presentViewController:animated:completion:
the NS_VALID_UNTIL_END_OF_SCOPE attribute is appended to the
declaration.
我已经在呈现前后检查了呈现的视图控制器上的 transitioningDelegate。在它之前是我的自定义 UIPresentationController,但在它之后是零。我的猜测是引用正在发布,但我在 Swift 中找不到与 NS_VALID_UNTIL_END_OF_SCOPE 等效的内容。 编辑: 我已经确认 transitioningDelegate 一直设置到演示之前,然后在演示时设置为 nil。
我在呈现视图控制器中的代码:
@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
}
transitioningDelegate
属性 是 weak var
。参见docs here。这意味着 presentationController
的保留计数在设置 secondViewController.transitioningDelegate = presentationController
时不会增加。由于您在该方法中实例化 presentationController
并且没有其他任何东西对该对象具有强引用,因此它的保留计数将变为 0,并且一旦从该函数返回控制权(就在 [=15 之后),它将变为 nil =],因为 UIView.animate(...)
是异步的)。
在整个视图控制器的呈现过程中,您需要一些东西来保持对 presentationController
的强引用。由于某些东西强烈地保留在引用中,它的保留计数不会低于 1,除非您将该引用专门设置为 nil
。一种解决方案是将其保留为当前 class 的 属性 或 secondViewController
.
的 属性
问题出在 beta 2 中,UIViewControllerTransitioningDelegate
中的方法签名发生了变化,因此我的代码中没有调用它们。我不明白为什么,但再一次一切都完美无缺,而无需显式存储对演示控制器的强引用。
在 Xcode beta 2 和 iOS 10 beta 2 之前,我有一个可用的自定义 UIPresentationController。我没有更改任何代码,但演示文稿现在以标准模式演示文稿呈现.
UIPresentationController 的 Apple 示例代码中有一条说明:
For presentations which will use a custom presentation controller, it is possible for that presentation controller to also be the transitioningDelegate. This avoids introducing another object or implementing in the source view controller.
transitioningDelegate does not hold a strong reference to its destination object.To prevent presentationController from being released prior to calling -presentViewController:animated:completion: the NS_VALID_UNTIL_END_OF_SCOPE attribute is appended to the declaration.
我已经在呈现前后检查了呈现的视图控制器上的 transitioningDelegate。在它之前是我的自定义 UIPresentationController,但在它之后是零。我的猜测是引用正在发布,但我在 Swift 中找不到与 NS_VALID_UNTIL_END_OF_SCOPE 等效的内容。 编辑: 我已经确认 transitioningDelegate 一直设置到演示之前,然后在演示时设置为 nil。
我在呈现视图控制器中的代码:
@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
}
transitioningDelegate
属性 是 weak var
。参见docs here。这意味着 presentationController
的保留计数在设置 secondViewController.transitioningDelegate = presentationController
时不会增加。由于您在该方法中实例化 presentationController
并且没有其他任何东西对该对象具有强引用,因此它的保留计数将变为 0,并且一旦从该函数返回控制权(就在 [=15 之后),它将变为 nil =],因为 UIView.animate(...)
是异步的)。
在整个视图控制器的呈现过程中,您需要一些东西来保持对 presentationController
的强引用。由于某些东西强烈地保留在引用中,它的保留计数不会低于 1,除非您将该引用专门设置为 nil
。一种解决方案是将其保留为当前 class 的 属性 或 secondViewController
.
问题出在 beta 2 中,UIViewControllerTransitioningDelegate
中的方法签名发生了变化,因此我的代码中没有调用它们。我不明白为什么,但再一次一切都完美无缺,而无需显式存储对演示控制器的强引用。