Segue to DetailViewController (SplitViewController) - ios

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.

Related

How to bring UIImageView to foreground upon tapping a tableViewCell?

currently thumbnails are being shown in UITableViewCell and upon tapping a cell, I want the image to be shown in foreground with a cross/X button on right top to dismiss the image and show tableView. I have the following code in didSelectRow:
let hoverImage = UIImageView()
hoverImage.image = UIImage(named: "splashpt")
hoverImage.contentMode = .scaleAspectFit
self.view.addSubview(hoverImage)
hoverImage.center = self.view.center
hoverImage.layer.zPosition = 5
self.view.bringSubview(toFront: hoverImage)
Still the image doesn't show up. The computation is hitting this section of the code because I'm able to debug and step through this part of the code. But nothing shows up on screen. I'm using the zPosition AND bringSubview(toFront:) and neither of the seem to work for my requirement. Any help would be greatly appreciated. Thank you.
This is a Demo table view.On tapping the table view cells a view is poped up with close button. And on pressing the close button the pop up view is closed.
import UIKit
class ViewController: UITableViewController {
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.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = "Happy"
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Cell\(indexPath.row) is selected")
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let popoverVC = storyBoard.instantiateViewControllerWithIdentifier("PopViewController") as! PopViewController
popoverVC.delegate = parentViewController as? InfoViewDelegate
let nav = UINavigationController(rootViewController: popoverVC)
nav.modalPresentationStyle = UIModalPresentationStyle.Popover
nav.navigationBar.hidden = true
self.presentViewController(nav, animated: true)
{
}
popoverVC.passingViewController = self
}
}
This is a PopUpViewController:
import UIKit
protocol InfoViewDelegate: class
{
func infoViewClicked(tag: Int)
}
class PopViewController :UIViewController
{
#IBOutlet weak var btnClose: UIButton!
var delegate = InfoViewDelegate?()
var passingViewController: UIViewController!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
}
override func viewDidDisappear(animated: Bool) {
self.presentingViewController?.dismissViewControllerAnimated(true
, completion: {
})
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func btnClicked(sender: UIButton) {
if(sender == self.btnClose)
{
self.delegate?.infoViewClicked(1)
self.presentingViewController?.dismissViewControllerAnimated(true
, completion: {
})
}
}
}

Detecting when tabBar item is pressed when is page

I have a UITabBar with 4 tabs.
I want to that a specific function will be called in each ViewController of the tab when the tabBarItem is pressed twice (like, the user is now on ProfileVC and presses on Profile item, I want to refresh the view).
How can I detect when the user pressed on the tab that he is in its view now?
Thank you!
One option is do the refreshing inside viewWillAppear() method. And the second one is considerably long.
In parent view controller
protocol ParentDelegate {
func refresh()
}
class LandingViewController: UIViewController, UITabBarDelegate {
var delegate: ParentDelegate?
var selectedItem: UITabBarItem!
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.delegate = self
self.selectedItem = self.tabBar.selectedItem
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SegueNameForDestinationViewController1" {
if let vc = segue.destinationViewController as? YourDestinationViewController1 {
self.delegate = vc.self
}
} else if segue.identifier == "SegueNameForDestinationViewController2" {
if let vc = segue.destinationViewController as? YourDestinationViewController2 {
self.delegate = vc.self
}
}
}
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
if self.selectedItem == item {
self.delegate?.refresh()
}
self.selectedItem = item
}
}
In each tab view controller,
class TabViewController: UIViewController, ParentDelegate {
func refresh() {
//write your code here
}
}

Passing data between segue with Swift 2.0

I seem to be following tutorials to the tee yet I can't get my data to pass to my second view controller without being nil.
I am new to Swift so I'm probably also not using optionals correctly. Here is how I have my code set up.
import UIKit
class DetailsViewController: UIViewController {
var book : PLBook?
override func viewDidLoad() {
super.viewDidLoad()
//View Did Load
print(self.book)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
}
Then this is how I am presenting the second view controller and preparing for segue.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("toDetailVC", sender:self)
}
//MARK: Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "toDetailVC"){
//prepare for segue to the details view controller
if let detailsVC = sender?.destinationViewController as? DetailsViewController {
let indexPath = self.tableView.indexPathForSelectedRow
detailsVC.book = self.books[indexPath!.row]
}
}
}
In the second view controller, the book var is always nil. Any ideas how I can get the data to pass?
Try This:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "toDetailVC") {
//prepare for segue to the details view controller
let detailsVC = segue.destinationViewController as! DetailsViewController
let indexPath = self.tableView.indexPathForSelectedRow
detailsVC.book = self.books[indexPath!.row]
}
You should be using segue.destinationViewController, not sender?.destinationViewController.

Overriding Swiping Actions on a UITableView over UIPageController VC segues

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) {
}

Get value from Modal View in Swift iOS

i'm trying to start writing Swift and i'm trying to get a value from a modal view controller with no luck.
I have two controllers, the ViewController and modalViewController.
In ViewController i have a UITableView and with a press of a button i open the modalViewController.
Then from a UITextField i pass the value.
I have implement a protocol with delegate and func but somewhere i'm missing something or had it wrong.
ViewController.swift
import UIKit
class ViewController: UIViewController,UITableViewDelegate,modalViewControllerDelegate{
#IBOutlet var table: UITableView!
var tableData = ["First Row","Second Row","Third Row"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(animated: Bool) {
table.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(table:UITableView?,numberOfRowsInSection section: Int) -> Int
{
return tableData.count
}
func tableView(table:UITableView?,cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
let cell:UITableViewCell = UITableViewCell(style:UITableViewCellStyle.Default,reuseIdentifier:"cell")
cell.textLabel?.text = tableData[indexPath.row]
return cell
}
func sendText(text: NSString) {
tableData.append(text)
} }
modalViewController.swift
import UIKit
protocol modalViewControllerDelegate {
func sendText(var text: NSString)
}
class modalViewController: UIViewController{
let delegate: modalViewControllerDelegate?
#IBOutlet var textField: UITextField?
#IBAction func cancelButton(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func saveButton(sender: AnyObject) {
delegate?.sendText(self.textField!.text)
dismissViewControllerAnimated(true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
I have no errors in the code, the delegate is not working, it's always nil.
Thanks.
You have to assign the delegate in your first view controller.
Also, you have to change let delegate: modalViewControllerDelegate? to a var, or else you can't change it.
Right now your delegate is empty.
It's unclear how you're accessing ModalViewController. If you're using segues:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "modalViewControllerSegue" {
var destination = segue.destinationViewController as CategoryViewController
destination.delegate = self
}
}
Or if you're doing it programmatically:
var modalViewController = ModalViewController(parameters)
modalViewController.delegate = self
presentViewController(modalViewController, animated: true, completion: nil)
Storyboard identifier:
let destination = UIStoryboard.mainStoryboard().instantiateViewControllerWithIdentifier("ModalViewController") as ModalViewController
delegate = self
showViewController(destination, sender: nil)
EDIT:
If you want to access ModalViewController by selecting a cell you need the tableView: didSelectRowAtIndexPath method:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("modalViewControllerSegue", sender: self)
}
Using this, you'll need the method prepareForSegue to set the delegate.
You have to set your modalViewController's delegate property before presenting it. If you're using segues, you can do this in prepareForSegue(_:).
Also, class names should begin with uppercase letters (modalViewController should be ModalViewController). Only instances should begin with lowercase letters.
Another option, instead of using delegation, is to use an unwind segue. Here's a tutorial: http://www.cocoanetics.com/2014/04/unwinding/
In your case, in your presenting view controller you could have the method:
func returnFromModalView(segue: UIStoryboardSegue) {
// This is called when returning from the modal view controller.
if let modalVC = segue.sourceViewController as? ModalViewController
where segue.identifier == "mySegueID" {
let text = modalVC.textField.text
// Now do stuff with the text.
}
}
And then just link up everything in the Interface Builder as shown in the tutorial.

Resources