24

I’m using CharacterSet.urlQueryAllowed to add percent-encoding to a String.

Some characters are not encoded the way I expected (i.e. & and ? are not changed). That being said, I had the idea to build a custom CharacterSet, ideally based on an existing one.

What’s the best approach to do so?

ixany
  • 5,433
  • 9
  • 41
  • 65
  • 1
    Look at `NSMutableCharacterSet` that should give you possibility to play with existing `NSCharacterSet`. – Larme Sep 11 '15 at 16:09

2 Answers2

48

The most typical way to create a new character set is using CharacterSet(charactersIn:), giving a String with all the characters of the set.

Adding some characters to an existing set can be achieved using:

let characterSet = NSMutableCharacterSet() //create an empty mutable set
characterSet.formUnionWithCharacterSet(NSCharacterSet.URLQueryAllowedCharacterSet())
characterSet.addCharactersInString("?&")

or in Swift 3+ simply:

var characterSet = CharacterSet.urlQueryAllowed
characterSet.insert(charactersIn: "?&")

For URL encoding, also note Objective-C and Swift URL encoding

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Works perfectly fine, thank you! But when I try to add "ÄÖÜäöü" it hasn't any effect? – ixany Sep 11 '15 at 17:41
  • @mrtn.lxo You will have to add more context to your comment. How are you adding them? What are you doing later with the character set? – Sulthan Sep 11 '15 at 20:03
  • I simply used myCaracterSet.addCharactersInString("Ä") – ixany Sep 11 '15 at 20:24
7

You can try my method:

let password = "?+=!@#$%^&*()-_abcdABCD1234`~"

// Swift 2.3
extension NSCharacterSet {
    static var rfc3986Unreserved: NSCharacterSet {
        let mutable = NSMutableCharacterSet()
        mutable.formUnionWithCharacterSet(.alphanumericCharacterSet())
        mutable.addCharactersInString("-_.~")
        return mutable
    }
}

let encoding = password.stringByAddingPercentEncodingWithAllowedCharacters(.rfc3986Unreserved)

// Swift 3
extension CharacterSet {
    static var rfc3986Unreserved: CharacterSet {
        return CharacterSet(charactersIn: "-_.~").union(.alphanumerics)
    }
}

let encoding = password.addingPercentEncoding(withAllowedCharacters: .rfc3986Unreserved)

Print:
original -> ?+=!@#$%^&*()-_abcdABCD1234`~
encoding -> %3F%2B%3D%21%40%23%24%25%5E%26%2A%28%29-_abcdABCD1234%60~

rfc3986: https://www.rfc-editor.org/rfc/rfc3986 reference

Community
  • 1
  • 1
Arco
  • 614
  • 5
  • 13