3

I am having country codes and country names in String Array. I just filtered country names and displaying in the filtered tableView. But, while displaying, I unable to fetch the respective country code from original tableview. Country code not getting filtered. Kindly help me. How to filter multiple fields in tableView cell.

My Code:

var countries = [String]()
for countryCodes : AnyObject in NSLocale.ISOCountryCodes() {
    let dictionary : NSDictionary = NSDictionary(object:countryCodes, forKey:NSLocaleCountryCode)
    let identifier : NSString? = NSLocale.localeIdentifierFromComponents(dictionary)
    if ((identifier) != nil) {
        let country : NSString = NSLocale.currentLocale().displayNameForKey(NSLocaleIdentifier, value: identifier!)!
        countries.append(country)
        println(countries)
    }
}
println(countries)
var country_codes = [String]()
country_codes =  NSLocale.ISOCountryCodes() as [String]
println(country_codes) //Working Successfully.

//SEARCH BAR WHILE TYPING TEXT
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {

        if(countElements(searchBar.text) >= 3)
        {
            searchActive = true

            filtered = countries.filter({ (text) -> Bool in
                let tmp: NSString = text
                let range = tmp.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
                return range.location != NSNotFound
            })
//I filtered only one fields. So, Filtered results are working fine, but, I am having one more fields in tableview cell. That is displaying different datas. I dont know how to filtered multiple fields.
            if(filtered.count == 0 || countElements(searchBar.text) == 0)
            {
                searchActive = false
                self.countryTableView.reloadData()
            }
            else
            {
                searchActive = true
                self.countryTableView.reloadData()
            }

        }
        else
        {

            searchActive = false
            self.countryTableView.reloadData()
        }

    }

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = countryTableView.dequeueReusableCellWithIdentifier("country", forIndexPath: indexPath) as country_tblCell

        //println("Cell for ROws \(searchActive)")
        if(searchActive)
        {
            if(filtered.count == 0 || countElements(searchBar.text) == 0)
            {
                searchActive = false
                self.countryTableView.reloadData()
            }

            else
            {
                println("First Index \(indexPath.row)")
                cell.country_Label.text = filtered[indexPath.row]
                cell.countryCodeLabel.text = countryCodes[indexPath.row] //Here need to display filtered datas for Country code.
                println("Second Index \(indexPath.row)")
            }
        }
        else
        {
            println("Normal First Index \(indexPath.row)")
            cell.selectionStyle = .None
            cell.country_Label.text = countries[indexPath.row]
            cell.countryCodeLabel.text = countryCodes[indexPath.row]
            cell.layer.borderColor = validateBorderColor.CGColor
            cell.layer.borderWidth = 1
            println("Normal Second Index \(indexPath.row)")
        }

        return cell
    }

My Output

enter image description here

3 Answers 3

3

Try using tuples.

This is a great feature in swift.

After getting countries and country_codes

Add them to this tuple

var countryAndCode: [(country:String , code: String)] = []
for i in 0...coutries.count {
  countryAndCode.append(country:countries[i] , code:country_codes[i])//this shows error in XCode some times
    //if the above code doesn't compile then use the below code
  countryAndCode += [(country:countries[i] , code:country_codes[i])]
}

Then perform the filtering on this tuple:

filtered = countryAndCode.filter({ (data) -> Bool in
        let tmp: NSString = data.country // the name from the variable decleration
            let range = tmp.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
            return range.location != NSNotFound
        })

Finally in the cellForRowAtIndexPath method use this tuple

cell.country_Label.text = filtered[indexPath.row].country
cell.countryCodeLabel.text = filtered[indexPath.row].code

For more information on tuples you can visit http://www.raywenderlich.com/75289/swift-tutorial-part-3-tuples-protocols-delegates-table-views

Sign up to request clarification or add additional context in comments.

12 Comments

Thanks @Raja . let tmp: NSString = data.country . I couldn understand this line?
I am asking about "data.country"
"filtered = countryAndCode.filter",, in this line I got an error. (country:String , code: String) not identical to String
@McDonal_11 object the name country. So in future to refer the country part of the tuple we call it using this name : countryAndCode[1].country . Here while filtering using .filter method we take each object of the array which is a tuple and assign it to data . SO to access the country part of the tuple we use data.country
yes @Raja !! I understood. "filtered = countryAndCode.filter",, in this line I got an error. (country:String , code: String) not identical to String. I dont know y I got this error?
|
0

I had a similar problem earlier. First step is the same I guess. create a tuple where the country and code are in one object together.

var countryAndCode: [(country:String , code: String)] = []

Then I basically used an OR operator for the fields. Your code:

        filtered = countries.filter({ (text) -> Bool in
            let tmp: NSString = text.attribute
            let range = tmp.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
            return range.location != NSNotFound
        })

Into something like this:

        filtered = countries.filter({ (text) -> Bool in
            let tmp: NSString = text.attribute
            let range = tmp.country.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch) || tmp.code.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
            return range.location != NSNotFound
        })

And in your case you could do && if you want to filter on both fields.

4 Comments

how can u use let tmp: NSString = text without specifying the attribute? i get an error if i don't use text.attributeName
I am hitting cannot convert value of type '(process:String, requestor:String, creation:String, status:String)' to specified type 'NSString'
So your object in the countries array is a string, but the clojure expects NSString and appearently cannot convert. It's been a while though.
Look at this question + answers: stackoverflow.com/questions/29448152/…
0

Above answer in Swift 3.0

var countryAndCode: [(country:String , code: String)] = []
for i in 0...coutries.count-1 {
  countryAndCode += [(country:countries[i] , code:country_codes[i])]
}

Then perform the filtering on this tuple:

filtered = countryAndCode.filter({ (data) -> Bool in
     let tmp: NSString = data.country // the name from the variable decleration
     let range = tmp.range(of: searchText, options: .caseInsensitive)
     return range.location != NSNotFound
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.