[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fg1w4F-NfsVPdFk1tjpPRJ6Yb8lY3JwL9TvlSTvnMJO0":3},{"code":4,"message":5,"data":6},200,"成功",{"id":7,"createdAt":8,"title":9,"content":10,"summary":11,"image":12,"uid":13,"user":14,"categoryId":21,"category":22,"subCategoryId":24,"subCategory":25,"comments":27,"status":17,"reason":28,"notice":28,"visitCount":29,"commentCount":30,"keywords":31},105,"2024-03-27T14:44:09.847Z","Swift知识一览（三）","## 一、枚举的内存布局\n### 1.1 内存分配\n从上一章内容《Swift知识一览（二）》[https://www.xinwei.ltd/article/103](https://www.xinwei.ltd/article/103) 中，我们知道可以通过`MemoryLayout`来查看枚举类型所占的字节数。如下例子：\n```swift\nenum Direction {\n    case east, south, west, north\n}\n// 打印该枚举类型所占内存\nprint(MemoryLayout.size(ofValue: Direction.east)) // 1，解释：1个字节可以存储该枚举类型\n\n// 上述枚举类型，在实际的内存存储中，从east开始存储0，1，2，3\n```\n\n- 原始值不影响枚举类型的内存存储大小的。\n\n每一个枚举成员都共用1个字节，其实针对上面的枚举案例或者有原始值的枚举，针对每一个case的枚举变量，存储的都是0、1、2、3这样的排序数字。原始值类型枚举不影响枚举成员内存大小。\n\n- 关联值，内存大小是最长的那个关联case长度 + 1字节的case识别。其他case枚举成员都共用关联类型最长的那个枚举成员的内存空间。\n\n举例如下：\n```swift\nenum CustomNumber {\n    case one(Int, Int, Int)\n    case two(Int, Int)\n    case three(Int)\n    case four(Bool)\n    case other\n}\n\n// 类似上面这种枚举，内存是：\nsize: 3 * 8 + 1 = 25 // 因为最大关联类型的参数最多有3个，足够存储其他关联类型。1是用来表示存储第几个case\n// 查看内存分布的时候，可以看到1字节中存储的是从对应于枚举成员排序的0、1、2、3、4这几个值\nalignment: 8\nstride: 32\n\n// 只有1个关联类型参数的情况\nenum CustomEnum {\n    case one(Int)\n}\n// size、stride、aligment应该都是8（64位平台）。无须存储识别case枚举成员的那1个字节。\n```\n\n\n### 1.2 Swift中获取变量内存地址\n使用`withUnsafePointer`来获取变量内存地址。\n函数定义：\n```swift\n/// Invokes the given closure with a pointer to the given argument.\n///\n/// The `withUnsafePointer(to:_:)` function is useful for calling Objective-C\n/// APIs that take in parameters by const pointer.\n///\n/// The pointer argument to `body` is valid only during the execution of\n/// `withUnsafePointer(to:_:)`. Do not store or return the pointer for later\n/// use.\n///\n/// - Parameters:\n///   - value: An instance to temporarily use via pointer. Note that the `inout`\n///     exclusivity rules mean that, like any other `inout` argument, `value`\n///     cannot be directly accessed by other code for the duration of `body`.\n///     Access must only occur through the pointer argument to `body` until\n///     `body` returns.\n///   - body: A closure that takes a pointer to `value` as its sole argument. If\n///     the closure has a return value, that value is also used as the return\n///     value of the `withUnsafePointer(to:_:)` function. The pointer argument\n///     is valid only for the duration of the function's execution.\n///     It is undefined behavior to try to mutate through the pointer argument\n///     by converting it to `UnsafeMutablePointer` or any other mutable pointer\n///     type. If you need to mutate the argument through the pointer, use\n///     `withUnsafeMutablePointer(to:_:)` instead.\n/// - Returns: The return value, if any, of the `body` closure.\n@inlinable public func withUnsafePointer\u003CT, Result>(to value: inout T, _ body: (UnsafePointer\u003CT>) throws -> Result) rethrows -> Result\n```\n\n使用：\n```swift\nvar dir = Direction.east\n\nlet result = withUnsafePointer(to: &dir) { address in\n    return address\n}\nprint(\"--0--dir内存地址--\\(result)\")\n```\n\n### 1.3 枚举内存分配汇编举证\n- 第一步，如下图所示，红色框内是枚举，按照图中设置断点。通过`withUnsafePointer`获取变量dir的内存地址，然后右键控制台左侧的dir变量，点击View Memory。\n![查看swift中枚举内存1.jpg](https://image.xinwei.ltd/11711550417432.jpg)\n\n- 第二步，如下图所示，会显示内存查看界面，但是在第1步点击后进来时，Address输入框是空值，Xcode没有允许我们访问枚举变量的内存地址。所以我们需要输入控制台打印出来的内存地址，才能查看内存。\n![查看swift中枚举内存2.jpg](https://image.xinwei.ltd/21711550448468.jpg)\n\n- 第三步，进入下一个断点，查看给dir赋值.south这个枚举成员后，dir会存储什么值。（按照1.1中的解释，应该存储1）\n![查看swift中枚举内存3.jpg](https://image.xinwei.ltd/31711550485510.jpg)\n\n同样跟第二步一样，查看View Memory。这一步可以验证，dir此时存储的是1.\n![查看swift中枚举内存4.jpg](https://image.xinwei.ltd/41711550512792.jpg)\n\n- 第四步，重复第三步的操作，进入到下一个断点。这个时候，dir被赋值了枚举成员west。按照1.1中的解释，此时dir中应该存储的是2.\n![查看swift中枚举内存5.jpg](https://image.xinwei.ltd/51711550552985.jpg)\n![查看swift中枚举内存6.jpg](https://image.xinwei.ltd/61711550571597.jpg)\n\n这是《Swift知识一览》系列的第三篇文章，若感兴趣，请关注后续发表的文章。\n\n\n\n\n\n\n","这篇文章是《Swift知识一览》的第三篇文章。该篇文章主要介绍Swift的枚举的内存分配，通过LLDB和汇编的相关知识去分析枚举的内存情况，附上操作截图，可以让大家自行动手去了解枚举的内存知识。最近有点忙，更新的有点慢。","https://image.xinwei.ltd/11711550417432.jpg",499668042977349,{"phone":15,"userId":13,"nickName":16,"vipType":17,"avatar":18,"sign":19,"createdAt":20},"13121171998","全栈老韩",1,"https://image.xinwei.ltd/images/IMG_5430.JPG","全栈工程师，擅长iOS App开发、前端（vue、react、nuxt、小程序&Taro）开发、Flutter、React Native、后端（midwayjs、golang、express、koa）开发、docker容器、seo优化等。","2024-01-01T16:14:30.305Z",2,{"id":21,"name":23},"IT技术",3,{"id":24,"name":26,"parentId":21},"iOS",[],"",259,0,"swift,swift开发,swift article,swift ios"]