문자열의 문자가 이모티콘인지 확인해야합니다.
예를 들어 다음과 같은 캐릭터가 있습니다.
let string = "?"
let character = Array(string)[0]
그 캐릭터가 이모티콘인지 알아 내야합니다.
답변
내가 우연히 발견 한 것은 문자, 유니 코드 스칼라 및 글리프의 차이입니다.
예를 들어 글리프 ????는 7 개의 유니 코드 스칼라로 구성됩니다.
또 다른 예, 글리프 ??는 2 개의 유니 코드 스칼라로 구성됩니다.
- 일반 이모티콘 : ?
- 피부톤 수정 자 : ?
마지막으로 글리프 1️⃣에는 세 개의 유니 코드 문자가 있습니다.
- 숫자 하나 :
1
- 변형 선택기
- 결합 형 엔 클로징 키캡 :
⃣
따라서 캐릭터를 렌더링 할 때 결과 글리프가 정말 중요합니다.
Swift 5.0 이상은이 과정을 훨씬 쉽게 만들어주고 우리가해야 할 추측을 없애줍니다. Unicode.Scalar
의 새로운 Property
유형은 우리가 다루는 것을 결정하는 데 도움이됩니다. 그러나 이러한 속성은 글리프 내의 다른 스칼라를 확인할 때만 의미가 있습니다. 이것이 우리를 돕기 위해 Character 클래스에 몇 가지 편리한 메서드를 추가하는 이유입니다.
자세한 내용 은 이것이 어떻게 작동하는지 설명하는 기사를 썼습니다 .
Swift 5.0의 경우 다음과 같은 결과가 나타납니다.
extension Character {
/// A simple emoji is one scalar and presented to the user as an Emoji
var isSimpleEmoji: Bool {
guard let firstScalar = unicodeScalars.first else { return false }
return firstScalar.properties.isEmoji && firstScalar.value > 0x238C
}
/// Checks if the scalars will be merged into an emoji
var isCombinedIntoEmoji: Bool { unicodeScalars.count > 1 && unicodeScalars.first?.properties.isEmoji ?? false }
var isEmoji: Bool { isSimpleEmoji || isCombinedIntoEmoji }
}
extension String {
var isSingleEmoji: Bool { count == 1 && containsEmoji }
var containsEmoji: Bool { contains { $0.isEmoji } }
var containsOnlyEmoji: Bool { !isEmpty && !contains { !$0.isEmoji } }
var emojiString: String { emojis.map { String($0) }.reduce("", +) }
var emojis: [Character] { filter { $0.isEmoji } }
var emojiScalars: [UnicodeScalar] { filter { $0.isEmoji }.flatMap { $0.unicodeScalars } }
}
다음과 같은 결과를 얻을 수 있습니다.
"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
"⏰".isSingleEmoji // true
"?".isSingleEmoji // true
"????".isSingleEmoji // true
"???????".isSingleEmoji // true
"???????".containsOnlyEmoji // 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
이전 Swift 버전의 경우 이전 코드가 포함 된이 요점을 확인하십시오.
답변
이 작업을 수행 하는 가장 간단하고 깔끔하며 가장 빠른 방법은 다음과 같이 문자열의 각 문자에 대한 유니 코드 코드 포인트를 알려진 이모 지 및 딩뱃 범위와 비교하여 확인하는 것입니다.
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
}
}
답변
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
}
}
이것은 업데이트 된 범위와 함께 내 수정입니다.
답변
스위프트 5.0
… 정확히 이것을 확인하는 새로운 방법을 도입했습니다!
당신은 String
그것의 Scalars
. 각 Scalar
갖는다 Property
지원 값isEmoji
가치를 가지고 있습니다!
실제로 Scalar가 Emoji modifier 이상인지 확인할 수도 있습니다. Apple의 문서를 확인하십시오 : https://developer.apple.com/documentation/swift/unicode/scalar/properties
Apple이 다음에 대해 다음과 같이 명시하고 있으므로 isEmojiPresentation
대신에 확인하는 것이 좋습니다 .isEmoji
isEmoji
이 속성은 기본적으로 이모티콘으로 렌더링되는 스칼라와 U + FE0F VARIATION SELECTOR-16이 뒤 따르는 경우 기본이 아닌 이모티콘 렌더링이있는 스칼라에 대해서도 true입니다. 여기에는 일반적으로 이모티콘으로 간주되지 않는 일부 스칼라가 포함됩니다.
이 방법은 실제로 Emoji를 모든 수정 자로 분할하지만 처리하기가 더 간단합니다. 그리고 Swift는 이제 수식어 (예 : ????, ???, ?)가있는 이모티콘을 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
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)
}
}
답변
Swift 5를 사용하면 이제 문자열에있는 각 문자의 유니 코드 속성을 검사 할 수 있습니다. 이것은 우리 isEmoji
에게 각 문자에 대한 편리한 변수를 제공 합니다. 문제는 isEmoji
0-9와 같이 2 바이트 이모티콘으로 변환 할 수있는 모든 문자에 대해 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)
}
}
우리에게
"hey".containsEmoji() //false
"Hello World ?".containsEmoji() //true
"Hello World ?".containsOnlyEmojis() //false
"3".containsEmoji() //false
"3️⃣".containsEmoji() //true
답변
Swift 3 참고 :
표시 cnui_containsEmojiCharacters
방법 중 어느 하나를 제거하거나 다른 동적 라이브러리로 이동되었다. _containsEmoji
그래도 작동합니다.
let str: NSString = "hello?"
@objc protocol NSStringPrivate {
func _containsEmoji() -> ObjCBool
}
let strPrivate = unsafeBitCast(str, to: NSStringPrivate.self)
strPrivate._containsEmoji() // true
str.value(forKey: "_containsEmoji") // 1
let swiftStr = "hello?"
(swiftStr as AnyObject).value(forKey: "_containsEmoji") // 1
Swift 2.x :
최근 NSString
에 문자열에 이모티콘 문자가 포함되어 있는지 감지하는 기능을 제공 하는 비공개 API를 발견했습니다 .
let str: NSString = "hello?"
objc 프로토콜 및 unsafeBitCast
:
@objc protocol NSStringPrivate {
func cnui_containsEmojiCharacters() -> ObjCBool
func _containsEmoji() -> ObjCBool
}
let strPrivate = unsafeBitCast(str, NSStringPrivate.self)
strPrivate.cnui_containsEmojiCharacters() // true
strPrivate._containsEmoji() // true
와 함께 valueForKey
:
str.valueForKey("cnui_containsEmojiCharacters") // 1
str.valueForKey("_containsEmoji") // 1
순수한 Swift 문자열 AnyObject
을 사용하면 valueForKey
다음을 사용하기 전에 문자열을 캐스팅해야합니다 .
let str = "hello?"
(str as AnyObject).valueForKey("cnui_containsEmojiCharacters") // 1
(str as AnyObject).valueForKey("_containsEmoji") // 1
NSString 헤더 파일 에있는 메소드 .
답변
Swift에서 사용하려면 카테고리를 YourProject_Bridging_Header
#import "NSString+EMOEmoji.h"
그런 다음 문자열에있는 모든 이모티콘의 범위를 확인할 수 있습니다.
let example: NSString = "string????with?emojis✊?" //string with emojis
let containsEmoji: Bool = example.emo_containsEmoji()
print(containsEmoji)
// Output: ["true"]