Return value in DropDownMenu on selection? - swift

I'm new to Xcode and Swift. I am using this library: https://github.com/PhamBaTho/BTNavigationDropdownMenu to create DropDownMenu in my app. I followed the demo from Github and everything works fine. I am trying to get the selected value and assign it to a string outside didSelectItemAtIndexHandler function. This is my code:
var menuView: BTNavigationDropdownMenu!
var items = ["San Francisco", "New York", "LA", "Chicago"]
menuView = BTNavigationDropdownMenu(navigationController: self.navigationController, containerView: self.navigationController!.view, title: BTTitle.index(0), items: items)
menuView.didSelectItemAtIndexHandler = {(indexPath: Int) -> Void in
self. myCity = items[indexPath]
//print(myCity) // prints the correct city every time
}
self.navigationItem.titleView = menuView
I am trying to get the following outside menuView.didSelectItemAtIndexHandler :
var test = String()
test = myCity
print(test)
Any help will be appreciated. Thanks in advance!
I am trying to pass the data from here to TopFiveViewController.
menuView.didSelectItemAtIndexHandler = {(indexPath: Int) -> Void in
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let vc = storyboard.instantiateViewController(withIdentifier: "TopFiveViewController") as! TopFiveViewController
vc.myCity = self!.items[indexPath]
print(myCity) // prints the correct city every time but it doesn't pass the value to TopFiveViewController!
}
In the TopFiveViewController I have:
var myCity = String()
override func viewDidLoad() {
super.viewDidLoad()
if self.myCity == "San Francisco" {
// load SF json file
} else if myCity == "New York" {
// load NY json file
}

As you mentioned that everything is happening in your viewDidLoad() I think it's important to understand what is happening.
The view loads and test as well as myCity are set to nil.
When the user selects an item from the dropdown menu the code within menuView.didSelectItemAtIndexHandler will be called and myCity will now be set to the selected value although test will still be nil as the completion handler setting the value of myCity has no effect on test.
You should execute whatever code you want to execute when the value is selected within the completion handler (where self. myCity = items[indexPath] is located).

Related

Unable to pass on or retrieve data to another class

Trying to create a custom drop-down and facing issues in passing on data and retrieving the user selection from the custom drop-down. The solution however works when I use static var.
In the below code, I have a viewController class from where I am programmatically calling a popOver.
let countryDropDown = customDropdown()
#IBAction func btMultiCountry(_ sender: Any) {
ViewController.countryDropDown.removeAll() //fuction to clear the array before load
for c in g.country{ //Array from which all items are loaded on the custom dropdown
countryDropDown.addItems(labelText: c.countryName!, toggleState: 1) //passing the values in the add function to update the Array
}
countryDropDown.showDropdown(btMultiCountry) //programatically calling the function to display popover that has the collection view with the countries as items.
}
class customDropdown: NSViewController {
#IBOutlet weak var cvDropDown: NSCollectionView!
var pop = NSPopover() // if I put static var, the popover closes with the OK button as required, however, without static the OK button doest do anything
var dropDownLabelText = [String]() //if I put static var, the values are shown on the collection view without any issue. Without static the array is blank that was load from additems function
var dropDownToggle = [Int]() // same as above
var selectedItemsIndex: [Int] {
var a = [Int]()
for (i,t) in dropDownToggle.enumerated() {
if t == 1 {
a.append(i)
print(a)
}
}
return a
}
func showDropdown(_ sender: NSButton){
let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
let VC = storyboard.instantiateController(withIdentifier: "dropDownForm") as? customDropdown
pop.contentViewController = VC
pop.behavior = NSPopover.Behavior.transient
pop.show(relativeTo: sender.bounds, of: sender, preferredEdge: NSRectEdge.minY)
print(pop)
}
#IBAction func btOK(_ sender: Any) { //this function does not close the popover if there is not static mention above
pop.close()
}
I tried putting static when declaring the variables and it worked. I do not want static and want to create different instances of the class that gives me selectedItemsIndex
For eg:
let countryDropDown = customDropdown()
let personDropDown = customDropdown()
I should be able to get a different values for countryDropDown.selectedItemsIndex and personDropDown.selectedItemsIndex
Any help is appreciated.

Passing value while instantiating the view

Need to adding a value from one view controller to another view controller via the following way. I successfully able to move to the another page but not able to passing the value
sideMenuController?.cache(viewControllerGenerator: {
self.storyboard?.instantiateViewController(withIdentifier: "projectDetailController")
}, with: "333")
sideMenuController?.delegate = self as? SideMenuControllerDelegate
sideMenuController?.setContentViewController(with: "333", animated: Preferences.shared.enableTransitionAnimation)
sideMenuController?.hideMenu()
Add a property inside ProjectDetailController:
class ProjectDetailController: UIViewController {
var someValue: String?
/* more code */
}
Move the ProjectDetailController creation above and, once created - try to inject the value you want:
let projectDetailController = self.storyboard?.instantiateViewController(withIdentifier: "projectDetailController") as! UINavigationController
let projectDetailViewController = projectDetailController.viewControllers.first as! ProjectDetailViewController
projectDetailViewController.projectId = id
sideMenuController?.cache(viewControllerGenerator: { projectDetailController }, with: "333")
sideMenuController?.delegate = self as? SideMenuControllerDelegate
sideMenuController?.setContentViewController(with: "333", animated:
Preferences.shared.enableTransitionAnimation)
sideMenuController?.hideMenu()

JSQMessagesviewcontroller can't perform segues

so I created a chat view controller using the JSQMessagesViewController following this tutorial here: https://learnappmaking.com/chat-app-ios-firebase-swift-xcode/#comment-1930 my code is more or less the same, I didn't tweak anything significant in it, the tutorial is only for a single view controller so I added another view controllers for the app but every time it perform segues, I get the error SIGABRT, no matter if I segues with performSegue or with the back button in navigation bar, it keeps giving signal SIGABRT. any help would be appreciated.
this is my viewdidload:
override func viewDidLoad() {
super.viewDidLoad()
senderId = "1111"
senderDisplayName = "Bob"
title = "Steve"
inputToolbar.contentView.leftBarButtonItem = nil
collectionView.collectionViewLayout.incomingAvatarViewSize = CGSize.zero
collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSize.zero
let query = Constants.refs.databaseChats.queryLimited(toLast: 10)
_ = query.observe(.childAdded, with: { [weak self] snapshot in
if let data = snapshot.value as? [String: String],
let id = data["sender_id"],
let name = data["name"],
let text = data["text"],
!text.isEmpty
{
if let message = JSQMessage(senderId: id, displayName: name, text: text)
{
self?.messages.append(message)
self?.finishReceivingMessage()
}
}
})
// Do any additional setup after loading the view.
}
SIGABRT (signal abort) is typically from a referencing error in your storyboard. Did you ever change the name of a class or make a connection from a button of one view controller to another and then delete it? If you changed the name of a class you must make the sure the name in the code of the class matches that. If you deleted a button connection between view controllers, click on the controller itself and under the connections tab you must delete it.

My cells are duplicating themselves

I am new to swift and I am trying to make this note app. I have split view controller that goes in my first view controller and that view controller connects to a table view controller. Everything works perfectly is just that when I launch the app I have all the notes like I want but when I try to go back to my first view controller and come back to my table view controller, all the notes are duplicated every single time I do it. I tried everything I can try, is there anyone who can help me
my MasterViewController is
import UIKit
class MasterViewController: UITableViewController {
var detailViewController: DetailViewController? = nil
override func viewDidLoad()
{
super.viewDidLoad()
Note.loadNotes() // The problem is here, I think
noteTable = self.tableView
// Do any additional setup after loading the view, typically from a nib.
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(insertNewObject(_:)))
navigationItem.rightBarButtonItem = addButton
if let split = splitViewController
{
let controllers = split.viewControllers
detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
}
My loadNotes function is
class func loadNotes()
{
let defaults:UserDefaults = UserDefaults.standard
let saveData: [NSDictionary]? = defaults.object(forKey: kAllNotes) as? [NSDictionary]
if let data:[NSDictionary] = saveData
{
for i:Int in 0 ..< data.count
{
let n:Note = Note()
n.setValuesForKeys(data[i] as! [String : Any])
allNotes.append(n)
}
}
}
Your loadNotes method keeps appending. The first line of loadNotes should be:
allNotes = [Note]()
Then it starts with an empty array and fills it up.
And why is loadNotes a static method? That's a bad design. Make Notes a normal class and make loadNotes an instance method.
On an unrelated note (no pun intended), do not use UserDefaults to store app data. Only use it to store little bits of information.

error "secondViewController does not have a member named "mastername"

I am using a sample from IOS 8 App Development Essentials. I added a variable to my second controller but keep getting this error.
Second controller code:
Class SocondDetailController: UIViewController{
var mastername: String?
...
}
First controller code:
override func prepareForSegue(segue: UIStoryboardSegue,sender: AnyObject?)
{
if segue.identifier == "ShowDetails"
{        
let detailViewController = segue.destinationViewController as SocondDetailController
let myIndexPath = self.tableView.indexPathForSelectedRow()
let row = myIndexPath?.row
SocondDetailController.mastername = tableData[row!]
}
}
I am new to Swift and IOS development. Just starting at age 71.
I have been using VB.Net for a long time.
Please help.
Thanks.
This row:
SocondDetailController.mastername = tableData[row!]
should be:
detailViewController.mastername = tableData[row!]
mastername is an instance property, and as such you have to access to it through an instance of SocondDetailController, and not the SocondDetailController type itself.
Also, although probably not needed due to the logic in your view controller, I'd avoid using the forced unwrapping operator !, preferring a safer optional binding:
let row = myIndexPath?.row
if let row = row {
detailViewController.mastername = tableData[row]
}
or, more concisely:
if let row = myIndexPath?.row {
detailViewController.mastername = tableData[row]
}