The enumeration
Enumerated values are one of the most common types in our development process, and the actual type of an enumerated value in OC is NSInterge. In Swift, enumerations are given more and more flexible uses, and knowing how to use enumerations makes our code cleaner and more logical.
Swfit uses key subenums to declare an enumerated type.
enum OSCardType {
case OSCardTypeOne
case OSCardTypeTwo
case OSCardTypeThree
}
Copy the code
Enumerations in Swift are very flexible and do not need to provide a value for every member of the enumeration. If a value (called a “primitive” value) is to be supplied to each enumerator, the value can be a string, a character, an arbitrary integer value, or a floating-point type.
enum OSDeviceCode: String {
case OSDeviceCodeLight = "light"
case OSDeviceCodeAirConditioner = "airConditioner"
}
Copy the code
RawValue can also be inferred by the compiler, which builds on Swift’s type inference mechanism
enum OSDayOfWeek: Int {
case mon, tue, wed, thu, fri = 10, sat, sun
}
Copy the code
Mon = 0, ture = 1… Sat = 11, Sun = 12. If it is a String, rawValue defaults to an enumerated String.
The associated values
In addition to the above usage, enumerated values in Swift can carry more information to express more complex cases. Several associated values can be followed.
enum OSShape {
case circle(redious: Double)
case ractange(width: Double, height: Double)}Copy the code
When comparing patterns, note that the case of the Swift enumeration value needs to match all enumeration types, otherwise the compiler will report an error. When patterns with associated values are matched, the associated values appear as parameters.
func func1(a) {
let cricle = OSShape.circle(redious: 10.0)
switch cricle {
case .circle(let circel):
print(circel)
case .ractange(let width, let height):
print(width, height)
}
}
Copy the code
Enumeration size of memory
Enumerations are value types that are stored on the stack. There are two storage types: no-payload enum and single-payload enum.
You can print to see the size of the enumeration.
func func2(a) {
print(MemoryLayout<OSCardType>.size)
var card1 = OSCardType.OSCardTypeOne
var card2 = OSCardType.OSCardTypeTwo
print(card1,card2)
}
Copy the code
Let’s move on to the size of memory with associated values.
enum SingleEnum1 {
case One(isgood: Bool)
case Two
case Three
}
enum SingleEnum2 {
case One(age: Int)
case Two
case Three
}
func func3(a) {
print(MemoryLayout<SingleEnum1>.size)
print(MemoryLayout<SingleEnum2>.size)
}
Copy the code
Output 1, 9
Note here: SingleEnum1 is memory optimized to save on memory costs. Bool is actually stored in 1BITE, and the rest of the bits are used to store enumeration information. There’s a lot of data on the web that says that the size of an enumeration is equal to the memory of the largest association type plus the memory of the enumeration value, except for Bool. Very easy to miss. The corresponding description can also be found in the source code.
If the storage space is sufficient for the associated values, the load size is the same as the enumeration values.
Indeirect keyword
Analysis: the size of the value type is determined at compile time, and the above “nesting” method does not determine the memory size. We use the compiler’s modification method.
indirect enum BinaryTree<T> {
case empty
case node(left: BinaryTree, right: BinaryTree, value: T)}Copy the code
func func4(a) {
var node = BinaryTree<Int>.node(left: BinaryTree<Int>.empty, right: BinaryTree<Int>.empty, value: 1)
print(node)
print(MemoryLayout<BinaryTree<Int>>.size)
print(MemoryLayout<BinaryTree<Int>>.stride)
}
Copy the code
Output bit 8 8, go ahead and print the address using LLDB.
This is when found when usedindirect
After the keyword modifier, the system allocates space in the heap for the enumeration.
An optional value
Optional values are ubiquitous throughout our SWIFT programming, designed primarily for security purposes. Optional values are also implemented through enumerations.
class InFuncRoom {
var roomId: String?
}
Copy the code
You can also write:
class InFuncRoom {
// var roomId: String?
var roomId: Optional<String> = nil
}
Copy the code
Click Optional to see the implementationObviously the optional value is an enumeration.
Take an example of using something like this to experience the use of optional values.
Title: Remove all even numbers from an array.
// Implement the optional values yourself
func func6(a) {
var array = [1.2.3.4.5.6]
for value in array {
let optional = getOddValue(value)
switch optional {
case .some(let ele):
array.remove(at: array.firstIndex(of: ele)!)
print(ele)
default:
print("not exit")}}print(array);
}
func getOddValue(_ value: Int) -> MyOptional<Int> {
if value % 2 = = 0 {
return .some(value)
} else {
return .none
}
}
Copy the code
Unpack the
If we use a switch case for each of the optional values, which would be tedious to write, we can use an if let to bind the optional values (unpack).
func func7(a) {
var name: String? = "hahaha"
if let name = name {
print(name)
}
name = nil
if let name = name {
print(name)
}
}
Copy the code
In addition to using the if let to handle optional values, we can also use the Gurad let to simplify our code. Let’s look at a specific example.
The guard let is the opposite of the if let. The guard let guard must have a value. If not, return directly. If you use an if let to create a branch layer out of thin air, guard lets are a way to lower the branch level
Operator overloading
struct Vector {
let x: Int
let y: Int
}
extension Vector {
static func + (fistVector: Vector.secondVector: Vector) -> Vector {
return Vector(x: fistVector.x + secondVector.x, y: fistVector.y + secondVector.y)
}
static prefix func - (vector: Vector) -> Vector {
return Vector(x: -vector.x, y: -vector.y)
}
static func - (fistVector: Vector.secondVector: Vector) -> Vector {
return fistVector + -secondVector
}
}
Copy the code
func func6(a) {
let x = Vector(x: 10, y: 20)
let y = Vector(x: 80, y: 50)
let z = x + y
print(z)
}
Copy the code