You should be able to use an NSRegularExpression and a method like
replaceMatchesInString:options:range:withTemplate:.
I am no expert on regular expressions. I believe that you can make your regular expression have 2 "capture groups" where the first capture group is a list of possible punctuation characters, and the second is a variable amount of whitespace. Your template would tell the `replaceMatchesInString:options:range:withTemplate: function to replace each matched expression with the just the contents of the first capture group (the matched punctuation symbol.)
You will need to list all the punctuation symbols that you want to handle (e.g. ".,:?!;")
Edit:
I decided to use this as a learning experience to learn more about regular expressions.
I found this page that is a decent introduction to regular expressions.
Then I read the docs on NSRegularExpression, and in particular, the stringByReplacingMatchesInString function. That says that the string is replaced based on a "template".
It seems that the parts of a regular expression can be divided into "capture groups", or sections that get matched separately. You can then use those capture groups to use parts of the matched string to the output of stringByReplacingMatchesInString.
Here is some playground code I wrote that searches for the punctuation characters ",.:;?!" followed by one or more whitespace characters and replaces them with just the punctuation, stripping away the whitespace:
var error: NSError?
let myRegEx = NSRegularExpression(pattern: "([,.:;?!])(\\s*)",
options: NSRegularExpressionOptions(0),
error: &error)
let testString = "This is a string, with some text. It has punctuation; can we replace that punctuation? I need to know what happens! "
let range = NSRange(location: 0, length: count(testString))
println(testString)
if let newString = myRegEx?.stringByReplacingMatchesInString(
testString,
options: NSMatchingOptions(0),
range: range,
withTemplate: "$1")
{
println("Result string = \(newString)")
}
else
{
println("No matches")
}
Apparently you create capture groups by enclosing part of your regular expression in parentheses. So I defined a regular expression with 2 capture groups. The first capture group is a "character class" that means any of the punctuation symbols: ,.:;?!. That part of the regular expression looks like this: ([,.:;?!]).
The second capture group matches any number of whitespace characters. The special "character class" for whitespace is \s. However, Swift strings also use a backslash for escaping, so in order to get a literal backslash in the regular expression, I had to write it as \\s. Putting that in parenthesis turns it into a capture group: (\\s).
In the call to stringByReplacingMatchesInString the regular expression is ([,.:;?!])(\\s*) and the template string is "$1".
That means:
Match strings that consist of a punctuation character followed by zero or more whitespace characters. Put the punctuation character of each match in "capture group" 1, and the whitespace in capture group 2".
Replace each match with the contents of capture group 1, which is the punctuation character.
That has the effect of discarding the whitespace from capture group 2, thus getting rid of whitespace after the specified punctuation characters.