Skip to content

Commit fb53d3b

Browse files
authored
fix: identify mac catalyst (#287)
* fix: identify mac catalyst * fix: build * fix: build tvos * fix: add properties for mac catalyst and ios running on mac * fix: same values for catalyst and ios running on mac
1 parent 22f1a37 commit fb53d3b

File tree

3 files changed

+91
-27
lines changed

3 files changed

+91
-27
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## Next
22

3+
- fix: identify macOS when running Mac Catalyst or iOS on Mac ([#287](https://github.com/PostHog/posthog-ios/pull/287))
4+
35
## 3.19.2 - 2025-01-30
46

57
- fix: XCFramework builds failing ([#288](https://github.com/PostHog/posthog-ios/pull/288))

PostHog.xcodeproj/project.pbxproj

+3-3
Original file line numberDiff line numberDiff line change
@@ -2021,11 +2021,11 @@
20212021
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
20222022
MACOSX_DEPLOYMENT_TARGET = 10.15;
20232023
MARKETING_VERSION = 1.0;
2024-
PRODUCT_BUNDLE_IDENTIFIER = com.posthog.PostHogExample.yj;
2024+
PRODUCT_BUNDLE_IDENTIFIER = com.posthog.PostHogExample;
20252025
PRODUCT_NAME = "$(TARGET_NAME)";
20262026
PROVISIONING_PROFILE_SPECIFIER = "";
20272027
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
2028-
SUPPORTS_MACCATALYST = NO;
2028+
SUPPORTS_MACCATALYST = YES;
20292029
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
20302030
SWIFT_EMIT_LOC_STRINGS = YES;
20312031
SWIFT_VERSION = 5.0;
@@ -2060,7 +2060,7 @@
20602060
PRODUCT_BUNDLE_IDENTIFIER = com.posthog.PostHogExample;
20612061
PRODUCT_NAME = "$(TARGET_NAME)";
20622062
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
2063-
SUPPORTS_MACCATALYST = NO;
2063+
SUPPORTS_MACCATALYST = YES;
20642064
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
20652065
SWIFT_EMIT_LOC_STRINGS = YES;
20662066
SWIFT_VERSION = 5.0;

PostHog/PostHogContext.swift

+86-24
Original file line numberDiff line numberDiff line change
@@ -53,38 +53,85 @@ class PostHogContext {
5353
properties["$is_emulator"] = false
5454
#endif
5555

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+
5674
#if os(iOS) || os(tvOS)
5775
let device = UIDevice.current
5876
// 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+
}
80127
}
81128
#elseif os(macOS)
82129
let deviceName = Host.current().localizedName
83130
if (deviceName?.isEmpty) != nil {
84131
properties["$device_name"] = deviceName
85132
}
86133
let processInfo = ProcessInfo.processInfo
87-
properties["$os_name"] = "macOS \(processInfo.operatingSystemVersionString)" // eg Version 14.2.1 (Build 23C71)
134+
properties["$os_name"] = "macOS"
88135
let osVersion = processInfo.operatingSystemVersion
89136
properties["$os_version"] = "\(osVersion.majorVersion).\(osVersion.minorVersion).\(osVersion.patchVersion)"
90137
properties["$device_type"] = "Desktop"
@@ -134,10 +181,25 @@ class PostHogContext {
134181
}
135182

136183
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+
137199
var size = 0
138-
sysctlbyname("hw.machine", nil, &size, nil, 0)
200+
sysctlbyname(sysctlName, nil, &size, nil, 0)
139201
var machine = [CChar](repeating: 0, count: size)
140-
sysctlbyname("hw.machine", &machine, &size, nil, 0)
202+
sysctlbyname(sysctlName, &machine, &size, nil, 0)
141203
return String(cString: machine)
142204
}
143205

0 commit comments

Comments
 (0)