How to stop video in UITableViewCell when new screen is pushed - swift

I do have tab bar controller with few tabs - one of the tabs looks like this:
I have a table view filled with cells
Some of the cells contains AVPlayer and AVPlayerLayer
I'm using a delegate method tableView:didEndDisplayingCell:forRowAtIndexPath to stop videos that are scrolled out of the visible area
What I need:
When I push a new controller, I need to stop video that is currently playing
When I tap on different tab in tab bar, I need to stop video as well
I tried to implement func willMove(toWindow newWindow: UIWindow?), but it has one annoying side-effect: I have to manually setup dismiss gesture for all the pushed screens.
Any alternative ideas about how to solve that problem? Thanks guys

You can do this in viewWillDisappear function of a UIViewController which has the video cells.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
for cell in tableView.visibleCells {
(cell as VideoCell).stopVideo()
}
}

Related

How can I always show the UIScrollBar indicator?

When a UIViewController with a UIScrollView is visible on screen, I want to show the UIScrollView scrollbar indicator.
Is there a way to show the indicator?
You can show the scrollbar momentarily with .flashScrollIndicators when the view controller has been added to the view hierarchy and is potentially visible to the user.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
scrollView.flashScrollIndicators()
}

Performing segue with UINavigationController (without IBAction)

It's easier to show you a drawing and then explain.
Dashboard Storyboard
I have 2 separate UIViewControllers (i've included just one in the drawing, the other is irrelevant) embedded in container view called ContainerViewController.
Post Storyboard
NewPostViewController shows a UIButton that presents TextPostViewController. As you can see, all of them are embedded in UINavigationControllers. Now, once the completion block of the new post is being called, I have to present the ContainerViewController and it needs to handle it's own logic. The problem is that it's embedded in UINavigationController and once I present it, the UITaBbar is hidden.
I tried to do this:
self.performSegue(withIdentifier: "TextPostToNavContainerVC", sender: nil)
The transition is successful but I'm losing the UITabBar, even though in the DashboardViewController and the ContainerViewController I called:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tabBarController?.tabBar.isHidden = false
}
What am I doing wrong or is there are better way to do that?
You should instantiate the tab bar controller. not the view controller.
Imagine you're putting a initial view controller ahead of your tab bar controller. Making your tab bar not being pushed
If I undestand it correctly.
You are doing this
Segue connect to a view controller
But you should actually do this Segue connected to a tab bar controller
You can try to add it as a child to control it's frame like this
let textPost = self.storyboard?.instantiateViewController(withIdentifier: "containerID") as! TextPostToNavContainerVC
textPost.view.frame = CGRect(x:20,y:0,width:self.view.frame.width,height:self.view.frame.height-50)
self.view.addSubview(nvc.view)
self.addChildViewController(textPost)
textPost.didMove(toParentViewController: self)

Update the data of a TableViewController after add item

I have tableView (A) responsible for listing items CoreData and viewController (B) to add new item. To create a ViewController (B) custom, they chose to use the following Present Modally to use presentation Over Current Context to enable transparent background and be able to apply the blur.
From tableView (A) press the button to add a new item, the viewController (B) appears.
Add a new item and saved in CoreData
The viewController (B) execute self.dismissViewControllerAnimated(true, completion: nil) and the display returns to the tableView (B)
The problem is that the table view does not update the data.
Following a post from Stack Overflow resulting in code:
override func viewDidAppear(animated: Bool) {
self.loadData()
}
But at the back of viewController (B), nothing happens in Xcode does not pass the lines of viewDidAppear.
Can anyone help me?
Try this:
override func viewDidAppear(animated: Bool)
{
self.yourTableViewName.reloadData()
}

Swift open a new view controller programmatically on top of a map from a button insider a popover and a cell

I have a bit of an odd problem. Note that everything is done programmatically, so please no storyboard suggestions. Here's the setup:
I have a Master-Detail view layout, where the Detail view is a map. The Master-view's table is filled with cells that represent annotation points on the map. When you tap on a cell, it focuses on that annotation on the map and opens a custom annotation view using a popover. Likewise, when you tap the annotation itself, the same popover opens. So far, so good.
Now, inside the popover and inside each cell there is an a button which, when pressed, should open a new view that fills the whole screen. The view would have information specific to its corresponding annotation.
Here is how I am trying to do it:
Class that has the map (MyDetailViewController)
public func openNewViewController(){
self.presentViewController(NewViewController(), animated: true, completion: nil)
}
Function call for cell button and popover button
func btnPressed(sender: AnyObject){
var dvc = MyDetailViewController()
dvc.openNewViewController()
}
When either button gets tapped, I get the same error:
Warning: Attempt to present NewViewController on DetailViewController whose view is not in the window hierarchy!
So, what does it mean that DetailViewController is not in the window hierarchy..? It must be since I see it, no?
Any idea how to fix this issue? Thanks in advance!
Your function openNewViewController() is doing nothing!
See the code
self.presentViewController(openNewViewController()) , animated : true , completion: nil)
is pointing to itself.
Instead try this :
public func openNewViewController(){
var newController = UIViewController() // or any other view you wish to instantiate
self.presentViewController(newController, animated: true, completion: nil)
}

iPhone popup menu like iPad popover?

How can i implement this popup menu in iphone app like a popover in ipad?
EDIT: This is the best at moment: https://github.com/runway20/PopoverView
iOS 8 and later
Beginning with iOS 8, you can use UIPopoverPresentationController for iPhones in addition to iPads.
Setup
Add a UIBarButtonItem to your main View Controller.
Add another View Controller to the storyboard. Change it to the size that you want the popover to be and add any content that you want it to have. For my example I just added a UILabel. If you want a whole menu, then just add a table view or list of buttons.
Add a segue from the bar button item to the view controller that you will use as the popover. Rather than show, choose Present as Popover.
Select the segue in the storyboard and set the identifier to popoverSegue (or whatever string you called it in the code).
In the Attributes inspector for the popover view controller, check Use Preferred Explicit Size and confirm that it is the size you want it to be.
Code
This is the code for the main view controller that has the bar button item in it.
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "popoverSegue" {
let popoverViewController = segue.destinationViewController
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
popoverViewController.popoverPresentationController!.delegate = self
}
}
// MARK: - UIPopoverPresentationControllerDelegate method
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
// Force popover style
return UIModalPresentationStyle.None
}
}
Popover at an arbitrary anchor point
If you want to set the popover to appear somewhere besides a bar button item (on a UIButton for example) then you need to set the sourceView and sourceRect. See this answer for details.
Further reading
The above example comes mostly from the first link.
iPad Style Popovers on the iPhone with Swift
iOS 8 Popover Presentations
UIPopoverPresentationController on iOS 8 iPhone
General overview of popup options in iOS
Have a look at the iPhone UIPopoverController implementation: WEPopover
On iPhone you would generally use a UIActionSheet for a stack of buttons like that. It slides up from the bottom, rather than popping up next to the button, but that's the standard behavior on iPhone.
There is one that is even better than WEPopover. Developed by a company called 50pixels, it is called FPPopover.
You can download FPPopover at https://github.com/50pixels/FPPopover
You would have to manually instantiate a UIView using a custom background image or drawing with transparency, add some UIButtons (or other type of custom view) on top, and also somehow handle all touches outside that view.
Note that is is non-standard UI. An actionsheet would be more HIG compliant.
To get a popover from a right side bar button item on a navigation controller that is part of a tableview controller, the following worked for me for Swift 4 and Xcode 9.
Follow the steps in Suragch answer above (as edited by the Community.)
Do not implement the Segue as shown in the answer above. For some reason, the segue causes the popover to go full screen despite setting the explicit size.
Give your popover view controller a title in Attributes Inspector
Add the following code in the TableView controller where the popup will show.
Modify the string identifier (the one here is referencing a Constant.swift file)
Modify "as! FilterVC" to use the title of the your popover view controller.
/// Shows a filter popover view
#IBAction func filterBtnPressed(_ sender: UIBarButtonItem) {
let popover = storyboard?.instantiateViewController(withIdentifier: FILTER_VC) as! FilterVC
popover.modalPresentationStyle = UIModalPresentationStyle.popover
popover.popoverPresentationController?.backgroundColor = UIColor.green
popover.popoverPresentationController?.delegate = self
popover.popoverPresentationController?.backgroundColor = ColorPalette.Blue.Medium
popover.popoverPresentationController?.sourceView = self.view
popover.popoverPresentationController?.sourceRect = CGRect(x: self.view!.bounds.width, y: 0, width: 0, height: 0)
popover.popoverPresentationController?.permittedArrowDirections = .up
self.present(popover, animated: true)
} }
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return UIModalPresentationStyle.none
}
You can check WYPopoverController: https://github.com/sammcewan/WYPopoverController
The screenshot above is not a UIActionSheet. It looks like a simple UIView subclass with custom UIButtons on top of it. So go ahead and create the subclass according to your needs and then add it as a subview to your view every time you need it.