我正在使用此
获取字符串的文本大小textSize = [[tempDict valueForKeyPath:@"caption.text"] sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:CGSizeMake(280, CGFLOAT_MAX) lineBreakMode: NSLineBreakByWordWrapping];
我唯一的问题是,如果字符串只包含表情符号,我的应用程序崩溃了。有没有一种简单的方法来检查表情符号,或者我是否必须创建一个包含所有可能的表情符号的数组,然后使用它来检查它们?
错误:
-[NSNull sizeWithFont:constrainedToSize:lineBreakMode:]: unrecognized selector sent to instance 0x3aa88a60
if ([tempDict valueForKeyPath:@"caption.text"]){
NSLog(@"%@", [tempDict valueForKeyPath:@"caption"]);
//Measure the message label box height
textSize = [[tempDict valueForKeyPath:@"caption.text"] sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:CGSizeMake(280, CGFLOAT_MAX) lineBreakMode: NSLineBreakByWordWrapping];
int height = 320 + 20 + textSize.height;
[cellHeight addObject:[NSNumber numberWithInt:height]];
}
答案 0 :(得分:12)
试试这段代码:
- (BOOL)stringContainsEmoji:(NSString *)string {
__block BOOL returnValue = NO;
[string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:
^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
const unichar hs = [substring characterAtIndex:0];
// surrogate pair
if (0xd800 <= hs && hs <= 0xdbff) {
if (substring.length > 1) {
const unichar ls = [substring characterAtIndex:1];
const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
if (0x1d000 <= uc && uc <= 0x1f77f) {
returnValue = YES;
}
}
} else if (substring.length > 1) {
const unichar ls = [substring characterAtIndex:1];
if (ls == 0x20e3) {
returnValue = YES;
}
} else {
// non surrogate
if (0x2100 <= hs && hs <= 0x27ff) {
returnValue = YES;
} else if (0x2B05 <= hs && hs <= 0x2b07) {
returnValue = YES;
} else if (0x2934 <= hs && hs <= 0x2935) {
returnValue = YES;
} else if (0x3297 <= hs && hs <= 0x3299) {
returnValue = YES;
} else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
returnValue = YES;
}
}
}];
return returnValue;
}
答案 1 :(得分:9)
@Simha.IC答案很棒。
然而,它不适用于新的iOS 9.1 emojis&#39;。
Simha.IC片段未检测到这些:
☂️✝️✡️☯️
所以为了解决这个问题,我稍微调整了一下代码并用它创建了一个类别:
- (BOOL)emo_containsEmoji
{
__block BOOL containsEmoji = NO;
[self enumerateSubstringsInRange:NSMakeRange(0,
[self length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring,
NSRange substringRange,
NSRange enclosingRange,
BOOL *stop)
{
const unichar hs = [substring characterAtIndex:0];
// surrogate pair
if (0xd800 <= hs &&
hs <= 0xdbff)
{
if (substring.length > 1)
{
const unichar ls = [substring characterAtIndex:1];
const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
if (0x1d000 <= uc &&
uc <= 0x1f9c0)
{
containsEmoji = YES;
}
}
}
else if (substring.length > 1)
{
const unichar ls = [substring characterAtIndex:1];
if (ls == 0x20e3 ||
ls == 0xfe0f ||
ls == 0xd83c)
{
containsEmoji = YES;
}
}
else
{
// non surrogate
if (0x2100 <= hs &&
hs <= 0x27ff)
{
containsEmoji = YES;
}
else if (0x2B05 <= hs &&
hs <= 0x2b07)
{
containsEmoji = YES;
}
else if (0x2934 <= hs &&
hs <= 0x2935)
{
containsEmoji = YES;
}
else if (0x3297 <= hs &&
hs <= 0x3299)
{
containsEmoji = YES;
}
else if (hs == 0xa9 ||
hs == 0xae ||
hs == 0x303d ||
hs == 0x3030 ||
hs == 0x2b55 ||
hs == 0x2b1c ||
hs == 0x2b1b ||
hs == 0x2b50)
{
containsEmoji = YES;
}
}
}];
return containsEmoji;
}
我的类别可以计算:
答案 2 :(得分:2)
这就是我正在使用的:
func isAllEmoji(aString: String) -> Bool {
for scalar in aString.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
0x0030...0x0039,
0x00A9...0x00AE,
0x203C...0x2049,
0x2122...0x3299,
0x1F004...0x1F251,
0x1F910...0x1F990:
break
default:
return false
}
}
return true
}
答案 3 :(得分:1)
您可以使用此新框架
https://github.com/woxtu/NSString-RemoveEmoji
用法:
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
</LinearLayout>
</TabHost>
答案 4 :(得分:1)
如果有任何字符超过0x00ff
,则可能会出现此问题。换句话说,除了表情符号之外,还有许多Unicode字符可能需要考虑。为了查看是否有任何Unicode字符(超出扩展ASCII的边界),请使用以下内容。
extension String {
var containsUnicodeCharacters: Bool {
for scalar in unicodeScalars {
if scalar.value > 0x00FF {
return true
}
}
return false
}
}
答案 5 :(得分:1)
对此进行回复为时已晚,但可能会对某人有所帮助。
- (BOOL)stringContainsEmoji:(NSString *)string {
__block BOOL returnValue = NO;
[string enumerateSubstringsInRange:NSMakeRange(0, string.length)
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop)
{
const unichar hs = [substring characterAtIndex:0];
const unichar ls = substring.length > 1 ? [substring characterAtIndex:1] : 0;
#define IS_IN(val, min, max) (((val) >= (min)) && ((val) <= (max)))
if(IS_IN(hs, 0xD800, 0xDBFF))
{
if(substring.length > 1)
{
const int uc = ((hs - 0xD800) * 0x400) + (ls - 0xDC00) + 0x10000;
// Musical: [U+1D000, U+1D24F]
// Enclosed Alphanumeric Supplement: [U+1F100, U+1F1FF]
// Enclosed Ideographic Supplement: [U+1F200, U+1F2FF]
// Miscellaneous Symbols and Pictographs: [U+1F300, U+1F5FF]
// Supplemental Symbols and Pictographs: [U+1F900, U+1F9FF]
// Emoticons: [U+1F600, U+1F64F]
// Transport and Map Symbols: [U+1F680, U+1F6FF]
if(IS_IN(uc, 0x1D000, 0x1F9FF))
returnValue = YES;
}
}
else if(substring.length > 1 && ls == 0x20E3)
{
// emojis for numbers: number + modifier ls = U+20E3
returnValue = YES;
}
else
{
if( // Latin-1 Supplement
hs == 0x00A9 || hs == 0x00AE
// General Punctuation
|| hs == 0x203C || hs == 0x2049
// Letterlike Symbols
|| hs == 0x2122 || hs == 0x2139
// Arrows
|| IS_IN(hs, 0x2194, 0x2199) || IS_IN(hs, 0x21A9, 0x21AA)
// Miscellaneous Technical
|| IS_IN(hs, 0x231A, 0x231B) || IS_IN(hs, 0x23E9, 0x23F3) || IS_IN(hs, 0x23F8, 0x23FA) || hs == 0x2328 || hs == 0x23CF
// Geometric Shapes
|| IS_IN(hs, 0x25AA, 0x25AB) || IS_IN(hs, 0x25FB, 0x25FE) || hs == 0x25B6 || hs == 0x25C0
// Miscellaneous Symbols
|| IS_IN(hs, 0x2600, 0x2604) || IS_IN(hs, 0x2614, 0x2615) || IS_IN(hs, 0x2622, 0x2623) || IS_IN(hs, 0x262E, 0x262F)
|| IS_IN(hs, 0x2638, 0x263A) || IS_IN(hs, 0x2648, 0x2653) || IS_IN(hs, 0x2665, 0x2666) || IS_IN(hs, 0x2692, 0x2694)
|| IS_IN(hs, 0x2696, 0x2697) || IS_IN(hs, 0x269B, 0x269C) || IS_IN(hs, 0x26A0, 0x26A1) || IS_IN(hs, 0x26AA, 0x26AB)
|| IS_IN(hs, 0x26B0, 0x26B1) || IS_IN(hs, 0x26BD, 0x26BE) || IS_IN(hs, 0x26C4, 0x26C5) || IS_IN(hs, 0x26CE, 0x26CF)
|| IS_IN(hs, 0x26D3, 0x26D4) || IS_IN(hs, 0x26D3, 0x26D4) || IS_IN(hs, 0x26E9, 0x26EA) || IS_IN(hs, 0x26F0, 0x26F5)
|| IS_IN(hs, 0x26F7, 0x26FA)
|| hs == 0x260E || hs == 0x2611 || hs == 0x2618 || hs == 0x261D || hs == 0x2620 || hs == 0x2626 || hs == 0x262A
|| hs == 0x2660 || hs == 0x2663 || hs == 0x2668 || hs == 0x267B || hs == 0x267F || hs == 0x2699 || hs == 0x26C8
|| hs == 0x26D1 || hs == 0x26FD
// Dingbats
|| IS_IN(hs, 0x2708, 0x270D) || IS_IN(hs, 0x2733, 0x2734) || IS_IN(hs, 0x2753, 0x2755)
|| IS_IN(hs, 0x2763, 0x2764) || IS_IN(hs, 0x2795, 0x2797)
|| hs == 0x2702 || hs == 0x2705 || hs == 0x270F || hs == 0x2712 || hs == 0x2714 || hs == 0x2716 || hs == 0x271D
|| hs == 0x2721 || hs == 0x2728 || hs == 0x2744 || hs == 0x2747 || hs == 0x274C || hs == 0x274E || hs == 0x2757
|| hs == 0x27A1 || hs == 0x27B0 || hs == 0x27BF
// CJK Symbols and Punctuation
|| hs == 0x3030 || hs == 0x303D
// Enclosed CJK Letters and Months
|| hs == 0x3297 || hs == 0x3299
// Supplemental Arrows-B
|| IS_IN(hs, 0x2934, 0x2935)
// Miscellaneous Symbols and Arrows
|| IS_IN(hs, 0x2B05, 0x2B07) || IS_IN(hs, 0x2B1B, 0x2B1C) || hs == 0x2B50 || hs == 0x2B55
)
{
returnValue = YES;
}
}
#undef IS_IN
}];
return returnValue;
}
答案 6 :(得分:0)
请参阅此答案How to get NSString size when NSString includes emojis?
如果您只有表情符号,则不应使用sizeWithFont
。使用标签或其他东西。
NSString不适用于Emojis,只适用于文本。如果您有表情符号,则应使用[label sizeToFit]
或[label sizeThatFits:]
此外,您可以使用此代码:
id text = [tempDict valueForKeyPath:@"caption.text"]
if (![text isKindOfClass:[NSNull class]]) {
...
}
因为,你从字典中获得NSNull,但它不等于nil,并且你的条件有效。
答案 7 :(得分:0)
人们一次又一次地使用valueForKeyPath而不是objectForKey。他们都无法解释原因。阅读文档。如果在阅读之后您可以解释为什么使用valueForKeyPath(和#34;我从某处复制了它&#34;不是解释),将其更改为objectForKey。
你遇到的问题根本与Emojis无关。任何在字符串中检测Emojis的尝试都将失败 - 原因很简单,你首先没有字符串,你有[NSNull null]。可以通过使用objectForKey来解决这个问题 - 你可能会得到nil而不是更宽容的行为。或者你仍然得到[NSNull null]。
找出你获得[NSNull null]的原因。有人把它放在那里。如果你不能阻止它在那里,那么你需要处理它。
答案 8 :(得分:0)
现在有了 iOS 10 的新版本,对于以下表情符号,它不起作用:
以下代码片段针对iOS 9和iOS 10进行了尝试和测试:
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
0x1F910...0x1F918, // New Emoticons
0x1F1E6...0x1F1FF, // Flags
0x1F980...0x1F984,
0x1F191...0x1F19A,
0x1F201...0x1F202,
0x1F232...0x1F23A,
0x1F250...0x1F251,
0x23E9...0x23F3,
0x23F8...0x23FA,
0x1F170...0x1F171,
0x1F17E,
0xA9,
0xAE,
0x2122,
0x2328,
0x3030,
0x1F0CF,
0x1F18E,
0x1F9C0:
return true
default:
continue
}
}
return false
}
}
如上所述,在您的应用中创建一个String扩展名。
可以像这样使用:
if string.containsEmoji {
// Do operations here
}
答案 9 :(得分:0)
一种简单的Swift解决方案,用于检查unicode中的每个标量。标量位于CharacterSet.symbols集中。
extension String {
var containsEmoji: Bool {
for scalar in unicodeScalars {
if CharacterSet.symbols.contains(scalar) {
return true
}
}
return false
}
}
但是我发现像ℹ️这样的emoji 1.0项目没有被归类为emoji。因此,我创建了此检查器:
extension Unicode.Scalar {
extension Unicode.Scalar {
var isEmojiMiscSymbol: Bool {
switch self.value {
case 0x2030...0x329F: // Misc symbols
return true
default:
return false
}
}
}
}
这是可以检测ℹ️的检查器:
extension String {
var containsEmoji: Bool {
for scalar in unicodeScalars {
if CharacterSet.symbols.contains(scalar) {
return true
} else if scalar.isEmojiMiscSymbol {
return true
}
}
return false
}
}