├── SwiftDemo ├── SwiftDemo │ └── main.swift └── SwiftDemo.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── jintao.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ ├── xcuserdata │ └── jintao.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── xcshareddata │ └── xcschemes │ │ └── SwiftDemo.xcscheme │ └── project.pbxproj ├── Swift ├── Struct.swift ├── Tuple.swift ├── Enum.swift ├── Protocol.swift └── Class.swift ├── SwiftCore ├── Bool.swift ├── Character.swift ├── Optional.swift ├── Array.swift ├── Set.swift ├── Dictionary.swift └── String.swift └── README.md /SwiftDemo/SwiftDemo/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // SwiftDemo 4 | // 5 | // Created by jintao on 2019/8/7. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftDemo/SwiftDemo.xcodeproj/xcuserdata/jintao.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/xcuserdata/jintao.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TannerJin/Swift-MemoryLayout/HEAD/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/xcuserdata/jintao.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Swift/Struct.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Struct.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/8/7. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // struct StructValue { (for memory alignment) 12 | // let a: Int8 = 4 | 13 | // let b: Int16 = 6 ==> 04 00 06 00 08 00 00 00 14 | // let c: Int32 = 8 | \ / \ / 15 | // } a b c 16 | 17 | 18 | // FYI: if you want to get the offset of each property at runtime, you can see https://github.com/apple/swift/blob/master/docs/ABI/TypeMetadata.rst 19 | -------------------------------------------------------------------------------- /SwiftDemo/SwiftDemo.xcodeproj/xcuserdata/jintao.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A947488F22FACE8F00212E57 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftCore/Bool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Bool.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/8/1. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Bool { 12 | // struct Bool 13 | // +-----------------------------------------------------------------------+ 14 | // | var _value: Int8 1: true ; others: false | 15 | // +-----------------------------------------------------------------------+ 16 | 17 | var valuePointer: UnsafeMutablePointer { 18 | mutating get { 19 | return withUnsafePointer(to: &self) { (pointer) -> UnsafeMutablePointer in 20 | UnsafeMutablePointer(OpaquePointer(pointer)) 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Swift/Tuple.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tuple.swift 3 | // SwiftDemo 4 | // 5 | // Created by jintao on 2019/8/13. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // typealias TupleValue = (Int8, Int16, Int32) 12 | // ∧ \ 13 | // | \ 14 | // | same layout | 15 | // | | 16 | // V V 17 | // 18 | // struct StructValue { 04 00 06 00 08 00 00 00 19 | // let a: Int8 = 4 | | \ / \ / 20 | // let b: Int16 = 6 -----> a | b c 21 | // let c: Int32 = 8 V 22 | // } (for memory alignment) 23 | -------------------------------------------------------------------------------- /SwiftCore/Character.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Character.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/8/1. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Character { 12 | // struct Character 13 | // +-----------------------------------------------------------------------+ 14 | // | var _str: String unicode | 15 | // +-----------------------------------------------------------------------+ 16 | 17 | // UTF-8 => use 1 ~ 4 bytes (one can byte compatible ASCII, 0x00...0x7F) 18 | // / 19 | // unicode - UTF-16 => use 2/4 bytes 20 | // \ 21 | // UTF-32 => use 4 bytes 22 | 23 | var valuePointer: UnsafeMutableRawPointer { 24 | mutating get { 25 | // unicode.bytes.count <= 15 26 | return withUnsafePointer(to: &self) { UnsafeMutableRawPointer(mutating: $0) } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SwiftCore/Optional.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Optional.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/8/1. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Optional { 12 | // enum Optional 13 | // +-----------------------------------------------------------------------+ 14 | // | case none | 15 | // | case some(Wrapped) | 16 | // +-----------------------------------------------------------------------+ 17 | 18 | // Optional.bytes count => 1 + Wrapped.bytes count 19 | 20 | // longjmp to Enum.Swift 21 | // Int8? = nil : Optional.none => 00 01 00 => self at all not associated enum's value ; 01 => all associated enum count 22 | // Int8? = 4 : Optional.some => 04 00 04 => associated value ; 00 => self at all associated enum's value 23 | 24 | var valuePointer: UnsafeMutableRawPointer { 25 | mutating get { 26 | return withUnsafePointer(to: &self) { UnsafeMutableRawPointer(mutating: $0) } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Swift/Enum.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Enum.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/8/6. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // enum EnumValue { => 1 byte 12 | // case a 0x00 13 | // case b 0x01 14 | // case c 0x02 15 | // case d 0x03 16 | // } 17 | 18 | 19 | // enum EnumValue: String { => 1 byte 20 | // case a = "a" 0x00 21 | // case b 0x01 22 | // case c 0x02 23 | // case d = "d" 0x03 24 | // } 25 | 26 | 27 | // enum EnumValue { => 17 bytes(ingore memory align) 28 | // case a enum's size + max association's type of enum = 1 + 16(String) 29 | // case b(String) 30 | // case c(Int32) 31 | // case d 32 | // case f(Int64) 33 | // case e 34 | // } 35 | // | 36 | // | 37 | // V 38 | // +----------------------------------------+ -- 39 | // | case a 00 count | \ 40 | // | case d 01 count | offset(1 byte) + all count of enums with association(b, c, f; count = 3) 41 | // | case e 02 count | / 42 | // | | 43 | // | case b(String) string 00 | \ 44 | // | case c(Int32) Int32 01 | association's value(16 bytes) + offset(1 byte) 45 | // | case f(Int64) Int64 02 | / 46 | // +----------------------------------------+ -- 47 | -------------------------------------------------------------------------------- /SwiftCore/Array.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Array.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/7/31. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Array { 12 | // struct Array 13 | // +--------------------------------------------------------------------+ 14 | // | struct _ArrayBuffer (_ContiguousArrayBuffer) | 15 | // +----/----------------------------------------|----------------------+ 16 | // / / 17 | // |(objc) |(nonobjc) 18 | // V V 19 | // class __ContiguousArrayStorageBase (_ContiguousArrayStorage) 20 | // +-----------------------------------------------------------------------+ 21 | // | var isa: UnsafeMutableRawPointer | 22 | // | var refcount: Int | 23 | // | var countAndCapacity: _ArrayBody | 24 | // +------------------------------|----------------------------------------+ 25 | // / 26 | // | 27 | // V 28 | // struct _ArrayBody 29 | // +-----------------------------------------------------------------------+ 30 | // | struct _SwiftArrayBodyStorage | 31 | // | +--------------------------------------------------------------+ | 32 | // | | var count: Int // 16 bytes offset | | 33 | // | | var _capacityAndFlags: Int | | 34 | // | | var sequence: [Element] // 32 bytes offset | | 35 | // | +--------------------------------------------------------------+ | 36 | // +-----------------------------------------------------------------------+ 37 | 38 | // count address 39 | var countPointer: UnsafeMutablePointer { 40 | get { 41 | let pointer = unsafeBitCast(self, to: UnsafeMutableRawPointer.self).advanced(by: 16) 42 | return pointer.assumingMemoryBound(to: Int.self) 43 | } 44 | } 45 | 46 | // sequence address 47 | var valuePointer: UnsafeMutablePointer { 48 | get { 49 | let pointer = unsafeBitCast(self, to: UnsafeMutableRawPointer.self).advanced(by: 32) 50 | return pointer.assumingMemoryBound(to: Element.self) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /SwiftCore/Set.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Set.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/8/1. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Set { 12 | // struct Set Element: Hashable 13 | // +------------------------------------------------+ 14 | // | struct Set._Variant | 15 | // | +------------------------------------------+ | 16 | // | | var objc: __RawSetStorage | | 17 | // | +--------------|---------------------------+ | 18 | // +-----------------/------------------------------+ 19 | // | 20 | // | 21 | // V 22 | // class __RawSetStorage 23 | // +-----------------------------------------------------------------------+ 24 | // | var isa: UnsafeMutableRawPointer | 25 | // | var refcount: Int | 26 | // | var _count: Int // 16 byte offset | 27 | // | var _capacity: Int | 28 | // | var _scale: Int8 | 29 | // | var _reservedScale: Int8 | 30 | // | var _extra: Int16 | 31 | // | var _age: Int32 | 32 | // | var _seed: Int | 33 | // | var _rawElements: UnsafeMutableRawPointer // 48 byte offset | 34 | // | var _bucketCount: Int | 35 | // | var _metadata: UnsafeMutablePointer<_HashTable.Word> | 36 | // | var _hashTable: _HashTable | 37 | // +-----------------------------------------------------------------------+ 38 | 39 | // count value of address 40 | var countPointer: UnsafeMutablePointer { 41 | get { 42 | return unsafeBitCast(self, to: UnsafeMutableRawPointer.self).advanced(by: 16).assumingMemoryBound(to: Int.self) 43 | } 44 | } 45 | 46 | // array of values address 47 | var valuesPointer: UnsafeMutablePointer { 48 | get { 49 | let valuesAddrValue = unsafeBitCast(self, to: UnsafeMutableRawPointer.self).advanced(by: 48).assumingMemoryBound(to: Int.self).pointee 50 | return UnsafeMutableRawPointer(bitPattern: valuesAddrValue)!.assumingMemoryBound(to: Element.self) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Swift/Protocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Protocol.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/8/6. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // protocol 12 | // +-----------------------------------------------------------------------+ 13 | // | var payload_data_0 8 bytes | -- 14 | // | var payload_data_1 8 bytes | payload_data => 24 bytes store instance_type's data 15 | // | var payload_data_2 8 bytes | -- | 16 | // | --------------------------------------------------- | | 17 | // | var instance_type: Any.Type 8 bytes | | 18 | // | var witness_table_protocol: UnsafeMutableRawPointer 8 bytes | | 19 | // +--------------|--------------------------------------------------------+ | 20 | // | | 21 | // V V 22 | // witness_table 23 | // +----------------------------------------+ if instance_type.size <= 24 { 24 | // | data: pointer | payload_data = instance 25 | // | protocol_method_0: void* | } else { 26 | // | protocol_method_1: void* | payload_data = instance* 27 | // | protocol_method_2: void* | } 28 | // | . | 29 | // | . | 30 | // +----------------------------------------+ 31 | // ∧ 32 | // | 33 | // +-------------------------------------------------------------+ 34 | // | 35 | // | 36 | // protocol: class | 37 | // +-----------------------------------------------------------------------+ | 38 | // | var instance: UnsafeMutableRawPointer | | 39 | // | var witness_table_protocol: UnsafeMutableRawPointer | | 40 | // +-------------|---------------------------------------------------------+ | 41 | // | | 42 | // +--------------------------------------------------------------+ 43 | -------------------------------------------------------------------------------- /SwiftDemo/SwiftDemo.xcodeproj/xcshareddata/xcschemes/SwiftDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /SwiftCore/Dictionary.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dictionary.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/7/31. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Dictionary { 12 | // struct Dictionary 13 | // +------------------------------------------------+ 14 | // | enum Dictionary._Variant | 15 | // | +--------------------------------------------+ | 16 | // | | [struct _NativeDictionary | | 17 | // | +---|----------------------------------------+ | 18 | // +----/-------------------------------------------+ 19 | // / 20 | // | 21 | // V 22 | // class __RawDictionaryStorage 23 | // +-----------------------------------------------------------------------+ 24 | // | var isa: UnsafeMutableRawPointer | 25 | // | var refcount: Int | 26 | // | var _count: Int // 16 byte offset | 27 | // | var _capacity: Int | 28 | // | var _scale: Int8 | 29 | // | var _reservedScale: Int8 | 30 | // | var _extra: Int16 | 31 | // | var _age: Int32 | 32 | // | var _seed: Int | 33 | // | var _rawKeys: UnsafeMutableRawPointer // 48 byte offset -----------------------+ 34 | // | var _rawValues: UnsafeMutableRawPointer // 56 byte offset -----------------------+---------------+ 35 | // | var _bucketCount: Int | | | 36 | // | var _metadata(get): UnsafeMutablePointer<_HashTable.Word> -----------------+ | | 37 | // | var _hashTable(get): _HashTable | | | | 38 | // +-----------------------------------------------------------------------+ | | | 39 | // | | | 40 | // | | | 41 | // | | | 42 | /* Dictionary | | | 43 | | | | | 44 | V | | | 45 | +-------------------------------------+ | | | 46 | | RawDictionaryStorage (MetaData) | | | | 47 | | | | | | 48 | +-------------------------------------+ <----------------------------------------------+ | | 49 | | Word (Hash Offset) | | | 50 | | | | | 51 | +-------------------------------------+ <----------------------------------------------------+ | 52 | | Keys | | 53 | | | | 54 | +-------------------------------------+ <--------------------------------------------------------------------+ 55 | | Values | 56 | | | 57 | +-------------------------------------+ 58 | 59 | Word (Hash Offset) 60 | | 61 | V 64(32) bits 62 | / \ 63 | if Word[0] = 0b1000000...0000000000100 => Keys[2] != nil and Keys[63] != nil 64 | if Word[1] = 0b1000000...0000000000101 => Keys[64] != nil and Keys[66] != nil and ... 65 | 66 | set: var bitOffset = hash(NewKey) & bucketCount 67 | when bitOffset of Word is occupied(bit is 1) { 68 | bitOffset += 1 69 | } 70 | 71 | set the bit of Word with bitOffset to 1 72 | Keys[bitOffset] = NewKey 73 | Values[bitOffset] = NewValue 74 | 75 | 76 | get: var bitOffset = hash(Key) & bucketCount 77 | when Keys[bitOffset] != Key { 78 | bitOffset += 1 79 | } 80 | return Values[bitOffset] 81 | */ 82 | 83 | 84 | 85 | // count value of address 86 | var countPointer: UnsafeMutablePointer { 87 | get { 88 | return unsafeBitCast(self, to: UnsafeMutableRawPointer.self).advanced(by: 16).assumingMemoryBound(to: Int.self) 89 | } 90 | } 91 | 92 | // array of keys address 93 | var keysPointer: UnsafeMutablePointer { 94 | get { 95 | let keysAddrValue = unsafeBitCast(self, to: UnsafeMutableRawPointer.self).advanced(by: 48).assumingMemoryBound(to: Int.self).pointee 96 | return UnsafeMutableRawPointer(bitPattern: keysAddrValue)!.assumingMemoryBound(to: Key.self) 97 | } 98 | } 99 | 100 | // array of values address 101 | var valuesPointer: UnsafeMutablePointer { 102 | get { 103 | let valuesAddrValue = unsafeBitCast(self, to: UnsafeMutableRawPointer.self).advanced(by: 56).assumingMemoryBound(to: Int.self).pointee 104 | return UnsafeMutableRawPointer(bitPattern: valuesAddrValue)!.assumingMemoryBound(to: Value.self) 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swift MemoryLayout 2 | 3 | **swift version =>: swift 5.0** 4 | 5 | - [Swift](#Swift) 6 | - [Struct](#Struct) 7 | - [Tuple](#Tuple) 8 | - [Class](#Class) 9 | - [Protocol](#Protocol) 10 | - [Enum](#Enum) 11 | - [SwiftCore](#SwiftCore) 12 | - [Bool](#Bool) 13 | - [Optional](#Optional) 14 | - [String](#String) 15 | - [Character](#Character) 16 | - [Array](#Array) 17 | - [Set](#Set) 18 | - [Dictionary](#Dictionary) 19 | 20 | 21 | ## Swift 22 | 23 | ### [Struct](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/Swift/Struct.swift) 24 | 25 | ```swift 26 | struct StructValue { 27 | let a: Int8 = 4 28 | let b: Int16 = 6 29 | let c: Int32 = 8 30 | } 31 | 32 | var structValue = StructValue() 33 | let structValuePointer = withUnsafePointer(to: &structValue) { UnsafeMutableRawPointer(mutating: $0) } 34 | structValuePointer.advanced(by: 2).assumingMemoryBound(to: Int16.self).initialize(to: 99) 35 | 36 | // structValue.b = 99 37 | ``` 38 | 39 | ### [Tuple](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/Swift/Tuple.swift) 40 | 41 | ```swift 42 | typealias TupleValue = (Int8, Int32, String) 43 | 44 | struct StructValue { 45 | var a: Int8 = 4 46 | var b: Int32 = 5 47 | var c: String = "SwiftTuple" 48 | } 49 | 50 | let structValue = StructValue() 51 | let tupleValue = unsafeBitCast(structValue, to: TupleValue.self) 52 | print(tupleValue.1) 53 | 54 | // print 5 (structValue.b) 55 | 56 | // if TupleValue = (Int8, Int8, String) => MemoryLayout of TupleValue != MemoryLayout of StructValue 57 | ``` 58 | 59 | ### [Class](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/Swift/Class.swift) 60 | 61 | ```swift 62 | class A { 63 | var a = 666 64 | } 65 | 66 | let a1 = A() 67 | unowned let unowned_a = a1 68 | let a2 = a1 69 | 70 | weak var weak_a = a1 71 | weak var weak_a2 = a1 72 | 73 | unowned let unowned_a2 = a1 74 | 75 | let a3 = a2 76 | let a4 = a2 77 | weak var weak_a3 = a1 78 | unowned let unowned_a3 = a1 79 | 80 | print(UnownedRefCount(a1)) 81 | print(WeakRefCount(a1)!) 82 | print(StrongRefCount(a2)) 83 | ``` 84 | 85 | ### [Protocol](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/Swift/Protocol.swift) 86 | 87 | ```swift 88 | // test with debug 89 | protocol SwiftProtocol { 90 | func foo() 91 | func foo2() 92 | } 93 | 94 | struct StructValue: SwiftProtocol { 95 | func foo() { 96 | print("foo") 97 | } 98 | 99 | func foo2() { 100 | print("foo2") 101 | } 102 | } 103 | 104 | var Protocol: SwiftProtocol = StructValue() 105 | let protocol_pointer = withUnsafePointer(to: &Protocol) { UnsafeMutableRawPointer(mutating: $0) } 106 | 107 | let witness_table_pointer_value = protocol_pointer.advanced(by: 32).assumingMemoryBound(to: UInt.self).pointee 108 | let witness_table_pointer = UnsafeMutablePointer.init(bitPattern: witness_table_pointer_value) 109 | 110 | typealias Foo2Method = @convention(thin) ()->Void 111 | 112 | let witness_foo2_pointer = unsafeBitCast(witness_table_pointer!.advanced(by: 2).pointee, to: Foo2Method.self) 113 | witness_foo2_pointer() 114 | 115 | // print foo2 116 | ``` 117 | 118 | ### [Enum](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/Swift/Enum.swift) 119 | 120 | ```swift 121 | enum EnumValue { 122 | case a 123 | case b(String) 124 | case c(Int32) 125 | case d 126 | case f(Int64) 127 | case e 128 | } 129 | 130 | var enumC = EnumValue.c(8) 131 | let enumCPointer = withUnsafePointer(to: &enumC) { UnsafeMutableRawPointer(mutating: $0) } 132 | enumCPointer.advanced(by: 16).assumingMemoryBound(to: Int8.self).initialize(to: 0x02) 133 | 134 | // enumC = EnumValue.f(8) 135 | ``` 136 | 137 | 138 | ## SwiftCore 139 | 140 | ### [Bool](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/SwiftCore/Bool.swift) 141 | 142 | ```swift 143 | var bool = true 144 | let boolPointer = bool.valuePointer 145 | boolPointer.initialize(to: -10) 146 | 147 | // bool = false 148 | ``` 149 | 150 | ### [Optional](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/SwiftCore/Optional.swift) 151 | 152 | ```swift 153 | var optional: Int16? // 0x00 0x00 0x01 154 | var optionalPointer = optional.valuePointer 155 | optionalPointer.assumingMemoryBound(to: Int16.self).initialize(to: 99) // 0x63 0x00 0x01 156 | optionalPointer.advanced(by: MemoryLayout.size).assumingMemoryBound(to: UInt8.self).initialize(to: 0x00) // 0x63 0x00 0x00 157 | 158 | // optional = 99 159 | ``` 160 | 161 | ### [String](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/SwiftCore/String.swift) 162 | 163 | ```swift 164 | var string = "TannerJin" 165 | let stringPointer = string.valuePointer 166 | stringPointer.assumingMemoryBound(to: Int8.self).initialize(to: 0x40) // 0x40 => "@" 167 | 168 | // string = "@anner Jin" 169 | ``` 170 | 171 | ### [Character](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/SwiftCore/Character.swift) 172 | 173 | ```swift 174 | var character = Character("😂") 175 | let characterPointer = character.valuePointer.assumingMemoryBound(to: UInt8.self) 176 | characterPointer.initialize(to: 0xf0) // f0 9f 9a 80 => "🚀" unicode(utf-8) 177 | characterPointer.advanced(by: 1).initialize(to: 0x9f) 178 | characterPointer.advanced(by: 2).initialize(to: 0x9a) 179 | characterPointer.advanced(by: 3).initialize(to: 0x80) 180 | 181 | // character = "🚀" 182 | ``` 183 | 184 | ### [Array](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/SwiftCore/Array.swift) 185 | 186 | ```swift 187 | let array = ["Apple", "Swift"] 188 | let arrayPointer = array.valuePointer 189 | arrayPointer.initialize(to: "Tanner") 190 | 191 | // array = ["Tanner", "Swift"] 192 | 193 | array.countPointer.initialize(to: 3) 194 | 195 | // array.count = 3 196 | ``` 197 | 198 | ### [Set](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/SwiftCore/Set.swift) 199 | 200 | ```swift 201 | let set: Set = ["Apple", "iOS", "Swift"] 202 | set.valuesPointer.initialize(to: "Tanner") 203 | 204 | // set = ["Tanner", "Swift", "iOS"] || ["Tanner", "Swift", "Apple"] || ... 205 | 206 | set.countPointer.initialize(to: 2) 207 | 208 | // set.count = 2 209 | ``` 210 | 211 | ### [Dictionary](https://github.com/TannerJin/Swift-MemoryLayout/blob/master/SwiftCore/Dictionary.swift) 212 | 213 | ```swift 214 | let dictionary = ["Swift": 5.0, "iOS": 2019] 215 | 216 | let dicCountPointer = dictionary.countPointer 217 | let dicKeysPointer = dictionary.keysPointer 218 | let dicValuesPointer = dictionary.valuesPointer 219 | ``` 220 | -------------------------------------------------------------------------------- /SwiftCore/String.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/7/31. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // struct String 12 | // +------------------------------------------------+ 13 | // | struct _StringGuts | 14 | // | +--------------------------------------------+ | 15 | // | | struct _StringObject | | 16 | // | | +----------------------------------------+ | | 17 | // | | | #if arch(i386) || arch(arm) | | | 18 | // | | | | | | 19 | // | | | --- 32-bit platforms --- | | | 20 | // | | | | | | 21 | // | | | enum Variant { | | | 22 | // | | | case immortal(UInt) | | | 23 | // | | | case native(AnyObject) | | | 24 | // | | | case bridged(_CocoaString) | | | 25 | // | | | } | | | 26 | // | | | var count: UInt | | | 27 | // | | | var _variant: Variant | | | 28 | // | | | var _discriminator: UInt8 | | | 29 | // | | | var _flags: UInt16 | | | 30 | // | | | var _countAndFlagsBits: UInt64 | | | 31 | // | | | | | | 32 | // | | | #else | | | 33 | // | | | | | | 34 | // | | | --- 64-bit platforms --- | | | 35 | // | | | | | | 36 | // | | | var _countAndFlagsBits: UInt64 | | | 37 | // | | | var _object: Builtin.BridgeObject | | | 38 | // | | | | | | 39 | // | | | #endif | | | 40 | // | | +----------------------------------------+ | | 41 | // | +--------------------------------------------+ | 42 | // +------------------------------------------------+ 43 | // +--------------------------------------+ 44 | // | | 45 | // | | 46 | // / count <= 15, Small => 15 bytes(string) + 1 byte(_object.abcdeeee) \ | 47 | // String 16 bytes | 48 | // \ count > 15, Large => 8 bytes(_countAndFlagsBits) + 8 bytes(_object) / | 49 | // | | | 50 | // | | | 51 | // +---------------------------------------------+ +------------------------------+ 52 | // | | 53 | // | | 54 | // | | 55 | // V | 56 | // _countAndFlagsBits (64 bits) | 57 | // | 58 | // abcd a => isASCII b => isNFC | 59 | // ∧∧∧∧ c => isNativelyStored d => isTailAllocated | 60 | // |||| | 61 | // 0000000000000000000000000000000000000000000000000000000000000000 | 62 | // | || | | 63 | // \ 16 bits / \ 48 bits / | 64 | // \ flags / \ count for Large String / | 65 | // \________/ \________________________________________/ | 66 | // | 67 | // | 68 | // | 69 | // | 70 | // +----------------------------------------------------------------------------------------------------+ 71 | // | 72 | // | 73 | // V 74 | // _object (64 bits) 75 | // 76 | // abcdeeee a => isImmortal b => largeIsCocoa e(4 bits) => count of Small String 77 | // ∧∧∧∧∧∧∧∧ c => isSmall d => providesFastUTF8 78 | // |||||||| 79 | // 0000000000000000000000000000000000000000000000000000000000000000 80 | // | || | 81 | // \ / \ 56 bits / 82 | // \ / \ pointer for Large String / 83 | // + \________________________________________________/ 84 | // | 85 | // V 86 | // 8 bits, 1 byte 87 | 88 | 89 | public extension String { 90 | var valuePointer: UnsafeMutableRawPointer? { 91 | mutating get { 92 | #if arch(i386) || arch(arm) 93 | // 32-bit platforms wati to do 94 | return nil 95 | #else 96 | if self.count <= 15 { 97 | // - Small strings 98 | return withUnsafePointer(to: &self) { UnsafeMutableRawPointer(mutating: $0) } 99 | } else { 100 | // - Large strings 101 | let _object = unsafeBitCast(self, to: (UInt64, UInt64).self).1 102 | let pointerMask = 1 << 56 - 1 // 56 bits => 111...111 103 | let pointerValue = _object & UInt64(pointerMask) 104 | return UnsafeMutableRawPointer(bitPattern: UInt(pointerValue))?.advanced(by: 32) 105 | } 106 | #endif 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Swift/Class.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Class.swift 3 | // SwiftPointerDemo 4 | // 5 | // Created by jintao on 2019/8/2. 6 | // Copyright © 2019 jintao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // class 12 | // +-----------------------------------------------------------------------+ 13 | // | var isa: objc_class* | 14 | // | var refCount: UInt64 >>>>>>>>---------------------------------------------------------+ 15 | // |- - - - - - - - - - - - - - - - - | | 16 | // | var property0: String | | 17 | // | var property1: [Int] | | 18 | // | . | | 19 | // | . | | 20 | // | . | | 21 | // +-----------------------------------------------------------------------+ | 22 | // | 23 | // | 24 | // +------------------------------------------------------------------------+ 25 | // | 26 | // V 27 | // InlineRefCountBits (64 bits) 28 | // 0000000000000000000000000000000000000000000000000000000000000000 29 | // || ||| || 30 | // | \ 30 bits / | \ 31 bits / | 31 | // | \ StrongExtraRefCount / | \ UnownedRefCount / | 32 | // | \______________________/ | \_______________________/ | 33 | // | | | 34 | // V V V 35 | // UseSlow(1 bit) IsDeiniting(1 bit) IsImmortal(1 bit) 36 | 37 | // or 38 | // (is Static Object 单例) 39 | // ∧ ∧ 40 | // | | 41 | // | HeapObjectSideTableEntry* (64 bits) | 42 | // 0000000000000000000000000000000000000000000000000000000000000000 43 | // || | 44 | // | \ 62 bits / 45 | // | \ HeapObjectSideTableEntry* / 46 | // | \______________________________________________________/ 47 | // | 48 | // V 49 | // SideTableMark(1 bit) 50 | 51 | /* HeapObject: 52 | 53 | if (StrongExtraRefCount or UnownedRefCount is overFlow) or hasWeakRef { 54 | Use HeapObjectSideTable 55 | } 56 | 57 | struct HeapObjectSideTable { 58 | let object: UnsafeMutableRawPointer 59 | let bits: (UInt64, Int64) // include StrongExtraRefCount and UnownedRefCount 60 | let weakBits: UInt32 61 | } 62 | 63 | each weak variable(WeakReference) will pointe to the same HeapObjectSideTable of the headObject, so *weak_variable = (heapObject*)objc 64 | 65 | for example: 66 | class A { 67 | } 68 | let a = A() 69 | weak var a2 = a // a2 is pointe to HeapObjectSideTable of a. so, (*a2) = (objc*)object 70 | */ 71 | 72 | 73 | // class: NSObject 74 | // +-----------------------------------------------------------------------+ 75 | // | var isa: objc_class* -------------+ 76 | // |- - - - - - - - - - - - - - - - - | | 77 | // | var property0: String | | 78 | // | var property1: [Int] | | 79 | // | . | | 80 | // | . | | 81 | // | . | | 82 | // +-----------------------------------------------------------------------+ | 83 | // | 84 | // | 85 | // +---------------------------------------------------------------+ 86 | // | 87 | // V 88 | // isa (64 bits) 89 | // 0000000000000000000000000000000000000000000000000000000000000000 90 | // | ||||| || |||| 91 | // | ||||| || |||| 92 | // | ||||| || |||| 93 | // \ / ||| \ / \ / ||| 94 | // extra_rc||| magic objc_class* ||| 95 | // V|| V|| 96 | // side_table|| has_cxx_dtor|| 97 | // || || 98 | // V| V| 99 | // deallocating| has_assoc| 100 | // | | 101 | // V V 102 | // weakly_referenced nonpointer 103 | 104 | /* NSObject: 105 | 106 | if extra_rc > 0xff || objc has weak ref { <--------------+ 107 | use SideTable and set side_table bit = 1 | 108 | } | 109 | | 110 | static GlobalSideTables = Dictionary.init(bucketCount: 8) // iOS | 111 | | 112 | strct SideTable { | 113 | var lock: spinlock_t | 114 | | 115 | /* Int: 0 bit => objc has weak ref --------------------------------------------+ 116 | Int: 1 bit => objc isDeallocating 117 | Int: 2~62 bits => count of extra_rc 118 | Int: 63 bit => ??? 119 | */ 120 | var refcnts: Dictionary 121 | var weak_table: Dictionary 122 | } 123 | 124 | struct weak_entry { 125 | var _objc: NSObject 126 | 127 | /* if weak_variables.count > 4 128 | weak_variables[0] become pointer and pointe to [&objc] 129 | weak_variables[1] = count of weak_variables 130 | */ 131 | var weak_variables: [&objc].init(count: 4) 132 | } 133 | 134 | 135 | Refcnt: 136 | GlobalSideTables[objc].refcnts[objc] 137 | 138 | WeakEntry: 139 | GlobalSideTables[objc].weak_table[objc] 140 | */ 141 | 142 | 143 | // MARK: - Swift Class 144 | /* unsafeBitCast is inlinable. enter unsafeBitCast, objc will retain 1. finish unsafeBitCast, objc will release 1. 145 | yout can use at debug, but not use at release 146 | */ 147 | 148 | public func StrongRefCount(_ objc: T) -> UInt32 { 149 | assertNotNSObject(objc) 150 | 151 | func getStrongRefCount(bitsValue: UInt64) -> UInt32 { 152 | var mask: UInt64 = 1 << 30 - 1 // 30 bits => 111...111 153 | mask <<= 33 // 63 bits => 111...111000...000 154 | return UInt32((bitsValue & mask) >> 33) + 1 // The strong RC is stored as an extra count, so +1 155 | } 156 | 157 | if hasWeakRefCount(objc) { 158 | let bitsValue = getSileTablePointer(objc)?.pointee.bits.1 159 | return getStrongRefCount(bitsValue: UInt64(bitsValue!)) 160 | } else { 161 | let objcPointer = unsafeBitCast(objc, to: UnsafeMutablePointer.self) 162 | let bitsValue = objcPointer.advanced(by: 1).pointee 163 | return getStrongRefCount(bitsValue: bitsValue) 164 | } 165 | } 166 | 167 | public func UnownedRefCount(_ objc: T) -> UInt32 { 168 | assertNotNSObject(objc) 169 | 170 | func getUnownedRefCount(bitsValue: UInt64) -> UInt32 { 171 | var mask: UInt64 = 1 << 31 - 1 // 31 bits => 111...111 172 | mask <<= 1 // 32 bits => 111...110 173 | return UInt32((bitsValue & mask) >> 1) - 1 // The unowned RC also has an extra +1 on behalf of the strong references; this +1 is decremented after deinit completes(Apple) 174 | } 175 | 176 | if hasWeakRefCount(objc) { 177 | let bitsValue = getSileTablePointer(objc)?.pointee.bits.1 178 | return getUnownedRefCount(bitsValue: UInt64(bitsValue!)) 179 | } else { 180 | let objcPointer = unsafeBitCast(objc, to: UnsafeMutablePointer.self) 181 | let bitsValue = objcPointer.advanced(by: 1).pointee 182 | return getUnownedRefCount(bitsValue: bitsValue) 183 | } 184 | } 185 | 186 | // nil: has not weak reference 187 | public func WeakRefCount(_ objc: T) -> UInt32? { 188 | assertNotNSObject(objc) 189 | 190 | if hasWeakRefCount(objc), let sileTable = getSileTablePointer(objc) { 191 | return sileTable.pointee.weakBits - 1 // The weak RC also has an extra +1, this +1 is decremented after the object's allocation is freed(Apple) 192 | } 193 | 194 | return nil 195 | } 196 | 197 | 198 | // MARK: - Helper 199 | 200 | // useSlowValue && !isImmortalValue 201 | public func hasWeakRefCount(_ objc: T) -> Bool { 202 | assertNotNSObject(objc) 203 | 204 | let objcPointer = unsafeBitCast(objc, to: UnsafeMutablePointer.self) 205 | let bitsValue = objcPointer.advanced(by: 1).pointee 206 | 207 | let isImmortalMask: UInt64 = 1 208 | let isImmortalValue = bitsValue & isImmortalMask 209 | 210 | let useSlowMask: UInt64 = 1 << 63 211 | let useSlowValue = (bitsValue & useSlowMask) >> 63 212 | 213 | return (useSlowValue == 1) && (isImmortalValue != 1) 214 | } 215 | 216 | private func assertNotNSObject(_ objc: T) { // where T != NSObject 217 | assert(!(objc is NSObject), "NSObject's instace has not refCount property, look up it at runtime.objc") 218 | } 219 | 220 | private func getSileTablePointer(_ objc: T) -> UnsafeMutablePointer? { 221 | assertNotNSObject(objc) 222 | assert(hasWeakRefCount(objc)) 223 | 224 | let objcPointer = unsafeBitCast(objc, to: UnsafeMutablePointer.self) 225 | let bitsValue = objcPointer.advanced(by: 1).pointee 226 | let mask: UInt64 = 1 << 62 - 1 // 62 bits => 111...111 227 | let slieTableValue = bitsValue & mask 228 | return UnsafeMutableRawPointer(bitPattern: UInt(slieTableValue << 3))?.assumingMemoryBound(to: HeapObjectSideTableEntry.self) 229 | } 230 | 231 | private struct HeapObjectSideTableEntry { 232 | let object: UnsafeMutableRawPointer 233 | let bits: (UInt64, Int64) 234 | let weakBits: UInt32 235 | } 236 | -------------------------------------------------------------------------------- /SwiftDemo/SwiftDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A93E5B64230262FC00DFC61A /* Tuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93E5B63230262FC00DFC61A /* Tuple.swift */; }; 11 | A947489422FACE8F00212E57 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = A947489322FACE8F00212E57 /* main.swift */; }; 12 | A94748A722FACE9F00212E57 /* Protocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A947489B22FACE9F00212E57 /* Protocol.swift */; }; 13 | A94748A822FACE9F00212E57 /* Class.swift in Sources */ = {isa = PBXBuildFile; fileRef = A947489C22FACE9F00212E57 /* Class.swift */; }; 14 | A94748A922FACE9F00212E57 /* Enum.swift in Sources */ = {isa = PBXBuildFile; fileRef = A947489D22FACE9F00212E57 /* Enum.swift */; }; 15 | A94748AA22FACE9F00212E57 /* Struct.swift in Sources */ = {isa = PBXBuildFile; fileRef = A947489E22FACE9F00212E57 /* Struct.swift */; }; 16 | A94748AB22FACE9F00212E57 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = A94748A022FACE9F00212E57 /* Array.swift */; }; 17 | A94748AC22FACE9F00212E57 /* Character.swift in Sources */ = {isa = PBXBuildFile; fileRef = A94748A122FACE9F00212E57 /* Character.swift */; }; 18 | A94748AD22FACE9F00212E57 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = A94748A222FACE9F00212E57 /* Dictionary.swift */; }; 19 | A94748AE22FACE9F00212E57 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = A94748A322FACE9F00212E57 /* String.swift */; }; 20 | A94748AF22FACE9F00212E57 /* Bool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A94748A422FACE9F00212E57 /* Bool.swift */; }; 21 | A94748B022FACE9F00212E57 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = A94748A522FACE9F00212E57 /* Optional.swift */; }; 22 | A94748B122FACE9F00212E57 /* Set.swift in Sources */ = {isa = PBXBuildFile; fileRef = A94748A622FACE9F00212E57 /* Set.swift */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXCopyFilesBuildPhase section */ 26 | A947488E22FACE8F00212E57 /* CopyFiles */ = { 27 | isa = PBXCopyFilesBuildPhase; 28 | buildActionMask = 2147483647; 29 | dstPath = /usr/share/man/man1/; 30 | dstSubfolderSpec = 0; 31 | files = ( 32 | ); 33 | runOnlyForDeploymentPostprocessing = 1; 34 | }; 35 | /* End PBXCopyFilesBuildPhase section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | A93E5B63230262FC00DFC61A /* Tuple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tuple.swift; sourceTree = ""; }; 39 | A947489022FACE8F00212E57 /* SwiftDemo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SwiftDemo; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | A947489322FACE8F00212E57 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 41 | A947489B22FACE9F00212E57 /* Protocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Protocol.swift; sourceTree = ""; }; 42 | A947489C22FACE9F00212E57 /* Class.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Class.swift; sourceTree = ""; }; 43 | A947489D22FACE9F00212E57 /* Enum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Enum.swift; sourceTree = ""; }; 44 | A947489E22FACE9F00212E57 /* Struct.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Struct.swift; sourceTree = ""; }; 45 | A94748A022FACE9F00212E57 /* Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = ""; }; 46 | A94748A122FACE9F00212E57 /* Character.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Character.swift; sourceTree = ""; }; 47 | A94748A222FACE9F00212E57 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; 48 | A94748A322FACE9F00212E57 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; 49 | A94748A422FACE9F00212E57 /* Bool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bool.swift; sourceTree = ""; }; 50 | A94748A522FACE9F00212E57 /* Optional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Optional.swift; sourceTree = ""; }; 51 | A94748A622FACE9F00212E57 /* Set.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Set.swift; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | A947488D22FACE8F00212E57 /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | A947488722FACE8F00212E57 = { 66 | isa = PBXGroup; 67 | children = ( 68 | A947489222FACE8F00212E57 /* SwiftDemo */, 69 | A947489122FACE8F00212E57 /* Products */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | A947489122FACE8F00212E57 /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | A947489022FACE8F00212E57 /* SwiftDemo */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | A947489222FACE8F00212E57 /* SwiftDemo */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | A947489A22FACE9F00212E57 /* Swift */, 85 | A947489F22FACE9F00212E57 /* SwiftCore */, 86 | A947489322FACE8F00212E57 /* main.swift */, 87 | ); 88 | path = SwiftDemo; 89 | sourceTree = ""; 90 | }; 91 | A947489A22FACE9F00212E57 /* Swift */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | A947489E22FACE9F00212E57 /* Struct.swift */, 95 | A93E5B63230262FC00DFC61A /* Tuple.swift */, 96 | A947489C22FACE9F00212E57 /* Class.swift */, 97 | A947489B22FACE9F00212E57 /* Protocol.swift */, 98 | A947489D22FACE9F00212E57 /* Enum.swift */, 99 | ); 100 | name = Swift; 101 | path = ../../Swift; 102 | sourceTree = ""; 103 | }; 104 | A947489F22FACE9F00212E57 /* SwiftCore */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | A94748A422FACE9F00212E57 /* Bool.swift */, 108 | A94748A522FACE9F00212E57 /* Optional.swift */, 109 | A94748A322FACE9F00212E57 /* String.swift */, 110 | A94748A122FACE9F00212E57 /* Character.swift */, 111 | A94748A022FACE9F00212E57 /* Array.swift */, 112 | A94748A222FACE9F00212E57 /* Dictionary.swift */, 113 | A94748A622FACE9F00212E57 /* Set.swift */, 114 | ); 115 | name = SwiftCore; 116 | path = ../../SwiftCore; 117 | sourceTree = ""; 118 | }; 119 | /* End PBXGroup section */ 120 | 121 | /* Begin PBXNativeTarget section */ 122 | A947488F22FACE8F00212E57 /* SwiftDemo */ = { 123 | isa = PBXNativeTarget; 124 | buildConfigurationList = A947489722FACE8F00212E57 /* Build configuration list for PBXNativeTarget "SwiftDemo" */; 125 | buildPhases = ( 126 | A947488C22FACE8F00212E57 /* Sources */, 127 | A947488D22FACE8F00212E57 /* Frameworks */, 128 | A947488E22FACE8F00212E57 /* CopyFiles */, 129 | ); 130 | buildRules = ( 131 | ); 132 | dependencies = ( 133 | ); 134 | name = SwiftDemo; 135 | productName = SwiftDemo; 136 | productReference = A947489022FACE8F00212E57 /* SwiftDemo */; 137 | productType = "com.apple.product-type.tool"; 138 | }; 139 | /* End PBXNativeTarget section */ 140 | 141 | /* Begin PBXProject section */ 142 | A947488822FACE8F00212E57 /* Project object */ = { 143 | isa = PBXProject; 144 | attributes = { 145 | LastSwiftUpdateCheck = 1020; 146 | LastUpgradeCheck = 1020; 147 | ORGANIZATIONNAME = jintao; 148 | TargetAttributes = { 149 | A947488F22FACE8F00212E57 = { 150 | CreatedOnToolsVersion = 10.2.1; 151 | }; 152 | }; 153 | }; 154 | buildConfigurationList = A947488B22FACE8F00212E57 /* Build configuration list for PBXProject "SwiftDemo" */; 155 | compatibilityVersion = "Xcode 9.3"; 156 | developmentRegion = en; 157 | hasScannedForEncodings = 0; 158 | knownRegions = ( 159 | en, 160 | ); 161 | mainGroup = A947488722FACE8F00212E57; 162 | productRefGroup = A947489122FACE8F00212E57 /* Products */; 163 | projectDirPath = ""; 164 | projectRoot = ""; 165 | targets = ( 166 | A947488F22FACE8F00212E57 /* SwiftDemo */, 167 | ); 168 | }; 169 | /* End PBXProject section */ 170 | 171 | /* Begin PBXSourcesBuildPhase section */ 172 | A947488C22FACE8F00212E57 /* Sources */ = { 173 | isa = PBXSourcesBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | A94748A822FACE9F00212E57 /* Class.swift in Sources */, 177 | A94748B022FACE9F00212E57 /* Optional.swift in Sources */, 178 | A94748AD22FACE9F00212E57 /* Dictionary.swift in Sources */, 179 | A947489422FACE8F00212E57 /* main.swift in Sources */, 180 | A94748AF22FACE9F00212E57 /* Bool.swift in Sources */, 181 | A94748AE22FACE9F00212E57 /* String.swift in Sources */, 182 | A94748AC22FACE9F00212E57 /* Character.swift in Sources */, 183 | A93E5B64230262FC00DFC61A /* Tuple.swift in Sources */, 184 | A94748A922FACE9F00212E57 /* Enum.swift in Sources */, 185 | A94748B122FACE9F00212E57 /* Set.swift in Sources */, 186 | A94748AB22FACE9F00212E57 /* Array.swift in Sources */, 187 | A94748AA22FACE9F00212E57 /* Struct.swift in Sources */, 188 | A94748A722FACE9F00212E57 /* Protocol.swift in Sources */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | /* End PBXSourcesBuildPhase section */ 193 | 194 | /* Begin XCBuildConfiguration section */ 195 | A947489522FACE8F00212E57 /* Debug */ = { 196 | isa = XCBuildConfiguration; 197 | buildSettings = { 198 | ALWAYS_SEARCH_USER_PATHS = NO; 199 | CLANG_ANALYZER_NONNULL = YES; 200 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 201 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 202 | CLANG_CXX_LIBRARY = "libc++"; 203 | CLANG_ENABLE_MODULES = YES; 204 | CLANG_ENABLE_OBJC_ARC = YES; 205 | CLANG_ENABLE_OBJC_WEAK = YES; 206 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 207 | CLANG_WARN_BOOL_CONVERSION = YES; 208 | CLANG_WARN_COMMA = YES; 209 | CLANG_WARN_CONSTANT_CONVERSION = YES; 210 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 211 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 212 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 213 | CLANG_WARN_EMPTY_BODY = YES; 214 | CLANG_WARN_ENUM_CONVERSION = YES; 215 | CLANG_WARN_INFINITE_RECURSION = YES; 216 | CLANG_WARN_INT_CONVERSION = YES; 217 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 218 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 219 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 220 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 221 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 222 | CLANG_WARN_STRICT_PROTOTYPES = YES; 223 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 224 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 225 | CLANG_WARN_UNREACHABLE_CODE = YES; 226 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 227 | CODE_SIGN_IDENTITY = "Mac Developer"; 228 | COPY_PHASE_STRIP = NO; 229 | DEBUG_INFORMATION_FORMAT = dwarf; 230 | ENABLE_STRICT_OBJC_MSGSEND = YES; 231 | ENABLE_TESTABILITY = YES; 232 | GCC_C_LANGUAGE_STANDARD = gnu11; 233 | GCC_DYNAMIC_NO_PIC = NO; 234 | GCC_NO_COMMON_BLOCKS = YES; 235 | GCC_OPTIMIZATION_LEVEL = 0; 236 | GCC_PREPROCESSOR_DEFINITIONS = ( 237 | "DEBUG=1", 238 | "$(inherited)", 239 | ); 240 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 242 | GCC_WARN_UNDECLARED_SELECTOR = YES; 243 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 244 | GCC_WARN_UNUSED_FUNCTION = YES; 245 | GCC_WARN_UNUSED_VARIABLE = YES; 246 | MACOSX_DEPLOYMENT_TARGET = 10.14; 247 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 248 | MTL_FAST_MATH = YES; 249 | ONLY_ACTIVE_ARCH = YES; 250 | SDKROOT = macosx; 251 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 252 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 253 | }; 254 | name = Debug; 255 | }; 256 | A947489622FACE8F00212E57 /* Release */ = { 257 | isa = XCBuildConfiguration; 258 | buildSettings = { 259 | ALWAYS_SEARCH_USER_PATHS = NO; 260 | CLANG_ANALYZER_NONNULL = YES; 261 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_MODULES = YES; 265 | CLANG_ENABLE_OBJC_ARC = YES; 266 | CLANG_ENABLE_OBJC_WEAK = YES; 267 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 268 | CLANG_WARN_BOOL_CONVERSION = YES; 269 | CLANG_WARN_COMMA = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 272 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 273 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 274 | CLANG_WARN_EMPTY_BODY = YES; 275 | CLANG_WARN_ENUM_CONVERSION = YES; 276 | CLANG_WARN_INFINITE_RECURSION = YES; 277 | CLANG_WARN_INT_CONVERSION = YES; 278 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 279 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 280 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 281 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 282 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 283 | CLANG_WARN_STRICT_PROTOTYPES = YES; 284 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 285 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 286 | CLANG_WARN_UNREACHABLE_CODE = YES; 287 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 288 | CODE_SIGN_IDENTITY = "Mac Developer"; 289 | COPY_PHASE_STRIP = NO; 290 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 291 | ENABLE_NS_ASSERTIONS = NO; 292 | ENABLE_STRICT_OBJC_MSGSEND = YES; 293 | GCC_C_LANGUAGE_STANDARD = gnu11; 294 | GCC_NO_COMMON_BLOCKS = YES; 295 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 296 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 297 | GCC_WARN_UNDECLARED_SELECTOR = YES; 298 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 299 | GCC_WARN_UNUSED_FUNCTION = YES; 300 | GCC_WARN_UNUSED_VARIABLE = YES; 301 | MACOSX_DEPLOYMENT_TARGET = 10.14; 302 | MTL_ENABLE_DEBUG_INFO = NO; 303 | MTL_FAST_MATH = YES; 304 | SDKROOT = macosx; 305 | SWIFT_COMPILATION_MODE = wholemodule; 306 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 307 | }; 308 | name = Release; 309 | }; 310 | A947489822FACE8F00212E57 /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | CODE_SIGN_STYLE = Automatic; 314 | DEVELOPMENT_TEAM = 8HX9UN9S6G; 315 | PRODUCT_NAME = "$(TARGET_NAME)"; 316 | SWIFT_VERSION = 5.0; 317 | }; 318 | name = Debug; 319 | }; 320 | A947489922FACE8F00212E57 /* Release */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | CODE_SIGN_STYLE = Automatic; 324 | DEVELOPMENT_TEAM = 8HX9UN9S6G; 325 | PRODUCT_NAME = "$(TARGET_NAME)"; 326 | SWIFT_VERSION = 5.0; 327 | }; 328 | name = Release; 329 | }; 330 | /* End XCBuildConfiguration section */ 331 | 332 | /* Begin XCConfigurationList section */ 333 | A947488B22FACE8F00212E57 /* Build configuration list for PBXProject "SwiftDemo" */ = { 334 | isa = XCConfigurationList; 335 | buildConfigurations = ( 336 | A947489522FACE8F00212E57 /* Debug */, 337 | A947489622FACE8F00212E57 /* Release */, 338 | ); 339 | defaultConfigurationIsVisible = 0; 340 | defaultConfigurationName = Release; 341 | }; 342 | A947489722FACE8F00212E57 /* Build configuration list for PBXNativeTarget "SwiftDemo" */ = { 343 | isa = XCConfigurationList; 344 | buildConfigurations = ( 345 | A947489822FACE8F00212E57 /* Debug */, 346 | A947489922FACE8F00212E57 /* Release */, 347 | ); 348 | defaultConfigurationIsVisible = 0; 349 | defaultConfigurationName = Release; 350 | }; 351 | /* End XCConfigurationList section */ 352 | }; 353 | rootObject = A947488822FACE8F00212E57 /* Project object */; 354 | } 355 | --------------------------------------------------------------------------------