Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@haacked
Copy link
Contributor

@haacked haacked commented Jul 22, 2025

This is a follow-up to #373 (and targets that branch)

💡 Motivation and Context

Feature flags that rely on person properties like $app_version or $os_version often fail to work immediately after SDK initialization because these properties aren't available until identify() calls are processed server-side. This creates a race condition where flags return incorrect values during the critical first moments of app usage.

This PR implements automatic person properties similar to the PostHog web SDK, where common device and app properties are automatically set as person properties during SDK initialization.

Properties automatically set:

  • $app_version - App version from bundle
    (CFBundleShortVersionString)
  • $app_build - App build number (CFBundleVersion)
  • $os_name - Operating system name (iOS, macOS, etc.)
  • $os_version - Operating system version
  • $device_type - Device type (Mobile, Tablet, Desktop, etc.)
  • $locale - User's current locale

Key benefits:

  • Eliminates race conditions for feature flag evaluation
  • Ensures flags work immediately without waiting for server-side processing
  • Maintains consistency with PostHog web SDK behavior
  • Includes opt-out configuration for flexibility

💚 How did you test it?

  • Added comprehensive test suite covering enabled/disabled states and app update scenarios
  • Verified automatic property setting during SDK initialization via flag request inspection
  • Tested that properties are refreshed on app updates
  • Confirmed opt-out functionality works correctly
  • Updated example app with usage documentation and testing functionality
  • All existing tests continue to pass

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

@haacked haacked requested a review from marandaneto as a code owner July 22, 2025 01:55
@haacked haacked requested review from a team, Copilot, ioannisj and marandaneto and removed request for marandaneto July 22, 2025 01:56

This comment was marked as outdated.

@haacked haacked force-pushed the haacked/366-attach-properties branch from 55b8101 to cbdc37e Compare July 22, 2025 21:00
@haacked haacked force-pushed the haacked/default-properties branch from 16e9060 to 42389e8 Compare July 22, 2025 21:00
@dmarticus dmarticus moved this to In Review in Feature Flags Jul 22, 2025
Copy link
Contributor

@ioannisj ioannisj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG, a minor comment

@github-project-automation github-project-automation bot moved this from In Review to Approved in Feature Flags Jul 23, 2025
Copy link
Member

@marandaneto marandaneto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left a few comments

@github-project-automation github-project-automation bot moved this from Approved to In Review in Feature Flags Jul 23, 2025
haacked added 10 commits July 23, 2025 13:46
Automatically sets common device and app properties as person properties
during SDK initialization to eliminate race conditions where feature flags
couldn't use person properties until identify() calls were processed.

Properties automatically set:
- $app_version: App version from bundle
- $app_build: App build number
- $os_name: Operating system name
- $os_version: OS version
- $device_type: Device type (Mobile, Tablet, Desktop, etc.)
- $locale: User's locale

Includes configuration option to disable (setDefaultPersonProperties)
and automatic refresh on app updates.
If sanitization of default person properties fails, log a warning and skip
setting the properties instead of silently falling back to empty dictionary.
Apply SwiftFormat fixes to remove trailing spaces, consecutive spaces,
and redundant internal access control.
Document the new default properties support for feature flag evaluation
that eliminates race conditions during SDK initialization.
Remove redundant waitFlagsRequest calls before getFlagsRequest calls,
since getFlagsRequest internally waits for the expectation. This fixes
the "expectations can only be waited on once" error in CI.
System-provided properties don't need sanitization as they are already
safe for JSON serialization.
App updates only occur on fresh launches, making this refresh redundant
since setDefaultPersonProperties is already called during SDK initialization.
Read locale directly from Locale.current instead of calling expensive
dynamicContext() method that computes many unnecessary values.
Method is no longer needed after removing Application Updated refresh logic.
Remove extra blank lines to satisfy SwiftFormat linter.
@haacked haacked force-pushed the haacked/default-properties branch from 5faf6c1 to fe000bc Compare July 23, 2025 20:46
The test expects a flags request to be made during SDK initialization
which only happens when preloadFeatureFlags is enabled.
- Remove caching of default person properties in storage
- Modify getPersonPropertiesForFlags to compute fresh default properties every time
- Default properties are now always current (e.g., locale, OS version changes)
- Remove setDefaultPersonProperties call from SDK initialization
- Add closure parameter to PostHogRemoteConfig for getting fresh default properties
- Update all test files to provide empty default properties closure

This addresses the concern that cached default properties could become stale
and lead to incorrect values being used in feature flag evaluation.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements automatic default person properties for feature flag evaluation, eliminating race conditions where flags fail to work immediately after SDK initialization. The feature automatically sets common device and app properties (like $app_version, $os_version) as person properties during SDK initialization, ensuring feature flags work without waiting for server-side processing of identify() calls.

  • Adds automatic setting of 6 default person properties ($app_version, $app_build, $os_name, $os_version, $device_type, $locale)
  • Includes configurable opt-out mechanism via setDefaultPersonProperties config option
  • Updates remote config initialization to support property provider callback pattern

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
PostHog/PostHogConfig.swift Adds setDefaultPersonProperties configuration option with detailed documentation
PostHog/PostHogSDK.swift Implements getDefaultPersonProperties() method and updates remote config initialization
PostHog/PostHogRemoteConfig.swift Updates constructor to accept property provider callback and merges default properties
PostHogTests/PostHogSDKTest.swift Adds comprehensive tests for enabled/disabled default properties scenarios
PostHogTests/*.swift Updates test helper constructors to include property provider callback
PostHogExample/ContentView.swift Updates documentation comments explaining automatic property behavior
CHANGELOG.md Documents the new feature

Copy link
Member

@marandaneto marandaneto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left a last comment otherwise LGTM

@github-project-automation github-project-automation bot moved this from In Review to Approved in Feature Flags Jul 24, 2025
@dmarticus dmarticus moved this from Approved to In Review in Feature Flags Jul 24, 2025
haacked added 8 commits July 24, 2025 09:05
This ensures consistent API design patterns for Objective-C interoperability
and provides clear semantics for the method parameters.
- Add setGroupPropertiesForFlagsIfNeeded helper method
- Automatically set person properties for flags in capture() method when userProperties or userPropertiesSetOnce are provided
- Automatically set group properties for flags in group() method when groupProperties are provided

This ensures feature flag evaluation has access to the latest properties without requiring manual calls to setPersonPropertiesForFlags or setGroupPropertiesForFlags.
- Test that capture() with userProperties automatically sets person properties for flags
- Test that group() with groupProperties automatically sets group properties for flags

These tests verify that feature flag evaluation has access to properties passed to capture() and group() methods without requiring manual calls to the property setter methods.
…tify

This improves code organization by:
- Making groupIdentify fully responsible for all group-related operations
- Matching the pattern used in identify() for consistency
- Ensuring flag properties are set even if groupIdentify is called from other places in the future
- Simplifying the public group() method to only handle validation and delegation
- Add hasPersonProcessing() check to setPersonPropertiesForFlags
- Add hasPersonProcessing() check to setGroupPropertiesForFlags
- Add hasPersonProcessing() check to resetPersonPropertiesForFlags
- Add hasPersonProcessing() check to resetGroupPropertiesForFlags

This ensures consistency with internal helper methods and prevents setting properties for feature flags when person processing is disabled (e.g., when personProfiles is set to 'never').
- Add optional reloadFeatureFlags parameter to setGroupPropertiesForFlags for consistency with setPersonPropertiesForFlags
- Maintain backward compatibility with a convenience overload that defaults to true
- Update documentation to explain both usage patterns

This allows users to batch multiple group property updates before reloading flags, improving performance when setting properties for multiple groups.
- Remove 'test' prefix from @test methods (Swift Testing convention)
- Remove trailing spaces from all lines

These changes comply with the project's SwiftFormat and SwiftLint rules.
Clear personPropertiesForFlags and groupPropertiesForFlags when resetting
the SDK storage. This ensures that cached feature flag properties are
properly cleaned up during reset operations.
@haacked
Copy link
Contributor Author

haacked commented Jul 24, 2025

I'm going to merge this into haacked/366-attach-properties and lets continue the work there.

@haacked haacked merged commit ab86981 into haacked/366-attach-properties Jul 24, 2025
6 of 7 checks passed
@haacked haacked deleted the haacked/default-properties branch July 24, 2025 17:43
@github-project-automation github-project-automation bot moved this from In Review to Done in Feature Flags Jul 24, 2025
haacked added a commit that referenced this pull request Jul 24, 2025
…erty reading

Addresses PR feedback from #375 by creating a centralized method for
extracting person properties from the context. This eliminates code
duplication and creates a single source of truth for property keys,
making future refactoring easier.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants