Skip to content

Instantly share code, notes, and snippets.

@hebertialmeida
Created November 23, 2017 16:49
Show Gist options
  • Save hebertialmeida/d868bd58efe8b5240e4ef8b542107099 to your computer and use it in GitHub Desktop.
Save hebertialmeida/d868bd58efe8b5240e4ef8b542107099 to your computer and use it in GitHub Desktop.
Twitter text counter 280 characters
import Foundation
struct WeightRange {
let range: ClosedRange<UInt32>
let weight: Int
}
struct TwitterText {
static func lengthOf(tweet: String) -> Int {
let defaultWeight = 200
let scale = 100
let ranges = [
WeightRange(range: 0...4351, weight: 100),
WeightRange(range: 8192...8205, weight: 100),
WeightRange(range: 8208...8223, weight: 100),
WeightRange(range: 8242...8247, weight: 100)
]
let (cleanText, urlLength) = cleanAndCountURLs(text: tweet)
var weightedLength = urlLength * scale
for char in cleanText.unicodeScalars {
var weight = defaultWeight
for item in ranges where item.range ~= char.value {
weight = item.weight
continue
}
weightedLength += weight
}
weightedLength /= scale
return weightedLength
}
private static func cleanAndCountURLs(text: String) -> (String, Int) {
var output = text
var lenght = 0
let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
let matches = detector.matches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count))
matches.forEach {
output = (text as NSString).replacingCharacters(in: $0.range, with: "")
lenght += 23
}
return (output, lenght)
}
}
@hebertialmeida
Copy link
Author

Sample:

var str = "日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本語日本 https://google.com"

TwitterText.lengthOf(tweet: str) // 280

@annjawn
Copy link

annjawn commented Mar 26, 2018

@hebertialmeida this was super helpful thanks a lot. There is one tiny issue though, NSDataDetector fails to handle some short URLs for example url like es.pn returns a length of 5 where as the twitter app correctly calculates it as 23. I have faced this issue and I am not sure how to go about solving this.

I see this note in the Objective C library for URL-

IFUnicodeURL is a category for NSURL which will allow it to support Internationalized domain names in URLs.

This uses code from IDN SDK from Verisign, Inc. The entire IDN SDK source package is included in IDNSDK-1.1.0.zip. I have pulled out and slightly modified (to avoid compiler and analyzer warnings) the files and headers needed so that building this in XCode is as easy as adding the IFUnicodeURL folder to your project.

@hebertialmeida
Copy link
Author

@annjaun I think any URLs on twitter should count as 23, but yeah, detecting this kind of URL will probably require a custom regex implementation if it is not handled by NSDataDetector .

Twitter also count es.pn as 23:

screen shot 2018-06-15 at 3 41 09 pm

screen shot 2018-06-15 at 3 39 19 pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment