• Working With Emoji in Swift
  • Originally written by Alex Nekrasov
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: Liu Jiayi
  • Proofread by: Godlowd, Zenblo

Play emoji on Swift

Emoji have become a big part of our lives. The iPhone and iPad have dedicated keyboards for emoji (unless that feature is turned off). We see them on websites, mobile and desktop apps, and we enter them when editing text or filling out forms.

How do we manage emoji? How to prevent users from entering emojis in UITextField? How do we parse emoji from the server’s JSON return body? Let’s find out.

A little bit of theory

Emoji are part of Unicode today. Computers operate in bits and bytes — not smileys or other small shapes. Each letter, number, or special character in text is encoded by one or more bytes. The same goes for emoji. They’re essentially symbols.

Unicode has three standard encoding variants. They are constantly evolving, adding new symbols and incorporating new languages. So there are actually more than three ways to encode Unicode, but it’s important for us as developers to know the following three coding standards:

  1. Utf-8 (Unicode Transformation Format 8-bit) : Under this encoding, each symbol is represented by one or more bytes. Simple Latin characters, numbers, and partial symbols take up only 1 byte (8 bits). If the first bit of a character is 0, we know that it is a 1-byte symbol. When encoding Russian, Chinese, Arabic, or emoji, each character takes up more than one byte, and the first bit is 1.
  2. Utf-16 (Unicode Transformation Format 16-bit) : All symbols are encoded in two or four bytes. Two bytes can combine 65536 different values, which can basically cover common characters. Emojis typically take up two bytes, but some emoji variants (different colors of skin or hair) take up more data bits.
  3. Utf-32 (Unicode Transformation Format 32-bit) : This is the easiest to understand encoding, but the memory space is inefficient. Each character is represented by four bytes.

Emoji characters have been added to Unicode 6.0 since 2010. All current iphones and Macs support newer Versions of Unicode, so you can safely use emoji in your app and they will be displayed correctly to the user.

“The NSString object encodes Unicode text strings and is represented as a series of UTF-16 code units.” – Apple Developer

As you can see, emoji can appear in any string on Swift.

In the macOS emoji

Since we primarily write Swift code in macOS, let’s take a look at how to add emoji to the code.

In any app with text editing capabilities, including Xcode, you can click on the Edit menu and then click on emoticons and symbols. You’ll see the emoji input panel. Select an emoji and click to add it to the code.

You can also invoke the Emoji palette by using the shortcut ⌃⌘Space (CTRL + CMD + Space).

Detect emoji in String

Before we start, let’s add some extensions to the project. They help us determine whether a String has emoji, whether it is all emoji, whether the Character is emoji, and so on.

import Foundation

extension Character {
    var isSimpleEmoji: Bool {
        guard let firstScalar = unicodeScalars.first else { return false }
        return firstScalar.properties.isEmoji && firstScalar.value > 0x238C
    }

    var isCombinedIntoEmoji: Bool { unicodeScalars.count > 1 && unicodeScalars.first?.properties.isEmoji ?? false }

    var isEmoji: Bool { isSimpleEmoji || isCombinedIntoEmoji }
}
Copy the code

Now you can check if the String contains emoji:

"Alex 😊".containsEmoji // true

"Alex 😊".containsOnlyEmoji // false
Copy the code

Disable emoji in UITextField

Normally, we don’t allow users to enter emojis. For example, when we want to get the user’s legal name or other similar data.

There are two ways to limit users — strict and slightly lax.

The strict method (easy to implement) requires setting the Keyboard Type of UITextField to ASCII Capable. This will contain only the first 128 symbols in the Unicode character set. If you remember the details of UTF-8, it is divided into 1 byte, 2 byte, and 4 byte characters. The option, when turned on, contains only 1 byte characters (the first bit is 0).

While this approach is useful in scenarios where a user name or password is entered, names and other data are likely to contain phonetic symbols, non-Latin letters, or other characters. In this case, we need to choose the second method. The specific steps are as follows:

  1. Set keyboard Type to Default.
  2. Sets the delegate. Usually pointed at youUIViewController.
  3. In the delegate, rewritefunc textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> BoolMethods.
  4. Get the updated text:
if let text = textField.text,
    let textRange = Range(range, in: text) {
    let updatedText = text.replacingCharacters(in: textRange, with: string)
}
Copy the code
  1. checkupdatedTextWhether to include emoji, if so returnsfalse.

The complete code is as follows:

func textField(_ textField: UITextField.shouldChangeCharactersIn range: NSRange.replacementString string: String) -> Bool {
    if let text = textField.text,
       let textRange = Range(range, in: text) {
       let updatedText = text.replacingCharacters(in: textRange, with: string)
        if updatedText.containsEmoji {
            return false}}return true
}
Copy the code

The input box will no longer respond when the user tries to insert an emoji into a string. If you want to explicitly remind the user, you can add a pop-up with a prompt message.

Parse the emoji in the API response

If you’ve ever called the REST API from Swift, you’ve probably encountered this situation where you get the interface return value but lose the emoji. Conversions between String and JSON-compatible types, like Array and Dictionary, lose emojis.

The safest and most efficient way to do this is to take Data from the API and convert it to the type you want:

let str = String(data: data, encoding: .utf8)
Copy the code

The same goes for JSON. It is best to parse the returned data manually:

let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
Copy the code

Let’s try using the well-known Alamofire library to solve this example:

import Foundation
import Alamofire

class API {
    func loadEmojiString(url: URL.delegate: @escaping (_ str: String?). ->Void) {
        AF.request(url).responseData { (response) in
            switch response.result {
            case .success(let data):
                let str = String(bytes: data, encoding: .utf8)
                delegate(str)
                
            case .failure(let error):
                print(error)
                delegate(nil)}}}}Copy the code

Alamofire updates the code periodically, so it’s likely that it will return emoji strings in the responseString handler in the future. Alamofire probably already supports this at this point, but when I tried it, it returned a String that didn’t contain emoji. If you are using another request library, the above method also applies. Just remember that the response you get from a network request is a bunch of bytes. The closest thing to it in Swift is the Data object. It can be converted to other types of data. If you want to fully understand the conversion of Data, you must choose the Data type first.

MySQL and other SQL database notes

This isn’t about Swift, but we’ve already covered emoji in the API, so I’ll just say a few more words. If you plan to store emojis in an SQL database such as MySQL, you need to do two things:

  1. Sets the character set for the entire database, database table, or single field toutf8mb4. simpleutf8Cannot allow you to store emojis in string fields.
  2. Run before running other SQL requestsSET NAMES utf8mb4Command.

Emoji variable

I really appreciate the Apple guys’ sense of humor. You can name functions or variables in emoji.

For example, these are legal Swift statements:

let 🌸 = 1
let🌸 🌸= 2

func +(_🐶 :Int._🐮 :Int) -> Int{🐶+🐮}let🌸 🌸 🌸=+ (🌸 🌸 🌸)print(🌸 🌸 🌸)Copy the code

Never write code like this in a production environment — it’s hard to type, retrieve, or share. But it can also be useful, for example, when teaching kids to code. This code looks interesting, right?

A more common way to do this is to insert emojis in strings:

let errorText = "Sorry, something went wrong 😢"
Copy the code

conclusion

In most cases, apps should allow users to enter emojis. If you don’t want users to enter emoji, you can add restrictions. More and more user interfaces are using emoji.

Also, don’t use emojis in your source code unless you really need them. Swift allows you to do this, but it’s really not a good habit. Even if emoji are part of a constant string, it’s best to keep them in a separate file.

Happy coding, we will see you next time!

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.