Pass Values from Popup VC to controller - ios

Currently in my App I am opening a popup View Controller inside a normal View Controller, and need to pass values back from my Popup VC to the normal VC.
This is how I am making the popups.
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "IconEditPopup") as! IconEditPopup
// this is where you can set values in the view
vc.id = "12"
self.addChild(vc)
vc.view.frame = self.view.frame
self.view.addSubview(vc.view)
vc.didMove(toParent: self)
Basically just want to pass values back from the popup View controller to my normal VC.

You can use Delegate pattern or Clouser callback handler to pass a value back to the parent view.
here is a example:
Define a clouser in your popVC like this:
var clouserName: ((returnType) -> Void)?
Inside your popVC where you need to call the clouser:
clouserName?(returnValue)
in your parent controller, capture the value in this way:
vc.clouserName = { returnValue in // dont forget [weak self] if you need self
// Do your stuff here
}

Related

how to block presses around child view controller using swift 4.0?

i'm attaching a child view controller to my view :
func showRaitingDialog () {
let popupRateExpiriance = UIStoryboard (name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ratePopupId") as! RateViewController
//adding the popup view to the corrent view controller
print ("this happens after")
self.addChildViewController(popupRateExpiriance)
popupRateExpiriance.refrenceToController = self
popupRateExpiriance.view.frame = self.view.frame
self.view.addSubview(popupRateExpiriance.view)
popupRateExpiriance.didMove(toParentViewController: self)
}
that child view controller is actually just a costume dialog that i did in my app.
my question is how do i block the presses around this dialog ? (so far the user can press on the screen blow it if he presses around the view controller itself)
You need to build a custom component and introduce the padding between the newly build child and your current one.
#IBAction func buttonAction(_ sender: Any) {
showRaitingDialog ()
}
func showRaitingDialog () {
let popupRateExpiriance = UIStoryboard (name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ratePopupId") as! RateViewController
//adding the popup view to the corrent view controller
addChild(popupRateExpiriance)
// popupRateExpiriance.refrenceToController = self // << maybe you should create an interface / delegate
popupRateExpiriance.view.frame = self.view.frame
view.addSubview(popupRateExpiriance.view)
popupRateExpiriance.didMove(toParent: self)
}
The controller on the right has the background view colour set to clear.
Here is the result at runtime after the button has been pressed to display the child controller (the user can no longer press the button).

How to call a viewcontroller in other class using KGModal

I'm working on an app. The app is in the swift. Now the problem is I'm trying to represent a view controller from another view using the KGModel.
Lets say that are two view controller ViewA and ViewB. Now if i set the viewB as the initial viewcontroller then it's working fine. All the delegate of the tableview controller called successfully but if try to call the ViewB from viewA then the table view always return empty. Is any one know how to call the other view controller in the current view using KGmodel. Thanks in advance.
Code To Call ViewB from ViewA
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "MoveToReviewView") as? ReviewViewController
controller?.assignValue = self
presentController(controller!)
func presentController(_ controller: UIViewController) {
let ret = self.view.frame
controller.view.frame.size.width = ret.size.width - ret.size.width/4
controller.view.frame.size.height = ret.size.height/2
KGModal.sharedInstance().show(withContentView: controller.view, andAnimated: true)
}
The output is

Switching containerView content from within viewController

I have three viewControllers Main, A, B. Main ViewController holds ContainerView and other content as well does all transactions in containerView. ViewControllerA has ButtonA when pressing it content of container has to change to ViewControllerB
how can I do that? I cannot find any similar examples.
You will need to create create delegate for that.
First create a protocol
protocol ViewControllerADelagate {
func didPressOnButtonA()
}
In ViewControllerA add following delegate variable
class ViewControllerA {
....
var delegate : ViewControllerADelagate?
....
}
In ViewControllerA add following on button press
#IBAction buttonAPressed(sender : UIButton) {
self.delegate?.didPressOnButtonA()
}
In MainViewController assign the delegate of ViewControllerA to self
like
vcA.delegate = self
Implement the delegate method in MainViewController like
func didPressOnButtonA {
let storyboard : UIStoryboard = UIStoryboard(name: storyboard, bundle: nil)
let vcB : UIViewController = storyboard.instantiateViewController(withIdentifier: viewControllerIdentifier) as! ViewControllerB
self.addChildViewController(vcB)
self.containerView.addSubview(vcB.view)
vcB.didMove(toParentViewController: self)
vcB.view.frame = CGRect.init(x: 0, y: 0, width: self.containerView.frame.size.width, height: self.containerView.frame.size.height)
}
While click on ButtonA. Post a notification to mainView. There remove viewController A from Container and add View Controller B .
I have created a storybaord with sample. you can download it from here.
You need to change the embed view to a navigation controller and then you can use segue to show second view on button press. also hide/show navigation bar depends on requirement.
I am not fond of using these but you can get the child view controller from parent controller by accessing an array childViewControllers. On view did load you would need to go through all of these and find the one that can be typecast into your view controller type like
childViewControllers.flatMap { $0 as? AViewController }.first.
Now that you found the correct view controller I suggest you to either assign yourself as a delegate
childViewControllers.flatMap { $0 as? AViewController }.first.delegate = self
or simply add a button target
childViewControllers.flatMap { $0 as? AViewController }.first.button.addTarget...
Now this can easily be done if you simply embed the 2 view controllers at the same time (have 2 content views) and hide one or the other depending on which you show. At least this way you can assign connection straight away. When this is not the case then you will need to iterate again when setting a new controller or assign connections where you initialize a new view controller.
In this case it then seems better to turn the system around: When child view controller is loaded rather call
self.delegate = parentViewController as? AViewControllerDelegate
Although this will work it seems wrong that a child view controller will control who its listener is so I advise you to avoid such coding.
I in general use a custom implementation for container view which you could do the same or maybe at least subclass the native one and target the methods so that your code will look something like:
private onBPressed() {
containerView.setViewController(viewController: BViewController(delegate: self), animation: .fade)
}
When you pressing Button A from View A:
#IBAction func BtnAPress(_ sender: Any)
{
//Moving Storyboard
let Storyboard = UIStoryboard(name: "Main", bundle: nil)
let MainVC : UIViewController = Storyboard.instantiateViewController(withIdentifier: "ViewControllerB")
self.present(MainVC, animated: true, completion: nil)
}

Best way to deinit Initial view controller?

I have a loading view controller when my app starts(is is my initial view controller).When an animation in this view controller finished I want it to show another view controller and dismiss the view controller with the animation.
The loading view controller is the initial view controller,
I have this code when UIStoryboard.mflMainTabBarViewController(). returns the view controller that I want to present
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
let animationID = anim.value(forKey: "animationID")
if animationID as! NSString == "transform" {
self.present(UIStoryboard.mflMainTabBarViewController(), animated: true, completion: {
_ = self.popoverPresentationController
})
}
}
But when deinit is never called
deinit {
print("deinit")
}
What is the best way to deinit the first view controller, and making the presenting view controller the root view controller?
Unless you're doing something very specialized, you don't need to de-init an object in Swift. It will be called automatically when the reference count goes to 0. If you really need to, you should be able to set you window's rootViewController through your AppDelegate.
However, be aware that maintenance like this is rarely necessary.
A deinitializer is called immediately before a class instance is deallocated
after you can use
if let delegate = UIApplication.shared.delegate as? AppDelegate {
let storyboard : UIStoryboard? = UIStoryboard(name: "storyboardName", bundle: nil)
let rootController = storyboard!.instantiateViewController(withIdentifier: "controllerIdentifier")
delegate.window?.rootViewController = rootController
}

Swift Navigating to ViewController thats 3 windows deep

I have a ViewController that I want to present when a push notification is opened from the locked screen.
The view controller is embedded inside a chain of view controllers, the chain is:
TabbedBarController(root) -> NavigationController0 -> ViewController0 -> ViewController1 -> ViewControllerIWant
I have two variables from the push notification I want to pass into ViewControllerIWant
So far I have:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateViewControllerWithIdentifier("HomeVC") as! UITabBarController // HomeVC is the TabbedBarController
let NaviVC = storyboard.instantiateViewControllerWithIdentifier("NavigationController0") as! UINavigationController // NavigationController0 is the Navigation Controller for this stack
let ViewController0 = storyBoard.instantiateViewControllerWithIdentifier("ViewController0") as ViewController0
let ViewController1 = storyBoard.instantiateViewControllerWithIdentifier("ViewController1") as ViewController1
let ViewControllerIWant = storyBoard.instantiateViewControllerWithIdentifier("ViewControllerIWant") as ViewControllerIWant
// Pass the Variables into ViewControllerIWant
ViewControllerIWant.Variable0 = "This is the first Variable"
ViewControllerIWant.Variable1 = "this is the second variable"
// Load the VC
self.presentViewController(ViewControllerIWant, animated:true, completion:nil)
I can load ViewControllerIWant directly but then loose the navigation and tab controllers so moving backwards requires you yo close the app and reload.
How do I nest the VC's so that when the user swipes this notification it loads ViewControllerIWant ?
You can just set the viewControllers of the navigationController. And show the current navigationController.
In your example you should add this after the line will be (I have change all to a lowercase. You really shouldn't be using a uppercase as variable)
viewControllerIWant.variable1 = "this is the second variable"
naviVC.viewControllers = [viewController0, viewController1, viewControllerIWant]
You can keep your navigation controller by using segues instead of presenting the View Controller
Once the segue is created from your starting VC into your desired VC, you give it an identifier (e.g. "segueFromVC1ToVCIWant").
Then call the method as an action of your notification:
self.performSegueWithIdentifier("segueFromVC1ToVCIWant", sender: nil)
Finally can pass the variables like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "segueFromVC1ToVCIWant"){
let viewControllerIWant = segue.destinationViewController as! ViewControllerIWant
ViewControllerIWant.variable0 = self.variable0
ViewControllerIWant.variable1 = self.variable1
}
}
Make sure you create variables with the same name in ViewControllerIWant in order to receive the values.

Resources