Skip to content

Conversation

wpinho-branch
Copy link
Collaborator

@wpinho-branch wpinho-branch commented Oct 2, 2025

Reference

EMT-2309 -- Add Class BNCServerRequestOperation.

Summary

This PR implements Swift Concurrency (async/await) patterns for the iOS Branch SDK, mirroring the Android Kotlin Coroutines implementation. The changes introduce modern asynchronous request processing using Swift Actors and structured concurrency while maintaining full backward compatibility with existing Objective-C code.

Key Components:

  • BranchRequestOperation: Modern async/await operation for request processing
  • BranchRequestQueue: Actor-based thread-safe queue management
  • ConfigurationController: SDK configuration telemetry in Swift
  • Swift Package Manager (SPM) integration with dual-target architecture
  • Objective-C ↔ Swift bridge with runtime detection and dynamic invocation

Motivation

The iOS SDK currently uses legacy GCD-based asynchronous patterns, while the Android SDK has migrated to modern Kotlin Coroutines. This creates architectural inconsistency between platforms and makes the codebase harder to maintain.

Benefits of Swift Concurrency:

  1. Architectural Parity: iOS now matches Android's modern async patterns
  2. Type Safety: Compile-time guarantees replacing runtime dispatch queue bugs
  3. Performance: Actor isolation eliminates race conditions without manual locking
  4. Maintainability: Structured concurrency replaces callback pyramids
  5. Developer Experience: async/await syntax is more readable and debuggable

Technical Alignment:

  • Android: CoroutineScope + Channel → iOS: Actor + AsyncStream
  • Android: Dispatchers.IO → iOS: Task.detached
  • Android: Dispatchers.Main → iOS: @MainActor

Type Of Change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

Testing Instructions

1. Build Verification

# Build the SPM package
xcodebuild -scheme BranchSDK \
    -destination 'platform=iOS Simulator,name=iPhone 16' \
    build

2. Runtime Verification

Run the Branch-TestBed app and verify console output shows:

🎉 ================================================
   ✅ SWIFT CONCURRENCY IS ACTIVE!
================================================
✅ BranchRequestOperation (Swift): FOUND
✅ BranchRequestQueue (Swift): FOUND
🚀 Using modern async/await patterns

3. Functional Testing

  • Open request should execute using Swift implementation
  • Event logging should work correctly
  • SDK initialization should complete successfully
  • No crashes or undefined symbol errors

4. Backward Compatibility

  • iOS < 13.0: Falls back gracefully to Objective-C implementation
  • Existing Objective-C code: Works without modifications
  • SPM integration: Works alongside existing CocoaPods/Carthage

5. Code Quality Checks

# Run unit tests
xcodebuild test -scheme Branch-SDK-Tests \
    -destination 'platform=iOS Simulator,name=iPhone 16'

# Verify no duplicate symbols
nm -gU <framework_path> | grep -i "branch" | sort | uniq -d

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • Swift files include comprehensive inline documentation
  • Objective-C bridge includes fallback logic and error handling
  • @objc annotations ensure proper Swift/ObjC interoperability
  • Build succeeds on iOS 12.0+ (backward compatibility verified)
  • Swift Concurrency activates on iOS 13.0+ (tested on simulator)
  • No breaking changes to existing public API

Implementation Details

Architecture

┌─────────────────────────────────────────────────┐
│         BranchSDK (SPM Package)                 │
├─────────────────────────────────────────────────┤
│  BranchSDK Target (Objective-C)                 │
│  ├── BNCServerRequestOperation.m (Bridge)       │
│  ├── BNCServerRequestQueue.m                    │
│  └── Public Headers (BranchSDK.h, etc.)         │
├─────────────────────────────────────────────────┤
│  BranchSwiftSDK Target (Swift 5.9+)             │
│  ├── BranchRequestOperation.swift (Actor)       │
│  ├── BranchRequestQueue.swift (Actor)           │
│  └── ConfigurationController.swift              │
└─────────────────────────────────────────────────┘

Runtime Detection Flow

  1. BNCServerRequestOperation checks iOS version (≥13.0)
  2. Uses NSClassFromString() to detect Swift classes
  3. Dynamically invokes Swift initializer via NSInvocation
  4. Falls back to Objective-C if Swift unavailable
  5. Logs implementation choice for debugging

cc @BranchMetrics/saas-sdk-devs for visibility.

https://branch.atlassian.net/browse/EMT-2309

-> Removed DeepLinkDemo, TestDeepLinking and TestHost Apps for the repo.
-> Removed Unit tests from Branch Test Bed App
-> Added Test Host App and Unit tests to BranchSDK Workspace.
NidhiDixit09 and others added 14 commits July 15, 2025 22:21
This commit introduces modern Swift Concurrency patterns to the iOS Branch SDK, mirroring the Android Kotlin Coroutines implementation. The changes enable async/await request processing, actor-based thread safety, and structured concurrency throughout the SDK.

## Swift Concurrency Implementation

Added three core Swift files using modern concurrency patterns:
- `BranchRequestOperation.swift`: Actor-isolated async operation for processing Branch server requests with structured concurrency, automatic main thread dispatching for callbacks, and session validation matching Android's implementation
- `BranchRequestQueue.swift`: Actor-based request queue with serial execution, async/await API, and thread-safe queue management replacing manual NSOperationQueue patterns
- `ConfigurationController.swift`: Swift configuration management with async initialization and proper error handling

Architecture parallels to Android:
- Android: CoroutineScope + Channel → iOS: Actor + AsyncStream
- Android: Dispatchers.IO → iOS: Task.detached
- Android: Dispatchers.Main → iOS: MainActor

## Swift Package Manager (SPM) Integration

Updated Package.swift to define dual-target architecture:
- `BranchObjCSDK`: Core Objective-C framework with all existing functionality
- `BranchSDK`: Swift wrapper exposing async/await APIs and importing BranchObjCSDK

This enables seamless Swift integration while maintaining full Objective-C compatibility.

## Objective-C Bridge Enhancements

Modified `BNCServerRequestOperation.m` to support Swift interop:
- Added Swift availability checks (@available decorators)
- Integrated async callback completion handling
- Maintained backward compatibility with existing Objective-C code

Updated `BNCServerRequestQueue.m` and `BNCRequestFactory.m` for improved Swift interaction.

## Public API Visibility Changes

Moved `BNCConfig.h` from Private to Public headers to enable SPM package visibility.

Added `BranchConstants.h` and `BranchConstants.m` to public BranchSDK directory for proper module exposure.

## Test Infrastructure Updates

Updated 16 test files to use modular imports:
- Changed from `#import "Branch.h"` to `@import BranchSDK`
- Updated bridging headers for Swift/Objective-C interop
- Modified test schemes to support SPM package dependencies

Test files updated:
- BNCAPIServerTest.m, BNCODMTests.m, BNCPasteboardTests.m
- BNCPreferenceHelperTests.m, BranchActivityItemTests.m
- BranchClassTests.m, BranchLoggerTests.m, BranchQRCodeTests.m
- BranchShareLinkTests.m, DispatchToIsolationQueueTests.m
- Branch_setBranchKeyTests.m
- UITestCaseMisc.m, UITestCaseTracking.m, UITestSendV2Event.m
- UITestSetIdentity.m, Branch-SDK-Tests-Bridging-Header.h

## Branch-TestBed Configuration

Updated Branch-TestBed Xcode project:
- Configured SPM package dependency reference
- Updated project.pbxproj with proper target dependencies
- Removed Package.resolved to allow flexible dependency resolution
- Updated all test schemes for SPM compatibility
- Modified AppDelegate.m and ViewControllers for async initialization

## Project Structure Cleanup

Organized source files into proper directory structure:
- Created `Sources/BranchSwiftSDK/` for Swift implementation
- Moved configuration files to appropriate locations
- Removed duplicate/temporary Swift files from previous iterations
- Updated both BranchSDK.xcodeproj and Package.swift configurations

## Key Features

- Structured concurrency with proper cancellation support
- Actor-based thread safety eliminating race conditions
- Automatic main thread dispatching for UI callbacks
- Session validation matching Android implementation
- Performance optimized with cooperative thread pool
- Serial request processing ensuring proper ordering
- Modern async/await API for Swift developers
- Full backward compatibility with existing Objective-C code
Copy link
Contributor

Code Quality New Feature Architectural Improvement Testing Enhancement

Summary By MatterAI MatterAI logo

🔄 What Changed

This Pull Request, titled "EMT-2309: Implement Swift Concurrency for iOS SDK mirroring Android Kotlin Coroutines," introduces foundational changes to integrate Swift Concurrency into the iOS SDK. Key updates include upgrading GitHub Actions runners to macos-15 and simplifying CI unit test execution by replacing Fastlane with direct xcodebuild commands. The .gitignore file was updated to include .build and .vscode for modern Swift development. Crucially, numerous Objective-C test files were modernized to use @import BranchSDK; for improved module management. The BranchSDK.podspec was significantly updated to declare support for Swift versions 5.0 through 6.0 and to include new Sources/BranchSDK_Swift and Sources/BranchSDK_ObjC directories, indicating the integration of new Swift-based concurrency components. A substantial suite of new Objective-C test files and a new BranchSDKTestsHostApp were added to provide comprehensive validation for the SDK's functionality, including specific checks in AppDelegate.m to verify the runtime presence and activation of Swift Concurrency classes like BranchRequestOperation and BranchRequestQueue.

🔍 Impact of the Change

This PR lays critical groundwork for a major architectural shift towards Swift Concurrency, aiming to align the iOS SDK's asynchronous patterns with Android's Kotlin Coroutines. The CI/CD improvements streamline the development and testing pipeline, while the module import changes enhance build efficiency and maintainability for mixed-language projects. The extensive addition of new tests significantly boosts the SDK's reliability and provides a robust framework for validating the new concurrency model. The explicit inclusion of Swift source directories in the Podspec and the runtime verification logic in AppDelegate.m confirm the active integration and testing of Swift Concurrency, promising improved performance, responsiveness, and thread safety for the SDK's operations.

📁 Total Files Changed

  • .github/workflows/pre-release-qa.yml: Updated macOS runner version. ⚙️
  • .github/workflows/verify.yml: Refactored unit test workflow, updated macOS runner. 🚀
  • .gitignore: Added .build and .vscode to ignored files. 🧹
  • Branch-TestBed/Branch-SDK-Tests/*.m (14 files): Updated Objective-C imports to @import BranchSDK;. 📦
  • Branch-TestBed/Branch-TestBed.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: Removed SPM package resolution file. 🗑️
  • Branch-TestBed/Branch-TestBed/AppDelegate.m: Updated imports and added Swift Concurrency runtime verification logic. 🔬
  • Branch-TestBed/Branch-TestBed/NavigationController.h: Updated Objective-C import. 📦
  • Branch-TestBed/Branch-TestBed/PasteControlViewController.m: Updated Objective-C imports. 📦
  • Branch-TestBed/Branch-TestBed/ViewController.m: Updated Objective-C imports. 📦
  • BranchSDK.podspec: Added Swift version support and new Swift/Objective-C source file paths. 🍎
  • BranchSDKTests/BNCAPIServerTest.m: Added new API server URL tests. ✅
  • BranchSDKTests/BNCAppleReceiptTests.m: Added new Apple receipt tests. ✅
  • BranchSDKTests/BNCApplicationTests.m: Added new application info tests. ✅
  • BranchSDKTests/BNCCallbackMapTests.m: Added new callback map tests. ✅
  • BranchSDKTests/BNCClassSerializationTests.m: Added new class serialization tests. ✅
  • BranchSDKTests/BNCCrashlyticsWrapperTests.m: Added new Crashlytics wrapper tests. ✅
  • BranchSDKTests/BNCCurrencyTests.m: Added new currency enum tests. ✅
  • BranchSDKTests/BNCDeviceInfoTests.m: Added new device info tests. ✅
  • BranchSDKTests/BNCDeviceSystemTests.m: Added new device system tests. ✅
  • BranchSDKTests/BNCDisableAdNetworkCalloutsTests.m: Added new ad network callout disable tests. ✅
  • BranchSDKTests/BNCEncodingUtilsTests.m: Added new encoding utility tests. ✅
  • BranchSDKTests/BNCJSONUtilityTests.m: Added new JSON utility tests. ✅
  • BranchSDKTests/BNCJsonLoader.h: Added new JSON loader header. ➕
  • BranchSDKTests/BNCJsonLoader.m: Added new JSON loader implementation. ➕
  • BranchSDKTests/BNCKeyChainTests.m: Added new keychain interaction tests. ✅
  • BranchSDKTests/BNCLinkDataTests.m: Added new link data hashing tests. ✅
  • BranchSDKTests/BNCNetworkInterfaceTests.m: Added new network interface tests. ✅
  • BranchSDKTests/BNCODMTests.m: Added new ODM info tests. ✅
  • BranchSDKTests/BNCPartnerParametersTests.m: Added new partner parameters tests. ✅
  • BranchSDKTests/BNCPasteboardTests.m: Added new pasteboard interaction tests. ✅
  • BranchSDKTests/BNCPreferenceHelperTests.m: Added new preference helper tests. ✅
  • BranchSDKTests/BNCReachabilityTests.m: Added new reachability tests. ✅
  • BranchSDKTests/BNCReferringURLUtilityTests.m: Added new referring URL utility tests. ✅
  • BranchSDKTests/BNCRequestFactoryTests.m: Added new request factory tests. ✅
  • BranchSDKTests/BNCSKAdNetworkTests.m: Added new SKAdNetwork tests. ✅
  • BranchSDKTests/BNCSystemObserverTests.m: Added new system observer tests. ✅
  • BranchSDKTests/BNCURLFilterSkiplistUpgradeTests.m: Added new URL filter skiplist upgrade tests. ✅
  • BranchSDKTests/BNCURLFilterTests.m: Added new URL filter tests. ✅
  • BranchSDKTests/BNCUserAgentCollectorTests.m: Added new user agent collector tests. ✅
  • BranchSDKTests/Branch-SDK-Tests-Bridging-Header.h: Added new bridging header for tests. ➕
  • BranchSDKTests/BranchActivityItemTests.m: Added new activity item tests. ✅
  • BranchSDKTests/BranchClassTests.m: Added new Branch class method tests. ✅
  • BranchSDKTests/BranchConfigurationControllerTests.m: Added new configuration controller tests. ✅
  • BranchSDKTests/BranchEvent.Test.m: Added new Branch event tests. ✅
  • BranchSDKTests/BranchEvent.Test.swift: Added new Swift Branch event tests (commented out). 📝
  • BranchSDKTests/BranchLastAttributedTouchDataTests.m: Added new last attributed touch data tests. ✅
  • BranchSDKTests/BranchLoggerTests.m: Added new logger tests. ✅
  • BranchSDKTests/BranchPluginSupportTests.m: Added new plugin support tests. ✅
  • BranchSDKTests/BranchQRCodeTests.m: Added new QR code generation and cache tests. ✅
  • BranchSDKTests/BranchSDKTests.m: Added new basic SDK tests. ✅
  • BranchSDKTests/BranchSDKTests.xctestplan: Added new Xcode test plan. 📋
  • BranchSDKTests/BranchShareLinkTests.m: Added new share link tests. ✅
  • BranchSDKTests/BranchUniversalObjectTests.m: Added new universal object tests. ✅
  • BranchSDKTests/DispatchToIsolationQueueTests.m: Added new dispatch queue tests (commented out). 📝
  • BranchSDKTests/NSErrorBranchTests.m: Added new NSError category tests. ✅
  • BranchSDKTests/NSMutableDictionaryBranchTests.m: Added new NSMutableDictionary category tests. ✅
  • BranchSDKTests/NSStringBranchTests.m: Added new NSString category tests. ✅
  • BranchSDKTestsHostApp/AppDelegate.h: Added new host app AppDelegate header. ➕
  • BranchSDKTestsHostApp/AppDelegate.m: Added new host app AppDelegate implementation. ➕
  • BranchSDKTestsHostApp/Base.lproj/Main.storyboard: Renamed storyboard, updated custom module provider. 🎨
  • BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements: Updated associated domains for app links. 🔗
  • BranchSDKTestsHostApp/SceneDelegate.h: Added new host app SceneDelegate header. ➕
  • BranchSDKTestsHostApp/SceneDelegate.m: Added new host app SceneDelegate implementation. ➕
  • BranchSDKTestsHostApp/ViewController.h: Added new host app ViewController header. ➕
  • BranchSDKTestsHostApp/ViewController.m: Added new host app ViewController implementation. ➕

🧪 Test Added

This PR includes a massive addition of new tests, covering almost every aspect of the SDK. Key areas include:

  • API Server Interactions: BNCAPIServerTest.m verifies correct URL generation for various Branch API endpoints (install, open, events, links, QR codes, LATD, validation) under different configurations (tracking domain, EU servers).
  • Device and System Info: BNCDeviceInfoTests.m, BNCDeviceSystemTests.m, BNCSystemObserverTests.m, and BranchPluginSupportTests.m thoroughly test the collection and reporting of device and system attributes (hardware ID, OS version, screen dimensions, locale, user agent, plugin info).
  • Utility Classes: BNCEncodingUtilsTests.m, BNCJSONUtilityTests.m, NSMutableDictionaryBranchTests.m, NSStringBranchTests.m validate various encoding, JSON parsing, and string/dictionary utility methods. BNCCallbackMapTests.m tests the request callback management.
  • SDK Core Functionality: BranchClassTests.m covers core Branch class methods like isUserIdentified, disableAdNetworkCallouts, setNetworkTimeout, setRequestMetadataKey, setTrackingDisabled, checkPasteboardOnInstall, setAppClipAppGroup, addFacebookPartnerParameter, getFirstReferringBranchUniversalObject, getShortURL, and DMA parameters. BNCPasteboardTests.m tests pasteboard interactions and Branch link detection. BranchQRCodeTests.m verifies QR code generation and caching. BNCSKAdNetworkTests.m includes extensive tests for SKAdNetwork 4.0 parameters, conversion value updates, and postback logic. BNCReferringURLUtilityTests.m validates parsing and extraction of referring URL query parameters like gclid and gbraid, including data migration logic. BranchUniversalObjectTests.m and BranchEvent.Test.m provide comprehensive tests for Branch Universal Objects and Branch Events, including their serialization and dictionary representations. BranchConfigurationControllerTests.m specifically tests the configuration settings related to the new Swift concurrency components.
  • CI/CD Integration: The updated verify.yml and pre-release-qa.yml workflows ensure these tests are run in a modern macos-15 environment, and the new BranchSDKTestsHostApp provides a dedicated environment for hosted tests.

🔒 Security Vulnerabilities

No direct security vulnerabilities were detected. The extensive test coverage, particularly for URL filtering (BNCURLFilterTests.m, BNCURLFilterSkiplistUpgradeTests.m), input parsing (BNCEncodingUtilsTests.m), and partner parameters (BNCPartnerParametersTests.m), enhances the SDK's overall security posture by reducing potential attack surfaces and ensuring robust data handling.

Tip

Quality Recommendations

  1. Address the commented-out BranchEvent.Test.swift and DispatchToIsolationQueueTests.m files. Either remove them if no longer relevant or fix and enable them to ensure full test coverage for all components, especially new Swift concurrency features.

  2. Ensure comprehensive documentation for the new Swift Concurrency components, detailing their architecture, usage, and interaction with existing Objective-C code to aid future development and maintenance.

  3. Consider adding specific performance benchmarks for the new Swift Concurrency implementation to quantify improvements and identify potential bottlenecks.

Tanka Poem ♫

Swift's new async,
Coroutines now iOS grace,
Tests bloom, strong and vast,
Old ways fade, new paths emerge,
Code flows, a river renewed. 🚀

Sequence Diagram

sequenceDiagram
    participant CI as GitHub Actions CI
    participant Dev as Developer
    participant Podspec as BranchSDK.podspec
    participant Xcode as Xcode Build System
    participant ObjC as Objective-C Code
    participant Swift as Swift Concurrency Code
    participant App as Branch-TestBed App
    participant BranchAPI as Branch API Servers

    CI->>Dev: Push to PR branch
    CI->>CI: Trigger `pre-release-qa.yml` & `verify.yml`
    Note over CI: Update `runs-on` to `macos-15`
    CI->>Xcode: `xcodebuild test -scheme BranchSDKTests`

    Xcode->>Podspec: Read `s.swift_versions` & `s.source_files`
    Note over Podspec: Include `Sources/BranchSDK_Swift/**/*.swift`
    Xcode->>ObjC: Compile existing Objective-C files
    Xcode->>Swift: Compile new Swift Concurrency files
    Note over ObjC,Swift: `@import BranchSDK;` for module imports

    App->>ObjC: `application:didFinishLaunchingWithOptions:`
    ObjC->>App: Call `[Branch getInstance]`
    App->>ObjC: Call `[branch checkPasteboardOnInstall]`

    App->>ObjC: Execute Swift Concurrency verification logic
    ObjC->>Swift: `NSClassFromString("BranchSwiftSDK.BranchRequestOperation")`
    Swift-->>ObjC: Return class reference if found
    ObjC->>Swift: `NSClassFromString("BranchSwiftSDK.BranchRequestQueue")`
    Swift-->>ObjC: Return class reference if found
    ObjC->>App: Log verification status (active/not active)

    App->>ObjC: SDK operations (e.g., `logEvent`)
    ObjC->>Swift: Delegate async operations to Swift Concurrency
    Swift->>BranchAPI: Perform network requests (e.g., `/v1/install`, `/v2/event/standard`)
    BranchAPI-->>Swift: API Response
    Swift-->>ObjC: Processed result
    ObjC-->>App: Callback with result

    CI->>Xcode: Run extensive new test suite
    Xcode->>ObjC: Execute `BranchSDKTests` (e.g., `BNCAPIServerTest`, `BNCSKAdNetworkTests`)
    ObjC-->>Xcode: Test results
    Xcode-->>CI: Report test status
Loading

Copy link
Contributor

Important

PR Review Skipped

PR review skipped as per the configuration setting. Run a manually review by commenting /matter review

💡Tips to use MatterAI

Command List

  • /matter summary: Generate AI Summary for the PR
  • /matter review: Generate AI Reviews for the latest commit in the PR
  • /matter review-full: Generate AI Reviews for the complete PR
  • /matter release-notes: Generate AI release-notes for the PR
  • /matter : Chat with your PR with MatterAI Agent
  • /matter remember : Generate AI memories for the PR
  • /matter explain: Get an explanation of the PR
  • /matter help: Show the list of available commands and documentation
  • Need help? Join our Discord server: https://discord.gg/fJU5DvanU3

@wpinho-branch wpinho-branch changed the title EMT-2309: Implement Swift Concurrency for iOS SDK mirroring Android Kotlin Coroutines EMT-2309: Add Class BNCServerRequestOperation. Oct 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants