add subview over UITableView - ios

First of, I am noob to Swift programming.
I am trying to show a custom view over a UITableView.
I am facing two major issues :
a) The subview does not appear correctly firstly. ref image below :
and after few moments actual view is loaded :
b) After the UITableView is scrolled, the view is not coming over the current top scroll position of UITableView
Following is the code to add subview :
let vaAdPopupViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AdPopupWithCrossViewController") as! AdPopupWithCrossViewController
vaAdPopupViewController.adID = adID
vaAdPopupViewController.tableView = self.tableView
if let message = parseJSON["adv_text"] as? String{
vaAdPopupViewController.message = message
}
let navigationBarFrame: CGRect = (self.navigationController?.view.frame)!
let frameSize = CGRect(x: navigationBarFrame.minX, y: navigationBarFrame.minY, width: navigationBarFrame.width, height: (navigationBarFrame.height - (self.navigationController?.navigationBar.frame.size.height)!))
vaAdPopupViewController.view.frame = frameSize
self.tableView.addSubview(vaAdPopupViewController.view)
vaAdPopupViewController.view.tag = 1000
self.addChildViewController(vaAdPopupViewController)
vaAdPopupViewController.didMove(toParentViewController: self)
also in AdPopupWithCrossViewController :
override func viewDidLoad() {
self.view.superview?.layoutIfNeeded()
self.view.layoutIfNeeded()
super.viewDidLoad()
}
Please guide me how to resolve this issue.
Thank You.

You probably want to either create a Present Modally Segue or use present() via code.
You've already created your AdPopupWithCrossViewController. Set its background color to be translucent. Then you can present it like this:
let vaAdPopupViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AdPopupWithCrossViewController") as! ModalOverTableViewController
vaAdPopupViewController.modalPresentationStyle = .overCurrentContext
self.present(vaAdPopupViewController, animated: true, completion: nil)
Then, your little "X" button can remove the ad with:
#IBAction func closeTapped(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
You can try out the various options on .modalPresentationStyle and .modalTransitionStyle, as well as setting animated to true or false, to get the appearance / behavior you desire.

As Dan says, you should add your popup as a subview of the view controller's view, not of the table view. A Table view's view hierarchy is private and you should not be trying to mess with it.
Note that you can't do this with a table view controller. This has always bugged me, but it's a fact: A UITableViewController manages a single table view and nothing else. If you want a more complex view hierarchy you need to embed your table view controller in another view controller. I do this with a container view and an embed segue, which is very easy.
If you do that then you can add your new view controller's content to the parent view controller's content view, not to the table view controller's view (or to the table view itself)

Related

Adding Custom popup doesn't filling the full view iOS, Swift

I have created a UIViewControlller and designed in storyboard, I want to show it as popup for my another view.
I used the following to show as popup:
guard let popupVC = UIStoryboard(name: "More", bundle: nil).instantiateViewController(withIdentifier: "LanguageSelectionViewController") as? LanguageSelectionViewController else{
fatalError("Unexpected destination VC")
}
self.addChildViewController(popupVC)
popupVC.view.frame = self.tableView.frame
print("POPUP Frame VIEW -- \(popupVC.view.frame)")
print("SElF VIEW -- \(self.tableView.frame)")
popupVC.view.frame = self.tableView.frame
print("POPUP Frame VIEW -- \(popupVC.view.frame)")
print("SElF VIEW -- \(self.view.frame)")
popupVC.modalPresentationStyle = .currentContext
popupVC.modalTransitionStyle = .crossDissolve
popupVC.view.bindFrameToSuperviewBounds()
self.view.addSubview(popupVC.view)
popupVC.didMove(toParentViewController: self)
It is working properly, but on my device half of the screen space is not filled by popup view.
Have you tried using the present() function? Something like this:
let popupVC = PopupViewController()
popupVC.modalPresentationStyle = .overFullScreen
popupVC.modalTransitionStyle = .crossDissolve
self.present(popupVC, animated: true, completion: nil)
I find designing view controllers in their own xib files easier, and it allows initialisation like in my example, rather than having to use the storyboard in code, but thats personal preference.
If it still isnt working, maybe check that the layout constraints for the popup's background are correct, so it actually fills it's parent.
You need to swap these two lines:
self.view.addSubview(popupVC.view)
popupVC.view.bindFrameToSuperviewBounds()
You can't bind a view to it's superview if the view hasn't been added to it yet.
First thing you need click on popup(storyboard or xib) and set it to background color .clear Color
Then make it to center. like
popupVC.center = self.view.center
it's just a guide you can change and set names accordingly. But my question why you are using storyboard why not have created Xib or View
Hope it will serve your purpose.

Adding a dependencies to a child view controller

I want to present a custom view controller within a navigation controller within modal view. To do this I made a view in interface builder, added a container view, and embedded the contained view in a navigation controller. The contained view is my custom view controller, DetailViewController.
I have to add dependencies to the DetailViewController object to at runtime. Here’s the method where I’ll be presenting the DetailViewController:
override func tableView(_: UITableView, didSelectRowAt: IndexPath) {
guard let record = records[didSelectRowAt.row] else { return }
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let containerView = storyBoard.instantiateViewController(withIdentifier: "DetailContainer")
containerView.modalPresentationStyle = .overFullScreen
self.present(detailContainer, animated: true, completion: nil)
}
How can I add the record to DetailViewController? I tried to access children of the container view, but the array is empty. This Apple document says
The children must be instantiated at the same time as the parent so that the appropriate parent-child relationships can be created.
I'm not sure how to achieve that.
containerView.children is empty because viewcontroller's view isn't loaded.
You can force to load view by calling containerView.view thereafter containerView.children will exist.

Container View Page Controller is Being Clipped instead of Resized

I am about fifteen seconds away from flipping over my desk and rage quitting, because I just cannot figure this out.
I have a Page View Controller as the embed of a Container View Controller. Sounds easy, right?
Problem is, the Page View Controller is getting clipped. I need it to resize. So they would be cute little pages with their full VC content.
I've tried every option on the Storyboard Display... things.
Here's a couple of pics to describe the problem:
Now I would share the code with you, but all it is the loading of the (single) page. The page does exist in a different storyboard, but even when I changed the view for View Controllers in the Main storyboard, they were still being cut off.
override viewDidLoad() {
let storyboard = UIStoryboard(name: "TEMPLATES", bundle: Bundle.main)
let vc = storyboard.instantiateViewController(withIdentifier: "template1")
self.setViewControllers([vc!], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
self.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] //Some code I found on Stack Overflow that did nothing
super.viewDidLoad()
}
Any help would be appreciated!
if you add it from the storyboard - it will just work.
if you add the child view controller from code - you also need to set the frame like so:
carsTableVC.view.frame = self.container.bounds
here is a full code example (carsTableVC is in a container):
let sb = UIStoryboard.init(name: "Cars", bundle: nil)
self.carsTableVC =
sb.instantiateViewController(withIdentifier:
"CarsTableViewController") as? CarsTableViewController
carsTableVC.view.frame = self.container.bounds
carsTableVC.willMove(toParent: self)
addChild(carsTableVC)
carsTableVC.didMove(toParent: self)
container.addSubview(carsTableVC.view)

Set content offset of presented view controller's scroll view before it's presented?

I have a container scrollView that contains a regular collection view and collection view cells inside of it (There are a couple custom views inside of it that aren't collection view cells, hence why I have a container scroll view and not just a collection view).
When a user taps a cell, I instantiate and present a view controller programmatically:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondVC = storyboard.instantiateViewControllerWithIdentifier("second") as! SecondViewController
self.presentViewController(secondVC, animated: false, completion: nil)
That works great. Now, I want to transition back to the original view controller at a certain content offset. So I have a method in my second view controller to perform this transition back:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let firstVC = storyboard.instantiateViewControllerWithIdentifier("first") as! FirstViewController
// There's an IBOutlet for my containerScrollView
firstVC.containerScrollView.setContentOffset(CGPoint(x: 500, y: 0), animated: false)
self.presentViewController(firstVC, animated: false, completion: nil)
The transition back to firstVC performs fine, but it always starts at the beginning of the container scroll view in firstVC rather than what I set for the custom content offset. I've checked to make sure that the containerScrollView property on the firstVC exists before I try setting the content offset, and it does exist. Is there a way to do this?

iOS Swift Popup View Controller

I need to have a ViewController slide up, be centered, and overlay the current ViewController. I thought the following code would work but it does not:
let view = storyboard?.instantiateViewControllerWithIdentifier("castSpell") as! CastSpellViewController
view.modalPresentationStyle = .OverCurrentContext
presentViewController(view, animated: true, completion: nil)
The new ViewController is shown but just as a full screen view. I have it's size set to 400x300 in the storyboard. I know I can do the same thing by having a view within a view and then showing the overlay view. Is that the route I need to go?
You need to set the presentation style on the presenter, not the presenting view.
Use self.modalPresentationStyle = .OverCurrentContext
let popOverVC = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewControllerWithIdentifier("ViewControllerName") as! PopOverViewContoller
self.addChildViewController(popOverVC)
popOverVC.view.frame = self.containerView.frame
self.containerView.addSubview(popOverVC.view)
popOverVC.didMoveToParentViewController(self)
Use the above code to add viewcontroller as a popover view. The container view is optional. I like using container views when the subviews position is fixed. I can position the container using autolayout and keep it hidden until needed.
In you case, you can place the container/subView at the bottom of the screen from where you need to slide up the subview.
UIView.animateWithDuration(0.5) { () -> Void in
//Animate here
}
Then change the frame of the container/subview inside the above block of code.
Note : Container view is just a normal UIView. I like naming it container :)

Resources