How to make Horizontal scroll segment in swift - swift

when we scroll segment horizontally then the segment and regarding viewcontroller should scroll move horizontally
for that i have tried SJSegmentedScrollView
i have installed cocoapod and added below code:
code: but here even segment not coming.. where i am mistake.. how to add segment and viewcontrollers horizontally
or is there any other thirdparty library for segment please do help here
import UIKit
import SJSegmentedScrollView
class SegmentViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationController?.isNavigationBarHidden = true
if let storyboard = self.storyboard {
let headerViewController = storyboard
.instantiateViewController(withIdentifier: "SegmentViewController")
let firstViewController = storyboard
.instantiateViewController(withIdentifier: "FirstTableViewController")
firstViewController.title = "First"
let secondViewController = storyboard
.instantiateViewController(withIdentifier: "SecondTableViewController")
secondViewController.title = "Second"
let thirdViewController = storyboard
.instantiateViewController(withIdentifier: "ThirdTableViewController")
thirdViewController.title = "Third"
self.present(thirdViewController, animated: false, completion: nil)
let segmentedViewController = SJSegmentedViewController(headerViewController: headerViewController,
segmentControllers: [firstViewController,
secondViewController,
thirdViewController])
addChild(segmentedViewController)
self.view.addSubview(segmentedViewController.view)
segmentedViewController.view.frame = self.view.bounds
segmentedViewController.didMove(toParent: self)
}
}
}

I think no need to the using third party frameworks for every development. Try native ways first. For example you can do something like this by using UIKit, UISegmentedControl Apple Document
class ViewController: UIViewController {
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var textLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func segmentedControlPressed(_ sender: UISegmentedControl) {
switch segmentedControl.selectedSegmentIndex {
case 0: textLabel.text = "First";
case 1: textLabel.text = "Second";
case 2: textLabel.text = "Third";
default: break;
}
}
}

Related

How to show containerview in viewcontroller in swift

I need to show containerview in viewcontroller, so i have taken one viewcontroller and designed and in that i have taken one containerview below to the buttons view
given containerview constraints: below to the buttonview
top = buttonview.bottom 10, leading, trailing, bottom = 0
there are two buttons indicates with green line.. initially i am in the "viewproposalvc" with red colour button.. here if i click gray colour button then i need to show containerview
here the viewproposalvc code:
class ViewProposalVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var postId: Int?
#IBOutlet weak var containerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
updateNavigationBar(with: "View Proposal")
containerView.isHidden = true
}
#IBAction func grayBtn(_ sender: Any) {
containerView.isHidden = false
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ContainerVC") as? ContainerVC
vc.serviceId = self.viewproposalData?.result?.posted_services?.id
self.navigationController?.pushViewController(vc!, animated: true)
}
#IBAction func redBtn(_ sender: Any) {
containerView.isHidden = true
postedServicesCall()
}
}
this is containervc code:
class ContainerVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
}
}
but here containervc not coming below to the buttonsview.. its coming in separate viewcontroller, why?
o/p of containervc: i dont want separate viewcontroller.. i need containervc to show below to the buttonsview of the viewproposalvc
first time i am working with container views, please do help
The reason why is because you are calling
self.navigationController?.pushViewController(vc!, animated: true)
ContainerView is just a generic UIView with an embedded segue, that is triggered from viewDidLoad of the hosted VC. If you need to do additional setup of that VC I suggest making an var on ViewProposalVC and making desired changes from there.
as in
class ViewProposalVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var postId: Int?
#IBOutlet weak var containerView: UIView!
#IBOutlet weak var secondaryController: UIViewController!
override func viewDidLoad() {
super.viewDidLoad()
updateNavigationBar(with: "View Proposal")
containerView.isHidden = true
}
#IBAction func grayBtn(_ sender: Any) {
containerView.isHidden = false
self.secondaryController.serviceId = self.viewproposalData?.result?.posted_services?.id
}

How do I present ViewController programatically?

import UIKit
//EventList ViewController
class EventPage: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
class EventForm: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
//IBOutlets
#IBOutlet weak var eventNameField: UITextField!
#IBOutlet weak var fromTimePicker: UIDatePicker!
#IBOutlet weak var toTimePicker: UIDatePicker!
#IBOutlet weak var colorPreview: UIView!
#IBAction func cancel(_ sender: Any) {
//empty text field
eventNameField.text = ""
}
#IBAction func save(_ sender: Any) {
if (eventNameField.hasText) {
//fix error handling
eventNameField.backgroundColor = UIColor.systemGray2
//pull data from fields
let text = eventNameField.text!
let fromTime = fromTimePicker.date
let toTime = toTimePicker.date
//initialize object
let currentEvent = EventModel(eventName: text, fromTime: fromTime, toTime: toTime, color: storedColor)
//append to data model
EventDataArray.append(currentEvent)
//transition
present(EventPage(), animated:true)
}
else {
eventNameField.backgroundColor = UIColor.systemRed
}
}
}
I currently have an EventPage class declared as type UIViewController, but upon pressing the save button with a populated text field a transition to a blank ViewController occurs. I've attached the class to the correct ViewController in main.storyboard.
The problem in here is that you are creating a new EventPage but it doesn't inherit from Storyboard.
1
Go to the inspector in your storyboard, select your View Controller, and write an identifier for your View Controller (can be anything)
Write it in Storyboard ID:
2
Replace
present(EventPage(), animated:true)
With
(don't forget to replace 'MYIDENTIFIER' with the id you entered earlier)
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MYIDENTIFIER") as! EventPage
// If you need to do any configurations to your view controller, do that in here.
// For example:
// viewController.label.text = "Hello, world!"
present(viewController, animated:true)
Note
If the name of your Storyboard file name is not called Main, replace "Main" in step 2 with the name of your storyboard file (excluding .storyboard)

Swift: NSTextfield and popover with suggested list of tags

I'm trying to do something like this:
This is what I have now:
How I'm doing this now:
I have MainViewController with input field: NSTextField.
Using controlTextDidChange I'm checking if input field contains # character.
If yes - I'm opening popover using PopoverViewController.
In the PopoverViewController I have NSTableView that displays a list of available tags.
By clicking on the row it should add selected tag to the input fields and close the popover.
So here I even have to implement 2 way of communication between 2 view controllers.
Questions:
I feel that I'm doing something wrong. The logic of this tags-popover looks too complicated for me. Maybe an easier solution exists, but I just don't know how to do this.
What the best way to display the list of available tags in NSTextField? Should I use a popover with another view controller?
How to communicate best in this case between 2 different view controllers? (I have to send InputField value to PopoverViewController, filter results there and display them. Then, I have to send back to MainViewController selected tag)
My code:
Here is some parts of my code if you want to see it in more details:
MainViewController:
class ViewController: NSViewController, NSTextFieldDelegate {
#IBOutlet weak var InputField: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
InputField.delegate = self
}
func controlTextDidChange(_ sender: Notification) {
if InputField.stringValue.contains("#") {
let controller = ToolTipVC.Controller()
let popover = NSPopover()
popover.contentViewController = controller
popover.behavior = .transient
popover.animates = true
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxY)
}
}
ToolTipViewController:
import Cocoa
import EventKit
class ToolTipVC: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
#IBOutlet weak var ToolTipTable: NSTableView!
override func viewDidLoad() {
super.viewDidLoad()
ToolTipTable.delegate = self
ToolTipTable.dataSource = self
}
func numberOfRows(in tableView: NSTableView) -> Int {
return ReminderLists.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let cell = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as? NSTableCellView else { return nil }
cell.textField?.stringValue = "Row #\(row): " + ReminderLists[row].title
return cell
}
}
extension ToolTipVC {
static func Controller() -> ToolTipVC {
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let identifier = NSStoryboard.SceneIdentifier("ToolTipId")
guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? ToolTipVC else {
fatalError("Why cant i find viewcontroller? - Check Main.storyboard")
}
return viewcontroller
}
}
I appreciate your feedback and advises.
Thank you in advance!
P.S.: I'm not a developer, I'm a Product Manager. This is my pet-project, so I know that my code is awful and has a lot of mistakes.
Please, don't judge me hard :)
At first glance it looks like when you call this line:
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxY)
preferredEdge is set to NSRectEdge.maxY
Try changing this from Y to X
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxX)
Is there a reason you are usin NSPopover?
If that doesnt work try this:
let controller = MyPopViewController()
controller.modalPresentationStyle = UIModalPresentationStyle.popover
let popController = controller.popoverPresentationController
popController?.permittedArrowDirections = .any
popController?.delegate = self
popController?.sourceRect = //set the frame here
popController?.sourceView = //set the source view here
self.present(controller, animated: true, completion: nil)
Here is another approach, this will centre the pop over over a button. Which is what you are trying to do i am assuming with no up arrow? Is that correct?
So you can hit the filters button on the right side whihc you have and this pop over will appear centred.
#IBAction func buttonTap(sender: UIButton) {
// get a reference to the view controller for the popover
let popController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "popoverId")
// set the presentation style
popController.modalPresentationStyle = UIModalPresentationStyle.popover
// set up the popover presentation controller
popController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.up
popController.popoverPresentationController?.delegate = self
popController.popoverPresentationController?.sourceView = sender // button
popController.popoverPresentationController?.sourceRect = sender.bounds
// present the popover
self.present(popController, animated: true, completion: nil)
}

macOS - Swift 4.0 Container View does not show NSView

I'm writing my first macOS App with Swift 4.0 and
currently I'm struggling with my Container View.
I've this layout
Layout while running the app
The issue is, when I click on one of the TableView Items my Container View does not load the NSView with the "THEMA 1" label in it.
(All TableView Items should load the "THEMA 1" View)
Here is my ViewController code
import Cocoa
class ViewController: NSViewController {
//VARS
var tableViewArray = ["Thema 1", "Thema 2", "Thema 3", "Thema 4", "Thema 5"]
var containerViewArray: [NSView]!
var thema1View = Thema1()
//IBOutlets
#IBOutlet weak var tableView: NSTableView!
#IBOutlet weak var container: NSView!
override func viewDidLoad() {
super.viewDidLoad()
//setup TableView
tableView.delegate = self
tableView.dataSource = self
tableView.action = #selector(onItemClicked)
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
//Extensions
extension ViewController: NSTableViewDelegate, NSTableViewDataSource {
//show what is clicked on tableView
#objc private func onItemClicked() {
if (tableView.clickedRow <= tableViewArray.count - 1) && (tableView.clickedRow >= 0) {
print("\(tableViewArray[tableView.clickedRow]), clicked")
removeAllSubView()
container.addSubview(thema1View, positioned: .above, relativeTo: container)
}
else {
print("There is no content in this cell")
}
}
//removes all SubViews from containerView
func removeAllSubView() {
for view in container.subviews{
view.removeFromSuperview()
}
}
//rows in tableViewArray
func numberOfRows(in tableView: NSTableView) -> Int {
return tableViewArray.count
}
//populate the tableView
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
return tableViewArray[row]
}
}
Thema1 ViewController code
import Cocoa
class Thema1: NSView {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
}
}
I think the issue is buried in the onItemClicked() method, but as I mentioned I'm quite new to macOS and Swift 4.0.
Therefore I've found quite many results regarding iOS but a few macOS, but nothing hinting to my case.
Thank you for taking your time and best regards,
Danny
I found sample code SourceView but it is rather complicated and in Objective-C. Here's my translation of the relevant part to Swift (I'm not very familiar with Swift).
class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
var tableViewArray = ["Thema 1", "Thema 2", "Thema 3", "Thema 4", "Thema 5"]
var detailViewController: NSViewController?
#IBOutlet weak var container: NSView!
#IBAction func tableViewClickAction(_ tableView: NSTableView) {
if tableView.clickedRow >= 0 {
print("\(tableViewArray[tableView.clickedRow]), clicked")
// remove the detail view if there is one
if let oldViewController = detailViewController {
oldViewController.view.removeFromSuperview()
oldViewController.removeFromParentViewController()
detailViewController = nil
}
// determine the identifier of the new detail view, this is the Storyboard ID of the detail scene
var sceneIdentifier: NSStoryboard.SceneIdentifier?
switch tableView.clickedRow {
case 0:
sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema1")
case 1:
sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema2")
case 2:
sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema3")
case 3:
sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema4")
case 4:
sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: "Thema5")
default:
sceneIdentifier = nil
}
if sceneIdentifier != nil {
// load the new detail controller and view from the storyboard
detailViewController = self.storyboard?.instantiateController(withIdentifier:sceneIdentifier!) as? NSViewController
if let newViewController = detailViewController {
newViewController.view.translatesAutoresizingMaskIntoConstraints = false
// add controller and view
self.addChildViewController(newViewController)
container.addSubview(newViewController.view)
// add constraints
let views = ["targetView": newViewController.view]
let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|[targetView]|",
options: [], metrics: nil, views: views)
let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|[targetView]|",
options: [], metrics: nil, views: views)
NSLayoutConstraint.activate(horizontalConstraints)
NSLayoutConstraint.activate(verticalConstraints)
}
}
}
else {
print("Clicked outside the cells")
}
}
}
Thank your for helping me out with the storyboard idea.
I've made a test dummy, where I had my Main view and made two ViewControllers with labels in it.
All ViewControllers got their Storyboard-IDs.
The Main view had two buttons, both assigned to one of the ViewControllers.
By clicking them, you will load one of the Test ViewControllers.
I came up with this
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func switchViews(viewNumber: Int) {
let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)
var controller = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "Main"))
switch viewNumber {
case 1:
print("View: 1")
controller = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "Test1"))
case 2:
print("View: 2")
controller = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "Test2"))
default:
print("Default");
}
if let window = NSApplication.shared.mainWindow {
window.contentViewController = controller as? NSViewController
}
}
#IBAction func buttonAction(_ sender: NSButton) {
var viewNumber: Int = 0
switch sender.title {
case "controller1":
viewNumber = 1
print("Button: 1")
case "controller2":
viewNumber = 2
print("Button2: 2")
default:
print("Default")
}
switchViews(viewNumber: viewNumber)
}
}

Swift 4 Delegate doesn't work from childViewController

I have to code simple program. Just one login screen waiting for some password and after setting proper one, change screen to "program itself" and its features.
I decided to do it by container View and its subviews. everything works fine but delegate which should be responsible for triggering this change doesn't respond. In any option I tried, nothing has changed... it still doesn't respond.
This is code of ViewController (main):
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var container: NSView!
var vc1 : ViewController1 = ViewController1()
var vc2 : ViewController2 = ViewController2()
override func viewDidLoad() {
super.viewDidLoad()
//initialise of delegate:
vc1.delegate = self
// set subviews:
vc1 = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "ViewController1")) as! ViewController1
vc2 = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "ViewController2")) as! ViewController2
self.addChildViewController(vc1)
self.addChildViewController(vc2)
// set first view:
vc1.view.frame = self.container.bounds
self.container.addSubview(vc1.view)
}
func changeViews()
{
for sView in self.container.subviews {
sView.removeFromSuperview()
}
// set second view:
vc2.view.frame = self.container.bounds
self.container.addSubview(vc2.view)
}
}
extension ViewController: ViewController1_Delegate {
func passwdEntered(_ correctPasswd: Bool) {
if correctPasswd == true{
changeViews()
}
}
}
and this is First (SubView) ViewController code, where I'm entering passwd:
import Cocoa
protocol ViewController1_Delegate: class {
func passwdEntered(_ correctPasswd: Bool)
}
class ViewController1: NSViewController{
#IBOutlet weak var passwordField: PasswordField!
weak var delegate: ViewController1_Delegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func passwordFIeldEdited(_ sender: PasswordField) {
delegate?.passwdEntered(true/*for testing purpose always true*/)
}
}
Finally Second (SubView) ViewController code:
import Cocoa
class ViewController2: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
What I'm doing wrong?
First you say this:
var vc1 : ViewController1 = ViewController1()
override func viewDidLoad() {
super.viewDidLoad()
vc1.delegate = self
Then you say this:
vc1 = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"),
bundle: nil).instantiateController(
withIdentifier: NSStoryboard.SceneIdentifier(
rawValue: "ViewController1")) as! ViewController1
So, you set yourself as delegate on a ViewController1 instance, but then, in the very next line, you throw away that ViewController1 and replace it with another!
Move the line v1.delegate = self down to after you set the real value of vc1.