在子视图按钮中调用父功能

时间:2017-03-28 05:12:33

标签: ios swift parent-child

我试图在父控制器的子视图中调用一个按钮。

我父控制器的代码是:

import Mapbox
import UIKit

class MapBoxViewController: UIViewController, MGLMapViewDelegate {


override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
    self.navigationController?.navigationBar.shadowImage = UIImage()
    self.navigationController?.navigationBar.isTranslucent = true

    let mapView = MGLMapView(frame: view.bounds)

    mapView.delegate = self

    navigationItem.leftBarButtonItem = UIBarButtonItem(title:"Back", style: .plain, target: self, action: #selector(handleCancel))

    let styleURL = NSURL(string: "mapbox://styles/abrach/ciicttgle001j9clv6ucj91ip")
    mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    // Set the map’s center coordinate and zoom level.
    mapView.setCenter(CLLocationCoordinate2D(latitude: 45.52258, longitude: -122.6732), zoomLevel: 6, animated: false)
    let point = MGLPointAnnotation()
    point.coordinate = CLLocationCoordinate2D(latitude: 45.52258, longitude: -122.6732)
    point.title = "Voodoo Doughnut"
    point.subtitle = "22 SW 3rd Avenue Portland Oregon, U.S.A."

    mapView.addAnnotation(point)
    view.addSubview(mapView)
    addBottomSheetView()

}

func addBottomSheetView() {
    // 1- Init bottomSheetVC
    let bottomSheetVC = BottomSheetViewController()

    // 2- Add bottomSheetVC as a child view
    self.addChildViewController(bottomSheetVC)
    self.view.addSubview(bottomSheetVC.view)
    bottomSheetVC.didMove(toParentViewController: self)

    // 3- Adjust bottomSheet frame and initial position.
    let height = view.frame.height
    let width  = view.frame.width
    bottomSheetVC.view.frame = CGRect(x:0, y:self.view.frame.maxY, width: width, height: height)
}

func addSettings() {
    // 1- Init bottomSheetVC
    let settingsVC = settingsViewController()

    // 2- Add bottomSheetVC as a child view
    self.addChildViewController(settingsVC)
    self.view.addSubview(settingsVC.view)
    settingsVC.didMove(toParentViewController: self)

    // 3- Adjust bottomSheet frame and initial position.
    let height = view.frame.height
    let width  = view.frame.width
    settingsVC.view.frame = CGRect(x:0, y:self.view.frame.maxY, width: width, height: height)
}

func handleCancel() {
    dismiss(animated: true, completion: nil)
}
}

此函数在地图加载时将BottomSheetViewController调用为子视图。

BottomSheViewController的代码为:

import UIKit

class BottomSheetViewController: UIViewController {

var fullView: CGFloat {
    return 65
}
var partialView: CGFloat {
    return UIScreen.main.bounds.height - 57.5
}
var halfView: CGFloat {
    return (UIScreen.main.bounds.height/2) + 60
}

let buttonBackgroundView: UIView = {
    let view = UIView()
    view.backgroundColor = UIColor(r: 239, g: 239, b: 239)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.layer.cornerRadius = 8
    view.layer.masksToBounds = true
    return view
}()

lazy var addButton: UIButton = {
    let button = UIButton(type: .system)
    button.setTitle("Add", for: .normal)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.setTitleColor(UIColor(r: 88, g: 88, b: 88), for: .normal)
    button.titleLabel?.font = UIFont(name: "Nunito", size: 17)
    button.addTarget(self, action: #selector(handleTouch), for: .touchUpInside)
    return button
}()

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = UIColor.white
    let gesture = UIPanGestureRecognizer.init(target: self, action: #selector(BottomSheetViewController.panGesture))
    view.addGestureRecognizer(gesture)
    roundViews()
    view.addSubview(buttonBackgroundView)
    buttonBackgroundView.addSubview(addButton)

    setupContainerViews()


}

func handleTouch() {

    print("button pressed")

}

func roundViews() {
    view.layer.cornerRadius = 18
    view.clipsToBounds = true
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func setupContainerViews() {

    buttonBackgroundView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -25).isActive = true
    buttonBackgroundView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 10).isActive = true
    buttonBackgroundView.heightAnchor.constraint(equalToConstant: 37.5).isActive = true
    buttonBackgroundView.widthAnchor.constraint(equalToConstant: 90).isActive = true

    addButton.centerXAnchor.constraint(equalTo: buttonBackgroundView.centerXAnchor).isActive = true
    addButton.centerYAnchor.constraint(equalTo: buttonBackgroundView.centerYAnchor).isActive = true

}


func panGesture(recognizer: UIPanGestureRecognizer) {
    let translation = recognizer.translation(in: self.view)
    let velocity = recognizer.velocity(in: self.view)
    let y = self.view.frame.minY
    if ( y + translation.y >= fullView) && (y + translation.y <= partialView ) {
        self.view.frame = CGRect(x: 0, y: y + translation.y, width: view.frame.width, height: view.frame.height)
        recognizer.setTranslation(CGPoint.zero, in: self.view)
    }

    if recognizer.state == .ended {
        var duration =  velocity.y < 0 ? Double((y - fullView) / -velocity.y) : Double((partialView - y) / velocity.y )

        duration = duration > 1.3 ? 1 : duration

        UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.4, options: [.allowUserInteraction], animations: {
            if  velocity.y >= 0 {
                if y > self.halfView {
                    self.view.frame = CGRect(x: 0, y: self.partialView, width: self.view.frame.width, height: self.view.frame.height)
                } else {
                    self.view.frame = CGRect(x: 0, y: self.halfView, width: self.view.frame.width, height: self.view.frame.height)
                }
            } else {
                if y > self.halfView {
                    self.view.frame = CGRect(x: 0, y: self.halfView, width: self.view.frame.width, height: self.view.frame.height)
                } else {
                self.view.frame = CGRect(x: 0, y: self.fullView, width: self.view.frame.width, height: self.view.frame.height)
                }
            }
        }, completion: nil)
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    UIView.animate(withDuration: 0.6, delay: 0.0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.2, options: [.allowUserInteraction], animations: {
        let frame = self.view.frame
        self.view.frame = CGRect(x: 0, y: self.halfView, width: frame.width, height: frame.height)

    }, completion: nil)
}

}

在这个子视图中是一个“添加”按钮,我想从父母调用一个函数。目前,该按钮正在打印“按下按钮”。我希望该按钮调用父级中的addSettings()函数。我所做的尝试都没有被调用。我知道随着print语句的推出,按钮的交互工作正常。

有关如何从BottomSheetViewController调用该函数的任何建议吗?

4 个答案:

答案 0 :(得分:1)

修改您的类BottomSheetViewController并添加一个成员变量 指向你的父母。

 class BottomSheetViewController: UIViewController {
     var parentVC : MapBoxViewController!
    }

然后,将parentVC设置为MapBoxViewController的那个。

func addBottomSheetView() {
    // 1- Init bottomSheetVC
    let bottomSheetVC = BottomSheetViewController()
    bottomSheetVC.parentVC = self
...
}

然后你可以调用BottomSheetViewController中的addSettings。 您可能还需要在主UI线程中调用addSettings。

答案 1 :(得分:0)

根据您的代码,没有子父关系,您可以像这样直接调用MapBoxViewController类函数。您需要addTarget作为父类,如MapBoxViewController

class BottomSheetViewController: UIViewController {
    lazy var addButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Add", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitleColor(UIColor(r: 88, g: 88, b: 88), for: .normal)
        button.titleLabel?.font = UIFont(name: "Nunito", size: 17)
       button.addTarget(MapBoxViewController, action: #selector(MapBoxViewController.addSettings), for: .touchUpInside)
        return button
    }()
}

您需要设置子父母关系的其他方式,然后您可以像这样覆盖孩子addSettings中的方法BottomSheViewController

class BottomSheetViewController: MapBoxViewController {

    lazy var addButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Add", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitleColor(UIColor(r: 88, g: 88, b: 88), for: .normal)
        button.titleLabel?.font = UIFont(name: "Nunito", size: 17)
        button.addTarget(self, action: #selector(BottomSheetViewController.addSettings), for: .touchUpInside)
        return button
    }()

    override func addSettings() {
        super.addSettings() // this will call MapBoxViewController addSettings() method
    }

}

答案 2 :(得分:0)

您可以为'BottomSheetViewController'提供一个闭包,并将MapBoxViewController.addBottomSheetView中的闭包分配给bottomSheetVC,在您只需调用addSettings函数的闭包中

```
class BottomSheetViewController: UIViewController {
    var aAddSettingsClosure: (() -> ())?
}

class MapBoxViewController: UIViewController, MGLMapViewDelegate {
   func addBottomSheetView() {
      // 1- Init bottomSheetVC
      let bottomSheetVC = BottomSheetViewController()

      bottomSheetVc.aAddSettingsClosure = { [weak self] in
          // Call the addSettings() function here
          self?.addSettings()
      }
   }
}
```

答案 3 :(得分:0)

我正在使用扩展程序在UIView中获取parentViewController:

extension UIResponder {
    var parentViewController: MyViewController? {
        return (self.next as? MyViewController) ?? self.next?.parentViewController
    }
}

以及按钮中的操作:

myButton?.addTarget(parentViewController, action: #selector(parentViewController?.playTapped), for: .touchUpInside)

在视图控制器(MyViewController)中,我具有以下功能:

@objc func playTapped(_ sender:Any) {

        //your code
    }