I have a search bar that filters through an xml array of recipe titles. The problem is that I have to search the entire title, otherwise I don't see suggested results. For example, if I have "Whole Grain Waffles" and "Whole Wheat Bread" typing "Whole" returns nothing. Typing "Whole Grain Waffles" returns successfully. This is the searchBar function
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text == nil || searchBar.text == "" {
isSearching = false
view.endEditing(true)
myTableView.reloadData()
} else {
isSearching = true
filteredData = tableViewDataSource.filter({$0.title == searchBar.text})
myTableView.reloadData()
}
}
I'm pretty sure the solution has to do with case sensitivity, and returning certain characters when setting the filteredData. Thanks for help in advance
You could use contains to filter any item in array that contains the text or you can also use hasPrefix, if you want to search for the strings that start with the search text.
Something like this,
filteredData = tableViewDataSource.filter { $0.title.contains(searchBar.text) ?? "" }
Or,
filteredData = tableViewDataSource.filter { $0.title.hasPrefix(searchBar.text) ?? "" }
Using range worked in my situation
filteredData = tableViewDataSource.filter({$0.title.range(of: searchBar.text!) != nil})
Related
i am working on a searchbar.
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = patientArray.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
searching = true
tableView.reloadData()
}
In this above 2 images, If i am writting the exact same string, then i am getting the result . But if i am searching for any numbers like "20". then the result is empty.
How to fix the issue that if i search for any containing text(it may be numbers or text), i will get the result.
You are searching from the beginning of the string (prefix). If you want to search if a string contains a substring you have to use contains.
But there is a more efficient API, range(of:options:) which also avoids the repetitively calling of lowercased()
filteredData = patientArray.filter{$0.range(of: searchText, options: .caseInsensitive) != nil}
I am wondering if there is a way to add characters automatically to a searchBar textField while the user is typing. For example, if the user typed 533 then I want to automatically add " X " to it. I tried to do the following:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty == false {
if searchText.count > 2 {
searchText.insert(" X ", at: 3)
}
}
However, Xcode is displaying an error message next to searchText.insert(" X ", at: 3) stating:
Cannot use mutating member on immutable value: 'searchText' is a let constant
You can't modify the value of searchText. Method parameters are constants. Create a local variable with the new value. Then update the search bar's text.
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.count > 2 {
var newText = searchText
newText.insert(" X ", at: 3)
searchBar.text = newText
}
}
But this still has issues that you need to work out. This doesn't account for the user moving the caret or the fact that you will add an X far too many times as the user enters more text into the search field.
#objc func searchButtonTap() {
searchBar.becomeFirstResponder()
var remove = searchBar.text
remove = String(remove!.dropLast())
searchBar.text = remove
}
Also tried two backspaces
#objc func searchButtonTap() {
let name: String = searchBar.text!
let endIndex = name.index(name.endIndex, offsetBy: -2)
let truncated = String(name[..<endIndex])
searchBar.text = truncated
}
Assuming that you want to remove the last character of the search bar text when the user taps on back(search?) button.
So,
#objc func searchButtonTap() {
guard !(searchBar.text?.isEmpty ?? true) else { return } //Making sure that you don't hit the "Fatal error: Can't remove more items from a collection than it contains"
searchBar.text?.removeLast(1)
}
I have a very large array of data that I use a searchbar to filter. However I would like to filter only exactly that which the user enters in the searchbar. I.e. if you type "b" you only get items starting with b. The list is more than 200,000 items so now even with many letters entered the results showing are often irrelevant. I have tried searching a lot but every guide I have found is a variation of what I have :
extension MapTableController : UISearchResultsUpdating {
func filterContentForSearchText(_ searchText: String) {
if(searchText == "") {
matchingItems = []
}
else {
matchingItems = arrayOfFixes.filter { fix in
return fix.lowercased().contains(searchText.lowercased())
}
tableView.reloadData()
}
}
func updateSearchResults(for searchController: UISearchController) {
let searchText = searchController.searchBar.text
filterContentForSearchText(searchText!)
self.tableView.reloadData()
}
}
I understand that using "contains" will have the above mentioned effect. But I can't figure out how to filter it in the desired way. For example I would like it so that if I enter "Ben" it will show results like "Bendi", "Benhu", "Benji" etc. Not so that it shows results like "Juben", "Ibeno" etc, you get the picture.
Thanks for any help!
You can use 'hasPrefix' instead of 'contains' for your filter:
return fix.lowercased().hasPrefix(searchText.lowercased())
(Swift)
So the problem is:
My app (which is a kind of calculator) is crashing when the user puts in the textfield things that can't be calculated.
For example, if he types " -4-.", the app won't be able to do the math.
So, a pattern must be followed.
The following characters are allowed: 1234567890.-
The minus sign can only be typed when it is the first character in the textfield and cannot be typed again.
The point can only be typed after a number, and cannot be typed again.
Well you would have to determine:
When the user clicks on a number/digit/character, you would have to do a:
//Goes at top of one of your classes
var decimalCount:Int = 0
//At location of tap for character
if(decimalCount < 1) {
textField.text += "."
decimalCount += 1
}
This ideology could be applied to "-" as well.
Some how i have understood your question. According to my assumption our task is to validate the input for proper math function.Ok here we go.
First of all declare a bool variable at top of your class
var isNonNumericCharactersAllowes = true
At first we need to make our textfield to respond according to user input.So add delegate to text field and add the following delegate method.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//1. To make sure that this is applicable to only particular textfield add tag.
if textField.tag == 1 {
let char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\\b")
//Helps to react only while typing and not while clearing text
if (isBackSpace != -92) {
let numbersOnly = NSCharacterSet(charactersInString: "1234567890")
let characterSetFromTextField = NSCharacterSet(charactersInString: string)
let Validate:Bool = numbersOnly .isSupersetOfSet(characterSetFromTextField)
if !Validate {
if isNonNumericCharactersAllowes {
isNonNumericCharactersAllowes = false
return true
}
return false
}
isNonNumericCharactersAllowes = true
}
}
return true
}
The above method stops unusual text entry's such as 0..012,--4,4++ etc..
Now while hitting calculate button we need to some validation.Add the following code in IBAction.
#IBAction func calculate(sender: AnyObject) {
let textContent:String!
textContent = textFieldTwo.text
var characterContainer = textContent.characters.map { String($0) }
let numbersOnly = NSCharacterSet(charactersInString: "1234567890")
let lastObjectOfString = NSCharacterSet(charactersInString: characterContainer.last!)
let Validate:Bool = numbersOnly .isSupersetOfSet(lastObjectOfString)
if !Validate {
characterContainer .removeLast()
textFieldTwo.text = characterContainer .joinWithSeparator("")
}
}
This above validation helps in removing things like 30+20+,4+4+, etc.. i.e removes unused operators at the end.