And*_*rew 68 string character ios emoji swift
我需要找出字符串中的字符是否是表情符号.
例如,我有这个角色:
let string = ""
let character = Array(string)[0]
Run Code Online (Sandbox Code Playgroud)
我需要弄清楚那个角色是不是表情符号.
Kev*_*n R 169
我偶然发现的是字符,unicode标量和字形之间的区别.
例如,字形由7个unicode标量组成:
另一个例子,字形由2个unicode标量组成:
因此,在渲染字符时,生成的字形确实很重要.
我正在寻找的是一种检测字符串是否完全且只有一个表情符号的方法.所以我可以渲染它比普通文本更大(就像iOS10和WhatsApp现在做的消息一样).如上所述,字符数实际上没用.('胶水字符'也不被视为表情符号).
你可以做的是使用CoreText来帮助你将字符串分解为字形并计算它们.此外,我将把阿诺德和塞巴斯蒂安洛佩兹提出的部分延期移到另一个延期1.
它会留下以下结果:
extension Character {
/// A simple emoji is one scalar and presented to the user as an Emoji
var isSimpleEmoji: Bool {
guard let firstProperties = unicodeScalars.first?.properties else {
return false
}
return unicodeScalars.count == 1 &&
(firstProperties.isEmojiPresentation ||
firstProperties.generalCategory == .otherSymbol)
}
/// Checks if the scalars will be merged into an emoji
var isCombinedIntoEmoji: Bool {
return unicodeScalars.count > 1 &&
unicodeScalars.contains { $0.properties.isJoinControl || $0.properties.isVariationSelector }
}
var isEmoji: Bool {
return isSimpleEmoji || isCombinedIntoEmoji
}
}
extension String {
var isSingleEmoji: Bool {
return count == 1 && containsEmoji
}
var containsEmoji: Bool {
return contains { $0.isEmoji }
}
var containsOnlyEmoji: Bool {
return !isEmpty && !contains { !$0.isEmoji }
}
var emojiString: String {
return emojis.map { String($0) }.reduce("", +)
}
var emojis: [Character] {
return filter { $0.isEmoji }
}
var emojiScalars: [UnicodeScalar] {
return filter{ $0.isEmoji }.flatMap { $0.unicodeScalars }
}
}
Run Code Online (Sandbox Code Playgroud)
哪个会给你以下结果:
"A???".containsEmoji // false
"3".containsEmoji // false
"A?????".unicodeScalars // [65, 795, 858, 790, 9654, 65039]
"A?????".emojiScalars // [9654, 65039]
"3??".isSingleEmoji // true
"3??".emojiScalars // [51, 65039, 8419]
"".isSingleEmoji // true
"???".isSingleEmoji // true
"???".isSingleEmoji // true
"???".containsOnlyEmoji // true
"Hello ???".containsOnlyEmoji // false
"Hello ???".containsEmoji // true
" Héllo ???".emojiString // "???"
"???".count // 1
" Héllœ ???".emojiScalars // [128107, 128104, 8205, 128105, 8205, 128103, 8205, 128103]
" Héllœ ???".emojis // ["", "???"]
" Héllœ ???".emojis.count // 2
"?????".isSingleEmoji // false
"?????".containsOnlyEmoji // true
Run Code Online (Sandbox Code Playgroud)
Arn*_*old 43
最简单,最简洁,最快捷的方法是简单地检查字符串中每个字符的Unicode代码点与已知的表情符号和dingbats范围,如下所示:
extension String {
var containsEmoji: Bool {
for scalar in unicodeScalars {
switch scalar.value {
case 0x1F600...0x1F64F, // Emoticons
0x1F300...0x1F5FF, // Misc Symbols and Pictographs
0x1F680...0x1F6FF, // Transport and Map
0x2600...0x26FF, // Misc symbols
0x2700...0x27BF, // Dingbats
0xFE00...0xFE0F, // Variation Selectors
0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs
0x1F1E6...0x1F1FF: // Flags
return true
default:
continue
}
}
return false
}
}
Run Code Online (Sandbox Code Playgroud)
使用 Swift 5,您现在可以检查字符串中每个字符的 unicode 属性。这为我们提供了isEmoji每个字母上的方便变量。问题是isEmoji对于任何可以转换为 2 字节表情符号的字符,例如 0-9,都将返回 true。
我们可以查看变量isEmoji并检查是否存在表情符号修饰符,以确定不明确的字符是否会显示为表情符号。
这个解决方案应该比这里提供的正则表达式解决方案更具前瞻性。
extension String {
func containsOnlyEmojis() -> Bool {
if count == 0 {
return false
}
for character in self {
if !character.isEmoji {
return false
}
}
return true
}
func containsEmoji() -> Bool {
for character in self {
if character.isEmoji {
return true
}
}
return false
}
}
extension Character {
// An emoji can either be a 2 byte unicode character or a normal UTF8 character with an emoji modifier
// appended as is the case with 3??. 0x238C is the first instance of UTF16 emoji that requires no modifier.
// `isEmoji` will evaluate to true for any character that can be turned into an emoji by adding a modifier
// such as the digit "3". To avoid this we confirm that any character below 0x238C has an emoji modifier attached
var isEmoji: Bool {
guard let scalar = unicodeScalars.first else { return false }
return scalar.properties.isEmoji && (scalar.value > 0x238C || unicodeScalars.count > 1)
}
}
Run Code Online (Sandbox Code Playgroud)
给我们
"hey".containsEmoji() //false
"Hello World ".containsEmoji() //true
"Hello World ".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3??".containsEmoji() //true
Run Code Online (Sandbox Code Playgroud)
小智 8
extension String {
func containsEmoji() -> Bool {
for scalar in unicodeScalars {
switch scalar.value {
case 0x3030, 0x00AE, 0x00A9,// Special Characters
0x1D000...0x1F77F, // Emoticons
0x2100...0x27BF, // Misc symbols and Dingbats
0xFE00...0xFE0F, // Variation Selectors
0x1F900...0x1F9FF: // Supplemental Symbols and Pictographs
return true
default:
continue
}
}
return false
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的修复,更新范围.
Swift 5解决方案使用使用标量的适用于文本、笑脸、心形表情符号 \xe2\x9d\xa4\xef\xb8\x8f\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d 和数字 0\xef \xb8\x8f\xe2\x83\xa3 1 2 3 等
\nSwift 5标量有isEmoji和isEmojiPresentation属性,有助于在特定的字符串中查找表情符号。
\n\n是表情符号 - 布尔值,指示标量是否具有表情符号呈现,无论它是否是默认的。
\nisEmojiPresentation - 一个布尔值,指示默认情况下标量是否应该使用表情符号呈现而不是文本呈现呈现。
\n
正如您从这些定义中看到的,我们不能只在字符串的标量上使用isEmojior - 这不会告诉我们这个标量是否真的是表情符号isEmojiPresentation
幸运的是,苹果给了我们一个线索:
\n\n\n仅对单个标量进行测试
\nisEmoji不足以\n确定文本单元是否呈现为表情符号;正确的测试\n需要检查Character. 除了检查基本标量是否具有 之外isEmoji == true,您还必须检查其默认表示形式(请参阅isEmojiPresentation)并确定其后面是否跟随会修改表示形式的变体选择器。
最后,这是我的实现,适用于数字、笑脸、文本和 \xe2\x9d\xa4\xef\xb8\x8f 符号:
\nimport Foundation\n\nextension String {\n\n func containsEmoji() -> Bool {\n \n for character in self {\n var shouldCheckNextScalar = false\n for scalar in character.unicodeScalars {\n if shouldCheckNextScalar {\n if scalar == "\\u{FE0F}" { // scalar that indicates that character should be displayed as emoji\n return true\n }\n shouldCheckNextScalar = false\n }\n \n if scalar.properties.isEmoji {\n if scalar.properties.isEmojiPresentation {\n return true\n }\n shouldCheckNextScalar = true\n }\n }\n }\n \n return false\n }\n \n}\nRun Code Online (Sandbox Code Playgroud)\n测试:
\n"hello \xe2\x9d\xa4\xef\xb8\x8f".containsEmoji() // true\n"1234567890".containsEmoji() // false\n"numero 0\xef\xb8\x8f\xe2\x83\xa3".containsEmoji() // true\n"abcde".containsEmoji() // false\n"panda ".containsEmoji() // true\nRun Code Online (Sandbox Code Playgroud)\n
…引入了一种新的检查方法!
您必须闯入String它Scalars。每个Scalar都有一个Property支持该isEmoji价值的价值!
实际上,您甚至可以检查Scalar是否为Emoji修改器或更多。查看Apple文档:https : //developer.apple.com/documentation/swift/unicode/scalar/properties
您可能要考虑检查isEmojiPresentation而不是isEmoji,因为Apple声明以下内容isEmoji:
此属性适用于默认情况下渲染为表情符号的标量,以及在后跟U + FE0F VARIATION SELECTOR-16时具有非默认表情符号渲染的标量。这包括一些通常不被视为表情符号的标量。
这种方法实际上将表情符号拆分为所有修饰符,但处理起来更简单。随着Swift现在将带有修饰符(例如???,?,)的Emoji计数为1,您可以进行各种处理。
var string = " test"
for scalar in string.unicodeScalars {
let isEmoji = scalar.properties.isEmoji
print("\(scalar.description) \(isEmoji)"))
}
// true
// false
// t false
// e false
// s false
// t false
Run Code Online (Sandbox Code Playgroud)
NSHipster指出了一种获取所有表情符号的有趣方法:
import Foundation
var emoji = CharacterSet()
for codePoint in 0x0000...0x1F0000 {
guard let scalarValue = Unicode.Scalar(codePoint) else {
continue
}
// Implemented in Swift 5 (SE-0221)
// https://github.com/apple/swift-evolution/blob/master/proposals/0221-character-properties.md
if scalarValue.properties.isEmoji {
emoji.insert(scalarValue)
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
对于上述任务有一个很好的解决方案。但检查 unicode 标量的 Unicode.Scalar.Properties 对于单个字符来说是有好处的。对于字符串来说不够灵活。
\n\n我们可以使用正则表达式来代替\xe2\x80\x94 更通用的方法。下面有对其工作原理的详细描述。解决方案就在这里。
\n\n在 Swift 中,您可以使用具有此类计算属性的扩展来检查字符串是否是单个表情符号字符:
\n\nextension String {\n\n var isSingleEmoji : Bool {\n if self.count == 1 {\n let emodjiGlyphPattern = "\\\\p{RI}{2}|(\\\\p{Emoji}(\\\\p{EMod}|\\\\x{FE0F}\\\\x{20E3}?|[\\\\x{E0020}-\\\\x{E007E}]+\\\\x{E007F})|[\\\\p{Emoji}&&\\\\p{Other_symbol}])(\\\\x{200D}(\\\\p{Emoji}(\\\\p{EMod}|\\\\x{FE0F}\\\\x{20E3}?|[\\\\x{E0020}-\\\\x{E007E}]+\\\\x{E007F})|[\\\\p{Emoji}&&\\\\p{Other_symbol}]))*"\n\n let fullRange = NSRange(location: 0, length: self.utf16.count)\n if let regex = try? NSRegularExpression(pattern: emodjiGlyphPattern, options: .caseInsensitive) {\n let regMatches = regex.matches(in: self, options: NSRegularExpression.MatchingOptions(), range: fullRange)\n if regMatches.count > 0 {\n // if any range found \xe2\x80\x94 it means, that that single character is emoji\n return true\n }\n }\n }\n return false\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n\n单个表情符号(字形)可以通过许多不同的符号、序列及其组合来再现。\n Unicode 规范定义了几种可能的表情符号字符表示形式。
\n\n由单个 Unicode 标量再现的表情符号字符。
\n\nUnicode 将表情符号定义为:
\n\nemoji_character := \\p{Emoji}\nRun Code Online (Sandbox Code Playgroud)\n\n但这并不一定意味着这样的字符将被绘制为表情符号。普通数字符号 \xe2\x80\x9c1\xe2\x80\x9d 的 Emoji 属性为 true,但仍可能被绘制为文本。并且有一个此类符号的列表:#、\xc2\xa9、4 等。
\n\n人们应该想到,我们可以使用附加属性来检查:\xe2\x80\x9cEmoji_Presentation\xe2\x80\x9d。但\xe2\x80\x99 并不是这样工作的。有一个类似于 或 的表情符号,其属性 Emoji_Presentation=false。
\n\n为了确保该字符默认绘制为表情符号,我们应该检查其类别:它应该是 \xe2\x80\x9cOther_symbol\xe2\x80\x9d。
\n\n所以,实际上单字符表情符号的正则表达式应该定义为:
\n\nemoji_character := \\p{Emoji}&&\\p{Other_symbol}\nRun Code Online (Sandbox Code Playgroud)\n\n一个字符,通常可以绘制为文本或表情符号。它\xe2\x80\x99的外观取决于一个特殊的后续符号,即表示选择器,它指示其表示类型。\\x{FE0E} 定义文本表示。\\x{FE0F} 定义表情符号表示。
\n\n此类符号的列表可以在[此处](\xe2\x80\xa8 https://unicode.org/Public/emoji/12.1/emoji-variation-sequences.txt )找到。
\n\nUnicode 定义表示顺序如下:
\n\nemoji_presentation_sequence := emoji_character emoji_presentation_selector\nRun Code Online (Sandbox Code Playgroud)\n\n它的正则表达式序列:
\n\nemoji_presentation_sequence := \\p{Emoji} \\x{FE0F}\nRun Code Online (Sandbox Code Playgroud)\n\n该序列看起来与演示序列非常相似,但它在末尾有一个额外的标量:\\x{20E3}。用于它的可能基标量的范围相当窄:0-9#* \xe2\x80\x94 和 \xe2\x80\x99 全部。示例:1\xef\xb8\x8f\xe2\x83\xa3、8\xef\xb8\x8f\xe2\x83\xa3、*\xef\xb8\x8f\xe2\x83\xa3。
\n\nUnicode 定义键帽序列如下:
\n\nemoji_keycap_sequence := [0-9#*] \\x{FE0F 20E3}\nRun Code Online (Sandbox Code Playgroud)\n\n它的正则表达式:
\n\nemoji_keycap_sequence := \\p{Emoji} \\x{FE0F} \\x{FE0F}\nRun Code Online (Sandbox Code Playgroud)\n\n有些表情符号可以修改外观,例如肤色。例如,表情符号可以不同: 。要定义表情符号(在本例中称为 \xe2\x80\x9cEmoji_Modifier_Base\xe2\x80\x9d),可以使用后续的 \xe2\x80\x9cEmoji_Modifier\xe2\x80\x9d。
\n\n一般来说,这样的序列看起来像这样:
\n\nemoji_modifier_sequence := emoji_modifier_base emoji_modifier\nRun Code Online (Sandbox Code Playgroud)\n\n为了检测它,我们可以搜索正则表达式序列:
\n\nemoji_modifier_sequence := \\p{Emoji} \\p{EMod}\nRun Code Online (Sandbox Code Playgroud)\n\n旗帜是具有特定结构的表情符号。每个标志由两个 \xe2\x80\x9cRegional_Indicator\xe2\x80\x9d 符号表示。
\n\nUnicode 将它们定义为:
\n\nemoji_flag_sequence := regional_indicator regional_indicator\nRun Code Online (Sandbox Code Playgroud)\n\n例如,乌克兰国旗实际上用两个标量表示: \\u{0001F1FA \\u{0001F1E6}
\n\n它的正则表达式:
\n\nemoji_flag_sequence := \\p{RI}{2}\nRun Code Online (Sandbox Code Playgroud)\n\n使用所谓的 tag_base 的序列,后跟由符号 \\x{E0020}-\\x{E007E} 范围组成的自定义标签规范,并以 tag_end 标记 \\x{E007F} 结束。
\n\nUnicode 是这样定义的:
\n\nemoji_tag_sequence := tag_base tag_spec tag_end\ntag_base\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0:= emoji_character\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 | emoji_modifier_sequence\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 | emoji_presentation_sequence\ntag_spec\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0:= [\\x{E0020}-\\x{E007E}]+\ntag_end\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0:= \\x{E007F}\nRun Code Online (Sandbox Code Playgroud)\n\n奇怪的是,Unicode 允许标签基于ED-14a中的 emoji_modifier_sequence 或 emoji_presentation_sequence 。但同时在同一文档提供的正则表达式中,他们似乎仅基于单个表情符号字符检查序列。
\n\n在 Unicode 12.1 表情符号列表中,仅定义了三个这样的表情符号。它们都是英国国家的国旗:英格兰、苏格兰和威尔士。所有这些都基于单个表情符号字符。因此,我们\xe2\x80\x99d 最好只检查这样的序列。
\n\n正则表达式:
\n\n\\p{Emoji} [\\x{E0020}-\\x{E007E}]+ \\x{E007F}\nRun Code Online (Sandbox Code Playgroud)\n\n零宽度连接符是标量 \\x{200D}。在它的帮助下,几个本身已经是表情符号的字符可以组合成新的表情符号。
\n\n例如,具有父亲、儿子和女儿的 \xe2\x80\x9cfamily\xe2\x80\x9d 表情符号 \xe2\x80\x8d\xe2\x80\x8d 是由父亲、女儿和儿子表情符号粘合在一起的组合再现的ZWJ 符号。
\n\n允许将元素粘在一起,这些元素是单个表情符号字符、表示和修饰符序列。
\n\n此类序列的正则表达式通常如下所示:
\n\nemoji_zwj_sequence := emoji_zwj_element (\\x{200d} emoji_zwj_element )+\nRun Code Online (Sandbox Code Playgroud)\n\n所有上述的表情符号表示都可以用一个正则表达式来描述:
\n\n\\p{RI}{2}\n| ( \\p{Emoji} \n ( \\p{EMod} \n | \\x{FE0F}\\x{20E3}? \n | [\\x{E0020}-\\x{E007E}]+\\x{E007F} \n ) \n | \xe2\x80\xa8[\\p{Emoji}&&\\p{Other_symbol}] \n )\n ( \\x{200D}\n ( \\p{Emoji} \n ( \\p{EMod} \n | \\x{FE0F}\\x{20E3}? \n | [\\x{E0020}-\\x{E007E}]+\\x{E007F} \n ) \n | [\\p{Emoji}&&\\p{Other_symbol}] \n ) \n )*\nRun Code Online (Sandbox Code Playgroud)\n