5

I'm just wondering how the (inverted) CharacterSet in Swift works.

Let's assume that I have the following two character sets:

let invertedNumbers = CharacterSet(charactersIn: "0123456789").inverted
let numbers = CharacterSet(charactersIn: "0123456789")

When I log both character sets with the print function like

print(numbers) 

it shows the same in the console as with

print(invertedNumbers)

And that is

<CFCharacterSet Items(U+0030 U+0031 U+0032 U+0033 U+0034 U+0035 U+0036 U+0037 U+0038 U+0039)>

But how can they be the same at all? I'm very confused as they aren't really. When I ask the inverted one if it contains an "a", it says true. On the other hand the not inverted one says false. And I like the way it works, but is the logging of the inverted one not buggy then?

Andreas Utzinger
  • 392
  • 2
  • 12
  • 4
    It might be that they do have the same characters but `invertedNumbers` also has some internal flag indicating it is inverted but this flag isn't shown in the debug output. – rmaddy Apr 07 '19 at 18:19
  • 3
    @rmaddy: Indeed, [CFCharacterset](https://opensource.apple.com/source/CF/CF-635/CFCharacterSet.c.auto.html) has an internal __kCFCharSetIsInverted flag. – Martin R Apr 07 '19 at 18:38
  • And from the documentation *Using the inverse of an immutable character set is much more efficient than inverting a mutable character set.* Which hints that it's not really inverting the characters. – Sulthan Apr 07 '19 at 18:39
  • Use [this](https://stackoverflow.com/a/15742659/7250862) to print it . Don't print inverted characters. Xcode isnt responding :) – RajeshKumar R Apr 07 '19 at 18:46
  • Hmm, interesting... inverted() method for CharacterSet seems useless, but maybe it's good for something but I don't recognize it yet. You can just reverse the String and convert it to an array... Array(String("0123456789").reversed()) right? – Kinga l Apr 07 '19 at 19:20
  • @Kingal An inverted character set is completely different from reversing a string. In the question, `numbers` has just the digits 0 - 9 while `invertedNumbers` has every single Unicode character there is *except* the digits 0 - 9. – rmaddy Apr 07 '19 at 19:33
  • Ok, I understand. If I need the unicode characters, then I would choose to handle the job with byte arrays. No offence, I'm just thinking when I would use this method. – Kinga l Apr 08 '19 at 08:14

2 Answers2

0

Inverted character set does work in Swift, although you can't really print it.

For example, if I wanted to percent-encode a group of characters, so I can send it in a POST:

let myPassword = "Hi+You?"
var charset1 = CharacterSet(charactersIn: "#%;<>?[\\]^'\"{|}&+")
let urlwithPercentEscapes = myPassword.addingPercentEncoding( withAllowedCharacters: charset1.inverted)
print(urlwithPercentEscapes)

when I print urlwithPercentEscapes, I will be percent-encoding any character in that character group since I'm showing " withAllowedCharacters: charset1.inverted". If I use " withAllowedCharacters: charset1", it will percent encode every character NOT in that list.

Vette
  • 511
  • 5
  • 10
0

CharacterSet has a list of decimal digits, letters, capitalized letters, symbols, etc. There are alphabet characters that maybe you understand but others not, because CharacterSet considers other alphabet character non-English language (UTF8, UTF16, UTF32).

You have two possible result of this:

1 let allowed_characters = CharacterSet.alphanumerics
2 let disallowed_characters = CharacterSet.alphanumerics.inverted

1 Has a list with all allowed alphanumeric characters.

2 Has a list with all outside characters from you set allowed characters.

In other words, you could have...

extension String {
    var isAlphanumeric: Bool {
      let allowed_characters = CharacterSet.alphanumerics
      let disallowed_characters = allowed_characters.inverted
    
      let range = rangeOfCharacter(from: disallowed_characters, options: .literal, range: nil)
      // allowed validation should be range: != nil
      // disallowed should be: range == nil
      return range == nil
   }}

"*".isAlphanumeric // prints false
"hello123".isAlphanumeric // true
"Olá".isAlphanumeric // true

I hope I have helped you ✌️

Gabs
  • 422
  • 2
  • 4