Swift XCUI string assertion failing - ios

I am using xcode 8.3.3 and writing a XCUI test.
I have the following:
let address = XCUIApplication().buttons["URL"].value as! String
Looking in the debugger, I can see the value is:
If I set
expectedURL = "\u{e2}auth.int....net" then it returns:
If I set
expectedURL = "auth.int....net" then it returns:
How can I make the test assertion find the two strings to be equal?
Tried the following, but it doesn't replace the "\u{e2}":
let address = value.components(separatedBy: ",").first!.replacingOccurrences(of: "\u{e2}", with: "")
And also (but it doesn't replace the "\u{e2}"):
let range = Range<String.Index>(uncheckedBounds: (lower: address.startIndex, upper: address.endIndex))
let strippedAddress = address.replacingOccurrences(of:"\\u{e2}", with: "", options: .literal, range: range)
For the assertion, I am using XCTAssertEqual(address, expectedURL)

You can fix it by separating by alphanumeric characters and then joining by an empty string, as shown below.
let myString = address.components(separatedBy: CharacterSet.alphanumerics.inverted).joined(separator: "")
myStringis then equal to authintxxxxxxxxxnet (no "." characters), so you should just be able to change your expected URL to match.
Hope that helps!

Related

Swift regex format to remove string contains brackets in iOS

Need to remove part of the string based on brackets.
For ex:
let str = "My Account (_1234)"
I wanted to remove inside brackets (_1234) and the result should be string My Account
Expected Output:
My Account
How can we achieve this with regex format or else using swift default class,need support on this.
Tried with separatedBy but it splits string into array but that is not the expected output.
str.components(separatedBy: "(")
Use replacingOccurrences(…)
let result = str.replacingOccurrences(of: #"\(.*\)"#,
with: "",
options: .regularExpression)
.trimmingCharacters(in: .whitespaces))
Regex ist not necessary. Just get the range of ( and extract the substring up to the lower bound of the range
let str = "My Account (_1234)"
if let range = str.range(of: " (") {
let account = String(str[..<range.lowerBound])
print(account)
}

Convert placeholders such as %1$s to {x} in Swift

I'm parsing an XML doc (using XMLParser) and some of the values have php-like placeholders, e.g. %1$s, and I would like to convert those to {x-1}.
Examples:
%1$s ---> {0}
%2$s ---> {1}
I'm doing this in a seemingly hacky way, using regex:
But there must be a better implementation of this regex.
Consider a string:
let str = "lala fawesfgeksgjesk 3rf3f %1$s rk32mrk3mfa %2$s fafafczcxz %3$s czcz $#$##%## %4$s qqq %5$s"
Now we're going to extract the integer strings between strings % and $s:
let regex = try! NSRegularExpression(pattern: "(?<=%)[^$s]+")
let range = NSRange(location: 0, length: str.utf16.count)
let matches = regex.matches(in: str, options: [], range: range)
matches.map {
print(String(str[Range($0.range, in: str)!]))
}
Works quite fine. The issue is that the "4" value got mixed up because of the preceding random strings before the %4$s.
Prints:
1
2
3
## %4
5
Is there any better way to do this?
This might not be a very efficient (or swifty :)) way but it gets the job done. What it does is that it searches for a given reg ex and uses the matched substring to extract the numeric value and decrease it and then perform a simple replace between the substring and a newly constructed placeholder value. This is executed in a loop until no more matches are found.
let pattern = #"%(\d*)\$s"#
while let range = str.range(of: pattern, options: .regularExpression) {
let placeholder = str[range]
let number = placeholder.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789.").inverted)
if let value = Int(number) {
str = str.replacingOccurrences(of: placeholder, with: "{\(value - 1)}")
}
}

How to remove '\u{ef}' character from String Swift

let's say I have a string
var a = "#bb #cccc #ddddd\u{ef}"
and i am setting it to textview like this
let text = a.trimmingCharacters(in: .whitespacesAndNewlines)
let textRemoved = text?.replacingOccurrences(of: "\u{ef}", with: "", options: NSString.CompareOptions.literal, range:nil)
textView.text = textRemove
I am trying to remove the \u{ef} character here. But in textRemoved it is not happening. Please help me how to do it.
I am using Xcode 10. Looks like below Xcode version than 10 is working
fine. is it a bug of Xcode 10?
This is a late answer but I struggled to replace "\u{ef}" in string as well. During debugging when hovered over string it showed presence of \u{ef} but when print in description it only showed space.
let str = "\u{ef} Some Title"
print(str) //" Some Title"
I tried replacingOccurrences(of: "\u{ef}", with: "", options: NSString.CompareOptions.literal, range: nil).trimmingCharacters(in: .whitespaces) but it failed as well.
So I used below snippet and it worked like wonder.
let modifiedStr = str.replacingOccurrences(of: "\u{fffc}", with: "", options: NSString.CompareOptions.literal, range: nil).trimmingCharacters(in: .whitespaces)
print(modifiedStr) //"Some Title"
Hope this helps someone!!
i also faced same issue for "\u{e2}". i have searched a lot but unable to find any answer. then i have tried below code , which works for me.
var newString = ""
for char in strMainString.unicodeScalars{
if char.isASCII{
newString += String(char)
}
}
Hope that will also work for you too.
In Xcode 10 Playground, string replaces for \u{00EF} is working.
var a = "#bb #cccc #ddddd\u{ef}"
a = a.replacingOccurrences(of: "\u{00EF}", with: "")
I hope that will work for you.
I tried the following and it worked like a charm:
replacingOccurrences(of: "�", with: " ", options: NSString.CompareOptions.literal, range: nil)
e.g. 1
let text = "\u{ef}\u{ef}\u{ef}\u{ef}😇哦哦哦"
let text1 = text.replacingOccurrences(of: "\u{fffc}", with: "", options: String.CompareOptions.literal, range: nil)
let text2 = text.replacingOccurrences(of: "\u{ef}", with: "", options: String.CompareOptions.literal, range: nil).trimmingCharacters(in: .whitespaces)
runnable
<img src="https://i.stack.imgur.com/styVo.png"/>
e.g. 2
let strBefore = textDocumentProxy.documentContextBeforeInput
let strAfter = textDocumentProxy.documentContextAfterInput
var textInput = strBefore + strAfter
let textInput2 = textInput.replacingOccurrences(of: "\u{ef}", with: "", options: String.CompareOptions.literal, range: nil)
let textInput1 = textInput.replacingOccurrences(of: "\u{fffc}", with: "", options: String.CompareOptions.literal, range: nil).trimmingCharacters(in: .whitespaces)
runnable
<img src="https://i.stack.imgur.com/xGHtW.png"/>
Similar to question but with \u{e2} symbol (fix is the same):
\u{e2} is not a character rather subset of UTF8 plane which starts with 0xE2 byte.
So look here, E2 are general punctuation symbols.
There many symbols actually which started with \u{e2} but not limited to it and full char can be represented f.e. with e2 80 a8 bytes (line separator).
That explains why shown in Xcode \u{e2} can't be replaced with replacingOccurrences... function. In order to filter out correct symbol you have to know what exact symbol it is, f.e. by using the snippet below:
"\u{2028}&😲".forEach { (char) in
print(Data(char.utf8).map { String(format: "%02x", $0) }.joined(separator: " "))
}
it prints to console:
e2 80 a8
26
f0 9f 98 b2
which are byte representation for each symbol.
Next step is to filter your string, go here and search in 3d column your bytes and unicode code point value is what you need (first column) and write it in swift code like "\u{2028}\u{206A}..." (depending on your sorting).
The final function may look like:
func removingE2Symbols() -> String {
let specialChars = "\u{202A}\u{202C}"
return filter { !specialChars.contains($0) }
}
Try this
extension String {
var asciiString: String {
return String(self.unicodeScalars.filter{ $0.isASCII })
}
}
It,s working Please check again:
let a = "#bb #cccc #ddddd\u{ef}"
let text = a.trimmingCharacters(in: .whitespacesAndNewlines)
let textRemoved = text.replacingOccurrences(of: "\u{ef}", with: "", options: NSString.CompareOptions.literal, range:nil)
print(textRemoved)

Remove U\0000fffc unicode scalar from string

I receive an NSAttributedString that contains a NSTextAttachment. I want to remove that attachment, and it looks like it is represented as "\u{ef}" in the string. Printing the unicode scalars of such string, it also seems that unicode scalar for the "\u{ef}" is U\0000fffc.
I tried to do this:
noAttachmentsText = text.replacingOccurrences(of: "\u{ef}", with: "")
with no success, so I'm trying by comparing unicode scalars:
var scalars = Array(text.unicodeScalars)
for scalar in scalars {
// compare `scalar` to `U\0000fffc`
}
but I'm not able either to succeed in the comparison.
How could I do this?
But this code works for me from How do I remove "\U0000fffc" from a string in Swift?
let original = "First part \u{ef} Last part"
let originalRange = Range<String.Index>(start: original.startIndex, end: original.endIndex)
let target = original.stringByReplacingOccurrencesOfString("\u{ef}", withString: "", options: NSStringCompareOptions.LiteralSearch, range: originalRange)
print(target)
Output :
"First part ï Last part"
to
First part Last part
U can use similar code for swift 3 just replace unicode using replacingOccurrences option for exapmle :
func stringTocleanup(str: String) -> String {
var result = str
result = result.replacingOccurrences(of: "\"", with: "\"")
.replacingOccurrences(of: "\u{10}", with: "")
return result
}

Find index of Nth instance of substring in string in Swift

My Swift app involves searching through text in a UITextView. The user can search for a certain substring within that text view, then jump to any instance of that string in the text view (say, the third instance). I need to find out the integer value of which character they are on.
For example:
Example 1: The user searches for "hello" and the text view reads "hey hi hello, hey hi hello", then the user presses down arrow to view second instance. I need to know the integer value of the first h in the second hello (i.e. which # character that h in hello is within the text view). The integer value should be 22.
Example 2: The user searches for "abc" while the text view reads "abcd" and they are looking for the first instance of abc, so the integer value should be 1 (which is the integer value of that a since it's the first character of the instance they're searching for).
How can I get the index of the character the user is searching for?
Xcode 11 • Swift 5 or later
let sentence = "hey hi hello, hey hi hello"
let query = "hello"
var searchRange = sentence.startIndex..<sentence.endIndex
var indices: [String.Index] = []
while let range = sentence.range(of: query, options: .caseInsensitive, range: searchRange) {
searchRange = range.upperBound..<searchRange.upperBound
indices.append(range.lowerBound)
}
print(indices) // "[7, 21]\n"
Another approach is NSRegularExpression which is designed to easily iterate through matches in an string. And if you use the .ignoreMetacharacters option, it will not apply any sophisticated wildcard/regex logic, but will just look for the string in question. So consider:
let string = "hey hi hello, hey hi hello" // string to search within
let searchString = "hello" // string to search for
let matchToFind = 2 // grab the second occurrence
let regex = try! NSRegularExpression(pattern: searchString, options: [.caseInsensitive, .ignoreMetacharacters])
You could use enumerateMatches:
var count = 0
let range = NSRange(string.startIndex ..< string.endIndex, in: string)
regex.enumerateMatches(in: string, range: range) { result, _, stop in
count += 1
if count == matchToFind {
print(result!.range.location)
stop.pointee = true
}
}
Or you can just find all of them with matches(in:range:) and then grab the n'th one:
let matches = regex.matches(in: string, range: range)
if matches.count >= matchToFind {
print(matches[matchToFind - 1].range.location)
}
Obviously, if you were so inclined, you could omit the .ignoreMetacharacters option and allow the user to perform regex searches, too (e.g. wildcards, whole word searches, start of word, etc.).
For Swift 2, see previous revision of this answer.

Resources