I am trying to compare the strings from searchbar textfield with array of strings. My array is in English strings. I am having localize strings(Burmsese string in localisation file) for the items in the array. I have tried the string method given by apple to compare. Could anyone resolve my problem or this is still mystery and I am wasting my time. I am posting one of the method I have tried, where localized is the custom extension of string for localisation string
searchResultList = keyArray.filter {
return $0.localized.lowercased().contains(ketText.lowercased())
}
I resolved it. If we are using normal contains methods it returns false. But if we are using range, its working perfect for this issue. I have used the following,
searchResultList = keyArray.filter {
guard let _ = $0.keyString.localized.localizedStandardRange(of: ketText) else { return false }
return true
}
Related
return value == String(value.reversed())
This is what I tried. It works well but takes a little bit longer. Does anyone know a better way?
There is nothing available in the standard library for String, or for anything else, so a solution for only String probably isn't the best option.
You don't need to make a new instance of anything based on reversed; elementsEqual does the job.
public extension Sequence where Element: Equatable {
var isSymmetric: Bool { elementsEqual(reversed()) }
}
"🐈🐆🐅🐆🐈".isSymmetric // true
"🐈🐆🐅".isSymmetric // false
You could in c test each character one at a time from beginning and end until your two indices meet in the middle. But for Swift you don't have a guarantee that characters are the same length in a Swift String, they have to store strings that are made of unicode characters which can have one of 100,000's of characters at the moment, I think they currently do this by storying the String using UTF16. So you can not just use offset logic to quickly calculate the index for a character, you have to enumerate through each character, checking the length of each character to get to the next. Objective-C made this even more complicated with the potential of private subclasses of NSString, each could have different encoding methods.
A less expensive way than reversing the array is to walk simultaneously from the beginning and the end to the middle and compare each character - or whatever the Element of the type conforming to BidirectionalCollection is.
public extension BidirectionalCollection where Element: Equatable {
var isPalindrome: Bool {
if isEmpty { return true }
var 👉 = startIndex
var 👈 = index(before: endIndex)
while 👉 < 👈 {
if self[👉] != self[👈] { return false }
formIndex(after: &👉)
formIndex(before: &👈)
}
return true
}
}
I have a field called keywords on Core Data that stores keywords separated by spaces, like:
car nascar race daytona crash
I have a list populated by core data. Every element on that list has keywords.
I have a search field on that view.
I want that list to be filtered as the user types.
If the user types c the app will check elements that have keywords beginning with c. In that case, the element mentioned above will be shown because it has car and crash, both beginning with c.
In order to check that, I created this extension
extension String {
func containsWordStartingWith(insensitive searchWord: String) -> Bool {
let lowercaseSelf = self.lowercased().trimmingCharacters(in: .whitespaces)
let lowercaseSearch = searchWord.lowercased().trimmingCharacters(in: .whitespaces)
let array = lowercaseSelf.components(separatedBy: " ")
return array.contains(where: {$0.hasPrefix(lowercaseSearch)})
}
}
This works but is slow as hell and typing characters on the search bar makes the app stall.
How can I improve that with something faster?
First thing I would do is split the single keywords string into a Set of actual keywords. If possible you should even store it in Core Data that way, so there's no need for a split step.
let keywords = "car nascar race daytona crash"
let keywordSet = Set(keywords.split(separator: " "))
Now the utility method you want is trivial and fast:
func keywordSet(_ set : Set<Substring>, containsWordStartingWith s: Substring) -> Bool {
for keyword in set {
if keyword.hasPrefix(s) { return true }
}
return false
}
Testing:
keywordSet(keywordSet, containsWordStartingWith:"c")
I'm new to iOS development and wondering if I could pass a string variable inside if statement? Here's my pseudo code:
x = 1
func myFunc() -> String {
myString = "x == 1"
return myString
}
if(myfunc()) {
code i want to execute
}
I am currently getting the following error: "'String' is not convertible to 'Bool'"
Is there a way I can do this?
You should use a comparison operator for this.
if myString == myFunc() {
// your code
}
If statement always wants a condition that can return a bool value. i.e. true and false.
In your above code, you are not providing sufficient data to if statement so that it can calculate whether the result iss true or false.
When you compare it like if myString == myFunc() , if statement will compare the string and return true if string matches else false.
if the string matches, it will execute the code that is within if conditions scope. Otherwise it will calculate the else condition.
UPDATE1:
I see you have updated the question, so you want to check if myFunc() is empty or not?
For that you can compare it with empty string.
if myFunc() == "" {
// your code
}
UPDATE2:
Question: (asked in comment) instead of writing "if(x == 1)" i am trying to use a variable so my if statement is "if(stringVaraible)" where stringVariable = "x ==1". Basically I am asking if it is possible to turn a string into normal code
Answer: No, you can't do that. Swift is a compiled language, not interpreted like Ajax. Read more here: https://stackoverflow.com/a/30058875/8374890
It's very specific and clear that you can't use String as boolean. The approach you can take is well known like..
if(myString == "x == 1") {
code i want to execute
}
or
if(desiredString == myFunc()) {
code i want to execute
}
I'm parsing the first two characters on a line of text and doing lots of comparisons against possible patterns:
In my Card class:
static let ourTypes = ["PL", "SY", "XT"]
In lots of other places:
if Card.ourTypes.contains(line[0..<2]) { continue }
Swift4 (3?) changed the []'s to return a Substring. I know I can cast it back with String(line[0..<2]), but I suspect that's the wrong solution... is there a better way?
One way would be to make your ourTypes array to be [Substring], then you wouldn't have to convert your Substring to make contains work:
static let ourTypes: [Substring] = ["PL", "SY", "XT"]
if Card.ourTypes.contains(line.prefix(2)) { continue }
#matt's observation that searching with contains is better with a Set (because it's more efficient) can be accomplished with:
static let ourTypes: Set<Substring> = ["PL", "SY", "XT"]
The String cast, while a bit jarring, is not expensive. Deriving a true independent substring from a string simply is a two-step process: access the slice, then unlink the indices and storage from the original. That is all that String() means here. So I think your original approach is actually correct and nonproblematic.
If you really want to stay in the String world, though, you can, by calling removeSubrange instead of taking a slice. You give up the convenience of slice notation and slice-related methods, but everything depends on your priorities. And by the way, if contains is your main test here, use a Set, not an Array:
let ourTypes = Set(["PL", "SY", "XT"])
var line = "PLARF"
line.removeSubrange(line.index(line.startIndex, offsetBy: 2)...)
ourTypes.contains(line) // true
I just joined a project that has a lot of existing code. The previous programmer was perhaps unfamiliar with Swift or began development in the early stages of the Swift language. They seemed to be using the if let statement in an odd way. They seemed to want to use the statement as a if is let. Before I edit the code I would like to know if there is any valid use for this:
// In JSON parser
if value is String, let string = value as? String {
document.createdBy = string
}
First checking if value is of type String seems redundant to me. Doesn't Swift check for this in the let string = value as? String portion of the statement?
QUESTION
Why would this need to be checked twice? Or would there be a reason for this?
You're correct, this is redundant. If value is not a string, then value as? String would return nil, and the conditional binding would fail.
To check the type, and not use the casted result:
if value is String {
// Do something that doesn't require `value` as a string
}
To check the type and use the result:
if let value = value as? String { // The new name can shadow the old name
document.createdBy = value
}
Doing both makes no sense.