#ios #swift #presentviewcontroller
Вопрос:
У меня есть CheckoutViewController с коллекционным представлением. В одной из этих ячеек отображается представление для ввода данных кредитной карты.
Платежная ячейка, в которой представлен вид
class PaymentCell_Checkout: UICollectionViewCell {
static let cellID = "PaymentCell_Checkout"
var delegate: Checkout_VC!
@objc func showPayWithView() {
let vc = PayWithView()
// let vc = CreditCardEntryView()
vc.delegate = delegate
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self
delegate.navigationController?.present(vc, animated: false, completion: nil)
}
}
extension PaymentCell_Checkout: UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
PaymentPresentationController(presentedViewController: presented, presenting: presenting)
}
}
Представленное представление имеет 4 различных варианта для выбора (табличное представление) и представлено пользовательским переходом с использованием UIViewControllerTransitioningDelegate и UIPresentationController. Все это отлично работает.
Просмотр, чтобы выбрать способ оплаты
class PayWithView: UIViewController {
var hasSetPointOrigin = false
var pointOrigin: CGPoint?
var delegate: Checkout_VC!
var payWithOptions: [PayWith] = []
struct Cells {
static let payCell = "PayCell"
}
lazy var tableView: UITableView = {
let tableView = UITableView()
tableView.alwaysBounceVertical = false
tableView.delegate = self
tableView.dataSource = self
tableView.rowHeight = 50
return tableView
}()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let selectedIndexPath = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: selectedIndexPath, animated: animated)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let selectedIndexPath = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: selectedIndexPath, animated: animated)
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
payWithOptions = setPayWith()
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureRecognizerAction))
view.addGestureRecognizer(panGesture)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
configTableView()
tableView.isScrollEnabled = tableView.contentSize.height > tableView.frame.size.height
}
override func viewDidLayoutSubviews() {
if !hasSetPointOrigin {
hasSetPointOrigin = true
pointOrigin = self.view.frame.origin
}
}
@objc func panGestureRecognizerAction(sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
guard translation.y >= 0 else { return }
view.frame.origin = CGPoint(x: 0, y: self.pointOrigin!.y translation.y)
if sender.state == .ended {
let dragVelocity = sender.velocity(in: view)
if dragVelocity.y >= 1300 {
self.dismiss(animated: true, completion: nil)
} else {
UIView.animate(withDuration: 0.3) {
self.view.frame.origin = self.pointOrigin ?? CGPoint(x: 0, y: 400)
}
}
}
}
}
//MARK: - Table View Methods
extension PayWithView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return payWithOptions.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Cells.payCell) as! PayWithCell
let payOptions = payWithOptions[indexPath.row]
cell.set(pay: payOptions)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
dismiss(animated: true)
}
if indexPath.row == 3 {
let vc = CreditCardEntryView()
vc.delegate = delegate
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self
self.navigationController?.present(vc, animated: false, completion: nil)
}
}
}
// Modal Presentation
extension PayWithView: UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
PaymentPresentationController(presentedViewController: presented, presenting: presenting)
}
}
UIPresentationController
class PaymentPresentationController: UIPresentationController {
let blurEffectView: UIVisualEffectView!
var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer()
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
let blurEffect = UIBlurEffect(style: .dark)
blurEffectView = UIVisualEffectView(effect: blurEffect)
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissController))
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.blurEffectView.isUserInteractionEnabled = true
self.blurEffectView.addGestureRecognizer(tapGestureRecognizer)
}
// Size of View
override var frameOfPresentedViewInContainerView: CGRect {
CGRect(origin: CGPoint(x: 0, y: self.containerView!.frame.height * 0.7),
size: CGSize(width: self.containerView!.frame.width, height: self.containerView!.frame.height *
0.3))
}
override func presentationTransitionWillBegin() {
self.blurEffectView.alpha = 0
self.containerView?.addSubview(blurEffectView)
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0.7
}, completion: { (UIViewControllerTransitionCoordinatorContext) in })
}
override func dismissalTransitionWillBegin() {
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0
}, completion: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.removeFromSuperview()
})
}
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
presentedView!.roundCornersCheckout([.topLeft, .topRight], radius: 22)
}
override func containerViewDidLayoutSubviews() {
super.containerViewDidLayoutSubviews()
presentedView?.frame = frameOfPresentedViewInContainerView
blurEffectView.frame = containerView!.bounds
}
@objc func dismissController() {
self.presentedViewController.dismiss(animated: true, completion: nil)
}
}
// Round Corners
extension UIView {
func roundCornersCheckout(_ corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}
When the user clicks on the EnterCreditCardView row in the presented tableView, I would like for it to also be presented with this custom transition and height. However visibly nothing happens. I have tested presenting it as the main/ first presented view from the CollectionCell and it works fine. I think I need to dismiss the original TableView view but not sure. Thanks for any help🙏
EnterCreditCardView that should be presented but doesn’t
class CreditCardEntryView: UIViewController {
var hasSetPointOrigin = false
var pointOrigin: CGPoint?
var delegate: Checkout_VC!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
delegate.startCheckout()
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureRecognizerAction))
view.addGestureRecognizer(panGesture)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
addViews()
constrainViews()
}
override func viewDidLayoutSubviews() {
if !hasSetPointOrigin {
hasSetPointOrigin = true
pointOrigin = self.view.frame.origin
}
}
@objc func panGestureRecognizerAction(sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: view)
guard translation.y >= 0 else { return }
view.frame.origin = CGPoint(x: 0, y: self.pointOrigin!.y translation.y)
if sender.state == .ended {
let dragVelocity = sender.velocity(in: view)
if dragVelocity.y >= 1300 {
self.dismiss(animated: true, completion: nil)
} else {
UIView.animate(withDuration: 0.3) {
self.view.frame.origin = self.pointOrigin ?? CGPoint(x: 0, y: 400)
}
}
}
}
}
extension CreditCardEntryView {
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
PaymentPresentationController(presentedViewController: presented, presenting: presenting)
}
}
Let me know if you need anymore of the code, trying to keep it to a minimal.
ALSO I set up breakpoints and I know my didSelectRow is being called, it enters the method but the breakpoint in The ViewDidLoad for CreditCardEntryView never fires?
Like I said the view works fine when presented from CollectionCell but not from TableView row