当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Swift MemoryLayout offset(of:)用法及代码示例


类型方法

offset(of:)

返回类型的内存表示中内联存储属性的偏移量。

声明

static func offset(of key: PartialKeyPath<T>) -> Int?

返回值

从指向类型为 T 的值的指针到指向由 key 引用的存储的指针的偏移量(以字节为单位),如果没有这样的偏移量可用于由 key 引用的存储,则为 nil。如果值为 nil ,则可能是因为 key 已计算、具有观察者、需要重新抽象或与其他属性重叠存储。

参数

key

引用存储的键路径,可以通过 T 类型的值访问。

详述

您可以使用此方法查找可以添加到类型 T 的指针的字节距离,以获取指向 key 引用的属性的指针。仅当给定键引用 T 的内存表示中的内联、直接可寻址存储时,偏移量才可用。

如果此方法的返回值不是 nil ,则通过键路径或偏移指针访问该值是等效的。例如,对于类型为 T 的变量 root 、类型为 WritableKeyPath<T, U> 的键路径 key 和类型为 Uvalue


// Mutation through the key path
root[keyPath: key] = value


// Mutation through the offset pointer
withUnsafeMutableBytes(of: &root) { bytes in
    let offset = MemoryLayout<T>.offset(of: key)!
    let rawPointerToValue = bytes.baseAddress! + offset
    let pointerToValue = rawPointerToValue.assumingMemoryBound(to: U.self)
    pointerToValue.pointee = value
}

当一个属性是一个存储属性,不需要额外的工作来提取或设置值时,它就具有内联、可直接寻址的存储。如果属性触发任何 didSetwillSet 访问器、执行任何表示更改(例如桥接或闭包重新抽象)或将值从重叠存储中屏蔽(如打包位域),则无法直接访问这些属性。此外,由于类实例属性始终存储 out-of-line,因此无法使用 offset(of:) 访问它们的位置。

例如,在此处定义的 ProductCategory 类型中,只有 \.updateCounter\.identifier\.identifier.name 指的是具有内联、可直接寻址存储的属性:


struct ProductCategory {
    struct Identifier {
        var name: String              // addressable
    }


    var identifier: Identifier        // addressable
    var updateCounter: Int            // addressable
    var products: [Product] {         // not addressable: didSet handler
        didSet { updateCounter += 1 }
    }
    var productCount: Int {           // not addressable: computed property
        return products.count
    }
}

offset(of:) 与从库中导入的类型一起使用时,不要假设该库的未来版本将具有相同的行为。如果属性从存储属性转换为计算属性,则 offset(of:) 的结果将更改为 nil 。这种转换在其他情况下是不间断的,但如果offset(of:) 的结果是force-unwrapped,则会触发运行时错误。

可用版本

iOS 8.0+, iPadOS 8.0+, macOS 10.10+, Mac Catalyst 13.0+, tvOS 9.0+, watchOS 2.0+

相关用法


注:本文由纯净天空筛选整理自apple.com大神的英文原创作品 MemoryLayout offset(of:)。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。