Call function from child to parent in Swift - ios

I am using xlpagertabstrip and I have a parent view controller which has two children (child1, child2).
In my parent view controller, I show a UIActivityViewIndicator but I want to know how to hide that indicator in my child1.
This is my code:
ParentViewController:
override func viewDidLoad() {
showActivityIndicator()
super.viewDidLoad()
}
func showActivityIndicator() {
//code related to titleview
navigationItem.titleView = titleView
}
func hideActivityIndicator() {
navigationItem.titleView = nil
}
Child1ViewController:
override func viewDidLoad() {
super.viewDidLoad()
call_api()
}
func call_api(){
//code related to api
//if api is ok, I call hideActivityIndicator()
let pctrl = ParentViewController()
pctrl.hideActivityIndicator()
}
But that code does not work. How can I solve that?

Just pass hideActivityIndicator() from the parent to the child and call it when necessary. So whenever you create your child controller do this:
// Parent Controller
childVC.someMethodFromParent = hideActivityIndicator
And in your ChildController do this:
// Child Controller
internal var someProperty: (() -> Void)!
override func viewDidLoad() {
super.viewDidLoad()
call_api()
}
func call_api(){
//code related to api
//if api is ok, I call hideActivityIndicator()
someMethodFromParent()
}
This should work

How about having a ChildViewControllerDelegate? Something like:
class ParentViewController {
func someFunc(){
...
childVC.delegate = self
...
}
}
extension ParentViewController: ChildViewControllerDelegate {
func childViewControllerDidFinishApiCall() {
hideActivityIndicator()
}
}
protocol ChildViewControllerDelegate: class {
func childViewControllerDidFinishApiCall()
}
class ChildViewController {
weak var delegate: ChildViewControllerDelegate?
func call_api(){
//code related to api
let pctrl = ParentViewController()
delegate?.childViewControllerDidFinishApiCall()
}
}

Related

i want to triger navigationcontroller when i press button in UIView class

I want to trigger Navigation controller to some other screen when i press the button in UIView class. How can i do this?
//Code for UIView Class in Which Button Iboutlet is created
import UIKit
protocol ButtonDelegate: class {
func buttonTapped()
}
class SlidesVC: UIView {
var delegate: ButtonDelegate?
#IBAction func onClickFinish(_ sender: UIButton) {
delegate?.buttonTapped()
}
#IBOutlet weak var imgProfile: UIImageView!
}
//ViewController Class code in Which Button Protocol will be entertained
class SwipingMenuVC: BaseVC, UIScrollViewDelegate {
var slidesVC = SlidesVC()
override func viewDidLoad() {
super.viewDidLoad()
slidesVC = SlidesVC()
// add as subview, setup constraints etc
slidesVC.delegate = self
}
extension BaseVC: ButtonDelegate {
func buttonTapped() {
self.navigationController?.pushViewController(SettingsVC.settingsVC(),
animated: true)
}
}
A more easy way is to use typealias. You have to write code in 2 places. 1. your viewClass and 2. in your View Controller.
in your SlidesView class add a typealias and define param type if you need otherwise leave it empty.
class SlidesView: UIView {
typealias OnTapInviteContact = () -> Void
var onTapinviteContact: OnTapInviteContact?
#IBAction func buttonWasTapped(_ sender: UIButton) {
if self.onTapinviteContact != nil {
self.onTapinviteContact()
}
}
}
class SwipingMenuVC: BaseVC, UIScrollViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let slidesView = SlidesView()
slidesView.onTapinviteContact = { () in
// do whatever you want to do on button tap
}
}
You can use the delegate pattern to tell the containing ViewController that the button was pressed and let it handle whatever is needed to do next, The view doesn't really need to know what happens.
A basic example:
protocol ButtonDelegate: class {
func buttonTapped()
}
class SomeView: UIView {
var delegate: ButtonDelegate?
#IBAction func buttonWasTapped(_ sender: UIButton) {
delegate?.buttonTapped()
}
}
class ViewController: UIViewController {
var someView: SomeView
override func viewDidLoad() {
someView = SomeView()
// add as subview, setup constraints etc
someView.delegate = self
}
}
extension ViewController: ButtonDelegate {
func buttonTapped() {
self.showSomeOtherViewController()
// or
let vc = NewViewController()
present(vc, animated: true)
}
}

Sending data to another controller - Without going to him

I want to send data to another controller without opening it.
Example
Main controller:
override func viewDidLoad() {
let vc = SecondViewController()
vc.test = "ABCDFER"
}
Second controller:
var test: String
override func viewDidLoad() {
print(test)
}
How to do it?
It works for me this way
class ViewController: UIViewController {
var otherViewController: OtherViewController!
override func viewDidLoad() {
super.viewDidLoad()
otherViewController = OtherViewController()
otherViewController.test = "ABCDFER"
}
#IBAction func press() {
self.show(self.otherViewController, sender: nil)
}
}
class OtherViewController: UIViewController {
var test: String!
override func viewDidLoad() {
super.viewDidLoad()
print(test)
}
}
In your Main controller, as soon as viewDidLoad() finishes your instance of SecondViewController is destroyed / deallocated. If you want to set a value inSecondViewController at that point, so you can "use" it later, you need to keep a reference to that instance:
So, in Main controller:
var secondVC: SecondViewController?
override func viewDidLoad() {
secondVC = SecondViewController()
secondVC.test = "ABCDFER"
}
Now, later - perhaps on a button tap - you want to use that same instance:
#IBAction func buttonTap(_ sender: Any) {
print("test in secondVC:", secondVC?.test)
}
Keep in mind the view life cycle, if the view viewDidLoad() it's only executed when loading the view through a xib or when view related actions are done with the controller, like addSubview().
The value is being passed and will not be deallocated while your main controller is alive.
You can force a lifecycle event to be called, but isn't recommended at all.
class ViewController: UIViewController {
var otherViewController: OtherViewController!
override func viewDidLoad() {
super.viewDidLoad()
otherViewController = OtherViewController()
otherViewController.test = "ABCDFER"
//Do not do this
otherViewController.viewDidLoad()
}
}
class OtherViewController: UIViewController {
var test: String!
override func viewDidLoad() {
super.viewDidLoad()
print(test)
}
}

Delegate doesnt work with SplitView

I have a SplitView with master(left) and detail(right) view for an iPad app. I want that, when I do click on a button in the master view, this call delegate method on parent split view and push a new view o top, but the delegate method is never called. Why?
Here the code:
Master view:
protocol newAlbumDelegate{
func openAlbum()
}
class newAlbumController: UIViewController {
var delegate:newAlbumDelegate?
#IBAction func buttonClick(sender:UIButton){
delegate?.openAlbum()
}
}
SplitView:
import UIKit
class AlbumSplitController: UISplitViewController, newAlbunDelegate {
var newAlbumToAdd:newAlbumController = newAlbumController()
//Delegate
func openAlbum(){
print("Do something")
}
override func viewDidLoad(){
super.viewDidLoad()
self.newAlbumToAdd.delegate = self
}
Any help??
Regards,
Within the masterViewController, assign the splitViewController as the delegate:
protocol newAlbumDelegate{
func openAlbum()
}
class newAlbumController: UIViewController {
var delegate:newAlbumDelegate?
#IBAction func buttonClick(sender:UIButton){
delegate?.openAlbum()
}
override func viewDidLoad(){
super.viewDidLoad()
let splitView = self.splitViewController as! AlbumSplitController
self.delegate = splitView
}
}
Your splitViewController becomes:
class AlbumSplitController: UISplitViewController, newAlbumDelegate {
//Delegate
func openAlbum(){
print("Do something")
}
}

how can I call a method stored in a parent uiviewcontroller from the uiviewcontroller embedded in a container in that controller?

I have a UIViewController -let's call it parentViewController - and it contains a container. This container has embeddedViewController embedded in it.
Now, my parentViewController contains a method that prints something into the console:
func printSomeData(){
print("some data")
}
embeddedViewController has a button with action asigned to it:
#IBAction func printSomething(sender: AnyObject) {
is there a way that I could call method printSomeData from printSomething in Swift?
There are couple of ways such as by implementing delegate or by posting NSNotification. Here I show the sample delegation pattern. This is exact scenario as your own controller but from this you can get some concept and if you implement this hope this will accomplished your goal.
class ParentController:UIViewController,printing {
override func viewDidLoad() {
//
}
func presentEmbadedController(){
let embadedVC = EmbadedController()
embadedVC.delegate = self
}
func printSomeData() {
print("some date")
}
}
Here is the protocol something like this
protocol printing{
func printSomeData()
}
And then the EmbadedController like this
class EmbadedController:UIViewController {
var delegate: printing?
override func viewDidLoad() {
//
}
#IBAction func printSomething(sender: AnyObject) {
if let _ = delegate{
delegate?.printSomeData()
}
}
}
You can use NSNotificationCenter.defaultCenter().addObserver(...)

Hide a view container with a button in the ViewContainer

I have a View. In this view, I have a Container View. And in the ContainerView I have a button.
When I am touching the button of the ContainerView, I want the ContainerView become hidden.
I want to do something like that :
class ContainerView: UIViewController {
#IBAction func closeContainerViewButton(sender: AnyObject) {
//I try this : self.hidden = false
//or this : self.setVisibility(self.INVISIBLE)
}
}
Any idea how do it?
There are serval ways but here is the easiest one, not prettiest though. You should really use delegates but this is a hacky way to get started. Just create a global variable of the class that holds the container (startController in this case). Then call it from your other view controller (MyViewInsideContainer) and tell it to hide the view you´re in. I have not run this code but it should work.
var startController = StartController()
class StartController:UIViewController {
#IBOutlet var myViewInsideContainerView: UIView
....
override func viewDidLoad() {
super.viewDidLoad()
startController = self
}
func hideContainerView(){
self.myContainerView.hidden = true
}
}
class MyViewInsideContainer:UIViewController {
...
#IBAction func hideThisView(sender: AnyObject) {
startController.hideContainerView()
}
}
i think a cleaner solution is to use delegation:
in the ParentViewController
class ParentViewController: UIViewController ,ContainerDelegateProtocol
{
#IBOutlet weak var containerView: UIView!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
//check here for the right segue by name
(segue.destinationViewController as ContainerViewController).delegate = self;
}
func Close() {
containerView.hidden = true;
}
in the ContainerViewController
protocol ContainerDelegateProtocol
{
func Close()
}
class ContainerViewController: UIViewController {
var delegate:AddTaskDelegateProtocol?
#IBAction func Close(sender: AnyObject) { //connect this to the button
delegate?.CloseThisShit()
}

Resources