0

I have two NSCombobox in same ViewController. One is for country and other for city. I have text files with country name which includes cities with respective latitude and longitude. For example: USA text file contains 17456 list of cities. I want to populate cities with respect to their country name. But combobox freezes while loading large number of cities. Especially, while searching cities in combobox application freezes due to large memory consumption. My text file looks like this:

214 North Temple Condominium,UT,Salt Lake,40N46'19,111W54'01,1,4265,L

A and B Trailer Court Number One,MT,Hill,48N33'09,109W40'50,1,,

A and B Trailer Court Number Two,MT,Hill,48N33'00,109W41'00,1,,

This is what i have tried.

let countryList = ["USA","Germany","Canada","Finland"]

var citiesList: [String] = []
var counter = 0
var countryOrCities = ""

@IBOutlet var country: NSComboBox!
@IBOutlet var city: NSComboBox!

override func viewDidLoad() {
        super.viewDidLoad()

        country.usesDataSource = true
        country.dataSource = self

        city.usesDataSource = true
        city.dataSource = self

        country.stringValue = "USA"
        citiesList = readCitiesFromCountry(country: "USA")
    }
func readCitiesFromCountry(country: String) -> [String] {
        var flag = true
        var returnedCitiesList: [String] = []

        if let path = Bundle.main.path(forResource: country, ofType: "txt") {
            guard let streamReader = StreamReader(path: path) else {fatalError()}
            defer {
                streamReader.close()
            }
            while flag {
                if let nextLine = streamReader.nextLine() {
                    returnedCitiesList.append(nextLine)
                } else {
                    flag = false
                }
            }
        } else {
            fatalError()
        }

        return returnedCitiesList
    }

func numberOfItems(in comboBox: NSComboBox) -> Int {
        switch comboBox {
        case country:
            counter = countryList.count
        case city:
            counter = citiesList.count
        default:
            break
        }
        return counter
    }

func comboBox(_ comboBox: NSComboBox, objectValueForItemAt index: Int) -> Any? {
        switch comboBox {
        case country:
            countryOrCities = countryList[index]
        case city:
            countryOrCities = citiesList[index]
        default:
            break
        }
        return countryOrCities
    }

func comboBoxSelectionDidChange(_ notification: Notification) {
        let comboBox = (notification.object as? NSComboBox)!
        if comboBox == country {
            citiesList = readCitiesFromCountry(country: country.stringValue)
            city.reloadData()
        } else {
            print("Value changed by other")
        }
    }

Instead of dropDownSize to be specific number, i want it to read all the number of cities so that searching cities for selected country is not restricted. StreamReader class is from Read a file/URL line-by-line in Swift

What i am trying to achieve is like this https://www.youtube.com/watch?v=QrdA-zbW4_o&feature=youtu.be>

John
  • 31
  • 5
  • txt is very unstructured data, i would recommend storing it as plist or have prepopulated database file. – Marek H Sep 22 '19 at 09:10
  • Don't call `readCountry` for every city, Instead call `readCountry` once when the country changes. – Willeke Sep 22 '19 at 09:10
  • @Willeke Would you please point out what you mean specifically in code? I am not getting exactly what you said. – John Sep 22 '19 at 09:17
  • And create an array property for the city list, that you clear and reload when a new country is selected. – Joakim Danielson Sep 22 '19 at 09:55
  • How many times is `readCountry` called when the city combo box list pops up? – Willeke Sep 22 '19 at 11:17
  • @Willeke Thanks for suggestion! Both comboBox are working fine but selectionDidChange method seems to be triggered before country.stringValue is set. Default country is USA, if i change it to UK cities are still of USA, if i change country to France then now UK's cities are populated. Every time it gets previous value of the country. How can i fix it? – John Sep 23 '19 at 18:04
  • 1
    `selectionDidChange` is called when the selection in the popup list changes (arrow keys). Use the action instead. – Willeke Sep 23 '19 at 20:50

0 Answers0