Skip to content

String

The Structure of String

Even though the String type is technically a struct, it can exist in many forms.

String-Structure

  1. An opaque string is capable of handling all string operations through resilient function calls. Currently, these are used for lazily-bridged NSString that do not provide access to contiguous UTF-8 bytes in memory.
  2. All other strings are contiguous, that is, they can provide a pointer and length to valid UTF-8 bytes in memory.
    1. An indirect string is capable of providing a pointer to validly-encoded UTF-8 bytes in memory through a resilient function. Currencly, indirect strings are used for NSStrings that can provide access to contiguous UTF-8 in memory.
    2. Other contiguous strings are immediate, which means they are in Swift's prefered form for the most efficient and direct access.
      1. A small string packs its contents (up to 15 UTF-8 code units in length) directly in the String struct, without the need for a separate location.
      2. A Large string holds a reference to a class instance with tail-allocated contents at a statically known offset from the instance's address. This means there is no additional indirection on top of the reference itself.

Bridging Between String and NSString

String is a struct and NSString is a class.

swift
@frozen
struct String
swift
class NSString : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
    ...
}

String and NSString instances can be bridged to each other using as operator.

Any String instance that originates in Objective-C may use an NSString instance as its storage.

Because NSString is immutable, it is just as though the storage was shared by a copy. The first in any sequence of mutating operations causes elements to be copied into unique, contiguous storage which may cost O(n) time and space.

swift
let string = "Hello World"
print(type(of: string))            //"String"
let nsString = string as NSString
print(type(of: nsString))          //"__StringStorage"
swift
let nsString: NSString = "Hello World"
print(type(of: nsString))         //"__NSCFString"
let string = nsString as String
print(type(of: string))           //"String"

Convert String to Number

In swift, number types are all struct.

swift
@frozen
struct Int
swift
@frozen
struct Float
swift
@frozen
struct Double
swift
struct Decimal

Convert a String into an Int, Int8, Int16, Int32, and Int64

The Swift type Int, and related Int8, Int16, Int32, and Int64, contain a constructor that takes in a String argument and return an optional parsed value.

swift
// Convert String to Int
let strInt = "10"
let int = Int(strInt)
let int8 = Int8(strInt)
let int16 = Int16(strInt)
let int32 = Int32(strInt)
let int64 = Int64(strInt)

let invalidStrInt = "hello"
let invalidInt = Int(invalidStrInt) // nil

Convert a String into a UInt, UInt8, UInt16, UInt32, and UInt64

Just like Int, the Swift type UInt, and related UInt8, UInt16, UInt32, and UInt64, contain a constructor that takes in a String argument and return an optional parsed value.

swift
// Convert String to UInt
let strUInt = "10"
let uint = UInt(strUInt)
let uint8 = UInt8(strUInt)
let uint16 = UInt16(strUInt)
let uint32 = UInt32(strUInt)
let uint64 = UInt64(strUInt)

let strNegativeUInt = "-10"
let negtiveUInt = UInt(strNegativeUInt) // nil

let invalidStrUInt = "hello"
let invalidUInt = UInt(invalidStrUInt) // nil

Convert a String into a Float, Double

Swift type Float and Double contain a constructor that takes in a String argument and return an optional parsed value.

swift
// Convert a String to Double,Float
let strfloat = "3.14"
let strdouble = "3.1415926"
let stroutdouble = "3.14159265358979323846"
let invalidStrFloat = "hello"

let float1 = Float(strfloat)                // "3.14" -> 3.14 
let float2 = Float(strdouble)               // "3.1415926" -> 3.141593
let float3 = Float(stroutdouble)            // "3.14159265358979323846" -> 3.141593
let float4 = Float(invalidStrFloat)         // "hello" -> nil

let double1 = Double(strfloat)              // "3.14" -> 3.14 
let double2 = Double(strdouble)             // "3.1415926" -> 3.1415926
let double3 = Double(stroutdouble)          // "3.14159265358979323846" -> 3.141592653589793
let double4 = Double(invalidStrFloat)       // "hello" -> nil

References