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 15 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
@matter-code-review
Copy link
Contributor

matter-code-review bot commented Oct 2, 2025

Summary By MatterAI MatterAI logo

🔄 What Changed

This Pull Request finalizes the integration of Swift Concurrency into the iOS Branch SDK, building upon the foundational setup from previous changes. It introduces the core BranchRequestOperation.swift for modern async/await request processing and BranchRequestQueue.swift for actor-based, thread-safe queue management, directly mirroring the Android Kotlin Coroutines implementation. The existing BNCServerRequestOperation.m is refactored to dynamically bridge to the new Swift operation on iOS 13+ devices, gracefully falling back to its Objective-C implementation for older OS versions. A new ConfigurationController.swift is added for SDK configuration telemetry, which is dynamically accessed by BNCRequestFactory.m and Branch.m. The Package.swift file is updated to define a dual-target architecture for Swift Package Manager, separating BranchSDK (Objective-C) and BranchSwiftSDK (Swift). Additionally, BranchConstants are consolidated into dedicated .h and .m files, and numerous Objective-C test files are updated to use the @import BranchSDK; module import syntax for improved modularity.

🔍 Impact of the Change

This PR represents a significant architectural modernization, bringing structured concurrency, enhanced thread safety, and improved maintainability to the iOS SDK. It achieves architectural parity with the Android SDK, leveraging Swift's async/await and Actors for robust asynchronous operations. The dynamic bridging ensures seamless backward compatibility for iOS versions below 13.0, while runtime verification logic in AppDelegate.m provides clear console feedback on the successful activation of the new Swift concurrency components. This transition is expected to improve performance, responsiveness, and developer experience by replacing legacy GCD-based patterns with modern Swift paradigms.

📁 Total Files Changed

File ChangeLog
Test Import Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/BNCPasteboardTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/Branch-SDK-Tests-Bridging-Header.h Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/BranchActivityItemTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/BranchLoggerTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/BranchQRCodeTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/BranchShareLinkTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Tests/DispatchToIsolationQueueTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-SDK-Unhosted-Tests/Branch_setBranchKeyTests.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-TestBed-UITests/UITestCaseMisc.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-TestBed-UITests/UITestCaseTracking.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-TestBed-UITests/UITestSendV2Event.m Updated import to @import BranchSDK;.
Test Import Branch-TestBed/Branch-TestBed-UITests/UITestSetIdentity.m Updated import to @import BranchSDK;.
SPM Config Branch-TestBed/Branch-TestBed.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Removed SPM package resolution file.
App Delegate Branch-TestBed/Branch-TestBed/AppDelegate.m Updated imports and added Swift Concurrency runtime verification.
Nav Controller Branch-TestBed/Branch-TestBed/NavigationController.h Updated import to @import BranchSDK;.
Paste Control Branch-TestBed/Branch-TestBed/PasteControlViewController.m Updated imports to @import BranchSDK;.
View Controller Branch-TestBed/Branch-TestBed/ViewController.m Updated imports to @import BranchSDK;.
SPM Package Package.swift Refactored SPM configuration for BranchSDK and BranchSwiftSDK targets.
Request Factory Sources/BranchSDK/BNCRequestFactory.m Added dynamic Swift ConfigurationController access and Swift bridging header logic.
Request Operation Sources/BranchSDK/BNCServerRequestOperation.m Refactored to dynamically bridge to Swift BranchRequestOperation on iOS 13+.
Request Queue Sources/BranchSDK/BNCServerRequestQueue.m Updated import for BNCServerRequestOperation.h.
Bridging Header Sources/BranchSDK/Branch-Bridging-Header.h Added new bridging header for Objective-C types to Swift.
Core SDK Sources/BranchSDK/Branch.m Updated dynamic Swift ConfigurationController access and Swift bridging header logic.
Config Controller Sources/BranchSDK/BranchConfigurationController.m Updated import for BranchConfigurationController.h.
Constants Impl Sources/BranchSDK/BranchConstants.m Added new file defining all Branch SDK string constants.
Constants Header Sources/BranchSDK/Public/BranchConstants.h Added new public header for Branch SDK string constants.
Public Header Sources/BranchSDK/Public/BranchSDK.h Added import for BNCConfig.h.
Swift Operation Sources/BranchSwiftSDK/BranchRequestOperation.swift Added new Swift Concurrency Operation for request processing.
Swift Queue Sources/BranchSwiftSDK/BranchRequestQueue.swift Added new Actor-based Swift Concurrency request queue.
Swift Config Sources/BranchSwiftSDK/ConfigurationController.swift Renamed/modified Swift ConfigurationController for SDK telemetry.

🧪 Test Added/Recommended

Added

This PR leverages the existing extensive test suite, with key verification steps integrated into the Branch-TestBed application's AppDelegate.m. This includes:

  • Runtime Swift Concurrency Activation Check: AppDelegate.m now contains explicit NSClassFromString checks to verify the presence and accessibility of BranchSwiftSDK.BranchRequestOperation and BranchSwiftSDK.BranchRequestQueue (or BranchSDK.BranchRequestOperation/BranchSDK.BranchRequestQueue for non-SPM builds) at runtime. This provides immediate console feedback (✅ SWIFT CONCURRENCY IS ACTIVE!) confirming the successful dynamic loading and bridging to the new Swift implementation on iOS 13+.
  • Shared Instance Accessibility: Further runtime checks in AppDelegate.m ensure that the BranchRequestQueue.shared instance is accessible via dynamic invocation, validating the Objective-C bridge to the Swift Actor.

Recommended

  • Dedicated Swift Unit Tests: While the Objective-C bridge is tested, consider adding dedicated unit tests directly within the BranchSwiftSDK target for BranchRequestOperation.swift and BranchRequestQueue.swift. This would ensure the internal logic of the Swift concurrency components is thoroughly validated in isolation, independent of the Objective-C bridging mechanism.
  • Concurrency Edge Case Testing: Implement tests specifically designed to stress the new Swift concurrency model, including scenarios with rapid request enqueueing, concurrent cancellations, and various network error conditions, to ensure robustness and thread safety.

🔒Security Vulnerabilities

No new security vulnerabilities were detected. The architectural shift to Swift Concurrency, with its actor-based thread safety and structured error handling, inherently improves the reliability and robustness of the SDK, indirectly contributing to a more secure codebase by reducing common concurrency-related bugs that could lead to unpredictable behavior or crashes.

@matter-code-review
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
wpinho-branch added a commit that referenced this pull request Nov 20, 2025
Work in progress on removing legacy Objective-C bridging code and adding modern Swift implementations to the 4.0.0-alpha.0 branch.

Changes:
- Added Swift implementations from PR #1533:
  - BranchRequestQueue.swift (Actor-based queue with Swift Concurrency)
  - BranchRequestOperation.swift (Modern operation implementation)
  - ConfigurationController.swift (Configuration management)

- Updated Package.swift:
  - Upgraded swift-tools-version to 5.9
  - Added BranchSwiftSDK target
  - Updated paths and dependencies

- Removed bridging files:
  - Deleted BNCServerRequestQueue.m and BNCServerRequestQueue.h
  - Removed 16 references from Xcode project

- Updated Branch.m:
  - Removed import of BNCServerRequestQueue.h
  - Commented out legacy error handling code that used remove: and peekAt: methods
    (These methods are incompatible with NSOperationQueue implementation)

- Updated Branch.h:
  - Removed import of BNCServerRequestQueue.h
  - Added forward declarations for BNCServerRequestQueue and BNCServerRequest

STATUS: Build currently failing with compilation errors. Additional work needed to:
1. Fix remaining compilation errors in dependent files
2. Implement proper error handling for NSOperationQueue-based request queue
3. Test framework and app builds
4. Complete migration to Swift implementations

This is part of the broader effort to modernize the iOS Branch SDK with Swift Concurrency patterns (async/await, actors) while maintaining backward compatibility.
wpinho-branch added a commit that referenced this pull request Nov 20, 2025
Major changes from PR #1533:

1. Updated BNCServerRequestQueue implementation:
   - Replaced NSMutableArray with NSOperationQueue for serial processing
   - Added configureWithServerInterface:branchKey:preferenceHelper: method
   - Added enqueue:withPriority: for request prioritization
   - Automatic request processing (no manual peek/remove needed)

2. Added BNCServerRequestOperation:
   - New NSOperation subclass for async request execution
   - Handles session validation and error processing
   - Integrates with BNCCallbackMap for event callbacks

3. Updated Branch.m:
   - Removed manual queue processing (processNextQueueItem calls)
   - Removed insertRequestAtFront: method (priority via NSOperationQueue)
   - Added queue configuration in init
   - Simplified request enqueueing (automatic processing)

4. Updated Xcode project:
   - Added BNCServerRequestOperation.m to compile sources
   - Added BNCServerRequestOperation.h to Private headers

Architecture improvements:
- Serial queue execution via maxConcurrentOperationCount = 1
- Automatic operation lifecycle management
- Better separation of concerns (queue vs operations)
- Foundation for future Swift migration

Build status: ✅ SUCCESS
@matter-code-review
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

@NidhiDixit09
Copy link
Collaborator

@wpinho-branch There are two BranchConstants.m files. One at the original location and one inside BranchSDK_ObjC directory. We should keep only one.
I have skipped review of all *.swift files which are removed in later PR.
Rest of the code looks good to me.

@NidhiDixit09
Copy link
Collaborator

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