Swift: The best way to show and hide different views based off of my UISegmentedControl? - ios

I want to show one view when the segmented control highlights the first option. When the user highlights the other option, I want the first view to disappear (or hide) and the other view to become visible. Then, if the user presses the first option again, the second view hides and the first becomes visible.
What is the best way to do this?
I do not want to switch ViewControllers, but simply Views who are both using the same ViewController.

A way to do that would be to give a tag to each view (as in your segment's indices) and call a method when the its value is changed that would hide all view's accept the one with the right tag number.

You could hook the UISegmentedControl from the view controller to the code using an #IBAction and use the following method:
#IBAction func switchView(sender: UISegmentedControl) {
// Change your view controller's view property
// to reference whatever custom views you have.
if(sender.selectedSegmentIndex == 0) {
self.view = viewOne
} else {
self.view = viewTwo
}
}
viewOne and viewTwo being UIViews

Related

Convert modal view to fullscreen view

I have a modal view controller A presented at the top of the view controllers hierarchy.
Is it possible to make it fullscreen temporarily when a user presses a button? And then go back to standard modal look when used presses another button?
To clarify, I'm not talking about modalPresentationStyle = .fullScreen BEFORE A is presented, I need to present A in a standard way and then stretch it to be fullscreen when needed.
Although if I write pseudo code it would be something like this:
class A: UIViewController {
#objc func goFullScreen(sender: UIButton) {
// pseudo code:
// modalPresentationStyle = .fullScreen
// go fullscreen, block `drag-to-dismiss` gesture, remove `cornerRadius`, set `self.view.frame = UIScreen.main.bounds`
}
#objc func cancelFullScreen(sender: UIButton) {
// pseudo code:
// modalPresentationStyle = .pageSheet
// return to the standard look of a modal view controller
}
}
I found UIAdaptivePresentationControllerDelegate.presentationControllerShouldDismiss method that intercepts drag to close gesture, but I don't see any way to go fullscreen.
Picture of what I am talking about:
ps. I know I can make a custom container view controller with a custom transition delegate but I'd like to know if it's possible to implement such behaviour with system classes because I basically need just to flip modalPresentationStyle property with some interpolation animation...
Also on the right I hide/show some UI elements, but still it's the same view controller

How can I get a Table View to register taps when each cell has an Image View covering it?

I've been trying to create table view cells each with a UIImageView serving as a background for them. However, when I tap on each cell the table view will not register the click and will not transition to the view controller I have hooked up, even while I'm using the didSelectRowAtIndexPath function.
I realize it's probably an issue with the ImageView obstructing the table views ability to register the cell tap. The cells will transition however when I drag my finger/mouse on it from left to right, just not on taps. I tried to use a Tap Gesture Recognizer on the Image View however it only worked for the cell at the very top and not all of them. How do I tackle this issue?
Here is an image of the table view cells so you have an idea of what I'm working with: http://imgur.com/a/Ku4uD. Thank you!
If you uncheck User Interaction Enabled on your Image View, the problem should be solved. When running into a problem always check the user interaction of the most child view and work your way up.
One trick I have also learned is to create a subclass of a child and override touchesShouldCancel like so:
override func touchesShouldCancel(in view: UIView) -> Bool {
print("touchesShouldCancel")
//Run extra code that you want when the user selects this view
//then still retrieve the tap by its parent.
return false
}
I am unsure of exactly what your problem is, but I would delete whatever segue that you have, add a new one by dragging from the yellow circle on the left side of the center portion of the top of your tableView ViewController inside the storyboard, to the viewController that you desire it to segue to. Give the segue an appropriate identifier, and then inside your tableView class under tableView didSelectRow add performSegue(withIdentifier: "ChosenIdentifier", sender: indexPath)
Then in prepare forSegue add in:
if let vc = sender.destination as? TheViewControllerYouAreSegueingTo {
if let indexPath = sender as? IndexPath {
vc.variableIdentifyingWhatCellWasClicked = indexPath.row
}
}
with whatever adjustment is needed to meet your specific needs.

I want to pass touch event for a transparent custom cell to its parent view (which is a pageview controller)?

I'm trying for this solution from many days, I have a scenario where I want to pass touch even (Swiping for page view controller) of my first custom cell to the parent view which is a page view controller.
Here my first cell in the table view is a transparent cell. It is not visible instead of we can see the background view which is a super class of table view controller and it is a page view controller. So here I want to pass the touch event which should be swiping for page view controller. And all the remaining cells are not transparent. Here I'm sending the image so that you can understand. easily. So help me out in passing the swipe/touch to my page view controller Basic Look with transparent cell on top So in that transparent cell area we can see the super view of table view controller which is a page view controller.
As you can see left side is the basic look, and in that you can see the page view controller, and then the right side image is when we scroll the cells it will look like this.
So now you can understand clearly the height of table view and my requirement too.
So how to pass touch/ swipe event to the page view controller when we select transparent cell(indexpath.row ==0 first cell)
I tried the solution that given but no use..
You can add one more view on top of it (pageview -> cellview -> new view on top with opacity = 0). Next add swipe gesture to new view and finally make a newView.delegate = pageviewController to capture swipe event.
#protocol NewViewControllerDelegate<NSObject>
-(void)gestureDidFire;
#end
#interface NewViewController : UIViewController
// you gesture outlet look like IBAction *swipeGestureReconizer;
#property (nonatomic, assign)id <NewViewControllerDelegate>delegate;
#end
//newViewContrlloer.m
- IBAction swipeGestureReconizer
{
if(self.delegate && [self.delegate responseToSelector:#seletor(gestureDidFire)])
{
[self.delegate gestureDidFire];
}
}
//in your page view interface
#interface yourPageView()<NewViewControllerDelegate>
{
//need instance of newView
newViewController.delegate = self;
}
-(void)gestureDidFire
{
//implement what you want
}

Get a UIButton's tag from the UIButtons which are in the popover presented by this UIButton

The headline seems lengthy but what I'm trying to do is quite simple.
I have a couple of identical buttons lined in a row and set their tags to 0...n. Clicking on any of them (the 2nd for example) would bring up a popover view in which there are several buttons representing different options (A, B, C, D). What I want to do is to turn the 2nd Button's title to B if we click on option B.
The problem is that the popover view does not know which Button presented it, since all popoverViews are instances of the same UIViewController class. So I am thinking of distinguishing the n buttons by setting their tags to different values. However, I don't know how to get the UIButton's tag from a button inside the popover this UIButton presented.
Many thanks in advance!
This is how I will solve this in swift. I will declare a delegate in the popoverViewController and have a method e.g
protocol popOverViewControllerDelegate: class {
func popOverViewController(controller: PopOverViewController,
didSelectItem buttonTitle: String)
}
then I will add a target action to the UIButton in the popOver
button.addTarget(self, action: "selected:",forControlEvents:.TouchUpInside)
the select method will have sender passed to it
func selected(sender:UIButton){
delegate?.popOverViewController(self, didSelectItem: sender.currentTitle)
//dismiss viewcontroller
}
remember to declare
weak var delegate: popOverViewControllerDelegate!
now have the viewcontroller that called the popOver, subclass to this delegate and implement it's method. Whenever a button in the popOver is selected, this method will be called and the currentTitle of the method will be passed. You can now use that to set the currentTitle of the button that called the popOver.
In case you need further help with the last part, please ask.
I've fixed the problem by adding a property tagNumberso that after instantiating the popoverViewController's class, I set the instance's tagNumber to the sender's tag. Then I send the tagNumber back together with sender.currentTitle. This way, the presenter of the popover could know both the title and tag number of the UIButton.

Tab bar with multiple tabs using only one view controller

I was not able to find an answer to my problem on SO, please link me if an answer already exists somewhere! My problem seems pretty common- i have a tableview embedded in a nav controller and i want a tab bar with 3 items, where the 3 items change the tableview to populate different data, the first tab representing the default data in the tableview when the view is loaded.
But it seems unnecessary to make two extra UITableViewController classes for the other two tabs, when i can simply just change the data populating the table, with a simple [tableView reloadData]. How do you go about doing this, and also how to implement this in storyboard?
Sounds to me what you really want is a single UITableViewController with a Segmented Control to change the view.Tab Bars are for navigation.
Segmented Control
Use UIControlEventValueChanged to detect the change, load the new data and reload the view.
You didn't indicate what you mean by 'different data'. If you mean something like perform some action which updates data via a CoreData fetch/predicate/sort, etc. then using the Segmented Control is probably the way to go. If your data is dramatically different (different entities, different data management, etc. ) then you should probably go with separate UITableViewControllers as you should not try to over generalize your UITableViewController but rather pair your data to your UITableViewController. After all, that's what it is for.
You can make multiple relationship segue to one controller with ctrl+drag like this.
storyboard> 5 times ctrl+drag to one Navigation Controller
And you should make CustomTabBarController.swift to modify tabs.
Don't forget to change class name of TabBarController that is drawn in storyboard.
class CustomTabBarController: UITabBarController {
let MENUS = ["tab1", "tab2", "tab3", "tab4", "tab5"]
override func viewDidLoad() {
super.viewDidLoad()
let items = tabBar.items!
for (var idx=0; idx<items.count; idx++) {
items[idx].title = MENUS[idx]
items[idx].tag = idx
}
}
...
}
You can use tag or selected index of tabs on the ViewController.swift
let tag = self.tabBarController?.tabBar.selectedItem!.tag
let selectedIndex = self.tabController?.selectedIndex
What you can do is reuse the same Class and have a check in you viewDidLoad method to determine how to populate your tableView, for example:
- (void)viewDidLoad{
//itemType is a property you set
//when instantiating the controller
int index = self.itemType;
switch (index) {
case 0:
[self populateTab1];
break;
case 1:
[self populateTab2];
break;
case 2:
[self populateTab3];
break;
default:
break;
}
}
In storyboard, add UITabbar into your table view controller. Do not use UITabbarViewController which works as a container of view controllers. On the other hand UITabbar is just a control unit.
Set the delegate of the tab bar to your table view controller, and add the following protocol method:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item;
You can load the correct data in this method. You can get the index of the selected item (button) by
NSUInteger index = [tabBar.items indexOfObject:item];

Resources