Replacing Double StackView with Single StackView on Ipad? - ios

I have a storyboard in which there is a separate view controller for a UIView. In that UIView I have to load 10 buttons in a single row in the case of IPad else I have to load 10 buttons in two rows. I have tried using 2 separate xib files and loading them statically but I want to do it programatically using view controllers.
I have added the screenshot of my storyboard.
Can anybody guide me on changing the views dynamically.Here is the code of the new ViewController for the buttons.
import Foundation
class TNPSRatingsViewController: UIViewController {
var selectedScoreButton: TNPSScoreButton?
var scoreSelectedOnce = false
#IBOutlet var buttons: [TNPSScoreButton]!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.modifyPositionOfTNPSButton()
}
override func viewWillTransition(to size: CGSize,
with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: nil, completion: ({ [unowned self] _ in
self.modifyPositionOfTNPSButton()
}))
}
// MARK: - Private functions
fileprivate func modifyPositionOfTNPSButton() {
if UIApplication.shared.delegate?.window??.traitCollection.horizontalSizeClass == .compact {
//
//
} else {
//
//
}
}
}
Thanks in Advance

How about using a UICollectionView?
on iPad, use 1 row of 10 items
on iPhone use 2 rows of 5 items
You can stick to view controller containment, or implement the uicollectionview directly with your first screen being the delegate/datasource.

Try making a class that will tell that current device is iPad or iPhone
class Env
{
//Check if its iPad
static var iPad: Bool
{
return UIDevice.current.userInterfaceIdiom == .pad
}
}
Now While you are require to add subview in containerView
just make use of that class as:
class ViewController: UIViewController {
var myCustomContainerView = UIView()
var subviewCreatedXIBForiPad = UIView()
var subviewCreatedXIBForiPhone = UIView()
override func viewDidLoad() {
super.viewDidLoad()
Env.iPad ? myCustomContainerView.addSubview(subviewCreatedXIBForiPad) : myCustomContainerView.addSubview(subviewCreatedXIBForiPhone)
}
}

Related

TabsController of Material Design is being shown above safe area [iOS, Swift, Material Design]

I was trying to use TabsController of Material Design in the ViewController. The viewcontrollers of tabs are
class ViewControllerOne: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
tabItem.title = "One"
}
}
class ViewControllerTwo: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
tabItem.title = "Two"
}
}
And the parent viewcontroller which is connected to the storyboard is,
import Material
class NewViewController: TabsController {
open override func prepare() {
viewControllers = [ViewControllerOne(), ViewControllerTwo()]
super.prepare()
tabBarAlignment = .top
tabBar.lineAlignment = .bottom
}
}
Now the output is,
The storyboard is
How can I bring the tabs under the Safe Area?

Swift - UIView Delegate Protocol not returning value

I am trying to apply the colour picker from the question below.
Simple swift color picker popover (iOS)
The way I set this up was the colour picker class is attached to a UIView within the main view controller. The code by Michael Ros works but when I try to access it using my main view controller nothing happens. Below is the code I use in my view controller. Is this correct? I went over other questions and I am not sure what I am doing wrong.
class ViewController: UIViewController {
weak var colorPickerDelegate: ColorPickerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
self.colorPickerDelegate = self
}
}
}
extension ViewController: colorPickerDelegate {
func colorChanged(color: UIColor) {
print(color)
}
}
The color picker code can be found on the attached question as I wasn't sure if it was allowed to copy the code over.
Thanks for the help
You should sublcass UIView and assign it to the view controllers view, then set the delegate of the ColorPickerView to the view controller:
ColorPickerView.swift
class ColorPickerView : UIView {
weak var delegate: ColorPickerDelegate?
// Other code from Michael Ros's adaptation.
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
lazy var colorPickerView = ColorPickerView(frame: CGRect(origin: .zero, size: CGSize(width: self.view.frame.width, height: 300)))
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
self.colorPickerView.delegate = self
self.view.addSubview(colorPickerView)
}
}
extension ViewController: ColorPickerDelegate {
func colorDidChange(color: UIColor) {
print(color)
}
}
you should replace
colorChanged -> colorDidChange !
if you delegate is ColorPickerDelegate; I think so

ContainerView Inside ScrollView don't scroll in Swift 3

I have example project on GitHub you can see on ->
https://github.com/LetSwiftDev/ContainerViewInsideScroll/tree/master
I have two, view controller, one is normal view controller named oneViewController second is twoViewController inside have UIScrollView and when I clicked OPEN TWO button going to twoViewController inside ContainerView but;
My twoViewController have different height size like 1500 and inside have scrollview and don't scroll to bottom? I didn't see middle side, bottom side labels.
How can I fix it?
Any idea?
Also my centerViewController codes under below. I'm controlling to past view controllers with centerViewController
import UIKit
open class centerViewController: UIViewController {
fileprivate weak var viewController : UIViewController!
fileprivate var containerViewObjects = Dictionary<String,UIViewController>()
open var currentViewController : UIViewController{
get {
return self.viewController
}
}
fileprivate var segueIdentifier : String!
#IBInspectable internal var startUp : String!
override open func viewDidLoad() {
super.viewDidLoad()
}
open override func viewDidAppear(_ animated: Bool) {
if let identifier = startUp{
segueIdentifierReceivedFromParent(identifier)
}
}
override open func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func segueIdentifierReceivedFromParent(_ identifier: String){
self.segueIdentifier = identifier
self.performSegue(withIdentifier: self.segueIdentifier, sender: nil)
}
override open func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == segueIdentifier{
if viewController != nil{
viewController.view.removeFromSuperview()
viewController = nil
}
if ((self.containerViewObjects[self.segueIdentifier] == nil)){
viewController = segue.destination
self.containerViewObjects[self.segueIdentifier] = viewController
}else{
for (key, value) in self.containerViewObjects{
if key == self.segueIdentifier{
viewController = value
}
}
}
self.addChildViewController(viewController)
viewController.view.frame = CGRect(x: 0,y: 0, width: self.view.frame.width,height: self.view.frame.height)
self.view.addSubview(viewController.view)
viewController.didMove(toParentViewController: self)
}
}
}
Here is your demo with solution. You can download it from here
https://www.dropbox.com/s/zvrjd0gp06xe5nw/ContainerViewInsideScroll-master%202.zip?dl=0
The thing is You have to learn autolayout for Scrollview.
I am just giving tips for the given constraint to scrollview.
First take scrollview and fit to the screen and give constraint as follows
Now take a view inside scrollview and fit to scrollview and give constraint like
Still its giving error of constraint. So now, give equal width of view to scrollview
and now you can take as many control as you want and give constraints as normal as we give to other controls.
Hope you understand well.
Enjoy Coding.
The reason is that scrollView is too long and hidden below the screen and contentSize isn't configured properly.
A lazy solution is to set them properly in code when twoViewController appears.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let width = self.scrollView.frame.width
scrollView.frame = CGRect(origin: scrollView.frame.origin,
size: CGSize(width: width, height: CGFloat(500)))
// Make sure this height is longer than scrollView.
scrollView.contentSize = CGSize(width: width, height: CGFloat(2000))
}
The proper solution (and correct way to implement a scrollview) is to fix scrollable content size ambiguity (auto layout errors in storyboard) like what #Jitendra Modi mentioned.

SubView click item to show in parent view label

I would like to make a UI that have label, table view and one button click. When click on the button, we pop up a half screen view that have lots of buttons. I want user can still click on the rest of the screen also.
So i use the approach that suggest in the post
How To Present Half Screen Modal View?
Method 2: to animate a UIView which is of size half of the existing view.
Then you have to simply follow animation of the UIView.
Here as it is just a UIView that will be added as subview to existing view, you will be able to touch the rest of the screen.
As i am newbie to the ios and swift, I would like to get some suggestions.
Now i am successfully add as subview and show in the half of the screen.
How can i implement to let subview click button result show on parent view label text?
I am thinking about parent.xib and subview.xib have the same UIVeiwController.swift. Then i can #IBOutlet and #IBAction to the same controller swift file and update the result. But don't know it is the accpetable way to do?
If not, how can the subViewController send result/event to the parent view and update in the parent view component?
You could use delegation. This keeps your view controllers decoupled, i.e. prevents the child from having a reference to its parent, which allows other view controllers to interact with the modal view controller in the same way.
class ParentViewController : UIViewController, ModalViewControllerDelegate {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let modalViewContorller = ModalViewController()
modalViewContorller.delegate = self
self.presentViewController( modalViewContorller, animated: true, completion: nil )
}
func modalViewControllerDidProduceResult( modalViewController: ModalViewController, result: String ) {
self.label.text = result
}
}
protocol ModalViewControllerDelegate {
func modalViewControllerDidProduceResult( modalViewController: ModalViewController, result: String )
}
class ModalViewController: UIViewController {
var delegate: ModalViewControllerDelegate?
#IBAction func buttonClicked( sender: AnyObject? ) {
delegate?.modalViewControllerDidProduceResult( self, result: "Hello!" )
}
}
You could also use a closure, which in Swift provides a more concise syntax.
class ParentViewController : UIViewController {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let modalViewContorller = ModalViewController()
self.presentViewController( modalViewContorller, animated: true, completion: nil )
modalViewContorller.resultBlock = { (result: String) in
self.label.text = result
}
}
}
class ModalViewController: UIViewController {
var resultBlock: ((String) -> ())?
#IBAction func buttonClicked( sender: AnyObject? ) {
self.resultBlock?( "Hello!" )
}
}

Sidemenu using swift - reference taken https://github.com/evnaz/ENSwiftSideMenu

I have created common sidemenu for all main view controller using reference https://github.com/evnaz/ENSwiftSideMenu
Now the issue is i have created sidemenu view controller from storyboard instead of using code itself,it will not show anything on side menu.
Ideally it has to show the page which design from story board.
Actually only TableViewController work with this example. i need to work with UIViewController.
Anyone have idea about this ?
Check out the latest version, I added precisely that functionality a few weeks ago: you can now use a UIViewController, no need to use a UITableViewController.
But other than that, I can't tell without more information why it doesn't show up.
I'm using it in several apps and it works ok.
I've got a UINavigationController, which uses a subclass of ENSideMenuNavigationController, and a UIViewController for the menu itself.
This is it, basically:
class MainNavigationController: ENSideMenuNavigationController, ENSideMenuDelegate {
override func viewDidLoad() {
super.viewDidLoad()
var mainMenuViewController: MainMenuViewController = storyboard?.instantiateViewControllerWithIdentifier("MainMenuViewController") as! MainMenuViewController
mainMenuViewController.navController = self
sideMenu = ENSideMenu(sourceView: self.view, menuViewController: mainMenuViewController, menuPosition:.Right)
//sideMenu?.delegate = self //optional
sideMenu?.menuWidth = 240.0 // optional, default is 160
sideMenu?.bouncingEnabled = false
sideMenu?.animationDuration = 0.2
// make navigation bar showing over side menu
view.bringSubviewToFront(navigationBar)
}
// MARK: - ENSideMenu Delegate
func sideMenuWillOpen() {
println("sideMenuWillOpen")
}
func sideMenuWillClose() {
println("sideMenuWillClose")
}
override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
super.didRotateFromInterfaceOrientation( fromInterfaceOrientation )
sideMenu?.updateFrame()
}
}
Then I have the menu view itself, also in the Storyboard, which is a UIViewController. Here is a fragment:
class ERAMainMenuViewController: UIViewController {
weak var navController: ERAMainNavigationController?
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var exitButton: UIButton!
#IBOutlet weak var headImage: UIImageView!
let kInset:CGFloat = 64.0
override func viewDidLoad() {
super.viewDidLoad()
// Customize apperance of table view
tableView.contentInset = UIEdgeInsetsMake(kInset, 0, 0, 0) //
tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine
tableView.backgroundColor = ERAssistantTheme.sideMenuItemBackgroundColor
tableView.scrollsToTop = false
// Preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = true
// tableView.selectRowAtIndexPath(NSIndexPath(forRow: selectedMenuItem, inSection: 0), animated: false, scrollPosition: .Middle)
}
}

Resources