@@ -53,38 +53,85 @@ class PostHogContext {
53
53
properties [ " $is_emulator " ] = false
54
54
#endif
55
55
56
+ // iOS app running in compatibility mode (Designed for iPad/iPhone)
57
+ var isiOSAppOnMac = false
58
+ #if os(iOS)
59
+ if #available( iOS 14 . 0 , * ) {
60
+ isiOSAppOnMac = ProcessInfo . processInfo. isiOSAppOnMac
61
+ }
62
+ #endif
63
+
64
+ // iPad app running on Mac Catalyst
65
+ #if targetEnvironment(macCatalyst)
66
+ let isMacCatalystApp = true
67
+ #else
68
+ let isMacCatalystApp = false
69
+ #endif
70
+
71
+ properties [ " $is_ios_running_on_mac " ] = isiOSAppOnMac
72
+ properties [ " $is_mac_catalyst_app " ] = isMacCatalystApp
73
+
56
74
#if os(iOS) || os(tvOS)
57
75
let device = UIDevice . current
58
76
// use https://github.com/devicekit/DeviceKit
59
- properties [ " $device_name " ] = device. model
60
- properties [ " $os_name " ] = device. systemName
61
- properties [ " $os_version " ] = device. systemVersion
62
-
63
- var deviceType : String ?
64
- switch device. userInterfaceIdiom {
65
- case UIUserInterfaceIdiom . phone:
66
- deviceType = " Mobile "
67
- case UIUserInterfaceIdiom . pad:
68
- deviceType = " Tablet "
69
- case UIUserInterfaceIdiom . tv:
70
- deviceType = " TV "
71
- case UIUserInterfaceIdiom . carPlay:
72
- deviceType = " CarPlay "
73
- case UIUserInterfaceIdiom . mac:
74
- deviceType = " Desktop "
75
- default :
76
- deviceType = nil
77
- }
78
- if deviceType != nil {
79
- properties [ " $device_type " ] = deviceType
77
+ let processInfo = ProcessInfo . processInfo
78
+
79
+ if isMacCatalystApp || isiOSAppOnMac {
80
+ let underlyingOS = device. systemName
81
+ let underlyingOSVersion = device. systemVersion
82
+ let macOSVersion = processInfo. operatingSystemVersionString
83
+
84
+ if isMacCatalystApp {
85
+ let osVersion = ProcessInfo . processInfo. operatingSystemVersion
86
+ properties [ " $os_version " ] = " \( osVersion. majorVersion) . \( osVersion. minorVersion) . \( osVersion. patchVersion) "
87
+ } else {
88
+ let osVersionString = processInfo. operatingSystemVersionString
89
+ if let versionRange = osVersionString. range ( of: #"\d+\.\d+\.\d+"# , options: . regularExpression) {
90
+ properties [ " $os_version " ] = osVersionString [ versionRange]
91
+ } else {
92
+ // fallback to full version string in case formatting changes
93
+ properties [ " $os_version " ] = osVersionString
94
+ }
95
+ }
96
+ // device.userInterfaceIdiom reports .pad here, so we use a static value instead
97
+ // - For an app deployable on iPad, the idiom type is always .pad (instead of .mac)
98
+ //
99
+ // Source: https://developer.apple.com/documentation/apple-silicon/adapting-ios-code-to-run-in-the-macos-environment#Handle-unknown-device-types-gracefully
100
+ properties [ " $os_name " ] = " macOS "
101
+ properties [ " $device_type " ] = " Desktop "
102
+ properties [ " $device_name " ] = processInfo. hostName
103
+ } else {
104
+ // use https://github.com/devicekit/DeviceKit
105
+ properties [ " $os_name " ] = device. systemName
106
+ properties [ " $os_version " ] = device. systemVersion
107
+ properties [ " $device_name " ] = device. model
108
+
109
+ var deviceType : String ?
110
+ switch device. userInterfaceIdiom {
111
+ case UIUserInterfaceIdiom . phone:
112
+ deviceType = " Mobile "
113
+ case UIUserInterfaceIdiom . pad:
114
+ deviceType = " Tablet "
115
+ case UIUserInterfaceIdiom . tv:
116
+ deviceType = " TV "
117
+ case UIUserInterfaceIdiom . carPlay:
118
+ deviceType = " CarPlay "
119
+ case UIUserInterfaceIdiom . mac:
120
+ deviceType = " Desktop "
121
+ default :
122
+ deviceType = nil
123
+ }
124
+ if deviceType != nil {
125
+ properties [ " $device_type " ] = deviceType
126
+ }
80
127
}
81
128
#elseif os(macOS)
82
129
let deviceName = Host . current ( ) . localizedName
83
130
if ( deviceName? . isEmpty) != nil {
84
131
properties [ " $device_name " ] = deviceName
85
132
}
86
133
let processInfo = ProcessInfo . processInfo
87
- properties [ " $os_name " ] = " macOS \( processInfo . operatingSystemVersionString ) " // eg Version 14.2.1 (Build 23C71)
134
+ properties [ " $os_name " ] = " macOS "
88
135
let osVersion = processInfo. operatingSystemVersion
89
136
properties [ " $os_version " ] = " \( osVersion. majorVersion) . \( osVersion. minorVersion) . \( osVersion. patchVersion) "
90
137
properties [ " $device_type " ] = " Desktop "
@@ -134,10 +181,25 @@ class PostHogContext {
134
181
}
135
182
136
183
private func platform( ) -> String {
184
+ var sysctlName = " hw.machine "
185
+
186
+ // In case of mac catalyst or iOS running on mac:
187
+ // - "hw.machine" returns underlying iPad/iPhone model
188
+ // - "hw.model" returns mac model
189
+ #if targetEnvironment(macCatalyst)
190
+ sysctlName = " hw.model "
191
+ #elseif os(iOS)
192
+ if #available( iOS 14 . 0 , * ) {
193
+ if ProcessInfo . processInfo. isiOSAppOnMac {
194
+ sysctlName = " hw.model "
195
+ }
196
+ }
197
+ #endif
198
+
137
199
var size = 0
138
- sysctlbyname ( " hw.machine " , nil , & size, nil , 0 )
200
+ sysctlbyname ( sysctlName , nil , & size, nil , 0 )
139
201
var machine = [ CChar] ( repeating: 0 , count: size)
140
- sysctlbyname ( " hw.machine " , & machine, & size, nil , 0 )
202
+ sysctlbyname ( sysctlName , & machine, & size, nil , 0 )
141
203
return String ( cString: machine)
142
204
}
143
205
0 commit comments