用twitter开源twemojireplaceiOS应用emoji

我想用tweet开源twemojireplaceUILable或UITextView的所有标准iOS表情符号。

我无法在iOS中find任何库或文档来执行此操作。 有没有人有一个解决scheme,不涉及我从头开始实施这个?

解决scheme需要高效并脱机工作。

这个问题引起了我的兴趣,经过了一些关于如何用一个自定义集合replace所有标准的iOS表情符号,我发现即使是Twitter自己的iOS应用程序也不使用Twemoji:

鸣叫

最后,我得出和你一样的结论:

我无法在iOS中find任何库或文档来执行此操作。

所以,我为了这个确切的目的在Swift中创build了一个框架 。

它为你做了所有的工作,但是如果你想实现你自己的解决scheme,我将在下面描述如何用Twemojireplace所有的标准表情符号。


1.logging可以表示为表情符号的所有字符

有1126个基本字符具有表情符号表示,并有超过一千个由序列组成的附加表示。 尽pipe大多数基本字符被限制在六个Unicode块中 ,但除了其中一个块之外 ,其他块都与非表情符号字符和/或未分配的代码点混合在一起。 这些块之外的其余基本字符分散在其他各个块中。

我的实现只是声明这些字符的UTF-32代码点,因为UnicodeScalarvalue属性就是这个。

2.检查一个angular色是否是一个表情符号

在Swift中, String包含一组Character对象,每个对象表示一个扩展的字形群集 。 一个扩展的字形集群是一个Unicode标量序列,它们共同代表一个人类可读的字符,这是有帮助的,因为您可以遍历string的字符并根据它们包含的UnicodeScalar处理它们(而不是循环遍历string的UTF-16值 )。

要确定一个Character是否是一个表情符号,只有第一个UnicodeScalar是重要的,所以比较这个值到您的表情符号字符就足够了。 但是,我还build议检查Character包含变体select器 ,如果是,请确保它是VS16 – 否则angular色不应该被显示为表情符号。

Character提取UnicodeScalar需要一个小小的破解:

 let c: Character = "A" let scalars = String(c).unicodeScalars 

3.将代码点转换为正确的格式

Twemoji图像根据其相应的代码点2命名,这是有道理的。 所以,下一步就是把Character转换成一个等同于图像名称的string:

 let codePoint = String("🙃").unicodeScalars.first!.value // 128579 let imageName = String(codePoint, radix: 16) // "1f643" 

太好了,但是这不适用于标志或键帽 ,所以我们必须修改我们的代码来考虑这些:

 let scalars = String("🇧🇪").unicodeScalars let filtered = scalars.filter{ $0.value != 0xfe0f } // Remove VS16 from variants, including keycaps. let mapped = filtered.map{ String($0.value, radix: 16) } let imageName = mapped.joined(separator: "-") // "1f1e7-1f1ea" 

4.replacestring中的表情符号

为了replace给定String的表情符号,我们需要使用NSMutableAttributedString来存储原始string,并用包含相应的Twemoji图像的NSTextAttachment对象replace表情符号。

 let originalString = "🙃" let attributedString = NSMutableAttributedString(string: originalString) for character in originalString.characters { // Check if character is emoji, see section 2. ... // Get the image name from the character, see section 3. let imageName = ... // Safely unwrapping to make sure the image exists. if let image = UIImage(named: imageName) { let attachment = NSTextAttachment() attachment.image = image // Create an attributed string from the attachment. let twemoji = NSAttributedString(attachment: attachment) // Get the range of the character in attributedString. let range = attributedString.mutableString.range(of: String(character)) // Replace the emoji with the corresponding Twemoji. attributedString.replaceCharacters(in: range, with: twemoji) } } 

要显示结果属性string,只需将其设置为UITextView / UILabelattributedText UITextView attributedText

请注意,上面的方法没有考虑到零宽度的join者或修饰符序列 ,但我觉得这个答案已经太长了。


1. Charactertypes有一个怪癖,尽pipe包含理论上无限量的Unicode标量,但它将一系列连接的区域指示符号解释为一个对象。 在操场上试试"🇩🇰🇫🇮🇮🇸🇳🇴🇸🇪".characters.count

2.关于零宽度join者和变体select器,命名模式略有不同,所以从图像名称中删除这些名称会更容易 – 请参阅此处。

最简单的事情是:

1)加载twemoji图像到您的项目。 2)创build一个NSDictionary,将iOS支持的表情符号与相应twemoji图像的path相关联:

 NSArray *iOSEmojis = @[@"iOSEmoji1",@"iOSEmoji2]; NSDictionary *twemojiPaths = [NSDictionary dictionaryWithObjects:@[@"Project/twemoji1.png",@"Project/twemoji2.png"] andKeys:@[@"iOSEmoji1","iOSEmoji2"]]; 

3)编写您的应用程序来search表情符号string,并显示常规表情符号将去的twemojis:

 for (NSString *emoji in iOSEmojis) { NSString *twemojiPath = [twemojiPaths valueForKey:emoji]; // Find the position of the emoji string in the text // and put an image view there. NSRange range = [label.text rangeOfString:emoji]; NSString *prefix = [label.text substringToIndex:range.location]; CGSize prefixSize = [prefix sizeWithAttributes: @{NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue" size:14]}]; CGSize emojiSize = [label.text sizeWithAttributes: @{NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue" size:14]}]; CGRect imageViewFrame = CGRectMake(prefixSize.width,label.frame.size.height,emojiSize.width,label.frame.size.height); imageViewFrame = [self.view convertRect:imageViewFrame fromView:label]; UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageViewFrame]; imageView.image = [UIImage imageWithContentsOfFile:twemojiPath]; }