Overriding Swiping Actions on a UITableView over UIPageController VC segues - uitableview

In swift, i'm currently working on segueing my VC's using a UIPageViewController, where when you swipe left or right it changes the VC. In one of my View Controllers, a table view exists, where if you swipe on the row there are options. My problem is, when I swipe on the row of the table, it changes to my View Controller. I want to override this so that it shows row actions before VC swiping. My code below is the first VC. PS: If you need my Code for my tableviews please comment for it! Thanks
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var myViewControllers = Array(count: 4, repeatedValue:UIViewController())
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let pvc = segue.destinationViewController as UIPageViewController
pvc.dataSource = self
let storyboard = UIStoryboard(name: "Main", bundle: nil);
var vc0 = storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as UIViewController
var vc1 = storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as UIViewController
var vc2 = storyboard.instantiateViewControllerWithIdentifier("ThirdViewController") as UIViewController
var vc3 = storyboard.instantiateViewControllerWithIdentifier("FourthViewController") as UIViewController
self.myViewControllers = [vc0, vc1, vc2, vc3]
pvc.setViewControllers([myViewControllers[1]], direction:.Forward, animated:false, completion:nil)
println("Loaded")
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var currentIndex = find(self.myViewControllers, viewController)!+1
if currentIndex >= self.myViewControllers.count {
return nil
}
return self.myViewControllers[currentIndex]
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var currentIndex = find(self.myViewControllers, viewController)!-1
if currentIndex < 0 {
return nil
}
return self.myViewControllers[currentIndex]
}
}

Did the tableView takes all the space in your view? let's try with
override func scrollViewDidScroll(scrollView: UIScrollView) {
}

Related

Delegate returns nil and not being called

I have an overlay that I want to remove when a button is clicked thereby dismissing the ViewController. I have debugged and the delegate is currently returning nil. I'm not sure what I'm doing wrong here. Have I missed implementing something else? I have even tried out print statements but can't see anything.
protocol DismissOverlayDelegate: class {
func dismissOverlay(_ sender: PlayersViewController)
}
class PlayersViewController: UIViewController {
weak var delegate: DismissOverlayDelegate?
#IBAction func getStartedTapped(_ sender: UIButton) {
self.delegate?.dismissOverlay(self)
}
}
and in my ViewController where I implement the delegate method
class HomeViewController: UIViewController, DismissOverlayDelegate {
#IBOutlet weak var customOverlay: CustomOverlayView!
let playersViewController = PlayersViewController()
override func viewDidLoad() {
super.viewDidLoad()
self.playersViewController.delegate = self
}
func dismissOverlay(_ sender: PlayersViewController) {
self.customOverlay.removeFromView()
}
}
delegate = (DismissOverlayDelegate?) nil
The PlayersViewController is embedded into a UIPageViewController
class HomeViewController: UIPageViewController, UIPageViewControllerDataSource {
var pages = [UIViewController]()
override func viewDidLoad() {
super.viewDidLoad()
for storyboardIDs in ["playersVC1","playersVC2"] {
let viewController = self.storyboard?.instantiateViewController(withIdentifier: storyboardIDs)
self.pages.append(viewController!)
}
self.dataSource = self
self.setViewControllers([self.pages.first!], direction: .forward, animated: true)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let currentIndex = self.pages.firstIndex(of: viewController)!
if currentIndex > 0 {
return self.pages[currentIndex - 1]
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let currentIndex = self.pages.firstIndex(of: viewController)!
if currentIndex < (self.pages.count - 1) {
return self.pages[currentIndex + 1]
}
return nil
}
}
It seems that PlayersViewController() is wrong.
You should use instantiateInitialViewController() or instantiateInitialViewController() when using StoryBoard.
https://developer.apple.com/documentation/uikit/uistoryboard/1616214-instantiateviewcontroller
https://developer.apple.com/documentation/uikit/uistoryboard/1616213-instantiateinitialviewcontroller
Let me explain you if you are using or want to use delegate for call or implement something there is root and you have to that on a right way. You are doing well no issue but the implementation of delegate is not properly your method can't accept that so try this:-
Your Home View Controller
class HomeViewController: UIViewController, DismissOverlayDelegate {
#IBOutlet weak var customOverlay: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
func dismissOverlay(_ sender: PlayersViewController) {
self.customOverlay.removeFromSuperview()
}
#IBAction func go(_ sender: UIButton) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "PlayersViewController") as! PlayersViewController
vc.delegate = self
self.navigationController?.pushViewController(vc, animated: true);
}
}
this is your playground VC
protocol DismissOverlayDelegate: class {
func dismissOverlay(_ sender: PlayersViewController)
}
class PlayersViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
weak var delegate: DismissOverlayDelegate?
#IBAction func getStartedTapped(_ sender: UIButton) {
self.delegate?.dismissOverlay(self)
}
}
now hope you understand what you have to do...!

IOS UIPageViewController second view not loading

I have a problem with my PageViewController. It works as expected when I switch views by taping on the page indicators, but when I swipe every second view is blank (black).The preview while swiping is displayed properly, but when I complete the swipe the view disappears.
import UIKit
class ScheduleViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
#IBAction func editButton(sender: AnyObject) {
(self.pageViewController.view as! UITableView).setEditing(true, animated: true)
print((self.pageViewController.view as! UITableView).editing)
}
#IBOutlet weak var navBar: UINavigationItem!
var pageViewController: UIPageViewController!
var index = 0
var viewControllers: [ContentViewController] = []
override func viewDidLoad()
{
self.navigationController!.navigationBar.translucent = false
self.tabBarController!.tabBar.translucent = false
self.pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ScheduleViewControllerPage") as! UIPageViewController
self.pageViewController.dataSource = self
self.pageViewController.delegate = self
for a in [0,1,2,3,4]{
var vc: ContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController
vc.pageIndex = a
vc.tableView.reloadData()
self.viewControllers.append(vc)
}
print(viewControllers)
self.pageViewController.setViewControllers([self.viewControllers[0]] as [UIViewController], direction: .Forward, animated: false, completion: nil)
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.size.height)
self.addChildViewController(self.pageViewController)
self.view.addSubview(self.pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
index--
if index <= -1 {
index = 4
}
return self.viewControllers[index] as UIViewController
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
index++
if index >= 5 {
index = 0
}
return self.viewControllers[index] as UIViewController
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return 5
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return index
}
}

Segue to DetailViewController (SplitViewController)

I'm having a hard time selecting the view controller that show be the detail view in the split view controller. It appears that there is some default caller to the view controller behind showDetail but I cannot find where. When the split view controller loads, it show DetailViewController as the detail in split of my attempts to set it to OverviewViewController. The showDetail segue is not called on load, however it is still the default.
When I have overrided the didSelectRowAtIndexPath on the master, I see a flicker as it sets the DetailViewController briefly before setting OverviewViewController.
Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem()
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? OverviewViewController
}
}
// MARK: - Segues
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("did select row")
NSOperationQueue.mainQueue().addOperationWithBlock {
self.performSegueWithIdentifier("showOverview", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
print("segue to showDetail")
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.injectOrder(gobl_meal_orders[indexPath.row])
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}else if segue.identifier == "showOverview"{
print("show overview called")
}
}
Where is this hidden preselection of view controller?
If I understand correctly, you don't want the detail view to be displayed when your splitview controller is loaded.
The way to control this is to use a custom class for your UISplitViewController and implement the following delegate method
splitViewController(_:collapseSecondaryViewController:ontoPrimaryViewController:)
Here is an example.
import UIKit
class MyCircleUISplitViewController: UISplitViewController, UISplitViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController, ontoPrimaryViewController primaryViewController: UIViewController) -> Bool {
return true
}
}
Here is also a nice blog on UISplitViewControllers that you might find interesting.

Swift Protocol delegation not working

I have a viewController that has a containerView with pageView. Once I slide a view from the pageView I want to call a function in the viewController I have tried with my code below but it is calling buttonMaskColor please where would be my issue?
class PlaceMenuDetailsViewController: UIViewController, PageViewSliderDelegate {
override func viewDidLoad() {
super.viewDidLoad()
detailsButton.pageDelegation = self
}
func buttonMaskColor(){
println("delegate work")
}
}
class DetailPageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
weak var pageDelegation:PageViewSliderDelegate?
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
pageDelegation?.buttonMaskColor()
var page = (viewController as! PageDelegate).pageNumber + 1
return viewControllerForPage(page)
}
You should assign self to pageDelegation in your prepareForSegue function in your mainView after giving and identifier for the embed segue like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "embedSegueIdentifier" {
let distinationVC = segue.destinationViewController as? DetailPageViewController
distinationVC?.pageDelegation = self
}
}

Loading View Controllers in UIPageViewController

I'm using a UIPageViewController to scroll through 3 view controllers. The goal is to be able to swipe left and right to navigate them, which I'm able to do with the following code. The issue is that on opening the app for the first time, the navigation bars load in the wrong place and need a full second to conform to constraints. The nav bars load higher than they should be. I'm wondering why there's such a delay in them loading.
class ViewController: UIViewController, UIPageViewControllerDataSource {
var myViewControllers = Array(count: 3, repeatedValue:UIViewController())
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let pvc = segue.destinationViewController as! UIPageViewController
pvc.dataSource = self
let storyboard = UIStoryboard(name: "Main", bundle: nil);
var vc0 = storyboard.instantiateViewControllerWithIdentifier("ViewController1") as! UIViewController
var vc1 = storyboard.instantiateViewControllerWithIdentifier("ViewController2") as! UIViewController
var vc2 = storyboard.instantiateViewControllerWithIdentifier("ViewController3") as! UIViewController
self.myViewControllers = \[vc0, vc1, vc2\]
pvc.setViewControllers(\[myViewControllers\[1\]\], direction:.Forward, animated:false, completion:nil)
println("Loaded")
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var currentIndex = find(self.myViewControllers, viewController)!+1
if currentIndex >= self.myViewControllers.count {
return nil
}
return self.myViewControllers\[currentIndex\]
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var currentIndex = find(self.myViewControllers, viewController)!-1
if currentIndex < 0 {
return nil
}
return self.myViewControllers\[currentIndex\]
}

Resources