preface
In the Objective-C world, all objects are Pointers. It’s a runtime language, and the object type of the specific pointer will be assigned by the system at runtime. It’s free, but it’s not safe.
The Swift world, by contrast, is secure (at least most of the time). We don’t have to worry about the type of object runtime, which Is Swift’s fortress for us. But at times, this fortress also becomes an operation that constrains our behavior.
The body of the
Swift also provides support for the unsafe behavior of manipulating Pointers.
MemoryLayout
MemoryLayout is an enumeration defined by Swift for structures such as structs that need to get the size of a specific memory space.
It contains a series of methods that make it easier to use.
There are three main attributes:
/// The actual memory size of the instance of the corresponding type
public static var size: Int { get }
// The size of bytes used by the instance of the corresponding type after memory alignment (please refer to Baidu Encyclopedia for memory alignment, links will be given below)
public static var stride: Int { get }
/// Default memory alignment unit
public static var alignment: Int { get }
Copy the code
Baidu Encyclopedia: baike.baidu.com/item/ Memory alignment /9…
These three properties are also commonly used, along with three methods obtained from instance objects
Playgroud introduces the code
struct Test {
let res1: Bool = false
let res2: Int = 0
let res3: Bool = false
}
print("\(MemoryLayout<Test>.stride)") / / 24
Copy the code
Since this class is not the first one we will cover, we will only cover it in general
Pointer to the memory
Pointer definition:
In computer science, a Pointer is an object in a programming language that, by means of an address, points directly to a value stored in another part of the computer’s memory. Since the desired variable unit can be found through the address, it can be said that the address refers to the variable unit. Therefore, the address visualization is called “pointer”. This means that it can find the memory location with its address.
Excerpt from Baidu Encyclopedia: baike.baidu.com/item/ pointer /287…
In Swift, all pointer-related operations are considered Unsafe, so all pointer-related structures contain the prefix Unsafe
There are eight structures in Swift
Swift | Objective-c | describe |
---|---|---|
UnsafePointer<T> |
const T * |
Pointers and the contents of memory to which they point are immutable |
UnsafeMutablePointer<T> |
T * |
Pointers and the contents of memory to which they point are mutable |
UnsafeBufferPointer<T> |
const T * [] |
Is an array of Pointers whose contents are immutable |
UnsafeMutableBufferPointer<T> |
T * [] |
|
UnsafeRawPointer |
const void * |
|
UnsafeMutableRawPointer |
void * |
|
UnsafeBufferRawPointer |
void * [] |
How does an instance class object get converted to a pointer
UnsafePointer
struct Obj {
var name: Int = 5
}
var obj = Obj()
let pointer = withUnsafePointer(to: &obj, {$0})
print("\(pointer.pointee)")
Copy the code
Note that unsafePointer. pointee only has a get method, that is, we get a let object, which complies with let requirements.
Note: Let and var are different here
Let and var are both prefixes used by Swift to declare variables. In the program, when we declare variables, in the real runtime environment, the program initializes the corresponding memory for the variables we declare.
The memory contents of the variables declared by the LET are not mutable after the declaration is initialized
The memory contents of variables declared by var can be modified at any time later.
Here we are using the memory contents, which are the values of 0 and 1 in the abstract memory address.
The difference between class let and var is that the variable can be assigned to a new class object without changing the storage properties of the original object. This is because the stack memory contents of class objects at the time of declaration are only 8 bytes (which we can retrieve using MemoryLayout), and the real objects are stored elsewhere. So we can change the value that let points to
For structs, the difference between let and var is that we cannot directly modify the value of the object created by let, regardless of whether the property is let or var. Only var modifiers can be modified. This is because struct objects are stored directly in the memory contents of the declaration.
For UnsafeMutablePointer, pointee is the set and get method, that is, we can change the value of the memory address directly.
How to get UnsafeMutablePointer and modify the related value
struct Obj {
var name: Int = 5
init(name: Int = 5) {
self.name = name
}
}
var obj = Obj()
let pointer = withUnsafeMutablePointer(to: &obj, {$0})
print("Obj: \(obj)")
pointer.pointee = Obj(name: 10)
print("\(pointer.pointee)")
print("Obj: \(obj)")
Copy the code
When we run this code, we can see that the contents of obj also change with the pointer.
Note: Obj can only use the var declaration, because the Unsafe class calls require & and may change the memory contents, so the let definition does not meet the requirements.
The next thing I want to talk about is the Swift equivalent of the C void star pointer UnsafeRawPointer
In apple’s official documentation, UnsafeRawPointer is defined as
A raw pointer for accessing untyped data.
A pointer to access an undefined type
Overview
The UnsafeRawPointer type provides no automated memory management, no type safety, and no alignment guarantees. You are responsible for handling the life cycle of any memory you work with through unsafe pointers, to avoid leaks or undefined behavior.
UnsafeRawPointer provides no automatic memory management, no type-safety, and memory alignment control guarantees. You are obligated to manage the declaration cycle of any memory you reference through Pointers to avoid memory leaks or other undefined (unsafe) behavior
Memory that you manually manage can be either untyped or bound to a specific type. You use the UnsafeRawPointer type to access and manage raw bytes in memory, whether or not that memory has been bound to a specific type.
The memory you manually manage can be undefined or defined to a specified type. You can use UnsafeRawPointer to access and manage undefined bytes of memory, regardless of whether the memory is already bound to a specified type.
The official definition is this, and the general idea is that if you need to manage memory yourself, use this class. Usually we’re working on some underlying code that needs to be passed in as a parameter.
Code examples:
var i = 2
let pointerRaw = withUnsafeBytes(of: &i, {$0})
guard let pointer = pointerRaw.bindMemory(to: Int.self).baseAddress else { fatalError("This code theoretically can't execute up here.")}let j = pointer.pointee
print("j:\(j)")
Copy the code
This is an example of converting rawPointer and pointer. What’s left is bufferPointer, which I won’t go into because there are fewer places to use it.
conclusion
The most important operations in pointer correlation are the generation of Pointers and the conversion of Pointers to instance objects. Important among these are pointee and several global functions withUnsafeXX.
In Swift, the world of Pointers is not complicated, and all pointer operations can be converted into eight UnsafeXX classes. Our use is also based on this, if we use some low-level methods need Pointers, this time only need to generate the corresponding pointer object can be passed.
At the end
A twinkling of an eye has been New Year’s day, during the period also wanted to write some articles, but nothing to write feel confused. Meanwhile, I have been learning Swift related languages during this period. Since socket operations will be used in my personal project, I decided to rewrite GCDAsyncSocket with Swift. Having encountered many similar problems with Pointers during the rewrite, I decided to write a tutorial on Pointers.
Swift socket library SwiftAsyncSocket is currently being improved, and the basic functions of TCP/IP protocol have been basically improved. It will be open source soon
This article was first published in my blog and public account (see the picture below), if you want to reprint to the public account, please contact me to open permission.
Finally, I wish you all a happy And successful New Year