|
|
|
@ -11,13 +11,83 @@ import Foundation
|
|
|
|
|
let fullText: String
|
|
|
|
|
let displayText: String
|
|
|
|
|
let isTextTruncated: Bool
|
|
|
|
|
let jumbomojiCount: NSNumber?
|
|
|
|
|
|
|
|
|
|
static let kMaxJumbomojiCount: UInt = 5
|
|
|
|
|
|
|
|
|
|
// MARK: Initializers
|
|
|
|
|
|
|
|
|
|
init(fullText: String, displayText: String, isTextTruncated: Bool) {
|
|
|
|
|
init(fullText: String, displayText: String, isTextTruncated: Bool, jumbomojiCount: NSNumber?) {
|
|
|
|
|
self.fullText = fullText
|
|
|
|
|
self.displayText = displayText
|
|
|
|
|
self.isTextTruncated = isTextTruncated
|
|
|
|
|
self.jumbomojiCount = jumbomojiCount
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: Emoji
|
|
|
|
|
|
|
|
|
|
private class func canDetectEmoji() -> Bool {
|
|
|
|
|
if #available(iOS 10.0, *) {
|
|
|
|
|
return true
|
|
|
|
|
} else {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the string is...
|
|
|
|
|
//
|
|
|
|
|
// * Non-empty
|
|
|
|
|
// * Only contains emoji
|
|
|
|
|
// * Contains <= maxEmojiCount emoji
|
|
|
|
|
//
|
|
|
|
|
// ...return the number of emoji in the string. Otherwise return nil.
|
|
|
|
|
//
|
|
|
|
|
// On iOS 9 and earler, always returns nil.
|
|
|
|
|
@objc public class func jumbomojiCount(to string: String) -> NSNumber? {
|
|
|
|
|
if string == "" {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if string.characters.count > Int(kMaxJumbomojiCount) {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if !canDetectEmoji() {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
var didFail = false
|
|
|
|
|
var emojiCount: UInt = 0
|
|
|
|
|
let attributes = [NSFontAttributeName: UIFont.systemFont(ofSize:12)]
|
|
|
|
|
let attributedString = NSMutableAttributedString(string: string, attributes: attributes)
|
|
|
|
|
let range = NSRange(location: 0, length: string.characters.count)
|
|
|
|
|
attributedString.fixAttributes(in: range)
|
|
|
|
|
attributedString.enumerateAttribute(NSFontAttributeName,
|
|
|
|
|
in: range,
|
|
|
|
|
options: [],
|
|
|
|
|
using: {(_ value: Any?, range: NSRange, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
|
|
|
|
|
guard emojiCount < kMaxJumbomojiCount else {
|
|
|
|
|
didFail = true
|
|
|
|
|
stop.pointee = true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
guard let rangeFont = value as? UIFont else {
|
|
|
|
|
didFail = true
|
|
|
|
|
stop.pointee = true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
guard rangeFont.fontName == ".AppleColorEmojiUI" else {
|
|
|
|
|
didFail = true
|
|
|
|
|
stop.pointee = true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if rangeFont.fontName == ".AppleColorEmojiUI" {
|
|
|
|
|
Logger.verbose("Detected Emoji at location: \(range.location), for length: \(range.length)")
|
|
|
|
|
emojiCount += UInt(range.length)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
guard !didFail else {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return NSNumber(value: emojiCount)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: Filter Methods
|
|
|
|
|