Recently, a character caused a Crash, because the actual business scenario is not easy to describe, here is a test code to illustrate.

Without further ado, go directly to the code:

let testCharacters: Set<Character> = ["!"."\""."$"."%"."&"."'"."+".","."<"."=".">"."@"."["."]"."`"."{"."}"]

let testString = "@ ` Hello World `!"

var result: UInt8 = 0

for character in testString {
    if testCharacters.contains(character) {
	result + = character.asciiValue!}}Copy the code

The above code does this by taking the ASCII characters from testString and adding them up.

Let’s Review this code. Experienced students should immediately smell the bad smell in the code: character.asciiValue! I’m using a strong solution here.

Does the strong solution make sense here? Since any character defined in testCharacters must have an ASCII code, at first glance it is ok to use strong solutions here.

But if we actually run it, we’re going to Crash a strong solution because asciiValue is nil. Why is that?

The key is that testString contains full-corner characters. The last ‘in testString is a full-corner character that has no asciiValue.

We can find the answer by executing the following code in Swift Playgrounds:

let halfWidth = "`"

halfWidth.lengthOfBytes(using: .utf8) / / 1

halfWidth.first!.isASCII // true

halfWidth.first!.asciiValue / / 96


let fullWidth = "`"

fullWidth.lengthOfBytes(using: .utf8) / / 3

fullWidth.first!.isASCII // false

fullWidth.first!.asciiValue // nil

// Character Implements the Equatable protocol and determines that two values are equal.
halfWidth = = fullWidth // true
Copy the code

As can be seen from the above code execution result, the halfWidth character is one byte long, the corresponding ASCII code is 96 and the fullWidth character is three bytes long, and its asciiValue is empty.

The contains method in the Swift array uses the Equatable protocol. HalfWidth == fullWidth = true The Equatable protocol implemented by Character does not take into account Character full/half corner cases.

The contains method results in true, which also affects our judgment, thinking that this strong solution is OK. If we do not pay attention to it, we will cause Crash.

Finally, a history of full corner/half corner from Wikipedia:

In early computers, English or Latin alphabet languages used systems that used one byte of space (eight bits, 256 coding Spaces) for each letter or symbol. However, Chinese, Japanese and Korean characters, because the number of characters is much more than 256, it is customary to use two bytes to store a character. So this is originally a “single byte” or “double byte” problem at the encoding level.

When computers at that time used the same width fonts (such as DOS, some text editors, etc.), the font also adapted to this encoding form, drawing the width of The Chinese, Japanese and Korean characters to twice the width of the Latin letters and numbers, so that the character encoding storage and display width can be matched one by one:

  • Single-byte textTo displayAnd a half wide.
  • Double-byte textTo displayFull width.

At that time, users began to call Chinese, Japanese and Korean characters full corner characters and Latin letters or numbers half corner characters.

But since then, the way computers encode words has changed so much that it can take one, two, four or more bytes to store a character. Even if an English character is displayed at half width, depending on the encoding method, it is not necessarily stored in one byte.

Therefore, there is no one-to-one correspondence between the character encoding storage and the character display width.

But because of the relationship between character encoding and font width, many users have habitually used the term “full/half corner”.

So today’s full corner probably means:

  • A character stored in two bytes
  • All characters except ASCII (so called half corner English and numbers)
  • Displays a font with a font width of one to one square.