diff --git a/.github/workflows/pre-release-qa.yml b/.github/workflows/pre-release-qa.yml index 0a2d30548..34b0bffa1 100644 --- a/.github/workflows/pre-release-qa.yml +++ b/.github/workflows/pre-release-qa.yml @@ -4,7 +4,7 @@ on: [push] jobs: verify-cocoapods-iOS: - runs-on: macos-latest + runs-on: macos-15 steps: - name: Check out code uses: actions/checkout@v4 @@ -33,7 +33,7 @@ jobs: carthage update --use-xcframeworks xcodebuild test -scheme iOSReleaseTest -project iOSReleaseTest.xcodeproj -destination "$DESTINATION" | xcpretty && exit ${PIPESTATUS[0]} verify-SPM-iOS: - runs-on: macos-latest + runs-on: macos-15 steps: - name: Check out code uses: actions/checkout@v4 @@ -44,7 +44,7 @@ jobs: cd SDKIntegrationTestApps/iOSReleaseTest-SPM/ xcodebuild test -scheme iOSReleaseTest -project iOSReleaseTest.xcodeproj -destination "$DESTINATION" | xcpretty && exit ${PIPESTATUS[0]} verify-manually-with-xcframework-iOS: - runs-on: macos-latest + runs-on: macos-15 steps: - name: Check out code uses: actions/checkout@v4 @@ -56,7 +56,7 @@ jobs: cd SDKIntegrationTestApps/iOSReleaseTest-Manual/ xcodebuild test -scheme iOSReleaseTest -project iOSReleaseTest.xcodeproj -destination "$DESTINATION" | xcpretty && exit ${PIPESTATUS[0]} verify-manually-with-StaticFramework-iOS: - runs-on: macos-latest + runs-on: macos-15 steps: - name: Check out code uses: actions/checkout@v4 @@ -68,7 +68,7 @@ jobs: cd SDKIntegrationTestApps/iOSReleaseTest-Manual-Static/ xcodebuild test -scheme iOSReleaseTest -project iOSReleaseTest.xcodeproj -destination "$DESTINATION" | xcpretty && exit ${PIPESTATUS[0]} verify-cocoapods-tvOS: - runs-on: macos-latest + runs-on: macos-15 steps: - name: Check out code uses: actions/checkout@v4 @@ -80,7 +80,7 @@ jobs: pod install xcodebuild test -scheme tvOSReleaseTest -workspace tvOSReleaseTest.xcworkspace -destination "$DESTINATION" | xcpretty && exit ${PIPESTATUS[0]} verify-carthage-tvOS: - runs-on: macos-latest + runs-on: macos-15 steps: - name: Check out code uses: actions/checkout@v4 @@ -91,7 +91,7 @@ jobs: cd SDKIntegrationTestApps/tvOSReleaseTest-Carthage/ echo "Skipping it ... its broken" verify-manually-with-xcframework-tvOS: - runs-on: macos-latest + runs-on: macos-15 steps: - name: Check out code uses: actions/checkout@v4 diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 92bc6a408..9158493b5 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -13,37 +13,13 @@ jobs: steps: - name: Check out code uses: actions/checkout@v4 - - name: Set up Ruby 2.7 - uses: ruby/setup-ruby@v1 - with: - ruby-version: '2.7' - - name: Restore cache - uses: actions/cache@v3 - with: - path: | - vendor - Branch-TestBed/Pods - key: ${{ runner.os }}-${{ hashFiles('Gemfile.lock','Branch-TestBed/Podfile.lock') }} - restore-keys: | - ${{ runner.os }}- - - name: Install Ruby dependencies - run: | - bundle config set --local path vendor - bundle check || bundle install - # This happens automatically with the unit_tests lane, but adding it here - # makes it easier to keep track of installation time via GHA without - # adding execution time to the next step. - #- name: Install CocoaPods dependencies - # run: bundle exec fastlane prepare_pods - name: Run unit tests - run: bundle exec fastlane unit_tests - - name: Upload test results - uses: actions/upload-artifact@v4 - if: always() # even if tests fail - with: - name: test-results - path: fastlane/test_output - - name: Upload codecov results - uses: codecov/codecov-action@v5 - with: - files: ./fastlane/test_output/cobertura.xml + run: | + echo "branch=${{ github.ref }}" >> $GITHUB_OUTPUT + ./scripts/getSimulator + DESTINATION="platform=iOS Simulator,name=$(cat ./iphoneSim),OS=latest" + xcodebuild test \ + -project BranchSDK.xcodeproj \ + -scheme BranchSDKTests \ + -destination "$DESTINATION" \ + -testPlan BranchSDKTests | xcpretty && exit ${PIPESTATUS[0]} diff --git a/.gitignore b/.gitignore index 041577f4e..ead61c614 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ # Mac + +.build +.vscode + .DS_Store .LSOverride diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m b/Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m index 28bb3b3b3..d79235760 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m +++ b/Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m @@ -11,7 +11,7 @@ #import "BNCSystemObserver.h" #import "BNCConfig.h" #import "BranchConstants.h" -#import "Branch.h" +@import BranchSDK; @interface BNCAPIServerTest : XCTestCase diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m b/Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m index 38d1b0cc2..555449d9a 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m @@ -7,7 +7,7 @@ // #import -#import "Branch.h" +@import BranchSDK; #import "BNCPreferenceHelper.h" #import "BNCRequestFactory.h" #import "BNCEncodingUtils.h" diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCPasteboardTests.m b/Branch-TestBed/Branch-SDK-Tests/BNCPasteboardTests.m index b850ef0cd..0e2cd06bf 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BNCPasteboardTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BNCPasteboardTests.m @@ -8,7 +8,7 @@ #import #import "BNCPasteboard.h" -#import "Branch.h" +@import BranchSDK; @interface BNCPasteboardTests : XCTestCase diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m b/Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m index 5269501b3..48645e03a 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m @@ -9,7 +9,7 @@ #import #import "BNCPreferenceHelper.h" #import "BNCEncodingUtils.h" -#import "Branch.h" +@import BranchSDK; #import "BNCConfig.h" @interface BNCPreferenceHelper() diff --git a/Branch-TestBed/Branch-SDK-Tests/Branch-SDK-Tests-Bridging-Header.h b/Branch-TestBed/Branch-SDK-Tests/Branch-SDK-Tests-Bridging-Header.h index 169bd50f3..e1b9477b6 100644 --- a/Branch-TestBed/Branch-SDK-Tests/Branch-SDK-Tests-Bridging-Header.h +++ b/Branch-TestBed/Branch-SDK-Tests/Branch-SDK-Tests-Bridging-Header.h @@ -2,4 +2,4 @@ // Module headers for Branch SDK unit testing. // -#import "Branch.h" +@import BranchSDK; diff --git a/Branch-TestBed/Branch-SDK-Tests/BranchActivityItemTests.m b/Branch-TestBed/Branch-SDK-Tests/BranchActivityItemTests.m index f117859f7..0dbd515f6 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BranchActivityItemTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BranchActivityItemTests.m @@ -7,7 +7,7 @@ // #import -#import "Branch.h" +@import BranchSDK; @interface BranchActivityItemTests: XCTestCase @end diff --git a/Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m b/Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m index d1e7713f1..a0727327b 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m @@ -7,7 +7,7 @@ // #import -#import "Branch.h" +@import BranchSDK; #import "BranchConstants.h" #import "BNCPasteboard.h" #import "BNCAppGroupsData.h" diff --git a/Branch-TestBed/Branch-SDK-Tests/BranchLoggerTests.m b/Branch-TestBed/Branch-SDK-Tests/BranchLoggerTests.m index 1a4be3490..a28b775d9 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BranchLoggerTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BranchLoggerTests.m @@ -8,7 +8,7 @@ #import #import "BranchLogger.h" -#import "Branch.h" +@import BranchSDK; @interface BranchLoggerTests : XCTestCase diff --git a/Branch-TestBed/Branch-SDK-Tests/BranchQRCodeTests.m b/Branch-TestBed/Branch-SDK-Tests/BranchQRCodeTests.m index 3d1e1ffc6..9208b9052 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BranchQRCodeTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BranchQRCodeTests.m @@ -7,7 +7,7 @@ // #import -#import "Branch.h" +@import BranchSDK; #import "BranchQRCode.h" #import "BNCQRCodeCache.h" diff --git a/Branch-TestBed/Branch-SDK-Tests/BranchShareLinkTests.m b/Branch-TestBed/Branch-SDK-Tests/BranchShareLinkTests.m index c41fdb618..6306a2792 100644 --- a/Branch-TestBed/Branch-SDK-Tests/BranchShareLinkTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/BranchShareLinkTests.m @@ -9,7 +9,7 @@ #import #import "BranchShareLink.h" #import "BranchLinkProperties.h" -#import "Branch.h" +@import BranchSDK; @interface BranchShareLinkTests : XCTestCase diff --git a/Branch-TestBed/Branch-SDK-Tests/DispatchToIsolationQueueTests.m b/Branch-TestBed/Branch-SDK-Tests/DispatchToIsolationQueueTests.m index 89043aa94..e51f4c7ef 100644 --- a/Branch-TestBed/Branch-SDK-Tests/DispatchToIsolationQueueTests.m +++ b/Branch-TestBed/Branch-SDK-Tests/DispatchToIsolationQueueTests.m @@ -7,7 +7,7 @@ // #import -// #import "Branch.h" +// @import BranchSDK; @interface DispatchToIsolationQueueTests : XCTestCase // @property (nonatomic, strong, readwrite) Branch *branch; diff --git a/Branch-TestBed/Branch-SDK-Unhosted-Tests/Branch_setBranchKeyTests.m b/Branch-TestBed/Branch-SDK-Unhosted-Tests/Branch_setBranchKeyTests.m index 3792b3933..6e92febdc 100644 --- a/Branch-TestBed/Branch-SDK-Unhosted-Tests/Branch_setBranchKeyTests.m +++ b/Branch-TestBed/Branch-SDK-Unhosted-Tests/Branch_setBranchKeyTests.m @@ -7,7 +7,7 @@ // #import -#import "Branch.h" +@import BranchSDK; #import "NSError+Branch.h" // expose private methods used by tests diff --git a/Branch-TestBed/Branch-TestBed-UITests/UITestCaseMisc.m b/Branch-TestBed/Branch-TestBed-UITests/UITestCaseMisc.m index 3c992a5b6..aaf34d73e 100644 --- a/Branch-TestBed/Branch-TestBed-UITests/UITestCaseMisc.m +++ b/Branch-TestBed/Branch-TestBed-UITests/UITestCaseMisc.m @@ -7,7 +7,7 @@ // #import "UITestCaseTestBed.h" -#import "Branch.h" +@import BranchSDK; #import "BranchEvent.h" @interface UITestCaseMisc : UITestCaseTestBed diff --git a/Branch-TestBed/Branch-TestBed-UITests/UITestCaseTracking.m b/Branch-TestBed/Branch-TestBed-UITests/UITestCaseTracking.m index 95eb6f594..89e8ebbb6 100644 --- a/Branch-TestBed/Branch-TestBed-UITests/UITestCaseTracking.m +++ b/Branch-TestBed/Branch-TestBed-UITests/UITestCaseTracking.m @@ -7,7 +7,7 @@ // #import "UITestCaseTestBed.h" -#import "Branch.h" +@import BranchSDK; #import "BranchEvent.h" @interface UITestCaseTracking : UITestCaseTestBed diff --git a/Branch-TestBed/Branch-TestBed-UITests/UITestSendV2Event.m b/Branch-TestBed/Branch-TestBed-UITests/UITestSendV2Event.m index e919669e4..41491c7ae 100644 --- a/Branch-TestBed/Branch-TestBed-UITests/UITestSendV2Event.m +++ b/Branch-TestBed/Branch-TestBed-UITests/UITestSendV2Event.m @@ -7,7 +7,7 @@ // #import -#import "Branch.h" +@import BranchSDK; #import "BranchEvent.h" #import "UITestCaseTestBed.h" diff --git a/Branch-TestBed/Branch-TestBed-UITests/UITestSetIdentity.m b/Branch-TestBed/Branch-TestBed-UITests/UITestSetIdentity.m index 60e1b6f66..9e2982319 100644 --- a/Branch-TestBed/Branch-TestBed-UITests/UITestSetIdentity.m +++ b/Branch-TestBed/Branch-TestBed-UITests/UITestSetIdentity.m @@ -8,7 +8,7 @@ #import -#import "Branch.h" +@import BranchSDK; #import "BranchEvent.h" #import "UITestCaseTestBed.h" diff --git a/Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj b/Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj index c55c7fb00..802a31f30 100644 --- a/Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj +++ b/Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj @@ -11,14 +11,13 @@ 032DAF232607B59300891641 /* UITestCaseTracking.m in Sources */ = {isa = PBXBuildFile; fileRef = 032DAF222607B59300891641 /* UITestCaseTracking.m */; }; 033E096325F459C300F39CB3 /* UITestSetIdentity.m in Sources */ = {isa = PBXBuildFile; fileRef = 033E096225F459C200F39CB3 /* UITestSetIdentity.m */; }; 033E097225F541D400F39CB3 /* UITestCaseTestBed.m in Sources */ = {isa = PBXBuildFile; fileRef = 033E097125F541D400F39CB3 /* UITestCaseTestBed.m */; }; - 0372076425E8418F00F29C30 /* libBranch.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 466B58381B17773000A69EDE /* libBranch.a */; }; 0372078825E9F81100F29C30 /* UITestCaseMisc.m in Sources */ = {isa = PBXBuildFile; fileRef = 0372078725E9F81000F29C30 /* UITestCaseMisc.m */; }; 0399DD122599BF8A00CDB36E /* UITestSendV2Event.m in Sources */ = {isa = PBXBuildFile; fileRef = 0399DD112599BF8A00CDB36E /* UITestSendV2Event.m */; }; 03B49EEB25F9F315000BF105 /* UITestCase0OpenNInstall.m in Sources */ = {isa = PBXBuildFile; fileRef = 03B49EEA25F9F315000BF105 /* UITestCase0OpenNInstall.m */; }; + 40EA3FC7C54A6B3CCEBDB9F8 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; 466B584F1B17775900A69EDE /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67BBCF271A69E49A009C7DAE /* AdSupport.framework */; settings = {ATTRIBUTES = (Required, ); }; }; 466B58521B17776500A69EDE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 670016631940F51400A9E103 /* Foundation.framework */; settings = {ATTRIBUTES = (Required, ); }; }; 466B58531B17776A00A69EDE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 670016671940F51400A9E103 /* UIKit.framework */; }; - 466B58811B1778DB00A69EDE /* libBranch.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 466B58381B17773000A69EDE /* libBranch.a */; }; 4683F0761B20A73F00A432E7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 670016731940F51400A9E103 /* AppDelegate.m */; }; 46DC406E1B2A328900D2D203 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67BBCF271A69E49A009C7DAE /* AdSupport.framework */; }; 4AB16368239E3A2700D42931 /* DispatchToIsolationQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AB16367239E3A2700D42931 /* DispatchToIsolationQueueTests.m */; }; @@ -36,6 +35,7 @@ 4D93D8622098D43C00CFABA6 /* UITestSafari.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D93D8602098D43C00CFABA6 /* UITestSafari.m */; }; 4DBEFFF61FB114F900F7C41B /* ArrayPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DBEFFF51FB114F900F7C41B /* ArrayPickerView.m */; }; 4DE235641FB12C2700D4E5A9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DBEFFFB1FB12A1000F7C41B /* Main.storyboard */; }; + 5AFDEF31D95DB3252A8F146D /* (null) in Frameworks */ = {isa = PBXBuildFile; }; 5F205D05231864E800C776D1 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F205D04231864E800C776D1 /* WebKit.framework */; settings = {ATTRIBUTES = (Required, ); }; }; 5F205D062318659500C776D1 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F205D04231864E800C776D1 /* WebKit.framework */; }; 5F205D0823186AF700C776D1 /* BNCUserAgentCollectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F205D022318641700C776D1 /* BNCUserAgentCollectorTests.m */; }; @@ -43,51 +43,8 @@ 5F3D671C233062FD00454FF1 /* BNCJsonLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F3D671A233062FD00454FF1 /* BNCJsonLoader.m */; }; 5F42763325DB3694005B9BBC /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F42763225DB3694005B9BBC /* AdServices.framework */; }; 5F437E40237E1A560052064B /* BNCDeviceSystemTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F437E3F237E1A560052064B /* BNCDeviceSystemTests.m */; }; - 5F5FDA102B7DE20800F14A43 /* BranchLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5FDA0F2B7DE20800F14A43 /* BranchLogger.m */; }; 5F5FDA122B7DE22A00F14A43 /* BranchLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F5FDA112B7DE22A00F14A43 /* BranchLogger.h */; }; 5F5FDA142B7DE27D00F14A43 /* BranchLoggerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5FDA132B7DE27D00F14A43 /* BranchLoggerTests.m */; }; - 5F644BB92B7AA811000DCD78 /* NSError+Branch.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B262B7AA810000DCD78 /* NSError+Branch.m */; }; - 5F644BBA2B7AA811000DCD78 /* BNCUserAgentCollector.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B272B7AA810000DCD78 /* BNCUserAgentCollector.m */; }; - 5F644BBB2B7AA811000DCD78 /* BNCEncodingUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B282B7AA810000DCD78 /* BNCEncodingUtils.m */; }; - 5F644BBC2B7AA811000DCD78 /* BranchUniversalObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B292B7AA810000DCD78 /* BranchUniversalObject.m */; }; - 5F644BBD2B7AA811000DCD78 /* BranchPasteControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B2A2B7AA810000DCD78 /* BranchPasteControl.m */; }; - 5F644BBE2B7AA811000DCD78 /* BNCApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B2B2B7AA810000DCD78 /* BNCApplication.m */; }; - 5F644BBF2B7AA811000DCD78 /* BNCDeviceSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B2C2B7AA810000DCD78 /* BNCDeviceSystem.m */; }; - 5F644BC02B7AA811000DCD78 /* NSMutableDictionary+Branch.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B2D2B7AA810000DCD78 /* NSMutableDictionary+Branch.m */; }; - 5F644BC12B7AA811000DCD78 /* BNCServerRequestQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B2E2B7AA810000DCD78 /* BNCServerRequestQueue.m */; }; - 5F644BC22B7AA811000DCD78 /* BNCUrlQueryParameter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B2F2B7AA810000DCD78 /* BNCUrlQueryParameter.m */; }; - 5F644BC32B7AA811000DCD78 /* BNCDeepLinkViewControllerInstance.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B302B7AA810000DCD78 /* BNCDeepLinkViewControllerInstance.m */; }; - 5F644BC42B7AA811000DCD78 /* BranchScene.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B312B7AA810000DCD78 /* BranchScene.m */; }; - 5F644BC52B7AA811000DCD78 /* BNCContentDiscoveryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B322B7AA810000DCD78 /* BNCContentDiscoveryManager.m */; }; - 5F644BC62B7AA811000DCD78 /* Branch+Validator.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B332B7AA810000DCD78 /* Branch+Validator.m */; }; - 5F644BC72B7AA811000DCD78 /* BranchInstallRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B342B7AA810000DCD78 /* BranchInstallRequest.m */; }; - 5F644BC82B7AA811000DCD78 /* BranchPluginSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B352B7AA810000DCD78 /* BranchPluginSupport.m */; }; - 5F644BC92B7AA811000DCD78 /* NSString+Branch.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B362B7AA810000DCD78 /* NSString+Branch.m */; }; - 5F644BCA2B7AA811000DCD78 /* BNCSystemObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B372B7AA810000DCD78 /* BNCSystemObserver.m */; }; - 5F644BCC2B7AA811000DCD78 /* BNCURLFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B392B7AA810000DCD78 /* BNCURLFilter.m */; }; - 5F644BCD2B7AA811000DCD78 /* BNCServerRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B3A2B7AA810000DCD78 /* BNCServerRequest.m */; }; - 5F644BCE2B7AA811000DCD78 /* BNCNetworkInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B3B2B7AA810000DCD78 /* BNCNetworkInterface.m */; }; - 5F644BCF2B7AA811000DCD78 /* BNCPreferenceHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B3C2B7AA810000DCD78 /* BNCPreferenceHelper.m */; }; - 5F644BD02B7AA811000DCD78 /* BNCConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B3D2B7AA810000DCD78 /* BNCConfig.m */; }; - 5F644BD12B7AA811000DCD78 /* BranchConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B3E2B7AA810000DCD78 /* BranchConstants.m */; }; - 5F644BD22B7AA811000DCD78 /* BranchContentDiscoveryManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B3F2B7AA810000DCD78 /* BranchContentDiscoveryManifest.m */; }; - 5F644BD32B7AA811000DCD78 /* BranchSpotlightUrlRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B402B7AA810000DCD78 /* BranchSpotlightUrlRequest.m */; }; - 5F644BD52B7AA811000DCD78 /* BranchContentDiscoverer.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B422B7AA810000DCD78 /* BranchContentDiscoverer.m */; }; - 5F644BD62B7AA811000DCD78 /* BNCDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B432B7AA810000DCD78 /* BNCDeviceInfo.m */; }; - 5F644BD72B7AA811000DCD78 /* BNCNetworkService.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B442B7AA810000DCD78 /* BNCNetworkService.m */; }; - 5F644BD82B7AA811000DCD78 /* BNCReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B452B7AA810000DCD78 /* BNCReachability.m */; }; - 5F644BD92B7AA811000DCD78 /* BNCRequestFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B462B7AA810000DCD78 /* BNCRequestFactory.m */; }; - 5F644BDA2B7AA811000DCD78 /* BNCReferringURLUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B472B7AA810000DCD78 /* BNCReferringURLUtility.m */; }; - 5F644BDB2B7AA811000DCD78 /* BNCProductCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B482B7AA810000DCD78 /* BNCProductCategory.m */; }; - 5F644BDC2B7AA811000DCD78 /* BNCCrashlyticsWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B492B7AA810000DCD78 /* BNCCrashlyticsWrapper.m */; }; - 5F644BDD2B7AA811000DCD78 /* BNCServerInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B4A2B7AA810000DCD78 /* BNCServerInterface.m */; }; - 5F644BDE2B7AA811000DCD78 /* BranchJsonConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B4B2B7AA810000DCD78 /* BranchJsonConfig.m */; }; - 5F644BDF2B7AA811000DCD78 /* BranchLATDRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B4C2B7AA810000DCD78 /* BranchLATDRequest.m */; }; - 5F644BE02B7AA811000DCD78 /* BNCPartnerParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B4D2B7AA810000DCD78 /* BNCPartnerParameters.m */; }; - 5F644BE12B7AA811000DCD78 /* BranchCSSearchableItemAttributeSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B4E2B7AA810000DCD78 /* BranchCSSearchableItemAttributeSet.m */; }; - 5F644BE22B7AA811000DCD78 /* BranchActivityItemProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B4F2B7AA810000DCD78 /* BranchActivityItemProvider.m */; }; - 5F644BE32B7AA811000DCD78 /* BranchQRCode.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B502B7AA810000DCD78 /* BranchQRCode.m */; }; - 5F644BE42B7AA811000DCD78 /* BNCKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B512B7AA810000DCD78 /* BNCKeyChain.m */; }; 5F644BE52B7AA811000DCD78 /* BNCLinkData.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B532B7AA810000DCD78 /* BNCLinkData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F644BE62B7AA811000DCD78 /* BranchDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B542B7AA810000DCD78 /* BranchDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F644BE72B7AA811000DCD78 /* BranchQRCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B552B7AA810000DCD78 /* BranchQRCode.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -151,7 +108,6 @@ 5F644C242B7AA811000DCD78 /* BranchSpotlightUrlRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B932B7AA811000DCD78 /* BranchSpotlightUrlRequest.h */; }; 5F644C252B7AA811000DCD78 /* BranchContentDiscoveryManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B942B7AA811000DCD78 /* BranchContentDiscoveryManifest.h */; }; 5F644C262B7AA811000DCD78 /* BNCConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B952B7AA811000DCD78 /* BNCConfig.h */; }; - 5F644C272B7AA811000DCD78 /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B962B7AA811000DCD78 /* BranchConstants.h */; }; 5F644C282B7AA811000DCD78 /* BNCPartnerParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B972B7AA811000DCD78 /* BNCPartnerParameters.h */; }; 5F644C292B7AA811000DCD78 /* BranchJsonConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B982B7AA811000DCD78 /* BranchJsonConfig.h */; }; 5F644C2A2B7AA811000DCD78 /* BranchLATDRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B992B7AA811000DCD78 /* BranchLATDRequest.h */; }; @@ -160,37 +116,10 @@ 5F644C2D2B7AA811000DCD78 /* BNCReferringURLUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B9C2B7AA811000DCD78 /* BNCReferringURLUtility.h */; }; 5F644C2E2B7AA811000DCD78 /* BNCNetworkService.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B9D2B7AA811000DCD78 /* BNCNetworkService.h */; }; 5F644C2F2B7AA811000DCD78 /* BNCReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F644B9E2B7AA811000DCD78 /* BNCReachability.h */; }; - 5F644C302B7AA811000DCD78 /* BranchDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644B9F2B7AA811000DCD78 /* BranchDelegate.m */; }; - 5F644C312B7AA811000DCD78 /* BNCLinkData.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA02B7AA811000DCD78 /* BNCLinkData.m */; }; - 5F644C322B7AA811000DCD78 /* Branch.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA12B7AA811000DCD78 /* Branch.m */; }; - 5F644C332B7AA811000DCD78 /* BNCJSONUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA22B7AA811000DCD78 /* BNCJSONUtility.m */; }; - 5F644C342B7AA811000DCD78 /* BNCCurrency.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA32B7AA811000DCD78 /* BNCCurrency.m */; }; - 5F644C352B7AA811000DCD78 /* BranchLastAttributedTouchData.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA42B7AA811000DCD78 /* BranchLastAttributedTouchData.m */; }; - 5F644C362B7AA811000DCD78 /* BNCSKAdNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA52B7AA811000DCD78 /* BNCSKAdNetwork.m */; }; - 5F644C372B7AA811000DCD78 /* BranchContentPathProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA62B7AA811000DCD78 /* BranchContentPathProperties.m */; }; - 5F644C382B7AA811000DCD78 /* BNCPasteboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA72B7AA811000DCD78 /* BNCPasteboard.m */; }; - 5F644C392B7AA811000DCD78 /* BNCAppleReceipt.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA82B7AA811000DCD78 /* BNCAppleReceipt.m */; }; - 5F644C3A2B7AA811000DCD78 /* BranchLinkProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BA92B7AA811000DCD78 /* BranchLinkProperties.m */; }; - 5F644C3B2B7AA811000DCD78 /* BNCInitSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BAA2B7AA811000DCD78 /* BNCInitSessionResponse.m */; }; - 5F644C3C2B7AA811000DCD78 /* BNCLinkCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BAB2B7AA811000DCD78 /* BNCLinkCache.m */; }; - 5F644C3D2B7AA811000DCD78 /* BNCSpotlightService.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BAC2B7AA811000DCD78 /* BNCSpotlightService.m */; }; - 5F644C3E2B7AA811000DCD78 /* BNCServerAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BAD2B7AA811000DCD78 /* BNCServerAPI.m */; }; - 5F644C3F2B7AA811000DCD78 /* BranchShareLink.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BAE2B7AA811000DCD78 /* BranchShareLink.m */; }; - 5F644C402B7AA811000DCD78 /* UIViewController+Branch.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BAF2B7AA811000DCD78 /* UIViewController+Branch.m */; }; - 5F644C412B7AA811000DCD78 /* BNCAppGroupsData.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB02B7AA811000DCD78 /* BNCAppGroupsData.m */; }; - 5F644C422B7AA811000DCD78 /* BNCServerResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB12B7AA811000DCD78 /* BNCServerResponse.m */; }; - 5F644C432B7AA811000DCD78 /* BranchEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB22B7AA811000DCD78 /* BranchEvent.m */; }; - 5F644C442B7AA811000DCD78 /* BranchShortUrlRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB32B7AA811000DCD78 /* BranchShortUrlRequest.m */; }; - 5F644C452B7AA811000DCD78 /* BranchOpenRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB42B7AA811000DCD78 /* BranchOpenRequest.m */; }; - 5F644C462B7AA811000DCD78 /* BNCQRCodeCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB52B7AA811000DCD78 /* BNCQRCodeCache.m */; }; - 5F644C472B7AA811000DCD78 /* BranchShortUrlSyncRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB62B7AA811000DCD78 /* BranchShortUrlSyncRequest.m */; }; - 5F644C482B7AA811000DCD78 /* BNCCallbackMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB72B7AA811000DCD78 /* BNCCallbackMap.m */; }; - 5F644C492B7AA811000DCD78 /* BNCEventUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F644BB82B7AA811000DCD78 /* BNCEventUtils.m */; }; 5F67F48E228F535500067429 /* BNCEncodingUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F67F48D228F535500067429 /* BNCEncodingUtilsTests.m */; }; 5F6D86D92BB5E9650068B536 /* BNCClassSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F6D86D82BB5E9650068B536 /* BNCClassSerializationTests.m */; }; 5F86501A2B76DA3200364BDE /* NSMutableDictionaryBranchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F8650192B76DA3200364BDE /* NSMutableDictionaryBranchTests.m */; }; 5F892EC5236116CD0023AEC1 /* NSErrorBranchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F892EC4236116CC0023AEC1 /* NSErrorBranchTests.m */; }; - 5F8B7B4021B5F5CD009CE0A6 /* libBranch.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 466B58381B17773000A69EDE /* libBranch.a */; }; 5F8B7B4721B5F5F0009CE0A6 /* Branch_setBranchKeyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F8B7B4621B5F5F0009CE0A6 /* Branch_setBranchKeyTests.m */; }; 5F8BB66E278771890055D2DC /* BNCKeyChainTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F8BB66D278771890055D2DC /* BNCKeyChainTests.m */; }; 5F909B5E23314CE900A774D2 /* BNCJSONUtilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F73FC8023314697000EBD32 /* BNCJSONUtilityTests.m */; }; @@ -225,6 +154,7 @@ 670016701940F51400A9E103 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6700166F1940F51400A9E103 /* main.m */; }; 6700167A1940F51400A9E103 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 670016791940F51400A9E103 /* ViewController.m */; }; 67F270891BA9FCFF002546A7 /* CoreSpotlight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67F270881BA9FCFF002546A7 /* CoreSpotlight.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + B77CB6C72E8EE36300FDF144 /* BranchSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B77CB6C62E8EE36300FDF144 /* BranchSDK */; }; C10A6DE629A995590061A851 /* StoreKitTestCertificate.cer in Resources */ = {isa = PBXBuildFile; fileRef = C10A6DE529A995590061A851 /* StoreKitTestCertificate.cer */; }; C10C61AA282481FB00761D7E /* BranchShareLinkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C10C61A9282481FB00761D7E /* BranchShareLinkTests.m */; }; C12320B52808DB90007771C0 /* BranchQRCodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C12320B42808DB90007771C0 /* BranchQRCodeTests.m */; }; @@ -234,70 +164,17 @@ C17DAF7B2AC20C2000B16B1A /* BranchClassTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C17DAF7A2AC20C2000B16B1A /* BranchClassTests.m */; }; C1CC888229BAAFC000BDD2B5 /* BNCReferringURLUtilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C1CC888129BAAFC000BDD2B5 /* BNCReferringURLUtilityTests.m */; }; E51F642A2CF46899000858D2 /* BranchFileLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = E51F64292CF46899000858D2 /* BranchFileLogger.h */; }; - E56394312CC7AC9F00E18E65 /* BranchFileLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = E563942F2CC7AC9500E18E65 /* BranchFileLogger.m */; }; E71E397B2DD3C14800110F59 /* BNCInAppBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = E71E397A2DD3C14800110F59 /* BNCInAppBrowser.h */; }; E72489D228E40D0200DCD8FD /* PasteControlViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E72489D128E40D0200DCD8FD /* PasteControlViewController.m */; }; E7A728BD2AA9A112009343B7 /* BNCAPIServerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E7A728BC2AA9A112009343B7 /* BNCAPIServerTest.m */; }; E7AC74572DB0639E002D8C40 /* BNCODMInfoCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = E7AC74562DB0639E002D8C40 /* BNCODMInfoCollector.h */; }; - E7AC74592DB063C6002D8C40 /* BNCODMInfoCollector.m in Sources */ = {isa = PBXBuildFile; fileRef = E7AC74582DB063C6002D8C40 /* BNCODMInfoCollector.m */; }; E7AC745B2DB06407002D8C40 /* BNCODMTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7AC745A2DB06407002D8C40 /* BNCODMTests.m */; }; - E7AC74702DB06992002D8C40 /* GULLogger in Frameworks */ = {isa = PBXBuildFile; productRef = E7AC746F2DB06992002D8C40 /* GULLogger */; }; - E7AC74722DB06992002D8C40 /* GULNetwork in Frameworks */ = {isa = PBXBuildFile; productRef = E7AC74712DB06992002D8C40 /* GULNetwork */; }; - E7AC74752DB069B2002D8C40 /* nanopb in Frameworks */ = {isa = PBXBuildFile; productRef = E7AC74742DB069B2002D8C40 /* nanopb */; }; - E7AC747B2DB0700D002D8C40 /* BranchSDK in Frameworks */ = {isa = PBXBuildFile; productRef = E7AC747A2DB0700D002D8C40 /* BranchSDK */; }; E7AC747E2DB0714B002D8C40 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E7AC747D2DB07145002D8C40 /* libc++.tbd */; }; E7AE4A092DFB2C4400696805 /* BranchConfigurationControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7AE4A082DFB2C4400696805 /* BranchConfigurationControllerTests.m */; }; - E7AE4A0C2DFB2D0100696805 /* BranchConfigurationController.h in Headers */ = {isa = PBXBuildFile; fileRef = E7AE4A0B2DFB2D0100696805 /* BranchConfigurationController.h */; }; - E7E28ECA2DD2424C00F75D0D /* BNCInAppBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E28EC82DD2424C00F75D0D /* BNCInAppBrowser.m */; }; - E7FC47732DFC7B020072B3ED /* BranchConfigurationController.m in Sources */ = {isa = PBXBuildFile; fileRef = E7FC47722DFC7B020072B3ED /* BranchConfigurationController.m */; }; + E7CA74B22E1B4890002EFB40 /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7CA74B12E1B4890002EFB40 /* BranchConstants.h */; }; F1CF14111F4CC79F00BB2694 /* CoreSpotlight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67F270881BA9FCFF002546A7 /* CoreSpotlight.framework */; settings = {ATTRIBUTES = (Required, ); }; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 466B586F1B1777DE00A69EDE /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 670016581940F51400A9E103 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 466B58371B17773000A69EDE; - remoteInfo = Branch; - }; - 4683F07B1B20AC6300A432E7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 670016581940F51400A9E103 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 466B58371B17773000A69EDE; - remoteInfo = Branch; - }; - 4D337DDC201019B8009A5774 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 670016581940F51400A9E103 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6700165F1940F51400A9E103; - remoteInfo = "Branch-TestBed"; - }; - 5F8B7B4121B5F5CD009CE0A6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 670016581940F51400A9E103 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 466B58371B17773000A69EDE; - remoteInfo = Branch; - }; - E7AC74652DB064BC002D8C40 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 670016581940F51400A9E103 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 466B58371B17773000A69EDE; - remoteInfo = Branch; - }; - F1D4F9B11F323F01002D13FF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 670016581940F51400A9E103 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6700165F1940F51400A9E103; - remoteInfo = "Branch-TestBed"; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 4DF79403209B90B6003597E8 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -320,7 +197,6 @@ 0372078725E9F81000F29C30 /* UITestCaseMisc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UITestCaseMisc.m; sourceTree = ""; }; 0399DD112599BF8A00CDB36E /* UITestSendV2Event.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UITestSendV2Event.m; sourceTree = ""; }; 03B49EEA25F9F315000BF105 /* UITestCase0OpenNInstall.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UITestCase0OpenNInstall.m; sourceTree = ""; }; - 466B58381B17773000A69EDE /* libBranch.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBranch.a; sourceTree = BUILT_PRODUCTS_DIR; }; 4AB16367239E3A2700D42931 /* DispatchToIsolationQueueTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DispatchToIsolationQueueTests.m; sourceTree = ""; }; 4D1683812098C901008819E3 /* Branch-SDK-Tests-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Branch-SDK-Tests-Bridging-Header.h"; sourceTree = ""; }; 4D1683842098C901008819E3 /* BNCLinkDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BNCLinkDataTests.m; sourceTree = ""; }; @@ -379,7 +255,7 @@ 5F644B3B2B7AA810000DCD78 /* BNCNetworkInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BNCNetworkInterface.m; sourceTree = ""; }; 5F644B3C2B7AA810000DCD78 /* BNCPreferenceHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BNCPreferenceHelper.m; sourceTree = ""; }; 5F644B3D2B7AA810000DCD78 /* BNCConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BNCConfig.m; sourceTree = ""; }; - 5F644B3E2B7AA810000DCD78 /* BranchConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchConstants.m; sourceTree = ""; }; + 5F644B3E2B7AA810000DCD78 /* BranchConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BranchConstants.m; path = ../BranchSDK_ObjC/BranchConstants.m; sourceTree = ""; }; 5F644B3F2B7AA810000DCD78 /* BranchContentDiscoveryManifest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchContentDiscoveryManifest.m; sourceTree = ""; }; 5F644B402B7AA810000DCD78 /* BranchSpotlightUrlRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchSpotlightUrlRequest.m; sourceTree = ""; }; 5F644B422B7AA810000DCD78 /* BranchContentDiscoverer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchContentDiscoverer.m; sourceTree = ""; }; @@ -461,7 +337,6 @@ 5F644B932B7AA811000DCD78 /* BranchSpotlightUrlRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchSpotlightUrlRequest.h; sourceTree = ""; }; 5F644B942B7AA811000DCD78 /* BranchContentDiscoveryManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchContentDiscoveryManifest.h; sourceTree = ""; }; 5F644B952B7AA811000DCD78 /* BNCConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BNCConfig.h; sourceTree = ""; }; - 5F644B962B7AA811000DCD78 /* BranchConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchConstants.h; sourceTree = ""; }; 5F644B972B7AA811000DCD78 /* BNCPartnerParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BNCPartnerParameters.h; sourceTree = ""; }; 5F644B982B7AA811000DCD78 /* BranchJsonConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchJsonConfig.h; sourceTree = ""; }; 5F644B992B7AA811000DCD78 /* BranchLATDRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchLATDRequest.h; sourceTree = ""; }; @@ -548,6 +423,161 @@ 67BBCF271A69E49A009C7DAE /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; 67F270881BA9FCFF002546A7 /* CoreSpotlight.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreSpotlight.framework; path = System/Library/Frameworks/CoreSpotlight.framework; sourceTree = SDKROOT; }; 7E6B3B511AA42D0E005F45BF /* Branch-SDK-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Branch-SDK-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8CED1FA4F572F144DA1055F3 /* BranchRequestOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BranchRequestOperation.swift; path = ../Sources/BranchSwiftSDK/BranchRequestOperation.swift; sourceTree = SOURCE_ROOT; }; + B7A21E2B2E8EDD5F00BB1E14 /* BNCAppGroupsData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCAppGroupsData.h; sourceTree = ""; }; + B7A21E2C2E8EDD5F00BB1E14 /* BNCAppleReceipt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCAppleReceipt.h; sourceTree = ""; }; + B7A21E2D2E8EDD5F00BB1E14 /* BNCApplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCApplication.h; sourceTree = ""; }; + B7A21E2E2E8EDD5F00BB1E14 /* BNCCallbackMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCCallbackMap.h; sourceTree = ""; }; + B7A21E2F2E8EDD5F00BB1E14 /* BNCConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCConfig.h; sourceTree = ""; }; + B7A21E302E8EDD5F00BB1E14 /* BNCContentDiscoveryManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCContentDiscoveryManager.h; sourceTree = ""; }; + B7A21E312E8EDD5F00BB1E14 /* BNCCrashlyticsWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCCrashlyticsWrapper.h; sourceTree = ""; }; + B7A21E322E8EDD5F00BB1E14 /* BNCDeepLinkViewControllerInstance.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCDeepLinkViewControllerInstance.h; sourceTree = ""; }; + B7A21E332E8EDD5F00BB1E14 /* BNCDeviceInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCDeviceInfo.h; sourceTree = ""; }; + B7A21E342E8EDD5F00BB1E14 /* BNCDeviceSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCDeviceSystem.h; sourceTree = ""; }; + B7A21E352E8EDD5F00BB1E14 /* BNCEncodingUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCEncodingUtils.h; sourceTree = ""; }; + B7A21E362E8EDD5F00BB1E14 /* BNCEventUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCEventUtils.h; sourceTree = ""; }; + B7A21E372E8EDD5F00BB1E14 /* BNCInAppBrowser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCInAppBrowser.h; sourceTree = ""; }; + B7A21E382E8EDD5F00BB1E14 /* BNCJSONUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCJSONUtility.h; sourceTree = ""; }; + B7A21E392E8EDD5F00BB1E14 /* BNCKeyChain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCKeyChain.h; sourceTree = ""; }; + B7A21E3A2E8EDD5F00BB1E14 /* BNCNetworkInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCNetworkInterface.h; sourceTree = ""; }; + B7A21E3B2E8EDD5F00BB1E14 /* BNCNetworkService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCNetworkService.h; sourceTree = ""; }; + B7A21E3C2E8EDD5F00BB1E14 /* BNCODMInfoCollector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCODMInfoCollector.h; sourceTree = ""; }; + B7A21E3D2E8EDD5F00BB1E14 /* BNCPartnerParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCPartnerParameters.h; sourceTree = ""; }; + B7A21E3E2E8EDD5F00BB1E14 /* BNCPasteboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCPasteboard.h; sourceTree = ""; }; + B7A21E3F2E8EDD5F00BB1E14 /* BNCQRCodeCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCQRCodeCache.h; sourceTree = ""; }; + B7A21E402E8EDD5F00BB1E14 /* BNCReachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCReachability.h; sourceTree = ""; }; + B7A21E412E8EDD5F00BB1E14 /* BNCReferringURLUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCReferringURLUtility.h; sourceTree = ""; }; + B7A21E422E8EDD5F00BB1E14 /* BNCRequestFactory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCRequestFactory.h; sourceTree = ""; }; + B7A21E432E8EDD5F00BB1E14 /* BNCServerAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCServerAPI.h; sourceTree = ""; }; + B7A21E442E8EDD5F00BB1E14 /* BNCServerRequestOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCServerRequestOperation.h; sourceTree = ""; }; + B7A21E452E8EDD5F00BB1E14 /* BNCSKAdNetwork.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCSKAdNetwork.h; sourceTree = ""; }; + B7A21E462E8EDD5F00BB1E14 /* BNCSpotlightService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCSpotlightService.h; sourceTree = ""; }; + B7A21E472E8EDD5F00BB1E14 /* BNCSystemObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCSystemObserver.h; sourceTree = ""; }; + B7A21E482E8EDD5F00BB1E14 /* BNCURLFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCURLFilter.h; sourceTree = ""; }; + B7A21E492E8EDD5F00BB1E14 /* BNCUrlQueryParameter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCUrlQueryParameter.h; sourceTree = ""; }; + B7A21E4A2E8EDD5F00BB1E14 /* BNCUserAgentCollector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCUserAgentCollector.h; sourceTree = ""; }; + B7A21E4B2E8EDD5F00BB1E14 /* Branch+Validator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Branch+Validator.h"; sourceTree = ""; }; + B7A21E4C2E8EDD5F00BB1E14 /* BranchConfigurationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchConfigurationController.h; sourceTree = ""; }; + B7A21E4D2E8EDD5F00BB1E14 /* BranchContentDiscoverer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchContentDiscoverer.h; sourceTree = ""; }; + B7A21E4E2E8EDD5F00BB1E14 /* BranchContentDiscoveryManifest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchContentDiscoveryManifest.h; sourceTree = ""; }; + B7A21E4F2E8EDD5F00BB1E14 /* BranchContentPathProperties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchContentPathProperties.h; sourceTree = ""; }; + B7A21E502E8EDD5F00BB1E14 /* BranchFileLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchFileLogger.h; sourceTree = ""; }; + B7A21E512E8EDD5F00BB1E14 /* BranchInstallRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchInstallRequest.h; sourceTree = ""; }; + B7A21E522E8EDD5F00BB1E14 /* BranchJsonConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchJsonConfig.h; sourceTree = ""; }; + B7A21E532E8EDD5F00BB1E14 /* BranchLATDRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchLATDRequest.h; sourceTree = ""; }; + B7A21E542E8EDD5F00BB1E14 /* BranchOpenRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchOpenRequest.h; sourceTree = ""; }; + B7A21E552E8EDD5F00BB1E14 /* BranchShortUrlRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchShortUrlRequest.h; sourceTree = ""; }; + B7A21E562E8EDD5F00BB1E14 /* BranchShortUrlSyncRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchShortUrlSyncRequest.h; sourceTree = ""; }; + B7A21E572E8EDD5F00BB1E14 /* BranchSpotlightUrlRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchSpotlightUrlRequest.h; sourceTree = ""; }; + B7A21E582E8EDD5F00BB1E14 /* NSError+Branch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+Branch.h"; sourceTree = ""; }; + B7A21E592E8EDD5F00BB1E14 /* NSMutableDictionary+Branch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+Branch.h"; sourceTree = ""; }; + B7A21E5A2E8EDD5F00BB1E14 /* NSString+Branch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+Branch.h"; sourceTree = ""; }; + B7A21E5B2E8EDD5F00BB1E14 /* UIViewController+Branch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Branch.h"; sourceTree = ""; }; + B7A21E5D2E8EDD5F00BB1E14 /* BNCCallbacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCCallbacks.h; sourceTree = ""; }; + B7A21E5E2E8EDD5F00BB1E14 /* BNCCurrency.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCCurrency.h; sourceTree = ""; }; + B7A21E5F2E8EDD5F00BB1E14 /* BNCInitSessionResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCInitSessionResponse.h; sourceTree = ""; }; + B7A21E602E8EDD5F00BB1E14 /* BNCLinkCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCLinkCache.h; sourceTree = ""; }; + B7A21E612E8EDD5F00BB1E14 /* BNCLinkData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCLinkData.h; sourceTree = ""; }; + B7A21E622E8EDD5F00BB1E14 /* BNCNetworkServiceProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCNetworkServiceProtocol.h; sourceTree = ""; }; + B7A21E632E8EDD5F00BB1E14 /* BNCPreferenceHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCPreferenceHelper.h; sourceTree = ""; }; + B7A21E642E8EDD5F00BB1E14 /* BNCProductCategory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCProductCategory.h; sourceTree = ""; }; + B7A21E652E8EDD5F00BB1E14 /* BNCServerInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCServerInterface.h; sourceTree = ""; }; + B7A21E662E8EDD5F00BB1E14 /* BNCServerRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCServerRequest.h; sourceTree = ""; }; + B7A21E672E8EDD5F00BB1E14 /* BNCServerRequestQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCServerRequestQueue.h; sourceTree = ""; }; + B7A21E682E8EDD5F00BB1E14 /* BNCServerResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCServerResponse.h; sourceTree = ""; }; + B7A21E692E8EDD5F00BB1E14 /* Branch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Branch.h; sourceTree = ""; }; + B7A21E6A2E8EDD5F00BB1E14 /* BranchActivityItemProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchActivityItemProvider.h; sourceTree = ""; }; + B7A21E6B2E8EDD5F00BB1E14 /* BranchConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchConstants.h; sourceTree = ""; }; + B7A21E6C2E8EDD5F00BB1E14 /* BranchCSSearchableItemAttributeSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchCSSearchableItemAttributeSet.h; sourceTree = ""; }; + B7A21E6D2E8EDD5F00BB1E14 /* BranchDeepLinkingController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchDeepLinkingController.h; sourceTree = ""; }; + B7A21E6E2E8EDD5F00BB1E14 /* BranchDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchDelegate.h; sourceTree = ""; }; + B7A21E6F2E8EDD5F00BB1E14 /* BranchEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchEvent.h; sourceTree = ""; }; + B7A21E702E8EDD5F00BB1E14 /* BranchLastAttributedTouchData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchLastAttributedTouchData.h; sourceTree = ""; }; + B7A21E712E8EDD5F00BB1E14 /* BranchLinkProperties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchLinkProperties.h; sourceTree = ""; }; + B7A21E722E8EDD5F00BB1E14 /* BranchLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchLogger.h; sourceTree = ""; }; + B7A21E732E8EDD5F00BB1E14 /* BranchPasteControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchPasteControl.h; sourceTree = ""; }; + B7A21E742E8EDD5F00BB1E14 /* BranchPluginSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchPluginSupport.h; sourceTree = ""; }; + B7A21E752E8EDD5F00BB1E14 /* BranchQRCode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchQRCode.h; sourceTree = ""; }; + B7A21E762E8EDD5F00BB1E14 /* BranchScene.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchScene.h; sourceTree = ""; }; + B7A21E772E8EDD5F00BB1E14 /* BranchSDK.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchSDK.h; sourceTree = ""; }; + B7A21E782E8EDD5F00BB1E14 /* BranchShareLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchShareLink.h; sourceTree = ""; }; + B7A21E792E8EDD5F00BB1E14 /* BranchUniversalObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchUniversalObject.h; sourceTree = ""; }; + B7A21E7B2E8EDD5F00BB1E14 /* BNCAppGroupsData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCAppGroupsData.m; sourceTree = ""; }; + B7A21E7C2E8EDD5F00BB1E14 /* BNCAppleReceipt.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCAppleReceipt.m; sourceTree = ""; }; + B7A21E7D2E8EDD5F00BB1E14 /* BNCApplication.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCApplication.m; sourceTree = ""; }; + B7A21E7E2E8EDD5F00BB1E14 /* BNCCallbackMap.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCCallbackMap.m; sourceTree = ""; }; + B7A21E7F2E8EDD5F00BB1E14 /* BNCConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCConfig.m; sourceTree = ""; }; + B7A21E802E8EDD5F00BB1E14 /* BNCContentDiscoveryManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCContentDiscoveryManager.m; sourceTree = ""; }; + B7A21E812E8EDD5F00BB1E14 /* BNCCrashlyticsWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCCrashlyticsWrapper.m; sourceTree = ""; }; + B7A21E822E8EDD5F00BB1E14 /* BNCCurrency.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCCurrency.m; sourceTree = ""; }; + B7A21E832E8EDD5F00BB1E14 /* BNCDeepLinkViewControllerInstance.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCDeepLinkViewControllerInstance.m; sourceTree = ""; }; + B7A21E842E8EDD5F00BB1E14 /* BNCDeviceInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCDeviceInfo.m; sourceTree = ""; }; + B7A21E852E8EDD5F00BB1E14 /* BNCDeviceSystem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCDeviceSystem.m; sourceTree = ""; }; + B7A21E862E8EDD5F00BB1E14 /* BNCEncodingUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCEncodingUtils.m; sourceTree = ""; }; + B7A21E872E8EDD5F00BB1E14 /* BNCEventUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCEventUtils.m; sourceTree = ""; }; + B7A21E882E8EDD5F00BB1E14 /* BNCInAppBrowser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCInAppBrowser.m; sourceTree = ""; }; + B7A21E892E8EDD5F00BB1E14 /* BNCInitSessionResponse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCInitSessionResponse.m; sourceTree = ""; }; + B7A21E8A2E8EDD5F00BB1E14 /* BNCJSONUtility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCJSONUtility.m; sourceTree = ""; }; + B7A21E8B2E8EDD5F00BB1E14 /* BNCKeyChain.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCKeyChain.m; sourceTree = ""; }; + B7A21E8C2E8EDD5F00BB1E14 /* BNCLinkCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCLinkCache.m; sourceTree = ""; }; + B7A21E8D2E8EDD5F00BB1E14 /* BNCLinkData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCLinkData.m; sourceTree = ""; }; + B7A21E8E2E8EDD5F00BB1E14 /* BNCNetworkInterface.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCNetworkInterface.m; sourceTree = ""; }; + B7A21E8F2E8EDD5F00BB1E14 /* BNCNetworkService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCNetworkService.m; sourceTree = ""; }; + B7A21E902E8EDD5F00BB1E14 /* BNCODMInfoCollector.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCODMInfoCollector.m; sourceTree = ""; }; + B7A21E912E8EDD5F00BB1E14 /* BNCPartnerParameters.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCPartnerParameters.m; sourceTree = ""; }; + B7A21E922E8EDD5F00BB1E14 /* BNCPasteboard.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCPasteboard.m; sourceTree = ""; }; + B7A21E932E8EDD5F00BB1E14 /* BNCPreferenceHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCPreferenceHelper.m; sourceTree = ""; }; + B7A21E942E8EDD5F00BB1E14 /* BNCProductCategory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCProductCategory.m; sourceTree = ""; }; + B7A21E952E8EDD5F00BB1E14 /* BNCQRCodeCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCQRCodeCache.m; sourceTree = ""; }; + B7A21E962E8EDD5F00BB1E14 /* BNCReachability.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCReachability.m; sourceTree = ""; }; + B7A21E972E8EDD5F00BB1E14 /* BNCReferringURLUtility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCReferringURLUtility.m; sourceTree = ""; }; + B7A21E982E8EDD5F00BB1E14 /* BNCRequestFactory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCRequestFactory.m; sourceTree = ""; }; + B7A21E992E8EDD5F00BB1E14 /* BNCServerAPI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCServerAPI.m; sourceTree = ""; }; + B7A21E9A2E8EDD5F00BB1E14 /* BNCServerInterface.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCServerInterface.m; sourceTree = ""; }; + B7A21E9B2E8EDD5F00BB1E14 /* BNCServerRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCServerRequest.m; sourceTree = ""; }; + B7A21E9C2E8EDD5F00BB1E14 /* BNCServerRequestOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCServerRequestOperation.m; sourceTree = ""; }; + B7A21E9D2E8EDD5F00BB1E14 /* BNCServerRequestQueue.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCServerRequestQueue.m; sourceTree = ""; }; + B7A21E9E2E8EDD5F00BB1E14 /* BNCServerResponse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCServerResponse.m; sourceTree = ""; }; + B7A21E9F2E8EDD5F00BB1E14 /* BNCSKAdNetwork.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCSKAdNetwork.m; sourceTree = ""; }; + B7A21EA02E8EDD5F00BB1E14 /* BNCSpotlightService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCSpotlightService.m; sourceTree = ""; }; + B7A21EA12E8EDD5F00BB1E14 /* BNCSystemObserver.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCSystemObserver.m; sourceTree = ""; }; + B7A21EA22E8EDD5F00BB1E14 /* BNCURLFilter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCURLFilter.m; sourceTree = ""; }; + B7A21EA32E8EDD5F00BB1E14 /* BNCUrlQueryParameter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCUrlQueryParameter.m; sourceTree = ""; }; + B7A21EA42E8EDD5F00BB1E14 /* BNCUserAgentCollector.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCUserAgentCollector.m; sourceTree = ""; }; + B7A21EA52E8EDD5F00BB1E14 /* Branch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Branch.m; sourceTree = ""; }; + B7A21EA62E8EDD5F00BB1E14 /* Branch-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Branch-Bridging-Header.h"; sourceTree = ""; }; + B7A21EA72E8EDD5F00BB1E14 /* Branch+Validator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "Branch+Validator.m"; sourceTree = ""; }; + B7A21EA82E8EDD5F00BB1E14 /* BranchActivityItemProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchActivityItemProvider.m; sourceTree = ""; }; + B7A21EA92E8EDD5F00BB1E14 /* BranchConfigurationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchConfigurationController.m; sourceTree = ""; }; + B7A21EAA2E8EDD5F00BB1E14 /* BranchConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchConstants.m; sourceTree = ""; }; + B7A21EAB2E8EDD5F00BB1E14 /* BranchContentDiscoverer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchContentDiscoverer.m; sourceTree = ""; }; + B7A21EAC2E8EDD5F00BB1E14 /* BranchContentDiscoveryManifest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchContentDiscoveryManifest.m; sourceTree = ""; }; + B7A21EAD2E8EDD5F00BB1E14 /* BranchContentPathProperties.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchContentPathProperties.m; sourceTree = ""; }; + B7A21EAE2E8EDD5F00BB1E14 /* BranchCSSearchableItemAttributeSet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchCSSearchableItemAttributeSet.m; sourceTree = ""; }; + B7A21EAF2E8EDD5F00BB1E14 /* BranchDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchDelegate.m; sourceTree = ""; }; + B7A21EB02E8EDD5F00BB1E14 /* BranchEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchEvent.m; sourceTree = ""; }; + B7A21EB12E8EDD5F00BB1E14 /* BranchFileLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchFileLogger.m; sourceTree = ""; }; + B7A21EB22E8EDD5F00BB1E14 /* BranchInstallRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchInstallRequest.m; sourceTree = ""; }; + B7A21EB32E8EDD5F00BB1E14 /* BranchJsonConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchJsonConfig.m; sourceTree = ""; }; + B7A21EB42E8EDD5F00BB1E14 /* BranchLastAttributedTouchData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchLastAttributedTouchData.m; sourceTree = ""; }; + B7A21EB52E8EDD5F00BB1E14 /* BranchLATDRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchLATDRequest.m; sourceTree = ""; }; + B7A21EB62E8EDD5F00BB1E14 /* BranchLinkProperties.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchLinkProperties.m; sourceTree = ""; }; + B7A21EB72E8EDD5F00BB1E14 /* BranchLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchLogger.m; sourceTree = ""; }; + B7A21EB82E8EDD5F00BB1E14 /* BranchOpenRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchOpenRequest.m; sourceTree = ""; }; + B7A21EB92E8EDD5F00BB1E14 /* BranchPasteControl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchPasteControl.m; sourceTree = ""; }; + B7A21EBA2E8EDD5F00BB1E14 /* BranchPluginSupport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchPluginSupport.m; sourceTree = ""; }; + B7A21EBB2E8EDD5F00BB1E14 /* BranchQRCode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchQRCode.m; sourceTree = ""; }; + B7A21EBC2E8EDD5F00BB1E14 /* BranchScene.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchScene.m; sourceTree = ""; }; + B7A21EBD2E8EDD5F00BB1E14 /* BranchShareLink.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchShareLink.m; sourceTree = ""; }; + B7A21EBE2E8EDD5F00BB1E14 /* BranchShortUrlRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchShortUrlRequest.m; sourceTree = ""; }; + B7A21EBF2E8EDD5F00BB1E14 /* BranchShortUrlSyncRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchShortUrlSyncRequest.m; sourceTree = ""; }; + B7A21EC02E8EDD5F00BB1E14 /* BranchSpotlightUrlRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchSpotlightUrlRequest.m; sourceTree = ""; }; + B7A21EC12E8EDD5F00BB1E14 /* BranchUniversalObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchUniversalObject.m; sourceTree = ""; }; + B7A21EC22E8EDD5F00BB1E14 /* NSError+Branch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+Branch.m"; sourceTree = ""; }; + B7A21EC32E8EDD5F00BB1E14 /* NSMutableDictionary+Branch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+Branch.m"; sourceTree = ""; }; + B7A21EC42E8EDD5F00BB1E14 /* NSString+Branch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSString+Branch.m"; sourceTree = ""; }; + B7A21EC52E8EDD5F00BB1E14 /* UIViewController+Branch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Branch.m"; sourceTree = ""; }; + B9BB25109C12DC8BD2D2F665 /* BranchRequestQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BranchRequestQueue.swift; path = ../Sources/BranchSwiftSDK/BranchRequestQueue.swift; sourceTree = SOURCE_ROOT; }; C10A6DE029A97E440061A851 /* TestStoreKitConfig.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = TestStoreKitConfig.storekit; sourceTree = ""; }; C10A6DE529A995590061A851 /* StoreKitTestCertificate.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = StoreKitTestCertificate.cer; sourceTree = ""; }; C10C61A9282481FB00761D7E /* BranchShareLinkTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchShareLinkTests.m; sourceTree = ""; }; @@ -558,6 +588,7 @@ C1614D55285BC8A00098946B /* LinkPresentation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LinkPresentation.framework; path = System/Library/Frameworks/LinkPresentation.framework; sourceTree = SDKROOT; }; C17DAF7A2AC20C2000B16B1A /* BranchClassTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchClassTests.m; sourceTree = ""; }; C1CC888129BAAFC000BDD2B5 /* BNCReferringURLUtilityTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCReferringURLUtilityTests.m; sourceTree = ""; }; + D8B1EA48C972289E75C4943A /* ConfigurationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ConfigurationController.swift; path = ../Sources/BranchSwiftSDK/ConfigurationController.swift; sourceTree = SOURCE_ROOT; }; E51F64292CF46899000858D2 /* BranchFileLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchFileLogger.h; sourceTree = ""; }; E563942F2CC7AC9500E18E65 /* BranchFileLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchFileLogger.m; sourceTree = ""; }; E71E397A2DD3C14800110F59 /* BNCInAppBrowser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCInAppBrowser.h; sourceTree = ""; }; @@ -573,9 +604,7 @@ E7AC74782DB06D47002D8C40 /* NSError+Branch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+Branch.h"; sourceTree = ""; }; E7AC747D2DB07145002D8C40 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk/usr/lib/libc++.tbd"; sourceTree = DEVELOPER_DIR; }; E7AE4A082DFB2C4400696805 /* BranchConfigurationControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchConfigurationControllerTests.m; sourceTree = ""; }; - E7AE4A0B2DFB2D0100696805 /* BranchConfigurationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchConfigurationController.h; sourceTree = ""; }; E7E28EC82DD2424C00F75D0D /* BNCInAppBrowser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCInAppBrowser.m; sourceTree = ""; }; - E7FC47722DFC7B020072B3ED /* BranchConfigurationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BranchConfigurationController.m; path = ../Sources/BranchSDK/BranchConfigurationController.m; sourceTree = ""; }; F1D4F9AC1F323F01002D13FF /* Branch-TestBed-UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Branch-TestBed-UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -588,6 +617,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 40EA3FC7C54A6B3CCEBDB9F8 /* (null) in Frameworks */, + 5AFDEF31D95DB3252A8F146D /* (null) in Frameworks */, 5F92B2362383644C00CA909B /* SystemConfiguration.framework in Frameworks */, 5F205D05231864E800C776D1 /* WebKit.framework in Frameworks */, 5FF7D2862A9549B40049158D /* AdServices.framework in Frameworks */, @@ -604,7 +635,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5F8B7B4021B5F5CD009CE0A6 /* libBranch.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -618,7 +648,6 @@ 670016661940F51400A9E103 /* CoreGraphics.framework in Frameworks */, 67F270891BA9FCFF002546A7 /* CoreSpotlight.framework in Frameworks */, 670016641940F51400A9E103 /* Foundation.framework in Frameworks */, - 466B58811B1778DB00A69EDE /* libBranch.a in Frameworks */, 670016681940F51400A9E103 /* UIKit.framework in Frameworks */, 5F42763325DB3694005B9BBC /* AdServices.framework in Frameworks */, ); @@ -636,10 +665,6 @@ buildActionMask = 2147483647; files = ( E7AC747E2DB0714B002D8C40 /* libc++.tbd in Frameworks */, - E7AC747B2DB0700D002D8C40 /* BranchSDK in Frameworks */, - E7AC74752DB069B2002D8C40 /* nanopb in Frameworks */, - E7AC74722DB06992002D8C40 /* GULNetwork in Frameworks */, - E7AC74702DB06992002D8C40 /* GULLogger in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -647,7 +672,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0372076425E8418F00F29C30 /* libBranch.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -724,92 +748,10 @@ path = "Branch-TestBed-UITests"; sourceTree = ""; }; - 5F644B252B7AA810000DCD78 /* BranchSDK */ = { - isa = PBXGroup; - children = ( - E563942F2CC7AC9500E18E65 /* BranchFileLogger.m */, - 5F644BB02B7AA811000DCD78 /* BNCAppGroupsData.m */, - 5F644BA82B7AA811000DCD78 /* BNCAppleReceipt.m */, - 5F644B2B2B7AA810000DCD78 /* BNCApplication.m */, - 5F644BB72B7AA811000DCD78 /* BNCCallbackMap.m */, - 5F644B3D2B7AA810000DCD78 /* BNCConfig.m */, - 5F644B322B7AA810000DCD78 /* BNCContentDiscoveryManager.m */, - 5F644B492B7AA810000DCD78 /* BNCCrashlyticsWrapper.m */, - 5F644BA32B7AA811000DCD78 /* BNCCurrency.m */, - 5F644B302B7AA810000DCD78 /* BNCDeepLinkViewControllerInstance.m */, - 5F644B432B7AA810000DCD78 /* BNCDeviceInfo.m */, - 5F644B2C2B7AA810000DCD78 /* BNCDeviceSystem.m */, - 5F644B282B7AA810000DCD78 /* BNCEncodingUtils.m */, - 5F644BB82B7AA811000DCD78 /* BNCEventUtils.m */, - 5F644BAA2B7AA811000DCD78 /* BNCInitSessionResponse.m */, - E7E28EC82DD2424C00F75D0D /* BNCInAppBrowser.m */, - 5F644BA22B7AA811000DCD78 /* BNCJSONUtility.m */, - 5F644B512B7AA810000DCD78 /* BNCKeyChain.m */, - 5F644BAB2B7AA811000DCD78 /* BNCLinkCache.m */, - E7AC74772DB06D05002D8C40 /* NSError+Branch.m */, - 5F644BA02B7AA811000DCD78 /* BNCLinkData.m */, - 5F644B3B2B7AA810000DCD78 /* BNCNetworkInterface.m */, - 5F644B442B7AA810000DCD78 /* BNCNetworkService.m */, - 5F644B4D2B7AA810000DCD78 /* BNCPartnerParameters.m */, - 5F644BA72B7AA811000DCD78 /* BNCPasteboard.m */, - 5F644B3C2B7AA810000DCD78 /* BNCPreferenceHelper.m */, - 5F644B482B7AA810000DCD78 /* BNCProductCategory.m */, - 5F644BB52B7AA811000DCD78 /* BNCQRCodeCache.m */, - 5F644B452B7AA810000DCD78 /* BNCReachability.m */, - 5F644B472B7AA810000DCD78 /* BNCReferringURLUtility.m */, - 5F644B462B7AA810000DCD78 /* BNCRequestFactory.m */, - 5F644BAD2B7AA811000DCD78 /* BNCServerAPI.m */, - 5F644B4A2B7AA810000DCD78 /* BNCServerInterface.m */, - 5F644B3A2B7AA810000DCD78 /* BNCServerRequest.m */, - 5F644B2E2B7AA810000DCD78 /* BNCServerRequestQueue.m */, - 5F644BB12B7AA811000DCD78 /* BNCServerResponse.m */, - 5F644BA52B7AA811000DCD78 /* BNCSKAdNetwork.m */, - 5F644BAC2B7AA811000DCD78 /* BNCSpotlightService.m */, - 5F644B372B7AA810000DCD78 /* BNCSystemObserver.m */, - 5F644B392B7AA810000DCD78 /* BNCURLFilter.m */, - 5F644B2F2B7AA810000DCD78 /* BNCUrlQueryParameter.m */, - 5F644B272B7AA810000DCD78 /* BNCUserAgentCollector.m */, - E7AC74582DB063C6002D8C40 /* BNCODMInfoCollector.m */, - 5F644BA12B7AA811000DCD78 /* Branch.m */, - 5F644B332B7AA810000DCD78 /* Branch+Validator.m */, - 5F644B4F2B7AA810000DCD78 /* BranchActivityItemProvider.m */, - 5F644B3E2B7AA810000DCD78 /* BranchConstants.m */, - 5F644B422B7AA810000DCD78 /* BranchContentDiscoverer.m */, - 5F644B3F2B7AA810000DCD78 /* BranchContentDiscoveryManifest.m */, - 5F644BA62B7AA811000DCD78 /* BranchContentPathProperties.m */, - 5F644B4E2B7AA810000DCD78 /* BranchCSSearchableItemAttributeSet.m */, - 5F644B9F2B7AA811000DCD78 /* BranchDelegate.m */, - 5F644BB22B7AA811000DCD78 /* BranchEvent.m */, - 5F644B342B7AA810000DCD78 /* BranchInstallRequest.m */, - 5F644B4B2B7AA810000DCD78 /* BranchJsonConfig.m */, - 5F644BA42B7AA811000DCD78 /* BranchLastAttributedTouchData.m */, - 5F644B4C2B7AA810000DCD78 /* BranchLATDRequest.m */, - 5F644BA92B7AA811000DCD78 /* BranchLinkProperties.m */, - 5F5FDA0F2B7DE20800F14A43 /* BranchLogger.m */, - 5F644BB42B7AA811000DCD78 /* BranchOpenRequest.m */, - 5F644B2A2B7AA810000DCD78 /* BranchPasteControl.m */, - 5F644B352B7AA810000DCD78 /* BranchPluginSupport.m */, - 5F644B502B7AA810000DCD78 /* BranchQRCode.m */, - 5F644B312B7AA810000DCD78 /* BranchScene.m */, - 5F644BAE2B7AA811000DCD78 /* BranchShareLink.m */, - 5F644BB32B7AA811000DCD78 /* BranchShortUrlRequest.m */, - 5F644BB62B7AA811000DCD78 /* BranchShortUrlSyncRequest.m */, - 5F644B402B7AA810000DCD78 /* BranchSpotlightUrlRequest.m */, - 5F644B292B7AA810000DCD78 /* BranchUniversalObject.m */, - 5F644B262B7AA810000DCD78 /* NSError+Branch.m */, - 5F644B2D2B7AA810000DCD78 /* NSMutableDictionary+Branch.m */, - 5F644B362B7AA810000DCD78 /* NSString+Branch.m */, - 5F644BAF2B7AA811000DCD78 /* UIViewController+Branch.m */, - 5F644B6E2B7AA810000DCD78 /* Private */, - 5F644B522B7AA810000DCD78 /* Public */, - ); - name = BranchSDK; - path = ../Sources/BranchSDK; - sourceTree = ""; - }; 5F644B522B7AA810000DCD78 /* Public */ = { isa = PBXGroup; children = ( + E7CA74B12E1B4890002EFB40 /* BranchConstants.h */, 5F644B5E2B7AA810000DCD78 /* BNCCallbacks.h */, 5F644B5A2B7AA810000DCD78 /* BNCCurrency.h */, 5F644B612B7AA810000DCD78 /* BNCInitSessionResponse.h */, @@ -835,7 +777,6 @@ 5F644B692B7AA810000DCD78 /* BranchPluginSupport.h */, 5F644B552B7AA810000DCD78 /* BranchQRCode.h */, 5F644B6A2B7AA810000DCD78 /* BranchScene.h */, - 5F644B592B7AA810000DCD78 /* BranchSDK.h */, 5F644B5F2B7AA810000DCD78 /* BranchShareLink.h */, 5F644B662B7AA810000DCD78 /* BranchUniversalObject.h */, ); @@ -845,7 +786,6 @@ 5F644B6E2B7AA810000DCD78 /* Private */ = { isa = PBXGroup; children = ( - E7AE4A0B2DFB2D0100696805 /* BranchConfigurationController.h */, E71E397A2DD3C14800110F59 /* BNCInAppBrowser.h */, 5F644B762B7AA810000DCD78 /* BNCAppGroupsData.h */, 5F644B702B7AA810000DCD78 /* BNCAppleReceipt.h */, @@ -878,7 +818,6 @@ 5F644B842B7AA811000DCD78 /* BNCUserAgentCollector.h */, E7AC74562DB0639E002D8C40 /* BNCODMInfoCollector.h */, 5F644B8D2B7AA811000DCD78 /* Branch+Validator.h */, - 5F644B962B7AA811000DCD78 /* BranchConstants.h */, 5F644B922B7AA811000DCD78 /* BranchContentDiscoverer.h */, 5F644B942B7AA811000DCD78 /* BranchContentDiscoveryManifest.h */, 5F644B722B7AA810000DCD78 /* BranchContentPathProperties.h */, @@ -924,12 +863,10 @@ 670016571940F51400A9E103 = { isa = PBXGroup; children = ( - E7FC47722DFC7B020072B3ED /* BranchConfigurationController.m */, E7AC74762DB06B42002D8C40 /* Reflection_ODM_Tests.xctestplan */, 6589EBA52674270100F2E28B /* Branch-TestBed-CI.xctestplan */, 033FC71025AC1E5800D8319E /* Branch-TestBed.xctestplan */, 4D93D8592098CC4400CFABA6 /* README.md */, - 5F644B252B7AA810000DCD78 /* BranchSDK */, 4D16837A2098C901008819E3 /* Branch-SDK-Tests */, 5F8B7B3C21B5F5CD009CE0A6 /* Branch-SDK-Unhosted-Tests */, 670016691940F51400A9E103 /* Branch-TestBed */, @@ -946,7 +883,6 @@ children = ( 670016601940F51400A9E103 /* Branch-TestBed.app */, 7E6B3B511AA42D0E005F45BF /* Branch-SDK-Tests.xctest */, - 466B58381B17773000A69EDE /* libBranch.a */, F1D4F9AC1F323F01002D13FF /* Branch-TestBed-UITests.xctest */, 5F8B7B3B21B5F5CD009CE0A6 /* Branch-SDK-Unhosted-Tests.xctest */, E7AC74602DB064BC002D8C40 /* Reflection_ODM_Tests.xctest */, @@ -1016,6 +952,97 @@ name = "Supporting Files"; sourceTree = ""; }; + B7A21E5C2E8EDD5F00BB1E14 /* Private */ = { + isa = PBXGroup; + children = ( + B7A21E2B2E8EDD5F00BB1E14 /* BNCAppGroupsData.h */, + B7A21E2C2E8EDD5F00BB1E14 /* BNCAppleReceipt.h */, + B7A21E2D2E8EDD5F00BB1E14 /* BNCApplication.h */, + B7A21E2E2E8EDD5F00BB1E14 /* BNCCallbackMap.h */, + B7A21E2F2E8EDD5F00BB1E14 /* BNCConfig.h */, + B7A21E302E8EDD5F00BB1E14 /* BNCContentDiscoveryManager.h */, + B7A21E312E8EDD5F00BB1E14 /* BNCCrashlyticsWrapper.h */, + B7A21E322E8EDD5F00BB1E14 /* BNCDeepLinkViewControllerInstance.h */, + B7A21E332E8EDD5F00BB1E14 /* BNCDeviceInfo.h */, + B7A21E342E8EDD5F00BB1E14 /* BNCDeviceSystem.h */, + B7A21E352E8EDD5F00BB1E14 /* BNCEncodingUtils.h */, + B7A21E362E8EDD5F00BB1E14 /* BNCEventUtils.h */, + B7A21E372E8EDD5F00BB1E14 /* BNCInAppBrowser.h */, + B7A21E382E8EDD5F00BB1E14 /* BNCJSONUtility.h */, + B7A21E392E8EDD5F00BB1E14 /* BNCKeyChain.h */, + B7A21E3A2E8EDD5F00BB1E14 /* BNCNetworkInterface.h */, + B7A21E3B2E8EDD5F00BB1E14 /* BNCNetworkService.h */, + B7A21E3C2E8EDD5F00BB1E14 /* BNCODMInfoCollector.h */, + B7A21E3D2E8EDD5F00BB1E14 /* BNCPartnerParameters.h */, + B7A21E3E2E8EDD5F00BB1E14 /* BNCPasteboard.h */, + B7A21E3F2E8EDD5F00BB1E14 /* BNCQRCodeCache.h */, + B7A21E402E8EDD5F00BB1E14 /* BNCReachability.h */, + B7A21E412E8EDD5F00BB1E14 /* BNCReferringURLUtility.h */, + B7A21E422E8EDD5F00BB1E14 /* BNCRequestFactory.h */, + B7A21E432E8EDD5F00BB1E14 /* BNCServerAPI.h */, + B7A21E442E8EDD5F00BB1E14 /* BNCServerRequestOperation.h */, + B7A21E452E8EDD5F00BB1E14 /* BNCSKAdNetwork.h */, + B7A21E462E8EDD5F00BB1E14 /* BNCSpotlightService.h */, + B7A21E472E8EDD5F00BB1E14 /* BNCSystemObserver.h */, + B7A21E482E8EDD5F00BB1E14 /* BNCURLFilter.h */, + B7A21E492E8EDD5F00BB1E14 /* BNCUrlQueryParameter.h */, + B7A21E4A2E8EDD5F00BB1E14 /* BNCUserAgentCollector.h */, + B7A21E4B2E8EDD5F00BB1E14 /* Branch+Validator.h */, + B7A21E4C2E8EDD5F00BB1E14 /* BranchConfigurationController.h */, + B7A21E4D2E8EDD5F00BB1E14 /* BranchContentDiscoverer.h */, + B7A21E4E2E8EDD5F00BB1E14 /* BranchContentDiscoveryManifest.h */, + B7A21E4F2E8EDD5F00BB1E14 /* BranchContentPathProperties.h */, + B7A21E502E8EDD5F00BB1E14 /* BranchFileLogger.h */, + B7A21E512E8EDD5F00BB1E14 /* BranchInstallRequest.h */, + B7A21E522E8EDD5F00BB1E14 /* BranchJsonConfig.h */, + B7A21E532E8EDD5F00BB1E14 /* BranchLATDRequest.h */, + B7A21E542E8EDD5F00BB1E14 /* BranchOpenRequest.h */, + B7A21E552E8EDD5F00BB1E14 /* BranchShortUrlRequest.h */, + B7A21E562E8EDD5F00BB1E14 /* BranchShortUrlSyncRequest.h */, + B7A21E572E8EDD5F00BB1E14 /* BranchSpotlightUrlRequest.h */, + B7A21E582E8EDD5F00BB1E14 /* NSError+Branch.h */, + B7A21E592E8EDD5F00BB1E14 /* NSMutableDictionary+Branch.h */, + B7A21E5A2E8EDD5F00BB1E14 /* NSString+Branch.h */, + B7A21E5B2E8EDD5F00BB1E14 /* UIViewController+Branch.h */, + ); + path = Private; + sourceTree = ""; + }; + B7A21E7A2E8EDD5F00BB1E14 /* Public */ = { + isa = PBXGroup; + children = ( + B7A21E5D2E8EDD5F00BB1E14 /* BNCCallbacks.h */, + B7A21E5E2E8EDD5F00BB1E14 /* BNCCurrency.h */, + B7A21E5F2E8EDD5F00BB1E14 /* BNCInitSessionResponse.h */, + B7A21E602E8EDD5F00BB1E14 /* BNCLinkCache.h */, + B7A21E612E8EDD5F00BB1E14 /* BNCLinkData.h */, + B7A21E622E8EDD5F00BB1E14 /* BNCNetworkServiceProtocol.h */, + B7A21E632E8EDD5F00BB1E14 /* BNCPreferenceHelper.h */, + B7A21E642E8EDD5F00BB1E14 /* BNCProductCategory.h */, + B7A21E652E8EDD5F00BB1E14 /* BNCServerInterface.h */, + B7A21E662E8EDD5F00BB1E14 /* BNCServerRequest.h */, + B7A21E672E8EDD5F00BB1E14 /* BNCServerRequestQueue.h */, + B7A21E682E8EDD5F00BB1E14 /* BNCServerResponse.h */, + B7A21E692E8EDD5F00BB1E14 /* Branch.h */, + B7A21E6A2E8EDD5F00BB1E14 /* BranchActivityItemProvider.h */, + B7A21E6B2E8EDD5F00BB1E14 /* BranchConstants.h */, + B7A21E6C2E8EDD5F00BB1E14 /* BranchCSSearchableItemAttributeSet.h */, + B7A21E6D2E8EDD5F00BB1E14 /* BranchDeepLinkingController.h */, + B7A21E6E2E8EDD5F00BB1E14 /* BranchDelegate.h */, + B7A21E6F2E8EDD5F00BB1E14 /* BranchEvent.h */, + B7A21E702E8EDD5F00BB1E14 /* BranchLastAttributedTouchData.h */, + B7A21E712E8EDD5F00BB1E14 /* BranchLinkProperties.h */, + B7A21E722E8EDD5F00BB1E14 /* BranchLogger.h */, + B7A21E732E8EDD5F00BB1E14 /* BranchPasteControl.h */, + B7A21E742E8EDD5F00BB1E14 /* BranchPluginSupport.h */, + B7A21E752E8EDD5F00BB1E14 /* BranchQRCode.h */, + B7A21E762E8EDD5F00BB1E14 /* BranchScene.h */, + B7A21E782E8EDD5F00BB1E14 /* BranchShareLink.h */, + B7A21E792E8EDD5F00BB1E14 /* BranchUniversalObject.h */, + ); + path = Public; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1030,7 +1057,6 @@ 5F644BE82B7AA811000DCD78 /* BranchActivityItemProvider.h in Headers */, 5F644BE92B7AA811000DCD78 /* BranchCSSearchableItemAttributeSet.h in Headers */, 5F644BEA2B7AA811000DCD78 /* BranchLinkProperties.h in Headers */, - 5F644BEB2B7AA811000DCD78 /* BranchSDK.h in Headers */, 5F644BEC2B7AA811000DCD78 /* BNCCurrency.h in Headers */, 5F644BED2B7AA811000DCD78 /* BranchLastAttributedTouchData.h in Headers */, 5F644BEE2B7AA811000DCD78 /* Branch.h in Headers */, @@ -1062,6 +1088,7 @@ 5F644C032B7AA811000DCD78 /* BranchContentPathProperties.h in Headers */, 5F644C042B7AA811000DCD78 /* BNCSKAdNetwork.h in Headers */, 5F644C0E2B7AA811000DCD78 /* BNCQRCodeCache.h in Headers */, + E7CA74B22E1B4890002EFB40 /* BranchConstants.h in Headers */, 5F644C2E2B7AA811000DCD78 /* BNCNetworkService.h in Headers */, 5F644C1B2B7AA811000DCD78 /* BNCSystemObserver.h in Headers */, 5F644C292B7AA811000DCD78 /* BranchJsonConfig.h in Headers */, @@ -1074,7 +1101,6 @@ 5F644C052B7AA811000DCD78 /* BNCJSONUtility.h in Headers */, 5F644C2D2B7AA811000DCD78 /* BNCReferringURLUtility.h in Headers */, 5F644C0B2B7AA811000DCD78 /* BNCEventUtils.h in Headers */, - 5F644C272B7AA811000DCD78 /* BranchConstants.h in Headers */, 5F644C002B7AA811000DCD78 /* BNCKeyChain.h in Headers */, 5F644C1D2B7AA811000DCD78 /* BranchInstallRequest.h in Headers */, 5F644C0D2B7AA811000DCD78 /* BranchShortUrlSyncRequest.h in Headers */, @@ -1097,7 +1123,6 @@ 5F644C062B7AA811000DCD78 /* UIViewController+Branch.h in Headers */, 5F644C022B7AA811000DCD78 /* BNCPasteboard.h in Headers */, 5F644C0F2B7AA811000DCD78 /* BranchOpenRequest.h in Headers */, - E7AE4A0C2DFB2D0100696805 /* BranchConfigurationController.h in Headers */, 5F644C2C2B7AA811000DCD78 /* BNCRequestFactory.h in Headers */, 5F644C142B7AA811000DCD78 /* BNCDeviceSystem.h in Headers */, ); @@ -1119,8 +1144,9 @@ dependencies = ( ); name = Branch; + packageProductDependencies = ( + ); productName = Branch; - productReference = 466B58381B17773000A69EDE /* libBranch.a */; productType = "com.apple.product-type.library.static"; }; 5F8B7B3A21B5F5CD009CE0A6 /* Branch-SDK-Unhosted-Tests */ = { @@ -1134,7 +1160,6 @@ buildRules = ( ); dependencies = ( - 5F8B7B4221B5F5CD009CE0A6 /* PBXTargetDependency */, ); name = "Branch-SDK-Unhosted-Tests"; productName = "Branch-SDK-Unhosted-Tests"; @@ -1153,9 +1178,11 @@ buildRules = ( ); dependencies = ( - 466B58701B1777DE00A69EDE /* PBXTargetDependency */, ); name = "Branch-TestBed"; + packageProductDependencies = ( + B77CB6C62E8EE36300FDF144 /* BranchSDK */, + ); productName = "Branch-TestBed"; productReference = 670016601940F51400A9E103 /* Branch-TestBed.app */; productType = "com.apple.product-type.application"; @@ -1172,8 +1199,6 @@ buildRules = ( ); dependencies = ( - 4683F07C1B20AC6300A432E7 /* PBXTargetDependency */, - 4D337DDD201019B8009A5774 /* PBXTargetDependency */, ); name = "Branch-SDK-Tests"; productName = "Branch-SDK Functionality Tests"; @@ -1191,18 +1216,11 @@ buildRules = ( ); dependencies = ( - E7AC74662DB064BC002D8C40 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( E7AC74612DB064BC002D8C40 /* Reflection_ODM_Tests */, ); name = Reflection_ODM_Tests; - packageProductDependencies = ( - E7AC746F2DB06992002D8C40 /* GULLogger */, - E7AC74712DB06992002D8C40 /* GULNetwork */, - E7AC74742DB069B2002D8C40 /* nanopb */, - E7AC747A2DB0700D002D8C40 /* BranchSDK */, - ); productName = Reflection_ODM_Tests; productReference = E7AC74602DB064BC002D8C40 /* Reflection_ODM_Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -1218,7 +1236,6 @@ buildRules = ( ); dependencies = ( - F1D4F9B21F323F01002D13FF /* PBXTargetDependency */, ); name = "Branch-TestBed-UITests"; productName = "Branch-TestBedUITests"; @@ -1238,6 +1255,7 @@ TargetAttributes = { 466B58371B17773000A69EDE = { CreatedOnToolsVersion = 6.3.2; + LastSwiftMigration = 1640; }; 5F8B7B3A21B5F5CD009CE0A6 = { CreatedOnToolsVersion = 10.1; @@ -1283,9 +1301,7 @@ ); mainGroup = 670016571940F51400A9E103; packageReferences = ( - E7AC746E2DB06992002D8C40 /* XCRemoteSwiftPackageReference "GoogleUtilities" */, - E7AC74732DB069B2002D8C40 /* XCRemoteSwiftPackageReference "nanopb" */, - E7AC74792DB0700D002D8C40 /* XCLocalSwiftPackageReference "../../ios-branch-deep-linking-attribution" */, + B77CB6C52E8EE36300FDF144 /* XCLocalSwiftPackageReference "../../ios-branch-deep-linking-attribution" */, ); productRefGroup = 670016611940F51400A9E103 /* Products */; projectDirPath = ""; @@ -1374,79 +1390,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E7FC47732DFC7B020072B3ED /* BranchConfigurationController.m in Sources */, - 5F644BB92B7AA811000DCD78 /* NSError+Branch.m in Sources */, - 5F644C482B7AA811000DCD78 /* BNCCallbackMap.m in Sources */, - 5F644BBE2B7AA811000DCD78 /* BNCApplication.m in Sources */, - 5F644C302B7AA811000DCD78 /* BranchDelegate.m in Sources */, - 5F5FDA102B7DE20800F14A43 /* BranchLogger.m in Sources */, - 5F644C3D2B7AA811000DCD78 /* BNCSpotlightService.m in Sources */, - 5F644BC02B7AA811000DCD78 /* NSMutableDictionary+Branch.m in Sources */, - 5F644BBC2B7AA811000DCD78 /* BranchUniversalObject.m in Sources */, - 5F644BE42B7AA811000DCD78 /* BNCKeyChain.m in Sources */, - 5F644BDE2B7AA811000DCD78 /* BranchJsonConfig.m in Sources */, - 5F644BE02B7AA811000DCD78 /* BNCPartnerParameters.m in Sources */, - 5F644BDF2B7AA811000DCD78 /* BranchLATDRequest.m in Sources */, - 5F644C382B7AA811000DCD78 /* BNCPasteboard.m in Sources */, - 5F644BE22B7AA811000DCD78 /* BranchActivityItemProvider.m in Sources */, - E7AC74592DB063C6002D8C40 /* BNCODMInfoCollector.m in Sources */, - 5F644BE12B7AA811000DCD78 /* BranchCSSearchableItemAttributeSet.m in Sources */, - 5F644BD92B7AA811000DCD78 /* BNCRequestFactory.m in Sources */, - 5F644BC32B7AA811000DCD78 /* BNCDeepLinkViewControllerInstance.m in Sources */, - 5F644C3C2B7AA811000DCD78 /* BNCLinkCache.m in Sources */, - 5F644C332B7AA811000DCD78 /* BNCJSONUtility.m in Sources */, - 5F644BDB2B7AA811000DCD78 /* BNCProductCategory.m in Sources */, - 5F644C322B7AA811000DCD78 /* Branch.m in Sources */, - 5F644BC72B7AA811000DCD78 /* BranchInstallRequest.m in Sources */, - 5F644BC62B7AA811000DCD78 /* Branch+Validator.m in Sources */, - 5F644BBA2B7AA811000DCD78 /* BNCUserAgentCollector.m in Sources */, - 5F644C362B7AA811000DCD78 /* BNCSKAdNetwork.m in Sources */, - 5F644BD02B7AA811000DCD78 /* BNCConfig.m in Sources */, - 5F644BD52B7AA811000DCD78 /* BranchContentDiscoverer.m in Sources */, - 5F644BBF2B7AA811000DCD78 /* BNCDeviceSystem.m in Sources */, - 5F644C412B7AA811000DCD78 /* BNCAppGroupsData.m in Sources */, - 5F644BBD2B7AA811000DCD78 /* BranchPasteControl.m in Sources */, - 5F644C492B7AA811000DCD78 /* BNCEventUtils.m in Sources */, - 5F644BD32B7AA811000DCD78 /* BranchSpotlightUrlRequest.m in Sources */, - 5F644BE32B7AA811000DCD78 /* BranchQRCode.m in Sources */, - 5F644BCA2B7AA811000DCD78 /* BNCSystemObserver.m in Sources */, - 5F644BC82B7AA811000DCD78 /* BranchPluginSupport.m in Sources */, - 5F644C462B7AA811000DCD78 /* BNCQRCodeCache.m in Sources */, - 5F644BD82B7AA811000DCD78 /* BNCReachability.m in Sources */, - 5F644BC92B7AA811000DCD78 /* NSString+Branch.m in Sources */, - 5F644C442B7AA811000DCD78 /* BranchShortUrlRequest.m in Sources */, - 5F644BDD2B7AA811000DCD78 /* BNCServerInterface.m in Sources */, - 5F644BC42B7AA811000DCD78 /* BranchScene.m in Sources */, - 5F644BBB2B7AA811000DCD78 /* BNCEncodingUtils.m in Sources */, - 5F644BD62B7AA811000DCD78 /* BNCDeviceInfo.m in Sources */, - 5F644BC22B7AA811000DCD78 /* BNCUrlQueryParameter.m in Sources */, - 5F644C3E2B7AA811000DCD78 /* BNCServerAPI.m in Sources */, - 5F644BD12B7AA811000DCD78 /* BranchConstants.m in Sources */, - 5F644C342B7AA811000DCD78 /* BNCCurrency.m in Sources */, - 5F644C472B7AA811000DCD78 /* BranchShortUrlSyncRequest.m in Sources */, - 5F644BC52B7AA811000DCD78 /* BNCContentDiscoveryManager.m in Sources */, - 5F644BCC2B7AA811000DCD78 /* BNCURLFilter.m in Sources */, - 5F644C352B7AA811000DCD78 /* BranchLastAttributedTouchData.m in Sources */, - 5F644BCE2B7AA811000DCD78 /* BNCNetworkInterface.m in Sources */, - 5F644BD72B7AA811000DCD78 /* BNCNetworkService.m in Sources */, - 5F644C402B7AA811000DCD78 /* UIViewController+Branch.m in Sources */, - 5F644BC12B7AA811000DCD78 /* BNCServerRequestQueue.m in Sources */, - E56394312CC7AC9F00E18E65 /* BranchFileLogger.m in Sources */, - 5F644C452B7AA811000DCD78 /* BranchOpenRequest.m in Sources */, - 5F644C312B7AA811000DCD78 /* BNCLinkData.m in Sources */, - E7E28ECA2DD2424C00F75D0D /* BNCInAppBrowser.m in Sources */, - 5F644BD22B7AA811000DCD78 /* BranchContentDiscoveryManifest.m in Sources */, - 5F644BDC2B7AA811000DCD78 /* BNCCrashlyticsWrapper.m in Sources */, - 5F644C3F2B7AA811000DCD78 /* BranchShareLink.m in Sources */, - 5F644BCD2B7AA811000DCD78 /* BNCServerRequest.m in Sources */, - 5F644C3A2B7AA811000DCD78 /* BranchLinkProperties.m in Sources */, - 5F644C432B7AA811000DCD78 /* BranchEvent.m in Sources */, - 5F644C392B7AA811000DCD78 /* BNCAppleReceipt.m in Sources */, - 5F644BDA2B7AA811000DCD78 /* BNCReferringURLUtility.m in Sources */, - 5F644C422B7AA811000DCD78 /* BNCServerResponse.m in Sources */, - 5F644C3B2B7AA811000DCD78 /* BNCInitSessionResponse.m in Sources */, - 5F644BCF2B7AA811000DCD78 /* BNCPreferenceHelper.m in Sources */, - 5F644C372B7AA811000DCD78 /* BranchContentPathProperties.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1546,39 +1489,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 466B58701B1777DE00A69EDE /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 466B58371B17773000A69EDE /* Branch */; - targetProxy = 466B586F1B1777DE00A69EDE /* PBXContainerItemProxy */; - }; - 4683F07C1B20AC6300A432E7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 466B58371B17773000A69EDE /* Branch */; - targetProxy = 4683F07B1B20AC6300A432E7 /* PBXContainerItemProxy */; - }; - 4D337DDD201019B8009A5774 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6700165F1940F51400A9E103 /* Branch-TestBed */; - targetProxy = 4D337DDC201019B8009A5774 /* PBXContainerItemProxy */; - }; - 5F8B7B4221B5F5CD009CE0A6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 466B58371B17773000A69EDE /* Branch */; - targetProxy = 5F8B7B4121B5F5CD009CE0A6 /* PBXContainerItemProxy */; - }; - E7AC74662DB064BC002D8C40 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 466B58371B17773000A69EDE /* Branch */; - targetProxy = E7AC74652DB064BC002D8C40 /* PBXContainerItemProxy */; - }; - F1D4F9B21F323F01002D13FF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6700165F1940F51400A9E103 /* Branch-TestBed */; - targetProxy = F1D4F9B11F323F01002D13FF /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 6700166C1940F51400A9E103 /* InfoPlist.strings */ = { isa = PBXVariantGroup; @@ -1603,6 +1513,9 @@ "DEBUG=1", "$(inherited)", ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ); IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = "-ObjC"; @@ -1610,6 +1523,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = /headers; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -1622,6 +1536,9 @@ DEFINES_MODULE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ); IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-ObjC"; @@ -1629,6 +1546,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = /headers; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -2072,49 +1990,16 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - E7AC74792DB0700D002D8C40 /* XCLocalSwiftPackageReference "../../ios-branch-deep-linking-attribution" */ = { + B77CB6C52E8EE36300FDF144 /* XCLocalSwiftPackageReference "../../ios-branch-deep-linking-attribution" */ = { isa = XCLocalSwiftPackageReference; relativePath = "../../ios-branch-deep-linking-attribution"; }; /* End XCLocalSwiftPackageReference section */ -/* Begin XCRemoteSwiftPackageReference section */ - E7AC746E2DB06992002D8C40 /* XCRemoteSwiftPackageReference "GoogleUtilities" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/google/GoogleUtilities"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 8.0.2; - }; - }; - E7AC74732DB069B2002D8C40 /* XCRemoteSwiftPackageReference "nanopb" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/nanopb/nanopb"; - requirement = { - kind = revision; - revision = b7e1104502eca3a213b46303391ca4d3bc8ddec1; - }; - }; -/* End XCRemoteSwiftPackageReference section */ - /* Begin XCSwiftPackageProductDependency section */ - E7AC746F2DB06992002D8C40 /* GULLogger */ = { - isa = XCSwiftPackageProductDependency; - package = E7AC746E2DB06992002D8C40 /* XCRemoteSwiftPackageReference "GoogleUtilities" */; - productName = GULLogger; - }; - E7AC74712DB06992002D8C40 /* GULNetwork */ = { - isa = XCSwiftPackageProductDependency; - package = E7AC746E2DB06992002D8C40 /* XCRemoteSwiftPackageReference "GoogleUtilities" */; - productName = GULNetwork; - }; - E7AC74742DB069B2002D8C40 /* nanopb */ = { - isa = XCSwiftPackageProductDependency; - package = E7AC74732DB069B2002D8C40 /* XCRemoteSwiftPackageReference "nanopb" */; - productName = nanopb; - }; - E7AC747A2DB0700D002D8C40 /* BranchSDK */ = { + B77CB6C62E8EE36300FDF144 /* BranchSDK */ = { isa = XCSwiftPackageProductDependency; + package = B77CB6C52E8EE36300FDF144 /* XCLocalSwiftPackageReference "../" */; productName = BranchSDK; }; /* End XCSwiftPackageProductDependency section */ diff --git a/Branch-TestBed/Branch-TestBed.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Branch-TestBed/Branch-TestBed.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index cd1bf1554..000000000 --- a/Branch-TestBed/Branch-TestBed.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,23 +0,0 @@ -{ - "originHash" : "d56bc7728e41c97a44136d6183fac55f67109eb4ddd481e77850df5331f07c38", - "pins" : [ - { - "identity" : "googleutilities", - "kind" : "remoteSourceControl", - "location" : "https://github.com/google/GoogleUtilities", - "state" : { - "revision" : "53156c7ec267db846e6b64c9f4c4e31ba4cf75eb", - "version" : "8.0.2" - } - }, - { - "identity" : "nanopb", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nanopb/nanopb", - "state" : { - "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1" - } - } - ], - "version" : 3 -} diff --git a/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Branch-SDK-Tests.xcscheme b/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Branch-SDK-Tests.xcscheme index 1f130cd47..461595a04 100644 --- a/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Branch-SDK-Tests.xcscheme +++ b/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Branch-SDK-Tests.xcscheme @@ -1,6 +1,6 @@ + + + + diff --git a/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Branch-SDK-Unhosted-Tests.xcscheme b/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Branch-SDK-Unhosted-Tests.xcscheme index 40a19b5ba..8cd35e0b8 100644 --- a/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Branch-SDK-Unhosted-Tests.xcscheme +++ b/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Branch-SDK-Unhosted-Tests.xcscheme @@ -1,6 +1,6 @@ @@ -34,7 +34,7 @@ @@ -83,7 +83,7 @@ @@ -99,7 +99,7 @@ diff --git a/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Reflection_ODM_Tests.xcscheme b/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Reflection_ODM_Tests.xcscheme index 84c83c2f5..ea6854043 100644 --- a/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Reflection_ODM_Tests.xcscheme +++ b/Branch-TestBed/Branch-TestBed.xcodeproj/xcshareddata/xcschemes/Reflection_ODM_Tests.xcscheme @@ -1,6 +1,6 @@ @end diff --git a/Branch-TestBed/Branch-TestBed/PasteControlViewController.m b/Branch-TestBed/Branch-TestBed/PasteControlViewController.m index aa702c70b..4349ac9e1 100644 --- a/Branch-TestBed/Branch-TestBed/PasteControlViewController.m +++ b/Branch-TestBed/Branch-TestBed/PasteControlViewController.m @@ -7,9 +7,7 @@ // #import "PasteControlViewController.h" -#import "Branch.h" -#import "BranchOpenRequest.h" -#import "BranchPasteControl.h" +@import BranchSDK; #import "LogOutputViewController.h" #import "AppDelegate.h" diff --git a/Branch-TestBed/Branch-TestBed/ViewController.m b/Branch-TestBed/Branch-TestBed/ViewController.m index 994b689d4..b094206df 100644 --- a/Branch-TestBed/Branch-TestBed/ViewController.m +++ b/Branch-TestBed/Branch-TestBed/ViewController.m @@ -6,16 +6,11 @@ // Copyright (c) 2014 Branch Metrics. All rights reserved. // -#import "Branch.h" -#import "BranchEvent.h" -#import "BranchQRCode.h" -#import "BranchConstants.h" -#import "BNCConfig.h" +@import BranchSDK; +#import "BNCConfig.h" // For BNC_SDK_VERSION #import "ViewController.h" #import "LogOutputViewController.h" #import "ArrayPickerView.h" -#import "BranchUniversalObject.h" -#import "BranchLinkProperties.h" #import "LogOutputViewController.h" #import "AppDelegate.h" #import diff --git a/BranchSDK.podspec b/BranchSDK.podspec index 35ff4cca3..31c9e28fd 100644 --- a/BranchSDK.podspec +++ b/BranchSDK.podspec @@ -18,10 +18,12 @@ Use the Branch SDK (branch.io) to create and power the links that point back to s.ios.deployment_target = '12.0' s.tvos.deployment_target = '12.0' + s.swift_versions = ['5.0', '5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '5.7', '5.8', '5.9', '6.0'] + s.resource_bundles = { 'BranchSDK' => 'Sources/Resources/*.xcprivacy' } - s.ios.source_files = "Sources/BranchSDK/**/*.{h,m}" + s.ios.source_files = "Sources/BranchSDK/**/*.{h,m}", "Sources/BranchSDK_Swift/**/*.swift", "Sources/BranchSDK_ObjC/**/*.{h,m}" - s.tvos.source_files = "Sources/BranchSDK/**/*.{h,m}" + s.tvos.source_files = "Sources/BranchSDK/**/*.{h,m}", "Sources/BranchSDK_Swift/**/*.swift", "Sources/BranchSDK_ObjC/**/*.{h,m}" s.tvos.exclude_files = "Sources/BranchSDK/**/BNCContentDiscoveryManager.{h,m}", "Sources/BranchSDK/**/BNCUserAgentCollector.{h,m}", "Sources/BranchSDK/**/BNCSpotlightService.{h,m}", diff --git a/BranchSDK.xcodeproj/project.pbxproj b/BranchSDK.xcodeproj/project.pbxproj index 74de0d1d8..0fec375bc 100644 --- a/BranchSDK.xcodeproj/project.pbxproj +++ b/BranchSDK.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 55; + objectVersion = 73; objects = { /* Begin PBXAggregateTarget section */ @@ -54,25 +54,12 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 5F2211722894A9C000C5B190 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211712894A9C000C5B190 /* AppDelegate.swift */; }; - 5F2211742894A9C000C5B190 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211732894A9C000C5B190 /* SceneDelegate.swift */; }; - 5F2211762894A9C000C5B190 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211752894A9C000C5B190 /* ViewController.swift */; }; - 5F2211792894A9C000C5B190 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F2211772894A9C000C5B190 /* Main.storyboard */; }; - 5F22117B2894A9C100C5B190 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F22117A2894A9C100C5B190 /* Assets.xcassets */; }; - 5F22117E2894A9C100C5B190 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F22117C2894A9C100C5B190 /* LaunchScreen.storyboard */; }; - 5F2211892894A9C100C5B190 /* TestHostTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211882894A9C100C5B190 /* TestHostTests.swift */; }; - 5F2211932894A9C100C5B190 /* TestHostUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211922894A9C100C5B190 /* TestHostUITests.swift */; }; - 5F2211952894A9C100C5B190 /* TestHostUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211942894A9C100C5B190 /* TestHostUITestsLaunchTests.swift */; }; 5F5FDA162B7DE2FE00F14A43 /* BranchLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5FDA152B7DE2FE00F14A43 /* BranchLogger.m */; }; 5F5FDA172B7DE2FE00F14A43 /* BranchLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5FDA152B7DE2FE00F14A43 /* BranchLogger.m */; }; 5F5FDA182B7DE2FE00F14A43 /* BranchLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5FDA152B7DE2FE00F14A43 /* BranchLogger.m */; }; 5F5FDA1A2B7DE31E00F14A43 /* BranchLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F5FDA192B7DE31E00F14A43 /* BranchLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F5FDA1B2B7DE31E00F14A43 /* BranchLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F5FDA192B7DE31E00F14A43 /* BranchLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F5FDA1C2B7DE31E00F14A43 /* BranchLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F5FDA192B7DE31E00F14A43 /* BranchLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5F6DD2482894AEBD00AE9FB0 /* BranchSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; }; - 5F6DD24C2894AF5E00AE9FB0 /* NSURLSession+Branch.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F6DD24A2894AF5E00AE9FB0 /* NSURLSession+Branch.m */; }; - 5F73EBFA28ECE65400608601 /* BranchSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F73EBF428ECE65400608601 /* BranchSDK.framework */; }; - 5F73EBFB28ECE65400608601 /* BranchSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5F73EBF428ECE65400608601 /* BranchSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5FA71BA82B7AE6B2008009CA /* Branch.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3A22B7AC6A100EAF29F /* Branch.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5FC446652ACCB97000FF1C87 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 5FC446642ACCB96000FF1C87 /* PrivacyInfo.xcprivacy */; }; 5FC446662ACCB97100FF1C87 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 5FC446642ACCB96000FF1C87 /* PrivacyInfo.xcprivacy */; }; @@ -383,9 +370,6 @@ 5FCDD5462B7AC6A300EAF29F /* BNCConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DB2B7AC6A100EAF29F /* BNCConfig.h */; }; 5FCDD5472B7AC6A300EAF29F /* BNCConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DB2B7AC6A100EAF29F /* BNCConfig.h */; }; 5FCDD5482B7AC6A300EAF29F /* BNCConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DB2B7AC6A100EAF29F /* BNCConfig.h */; }; - 5FCDD5492B7AC6A300EAF29F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DC2B7AC6A100EAF29F /* BranchConstants.h */; }; - 5FCDD54A2B7AC6A300EAF29F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DC2B7AC6A100EAF29F /* BranchConstants.h */; }; - 5FCDD54B2B7AC6A300EAF29F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DC2B7AC6A100EAF29F /* BranchConstants.h */; }; 5FCDD54C2B7AC6A300EAF29F /* BNCPartnerParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DD2B7AC6A100EAF29F /* BNCPartnerParameters.h */; }; 5FCDD54D2B7AC6A300EAF29F /* BNCPartnerParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DD2B7AC6A100EAF29F /* BNCPartnerParameters.h */; }; 5FCDD54E2B7AC6A300EAF29F /* BNCPartnerParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3DD2B7AC6A100EAF29F /* BNCPartnerParameters.h */; }; @@ -489,6 +473,12 @@ 5FCDD5B22B7AC89100EAF29F /* BranchSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FF2AFDF28E7C22100393216 /* BranchSDK.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5FCDD5B32B7AC89200EAF29F /* BranchSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FF2AFDF28E7C22100393216 /* BranchSDK.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5FCDD5B42B7AC89200EAF29F /* BranchSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FF2AFDF28E7C22100393216 /* BranchSDK.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B70D0E162E8DB20C002BD4FE /* jira_task.xml in Sources */ = {isa = PBXBuildFile; fileRef = B70D0E152E8DB20A002BD4FE /* jira_task.xml */; }; + B70D0E252E8DC1F8002BD4FE /* BranchConfigurationController.m in Sources */ = {isa = PBXBuildFile; fileRef = B70D0E242E8DC1F8002BD4FE /* BranchConfigurationController.m */; }; + B70D0E262E8DC1F8002BD4FE /* BranchConfigurationController.m in Sources */ = {isa = PBXBuildFile; fileRef = B70D0E242E8DC1F8002BD4FE /* BranchConfigurationController.m */; }; + B70D0E272E8DC1F8002BD4FE /* BranchConfigurationController.m in Sources */ = {isa = PBXBuildFile; fileRef = B70D0E242E8DC1F8002BD4FE /* BranchConfigurationController.m */; }; + B70D0E2C2E8DCEC6002BD4FE /* BNCServerRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = E74E438D2E2F56AC000DC427 /* BNCServerRequestOperation.m */; }; + B70D0E2D2E8DCEC6002BD4FE /* BNCServerRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = E74E438D2E2F56AC000DC427 /* BNCServerRequestOperation.m */; }; E52E5B062CC79E4E00F553EE /* BranchFileLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = E52E5B052CC79E4E00F553EE /* BranchFileLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; E52E5B072CC79E4E00F553EE /* BranchFileLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = E52E5B052CC79E4E00F553EE /* BranchFileLogger.h */; }; E52E5B0A2CC79E5C00F553EE /* BranchFileLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = E52E5B092CC79E5C00F553EE /* BranchFileLogger.m */; }; @@ -499,51 +489,59 @@ E71E39722DD3A92900110F59 /* BNCInAppBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = E71E396D2DD3A92900110F59 /* BNCInAppBrowser.h */; }; E71E39732DD3A92900110F59 /* BNCInAppBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = E71E396E2DD3A92900110F59 /* BNCInAppBrowser.m */; }; E71E39742DD3A92900110F59 /* BNCInAppBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = E71E396D2DD3A92900110F59 /* BNCInAppBrowser.h */; }; - E73D02812DEE8AE90076C3F1 /* BranchConfigurationController.m in Sources */ = {isa = PBXBuildFile; fileRef = E73D02802DEE8AE90076C3F1 /* BranchConfigurationController.m */; }; - E73D02822DEE8AE90076C3F1 /* BranchConfigurationController.h in Headers */ = {isa = PBXBuildFile; fileRef = E73D027F2DEE8AE90076C3F1 /* BranchConfigurationController.h */; }; - E73D02832DEE8AE90076C3F1 /* BranchConfigurationController.h in Headers */ = {isa = PBXBuildFile; fileRef = E73D027F2DEE8AE90076C3F1 /* BranchConfigurationController.h */; }; - E73D02842DEE8AE90076C3F1 /* BranchConfigurationController.m in Sources */ = {isa = PBXBuildFile; fileRef = E73D02802DEE8AE90076C3F1 /* BranchConfigurationController.m */; }; - E73D02852DEE8AE90076C3F1 /* BranchConfigurationController.m in Sources */ = {isa = PBXBuildFile; fileRef = E73D02802DEE8AE90076C3F1 /* BranchConfigurationController.m */; }; - E73D02862DEE8AE90076C3F1 /* BranchConfigurationController.h in Headers */ = {isa = PBXBuildFile; fileRef = E73D027F2DEE8AE90076C3F1 /* BranchConfigurationController.h */; }; + E74E43862E2F55E5000DC427 /* BNCServerRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = E74E43852E2F55E5000DC427 /* BNCServerRequestOperation.h */; }; + E74E43872E2F55E5000DC427 /* BNCServerRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = E74E43852E2F55E5000DC427 /* BNCServerRequestOperation.h */; }; + E74E43882E2F55E5000DC427 /* BNCServerRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = E74E43852E2F55E5000DC427 /* BNCServerRequestOperation.h */; }; + E74E438E2E2F56AC000DC427 /* BNCServerRequestOperation.m in Headers */ = {isa = PBXBuildFile; fileRef = E74E438D2E2F56AC000DC427 /* BNCServerRequestOperation.m */; }; + E74E438F2E2F56AC000DC427 /* BNCServerRequestOperation.m in Headers */ = {isa = PBXBuildFile; fileRef = E74E438D2E2F56AC000DC427 /* BNCServerRequestOperation.m */; }; + E74E43902E2F56AC000DC427 /* BNCServerRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = E74E438D2E2F56AC000DC427 /* BNCServerRequestOperation.m */; }; + E7CA74EF2E1B4F75002EFB40 /* BranchSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; settings = {ATTRIBUTES = (Required, ); }; }; + E7CA75B92E1B994B002EFB40 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7CA75B82E1B994B002EFB40 /* AdServices.framework */; }; + E7CA75BB2E1B9951002EFB40 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7CA75BA2E1B9951002EFB40 /* AdSupport.framework */; }; + E7CA75BC2E1B9957002EFB40 /* BranchSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; }; + E7CA75BD2E1B9957002EFB40 /* BranchSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; E7F311AE2DACB4D400F824A7 /* BNCODMInfoCollector.m in Sources */ = {isa = PBXBuildFile; fileRef = E7F311AD2DACB4D400F824A7 /* BNCODMInfoCollector.m */; }; E7F311AF2DACB4D400F824A7 /* BNCODMInfoCollector.m in Sources */ = {isa = PBXBuildFile; fileRef = E7F311AD2DACB4D400F824A7 /* BNCODMInfoCollector.m */; }; E7F311B12DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */; }; E7F311B22DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */; }; E7F311B32DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */; }; + E7FAF6A02E26E497006C167F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FAF69F2E26E497006C167F /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E7FAF6A12E26E497006C167F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FAF69F2E26E497006C167F /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E7FAF6A22E26E497006C167F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FAF69F2E26E497006C167F /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 5F2211852894A9C100C5B190 /* PBXContainerItemProxy */ = { + E7CA75592E1B52F4002EFB40 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5F2210142894A0DB00C5B190 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5F22116E2894A9C000C5B190; - remoteInfo = TestHost; + remoteGlobalIDString = 5F22101C2894A0DB00C5B190; + remoteInfo = BranchSDK; }; - 5F22118F2894A9C100C5B190 /* PBXContainerItemProxy */ = { + E7CA75A62E1B79CD002EFB40 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5F2210142894A0DB00C5B190 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5F22116E2894A9C000C5B190; - remoteInfo = TestHost; + remoteGlobalIDString = E7CA755E2E1B59F5002EFB40; + remoteInfo = BranchSDKTestsHostApp; }; - 5F73EBF828ECE65400608601 /* PBXContainerItemProxy */ = { + E7CA75BE2E1B9957002EFB40 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5F2210142894A0DB00C5B190 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5F73EBF328ECE65400608601; - remoteInfo = "BranchSDK-static"; + remoteGlobalIDString = 5F22101C2894A0DB00C5B190; + remoteInfo = BranchSDK; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 5F73EBFF28ECE65400608601 /* Embed Frameworks */ = { + E7CA75C02E1B9957002EFB40 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - 5F73EBFB28ECE65400608601 /* BranchSDK.framework in Embed Frameworks */, + E7CA75BD2E1B9957002EFB40 /* BranchSDK.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -552,24 +550,8 @@ /* Begin PBXFileReference section */ 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BranchSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5F22116F2894A9C000C5B190 /* TestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 5F2211712894A9C000C5B190 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 5F2211732894A9C000C5B190 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 5F2211752894A9C000C5B190 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 5F2211782894A9C000C5B190 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 5F22117A2894A9C100C5B190 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 5F22117D2894A9C100C5B190 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 5F22117F2894A9C100C5B190 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5F2211842894A9C100C5B190 /* TestHostTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestHostTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 5F2211882894A9C100C5B190 /* TestHostTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHostTests.swift; sourceTree = ""; }; - 5F22118E2894A9C100C5B190 /* TestHostUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestHostUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 5F2211922894A9C100C5B190 /* TestHostUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHostUITests.swift; sourceTree = ""; }; - 5F2211942894A9C100C5B190 /* TestHostUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHostUITestsLaunchTests.swift; sourceTree = ""; }; 5F5FDA152B7DE2FE00F14A43 /* BranchLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchLogger.m; sourceTree = ""; }; 5F5FDA192B7DE31E00F14A43 /* BranchLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchLogger.h; sourceTree = ""; }; - 5F6DD2492894AF5E00AE9FB0 /* TestHost-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TestHost-Bridging-Header.h"; sourceTree = ""; }; - 5F6DD24A2894AF5E00AE9FB0 /* NSURLSession+Branch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURLSession+Branch.m"; sourceTree = ""; }; - 5F6DD24B2894AF5E00AE9FB0 /* NSURLSession+Branch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURLSession+Branch.h"; sourceTree = ""; }; 5F73EBF428ECE65400608601 /* BranchSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BranchSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 5F73EC0028EDEAC200608601 /* build_static_xcframework_noidfa.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_static_xcframework_noidfa.sh; sourceTree = ""; }; 5F73EC0128EDEAC200608601 /* build_static_xcframework.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_static_xcframework.sh; sourceTree = ""; }; @@ -599,7 +581,7 @@ 5FCDD3812B7AC6A100EAF29F /* BNCNetworkInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BNCNetworkInterface.m; sourceTree = ""; }; 5FCDD3822B7AC6A100EAF29F /* BNCPreferenceHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BNCPreferenceHelper.m; sourceTree = ""; }; 5FCDD3832B7AC6A100EAF29F /* BNCConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BNCConfig.m; sourceTree = ""; }; - 5FCDD3842B7AC6A100EAF29F /* BranchConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchConstants.m; sourceTree = ""; }; + 5FCDD3842B7AC6A100EAF29F /* BranchConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BranchConstants.m; path = ../BranchSDK_ObjC/BranchConstants.m; sourceTree = ""; }; 5FCDD3852B7AC6A100EAF29F /* BranchContentDiscoveryManifest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchContentDiscoveryManifest.m; sourceTree = ""; }; 5FCDD3862B7AC6A100EAF29F /* BranchSpotlightUrlRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchSpotlightUrlRequest.m; sourceTree = ""; }; 5FCDD3882B7AC6A100EAF29F /* BranchContentDiscoverer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchContentDiscoverer.m; sourceTree = ""; }; @@ -681,7 +663,6 @@ 5FCDD3D92B7AC6A100EAF29F /* BranchSpotlightUrlRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchSpotlightUrlRequest.h; sourceTree = ""; }; 5FCDD3DA2B7AC6A100EAF29F /* BranchContentDiscoveryManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchContentDiscoveryManifest.h; sourceTree = ""; }; 5FCDD3DB2B7AC6A100EAF29F /* BNCConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BNCConfig.h; sourceTree = ""; }; - 5FCDD3DC2B7AC6A100EAF29F /* BranchConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchConstants.h; sourceTree = ""; }; 5FCDD3DD2B7AC6A100EAF29F /* BNCPartnerParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BNCPartnerParameters.h; sourceTree = ""; }; 5FCDD3DE2B7AC6A100EAF29F /* BranchJsonConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchJsonConfig.h; sourceTree = ""; }; 5FCDD3DF2B7AC6A100EAF29F /* BranchLATDRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchLATDRequest.h; sourceTree = ""; }; @@ -719,58 +700,111 @@ 5FF2AFDC28E7BF8A00393216 /* build_xcframework.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_xcframework.sh; sourceTree = ""; }; 5FF2AFDE28E7C22100393216 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; 5FF2AFDF28E7C22100393216 /* BranchSDK.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchSDK.h; sourceTree = ""; }; + B70D0E152E8DB20A002BD4FE /* jira_task.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = jira_task.xml; sourceTree = ""; }; + B70D0E242E8DC1F8002BD4FE /* BranchConfigurationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchConfigurationController.m; sourceTree = ""; }; E52E5B052CC79E4E00F553EE /* BranchFileLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchFileLogger.h; sourceTree = ""; }; E52E5B092CC79E5C00F553EE /* BranchFileLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchFileLogger.m; sourceTree = ""; }; E71E396D2DD3A92900110F59 /* BNCInAppBrowser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCInAppBrowser.h; sourceTree = ""; }; E71E396E2DD3A92900110F59 /* BNCInAppBrowser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCInAppBrowser.m; sourceTree = ""; }; - E73D027F2DEE8AE90076C3F1 /* BranchConfigurationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BranchConfigurationController.h; sourceTree = ""; }; - E73D02802DEE8AE90076C3F1 /* BranchConfigurationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BranchConfigurationController.m; sourceTree = ""; }; + E74E43852E2F55E5000DC427 /* BNCServerRequestOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCServerRequestOperation.h; sourceTree = ""; }; + E74E438D2E2F56AC000DC427 /* BNCServerRequestOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCServerRequestOperation.m; sourceTree = ""; }; + E7CA74EB2E1B4F75002EFB40 /* BranchSDKTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BranchSDKTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + E7CA755F2E1B59F5002EFB40 /* BranchSDKTestsHostApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BranchSDKTestsHostApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E7CA75B82E1B994B002EFB40 /* AdServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdServices.framework; path = System/Library/Frameworks/AdServices.framework; sourceTree = SDKROOT; }; + E7CA75BA2E1B9951002EFB40 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; E7F311AD2DACB4D400F824A7 /* BNCODMInfoCollector.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCODMInfoCollector.m; sourceTree = ""; }; E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BNCODMInfoCollector.h; sourceTree = ""; }; + E7FAF69F2E26E497006C167F /* BranchConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BranchConstants.h; path = Sources/BranchSDK_ObjC/Public/BranchConstants.h; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ -/* Begin PBXFrameworksBuildPhase section */ - 5F22101A2894A0DB00C5B190 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + E7CA75552E1B504C002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, ); - runOnlyForDeploymentPostprocessing = 0; + target = E7CA74EA2E1B4F75002EFB40 /* BranchSDKTests */; }; - 5F22116C2894A9C000C5B190 /* Frameworks */ = { + E7CA758B2E1B59F7002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */; + }; + E7CA75B12E1B7B02002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + cannedData/example.json, + cannedData/latd_empty_data.json, + cannedData/latd_missing_data.json, + cannedData/latd_missing_window.json, + cannedData/latd.json, + ); + target = E7CA74EA2E1B4F75002EFB40 /* BranchSDKTests */; + }; + E7F2461F2E26B8F90083FDE1 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + BranchSDKTests.xctestplan, + ); + target = E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ + E7CA75562E1B504C002EFB40 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */ = { + isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet; + buildPhase = E7CA74E72E1B4F75002EFB40 /* Sources */; + membershipExceptions = ( + BNCJsonLoader.h, + "Branch-SDK-Tests-Bridging-Header.h", + ); + }; +/* End PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + E7CA74EC2E1B4F75002EFB40 /* BranchSDKTests */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (E7CA75552E1B504C002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, E7CA75562E1B504C002EFB40 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */, E7F2461F2E26B8F90083FDE1 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = BranchSDKTests; sourceTree = ""; }; + E7CA75602E1B59F5002EFB40 /* BranchSDKTestsHostApp */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (E7CA75B12E1B7B02002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, E7CA758B2E1B59F7002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = BranchSDKTestsHostApp; sourceTree = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5F22101A2894A0DB00C5B190 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5F6DD2482894AEBD00AE9FB0 /* BranchSDK.framework in Frameworks */, - 5F73EBFA28ECE65400608601 /* BranchSDK.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F2211812894A9C100C5B190 /* Frameworks */ = { + 5F73EBF128ECE65400608601 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 5F22118B2894A9C100C5B190 /* Frameworks */ = { + 5F79038928B5765D003144CD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 5F73EBF128ECE65400608601 /* Frameworks */ = { + E7CA74E82E1B4F75002EFB40 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E7CA74EF2E1B4F75002EFB40 /* BranchSDK.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F79038928B5765D003144CD /* Frameworks */ = { + E7CA755C2E1B59F5002EFB40 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E7CA75BC2E1B9957002EFB40 /* BranchSDK.framework in Frameworks */, + E7CA75B92E1B994B002EFB40 /* AdServices.framework in Frameworks */, + E7CA75BB2E1B9951002EFB40 /* AdSupport.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -781,12 +815,13 @@ isa = PBXGroup; children = ( 5FCDD36B2B7AC6A100EAF29F /* BranchSDK */, - 5F2211702894A9C000C5B190 /* TestHost */, - 5F2211872894A9C100C5B190 /* TestHostTests */, - 5F2211912894A9C100C5B190 /* TestHostUITests */, 5FF2AFDD28E7C1F200393216 /* Framework */, 5FF2AFDB28E7BF5500393216 /* Scripts */, + E7CA74EC2E1B4F75002EFB40 /* BranchSDKTests */, + E7CA75602E1B59F5002EFB40 /* BranchSDKTestsHostApp */, + E7CA75B72E1B994B002EFB40 /* Frameworks */, 5F22101E2894A0DB00C5B190 /* Products */, + B70D0E152E8DB20A002BD4FE /* jira_task.xml */, ); sourceTree = ""; }; @@ -794,52 +829,19 @@ isa = PBXGroup; children = ( 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */, - 5F22116F2894A9C000C5B190 /* TestHost.app */, - 5F2211842894A9C100C5B190 /* TestHostTests.xctest */, - 5F22118E2894A9C100C5B190 /* TestHostUITests.xctest */, 5F79038C28B5765D003144CD /* BranchSDK.framework */, 5F73EBF428ECE65400608601 /* BranchSDK.framework */, + E7CA74EB2E1B4F75002EFB40 /* BranchSDKTests.xctest */, + E7CA755F2E1B59F5002EFB40 /* BranchSDKTestsHostApp.app */, ); name = Products; sourceTree = ""; }; - 5F2211702894A9C000C5B190 /* TestHost */ = { - isa = PBXGroup; - children = ( - 5F2211712894A9C000C5B190 /* AppDelegate.swift */, - 5F2211732894A9C000C5B190 /* SceneDelegate.swift */, - 5F2211752894A9C000C5B190 /* ViewController.swift */, - 5F6DD24B2894AF5E00AE9FB0 /* NSURLSession+Branch.h */, - 5F6DD24A2894AF5E00AE9FB0 /* NSURLSession+Branch.m */, - 5F2211772894A9C000C5B190 /* Main.storyboard */, - 5F22117A2894A9C100C5B190 /* Assets.xcassets */, - 5F22117C2894A9C100C5B190 /* LaunchScreen.storyboard */, - 5F22117F2894A9C100C5B190 /* Info.plist */, - 5F6DD2492894AF5E00AE9FB0 /* TestHost-Bridging-Header.h */, - ); - path = TestHost; - sourceTree = ""; - }; - 5F2211872894A9C100C5B190 /* TestHostTests */ = { - isa = PBXGroup; - children = ( - 5F2211882894A9C100C5B190 /* TestHostTests.swift */, - ); - path = TestHostTests; - sourceTree = ""; - }; - 5F2211912894A9C100C5B190 /* TestHostUITests */ = { - isa = PBXGroup; - children = ( - 5F2211922894A9C100C5B190 /* TestHostUITests.swift */, - 5F2211942894A9C100C5B190 /* TestHostUITestsLaunchTests.swift */, - ); - path = TestHostUITests; - sourceTree = ""; - }; 5FCDD36B2B7AC6A100EAF29F /* BranchSDK */ = { isa = PBXGroup; children = ( + B70D0E242E8DC1F8002BD4FE /* BranchConfigurationController.m */, + E74E438D2E2F56AC000DC427 /* BNCServerRequestOperation.m */, E71E396E2DD3A92900110F59 /* BNCInAppBrowser.m */, E52E5B092CC79E5C00F553EE /* BranchFileLogger.m */, 5FCDD3F62B7AC6A100EAF29F /* BNCAppGroupsData.m */, @@ -912,7 +914,6 @@ 5FCDD3732B7AC6A100EAF29F /* NSMutableDictionary+Branch.m */, 5FCDD37C2B7AC6A100EAF29F /* NSString+Branch.m */, 5FCDD3F52B7AC6A100EAF29F /* UIViewController+Branch.m */, - E73D02802DEE8AE90076C3F1 /* BranchConfigurationController.m */, 5FCDD3B42B7AC6A100EAF29F /* Private */, 5FCDD3982B7AC6A100EAF29F /* Public */, ); @@ -923,6 +924,7 @@ 5FCDD3982B7AC6A100EAF29F /* Public */ = { isa = PBXGroup; children = ( + E7FAF69F2E26E497006C167F /* BranchConstants.h */, 5FCDD3A42B7AC6A100EAF29F /* BNCCallbacks.h */, 5FCDD3A02B7AC6A100EAF29F /* BNCCurrency.h */, 5FCDD3A72B7AC6A100EAF29F /* BNCInitSessionResponse.h */, @@ -958,6 +960,7 @@ 5FCDD3B42B7AC6A100EAF29F /* Private */ = { isa = PBXGroup; children = ( + E74E43852E2F55E5000DC427 /* BNCServerRequestOperation.h */, 5FCDD3BC2B7AC6A100EAF29F /* BNCAppGroupsData.h */, 5FCDD3B62B7AC6A100EAF29F /* BNCAppleReceipt.h */, 5FCDD3C72B7AC6A100EAF29F /* BNCApplication.h */, @@ -989,7 +992,6 @@ 5FCDD3CA2B7AC6A100EAF29F /* BNCUserAgentCollector.h */, E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */, 5FCDD3D32B7AC6A100EAF29F /* Branch+Validator.h */, - 5FCDD3DC2B7AC6A100EAF29F /* BranchConstants.h */, 5FCDD3D82B7AC6A100EAF29F /* BranchContentDiscoverer.h */, 5FCDD3DA2B7AC6A100EAF29F /* BranchContentDiscoveryManifest.h */, 5FCDD3B82B7AC6A100EAF29F /* BranchContentPathProperties.h */, @@ -1006,7 +1008,6 @@ E52E5B052CC79E4E00F553EE /* BranchFileLogger.h */, 5FCDD3BB2B7AC6A100EAF29F /* UIViewController+Branch.h */, E71E396D2DD3A92900110F59 /* BNCInAppBrowser.h */, - E73D027F2DEE8AE90076C3F1 /* BranchConfigurationController.h */, ); path = Private; sourceTree = ""; @@ -1032,6 +1033,15 @@ path = Framework; sourceTree = ""; }; + E7CA75B72E1B994B002EFB40 /* Frameworks */ = { + isa = PBXGroup; + children = ( + E7CA75BA2E1B9951002EFB40 /* AdSupport.framework */, + E7CA75B82E1B994B002EFB40 /* AdServices.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1039,6 +1049,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + E7FAF6A02E26E497006C167F /* BranchConstants.h in Headers */, 5FCDD52E2B7AC6A300EAF29F /* Branch+Validator.h in Headers */, 5FCDD4A42B7AC6A200EAF29F /* BNCCallbacks.h in Headers */, 5FCDD4922B7AC6A100EAF29F /* BranchLinkProperties.h in Headers */, @@ -1062,6 +1073,7 @@ 5FCDD48C2B7AC6A100EAF29F /* BranchActivityItemProvider.h in Headers */, 5FCDD4832B7AC6A100EAF29F /* BNCLinkData.h in Headers */, 5FCDD4B02B7AC6A200EAF29F /* BranchEvent.h in Headers */, + E74E43882E2F55E5000DC427 /* BNCServerRequestOperation.h in Headers */, 5FCDD4B32B7AC6A200EAF29F /* BNCNetworkServiceProtocol.h in Headers */, 5FCDD4A12B7AC6A200EAF29F /* BNCServerResponse.h in Headers */, 5FCDD4C22B7AC6A200EAF29F /* BranchDeepLinkingController.h in Headers */, @@ -1071,7 +1083,6 @@ 5FCDD5462B7AC6A300EAF29F /* BNCConfig.h in Headers */, 5FCDD4E62B7AC6A200EAF29F /* UIViewController+Branch.h in Headers */, 5F5FDA1A2B7DE31E00F14A43 /* BranchLogger.h in Headers */, - 5FCDD5492B7AC6A300EAF29F /* BranchConstants.h in Headers */, E7F311B22DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */, 5FCDD5402B7AC6A300EAF29F /* BranchSpotlightUrlRequest.h in Headers */, 5FCDD5552B7AC6A300EAF29F /* BNCCrashlyticsWrapper.h in Headers */, @@ -1113,7 +1124,6 @@ 5FCDD54F2B7AC6A300EAF29F /* BranchJsonConfig.h in Headers */, 5FCDD4E02B7AC6A200EAF29F /* BNCSKAdNetwork.h in Headers */, 5FCDD5102B7AC6A300EAF29F /* BNCDeviceSystem.h in Headers */, - E73D02832DEE8AE90076C3F1 /* BranchConfigurationController.h in Headers */, 5FCDD51F2B7AC6A300EAF29F /* BNCNetworkInterface.h in Headers */, 5FA71BA82B7AE6B2008009CA /* Branch.h in Headers */, ); @@ -1123,6 +1133,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + E7FAF6A22E26E497006C167F /* BranchConstants.h in Headers */, 5FCDD52F2B7AC6A300EAF29F /* Branch+Validator.h in Headers */, 5FCDD4A52B7AC6A200EAF29F /* BNCCallbacks.h in Headers */, 5FCDD4932B7AC6A100EAF29F /* BranchLinkProperties.h in Headers */, @@ -1130,6 +1141,7 @@ 5FCDD4A82B7AC6A200EAF29F /* BranchShareLink.h in Headers */, 5FCDD4B72B7AC6A200EAF29F /* BNCServerRequestQueue.h in Headers */, 5FCDD4992B7AC6A100EAF29F /* BNCCurrency.h in Headers */, + E74E438E2E2F56AC000DC427 /* BNCServerRequestOperation.m in Headers */, 5FCDD4C62B7AC6A200EAF29F /* BranchPluginSupport.h in Headers */, 5FCDD4BD2B7AC6A200EAF29F /* BranchUniversalObject.h in Headers */, 5FCDD4D22B7AC6A200EAF29F /* BNCProductCategory.h in Headers */, @@ -1146,6 +1158,7 @@ 5FCDD48D2B7AC6A100EAF29F /* BranchActivityItemProvider.h in Headers */, 5FCDD4842B7AC6A100EAF29F /* BNCLinkData.h in Headers */, 5FCDD4B12B7AC6A200EAF29F /* BranchEvent.h in Headers */, + E74E43872E2F55E5000DC427 /* BNCServerRequestOperation.h in Headers */, 5FCDD4B42B7AC6A200EAF29F /* BNCNetworkServiceProtocol.h in Headers */, 5FCDD4A22B7AC6A200EAF29F /* BNCServerResponse.h in Headers */, 5FCDD4C32B7AC6A200EAF29F /* BranchDeepLinkingController.h in Headers */, @@ -1157,7 +1170,6 @@ 5F5FDA1B2B7DE31E00F14A43 /* BranchLogger.h in Headers */, 5FCDD4E72B7AC6A200EAF29F /* UIViewController+Branch.h in Headers */, E7F311B12DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */, - 5FCDD54A2B7AC6A300EAF29F /* BranchConstants.h in Headers */, 5FCDD5412B7AC6A300EAF29F /* BranchSpotlightUrlRequest.h in Headers */, 5FCDD5562B7AC6A300EAF29F /* BNCCrashlyticsWrapper.h in Headers */, 5FCDD52C2B7AC6A300EAF29F /* BranchInstallRequest.h in Headers */, @@ -1197,7 +1209,6 @@ 5FCDD4D82B7AC6A200EAF29F /* BNCAppleReceipt.h in Headers */, 5FCDD5502B7AC6A300EAF29F /* BranchJsonConfig.h in Headers */, 5FCDD4E12B7AC6A200EAF29F /* BNCSKAdNetwork.h in Headers */, - E73D02822DEE8AE90076C3F1 /* BranchConfigurationController.h in Headers */, 5FCDD5112B7AC6A300EAF29F /* BNCDeviceSystem.h in Headers */, 5FCDD5202B7AC6A300EAF29F /* BNCNetworkInterface.h in Headers */, ); @@ -1207,6 +1218,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + E7FAF6A12E26E497006C167F /* BranchConstants.h in Headers */, 5FCDD4BB2B7AC6A200EAF29F /* BranchPasteControl.h in Headers */, 5FCDD5302B7AC6A300EAF29F /* Branch+Validator.h in Headers */, 5FCDD4A62B7AC6A200EAF29F /* BNCCallbacks.h in Headers */, @@ -1214,6 +1226,7 @@ 5FCDD4CA2B7AC6A200EAF29F /* BranchScene.h in Headers */, 5FCDD4A92B7AC6A200EAF29F /* BranchShareLink.h in Headers */, 5FCDD4B82B7AC6A200EAF29F /* BNCServerRequestQueue.h in Headers */, + E74E438F2E2F56AC000DC427 /* BNCServerRequestOperation.m in Headers */, 5FCDD49A2B7AC6A100EAF29F /* BNCCurrency.h in Headers */, 5FCDD4C72B7AC6A200EAF29F /* BranchPluginSupport.h in Headers */, 5FCDD4BE2B7AC6A200EAF29F /* BranchUniversalObject.h in Headers */, @@ -1230,6 +1243,7 @@ 5FCDD48E2B7AC6A100EAF29F /* BranchActivityItemProvider.h in Headers */, 5FCDD4852B7AC6A100EAF29F /* BNCLinkData.h in Headers */, 5FCDD4B22B7AC6A200EAF29F /* BranchEvent.h in Headers */, + E74E43862E2F55E5000DC427 /* BNCServerRequestOperation.h in Headers */, 5FCDD4B52B7AC6A200EAF29F /* BNCNetworkServiceProtocol.h in Headers */, 5FCDD4A32B7AC6A200EAF29F /* BNCServerResponse.h in Headers */, 5FCDD4C42B7AC6A200EAF29F /* BranchDeepLinkingController.h in Headers */, @@ -1238,7 +1252,6 @@ 5FCDD5482B7AC6A300EAF29F /* BNCConfig.h in Headers */, E563942E2CC7A8E600E18E65 /* BranchFileLogger.h in Headers */, 5FCDD4E82B7AC6A200EAF29F /* UIViewController+Branch.h in Headers */, - 5FCDD54B2B7AC6A300EAF29F /* BranchConstants.h in Headers */, 5F5FDA1C2B7DE31E00F14A43 /* BranchLogger.h in Headers */, E7F311B32DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */, 5FCDD5422B7AC6A300EAF29F /* BranchSpotlightUrlRequest.h in Headers */, @@ -1281,7 +1294,6 @@ 5FCDD4D92B7AC6A200EAF29F /* BNCAppleReceipt.h in Headers */, 5FCDD5512B7AC6A300EAF29F /* BranchJsonConfig.h in Headers */, 5FCDD4E22B7AC6A200EAF29F /* BNCSKAdNetwork.h in Headers */, - E73D02862DEE8AE90076C3F1 /* BranchConfigurationController.h in Headers */, 5FCDD5122B7AC6A300EAF29F /* BNCDeviceSystem.h in Headers */, 5FCDD5212B7AC6A300EAF29F /* BNCNetworkInterface.h in Headers */, ); @@ -1308,61 +1320,6 @@ productReference = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; productType = "com.apple.product-type.framework"; }; - 5F22116E2894A9C000C5B190 /* TestHost */ = { - isa = PBXNativeTarget; - buildConfigurationList = 5F2211962894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHost" */; - buildPhases = ( - 5F22116B2894A9C000C5B190 /* Sources */, - 5F22116C2894A9C000C5B190 /* Frameworks */, - 5F22116D2894A9C000C5B190 /* Resources */, - 5F73EBFF28ECE65400608601 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 5F73EBF928ECE65400608601 /* PBXTargetDependency */, - ); - name = TestHost; - productName = TestHost; - productReference = 5F22116F2894A9C000C5B190 /* TestHost.app */; - productType = "com.apple.product-type.application"; - }; - 5F2211832894A9C100C5B190 /* TestHostTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 5F2211992894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHostTests" */; - buildPhases = ( - 5F2211802894A9C100C5B190 /* Sources */, - 5F2211812894A9C100C5B190 /* Frameworks */, - 5F2211822894A9C100C5B190 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 5F2211862894A9C100C5B190 /* PBXTargetDependency */, - ); - name = TestHostTests; - productName = TestHostTests; - productReference = 5F2211842894A9C100C5B190 /* TestHostTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 5F22118D2894A9C100C5B190 /* TestHostUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 5F22119C2894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHostUITests" */; - buildPhases = ( - 5F22118A2894A9C100C5B190 /* Sources */, - 5F22118B2894A9C100C5B190 /* Frameworks */, - 5F22118C2894A9C100C5B190 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 5F2211902894A9C100C5B190 /* PBXTargetDependency */, - ); - name = TestHostUITests; - productName = TestHostUITests; - productReference = 5F22118E2894A9C100C5B190 /* TestHostUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; 5F73EBF328ECE65400608601 /* BranchSDK-static */ = { isa = PBXNativeTarget; buildConfigurationList = 5F73EBFC28ECE65400608601 /* Build configuration list for PBXNativeTarget "BranchSDK-static" */; @@ -1399,6 +1356,54 @@ productReference = 5F79038C28B5765D003144CD /* BranchSDK.framework */; productType = "com.apple.product-type.framework"; }; + E7CA74EA2E1B4F75002EFB40 /* BranchSDKTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7CA74F42E1B4F75002EFB40 /* Build configuration list for PBXNativeTarget "BranchSDKTests" */; + buildPhases = ( + E7CA74E72E1B4F75002EFB40 /* Sources */, + E7CA74E82E1B4F75002EFB40 /* Frameworks */, + E7CA74E92E1B4F75002EFB40 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + E7CA755A2E1B52F4002EFB40 /* PBXTargetDependency */, + E7CA75A72E1B79CD002EFB40 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + E7CA74EC2E1B4F75002EFB40 /* BranchSDKTests */, + ); + name = BranchSDKTests; + packageProductDependencies = ( + ); + productName = BranchSDKTests; + productReference = E7CA74EB2E1B4F75002EFB40 /* BranchSDKTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7CA758C2E1B59F7002EFB40 /* Build configuration list for PBXNativeTarget "BranchSDKTestsHostApp" */; + buildPhases = ( + E7CA755B2E1B59F5002EFB40 /* Sources */, + E7CA755C2E1B59F5002EFB40 /* Frameworks */, + E7CA755D2E1B59F5002EFB40 /* Resources */, + E7CA75C02E1B9957002EFB40 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + E7CA75BF2E1B9957002EFB40 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + E7CA75602E1B59F5002EFB40 /* BranchSDKTestsHostApp */, + ); + name = BranchSDKTestsHostApp; + packageProductDependencies = ( + ); + productName = BranchSDKTestsHostApp; + productReference = E7CA755F2E1B59F5002EFB40 /* BranchSDKTestsHostApp.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -1411,27 +1416,18 @@ TargetAttributes = { 5F22101C2894A0DB00C5B190 = { CreatedOnToolsVersion = 13.4.1; + LastSwiftMigration = 1640; }; 5F2211672894A90500C5B190 = { CreatedOnToolsVersion = 13.4.1; }; - 5F22116E2894A9C000C5B190 = { - CreatedOnToolsVersion = 13.4.1; - LastSwiftMigration = 1340; - }; - 5F2211832894A9C100C5B190 = { - CreatedOnToolsVersion = 13.4.1; - TestTargetID = 5F22116E2894A9C000C5B190; - }; - 5F22118D2894A9C100C5B190 = { - CreatedOnToolsVersion = 13.4.1; - TestTargetID = 5F22116E2894A9C000C5B190; - }; 5F73EBF328ECE65400608601 = { CreatedOnToolsVersion = 14.0; + LastSwiftMigration = 1640; }; 5F79038B28B5765D003144CD = { CreatedOnToolsVersion = 13.4.1; + LastSwiftMigration = 1640; }; 5FF9DEEC28EE7C0D00D62DE1 = { CreatedOnToolsVersion = 14.0; @@ -1442,10 +1438,16 @@ 5FF9DEF428EE7C3600D62DE1 = { CreatedOnToolsVersion = 14.0; }; + E7CA74EA2E1B4F75002EFB40 = { + CreatedOnToolsVersion = 16.4; + TestTargetID = E7CA755E2E1B59F5002EFB40; + }; + E7CA755E2E1B59F5002EFB40 = { + CreatedOnToolsVersion = 16.4; + }; }; }; buildConfigurationList = 5F2210172894A0DB00C5B190 /* Build configuration list for PBXProject "BranchSDK" */; - compatibilityVersion = "Xcode 13.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -1453,6 +1455,7 @@ Base, ); mainGroup = 5F2210132894A0DB00C5B190; + preferredProjectObjectVersion = 55; productRefGroup = 5F22101E2894A0DB00C5B190 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -1460,13 +1463,12 @@ 5F22101C2894A0DB00C5B190 /* BranchSDK */, 5F73EBF328ECE65400608601 /* BranchSDK-static */, 5F79038B28B5765D003144CD /* BranchSDK-tvOS */, - 5F22116E2894A9C000C5B190 /* TestHost */, - 5F2211832894A9C100C5B190 /* TestHostTests */, - 5F22118D2894A9C100C5B190 /* TestHostUITests */, 5F2211672894A90500C5B190 /* xcframework */, 5FF9DEEC28EE7C0D00D62DE1 /* xcframework-noidfa */, 5FF9DEF428EE7C3600D62DE1 /* static-xcframework */, 5FF9DEF028EE7C2200D62DE1 /* static-xcframework-noidfa */, + E7CA74EA2E1B4F75002EFB40 /* BranchSDKTests */, + E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */, ); }; /* End PBXProject section */ @@ -1480,43 +1482,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5F22116D2894A9C000C5B190 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5F22117E2894A9C100C5B190 /* LaunchScreen.storyboard in Resources */, - 5F22117B2894A9C100C5B190 /* Assets.xcassets in Resources */, - 5F2211792894A9C000C5B190 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5F2211822894A9C100C5B190 /* Resources */ = { + 5F73EBF228ECE65400608601 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5FC446662ACCB97100FF1C87 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F22118C2894A9C100C5B190 /* Resources */ = { + 5F79038A28B5765D003144CD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5FC446672ACCB97200FF1C87 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F73EBF228ECE65400608601 /* Resources */ = { + E7CA74E92E1B4F75002EFB40 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5FC446662ACCB97100FF1C87 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F79038A28B5765D003144CD /* Resources */ = { + E7CA755D2E1B59F5002EFB40 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5FC446672ACCB97200FF1C87 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1602,6 +1594,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E74E43902E2F56AC000DC427 /* BNCServerRequestOperation.m in Sources */, 5FCDD5AC2B7AC6A400EAF29F /* BNCCallbackMap.m in Sources */, 5FCDD40E2B7AC6A100EAF29F /* BNCApplication.m in Sources */, 5FCDD5642B7AC6A300EAF29F /* BranchDelegate.m in Sources */, @@ -1613,6 +1606,7 @@ 5FCDD46E2B7AC6A100EAF29F /* BranchJsonConfig.m in Sources */, 5FCDD4742B7AC6A100EAF29F /* BNCPartnerParameters.m in Sources */, 5FCDD4712B7AC6A100EAF29F /* BranchLATDRequest.m in Sources */, + B70D0E272E8DC1F8002BD4FE /* BranchConfigurationController.m in Sources */, 5FCDD57C2B7AC6A400EAF29F /* BNCPasteboard.m in Sources */, 5FCDD47A2B7AC6A100EAF29F /* BranchActivityItemProvider.m in Sources */, E7F311AE2DACB4D400F824A7 /* BNCODMInfoCollector.m in Sources */, @@ -1640,7 +1634,6 @@ 5FCDD42C2B7AC6A100EAF29F /* BranchPluginSupport.m in Sources */, 5FCDD5A62B7AC6A400EAF29F /* BNCQRCodeCache.m in Sources */, 5FCDD45C2B7AC6A100EAF29F /* BNCReachability.m in Sources */, - E73D02842DEE8AE90076C3F1 /* BranchConfigurationController.m in Sources */, 5FCDD42F2B7AC6A100EAF29F /* NSString+Branch.m in Sources */, 5FCDD5A02B7AC6A400EAF29F /* BranchShortUrlRequest.m in Sources */, 5FCDD46B2B7AC6A100EAF29F /* BNCServerInterface.m in Sources */, @@ -1678,38 +1671,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5F22116B2894A9C000C5B190 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5F2211762894A9C000C5B190 /* ViewController.swift in Sources */, - 5F6DD24C2894AF5E00AE9FB0 /* NSURLSession+Branch.m in Sources */, - 5F2211722894A9C000C5B190 /* AppDelegate.swift in Sources */, - 5F2211742894A9C000C5B190 /* SceneDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5F2211802894A9C100C5B190 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5F2211892894A9C100C5B190 /* TestHostTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5F22118A2894A9C100C5B190 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5F2211952894A9C100C5B190 /* TestHostUITestsLaunchTests.swift in Sources */, - 5F2211932894A9C100C5B190 /* TestHostUITests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 5F73EBF028ECE65400608601 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B70D0E252E8DC1F8002BD4FE /* BranchConfigurationController.m in Sources */, 5FCDD5AD2B7AC6A400EAF29F /* BNCCallbackMap.m in Sources */, 5FCDD40F2B7AC6A100EAF29F /* BNCApplication.m in Sources */, 5FCDD5652B7AC6A300EAF29F /* BranchDelegate.m in Sources */, @@ -1748,7 +1714,6 @@ 5FCDD42D2B7AC6A100EAF29F /* BranchPluginSupport.m in Sources */, 5FCDD5A72B7AC6A400EAF29F /* BNCQRCodeCache.m in Sources */, 5FCDD45D2B7AC6A100EAF29F /* BNCReachability.m in Sources */, - E73D02812DEE8AE90076C3F1 /* BranchConfigurationController.m in Sources */, 5FCDD4302B7AC6A100EAF29F /* NSString+Branch.m in Sources */, 5FCDD5A12B7AC6A400EAF29F /* BranchShortUrlRequest.m in Sources */, 5FCDD46C2B7AC6A100EAF29F /* BNCServerInterface.m in Sources */, @@ -1802,6 +1767,7 @@ 5FCDD57E2B7AC6A400EAF29F /* BNCPasteboard.m in Sources */, 5F5FDA182B7DE2FE00F14A43 /* BranchLogger.m in Sources */, 5FCDD4612B7AC6A100EAF29F /* BNCRequestFactory.m in Sources */, + B70D0E262E8DC1F8002BD4FE /* BranchConfigurationController.m in Sources */, 5FCDD41F2B7AC6A100EAF29F /* BNCDeepLinkViewControllerInstance.m in Sources */, 5FCDD58A2B7AC6A400EAF29F /* BNCLinkCache.m in Sources */, 5FCDD56F2B7AC6A400EAF29F /* BNCJSONUtility.m in Sources */, @@ -1844,7 +1810,6 @@ 5FCDD44C2B7AC6A100EAF29F /* BranchContentDiscoveryManifest.m in Sources */, 5FCDD46A2B7AC6A100EAF29F /* BNCCrashlyticsWrapper.m in Sources */, 5FCDD43D2B7AC6A100EAF29F /* BNCServerRequest.m in Sources */, - E73D02852DEE8AE90076C3F1 /* BranchConfigurationController.m in Sources */, 5FCDD5842B7AC6A400EAF29F /* BranchLinkProperties.m in Sources */, 5FCDD59F2B7AC6A400EAF29F /* BranchEvent.m in Sources */, 5FCDD5812B7AC6A400EAF29F /* BNCAppleReceipt.m in Sources */, @@ -1856,45 +1821,43 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + E7CA74E72E1B4F75002EFB40 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B70D0E162E8DB20C002BD4FE /* jira_task.xml in Sources */, + B70D0E2C2E8DCEC6002BD4FE /* BNCServerRequestOperation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7CA755B2E1B59F5002EFB40 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B70D0E2D2E8DCEC6002BD4FE /* BNCServerRequestOperation.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 5F2211862894A9C100C5B190 /* PBXTargetDependency */ = { + E7CA755A2E1B52F4002EFB40 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 5F22116E2894A9C000C5B190 /* TestHost */; - targetProxy = 5F2211852894A9C100C5B190 /* PBXContainerItemProxy */; + target = 5F22101C2894A0DB00C5B190 /* BranchSDK */; + targetProxy = E7CA75592E1B52F4002EFB40 /* PBXContainerItemProxy */; }; - 5F2211902894A9C100C5B190 /* PBXTargetDependency */ = { + E7CA75A72E1B79CD002EFB40 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 5F22116E2894A9C000C5B190 /* TestHost */; - targetProxy = 5F22118F2894A9C100C5B190 /* PBXContainerItemProxy */; + target = E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */; + targetProxy = E7CA75A62E1B79CD002EFB40 /* PBXContainerItemProxy */; }; - 5F73EBF928ECE65400608601 /* PBXTargetDependency */ = { + E7CA75BF2E1B9957002EFB40 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 5F73EBF328ECE65400608601 /* BranchSDK-static */; - targetProxy = 5F73EBF828ECE65400608601 /* PBXContainerItemProxy */; + target = 5F22101C2894A0DB00C5B190 /* BranchSDK */; + targetProxy = E7CA75BE2E1B9957002EFB40 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ -/* Begin PBXVariantGroup section */ - 5F2211772894A9C000C5B190 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 5F2211782894A9C000C5B190 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 5F22117C2894A9C100C5B190 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 5F22117D2894A9C100C5B190 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ 5F2210222894A0DB00C5B190 /* Debug */ = { isa = XCBuildConfiguration; @@ -2016,6 +1979,8 @@ isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(MARKETING_VERSION)"; DEFINES_MODULE = YES; @@ -2043,6 +2008,9 @@ "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -2051,6 +2019,8 @@ isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(MARKETING_VERSION)"; DEFINES_MODULE = YES; @@ -2078,6 +2048,8 @@ "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -2102,160 +2074,12 @@ }; name = Release; }; - 5F2211972894A9C100C5B190 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = TestHost/Info.plist; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 15.5; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHost; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "TestHost/TestHost-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 5F2211982894A9C100C5B190 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = TestHost/Info.plist; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 15.5; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHost; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "TestHost/TestHost-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 5F22119A2894A9C100C5B190 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.5; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHostTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestHost.app/TestHost"; - }; - name = Debug; - }; - 5F22119B2894A9C100C5B190 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.5; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHostTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestHost.app/TestHost"; - }; - name = Release; - }; - 5F22119D2894A9C100C5B190 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHostUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestHost; - }; - name = Debug; - }; - 5F22119E2894A9C100C5B190 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHostUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestHost; - }; - name = Release; - }; 5F73EBFD28ECE65400608601 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(MARKETING_VERSION)"; DEFINES_MODULE = YES; @@ -2285,6 +2109,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2294,7 +2119,9 @@ 5F73EBFE28ECE65400608601 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(MARKETING_VERSION)"; DEFINES_MODULE = YES; @@ -2324,6 +2151,7 @@ SKIP_INSTALL = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2333,6 +2161,8 @@ 5F79039128B5765D003144CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(MARKETING_VERSION)"; DEFINES_MODULE = YES; @@ -2360,6 +2190,9 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 12.0; }; @@ -2368,6 +2201,8 @@ 5F79039228B5765D003144CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(MARKETING_VERSION)"; DEFINES_MODULE = YES; @@ -2395,6 +2230,8 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 12.0; }; @@ -2460,6 +2297,123 @@ }; name = Release; }; + E7CA74F22E1B4F75002EFB40 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R63EM248DP; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = branch.BranchSDKTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 6.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BranchSDKTestsHostApp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/BranchSDKTestsHostApp"; + }; + name = Debug; + }; + E7CA74F32E1B4F75002EFB40 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R63EM248DP; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = branch.BranchSDKTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 6.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BranchSDKTestsHostApp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/BranchSDKTestsHostApp"; + }; + name = Release; + }; + E7CA758D2E1B59F7002EFB40 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R63EM248DP; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = BranchSDKTestsHostApp/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = BranchSDKTestsHostApp; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = branch.BranchSDKTestsHostApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + E7CA758E2E1B59F7002EFB40 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_ENTITLEMENTS = BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R63EM248DP; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = BranchSDKTestsHostApp/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = BranchSDKTestsHostApp; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = branch.BranchSDKTestsHostApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -2490,33 +2444,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5F2211962894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHost" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5F2211972894A9C100C5B190 /* Debug */, - 5F2211982894A9C100C5B190 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 5F2211992894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHostTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5F22119A2894A9C100C5B190 /* Debug */, - 5F22119B2894A9C100C5B190 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 5F22119C2894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHostUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5F22119D2894A9C100C5B190 /* Debug */, - 5F22119E2894A9C100C5B190 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 5F73EBFC28ECE65400608601 /* Build configuration list for PBXNativeTarget "BranchSDK-static" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -2562,6 +2489,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + E7CA74F42E1B4F75002EFB40 /* Build configuration list for PBXNativeTarget "BranchSDKTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7CA74F22E1B4F75002EFB40 /* Debug */, + E7CA74F32E1B4F75002EFB40 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E7CA758C2E1B59F7002EFB40 /* Build configuration list for PBXNativeTarget "BranchSDKTestsHostApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7CA758D2E1B59F7002EFB40 /* Debug */, + E7CA758E2E1B59F7002EFB40 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 5F2210142894A0DB00C5B190 /* Project object */; diff --git a/TestDeepLinking/TestDeepLinking.xcodeproj/xcshareddata/xcschemes/TestDeepLinking.xcscheme b/BranchSDK.xcodeproj/xcshareddata/xcschemes/BranchSDKTests.xcscheme similarity index 56% rename from TestDeepLinking/TestDeepLinking.xcodeproj/xcshareddata/xcschemes/TestDeepLinking.xcscheme rename to BranchSDK.xcodeproj/xcshareddata/xcschemes/BranchSDKTests.xcscheme index fe40949b8..f32d4b149 100644 --- a/TestDeepLinking/TestDeepLinking.xcodeproj/xcshareddata/xcschemes/TestDeepLinking.xcscheme +++ b/BranchSDK.xcodeproj/xcshareddata/xcschemes/BranchSDKTests.xcscheme @@ -1,10 +1,11 @@ + LastUpgradeVersion = "1640" + version = "2.1"> + buildImplicitDependencies = "YES" + buildArchitectures = "Automatic"> + BlueprintIdentifier = "E7CA755E2E1B59F5002EFB40" + BuildableName = "BranchSDKTestsHostApp.app" + BlueprintName = "BranchSDKTestsHostApp" + ReferencedContainer = "container:BranchSDK.xcodeproj"> + + + + + skipped = "NO" + parallelizable = "YES"> - - - - + BlueprintIdentifier = "E7CA74EA2E1B4F75002EFB40" + BuildableName = "BranchSDKTests.xctest" + BlueprintName = "BranchSDKTests" + ReferencedContainer = "container:BranchSDK.xcodeproj"> @@ -70,10 +72,10 @@ runnableDebuggingMode = "0"> + BlueprintIdentifier = "E7CA755E2E1B59F5002EFB40" + BuildableName = "BranchSDKTestsHostApp.app" + BlueprintName = "BranchSDKTestsHostApp" + ReferencedContainer = "container:BranchSDK.xcodeproj"> @@ -83,16 +85,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> - + + BlueprintIdentifier = "E7CA755E2E1B59F5002EFB40" + BuildableName = "BranchSDKTestsHostApp.app" + BlueprintName = "BranchSDKTestsHostApp" + ReferencedContainer = "container:BranchSDK.xcodeproj"> - + diff --git a/BranchSDKTests/BNCAPIServerTest.m b/BranchSDKTests/BNCAPIServerTest.m new file mode 100644 index 000000000..eb9165001 --- /dev/null +++ b/BranchSDKTests/BNCAPIServerTest.m @@ -0,0 +1,508 @@ +// +// BNCAPIServerTest.m +// Branch-SDK-Tests +// +// Created by Nidhi Dixit on 9/6/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCServerAPI.h" +#import "BNCSystemObserver.h" +#import "BNCConfig.h" +#import "BranchConstants.h" +#import "Branch.h" + +@interface BNCAPIServerTest : XCTestCase + +@end + +@implementation BNCAPIServerTest + +- (void)testInstallServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI installServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/install"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testOpenServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI openServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/open"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testStandardEventServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI standardEventServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v2/event/standard"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testCustomEventServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI customEventServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v2/event/custom"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLinkServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI linkServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/url"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testQRCodeServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI qrcodeServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/qr-code"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLATDServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI latdServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/cpid/latd"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testValidationServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI validationServiceURL]; + NSString *expectedUrlPrefix= @"https://api3.branch.io/v1/app-link-settings"; + + XCTAssertTrue([url hasPrefix:expectedUrlPrefix]); +} + +- (void)testInstallServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI installServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack.branch.io/v1/install"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testOpenServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI openServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack.branch.io/v1/open"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testStandardEventServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI standardEventServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack.branch.io/v2/event/standard"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testCustomEventServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI customEventServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack.branch.io/v2/event/custom"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLinkServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI linkServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/url"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testQRCodeServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI qrcodeServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/qr-code"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLATDServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI latdServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/cpid/latd"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testValidationServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI validationServiceURL]; + NSString *expectedUrlPrefix= @"https://api3.branch.io/v1/app-link-settings"; + + XCTAssertTrue([url hasPrefix:expectedUrlPrefix]); +} + +- (void)testInstallServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI installServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/install"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testOpenServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI openServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/open"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testStandardEventServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI standardEventServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v2/event/standard"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testCustomEventServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI customEventServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v2/event/custom"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLinkServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI linkServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/url"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testQRCodeServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI qrcodeServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/qr-code"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLATDServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI latdServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/cpid/latd"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testValidationServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI validationServiceURL]; + NSString *expectedUrlPrefix= @"https://api3-eu.branch.io/v1/app-link-settings"; + + XCTAssertTrue([url hasPrefix:expectedUrlPrefix]); +} + +- (void)testInstallServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI installServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack-eu.branch.io/v1/install"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testOpenServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI openServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack-eu.branch.io/v1/open"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testStandardEventServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI standardEventServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack-eu.branch.io/v2/event/standard"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testCustomEventServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI customEventServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack-eu.branch.io/v2/event/custom"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLinkServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI linkServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/url"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testQRCodeServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI qrcodeServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/qr-code"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLATDServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI latdServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/cpid/latd"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testValidationServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI validationServiceURL]; + NSString *expectedUrlPrefix= @"https://api3-eu.branch.io/v1/app-link-settings"; + + XCTAssertTrue([url hasPrefix:expectedUrlPrefix]); +} + +- (void)testDefaultAPIURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + XCTAssertNil(serverAPI.customAPIURL); + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = [BNC_API_URL stringByAppendingString: @"/v1/install"]; + XCTAssertEqualObjects(storedUrl, expectedUrl); +} + +- (void)testSetAPIURL_Example { + NSString *url = @"https://www.example.com"; + [Branch setAPIUrl:url]; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = [url stringByAppendingString: @"/v1/install"]; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + [Branch setAPIUrl:BNC_API_URL]; +} + +- (void)testSetAPIURL_InvalidHttp { + NSString *url = @"Invalid://www.example.com"; + [Branch setAPIUrl:url]; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = [BNC_API_URL stringByAppendingString: @"/v1/install"]; + XCTAssertEqualObjects(storedUrl, expectedUrl); +} + +- (void)testSetAPIURL_InvalidEmpty { + NSString *url = @""; + [Branch setAPIUrl:url]; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = [BNC_API_URL stringByAppendingString: @"/v1/install"]; + XCTAssertEqualObjects(storedUrl, expectedUrl); +} + + +- (void)testSetSafeTrackServiceURLWithUserTrackingDomain { + NSString *url = @"https://links.toTestDomain.com"; + NSString *safeTrackUrl = @"https://links.toTestDomain-safeTrack.com"; + + [Branch setAPIUrl:url]; + [Branch setSafetrackAPIURL:safeTrackUrl]; + + BNCServerAPI *serverAPI = [BNCServerAPI sharedInstance]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = @"https://links.toTestDomain-safeTrack.com/v1/install"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] openServiceURL]; + expectedUrl = @"https://links.toTestDomain-safeTrack.com/v1/open"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] standardEventServiceURL]; + expectedUrl = @"https://links.toTestDomain-safeTrack.com/v2/event/standard"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] customEventServiceURL]; + expectedUrl = @"https://links.toTestDomain-safeTrack.com/v2/event/custom"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] linkServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/url"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] qrcodeServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/qr-code"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] latdServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/cpid/latd"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + + [BNCServerAPI sharedInstance].useTrackingDomain = NO; + [BNCServerAPI sharedInstance].useEUServers = NO; + [BNCServerAPI sharedInstance].automaticallyEnableTrackingDomain = YES; + [BNCServerAPI sharedInstance].customAPIURL = nil; + [BNCServerAPI sharedInstance].customSafeTrackAPIURL = nil; + +} + +- (void)testSetSafeTrackServiceURLWithOutUserTrackingDomain { + NSString *url = @"https://links.toTestDomain.com"; + NSString *safeTrackUrl = @"https://links.toTestDomain-safeTrack.com"; + + [Branch setAPIUrl:url]; + [Branch setSafetrackAPIURL:safeTrackUrl]; + + BNCServerAPI *serverAPI = [BNCServerAPI sharedInstance]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = NO; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = @"https://links.toTestDomain.com/v1/install"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] openServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/open"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] standardEventServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v2/event/standard"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] customEventServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v2/event/custom"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] linkServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/url"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] qrcodeServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/qr-code"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] latdServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/cpid/latd"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + [BNCServerAPI sharedInstance].useTrackingDomain = NO; + [BNCServerAPI sharedInstance].useEUServers = NO; + [BNCServerAPI sharedInstance].automaticallyEnableTrackingDomain = YES; + [BNCServerAPI sharedInstance].customAPIURL = nil; + [BNCServerAPI sharedInstance].customSafeTrackAPIURL = nil; + +} + +@end diff --git a/BranchSDKTests/BNCAppleReceiptTests.m b/BranchSDKTests/BNCAppleReceiptTests.m new file mode 100644 index 000000000..faff0ef96 --- /dev/null +++ b/BranchSDKTests/BNCAppleReceiptTests.m @@ -0,0 +1,33 @@ +// +// BNCAppleReceiptTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 7/15/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCAppleReceipt.h" + +@interface BNCAppleReceiptTests : XCTestCase + +@end + +@implementation BNCAppleReceiptTests + +- (void)setUp { + +} + +- (void)tearDown { + +} + +- (void)testReceiptOnSimulator { + BNCAppleReceipt *receipt = [[BNCAppleReceipt alloc] init]; + // Appears the simulator can have a receipt + //XCTAssertNil([receipt installReceipt]); + XCTAssertFalse([receipt isTestFlight]); +} + +@end diff --git a/BranchSDKTests/BNCApplicationTests.m b/BranchSDKTests/BNCApplicationTests.m new file mode 100644 index 000000000..147a2a665 --- /dev/null +++ b/BranchSDKTests/BNCApplicationTests.m @@ -0,0 +1,75 @@ +// +// BNCApplication.Test.m +// Branch-SDK-Tests +// +// Created by Edward on 1/10/18. +// Copyright © 2018 Branch, Inc. All rights reserved. +// + +#import +#import "BNCApplication.h" +#import "BNCKeyChain.h" + +@interface BNCApplicationTests : XCTestCase +@end + +@implementation BNCApplicationTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testApplication { + // Test general info: + + if ([UIApplication sharedApplication] == nil) { + NSLog(@"No host application for BNCApplication testing!"); + return; + } + + BNCApplication *application = [BNCApplication currentApplication]; + XCTAssertEqualObjects(application.bundleID, @"branch.BranchSDKTestsHostApp"); + XCTAssertEqualObjects(application.displayName, @"BranchSDKTestsHostApp"); + XCTAssertEqualObjects(application.shortDisplayName, @"BranchSDKTestsHostApp"); + XCTAssertEqualObjects(application.displayVersionString, @"1.0"); + XCTAssertEqualObjects(application.versionString, @"1"); +} + +- (void) testAppDates { + // App dates. Not a great test but tests basic function: + + if ([UIApplication sharedApplication] == nil) { + NSLog(@"No host application for BNCApplication testing!"); + return; + } + + NSTimeInterval const kOneYearAgo = -365.0 * 24.0 * 60.0 * 60.0; + + BNCApplication *application = [BNCApplication currentApplication]; + XCTAssertTrue(application.firstInstallDate && [application.firstInstallDate timeIntervalSinceNow] > kOneYearAgo); + XCTAssertTrue(application.firstInstallBuildDate && [application.firstInstallBuildDate timeIntervalSinceNow] > kOneYearAgo); + XCTAssertTrue(application.currentInstallDate && [application.currentInstallDate timeIntervalSinceNow] > kOneYearAgo); + XCTAssertTrue(application.currentBuildDate && [application.currentBuildDate timeIntervalSinceNow] > kOneYearAgo); + + NSString*const kBranchKeychainService = @"BranchKeychainService"; + NSString*const kBranchKeychainFirstBuildKey = @"BranchKeychainFirstBuild"; + NSString*const kBranchKeychainFirstInstalldKey = @"BranchKeychainFirstInstall"; + + NSDate * firstBuildDate = + [BNCKeyChain retrieveDateForService:kBranchKeychainService + key:kBranchKeychainFirstBuildKey + error:nil]; + XCTAssertEqualObjects(application.firstInstallBuildDate, firstBuildDate); + + NSDate * firstInstallDate = + [BNCKeyChain retrieveDateForService:kBranchKeychainService + key:kBranchKeychainFirstInstalldKey + error:nil]; + XCTAssertEqualObjects(application.firstInstallDate, firstInstallDate); +} + +@end diff --git a/BranchSDKTests/BNCCallbackMapTests.m b/BranchSDKTests/BNCCallbackMapTests.m new file mode 100644 index 000000000..4d5482499 --- /dev/null +++ b/BranchSDKTests/BNCCallbackMapTests.m @@ -0,0 +1,134 @@ +// +// BNCCallbackMapTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 2/25/20. +// Copyright © 2020 Branch, Inc. All rights reserved. +// + +#import +#import "BNCCallbackMap.h" +#import "NSError+Branch.h" + +// expose private storage object for state checks +@interface BNCCallbackMap() +@property (nonatomic, strong, readwrite) NSMapTable *callbacks; +@end + +@interface BNCCallbackMapTests : XCTestCase + +@end + +@implementation BNCCallbackMapTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testRequestSaveAndCallback { + BNCCallbackMap *map = [BNCCallbackMap new]; + + __block BOOL successResult = NO; + __block NSError *errorResult = nil; + + // store a request and callback block + BNCServerRequest *request = [BNCServerRequest new]; + [map storeRequest:request withCompletion:^(BOOL success, NSError * _Nullable error) { + successResult = success; + errorResult = error; + }]; + + // confirm there's one entry + XCTAssert([map containsRequest:request] != NO); + XCTAssert(map.callbacks.count == 1); + + // call callback + [map callCompletionForRequest:request withSuccessStatus:YES error:nil]; + + // check if variable was updated + XCTAssertTrue(successResult); + XCTAssertNil(errorResult); +} + +- (void)testRequestSaveAndCallbackWithError { + BNCCallbackMap *map = [BNCCallbackMap new]; + + __block BOOL successResult = YES; + __block NSError *errorResult = nil; + + // store a request and callback block + BNCServerRequest *request = [BNCServerRequest new]; + [map storeRequest:request withCompletion:^(BOOL success, NSError * _Nullable error) { + successResult = success; + errorResult = error; + }]; + + // confirm there's one entry + XCTAssert([map containsRequest:request] != NO); + XCTAssert(map.callbacks.count == 1); + + // call callback + [map callCompletionForRequest:request withSuccessStatus:NO error:[NSError branchErrorWithCode:BNCGeneralError localizedMessage:@"Test Error"]]; + + // check if variable was updated + XCTAssertFalse(successResult); + XCTAssert([@"Test Error" isEqualToString:errorResult.localizedFailureReason]); +} + +- (void)testAttemptCallbackWithUnsavedRequest { + BNCCallbackMap *map = [BNCCallbackMap new]; + + __block BOOL successResult = NO; + __block NSError *errorResult = nil; + + // store a request and callback block + BNCServerRequest *request = [BNCServerRequest new]; + [map storeRequest:request withCompletion:^(BOOL success, NSError * _Nullable error) { + successResult = success; + errorResult = error; + }]; + + // confirm there's one entry + XCTAssert([map containsRequest:request] != NO); + XCTAssert(map.callbacks.count == 1); + + // confirm a new request results in no callback + request = [BNCServerRequest new]; + XCTAssert([map containsRequest:request] == NO); + [map callCompletionForRequest:request withSuccessStatus:YES error:nil]; + + // check if variable was updated + XCTAssertFalse(successResult); + XCTAssertNil(errorResult); +} + +- (void)testRequestsGetReleasedAutomatically { + BNCCallbackMap *map = [BNCCallbackMap new]; + + __block int count = 0; + + BNCServerRequest *request = [BNCServerRequest new]; + [map storeRequest:request withCompletion:^(BOOL success, NSError * _Nullable error) { + count++; + }]; + + for (int i=0; i<100; i++) { + BNCServerRequest *tmp = [BNCServerRequest new]; + [map storeRequest:tmp withCompletion:^(BOOL success, NSError * _Nullable error) { + count++; + }]; + } + + // confirm there's less than 100 entries. By not retaining the tmp request, they should be getting ARC'd + XCTAssert(map.callbacks.count < 100); + + // confirm the one request we held does get a callback + [map callCompletionForRequest:request withSuccessStatus:YES error:nil]; + XCTAssert(count == 1); +} + +@end diff --git a/BranchSDKTests/BNCClassSerializationTests.m b/BranchSDKTests/BNCClassSerializationTests.m new file mode 100644 index 000000000..f1af287d9 --- /dev/null +++ b/BranchSDKTests/BNCClassSerializationTests.m @@ -0,0 +1,120 @@ +// +// BNCClassSerializationTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 3/28/24. +// Copyright © 2024 Branch, Inc. All rights reserved. +// + +#import +#import "BranchEvent.h" +#import "BranchOpenRequest.h" +#import "BranchInstallRequest.h" + +@interface BranchEvent() +// private BranchEvent methods used to build a BranchEventRequest +- (NSDictionary *)buildEventDictionary; +@end + +@interface BranchOpenRequest() +- (NSString *)getActionName; +@end + +@interface BNCClassSerializationTests : XCTestCase + +@end + +// Test serialization of replayable requests +@implementation BNCClassSerializationTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +// BranchEventRequest is creation is tightly coupled with the BranchEvent class +// In order to test building it, we need to expose some private methods. :( +- (BranchEventRequest *)buildBranchEventRequest { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventPurchase]; + NSURL *url = [NSURL URLWithString:@"https://api3.branch.io/v2/event/standard"]; + NSDictionary *eventDictionary = [event buildEventDictionary]; + + BranchEventRequest *request = [[BranchEventRequest alloc] initWithServerURL:url eventDictionary:eventDictionary completion:nil]; + return request; +} + +- (void)testBranchEventRequestArchive { + BranchEventRequest *request = [self buildBranchEventRequest]; + + // archive the event + NSError *error = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:request requiringSecureCoding:YES error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(data); + + // unarchive the event + id object = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[BranchEventRequest.class]] fromData:data error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(object); + + // check object + XCTAssertTrue([object isKindOfClass:BranchEventRequest.class]); + BranchEventRequest *unarchivedRequest = (BranchEventRequest *)object; + + XCTAssertTrue([request.serverURL.absoluteString isEqualToString:unarchivedRequest.serverURL.absoluteString]); + XCTAssertTrue(request.eventDictionary.count == unarchivedRequest.eventDictionary.count); + XCTAssertNil(unarchivedRequest.completion); +} + +- (void)testBranchOpenRequestArchive { + BranchOpenRequest *request = [[BranchOpenRequest alloc] initWithCallback:nil]; + request.urlString = @"https://branch.io"; + + // archive the event + NSError *error = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:request requiringSecureCoding:YES error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(data); + + // unarchive the event + id object = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[BranchOpenRequest.class]] fromData:data error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(object); + + // check object + XCTAssertTrue([object isKindOfClass:BranchOpenRequest.class]); + BranchOpenRequest *unarchivedRequest = (BranchOpenRequest *)object; + + XCTAssertTrue([request.urlString isEqualToString:unarchivedRequest.urlString]); + XCTAssertNil(unarchivedRequest.callback); + XCTAssertTrue([@"open" isEqualToString:[unarchivedRequest getActionName]]); +} + +- (void)testBranchInstallRequestArchive { + BranchInstallRequest *request = [[BranchInstallRequest alloc] initWithCallback:nil]; + request.urlString = @"https://branch.io"; + + // archive the event + NSError *error = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:request requiringSecureCoding:YES error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(data); + + // unarchive the event + id object = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[BranchInstallRequest.class]] fromData:data error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(object); + + // check object + XCTAssertTrue([object isKindOfClass:BranchInstallRequest.class]); + BranchInstallRequest *unarchivedRequest = (BranchInstallRequest *)object; + + XCTAssertTrue([request.urlString isEqualToString:unarchivedRequest.urlString]); + XCTAssertNil(unarchivedRequest.callback); + XCTAssertTrue([@"install" isEqualToString:[unarchivedRequest getActionName]]); +} + +@end diff --git a/BranchSDKTests/BNCCrashlyticsWrapperTests.m b/BranchSDKTests/BNCCrashlyticsWrapperTests.m new file mode 100644 index 000000000..4b9be75a4 --- /dev/null +++ b/BranchSDKTests/BNCCrashlyticsWrapperTests.m @@ -0,0 +1,68 @@ +// +// BNCCrashlyticsWrapperTest.m +// Branch-TestBed +// +// Created by Jimmy Dee on 7/18/17. +// Copyright © 2017 Branch Metrics. All rights reserved. +// + +#import +#import "BNCCrashlyticsWrapper.h" + +#pragma mark Crashlytics SDK Stand-In + +@interface FIRCrashlytics : NSObject ++ (FIRCrashlytics *)crashlytics; +@property NSMutableDictionary *values; +- (void)setCustomValue:(id)value forKey:(NSString *)key; +-(id)getCustomValueForKey:(NSString *)key; +@end + +@implementation FIRCrashlytics + ++ (FIRCrashlytics *)crashlytics { + @synchronized (self) { + static FIRCrashlytics * sharedCrashlytics = nil; + if (!sharedCrashlytics) sharedCrashlytics = [[self alloc] init]; + return sharedCrashlytics; + } +} + +- (void)setCustomValue:(id)value forKey:(NSString *)key { + if (!_values) { + _values = [[NSMutableDictionary alloc] init]; + } + [_values setObject:value forKey:key]; +} + +-(id)getCustomValueForKey:(NSString *)key { + return [_values valueForKey:key]; +} +@end + +#pragma mark - BNCCrashlyticsWrapperTest + +@interface BNCCrashlyticsWrapperTests : XCTestCase +@end + +@implementation BNCCrashlyticsWrapperTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testSetValue { + BNCCrashlyticsWrapper *wrapper = [BNCCrashlyticsWrapper wrapper]; + NSString *value = @"TestString"; + NSString *key = @"TestKey"; + + [wrapper setCustomValue:value forKey:key]; + + XCTAssertEqual([[FIRCrashlytics crashlytics] getCustomValueForKey:key], value); +} + +@end diff --git a/BranchSDKTests/BNCCurrencyTests.m b/BranchSDKTests/BNCCurrencyTests.m new file mode 100644 index 000000000..ec24da0f8 --- /dev/null +++ b/BranchSDKTests/BNCCurrencyTests.m @@ -0,0 +1,194 @@ +// +// BNCCurrencyTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 9/21/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCCurrency.h" + +@interface BNCCurrencyTests : XCTestCase +@end + +@implementation BNCCurrencyTests + +- (void)testEnumValues { + XCTAssertEqualObjects(BNCCurrencyAED, @"AED"); + XCTAssertEqualObjects(BNCCurrencyAFN, @"AFN"); + XCTAssertEqualObjects(BNCCurrencyALL, @"ALL"); + XCTAssertEqualObjects(BNCCurrencyAMD, @"AMD"); + XCTAssertEqualObjects(BNCCurrencyANG, @"ANG"); + XCTAssertEqualObjects(BNCCurrencyAOA, @"AOA"); + XCTAssertEqualObjects(BNCCurrencyARS, @"ARS"); + XCTAssertEqualObjects(BNCCurrencyAUD, @"AUD"); + XCTAssertEqualObjects(BNCCurrencyAWG, @"AWG"); + XCTAssertEqualObjects(BNCCurrencyAZN, @"AZN"); + XCTAssertEqualObjects(BNCCurrencyBAM, @"BAM"); + XCTAssertEqualObjects(BNCCurrencyBBD, @"BBD"); + XCTAssertEqualObjects(BNCCurrencyBDT, @"BDT"); + XCTAssertEqualObjects(BNCCurrencyBGN, @"BGN"); + XCTAssertEqualObjects(BNCCurrencyBHD, @"BHD"); + XCTAssertEqualObjects(BNCCurrencyBIF, @"BIF"); + XCTAssertEqualObjects(BNCCurrencyBMD, @"BMD"); + XCTAssertEqualObjects(BNCCurrencyBND, @"BND"); + XCTAssertEqualObjects(BNCCurrencyBOB, @"BOB"); + XCTAssertEqualObjects(BNCCurrencyBOV, @"BOV"); + XCTAssertEqualObjects(BNCCurrencyBRL, @"BRL"); + XCTAssertEqualObjects(BNCCurrencyBSD, @"BSD"); + XCTAssertEqualObjects(BNCCurrencyBTN, @"BTN"); + XCTAssertEqualObjects(BNCCurrencyBWP, @"BWP"); + XCTAssertEqualObjects(BNCCurrencyBYN, @"BYN"); + XCTAssertEqualObjects(BNCCurrencyBYR, @"BYR"); + XCTAssertEqualObjects(BNCCurrencyBZD, @"BZD"); + XCTAssertEqualObjects(BNCCurrencyCAD, @"CAD"); + XCTAssertEqualObjects(BNCCurrencyCDF, @"CDF"); + XCTAssertEqualObjects(BNCCurrencyCHE, @"CHE"); + XCTAssertEqualObjects(BNCCurrencyCHF, @"CHF"); + XCTAssertEqualObjects(BNCCurrencyCHW, @"CHW"); + XCTAssertEqualObjects(BNCCurrencyCLF, @"CLF"); + XCTAssertEqualObjects(BNCCurrencyCLP, @"CLP"); + XCTAssertEqualObjects(BNCCurrencyCNY, @"CNY"); + XCTAssertEqualObjects(BNCCurrencyCOP, @"COP"); + XCTAssertEqualObjects(BNCCurrencyCOU, @"COU"); + XCTAssertEqualObjects(BNCCurrencyCRC, @"CRC"); + XCTAssertEqualObjects(BNCCurrencyCUC, @"CUC"); + XCTAssertEqualObjects(BNCCurrencyCUP, @"CUP"); + XCTAssertEqualObjects(BNCCurrencyCVE, @"CVE"); + XCTAssertEqualObjects(BNCCurrencyCZK, @"CZK"); + XCTAssertEqualObjects(BNCCurrencyDJF, @"DJF"); + XCTAssertEqualObjects(BNCCurrencyDKK, @"DKK"); + XCTAssertEqualObjects(BNCCurrencyDOP, @"DOP"); + XCTAssertEqualObjects(BNCCurrencyDZD, @"DZD"); + XCTAssertEqualObjects(BNCCurrencyEGP, @"EGP"); + XCTAssertEqualObjects(BNCCurrencyERN, @"ERN"); + XCTAssertEqualObjects(BNCCurrencyETB, @"ETB"); + XCTAssertEqualObjects(BNCCurrencyEUR, @"EUR"); + XCTAssertEqualObjects(BNCCurrencyFJD, @"FJD"); + XCTAssertEqualObjects(BNCCurrencyFKP, @"FKP"); + XCTAssertEqualObjects(BNCCurrencyGBP, @"GBP"); + XCTAssertEqualObjects(BNCCurrencyGEL, @"GEL"); + XCTAssertEqualObjects(BNCCurrencyGHS, @"GHS"); + XCTAssertEqualObjects(BNCCurrencyGIP, @"GIP"); + XCTAssertEqualObjects(BNCCurrencyGMD, @"GMD"); + XCTAssertEqualObjects(BNCCurrencyGNF, @"GNF"); + XCTAssertEqualObjects(BNCCurrencyGTQ, @"GTQ"); + XCTAssertEqualObjects(BNCCurrencyGYD, @"GYD"); + XCTAssertEqualObjects(BNCCurrencyHKD, @"HKD"); + XCTAssertEqualObjects(BNCCurrencyHNL, @"HNL"); + XCTAssertEqualObjects(BNCCurrencyHRK, @"HRK"); + XCTAssertEqualObjects(BNCCurrencyHTG, @"HTG"); + XCTAssertEqualObjects(BNCCurrencyHUF, @"HUF"); + XCTAssertEqualObjects(BNCCurrencyIDR, @"IDR"); + XCTAssertEqualObjects(BNCCurrencyILS, @"ILS"); + XCTAssertEqualObjects(BNCCurrencyINR, @"INR"); + XCTAssertEqualObjects(BNCCurrencyIQD, @"IQD"); + XCTAssertEqualObjects(BNCCurrencyIRR, @"IRR"); + XCTAssertEqualObjects(BNCCurrencyISK, @"ISK"); + XCTAssertEqualObjects(BNCCurrencyJMD, @"JMD"); + XCTAssertEqualObjects(BNCCurrencyJOD, @"JOD"); + XCTAssertEqualObjects(BNCCurrencyJPY, @"JPY"); + XCTAssertEqualObjects(BNCCurrencyKES, @"KES"); + XCTAssertEqualObjects(BNCCurrencyKGS, @"KGS"); + XCTAssertEqualObjects(BNCCurrencyKHR, @"KHR"); + XCTAssertEqualObjects(BNCCurrencyKMF, @"KMF"); + XCTAssertEqualObjects(BNCCurrencyKPW, @"KPW"); + XCTAssertEqualObjects(BNCCurrencyKRW, @"KRW"); + XCTAssertEqualObjects(BNCCurrencyKWD, @"KWD"); + XCTAssertEqualObjects(BNCCurrencyKYD, @"KYD"); + XCTAssertEqualObjects(BNCCurrencyKZT, @"KZT"); + XCTAssertEqualObjects(BNCCurrencyLAK, @"LAK"); + XCTAssertEqualObjects(BNCCurrencyLBP, @"LBP"); + XCTAssertEqualObjects(BNCCurrencyLKR, @"LKR"); + XCTAssertEqualObjects(BNCCurrencyLRD, @"LRD"); + XCTAssertEqualObjects(BNCCurrencyLSL, @"LSL"); + XCTAssertEqualObjects(BNCCurrencyLYD, @"LYD"); + XCTAssertEqualObjects(BNCCurrencyMAD, @"MAD"); + XCTAssertEqualObjects(BNCCurrencyMDL, @"MDL"); + XCTAssertEqualObjects(BNCCurrencyMGA, @"MGA"); + XCTAssertEqualObjects(BNCCurrencyMKD, @"MKD"); + XCTAssertEqualObjects(BNCCurrencyMMK, @"MMK"); + XCTAssertEqualObjects(BNCCurrencyMNT, @"MNT"); + XCTAssertEqualObjects(BNCCurrencyMOP, @"MOP"); + XCTAssertEqualObjects(BNCCurrencyMRO, @"MRO"); + XCTAssertEqualObjects(BNCCurrencyMUR, @"MUR"); + XCTAssertEqualObjects(BNCCurrencyMVR, @"MVR"); + XCTAssertEqualObjects(BNCCurrencyMWK, @"MWK"); + XCTAssertEqualObjects(BNCCurrencyMXN, @"MXN"); + XCTAssertEqualObjects(BNCCurrencyMXV, @"MXV"); + XCTAssertEqualObjects(BNCCurrencyMYR, @"MYR"); + XCTAssertEqualObjects(BNCCurrencyMZN, @"MZN"); + XCTAssertEqualObjects(BNCCurrencyNAD, @"NAD"); + XCTAssertEqualObjects(BNCCurrencyNGN, @"NGN"); + XCTAssertEqualObjects(BNCCurrencyNIO, @"NIO"); + XCTAssertEqualObjects(BNCCurrencyNOK, @"NOK"); + XCTAssertEqualObjects(BNCCurrencyNPR, @"NPR"); + XCTAssertEqualObjects(BNCCurrencyNZD, @"NZD"); + XCTAssertEqualObjects(BNCCurrencyOMR, @"OMR"); + XCTAssertEqualObjects(BNCCurrencyPAB, @"PAB"); + XCTAssertEqualObjects(BNCCurrencyPEN, @"PEN"); + XCTAssertEqualObjects(BNCCurrencyPGK, @"PGK"); + XCTAssertEqualObjects(BNCCurrencyPHP, @"PHP"); + XCTAssertEqualObjects(BNCCurrencyPKR, @"PKR"); + XCTAssertEqualObjects(BNCCurrencyPLN, @"PLN"); + XCTAssertEqualObjects(BNCCurrencyPYG, @"PYG"); + XCTAssertEqualObjects(BNCCurrencyQAR, @"QAR"); + XCTAssertEqualObjects(BNCCurrencyRON, @"RON"); + XCTAssertEqualObjects(BNCCurrencyRSD, @"RSD"); + XCTAssertEqualObjects(BNCCurrencyRUB, @"RUB"); + XCTAssertEqualObjects(BNCCurrencyRWF, @"RWF"); + XCTAssertEqualObjects(BNCCurrencySAR, @"SAR"); + XCTAssertEqualObjects(BNCCurrencySBD, @"SBD"); + XCTAssertEqualObjects(BNCCurrencySCR, @"SCR"); + XCTAssertEqualObjects(BNCCurrencySDG, @"SDG"); + XCTAssertEqualObjects(BNCCurrencySEK, @"SEK"); + XCTAssertEqualObjects(BNCCurrencySGD, @"SGD"); + XCTAssertEqualObjects(BNCCurrencySHP, @"SHP"); + XCTAssertEqualObjects(BNCCurrencySLL, @"SLL"); + XCTAssertEqualObjects(BNCCurrencySOS, @"SOS"); + XCTAssertEqualObjects(BNCCurrencySRD, @"SRD"); + XCTAssertEqualObjects(BNCCurrencySSP, @"SSP"); + XCTAssertEqualObjects(BNCCurrencySTD, @"STD"); + XCTAssertEqualObjects(BNCCurrencySYP, @"SYP"); + XCTAssertEqualObjects(BNCCurrencySZL, @"SZL"); + XCTAssertEqualObjects(BNCCurrencyTHB, @"THB"); + XCTAssertEqualObjects(BNCCurrencyTJS, @"TJS"); + XCTAssertEqualObjects(BNCCurrencyTMT, @"TMT"); + XCTAssertEqualObjects(BNCCurrencyTND, @"TND"); + XCTAssertEqualObjects(BNCCurrencyTOP, @"TOP"); + XCTAssertEqualObjects(BNCCurrencyTRY, @"TRY"); + XCTAssertEqualObjects(BNCCurrencyTTD, @"TTD"); + XCTAssertEqualObjects(BNCCurrencyTWD, @"TWD"); + XCTAssertEqualObjects(BNCCurrencyTZS, @"TZS"); + XCTAssertEqualObjects(BNCCurrencyUAH, @"UAH"); + XCTAssertEqualObjects(BNCCurrencyUGX, @"UGX"); + XCTAssertEqualObjects(BNCCurrencyUSD, @"USD"); + XCTAssertEqualObjects(BNCCurrencyUSN, @"USN"); + XCTAssertEqualObjects(BNCCurrencyUYI, @"UYI"); + XCTAssertEqualObjects(BNCCurrencyUYU, @"UYU"); + XCTAssertEqualObjects(BNCCurrencyUZS, @"UZS"); + XCTAssertEqualObjects(BNCCurrencyVEF, @"VEF"); + XCTAssertEqualObjects(BNCCurrencyVND, @"VND"); + XCTAssertEqualObjects(BNCCurrencyVUV, @"VUV"); + XCTAssertEqualObjects(BNCCurrencyWST, @"WST"); + XCTAssertEqualObjects(BNCCurrencyXAF, @"XAF"); + XCTAssertEqualObjects(BNCCurrencyXAG, @"XAG"); + XCTAssertEqualObjects(BNCCurrencyXAU, @"XAU"); + XCTAssertEqualObjects(BNCCurrencyXCD, @"XCD"); + XCTAssertEqualObjects(BNCCurrencyXDR, @"XDR"); + XCTAssertEqualObjects(BNCCurrencyXOF, @"XOF"); + XCTAssertEqualObjects(BNCCurrencyXPD, @"XPD"); + XCTAssertEqualObjects(BNCCurrencyXPF, @"XPF"); + XCTAssertEqualObjects(BNCCurrencyXPT, @"XPT"); + XCTAssertEqualObjects(BNCCurrencyXSU, @"XSU"); + XCTAssertEqualObjects(BNCCurrencyXTS, @"XTS"); + XCTAssertEqualObjects(BNCCurrencyXUA, @"XUA"); + XCTAssertEqualObjects(BNCCurrencyXXX, @"XXX"); + XCTAssertEqualObjects(BNCCurrencyYER, @"YER"); + XCTAssertEqualObjects(BNCCurrencyZAR, @"ZAR"); + XCTAssertEqualObjects(BNCCurrencyZMW, @"ZMW"); +} + + +@end diff --git a/BranchSDKTests/BNCDeviceInfoTests.m b/BranchSDKTests/BNCDeviceInfoTests.m new file mode 100644 index 000000000..39b4ee5d8 --- /dev/null +++ b/BranchSDKTests/BNCDeviceInfoTests.m @@ -0,0 +1,190 @@ +// +// BNCDeviceInfoTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 11/21/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCDeviceInfo.h" +#import "BNCUserAgentCollector.h" + +@interface BNCDeviceInfoTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCDeviceInfo *deviceInfo; +@end + +@implementation BNCDeviceInfoTests + +- (void)setUp { + [self workaroundUserAgentLazyLoad]; + self.deviceInfo = [BNCDeviceInfo new]; +} + +// user agent needs to be loaded +- (void)workaroundUserAgentLazyLoad { + __block XCTestExpectation *expectation = [self expectationWithDescription:@"setup"]; + [[BNCUserAgentCollector instance] loadUserAgentWithCompletion:^(NSString * _Nullable userAgent) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:5.0 handler:^(NSError * _Nullable error) { }]; +} + +- (void)tearDown { + +} + +- (void)testHardwareId { + XCTAssertNotNil(self.deviceInfo.hardwareId); + + // verify hardwareId is a valid UUID + NSUUID *hardwareId = [[NSUUID alloc] initWithUUIDString:self.deviceInfo.hardwareId]; + XCTAssertNotNil(hardwareId); +} + +- (void)testHardwareIdType { + // without ATT, this is the IDFV. Branch servers expect it as vendor_id + XCTAssert([self.deviceInfo.hardwareIdType isEqualToString:@"vendor_id"]); +} + +- (void)testIsRealHardwareId { + XCTAssert(self.deviceInfo.isRealHardwareId); +} + +- (void)testAdvertiserId { + // the testbed does not show the ATT prompt. + XCTAssertNil(self.deviceInfo.advertiserId); +} + +- (void)testVendorId { + XCTAssertNotNil(self.deviceInfo.vendorId); + + // verify vendorId is a valid UUID + NSUUID *vendorId = [[NSUUID alloc] initWithUUIDString:self.deviceInfo.vendorId]; + XCTAssertNotNil(vendorId); +} + +- (void)testAnonId { + XCTAssertNotNil(self.deviceInfo.anonId); + + // verify anonId is a valid UUID + NSUUID *anonId = [[NSUUID alloc] initWithUUIDString:self.deviceInfo.anonId]; + XCTAssertNotNil(anonId); +} + +- (void)testOptedInStatus { + // the testbed does not show the ATT prompt. + XCTAssert([self.deviceInfo.optedInStatus isEqualToString:@"not_determined"]); +} + +- (void)testIsFirstOptIn { + // the testbed does not show the ATT prompt. + XCTAssert(self.deviceInfo.isFirstOptIn == NO); +} + +- (void)testLocalIPAddress { + NSString *address = [self.deviceInfo localIPAddress]; + XCTAssertNotNil(address); + XCTAssert(address.length > 7); +} + +- (void)testConnectionType { + // simulator is on wifi + XCTAssert([[self.deviceInfo connectionType] isEqualToString:@"wifi"]); +} + +- (void)testBrandName { + XCTAssert([@"Apple" isEqualToString:self.deviceInfo.brandName]); +} + +- (void)testModelName_Simulator { + // intel processor + bool x86_64 = [@"x86_64" isEqualToString:self.deviceInfo.modelName]; + + // apple processor + bool arm64 = [@"arm64" isEqualToString:self.deviceInfo.modelName]; + + XCTAssert(x86_64 || arm64); +} + +- (void)testOSName { + XCTAssertNotNil(self.deviceInfo.osName); + XCTAssert([@"iOS" isEqualToString:self.deviceInfo.osName]); +} + +- (void)testOSVersion { + XCTAssertNotNil(self.deviceInfo.osVersion); + XCTAssert([self.deviceInfo.osVersion isEqualToString:[UIDevice currentDevice].systemVersion]); +} + +- (void)testOSBuildVersion { + XCTAssertNotNil(self.deviceInfo.osBuildVersion); +} + +- (void)testEnvironment { + // currently not running unit tests on extensions + XCTAssert([@"FULL_APP" isEqualToString:self.deviceInfo.environment]); +} + +- (void)testCpuType_Simulator { + // intel processors + bool x86 = [@"7" isEqualToString:self.deviceInfo.cpuType]; + + // apple processors + bool arm = [@"16777228" isEqualToString:self.deviceInfo.cpuType]; + + XCTAssert(x86 || arm); +} + +- (void)testScreenWidth { + XCTAssert(self.deviceInfo.screenWidth.intValue >= 320); +} + +- (void)testScreenHeight { + XCTAssert(self.deviceInfo.screenHeight.intValue >= 320); +} + +- (void)testScreenScale { + XCTAssert(self.deviceInfo.screenScale.intValue >= 1); +} + +- (void)testLocale { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale isEqualToString:self.deviceInfo.locale]); +} + +- (void)testCountry { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale containsString:self.deviceInfo.country]); +} + +- (void)testLanguage { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale containsString:self.deviceInfo.language]); +} + +- (void)testUserAgentString { + XCTAssert([self.deviceInfo.userAgentString containsString:@"AppleWebKit"]); +} + +- (void)testApplicationVersion_TestBed { + XCTAssert([@"1.0" isEqualToString:self.deviceInfo.applicationVersion]); +} + +- (void)testRegisterPluginNameVersion { + XCTAssertNil(self.deviceInfo.pluginName); + XCTAssertNil(self.deviceInfo.pluginVersion); + + NSString *expectedName = @"react native"; + NSString *expectedVersion = @"1.0.0"; + + [self.deviceInfo registerPluginName:expectedName version:expectedVersion]; + + XCTAssert([expectedName isEqualToString:self.deviceInfo.pluginName]); + XCTAssert([expectedVersion isEqualToString:self.deviceInfo.pluginVersion]); +} + +@end diff --git a/BranchSDKTests/BNCDeviceSystemTests.m b/BranchSDKTests/BNCDeviceSystemTests.m new file mode 100644 index 000000000..0a47b73d9 --- /dev/null +++ b/BranchSDKTests/BNCDeviceSystemTests.m @@ -0,0 +1,62 @@ +// +// BNCDeviceSystemTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 11/14/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCDeviceSystem.h" + +@interface BNCDeviceSystemTests : XCTestCase + +@property (nonatomic, strong, readwrite) BNCDeviceSystem *deviceSystem; + +@end + +@implementation BNCDeviceSystemTests + +- (void)setUp { + self.deviceSystem = [BNCDeviceSystem new]; +} + +- (void)tearDown { + +} + +- (void)testSystemBuildVersion { + XCTAssertNotNil(self.deviceSystem.systemBuildVersion); + XCTAssert(self.deviceSystem.systemBuildVersion.length > 0); +} + +- (void)testMachine_Simulator { + // intel processor + bool x86_64 = [@"x86_64" isEqualToString:self.deviceSystem.machine]; + + // apple processor + bool arm64 = [@"arm64" isEqualToString:self.deviceSystem.machine]; + + XCTAssert(x86_64 || arm64); +} + +- (void)testCPUType_Simulator { + // intel processor + bool x86 = [@(7) isEqualToNumber:self.deviceSystem.cpuType]; + bool x86_sub = [@(8) isEqualToNumber:self.deviceSystem.cpuSubType]; + + // apple processor + bool arm = [@(16777228) isEqualToNumber:self.deviceSystem.cpuType]; + bool arm_sub = [@(2) isEqualToNumber:self.deviceSystem.cpuSubType]; + + XCTAssert(x86 || arm); + +// cpu subtype is different on cloud runners +// if (x86) { +// XCTAssert(x86_sub); +// } else { +// XCTAssert(arm_sub); +// } +} + +@end diff --git a/BranchSDKTests/BNCDisableAdNetworkCalloutsTests.m b/BranchSDKTests/BNCDisableAdNetworkCalloutsTests.m new file mode 100644 index 000000000..ea277ac39 --- /dev/null +++ b/BranchSDKTests/BNCDisableAdNetworkCalloutsTests.m @@ -0,0 +1,59 @@ +// +// BNCDisableAdNetworkCalloutsTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 3/2/20. +// Copyright © 2020 Branch, Inc. All rights reserved. +// + +#import +#import "BNCPreferenceHelper.h" +#import "BNCDeviceInfo.h" +#import "BNCServerInterface.h" +@import BranchSDK; + +@interface BNCServerInterface() +- (void)updateDeviceInfoToMutableDictionary:(NSMutableDictionary *)dict; +@end + +@interface BNCDisableAdNetworkCalloutsTests : XCTestCase + +@end + +// These tests are not parallelizable and therefore disabled by default +// This is due to the tight coupling between BNCPreferenceHelper and BNCDeviceInfo +@implementation BNCDisableAdNetworkCalloutsTests +/* +- (void)setUp { + [BNCPreferenceHelper preferenceHelper].disableAdNetworkCallouts = YES; +} + +- (void)tearDown { + [BNCPreferenceHelper preferenceHelper].disableAdNetworkCallouts = NO; +} + +// check on the V2 dictionary +- (void)testV2Dictionary { + NSDictionary *dict = [[BNCDeviceInfo getInstance] v2dictionary]; + XCTAssertNotNil(dict); + XCTAssertNotNil(dict[@"brand"]); + XCTAssertNotNil(dict[@"os"]); + XCTAssertNotNil(dict[@"sdk"]); + XCTAssertNotNil(dict[@"sdk_version"]); + + XCTAssertTrue(dict[@"disable_ad_network_callouts"]); +} + +// check on V1 payload +- (void)testV1Payload { + BNCServerInterface *interface = [BNCServerInterface new]; + interface.preferenceHelper = [BNCPreferenceHelper preferenceHelper]; + + NSMutableDictionary *tmp = [NSMutableDictionary new]; + [interface updateDeviceInfoToMutableDictionary:tmp]; + + XCTAssertNotNil(tmp); + XCTAssertTrue(tmp[@"disable_ad_network_callouts"]); +} +*/ +@end diff --git a/BranchSDKTests/BNCEncodingUtilsTests.m b/BranchSDKTests/BNCEncodingUtilsTests.m new file mode 100644 index 000000000..0b18fe51a --- /dev/null +++ b/BranchSDKTests/BNCEncodingUtilsTests.m @@ -0,0 +1,609 @@ +// +// BNCEncodingUtils.m +// Branch +// +// Created by Graham Mueller on 4/1/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import +#import "BNCEncodingUtils.h" + +@interface BNCEncodingUtilsTests : XCTestCase +@end + +@implementation BNCEncodingUtilsTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +#pragma mark - EncodeDictionaryToJsonString tests + +- (void)testEncodeDictionaryToJsonStringWithExpectedParams { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; + NSDate *date = [dateFormatter dateFromString:@"2015-04-01T00:00:00-05:00"]; + NSString *formattedDateString = [dateFormatter stringFromDate:date]; + + NSURL *someUrl = [NSURL URLWithString:@"https://branch.io"]; + NSDictionary *dataDict = @{ + @"foo": @"bar", + @"num": @1, + @"array": @[ @"array", @"items" ], + @"dict": @{ @"sub": @1 }, + @"url": someUrl, + @"date": date + }; + NSString *expectedEncodedString = [NSString stringWithFormat: + @"{\"foo\":\"bar\",\"num\":1,\"array\":[\"array\",\"items\"],\"dict\":{\"sub\":1},\"url\":\"https://branch.io\",\"date\":\"%@\"}", + formattedDateString]; + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeDictionaryToJsonStringWithUnexpectedParams { + NSObject *arbitraryObj = [[NSObject alloc] init]; + NSDictionary *dataDict = @{ @"foo": @"bar", @"random": arbitraryObj }; + NSString *expectedEncodedString = @"{\"foo\":\"bar\"}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeDictionaryToJsonStringStringWithNull { + NSDictionary *dataDict = @{ @"foo": [NSNull null] }; + NSString *expectedEncodedString = @"{\"foo\":null}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodingNilDictionaryToJsonString { + NSDictionary *dataDict = nil; + NSString *expectedEncodedString = @"{}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeDictionaryToJsonStringWithNoKeys { + NSDictionary *emptyDict = @{ }; + NSString *expectedEncodedString = @"{}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:emptyDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeDictionaryToJsonStringWithQuotes { + NSDictionary *dictionaryWithQuotes = @{ @"my\"cool\"key": @"my\"cool\"value" }; + NSString *expectedEncodedString = @"{\"my\\\"cool\\\"key\":\"my\\\"cool\\\"value\"}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dictionaryWithQuotes]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testSimpleEncodeDictionaryToJsonData { + NSDictionary *dataDict = @{ @"foo": @"bar" }; + NSData *expectedEncodedData = [@"{\"foo\":\"bar\"}" dataUsingEncoding:NSUTF8StringEncoding]; + + NSData *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonData:dataDict]; + + XCTAssertEqualObjects(expectedEncodedData, encodedValue); +} + +- (void)testEncodeDictionaryToQueryString { + NSDictionary *dataDict = @{ @"foo": @"bar", @"something": @"something & something" }; + NSString *expectedEncodedString = @"?foo=bar&something=something%20%26%20something"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToQueryString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + + +#pragma mark - EncodeArrayToJsonString + +- (void)testEncodeArrayToJsonStringWithExpectedParams { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; + NSDate *date = [dateFormatter dateFromString:@"2015-04-01T00:00:00Z"]; + NSString *formattedDateString = [dateFormatter stringFromDate:date]; + + NSURL *someUrl = [NSURL URLWithString:@"https://branch.io"]; + NSArray *dataArray = @[ @"bar", @1, @[ @"array", @"items" ], @{ @"sub": @1 }, someUrl, date ]; + NSString *expectedEncodedString = [NSString stringWithFormat:@"[\"bar\",1,[\"array\",\"items\"],{\"sub\":1},\"https://branch.io\",\"%@\"]", formattedDateString]; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:dataArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeArrayToJsonStringWithUnexpectedParams { + NSObject *arbitraryObj = [[NSObject alloc] init]; + NSArray *dataArray = @[ @"bar", arbitraryObj ]; + NSString *expectedEncodedString = @"[\"bar\"]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:dataArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeArrayToJsonStringStringWithNull { + NSArray *dataArray = @[ [NSNull null] ]; + NSString *expectedEncodedString = @"[null]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:dataArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeArrayToJsonStringWithNoValues { + NSArray *emptyArray = @[ ]; + NSString *expectedEncodedString = @"[]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:emptyArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodingEmptyArrayToJsonString { + NSArray *emptyArray = nil; + NSString *expectedEncodedString = @"[]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:emptyArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeArrayToJsonStringWithQuotes { + NSArray *arrayWithQuotes = @[ @"my\"cool\"value1", @"my\"cool\"value2" ]; + NSString *expectedEncodedString = @"[\"my\\\"cool\\\"value1\",\"my\\\"cool\\\"value2\"]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:arrayWithQuotes]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + + +#pragma mark - Character Length tests + +- (void)testChineseCharactersWithLengthGreaterThanOne { + NSString *multiCharacterString = @"𥑮"; + NSDictionary *jsonDict = @{ @"foo": multiCharacterString }; + NSString *expectedEncoding = @"{\"foo\":\"𥑮\"}"; + NSInteger expectedLength = [expectedEncoding lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + + NSData *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonData:jsonDict]; + + XCTAssertEqual(expectedLength, [encodedValue length]); +} + + +#pragma mark - DecodeToDictionary tests + +- (void)testDecodeJsonDataToDictionary { + NSData *encodedData = [@"{\"foo\":\"bar\"}" dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *expectedDataDict = @{ @"foo": @"bar" }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonDataToDictionary:encodedData]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +- (void)testDecodeJsonStringToDictionary { + NSString *encodedString = @"{\"foo\":\"bar\"}"; + NSDictionary *expectedDataDict = @{ @"foo": @"bar" }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:encodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#if 0 + +// From Ed: See note below +- (void)testDecodeJsonStringToDictionaryWithNilDecodedString { + char badCStr[5] = { '{', 'f', ':', 'o', '}' }; // not nil terminated + NSString *encodedString = [NSString stringWithUTF8String:badCStr]; + NSDictionary *expectedDataDict = @{ }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:encodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#else + +- (void)testDecodeJsonStringToDictionaryWithNilDecodedString { + NSString *encodedString = nil; + NSDictionary *expectedDataDict = @{ }; + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:encodedString]; + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#endif + +- (void)testDecodeBase64EncodedJsonStringToDictionary { + NSString *encodedString = [BNCEncodingUtils base64EncodeStringToString:@"{\"foo\":\"bar\"}"]; + NSDictionary *expectedDataDict = @{ @"foo": @"bar" }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:encodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +- (void)testDecodeNonASCIIString { + // Should fail, but not crash. + NSString* result = [BNCEncodingUtils base64DecodeStringToString:@"𝄞"]; + XCTAssertNil(result); +} + +#if 0 + +// From Ed: I don't get the point of this test. +// It reads memory from the stack as a C string and decodes it as an NSString? +// The test itself won't run consistently and may fault sometimes. +- (void)testDecodeBase64JsonStringToDictionaryWithNilDecodedString { + char badCStr[5] = { '{', 'f', ':', 'o', '}' }; // not nil terminated + NSString *encodedString = [NSString stringWithUTF8String:badCStr]; + NSString *base64EncodedString = [BNCEncodingUtils base64EncodeStringToString:encodedString]; + NSDictionary *expectedDataDict = @{ }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:base64EncodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#else + +// This should do the same thing without faulting during the test. +- (void)testDecodeBase64JsonStringToDictionaryWithNilDecodedString { + NSString *base64EncodedString = nil; + NSDictionary *expectedDataDict = @{ }; + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:base64EncodedString]; + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#endif + +- (void)testDecodeQueryStringToDictionary { + NSString *encodedString = @"foo=bar&baz=1&quux=&quo=Hi%20there"; + NSDictionary *expectedDataDict = @{ @"foo": @"bar", @"baz": @"1", @"quo": @"Hi there" }; // always goes to string + + NSDictionary *decodedValue = [BNCEncodingUtils decodeQueryStringToDictionary:encodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#pragma mark - Test Util methods + +- (NSString *)stringForDate:(NSDate *)date { + static NSDateFormatter *dateFormatter = nil; + static dispatch_once_t onceToken = 0; + + dispatch_once(&onceToken, ^{ + dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; // POSIX to avoid weird issues + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; + }); + + return [dateFormatter stringFromDate:date]; +} + +#pragma mark - Base64EncodeData Tests + +#define _countof(array) (sizeof(array)/sizeof(array[0])) + +- (void)testBase64EncodeData { + NSData *data = nil; + NSString *truth = nil; + NSString *string = nil; + + string = [BNCEncodingUtils base64EncodeData:nil]; + XCTAssertEqualObjects(string, @""); + + string = [BNCEncodingUtils base64EncodeData:[NSData new]]; + XCTAssertEqualObjects(string, @""); + + uint8_t b1[] = {0, 1, 2, 3, 4, 5}; + data = [[NSData alloc] initWithBytes:b1 length:_countof(b1)]; + truth = @"AAECAwQF"; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + // Test that 1, 2, 3, 4, 5 length data encode correctly. + + data = [[NSData alloc] initWithBytes:b1 length:1]; + truth = @"AA=="; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + data = [[NSData alloc] initWithBytes:b1 length:2]; + truth = @"AAE="; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + data = [[NSData alloc] initWithBytes:b1 length:3]; + truth = @"AAEC"; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + data = [[NSData alloc] initWithBytes:b1 length:4]; + truth = @"AAECAw=="; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + data = [[NSData alloc] initWithBytes:b1 length:5]; + truth = @"AAECAwQ="; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + uint8_t b2[] = { + 0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8B, 0x30, 0xD3, 0x8F, 0x41, 0x14, 0x93, 0x51, + 0x55, 0x97, 0x61, 0x96, 0x9B, 0x71, 0xD7, 0x9F, 0x82, 0x18, 0xA3, 0x92, 0x59, 0xA7, 0xA2, 0x9A, + 0xAB, 0xB2, 0xDB, 0xAF, 0xC3, 0x1C, 0xB3, 0xD3, 0x5D, 0xB7, 0xE3, 0x9E, 0xBB, 0xF3, 0xDF, 0xBF, + }; + data = [[NSData alloc] initWithBytes:b2 length:_countof(b2)]; + truth = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); +} + +- (void)testBase64DecodeString { + NSData *data = nil; + + data = [BNCEncodingUtils base64DecodeString:nil]; + XCTAssertEqual(data, nil); + + data = [BNCEncodingUtils base64DecodeString:@""]; + XCTAssertEqualObjects(data, [NSData new]); + + uint8_t truth[] = {0, 1, 2, 3, 4, 5}; + + data = [BNCEncodingUtils base64DecodeString:@"AAECAwQF"]; + XCTAssertTrue( data.length == 6 && memcmp(data.bytes, truth, 6) == 0 ); + + // Test that 1, 2, 3, 4, 5 length data encode correctly. + + #define testDecode(string, dataLength) { \ + data = [BNCEncodingUtils base64DecodeString:string]; \ + XCTAssertTrue( data.length == dataLength && memcmp(data.bytes, truth, dataLength) == 0 ); \ + } + + testDecode(@"AA==", 1); + testDecode(@"AAE=", 2); + testDecode(@"AAEC", 3); + testDecode(@"AAECAw==", 4); + testDecode(@"AAECAwQ=", 5); + + uint8_t b2[] = { + 0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8B, 0x30, 0xD3, 0x8F, 0x41, 0x14, 0x93, 0x51, + 0x55, 0x97, 0x61, 0x96, 0x9B, 0x71, 0xD7, 0x9F, 0x82, 0x18, 0xA3, 0x92, 0x59, 0xA7, 0xA2, 0x9A, + 0xAB, 0xB2, 0xDB, 0xAF, 0xC3, 0x1C, 0xB3, 0xD3, 0x5D, 0xB7, 0xE3, 0x9E, 0xBB, 0xF3, 0xDF, 0xBF, + }; + data = [BNCEncodingUtils base64DecodeString: + @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"]; + XCTAssertTrue( data.length == _countof(b2) && memcmp(data.bytes, b2, _countof(b2)) == 0 ); + + // Test decode invalid data + data = [BNCEncodingUtils base64DecodeString: + @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde (Junk:%&*^**) fghijklmnopqrstuvwxyz0123456789+/"]; + XCTAssertEqual(data, nil); +} + +#pragma mark - Hex String Tests + +- (void) testHexStringFromData { + + NSString *s = nil; + + s = [BNCEncodingUtils hexStringFromData:[NSData data]]; + XCTAssertEqualObjects(s, @""); + + unsigned char bytes1[] = { 0x01 }; + s = [BNCEncodingUtils hexStringFromData:[NSData dataWithBytes:bytes1 length:1]]; + XCTAssertEqualObjects(s, @"01"); + + unsigned char bytes2[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef + }; + NSString *truth = + @"000102030405060708090A0B0C0D0E0F" + "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"; + + s = [BNCEncodingUtils hexStringFromData:[NSData dataWithBytes:bytes2 length:sizeof(bytes2)]]; + XCTAssertEqualObjects(s, truth); +} + +- (void) testDataFromHexString { + + NSData *data = nil; + + // nil + data = [BNCEncodingUtils dataFromHexString:nil]; + XCTAssertEqual(data, nil); + + // empty string + data = [BNCEncodingUtils dataFromHexString:@""]; + XCTAssertEqualObjects(data, [NSData data]); + + // upper string + unsigned char bytes[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef + }; + + NSString *stringUpper = + @"000102030405060708090A0B0C0D0E0F" + "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"; + + data = [BNCEncodingUtils dataFromHexString:stringUpper]; + XCTAssertEqualObjects(data, [NSData dataWithBytes:bytes length:sizeof(bytes)]); + + // lower string + + NSString *stringLower = + @"000102030405060708090a0b0c0d0e0f" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"; + + data = [BNCEncodingUtils dataFromHexString:stringLower]; + XCTAssertEqualObjects(data, [NSData dataWithBytes:bytes length:sizeof(bytes)]); + + // white space + + NSString *stringWS = + @" 000102030405060708090a0b0c0d0e0f\n" + "e0e1e2e3e4e5e6\t\t\te7e8e9eaebeced\vee\ref"; + + data = [BNCEncodingUtils dataFromHexString:stringWS]; + XCTAssertEqualObjects(data, [NSData dataWithBytes:bytes length:sizeof(bytes)]); + + // odd number of charaters + + NSString *stringShort = + @"000102030405060708090a0b0c0d0e0f" + "e0e1e2e3e4e5e6e7e8e9eaebecedeee"; + + data = [BNCEncodingUtils dataFromHexString:stringShort]; + XCTAssertEqual(data, nil); + + // invalid characters + + NSString *stringInvalid = + @"000102030405060708090a0b0c0d0e0fInvalid" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"; + + data = [BNCEncodingUtils dataFromHexString:stringInvalid]; + XCTAssertEqual(data, nil); + + // singles + + NSString *stringShortShort1 = @"A"; + data = [BNCEncodingUtils dataFromHexString:stringShortShort1]; + XCTAssertEqual(data, nil); + + NSString *stringShortShort2 = @"af"; + unsigned char stringShortShort2Bytes[] = { 0xaf }; + data = [BNCEncodingUtils dataFromHexString:stringShortShort2]; + XCTAssertEqualObjects(data, [NSData dataWithBytes:stringShortShort2Bytes length:1]); +} + +- (void) testPercentDecoding { + + NSString *s = nil; + s = [BNCEncodingUtils stringByPercentDecodingString:nil]; + XCTAssert(s == nil); + + NSArray* tests = @[ + @"", + @"", + + @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + + @"-._~", + @"-._~", + + @"one%20two", + @"one two", + + // @"one+two", + // @"one two", + + @"one%2Btwo", + @"one+two", + + @"%21%23%24%26%27%28%29%2A%2B%2C%3A%3B%3D%40%5B%5D", + @"!#$&'()*+,:;=@[]", + ]; + + for (int i = 0; i < tests.count; i+=2) { + NSString *result = [BNCEncodingUtils stringByPercentDecodingString:tests[i]]; + XCTAssertEqualObjects(result, tests[i+1]); + } +} + +- (void) testQueryItems { + + NSURL *URL = nil; + NSArray* items = nil; + NSArray* expected = nil; + + items = [BNCEncodingUtils queryItems:URL]; + XCTAssert(items != nil && items.count == 0); + + URL = [NSURL URLWithString:@"http://example.com/thus?a=1&a=2&b=3"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@"1"], [BNCKeyValue key:@"a" value:@"2"], [BNCKeyValue key:@"b" value:@"3"] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?="]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?a="]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@""] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?=1"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"" value:@"1"] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?a=1&"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@"1"] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?a=1&&b=2"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@"1"], [BNCKeyValue key:@"b" value:@"2"] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?a=1&b==2"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@"1"], [BNCKeyValue key:@"b" value:@"=2"] ]; + XCTAssertEqualObjects(items, expected); +} + +- (void) testSanitzeString { + NSString*test = @"\b\f\n\r\t\"`\\"; + NSString*truth = @"\\b\\f\\n\\r\\t\\\"'\\\\"; + NSString*result = [BNCEncodingUtils sanitizedStringFromString:test]; + XCTAssertEqualObjects(result, truth); +} + +// Branch servers never return a json array at the top level. However, our parser should enforce it. +- (void)testArrayJSON { + NSString *test = @"[\"helloworld\"]"; + NSDictionary *tmp = [BNCEncodingUtils decodeJsonStringToDictionary:test]; + XCTAssert([tmp isKindOfClass:[NSDictionary class]]); +} + +@end diff --git a/BranchSDKTests/BNCJSONUtilityTests.m b/BranchSDKTests/BNCJSONUtilityTests.m new file mode 100644 index 000000000..7f5f1c1cf --- /dev/null +++ b/BranchSDKTests/BNCJSONUtilityTests.m @@ -0,0 +1,188 @@ +// +// BNCJSONUtilityTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 9/17/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCJSONUtility.h" +#import "BNCJsonLoader.h" + +@interface BNCJSONUtilityTests : XCTestCase +@property (nonatomic, strong, readwrite) NSDictionary *json; +@end + +@implementation BNCJSONUtilityTests + +- (void)setUp { + self.json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"example"]; + XCTAssertNotNil(self.json); +} + +- (void)tearDown { + +} + +- (void)testIsNumber { + NSNumber *number = [NSNumber numberWithInt:314]; + XCTAssertTrue([BNCJSONUtility isNumber:number]); +} + +- (void)testIsNumber_Boxed { + XCTAssertTrue([BNCJSONUtility isNumber:@(1.0)]); +} + +- (void)testIsNumber_Nil { + XCTAssertFalse([BNCJSONUtility isNumber:nil]); +} + +- (void)testIsNumber_String { + XCTAssertFalse([BNCJSONUtility isNumber:@"1.0"]); +} + +- (void)testIsString { + XCTAssertTrue([BNCJSONUtility isString:@"1.0"]); +} + +- (void)testIsString_MutableString { + NSMutableString *string = [NSMutableString new]; + XCTAssertTrue([BNCJSONUtility isString:string]); +} + +- (void)testIsString_EmptyString { + XCTAssertTrue([BNCJSONUtility isString:@""]); +} + +- (void)testIsString_Nil { + XCTAssertFalse([BNCJSONUtility isString:nil]); +} + +- (void)testIsString_Number { + XCTAssertFalse([BNCJSONUtility isString:@(1.0)]); +} + +- (void)testIsArray { + NSArray *tmp = @[@1, @2]; + XCTAssertTrue([BNCJSONUtility isArray:tmp]); +} + +- (void)testIsArray_MutableArray { + NSMutableArray *tmp = [NSMutableArray new]; + XCTAssertTrue([BNCJSONUtility isArray:tmp]); +} + +- (void)testIsArray_EmptyArray { + XCTAssertTrue([BNCJSONUtility isArray:@[]]); +} + +- (void)testIsArray_Nil { + XCTAssertFalse([BNCJSONUtility isArray:nil]); +} + +- (void)testIsArray_Dictionary { + XCTAssertFalse([BNCJSONUtility isArray:[NSDictionary new]]); +} + +// successful call on untyped dictionary +- (void)testUntypedDictionary_CorrectType { + NSString *string = self.json[@"user_string"]; + XCTAssertNotNil(string); + XCTAssertTrue(([string isKindOfClass:[NSString class]] || [string isKindOfClass:[NSMutableString class]])); +} + +// demonstrates that an untyped dictionary can lead to type mismatches cause it always returns id +- (void)testUntypedDictionary_IncorrectType { + NSString *string = self.json[@"user_number"]; + XCTAssertNotNil(string); + XCTAssertTrue(([string isKindOfClass:[NSNumber class]])); +} + +- (void)testStringForKey_InvalidKey { + id key = @(1); + NSString *string = [BNCJSONUtility stringForKey:key json:self.json]; + XCTAssertNil(string); +} + +- (void)testStringForKey { + NSString *string = [BNCJSONUtility stringForKey:@"user_string" json:self.json]; + XCTAssertNotNil(string); + XCTAssertTrue(([string isKindOfClass:[NSString class]] || [string isKindOfClass:[NSMutableString class]])); +} + +- (void)testStringForKey_IncorrectType { + NSString *string = [BNCJSONUtility stringForKey:@"user_number" json:self.json]; + XCTAssertNil(string); +} + +- (void)testNumberForKey { + NSNumber *number = [BNCJSONUtility numberForKey:@"user_number" json:self.json]; + XCTAssertNotNil(number); + XCTAssertTrue([number isKindOfClass:[NSNumber class]]); +} + +- (void)testNumberForKey_IncorrectType { + NSNumber *number = [BNCJSONUtility numberForKey:@"user_string" json:self.json]; + XCTAssertNil(number); +} + +- (void)testDictionaryForKey { + NSDictionary *dict = [BNCJSONUtility dictionaryForKey:@"user_dict" json:self.json]; + XCTAssertNotNil(dict); + XCTAssertTrue(([dict isKindOfClass:NSDictionary.class] || [dict isKindOfClass:NSMutableDictionary.class])); +} + +- (void)testDictionaryForKey_IncorrectType { + NSDictionary *dict = [BNCJSONUtility dictionaryForKey:@"user_array" json:self.json]; + XCTAssertNil(dict); +} + +- (void)testArrayForKey { + NSArray *array = [BNCJSONUtility arrayForKey:@"user_array" json:self.json]; + XCTAssertNotNil(array); + XCTAssertTrue(([array isKindOfClass:[NSArray class]] || [array isKindOfClass:[NSMutableArray class]])); +} + +- (void)testArrayForKey_IncorrectType { + NSArray *array = [BNCJSONUtility arrayForKey:@"user_dict" json:self.json]; + XCTAssertNil(array); +} + +- (void)testStringArrayForKey { + NSArray *array = [BNCJSONUtility stringArrayForKey:@"user_array" json:self.json]; + XCTAssertNotNil(array); + XCTAssertTrue(array.count > 0); +} + +- (void)testStringArrayForKey_MixedTypes { + NSArray *array = [BNCJSONUtility stringArrayForKey:@"user_array_mixed" json:self.json]; + XCTAssertNotNil(array); + XCTAssertTrue(array.count > 0); +} + +- (void)testStringArrayForKey_Numbers { + NSArray *array = [BNCJSONUtility stringArrayForKey:@"user_array_numbers" json:self.json]; + XCTAssertNotNil(array); + XCTAssertTrue(array.count == 0); +} + +- (void)testStringDictionaryForKey { + NSDictionary *dict = [BNCJSONUtility stringDictionaryForKey:@"user_dict" json:self.json]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.count > 0); +} + +- (void)testStringDictionaryForKey_MixedTypes { + NSDictionary *dict = [BNCJSONUtility stringDictionaryForKey:@"user_dict_mixed" json:self.json]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.count > 0); +} + +- (void)testStringDictionaryForKey_Numbers { + NSDictionary *dict = [BNCJSONUtility stringDictionaryForKey:@"user_dict_numbers" json:self.json]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.count == 0); +} + +@end diff --git a/BranchSDKTests/BNCJsonLoader.h b/BranchSDKTests/BNCJsonLoader.h new file mode 100644 index 000000000..6df022300 --- /dev/null +++ b/BranchSDKTests/BNCJsonLoader.h @@ -0,0 +1,20 @@ +// +// BNCJsonLoader.h +// Branch-TestBed +// +// Created by Ernest Cho on 9/16/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BNCJsonLoader : NSObject + +// test utility that loads json files from the Test Bundle. only works on hosted tests ++ (NSDictionary *)dictionaryFromJSONFileNamed:(NSString *)fileName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/BranchSDKTests/BNCJsonLoader.m b/BranchSDKTests/BNCJsonLoader.m new file mode 100644 index 000000000..098798ba8 --- /dev/null +++ b/BranchSDKTests/BNCJsonLoader.m @@ -0,0 +1,27 @@ +// +// BNCJsonLoader.m +// Branch-TestBed +// +// Created by Ernest Cho on 9/16/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import "BNCJsonLoader.h" + +@implementation BNCJsonLoader + ++ (NSDictionary *)dictionaryFromJSONFileNamed:(NSString *)fileName { + + // Since this class is part of the Test target, [self class] returns the Test Bundle + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:fileName ofType:@"json"]; + + NSString *jsonString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; + + id dict = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; + if ([dict isKindOfClass:NSDictionary.class]) { + return dict; + } + return nil; +} + +@end diff --git a/BranchSDKTests/BNCKeyChainTests.m b/BranchSDKTests/BNCKeyChainTests.m new file mode 100644 index 000000000..07af91a22 --- /dev/null +++ b/BranchSDKTests/BNCKeyChainTests.m @@ -0,0 +1,121 @@ +// +// BNCKeyChainTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 1/6/22. +// Copyright © 2022 Branch, Inc. All rights reserved. +// + +#import +#import "BNCKeyChain.h" + +@interface BNCKeyChainTests : XCTestCase +@property (nonatomic, copy, readwrite) NSString *serviceName; +@end + +@implementation BNCKeyChainTests + +- (void)setUp { + self.serviceName = @"Service"; +} + +- (void)tearDown { + +} + +- (void)testEnvironment { + // Keychain tests must be hosted in an app, otherwise it won't have security access. + XCTAssertFalse([UIApplication sharedApplication] == nil); + + NSString *group = [BNCKeyChain securityAccessGroup]; + XCTAssertTrue(group.length > 0); +} + +- (void)testRemoveValues_Empty { + NSError *error = [BNCKeyChain removeValuesForService:nil key:nil]; + XCTAssertTrue(error == nil); +} + +- (void)testRetrieveDate_Empty { + NSError *error; + NSDate *date = [BNCKeyChain retrieveDateForService:self.serviceName key:@"testKey" error:&error]; + XCTAssertTrue(date == nil && error.code == errSecItemNotFound); +} + +- (void)testStoreAndRetrieveDate { + NSError *error; + NSString *key = @"testKey"; + NSDate *date = [NSDate date]; + + [BNCKeyChain storeDate:date forService:self.serviceName key:key cloudAccessGroup:nil]; + NSDate *tmp = [BNCKeyChain retrieveDateForService:self.serviceName key:key error:&error]; + XCTAssertNil(error); + XCTAssertTrue([date isEqualToDate:tmp]); + + // cleanup + error = [BNCKeyChain removeValuesForService:self.serviceName key:key]; + XCTAssertNil(error); +} + +- (void)testStore_Nil { + NSError *error; + NSString *key = @"testKey"; + NSDate *date = nil; + + error = [BNCKeyChain storeDate:date forService:self.serviceName key:key cloudAccessGroup:nil]; + XCTAssertTrue(error.code == errSecParam); + + NSDate *tmp = [BNCKeyChain retrieveDateForService:self.serviceName key:key error:&error]; + XCTAssertNil(tmp); + XCTAssertTrue(error.code == errSecItemNotFound); +} + +- (void)testStoreAndRetrieveMultipleDates { + NSError *error; + NSString *keyA = @"testKeyA"; + NSString *keyB = @"testKeyB"; + + NSDate *dateA = [NSDate date]; + NSDate *dateB = [NSDate dateWithTimeIntervalSinceNow:1]; + XCTAssertFalse([dateA isEqualToDate:dateB]); + + [BNCKeyChain storeDate:dateA forService:self.serviceName key:keyA cloudAccessGroup:nil]; + [BNCKeyChain storeDate:dateB forService:self.serviceName key:keyB cloudAccessGroup:nil]; + + NSDate *tmpA = [BNCKeyChain retrieveDateForService:self.serviceName key:keyA error:&error]; + XCTAssertNil(error); + XCTAssertTrue([dateA isEqualToDate:tmpA]); + + NSDate *tmpB = [BNCKeyChain retrieveDateForService:self.serviceName key:keyB error:&error]; + XCTAssertNil(error); + XCTAssertTrue([dateB isEqualToDate:tmpB]); + + XCTAssertFalse([tmpA isEqualToDate:tmpB]); + + // cleanup + error = [BNCKeyChain removeValuesForService:self.serviceName key:keyA]; + XCTAssertNil(error); + error = [BNCKeyChain removeValuesForService:self.serviceName key:keyB]; + XCTAssertNil(error); +} + +- (void)testStoreAndRetrieveDate_retrieveWrongKey { + NSError *error; + NSString *keyA = @"testKeyA"; + NSString *keyB = @"testKeyB"; + NSDate *date = [NSDate date]; + + [BNCKeyChain storeDate:date forService:self.serviceName key:keyA cloudAccessGroup:nil]; + NSDate *tmp = [BNCKeyChain retrieveDateForService:self.serviceName key:keyB error:&error]; + XCTAssertNil(tmp); + XCTAssertTrue(error.code == errSecItemNotFound); + + // cleanup + error = [BNCKeyChain removeValuesForService:self.serviceName key:keyA]; + XCTAssertNil(error); + error = [BNCKeyChain removeValuesForService:self.serviceName key:keyB]; + XCTAssertNil(error); +} + + +@end diff --git a/BranchSDKTests/BNCLinkDataTests.m b/BranchSDKTests/BNCLinkDataTests.m new file mode 100644 index 000000000..10eb3cb25 --- /dev/null +++ b/BranchSDKTests/BNCLinkDataTests.m @@ -0,0 +1,103 @@ +// +// BNCLinkDataTests.m +// Branch-TestBed +// +// Created by Graham Mueller on 6/15/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import +#import "BNCLinkData.h" + +@interface BNCLinkDataTests : XCTestCase +@end + +@implementation BNCLinkDataTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testBasicObjectHash { + BNCLinkData *a = [[BNCLinkData alloc] init]; + BNCLinkData *b = [[BNCLinkData alloc] init]; + + XCTAssertEqual([a hash], [b hash]); +} + +- (void)testObjectHashWithSameValuesForKeys { + NSArray * const TAGS = @[ @"foo-tag" ]; + NSString * const ALIAS = @"foo-alias"; + BranchLinkType const LINK_TYPE = BranchLinkTypeOneTimeUse; + NSString * const CHANNEL = @"foo-channel"; + NSString * const FEATURE = @"foo-feature"; + NSString * const STAGE = @"foo-stage"; + NSDictionary * const PARAMS = @{ @"foo-key": @"foo-value" }; + NSInteger const DURATION = 1; + NSString * const IGNORE_UA = @"foo-ua"; + + BNCLinkData *a = [[BNCLinkData alloc] init]; + [a setupTags:TAGS]; + [a setupAlias:ALIAS]; + [a setupType:LINK_TYPE]; + [a setupChannel:CHANNEL]; + [a setupFeature:FEATURE]; + [a setupStage:STAGE]; + [a setupParams:PARAMS]; + [a setupMatchDuration:DURATION]; + [a setupIgnoreUAString:IGNORE_UA]; + + BNCLinkData *b = [[BNCLinkData alloc] init]; + [b setupTags:TAGS]; + [b setupAlias:ALIAS]; + [b setupType:LINK_TYPE]; + [b setupChannel:CHANNEL]; + [b setupFeature:FEATURE]; + [b setupStage:STAGE]; + [b setupParams:PARAMS]; + [b setupMatchDuration:DURATION]; + [b setupIgnoreUAString:IGNORE_UA]; + + XCTAssertEqual([a hash], [b hash]); +} + +- (void)testObjectHashWithDifferentValuesForSameKeys { + BNCLinkData *a = [[BNCLinkData alloc] init]; + [a setupTags:@[ @"foo-tags" ]]; + [a setupAlias:@"foo-alias"]; + [a setupType:BranchLinkTypeOneTimeUse]; + [a setupChannel:@"foo-channel"]; + [a setupFeature:@"foo-feature"]; + [a setupStage:@"foo-stage"]; + [a setupParams:@{ @"foo-key": @"foo-value" }]; + [a setupMatchDuration:1]; + [a setupIgnoreUAString:@"foo-ua"]; + + BNCLinkData *b = [[BNCLinkData alloc] init]; + [b setupTags:@[ @"bar-tag" ]]; + [b setupAlias:@"bar-alias"]; + [b setupType:BranchLinkTypeUnlimitedUse]; + [b setupChannel:@"bar-channel"]; + [b setupFeature:@"bar-feature"]; + [b setupStage:@"bar-stage"]; + [b setupParams:@{ @"bar-key": @"bar-value" }]; + [b setupMatchDuration:2]; + [b setupIgnoreUAString:@"bar-ua"]; + + XCTAssertNotEqual([a hash], [b hash]); +} + +- (void)testObjectHashWithDifferentCasedValues { + BNCLinkData *a = [[BNCLinkData alloc] init]; + [a setupAlias:@"foo-alias"]; + BNCLinkData *b = [[BNCLinkData alloc] init]; + [b setupAlias:@"FOO-ALIAS"]; + + XCTAssertNotEqual([a hash], [b hash]); +} + +@end diff --git a/BranchSDKTests/BNCNetworkInterfaceTests.m b/BranchSDKTests/BNCNetworkInterfaceTests.m new file mode 100644 index 000000000..8869ecc37 --- /dev/null +++ b/BranchSDKTests/BNCNetworkInterfaceTests.m @@ -0,0 +1,82 @@ +// +// BNCNetworkInterfaceTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 3/10/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import +#import "BNCNetworkInterface.h" + +// Category using inet_pton to validate +@implementation NSString (Test) + +- (BOOL)isValidIPAddress { + const char *utf8 = [self UTF8String]; + int success; + + struct in_addr dst; + success = inet_pton(AF_INET, utf8, &dst); + if (success != 1) { + struct in6_addr dst6; + success = inet_pton(AF_INET6, utf8, &dst6); + } + + return success == 1; +} + +@end + +@interface BNCNetworkInterfaceTests : XCTestCase + +@end + +@implementation BNCNetworkInterfaceTests + +- (void)setUp { + +} + +- (void)tearDown { + +} + +// verify tooling method works +- (void)testIPValidationCategory { + XCTAssert(![@"" isValidIPAddress]); + + // ipv4 + XCTAssert([@"0.0.0.0" isValidIPAddress]); + XCTAssert([@"127.0.0.1" isValidIPAddress]); + XCTAssert([@"10.1.2.3" isValidIPAddress]); + XCTAssert([@"172.0.0.0" isValidIPAddress]); + XCTAssert([@"192.0.0.0" isValidIPAddress]); + XCTAssert([@"255.255.255.255" isValidIPAddress]); + + // invalid ipv4 + XCTAssert(![@"-1.0.0.0" isValidIPAddress]); + XCTAssert(![@"256.0.0.0" isValidIPAddress]); + + // ipv6 + XCTAssert([@"2001:0db8:0000:0000:0000:8a2e:0370:7334" isValidIPAddress]); + XCTAssert([@"2001:db8::8a2e:370:7334" isValidIPAddress]); + + // invalid ipv6 + XCTAssert(![@"2001:0db8:0000:0000:0000:8a2e:0370:733g" isValidIPAddress]); + XCTAssert(![@"2001:0db8:0000:0000:0000:8a2e:0370:7330:1234" isValidIPAddress]); +} + +- (void)testLocalIPAddress { + XCTAssert([[BNCNetworkInterface localIPAddress] isValidIPAddress]); +} + +- (void)testAllIPAddresses { + // All IP addresses is a debug method that returns object descriptions + for (NSString *address in BNCNetworkInterface.allIPAddresses) { + XCTAssert([address containsString:@"BNCNetworkInterface"]); + } +} + +@end diff --git a/BranchSDKTests/BNCODMTests.m b/BranchSDKTests/BNCODMTests.m new file mode 100644 index 000000000..38d1b0cc2 --- /dev/null +++ b/BranchSDKTests/BNCODMTests.m @@ -0,0 +1,102 @@ +// +// BNCODMTests.m +// Branch-SDK-Tests +// +// Created by Nidhi Dixit on 4/16/25. +// Copyright © 2025 Branch, Inc. All rights reserved. +// + +#import +#import "Branch.h" +#import "BNCPreferenceHelper.h" +#import "BNCRequestFactory.h" +#import "BNCEncodingUtils.h" +#import "BNCODMInfoCollector.h" +#import "NSError+Branch.h" + +@interface BNCODMTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCPreferenceHelper *prefHelper; +@end + +@implementation BNCODMTests + +- (void)setUp { + _prefHelper = [BNCPreferenceHelper sharedInstance]; +} + +- (void)testSetODM { + NSString *odm = @"testODMString"; + NSDate *firstOpenTS = [NSDate date]; + [Branch setODMInfo:odm andFirstOpenTimestamp:firstOpenTS]; + XCTAssertTrue([_prefHelper.odmInfo isEqualToString:odm]); + XCTAssertTrue([_prefHelper.odmInfoInitDate isEqualToDate:firstOpenTS]); + +} + +- (void)testSetODMandSDKRequests { + NSString* requestUUID = [[NSUUID UUID ] UUIDString]; + NSNumber* requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); + NSString *odm = @"testODMString"; + NSDate *firstOpenTS = [NSDate date]; + + [Branch setODMInfo:odm andFirstOpenTimestamp:firstOpenTS]; + + [[Branch getInstance] setConsumerProtectionAttributionLevel:BranchAttributionLevelFull]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:requestUUID TimeStamp:requestCreationTimeStamp]; + NSDictionary *jsonInstall = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertTrue([odm isEqualToString:[jsonInstall objectForKey:@"odm_info"]]); + + NSDictionary *jsonOpen = [factory dataForOpenWithURLString:@"https://branch.io"]; + XCTAssertTrue([odm isEqualToString:[jsonOpen objectForKey:@"odm_info"]]); + + NSDictionary *event = @{@"name": @"ADD_TO_CART"}; + NSDictionary *jsonEvent = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertTrue([jsonEvent objectForKey:@"odm_info"] == nil); + + [[Branch getInstance] setConsumerProtectionAttributionLevel:BranchAttributionLevelReduced]; + jsonInstall = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertTrue([jsonInstall objectForKey:@"odm_info"] == nil); + + jsonOpen = [factory dataForOpenWithURLString:@"https://branch.io"]; + XCTAssertTrue([jsonOpen objectForKey:@"odm_info"] == nil); + + self.prefHelper.odmInfo = nil; + self.prefHelper.odmInfoInitDate = nil; +} + +- (void)testODMTimeOut { + + NSString* requestUUID = [[NSUUID UUID ] UUIDString]; + NSNumber* requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); + NSString *odm = @"testODMString"; + NSDate *firstOpenTS = [[NSDate date] dateByAddingTimeInterval:-((180*24*3600) - 5)]; + + [Branch setODMInfo:odm andFirstOpenTimestamp:firstOpenTS]; + + [[Branch getInstance] setConsumerProtectionAttributionLevel:BranchAttributionLevelFull]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:requestUUID TimeStamp:requestCreationTimeStamp]; + NSDictionary *jsonInstall = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertTrue([odm isEqualToString:[jsonInstall objectForKey:@"odm_info"]]); + + sleep(10); + + NSDictionary *jsonOpen = [factory dataForOpenWithURLString:@"https://branch.io"]; + XCTAssertTrue(![odm isEqualToString:[jsonOpen objectForKey:@"odm_info"]]); + + self.prefHelper.odmInfo = nil; + self.prefHelper.odmInfoInitDate = nil; + +} + + +- (void) testODMAPIsNotLoaded { + XCTestExpectation *expectation = [self expectationWithDescription:@"Check if ODCManager class is loaded."]; + [[BNCODMInfoCollector instance ] loadODMInfoWithTimeOut:DISPATCH_TIME_FOREVER andCompletionHandler:^(NSString * _Nullable odmInfo, NSError * _Nullable error) { + if (error.code == BNCClassNotFoundError){ + [expectation fulfill]; + } + }]; + [self waitForExpectationsWithTimeout:15 handler:nil]; +} + +@end diff --git a/BranchSDKTests/BNCPartnerParametersTests.m b/BranchSDKTests/BNCPartnerParametersTests.m new file mode 100644 index 000000000..7fad38ac2 --- /dev/null +++ b/BranchSDKTests/BNCPartnerParametersTests.m @@ -0,0 +1,219 @@ +// +// BNCPartnerParametersTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 12/9/20. +// Copyright © 2020 Branch, Inc. All rights reserved. +// + +#import +#import "BNCPartnerParameters.h" + +// expose private methods for testing +@interface BNCPartnerParameters() +- (BOOL)sha256HashSanityCheckValue:(NSString *)value; +- (BOOL)isStringHex:(NSString *)string; +@end + +@interface BNCPartnerParametersTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCPartnerParameters *partnerParams; +@end + +@implementation BNCPartnerParametersTests + +- (void)setUp { + self.partnerParams = [BNCPartnerParameters new]; +} + +- (void)tearDown { + +} + +- (void)testStringHexNil { + XCTAssertFalse([self.partnerParams isStringHex:nil]); +} + +- (void)testStringHexEmpty { + XCTAssertTrue([self.partnerParams isStringHex:@""]); +} + +- (void)testStringHexDash { + XCTAssertFalse([self.partnerParams isStringHex:@"-1"]); +} + +- (void)testStringHexDecimal { + XCTAssertFalse([self.partnerParams isStringHex:@"1.0"]); +} + +- (void)testStringHexFraction { + XCTAssertFalse([self.partnerParams isStringHex:@"2/4"]); +} + +- (void)testStringHexAt { + XCTAssertFalse([self.partnerParams isStringHex:@"test@12345"]); +} + +- (void)testStringHexUpperG { + XCTAssertFalse([self.partnerParams isStringHex:@"0123456789ABCDEFG"]); +} + +- (void)testStringHexLowerG { + XCTAssertFalse([self.partnerParams isStringHex:@"0123456789abcdefg"]); +} + +- (void)testStringHexUpperCase { + XCTAssertTrue([self.partnerParams isStringHex:@"0123456789ABCDEF"]); +} + +- (void)testStringHexLowerCase { + XCTAssertTrue([self.partnerParams isStringHex:@"0123456789abcdef"]); +} + +- (void)testSha256HashSanityCheckValueNil { + XCTAssertFalse([self.partnerParams sha256HashSanityCheckValue:nil]); +} + +- (void)testSha256HashSanityCheckValueEmpty { + XCTAssertFalse([self.partnerParams sha256HashSanityCheckValue:@""]); +} + +- (void)testSha256HashSanityCheckValueTooShort { + // 63 char string + XCTAssertFalse([self.partnerParams sha256HashSanityCheckValue:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcde"]); +} + +- (void)testSha256HashSanityCheckValueTooLong { + // 65 char string + XCTAssertFalse([self.partnerParams sha256HashSanityCheckValue:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdeff"]); +} + +- (void)testSha256HashSanityCheckValueLowerCase { + // 64 char string + XCTAssertTrue([self.partnerParams sha256HashSanityCheckValue:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]); +} + +- (void)testSha256HashSanityCheckValueUpperCase { + // 64 char string + XCTAssertTrue([self.partnerParams sha256HashSanityCheckValue:@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"]); +} + +- (void)testSha256HashSanityCheckValueMixedCase { + // 64 char string + XCTAssertTrue([self.partnerParams sha256HashSanityCheckValue:@"0123456789ABCDEF0123456789ABCDEF1234567890abcdef1234567890abcdef"]); +} + +- (void)testJsonEmpty { + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterEmpty { + [self.partnerParams addFacebookParameterWithName:@"em" value:@""]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterShort { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"0123456789ABCDEF0123456789ABCDEF1234567890abcdef1234567890abcde"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterPhoneNumberIsIgnored { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"1-555-555-5555"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterEmailIsIgnored { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"test@branch.io"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterBase64EncodedIsIgnored { + // 123456789012345678901234567890123456789012345678 -> MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4 + [self.partnerParams addFacebookParameterWithName:@"em" value:@"MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterHashedValue { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{\"fb\":{\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterExample { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addFacebookParameterWithName:@"ph" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + + XCTAssertTrue([@"{\"fb\":{\"ph\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}" isEqualToString:jsonString]); +} + +- (void)testJsonSnapParameterExample { + [self.partnerParams addSnapParameterWithName:@"hashed_email_address" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addSnapParameterWithName:@"hashed_phone_number" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + + XCTAssertTrue([@"{\"snap\":{\"hashed_phone_number\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"hashed_email_address\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}" isEqualToString:jsonString]); +} + + +- (void)testJsonMultipleParameterExample { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addFacebookParameterWithName:@"ph" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + [self.partnerParams addSnapParameterWithName:@"hashed_email_address" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addSnapParameterWithName:@"hashed_phone_number" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + + NSString *expectedJsonString = @"{\"snap\":{\"hashed_phone_number\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"hashed_email_address\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"},\"fb\":{\"ph\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}"; + + XCTAssertTrue([expectedJsonString isEqualToString:jsonString]); +} + +- (void)testParameterClear { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addFacebookParameterWithName:@"ph" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + [self.partnerParams addSnapParameterWithName:@"hashed_email_address" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addSnapParameterWithName:@"hashed_phone_number" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + [self.partnerParams clearAllParameters]; + + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +// sanity check test func on an empty dictionary +- (void)testEmptyJson { + NSString *jsonString = [self jsonStringFromDictionary:@{}]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +// sanity check test func on the sample json dictionary +- (void)testSampleJson { + NSString *jsonString = [self jsonStringFromDictionary:@{ + @"fb": @{ + @"ph": @"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b", + @"em": @"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088" + } + }]; + + XCTAssertTrue([@"{\"fb\":{\"ph\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}" isEqualToString:jsonString] || [@"{\"fb\":{\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\",\"ph\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\"}}" isEqualToString:jsonString]); +} + +// There is an assumption that this code always results in the same string for the same json data. +// This appears to be true, but I haven't found documentation to confirm it. +- (NSString *)jsonStringFromDictionary:(NSDictionary *)dictionary { + NSError *error; + NSData *json = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error]; + + if (!error) { + NSString *tmp = [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding]; + return tmp; + } else { + return @""; + } +} + +@end diff --git a/BranchSDKTests/BNCPasteboardTests.m b/BranchSDKTests/BNCPasteboardTests.m new file mode 100644 index 000000000..6a3a4d69c --- /dev/null +++ b/BranchSDKTests/BNCPasteboardTests.m @@ -0,0 +1,170 @@ +// +// BNCPasteboardTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 7/19/21. +// Copyright © 2021 Branch, Inc. All rights reserved. +// + +#import +#import "BNCPasteboard.h" +#import "Branch.h" + +@interface BNCPasteboardTests : XCTestCase + +@property (nonatomic, assign, readwrite) NSString *testString; +@property (nonatomic, strong, readwrite) NSURL *testBranchURL; + +@end + +@implementation BNCPasteboardTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. + self.testString = @"Pasteboard String"; + self.testBranchURL = [NSURL URLWithString:@"https://123.app.link"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)addStringToPasteboard { +#if !TARGET_OS_TV + [UIPasteboard.generalPasteboard setString:self.testString]; +#endif +} + +- (void)addBranchURLToPasteboard { +#if !TARGET_OS_TV + [UIPasteboard.generalPasteboard setURL:self.testBranchURL]; +#endif +} + +- (void)addNonBranchURLToPasteboard { +#if !TARGET_OS_TV + [UIPasteboard.generalPasteboard setURL:[NSURL URLWithString:@"https://www.apple.com"]]; +#endif +} + +- (void)clearPasteboard { +#if !TARGET_OS_TV + // cannot delete items from the pasteboard, but we can put something else on there + [[UIPasteboard generalPasteboard] setString:@""]; +#endif +} + +- (NSString *)getStringFromClipboard { + NSString *string = nil; +#if !TARGET_OS_TV + string = [UIPasteboard.generalPasteboard string]; +#endif + return string; +} + +- (NSURL *)getURLFromPasteboard { + NSURL *url = nil; +#if !TARGET_OS_TV + url = [UIPasteboard.generalPasteboard URL]; +#endif + return url; +} + +- (void)testStringUtilityMethods { + + // set and retrieve a string + [self addStringToPasteboard]; + NSString *tmp = [self getStringFromClipboard]; + XCTAssert([self.testString isEqualToString:tmp]); + + // overwrite the pasteboard + [self clearPasteboard]; + tmp = [self getStringFromClipboard]; + XCTAssert([@"" isEqualToString:tmp]); +} + +- (void)testURLUtilityMethods { + + // set and retrieve a url + [self addBranchURLToPasteboard]; + NSURL *tmp = [self getURLFromPasteboard]; + XCTAssert([self.testBranchURL.absoluteString isEqualToString:tmp.absoluteString]); + + // overwrite the pasteboard + [self clearPasteboard]; + tmp = [self getURLFromPasteboard]; + XCTAssertNil(tmp); +} + +- (void)testDefaultState { + // host app sets this to true, should consider a no-op test host + XCTAssertFalse([BNCPasteboard sharedInstance].checkOnInstall); +} + +- (void)testIsUrlOnPasteboard { + XCTAssertFalse([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + [self addBranchURLToPasteboard]; + XCTAssertTrue([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + [self clearPasteboard]; + XCTAssertFalse([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); +} + +- (void)testCheckForBranchLink { + [self addBranchURLToPasteboard]; + XCTAssertTrue([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + NSURL *tmp = [[BNCPasteboard sharedInstance] checkForBranchLink]; + XCTAssert([self.testBranchURL.absoluteString isEqualToString:tmp.absoluteString]); + + [self clearPasteboard]; +} + +- (void)testCheckForBranchLink_nonBranchLink { + [self addNonBranchURLToPasteboard]; + XCTAssertTrue([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + NSURL *tmp = [[BNCPasteboard sharedInstance] checkForBranchLink]; + XCTAssertNil(tmp); + + [self clearPasteboard]; +} + +- (void)testCheckForBranchLink_noLink { + [self addStringToPasteboard]; + XCTAssertFalse([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + NSURL *tmp = [[BNCPasteboard sharedInstance] checkForBranchLink]; + XCTAssertNil(tmp); + + [self clearPasteboard]; +} + +#if 0 +// This test fails intermittently when executed with other tests - depending upon the order in which its executed +- (void) testPassPasteControl { +#if !TARGET_OS_TV + if (@available(iOS 16.0, macCatalyst 16.0, *)) { + + long long timeStamp = ([[NSDate date] timeIntervalSince1970] - 5*60)*1000; // 5 minute earlier timestamp + NSString *urlString = [NSString stringWithFormat:@"https://bnctestbed-alternate.app.link/9R7MbTmnRtb?__branch_flow_type=viewapp&__branch_flow_id=1105940563590163783&__branch_mobile_deepview_type=1&nl_opt_in=1&_cpts=%lld", timeStamp]; + NSURL *testURL = [[NSURL alloc] initWithString:urlString]; + + NSArray *itemProviders = @[[[NSItemProvider alloc] initWithItem:testURL typeIdentifier:UTTypeURL.identifier]]; + XCTestExpectation *openExpectation = [self expectationWithDescription:@"Test open"]; + + [[Branch getInstance] initSessionWithLaunchOptions:@{} andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) { + [openExpectation fulfill]; + XCTAssertNil(error); + }]; + + [[Branch getInstance] passPasteItemProviders:itemProviders]; + [self waitForExpectationsWithTimeout:5.0 handler:NULL]; + + } +#endif +} +#endif + +@end diff --git a/BranchSDKTests/BNCPreferenceHelperTests.m b/BranchSDKTests/BNCPreferenceHelperTests.m new file mode 100644 index 000000000..5269501b3 --- /dev/null +++ b/BranchSDKTests/BNCPreferenceHelperTests.m @@ -0,0 +1,417 @@ +// +// BNCPreferenceHelperTests.m +// Branch-TestBed +// +// Created by Graham Mueller on 4/2/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import +#import "BNCPreferenceHelper.h" +#import "BNCEncodingUtils.h" +#import "Branch.h" +#import "BNCConfig.h" + +@interface BNCPreferenceHelper() + +// expose private methods for testing +- (NSMutableDictionary *)deserializePrefDictFromData:(NSData *)data; +- (NSData *)serializePrefDict:(NSMutableDictionary *)dict; + +@end + +@interface BNCPreferenceHelperTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCPreferenceHelper *prefHelper; +@end + +@implementation BNCPreferenceHelperTests + +- (void)setUp { + self.prefHelper = [BNCPreferenceHelper new]; +} + +- (void)tearDown { + +} + +- (void)testPreferenceDefaults { + XCTAssertEqual(self.prefHelper.timeout, 5.5); + XCTAssertEqual(self.prefHelper.retryInterval, 0); + XCTAssertEqual(self.prefHelper.retryCount, 3); + XCTAssertFalse(self.prefHelper.disableAdNetworkCallouts); +} + +- (void)testPreferenceSets { + self.prefHelper.retryCount = NSIntegerMax; + self.prefHelper.retryInterval = NSIntegerMax; + self.prefHelper.timeout = NSIntegerMax; + + XCTAssertEqual(self.prefHelper.retryCount, NSIntegerMax); + XCTAssertEqual(self.prefHelper.retryInterval, NSIntegerMax); + XCTAssertEqual(self.prefHelper.timeout, NSIntegerMax); +} + +// This test is not reliable when run concurrently with other tests that set the patterListURL +- (void)testURLFilter { + XCTAssertTrue([@"https://cdn.branch.io" isEqualToString:self.prefHelper.patternListURL]); + + NSString *customURL = @"https://banned.branch.io"; + self.prefHelper.patternListURL = customURL; + XCTAssertTrue([customURL isEqualToString:self.prefHelper.patternListURL]); +} + +- (void)testSerializeDict_Nil { + NSMutableDictionary *dict = nil; + NSData *data = [self.prefHelper serializePrefDict:dict]; + XCTAssert(data == nil); +} + +- (void)testSerializeDict_Empty { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 0); +} + +- (void)testSerializeDict_String { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSString *value = @"the quick brown fox jumps over the lazy dog"; + NSString *key = @"test"; + [dict setObject:value forKey:key]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 1); + + XCTAssert([[tmp objectForKey:key] isEqualToString:value]); +} + +- (void)testSerializeDict_Date { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSDate *value = [NSDate date]; + NSString *key = @"test"; + [dict setObject:value forKey:key]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 1); + + XCTAssert([[tmp objectForKey:key] isEqual:value]); +} + +- (void)testSerializeDict_Bool { + NSMutableDictionary *dict = [NSMutableDictionary new]; + bool value = YES; + NSString *key = @"test"; + [dict setObject:@(value) forKey:key]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 1); + + XCTAssert([[tmp objectForKey:key] isEqual:@(value)]); +} + +- (void)testSerializeDict_Integer { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSInteger value = 1234; + NSString *key = @"test"; + [dict setObject:@(value) forKey:key]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 1); + + XCTAssert([[tmp objectForKey:key] isEqual:@(value)]); +} + +- (void)testSerializeDict_All { + NSMutableDictionary *dict = [NSMutableDictionary new]; + + NSString *value1 = @"the quick brown fox jumps over the lazy dog"; + NSString *key1 = @"test1"; + [dict setObject:value1 forKey:key1]; + + NSDate *value2 = [NSDate date]; + NSString *key2 = @"test2"; + [dict setObject:value2 forKey:key2]; + + bool value3 = YES; + NSString *key3 = @"test3"; + [dict setObject:@(value3) forKey:key3]; + + NSInteger value4 = 1234; + NSString *key4 = @"test4"; + [dict setObject:@(value4) forKey:key4]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 4); + + XCTAssert([[tmp objectForKey:key1] isEqualToString:value1]); + XCTAssert([[tmp objectForKey:key2] isEqual:value2]); + XCTAssert([[tmp objectForKey:key3] isEqual:@(value3)]); + XCTAssert([[tmp objectForKey:key4] isEqual:@(value4)]); +} + +- (void)testURLSkipList { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSString *key = @"test"; + NSArray *value = @[ + @"^fb\\d+:", + @"^li\\d+:", + @"^pdk\\d+:", + @"^twitterkit-.*:", + @"^com\\.googleusercontent\\.apps\\.\\d+-.*:\\/oauth", + @"^(?i)(?!(http|https):).*(:|:.*\\b)(password|o?auth|o?auth.?token|access|access.?token)\\b", + @"^(?i)((http|https):\\/\\/).*[\\/|?|#].*\\b(password|o?auth|o?auth.?token|access|access.?token)\\b", + ]; + [dict setObject:value forKey:key]; + NSData *data = [self.prefHelper serializePrefDict:dict]; + + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + + NSArray *filter = [tmp objectForKey:key]; + + NSString *filterDesc = filter.description; + NSString *valueDesc = value.description; + XCTAssert([filterDesc isEqualToString:valueDesc]); +} + +- (void)testSetCDNBaseURL_Example { + + NSString *url = @"https://www.example.com/"; + [self.prefHelper setPatternListURL:url]; + + NSString *urlStored = self.prefHelper.patternListURL ; + XCTAssert([url isEqualToString:urlStored]); +} + +- (void)testSetCDNBaseURL_InvalidHttp { + + NSString *url = @"Invalid://www.example.com/"; + [self.prefHelper setPatternListURL:url] ; + + NSString *urlStored = self.prefHelper.patternListURL ; + XCTAssert(![url isEqualToString:urlStored]); + XCTAssert([urlStored isEqualToString:BNC_CDN_URL]); +} + +- (void)testSetCDNBaseURL_InvalidEmpty { + + [self.prefHelper setPatternListURL:@""] ; + + NSString *urlStored = self.prefHelper.patternListURL ; + XCTAssert(![urlStored isEqualToString:@""]); + XCTAssert([urlStored isEqualToString:BNC_CDN_URL]); +} + +- (void)testSetPatternListURL { + NSString *expectedURL = @"https://example.com"; + [self.prefHelper setPatternListURL:expectedURL]; + + NSString *patternListURL = self.prefHelper.patternListURL; + XCTAssert([patternListURL isEqualToString: expectedURL]); +} + +- (void)testSetLastStrongMatchDate { + NSDate *expectedDate = [NSDate date]; + [self.prefHelper setLastStrongMatchDate: expectedDate]; + + NSDate *actualDate = [self.prefHelper lastStrongMatchDate]; + XCTAssertEqualObjects(expectedDate, actualDate); +} + +- (void)testSetAppVersion { + NSString *expectedVersion = @"1.0.0"; + [self.prefHelper setAppVersion: expectedVersion]; + + NSString *actualVersion = [self.prefHelper appVersion]; + XCTAssertEqualObjects(expectedVersion, actualVersion); +} + +- (void)testSetLocalUrl { + NSString *expectedLocalURL = @"https://local.example.com"; + [self.prefHelper setLocalUrl:expectedLocalURL]; + + NSString *localURL = [self.prefHelper localUrl]; + XCTAssertEqualObjects(localURL, expectedLocalURL); +} + +- (void)testSetInitialReferrer { + NSString *expectedReferrer = @"referrer.example.com"; + [self.prefHelper setInitialReferrer:expectedReferrer]; + + NSString *actualReferrer = [self.prefHelper initialReferrer]; + XCTAssertEqualObjects(actualReferrer, expectedReferrer); +} + +- (void)testSetAppleAttributionTokenChecked { + BOOL expectedValue = YES; + [self.prefHelper setAppleAttributionTokenChecked:expectedValue]; + + BOOL actualValue = [self.prefHelper appleAttributionTokenChecked]; + XCTAssertEqual(expectedValue, actualValue); +} + +- (void)testSetHasOptedInBefore { + BOOL expectedValue = YES; + [self.prefHelper setHasOptedInBefore:expectedValue]; + + BOOL actualValue = [self.prefHelper hasOptedInBefore]; + XCTAssertEqual(expectedValue, actualValue); +} + +- (void)testSetHasCalledHandleATTAuthorizationStatus { + BOOL expectedValue = YES; + [self.prefHelper setHasCalledHandleATTAuthorizationStatus:expectedValue]; + + BOOL actualValue = [self.prefHelper hasCalledHandleATTAuthorizationStatus]; + XCTAssertEqual(expectedValue, actualValue); +} + +- (void)testSetRequestMetadataKeyValidKeyValue { + NSString *key = @"testKey"; + NSString *value = @"testValue"; + + [self.prefHelper setRequestMetadataKey:key value:value]; + + NSObject *retrievedValue = [self.prefHelper.requestMetadataDictionary objectForKey:key]; + XCTAssertEqualObjects(retrievedValue, value); +} + +- (void)testSetRequestMetadataKeyValidKeyNilValue { + NSString *key = @"testKey"; + NSString *value = @"testValue"; + + [self.prefHelper.requestMetadataDictionary setObject:value forKey:key]; + + [self.prefHelper setRequestMetadataKey:key value:nil]; + + NSObject *retrievedValue = [self.prefHelper.requestMetadataDictionary objectForKey:key]; + XCTAssertNil(retrievedValue); +} + +- (void)testSetRequestMetadataKeyValidKeyNilValueKeyNotExists { + NSString *key = @"testKeyNotExists"; + + NSUInteger initialDictCount = [self.prefHelper.requestMetadataDictionary count]; + + [self.prefHelper setRequestMetadataKey:key value:nil]; + + NSUInteger postActionDictCount = [self.prefHelper.requestMetadataDictionary count]; + XCTAssertEqual(initialDictCount, postActionDictCount); +} + +- (void)testSetRequestMetadataKeyNilKey { + NSString *value = @"testValue"; + NSUInteger initialDictCount = [self.prefHelper.requestMetadataDictionary count]; + + [self.prefHelper setRequestMetadataKey:nil value:value]; + + NSUInteger postActionDictCount = [self.prefHelper.requestMetadataDictionary count]; + XCTAssertEqual(initialDictCount, postActionDictCount); +} + +- (void)testSetLimitFacebookTracking { + BOOL expectedValue = YES; + + [self.prefHelper setLimitFacebookTracking:expectedValue]; + + BOOL storedValue = [self.prefHelper limitFacebookTracking]; + + XCTAssertEqual(expectedValue, storedValue); +} + +- (void)testSetTrackingDisabled_YES { + [self.prefHelper setTrackingDisabled:YES]; + + BOOL storedValue = [self.prefHelper trackingDisabled]; + XCTAssertTrue(storedValue); + [self.prefHelper setTrackingDisabled:NO]; +} + +- (void)testSetTrackingDisabled_NO { + [self.prefHelper setTrackingDisabled:NO]; + + BOOL storedValue = [self.prefHelper trackingDisabled]; + XCTAssertFalse(storedValue); +} + +// TODO: rethink this test as these values are not set in a freshly instantiated prefHelper +- (void)testClearTrackingInformation { + [self.prefHelper clearTrackingInformation]; + + XCTAssertNil(self.prefHelper.sessionID); + XCTAssertNil(self.prefHelper.linkClickIdentifier); + XCTAssertNil(self.prefHelper.spotlightIdentifier); + XCTAssertNil(self.prefHelper.referringURL); + XCTAssertNil(self.prefHelper.universalLinkUrl); + XCTAssertNil(self.prefHelper.initialReferrer); + XCTAssertNil(self.prefHelper.installParams); + XCTAssertNil(self.prefHelper.sessionParams); + XCTAssertNil(self.prefHelper.externalIntentURI); + XCTAssertNil(self.prefHelper.savedAnalyticsData); + XCTAssertNil(self.prefHelper.previousAppBuildDate); + XCTAssertEqual(self.prefHelper.requestMetadataDictionary.count, 0); + XCTAssertNil(self.prefHelper.lastStrongMatchDate); + XCTAssertNil(self.prefHelper.userIdentity); + XCTAssertNil(self.prefHelper.referringURLQueryParameters); + XCTAssertNil(self.prefHelper.anonID); +} + +- (void)testSaveBranchAnalyticsData { + NSString *dummySessionID = @"testSession123"; + NSDictionary *dummyAnalyticsData = @{ @"key1": @"value1", @"key2": @"value2" }; + + self.prefHelper.sessionID = dummySessionID; + + [self.prefHelper saveBranchAnalyticsData:dummyAnalyticsData]; + + NSMutableDictionary *retrievedData = [self.prefHelper getBranchAnalyticsData]; + + NSArray *viewDataArray = [retrievedData objectForKey:dummySessionID]; + XCTAssertNotNil(viewDataArray); + XCTAssertEqual(viewDataArray.count, 1); + XCTAssertEqualObjects(viewDataArray.firstObject, dummyAnalyticsData); +} + +- (void)testClearBranchAnalyticsData { + [self.prefHelper clearBranchAnalyticsData]; + + NSMutableDictionary *retrievedData = [self.prefHelper getBranchAnalyticsData]; + XCTAssertEqual(retrievedData.count, 0); +} + +- (void)testSaveContentAnalyticsManifest { + NSDictionary *dummyManifest = @{ @"manifestKey1": @"manifestValue1", @"manifestKey2": @"manifestValue2" }; + + [self.prefHelper saveContentAnalyticsManifest:dummyManifest]; + + NSDictionary *retrievedManifest = [self.prefHelper getContentAnalyticsManifest]; + + XCTAssertEqualObjects(retrievedManifest, dummyManifest); +} + +@end diff --git a/BranchSDKTests/BNCReachabilityTests.m b/BranchSDKTests/BNCReachabilityTests.m new file mode 100644 index 000000000..3f159c1e3 --- /dev/null +++ b/BranchSDKTests/BNCReachabilityTests.m @@ -0,0 +1,45 @@ +// +// BNCReachabilityTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 11/18/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCReachability.h" + +@interface BNCReachabilityTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCReachability *reachability; +@end + +@implementation BNCReachabilityTests + +- (void)setUp { + self.reachability = [BNCReachability new]; +} + +- (void)tearDown { + +} + +- (void)testSimulator_WIFI { + NSString *status = [self.reachability reachabilityStatus]; + XCTAssertNotNil(status); + XCTAssert([@"wifi" isEqualToString:status]); +} + +// Only works on a device with cell +//- (void)testDevice_Cell { +// NSString *status = [self.reachability reachabilityStatus]; +// XCTAssertNotNil(status); +// XCTAssert([@"mobile" isEqualToString:status]); +//} + +// Only works on a device in Airplane mode +//- (void)testDevice_AirplaneMode { +// NSString *status = [self.reachability reachabilityStatus]; +// XCTAssertNil(status); +//} + +@end diff --git a/BranchSDKTests/BNCReferringURLUtilityTests.m b/BranchSDKTests/BNCReferringURLUtilityTests.m new file mode 100644 index 000000000..b76f91b4d --- /dev/null +++ b/BranchSDKTests/BNCReferringURLUtilityTests.m @@ -0,0 +1,538 @@ +// +// BNCReferringURLUtilityTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 3/9/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCReferringURLUtility.h" +#import "BNCUrlQueryParameter.h" +#import "BNCPreferenceHelper.h" + +@interface BNCReferringURLUtility(Test) +// expose the private data structure so tests can clear it +@property (strong, readwrite, nonatomic) NSMutableDictionary *urlQueryParameters; + +// expose private methods to test data migration +- (void)checkForAndMigrateOldGbraid; +@end + +@interface BNCReferringURLUtilityTests : XCTestCase + +@end + +@implementation BNCReferringURLUtilityTests + +// test constants +static NSString *openEndpoint = @"/v1/open"; +static NSString *eventEndpoint = @"/v2/event"; + ++ (void)tearDown { + // clear test data from global storage + [BNCPreferenceHelper sharedInstance].referringURLQueryParameters = nil; + [BNCPreferenceHelper sharedInstance].referrerGBRAID = nil; + [BNCPreferenceHelper sharedInstance].referrerGBRAIDValidityWindow = 0; + [BNCPreferenceHelper sharedInstance].referrerGBRAIDInitDate = nil; +} + +// workaround for BNCPreferenceHelper being persistent across tests and not currently mockable +- (BNCReferringURLUtility *)referringUtilityForTests { + BNCReferringURLUtility *utility = [BNCReferringURLUtility new]; + utility.urlQueryParameters = [NSMutableDictionary new]; + return utility; +} + +// make gbraid equality check simpler by excluding timestamp +- (NSDictionary *)removeTimestampFromParams:(NSDictionary *)params { + NSMutableDictionary *paramsWithoutTimestamp = [params mutableCopy]; + paramsWithoutTimestamp[@"gbraid_timestamp"] = nil; + return paramsWithoutTimestamp; +} + +// gbraid timestamp is a string representing time in millis +- (void)validateGbraidTimestampInReferringParameters:(NSDictionary *)params { + id timestamp = params[@"gbraid_timestamp"]; + XCTAssert(timestamp != nil); + XCTAssert([timestamp isKindOfClass:NSString.class]); +} + +- (void)expireValidityWindowsInUtility:(BNCReferringURLUtility *)utility { + for (NSString *paramName in utility.urlQueryParameters.allKeys) { + BNCUrlQueryParameter *param = utility.urlQueryParameters[paramName]; + + // currently the longest validity window is 30 days + NSTimeInterval sixtyDaysAgo = -1 * 60 * 24 * 60 * 60; + param.timestamp = [NSDate dateWithTimeIntervalSinceNow:sixtyDaysAgo]; + } +} + +- (void)testReferringURLWithNoParams { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link"]; + NSDictionary *expected = @{}; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testNilReferringURL { + NSURL *url = nil; + NSDictionary *expected = @{}; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLIgnoredParam { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?other=12345"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +// NSURL treats URI schemes in a consistent manner with Universal Links +- (void)testReferringURLWithURISchemeSanityCheck{ + NSURL *url = [NSURL URLWithString:@"branchtest://?gclid=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidCapitalized { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?GCLID=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidMixedCase { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?GcLiD=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidNoValue { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid="]; + NSDictionary *expected = @{ + @"gclid": @"" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidValueCasePreserved { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=aAbBcC"]; + NSDictionary *expected = @{ + @"gclid": @"aAbBcC" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidIgnoredParam { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345&other=abcde"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidFragment{ + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345#header"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidAsFragment{ + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?other=abcde#gclid=12345"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidOverwritesValue { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + NSURL *url2 = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=abcde"]; + NSDictionary *expected2 = @{ + @"gclid": @"abcde" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + XCTAssert([expected isEqualToDictionary:params]); + + [utility parseReferringURL:url2]; + NSDictionary *params2 = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected2 isEqualToDictionary:params2]); +} + +- (void)testReferringURLWithMetaCampaignIdsAndInvalidURL { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?al_applink_data=[]#target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"]; + NSDictionary *expected = @{}; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithMetaCampaignIds { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"]; + NSDictionary *expected = @{ + @"meta_campaign_ids": @"ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithMetaCampaignIdsExpired { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + [self expireValidityWindowsInUtility:utility]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithMetaNoCampaignIds { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22test_deeplink%22%3A1%7D"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGbraid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=abcde"]; + NSDictionary *expected = @{ + @"gbraid": @"abcde", + @"is_deeplink_gbraid": @(true) + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + [self validateGbraidTimestampInReferringParameters:params]; + NSDictionary *paramsWithoutTimestamp = [self removeTimestampFromParams:params]; + XCTAssert([expected isEqualToDictionary:paramsWithoutTimestamp]); +} + +- (void)testReferringURLWithGbraidOnEvent { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=abcde"]; + NSDictionary *expected = @{ + @"gbraid": @"abcde" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:eventEndpoint]; + + [self validateGbraidTimestampInReferringParameters:params]; + NSDictionary *paramsWithoutTimestamp = [self removeTimestampFromParams:params]; + XCTAssert([expected isEqualToDictionary:paramsWithoutTimestamp]); +} + +- (void)testReferringURLWithGbraidExpired { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=abcde"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + [self expireValidityWindowsInUtility:utility]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLPreservesNonZeroValidityWindowForGbraid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=12345"]; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + + // pretend this object was loaded from disk + // this simulates setting a custom non-zero validity window, only supported for gbraid + BNCUrlQueryParameter *existingParam = [BNCUrlQueryParameter new]; + existingParam.name = @"gbraid"; + existingParam.value = @""; + existingParam.timestamp = [NSDate date]; + existingParam.validityWindow = 5; // not the default gbraid window + utility.urlQueryParameters[@"gbraid"] = existingParam; + + [utility parseReferringURL:url]; + + // verify validity window was not changed + XCTAssert(utility.urlQueryParameters[@"gbraid"].validityWindow == 5); +} + +- (void)testReferringURLOverwritesZeroValidityWindowForGbraid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=12345"]; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + + // pretend this object was loaded from disk + // for gbraid, or any param, we overwrite the 0 validity windows with the default + BNCUrlQueryParameter *existingParam = [BNCUrlQueryParameter new]; + existingParam.name = @"gbraid"; + existingParam.value = @""; + existingParam.timestamp = [NSDate date]; + existingParam.validityWindow = 0; + utility.urlQueryParameters[@"gbraid"] = existingParam; + + [utility parseReferringURL:url]; + + // verify validity window was changed + XCTAssert(utility.urlQueryParameters[@"gbraid"].validityWindow != 0); +} + +- (void)testReferringURLWithGclidGbraid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345&gbraid=abcde"]; + NSDictionary *expected = @{ + @"gclid": @"12345", + @"gbraid": @"abcde", + @"is_deeplink_gbraid": @(true) + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + [self validateGbraidTimestampInReferringParameters:params]; + NSDictionary *paramsWithoutTimestamp = [self removeTimestampFromParams:params]; + XCTAssert([expected isEqualToDictionary:paramsWithoutTimestamp]); +} + +- (void)testGbraidDataMigration { + // Manipulates the global BNCPreferenceHelper. + // This is not safe for concurrent unit tests, so only the happy path is tested. + [self clearCurrentQueryParameters]; + [self addOldGbraidData]; + + NSDictionary *expected = @{ + @"gbraid": @"abcde", + @"is_deeplink_gbraid": @(false) + }; + + BNCReferringURLUtility *utility = [BNCReferringURLUtility new]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + [self validateGbraidTimestampInReferringParameters:params]; + NSDictionary *paramsWithoutTimestamp = [self removeTimestampFromParams:params]; + XCTAssert([expected isEqualToDictionary:paramsWithoutTimestamp]); + + [self verifyOldGbraidDataIsCleared]; +} + +- (void)clearCurrentQueryParameters { + [BNCPreferenceHelper sharedInstance].referringURLQueryParameters = nil; +} + +- (void)addOldGbraidData { + [BNCPreferenceHelper sharedInstance].referrerGBRAID = @"abcde"; + [BNCPreferenceHelper sharedInstance].referrerGBRAIDValidityWindow = 2592000; + [BNCPreferenceHelper sharedInstance].referrerGBRAIDInitDate = [NSDate date]; +} + +- (void)verifyOldGbraidDataIsCleared { + XCTAssertNil([BNCPreferenceHelper sharedInstance].referrerGBRAID); + XCTAssert([BNCPreferenceHelper sharedInstance].referrerGBRAIDValidityWindow == 0); + XCTAssertNil([BNCPreferenceHelper sharedInstance].referrerGBRAIDInitDate); +} + +- (void)testReferringURLWithSccid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=12345"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidMixedCase { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?ScCiD=12345"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidNoValue { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid="]; + NSDictionary *expected = @{ + @"sccid": @"" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidValueCasePreserved { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=aAbBcC"]; + NSDictionary *expected = @{ + @"sccid": @"aAbBcC" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidIgnoredParam { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=12345&other=abcde"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidFragment{ + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=12345#header"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidAsFragment{ + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?other=abcde#sccid=12345"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidOverwritesValue { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=12345"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + NSURL *url2 = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=abcde"]; + NSDictionary *expected2 = @{ + @"sccid": @"abcde" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + XCTAssert([expected isEqualToDictionary:params]); + + [utility parseReferringURL:url2]; + NSDictionary *params2 = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected2 isEqualToDictionary:params2]); +} + + +@end diff --git a/BranchSDKTests/BNCRequestFactoryTests.m b/BranchSDKTests/BNCRequestFactoryTests.m new file mode 100644 index 000000000..c28d3b6e0 --- /dev/null +++ b/BranchSDKTests/BNCRequestFactoryTests.m @@ -0,0 +1,234 @@ +// +// BNCRequestFactoryTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 8/21/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCRequestFactory.h" +#import "BranchConstants.h" +#import "BNCEncodingUtils.h" + +@interface BNCRequestFactoryTests : XCTestCase +@property (nonatomic, copy, readwrite) NSString *requestUUID; +@property (nonatomic, copy, readwrite) NSNumber *requestCreationTimeStamp; +@end + +@implementation BNCRequestFactoryTests + +- (void)setUp { + _requestUUID = [[NSUUID UUID ] UUIDString]; + _requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); +} + +- (void)tearDown { + +} + +- (void)testInitWithBranchKeyNil { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:nil UUID:_requestUUID TimeStamp:_requestCreationTimeStamp]; + NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + + // key is omitted when nil + XCTAssertNil([json objectForKey:@"branch_key"]); + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testInitWithBranchKeyEmpty { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + + // empty string is allowed + XCTAssertTrue([@"" isEqualToString:[json objectForKey:@"branch_key"]]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testInitWithBranchKey { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + XCTAssertTrue([@"key_abcd" isEqualToString:[json objectForKey:@"branch_key"]]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForInstall { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"key_abcd" isEqualToString:[json objectForKey:@"branch_key"]]); + XCTAssertNotNil([json objectForKey:@"sdk"]); + XCTAssertTrue([@"Apple" isEqualToString:[json objectForKey:@"brand"]]); + XCTAssertNotNil([json objectForKey:@"ios_vendor_id"]); + + // not present on installs + XCTAssertNil([json objectForKey:@"randomized_bundle_token"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForOpen { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForOpenWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"key_abcd" isEqualToString:[json objectForKey:@"branch_key"]]); + XCTAssertNotNil([json objectForKey:@"sdk"]); + XCTAssertTrue([@"Apple" isEqualToString:[json objectForKey:@"brand"]]); + XCTAssertNotNil([json objectForKey:@"ios_vendor_id"]); + + // Present only on opens. Assumes test runs after the host app completes an install. + // This is not a reliable assumption on test runners + //XCTAssertNotNil([json objectForKey:@"randomized_bundle_token"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEvent { + NSDictionary *event = @{@"name": @"ADD_TO_CART"}; + + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"ADD_TO_CART" isEqualToString:[json objectForKey:@"name"]]); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEventWithContentItem { + NSDictionary *event = @{ + @"name": @"ADD_TO_CART", + @"content_items": @[ + @{ + @"$og_title": @"TestTitle", + @"$quantity": @(2), + @"$product_name": @"TestProduct", + @"$price": @(10) + } + ] + }; + + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"ADD_TO_CART" isEqualToString:[json objectForKey:@"name"]]); + + NSDictionary *contentItems = [json objectForKey:@"content_items"]; + XCTAssertNotNil(contentItems); + XCTAssertTrue(contentItems.count == 1); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEventWithTwoContentItem { + NSDictionary *event = @{ + @"name": @"ADD_TO_CART", + @"content_items": @[ + @{ + @"$og_title": @"TestTitle1", + @"$quantity": @(2), + @"$product_name": @"TestProduct1", + @"$price": @(10) + }, + @{ + @"$og_title": @"TestTitle2", + @"$quantity": @(3), + @"$product_name": @"TestProduct2", + @"$price": @(20) + } + ] + }; + + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"ADD_TO_CART" isEqualToString:[json objectForKey:@"name"]]); + + NSDictionary *contentItems = [json objectForKey:@"content_items"]; + XCTAssertNotNil(contentItems); + XCTAssertTrue(contentItems.count == 2); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEventEmpty { + NSDictionary *event = @{}; + + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertNotNil(json); + + XCTAssertNil([json objectForKey:@"name"]); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEventNil { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:nil]; + XCTAssertNotNil(json); + + XCTAssertNil([json objectForKey:@"name"]); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + + +- (void)testDataForShortURL { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForShortURLWithLinkDataDictionary:@{}.mutableCopy isSpotlightRequest:NO]; + XCTAssertNotNil(json); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForLATD { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForLATDWithDataDictionary:@{}.mutableCopy]; + XCTAssertNotNil(json); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +@end diff --git a/BranchSDKTests/BNCSKAdNetworkTests.m b/BranchSDKTests/BNCSKAdNetworkTests.m new file mode 100644 index 000000000..d71cf203a --- /dev/null +++ b/BranchSDKTests/BNCSKAdNetworkTests.m @@ -0,0 +1,264 @@ +// +// BNCSKAdNetworkTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 8/13/20. +// Copyright © 2020 Branch, Inc. All rights reserved. +// + +#import +#import "BNCSKAdNetwork.h" +#import "BranchEvent.h" + +// Expose private methods for testing +@interface BNCSKAdNetwork() + +@property (nonatomic, copy, readwrite) NSDate *installDate; + +- (BOOL)shouldAttemptSKAdNetworkCallout; + +@end + +@interface BranchEvent() + +// private BranchEvent methods used to check data before sending to network service. +- (NSDictionary *)buildEventDictionary; +- (BranchEventRequest *)buildRequestWithEventDictionary:(NSDictionary *)eventDictionary; + +@end + + +@interface BNCSKAdNetworkTests : XCTestCase + +@property (nonatomic, strong, readwrite) BNCSKAdNetwork *skAdNetwork; + +@end + +@implementation BNCSKAdNetworkTests + +- (void)setUp { + self.skAdNetwork = [BNCSKAdNetwork new]; + self.skAdNetwork.installDate = [NSDate date]; +} + +- (void)tearDown { + +} + +- (void)testDefaultMaxTimeout { + NSTimeInterval days; + if (@available(iOS 16.1, macCatalyst 16.1, *)) { + days = 3600.0 * 24.0 * 60.0; // one day + } else { + days = 3600.0 * 24.0; // one day + } + XCTAssertTrue(self.skAdNetwork.maxTimeSinceInstall == days); +} + +- (void)testShouldAttemptSKAdNetworkCallout { + XCTAssertTrue([self.skAdNetwork shouldAttemptSKAdNetworkCallout]); +} + +- (void)testShouldAttemptSKAdNetworkCalloutFalse { + self.skAdNetwork.maxTimeSinceInstall = 0.0; + XCTAssertFalse([self.skAdNetwork shouldAttemptSKAdNetworkCallout]); +} + +- (void)testPostbackCall { + + if (@available(iOS 16.1, macCatalyst 16.1, *)) { + self.skAdNetwork.maxTimeSinceInstall = 3600.0 * 24.0 * 60.0; + } else { + self.skAdNetwork.maxTimeSinceInstall = 3600.0 * 24.0; // one day + } + + XCTAssertTrue([self.skAdNetwork shouldAttemptSKAdNetworkCallout]); + + [[BNCSKAdNetwork sharedInstance] registerAppForAdNetworkAttribution]; + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventInvite]; + NSDictionary *eventDictionary = [event buildEventDictionary]; + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"TestPostback"]; + BNCServerResponse *openInstallResponse = [[BNCServerResponse alloc] init]; + + openInstallResponse.data = @{ @"update_conversion_value": @60 }; + request.completion = ^(NSDictionary*_Nullable response, NSError*_Nullable error){ + [expectation fulfill]; + }; + [request processResponse:openInstallResponse error:Nil]; + + [self waitForExpectationsWithTimeout:5.0 handler:nil]; +} + +- (void)testSKAN4ParamsDefaultValues { + + if (@available(iOS 16.1, macCatalyst 16.1, *)) { + NSString *coarseValue = [[BNCSKAdNetwork sharedInstance] getCoarseConversionValueFromDataResponse:@{}]; + XCTAssertTrue([coarseValue isEqualToString:@"low"]); + + BOOL isLocked = [[BNCSKAdNetwork sharedInstance] getLockedStatusFromDataResponse:@{}]; + XCTAssertFalse(isLocked); + + BOOL ascendingOnly = [[BNCSKAdNetwork sharedInstance] getAscendingOnlyFromDataResponse:@{}]; + XCTAssertTrue(ascendingOnly); + } +} + +- (void)testSKAN4ParamsValues { + + if (@available(iOS 16.1, macCatalyst 16.1, *)) { + + NSDictionary *response = @{@"update_conversion_value": @16, @"coarse_key": @"high", @"locked": @YES, @"ascending_only":@NO }; + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + + NSString *coarseValue = [adNetwork getCoarseConversionValueFromDataResponse:response]; + XCTAssertTrue([coarseValue isEqualToString:@"high"]); + + BOOL isLocked = [adNetwork getLockedStatusFromDataResponse:response]; + XCTAssertTrue(isLocked); + + BOOL ascendingOnly = [adNetwork getAscendingOnlyFromDataResponse:response]; + XCTAssertFalse(ascendingOnly); + } +} + +- (void)testSKAN4CurrentWindow { + + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + NSDate *currentDateAndTime = [NSDate date]; + prefs.firstAppLaunchTime = [currentDateAndTime dateByAddingTimeInterval:-30]; + NSInteger win = [adNetwork calculateSKANWindowForTime:currentDateAndTime]; + XCTAssertTrue(win == 1); + + win = [adNetwork calculateSKANWindowForTime: [ currentDateAndTime dateByAddingTimeInterval:24*3600*3 ]]; + XCTAssertTrue(win == 2); + + win = [adNetwork calculateSKANWindowForTime: [ currentDateAndTime dateByAddingTimeInterval:24*3600*10 ]]; + XCTAssertTrue(win == 3); + + win = [adNetwork calculateSKANWindowForTime: [ currentDateAndTime dateByAddingTimeInterval:24*3600*36 ]]; + XCTAssertTrue(win == 0); + + prefs.firstAppLaunchTime = nil; + [prefs synchronize]; + win = [adNetwork calculateSKANWindowForTime: currentDateAndTime]; + XCTAssertTrue(win == 0); +} + +- (void)testSKAN4HighestConversionValue { + + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + prefs.highestConversionValueSent = 0; + prefs.skanCurrentWindow = 0; + NSDate *currentDateAndTime = [NSDate date]; + prefs.invokeRegisterApp = YES; + + prefs.firstAppLaunchTime = [currentDateAndTime dateByAddingTimeInterval:-30 ]; + [adNetwork shouldCallPostbackForDataResponse:@{}]; + XCTAssertTrue(prefs.highestConversionValueSent == 0); + + [adNetwork shouldCallPostbackForDataResponse:@{@"update_conversion_value": @6}]; + XCTAssertTrue(prefs.highestConversionValueSent == 6); + + [adNetwork shouldCallPostbackForDataResponse:@{@"update_conversion_value": @3}]; + XCTAssertTrue(prefs.highestConversionValueSent == 6); + + + prefs.firstAppLaunchTime = [currentDateAndTime dateByAddingTimeInterval:-24*3600*3 ]; + [adNetwork shouldCallPostbackForDataResponse:@{}]; + XCTAssertTrue(prefs.highestConversionValueSent == 0); +} + +- (void)testSKAN4ShouldCallPostback { + + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + prefs.firstAppLaunchTime = nil; + [prefs synchronize]; + + NSDictionary *response = @{@"update_conversion_value": @16, @"coarse_key": @"high", @"locked": @YES, @"ascending_only":@NO }; + + BOOL shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertFalse(shouldCall); + +} + +- (void)testSKAN4ShouldCallPostback2 { + + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + prefs.invokeRegisterApp = YES; + prefs.highestConversionValueSent = 0; + prefs.firstAppLaunchTime = [NSDate date]; + prefs.skanCurrentWindow = 0; + [prefs synchronize]; + + NSMutableDictionary *response = [[NSMutableDictionary alloc] initWithDictionary: + @{@"update_conversion_value": @16, @"coarse_key": @"high", @"locked": @YES, @"ascending_only":@YES }]; + + BOOL shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertFalse(shouldCall); + + response[@"update_conversion_value"] = @14; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertFalse(shouldCall); + + response[@"update_conversion_value"] = @18; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + prefs.firstAppLaunchTime = nil; + prefs.firstAppLaunchTime = [[NSDate date] dateByAddingTimeInterval:-24*3600*3]; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + NSLog(@"Conv : %ld", prefs.highestConversionValueSent); + XCTAssertTrue(shouldCall); + + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertFalse(shouldCall); +} + +- (void)testSKAN4ShouldCallPostback3 { + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + prefs.invokeRegisterApp = YES; + prefs.highestConversionValueSent = 0; + prefs.firstAppLaunchTime = [NSDate date]; + [prefs synchronize]; + + NSMutableDictionary *response = [[NSMutableDictionary alloc] initWithDictionary: + @{@"update_conversion_value": @16, @"coarse_key": @"high", @"locked": @YES, @"ascending_only":@NO }]; + + BOOL shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + response[@"update_conversion_value"] = @14; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + response[@"update_conversion_value"] = @18; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + prefs.firstAppLaunchTime = [[NSDate date] dateByAddingTimeInterval:-24*3600*3]; + //NSLog(@"Conv : %ld", (long)prefs.highestConversionValueSent); + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + NSLog(@"Conv : %ld", prefs.highestConversionValueSent); + XCTAssertTrue(shouldCall); +} + +@end diff --git a/BranchSDKTests/BNCSystemObserverTests.m b/BranchSDKTests/BNCSystemObserverTests.m new file mode 100644 index 000000000..8cc54f632 --- /dev/null +++ b/BranchSDKTests/BNCSystemObserverTests.m @@ -0,0 +1,139 @@ +// +// BNCSystemObserverTests.m +// Branch-TestBed +// +// Created by Graham Mueller on 4/22/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import +#import "BNCSystemObserver.h" + +@interface BNCSystemObserver () ++ (BOOL)compareUriSchemes:(NSString *)serverUriScheme With:(NSArray *)urlTypes; +@end + +@interface BNCSystemObserverTests : XCTestCase + +@end + +@implementation BNCSystemObserverTests + +- (void)testDefaultURIScheme_TestBed { + //ND XCTAssert([[BNCSystemObserver defaultURIScheme] isEqualToString:@"branchtest"]); +} + +- (void)testAppVersion_TestBed { + XCTAssert([[BNCSystemObserver applicationVersion] isEqualToString:@"1.0"]); +} + +- (void)testBundleIdentifier_TestBed { + NSString *bundleId = [BNCSystemObserver bundleIdentifier]; + XCTAssert([bundleId isEqualToString:@"branch.BranchSDKTestsHostApp"]); +} + +- (void)testBrand { + XCTAssert([[BNCSystemObserver brand] isEqualToString:@"Apple"]); +} + +- (void)testModel_Simulator { + // simulator models + NSString *tmp = [BNCSystemObserver model]; + XCTAssert([tmp containsString:@"arm64"] || [tmp containsString:@"x86_64"]); +} + +//- (void)testModelName_iPhone7 { +// XCTAssert([@"iPhone9,3" isEqualToString:[BNCSystemObserver model]]); +//} + +- (void)testOSName { + XCTAssertNotNil([BNCSystemObserver osName]); + + // This is not the system name, but rather the name Branch server expects + // XCTAssert([self.deviceInfo.osName isEqualToString:[UIDevice currentDevice].systemName]); + XCTAssert([@"iOS" isEqualToString:[BNCSystemObserver osName]] || [@"tv_OS" isEqualToString:[BNCSystemObserver osName]]); +} + +- (void)testOSVersion { + XCTAssertNotNil([BNCSystemObserver osVersion]); + XCTAssert([[BNCSystemObserver osVersion] isEqualToString:[UIDevice currentDevice].systemVersion]); +} + +/* + * Sample device screens + * original iPhone 320x480 1 + * iPad Pro (6th gen 12.9") 2048x2732 2 + * iPhone 14 Pro max 1290x2796 3 + */ + +- (void)testScreenWidth { + XCTAssert([BNCSystemObserver screenWidth].intValue >= 320 && [BNCSystemObserver screenWidth].intValue <= 2796); +} + +- (void)testScreenHeight { + XCTAssert([BNCSystemObserver screenHeight].intValue >= 320 && [BNCSystemObserver screenWidth].intValue <= 2796); +} + +- (void)testScreenScale { + XCTAssert([BNCSystemObserver screenScale].intValue >= 1 && [BNCSystemObserver screenScale].intValue <= 3); +} + +- (void)testIsSimulator_Simulator { + XCTAssert([BNCSystemObserver isSimulator]); +} + +- (void)testAdvertiserIdentifier_NoATTPrompt { + XCTAssertNil([BNCSystemObserver advertiserIdentifier]); +} + +- (void)testOptedInStatus_NoATTPrompt { + XCTAssert([[BNCSystemObserver attOptedInStatus] isEqualToString:@"not_determined"]); +} + +- (void)testAppleAttributionToken_Simulator { + NSString *token = [BNCSystemObserver appleAttributionToken]; + XCTAssertNil(token); +} + +- (void)testEnvironment { + // currently not running unit tests on extensions + XCTAssert([@"FULL_APP" isEqualToString:[BNCSystemObserver environment]]); +} + +- (void)testIsAppClip { + // currently not running unit tests on extensions + XCTAssert(![BNCSystemObserver isAppClip]); +} + +- (void)testCompareURIScemes { + + NSString *serverUriScheme = @"bnctest://"; + NSArray *urlTypes = @[@{@"CFBundleURLSchemes" : @[@""]}, @{@"CFBundleURLSchemes" : @[@"bnctest", @"xyzs"]}]; + + XCTAssertTrue([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:serverUriScheme With:nil]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:nil With:nil]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:nil With:urlTypes]); + + serverUriScheme = @":/"; + XCTAssertFalse([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + serverUriScheme = @"bnctest"; + XCTAssertTrue([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + serverUriScheme = @"bnctest://"; + urlTypes = @[ @{@"CFBundleURLSchemes" : @[@"bnctestX", @"xyzs"]}]; + XCTAssertFalse([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + serverUriScheme = @"://"; + XCTAssertFalse([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:@"" With:urlTypes]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:@"" With:@[@{}]]); +} + +@end diff --git a/BranchSDKTests/BNCURLFilterSkiplistUpgradeTests.m b/BranchSDKTests/BNCURLFilterSkiplistUpgradeTests.m new file mode 100644 index 000000000..ad7d5b029 --- /dev/null +++ b/BranchSDKTests/BNCURLFilterSkiplistUpgradeTests.m @@ -0,0 +1,273 @@ +// +// BNCURLFilterSkiplistUpgradeTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 4/4/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCURLFilter.h" + +@interface BNCURLFilterSkiplistUpgradeTests : XCTestCase + +@end + +@implementation BNCURLFilterSkiplistUpgradeTests + +- (void)setUp { + +} + +- (void)tearDown { + +} + + // v0 list + // https://cdn.branch.io/sdk/uriskiplist_v0.json +- (NSArray *)v0PatternList { + NSArray *patternList = @[ + @"^fb\\d+:", + @"^li\\d+:", + @"^pdk\\d+:", + @"^twitterkit-.*:", + @"^com\\.googleusercontent\\.apps\\.\\d+-.*:\\/oauth", + @"^(?i)(?!(http|https):).*(:|:.*\\b)(password|o?auth|o?auth.?token|access|access.?token)\\b", + @"^(?i)((http|https):\\/\\/).*[\\/|?|#].*\\b(password|o?auth|o?auth.?token|access|access.?token)\\b" + ]; + return patternList; +} + +// v1 list +// https://cdn.branch.io/sdk/uriskiplist_v1.json +- (NSArray *)v1PatternList { + NSArray *patternList = @[ + @"^fb\\d+:", + @"^li\\d+:", + @"^pdk\\d+:", + @"^twitterkit-.*:", + @"^com\\.googleusercontent\\.apps\\.\\d+-.*:\\/oauth", + @"^(?i)(?!(http|https):).*(:|:.*\\b)(password|o?auth|o?auth.?token|access|access.?token)\\b", + @"^(?i)((http|https):\\/\\/).*[\\/|?|#].*\\b(password|o?auth|o?auth.?token|access|access.?token)\\b" + ]; + return patternList; +} + +// v2 list +// https://cdn.branch.io/sdk/uriskiplist_v2.json +- (NSArray *)v2PatternList { + NSArray *patternList = @[ + @"^fb\\d+:((?!campaign_ids).)*$", + @"^li\\d+:", + @"^pdk\\d+:", + @"^twitterkit-.*:", + @"^com\\.googleusercontent\\.apps\\.\\d+-.*:\\/oauth", + @"^(?i)(?!(http|https):).*(:|:.*\\b)(password|o?auth|o?auth.?token|access|access.?token)\\b", + @"^(?i)((http|https):\\/\\/).*[\\/|?|#].*\\b(password|o?auth|o?auth.?token|access|access.?token)\\b" + ]; + return patternList; +} + +- (BNCURLFilter *)filterWithV0List { + BNCURLFilter *filter = [BNCURLFilter new]; + [self migrateFilter:filter patternList:[self v1PatternList]]; + return filter; +} + +- (BNCURLFilter *)filterWithV1List { + BNCURLFilter *filter = [BNCURLFilter new]; + [self migrateFilter:filter patternList:[self v1PatternList]]; + return filter; +} + +- (BNCURLFilter *)filterWithV2List { + BNCURLFilter *filter = [BNCURLFilter new]; + [self migrateFilter:filter patternList:[self v2PatternList]]; + return filter; +} + +- (void)migrateFilter:(BNCURLFilter *)filter patternList:(NSArray *)patternList { + [filter useCustomPatternList:patternList]; +} + +- (NSArray *)badURLs { + NSArray *kBadURLs = @[ + @"fb123456:login/464646", + @"twitterkit-.4545:", + @"shsh:oauth/login", + @"https://myapp.app.link/oauth_token=fred", + @"https://myapp.app.link/auth_token=fred", + @"https://myapp.app.link/authtoken=fred", + @"https://myapp.app.link/auth=fred", + @"fb1234:", + @"fb1234:/", + @"fb1234:/this-is-some-extra-info/?whatever", + @"fb1234:/this-is-some-extra-info/?whatever:andstuff", + @"myscheme:path/to/resource?oauth=747474", + @"myscheme:oauth=747474", + @"myscheme:/oauth=747474", + @"myscheme://oauth=747474", + @"myscheme://path/oauth=747474", + @"myscheme://path/:oauth=747474", + @"https://google.com/userprofile/devonbanks=oauth?", + ]; + return kBadURLs; +} + +- (NSArray *)goodURLs { + NSArray *kGoodURLs = @[ + @"shshs:/content/path", + @"shshs:content/path", + @"https://myapp.app.link/12345/link", + @"fb123x:/", + @"https://myapp.app.link?authentic=true&tokemonsta=false", + @"myscheme://path/brauth=747474", + ]; + return kGoodURLs; +} + +- (void)testOldBadURLsWithV0 { + BNCURLFilter *filter = [self filterWithV0List]; + NSArray *list = [self badURLs]; + for (NSString *string in list) { + NSURL *url = [NSURL URLWithString:string]; + if (url) { + XCTAssertTrue([filter shouldIgnoreURL:url], @"Checking '%@'.", url); + } + } +} + +- (void)testOldGoodURLsWithV0 { + BNCURLFilter *filter = [self filterWithV0List]; + NSArray *list = [self goodURLs]; + for (NSString *string in list) { + NSURL *url = [NSURL URLWithString:string]; + if (url) { + XCTAssertFalse([filter shouldIgnoreURL:url], @"Checking '%@'.", url); + } + } +} + +- (void)testOldBadURLsWithV2 { + BNCURLFilter *filter = [self filterWithV2List]; + NSArray *list = [self badURLs]; + for (NSString *string in list) { + NSURL *url = [NSURL URLWithString:string]; + if (url) { + XCTAssertTrue([filter shouldIgnoreURL:url], @"Checking '%@'.", url); + } + } +} + +- (void)testOldGoodURLsWithV2 { + BNCURLFilter *filter = [self filterWithV2List]; + NSArray *list = [self goodURLs]; + for (NSString *string in list) { + NSURL *url = [NSURL URLWithString:string]; + if (url) { + XCTAssertFalse([filter shouldIgnoreURL:url], @"Checking '%@'.", url); + } + } +} + +- (void)testMetaAEMWithV0 { + NSString *string = @"fb1://?campaign_ids=a"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV0List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +- (void)testMetaAEMWithV2 { + NSString *string = @"fb1://?campaign_ids=a"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testMetaAEMWithV2WithTrailingParameters { + NSString *string = @"fb1://?campaign_ids=a&token=abcde"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testMetaAEMWithV2WithPrecedingParameters { + NSString *string = @"fb1://?brand=abcde&campaign_ids=a"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testMetaAEMWithV2WithPrecedingAndTrailingParameters { + NSString *string = @"fb1://?brand=abcde&campaign_ids=a&link=12345"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMWithV0 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV0List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMWithV1 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV1List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +// This one is not filtered! +- (void)testSampleMetaAEMWithV2 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMNoCampignIDsWithV0 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV0List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMNoCampignIDsWithV1 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV1List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMNoCampignIDsWithV2 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +@end diff --git a/BranchSDKTests/BNCURLFilterTests.m b/BranchSDKTests/BNCURLFilterTests.m new file mode 100644 index 000000000..1573bc36e --- /dev/null +++ b/BranchSDKTests/BNCURLFilterTests.m @@ -0,0 +1,168 @@ +/** + @file BNCURLFilterTests.m + @package Branch-SDK-Tests + @brief BNCURLFilter tests. + + @author Edward Smith + @date February 14, 2018 + @copyright Copyright © 2018 Branch. All rights reserved. +*/ + +#import +#import "BNCURLFilter.h" + +@interface BNCURLFilterTests : XCTestCase +@end + +@implementation BNCURLFilterTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testPatternMatchingURL_nil { + BNCURLFilter *filter = [BNCURLFilter new]; + NSURL *url = nil; + NSString *matchingRegex = [filter patternMatchingURL:url]; + XCTAssertNil(matchingRegex); +} + +- (void)testPatternMatchingURL_emptyString { + BNCURLFilter *filter = [BNCURLFilter new]; + NSURL *url = [NSURL URLWithString:@""]; + NSString *matchingRegex = [filter patternMatchingURL:url]; + XCTAssertNil(matchingRegex); +} + +- (void)testPatternMatchingURL_fbRegexMatches { + NSString *pattern = @"^fb\\d+:((?!campaign_ids).)*$"; + NSString *sampleURL = @"fb12345://"; + + BNCURLFilter *filter = [BNCURLFilter new]; + NSURL *url = [NSURL URLWithString:sampleURL]; + NSString *matchingRegex = [filter patternMatchingURL:url]; + XCTAssertTrue([pattern isEqualToString:matchingRegex]); +} + +- (void)testPatternMatchingURL_fbRegexDoesNotMatch { + NSString *pattern = @"^fb\\d+:((?!campaign_ids).)*$"; + NSString *sampleURL = @"fb12345://campaign_ids"; + + BNCURLFilter *filter = [BNCURLFilter new]; + NSURL *url = [NSURL URLWithString:sampleURL]; + NSString *matchingRegex = [filter patternMatchingURL:url]; + XCTAssertFalse([pattern isEqualToString:matchingRegex]); +} + + +- (void)testIgnoredSuspectedAuthURLs { + NSArray *urls = @[ + @"fb123456:login/464646", + @"shsh:oauth/login", + @"https://myapp.app.link/oauth_token=fred", + @"https://myapp.app.link/auth_token=fred", + @"https://myapp.app.link/authtoken=fred", + @"https://myapp.app.link/auth=fred", + @"myscheme:path/to/resource?oauth=747474", + @"myscheme:oauth=747474", + @"myscheme:/oauth=747474", + @"myscheme://oauth=747474", + @"myscheme://path/oauth=747474", + @"myscheme://path/:oauth=747474", + @"https://google.com/userprofile/devonbanks=oauth?" + ]; + + BNCURLFilter *filter = [BNCURLFilter new]; + for (NSString *string in urls) { + NSURL *URL = [NSURL URLWithString:string]; + XCTAssertTrue([filter shouldIgnoreURL:URL], @"Checking '%@'.", URL); + } +} + +- (void)testAllowedURLsSimilarToAuthURLs { + NSArray *urls = @[ + @"shshs:/content/path", + @"shshs:content/path", + @"https://myapp.app.link/12345/link", + @"https://myapp.app.link?authentic=true&tokemonsta=false", + @"myscheme://path/brauth=747474" + ]; + + BNCURLFilter *filter = [BNCURLFilter new]; + for (NSString *string in urls) { + NSURL *URL = [NSURL URLWithString:string]; + XCTAssertFalse([filter shouldIgnoreURL:URL], @"Checking '%@'", URL); + } +} + +- (void)testIgnoredFacebookURLs { + // Most FB URIs are ignored + NSArray *urls = @[ + @"fb123456://login/464646", + @"fb1234:", + @"fb1234:/", + @"fb1234:/this-is-some-extra-info/?whatever", + @"fb1234:/this-is-some-extra-info/?whatever:andstuff" + ]; + + BNCURLFilter *filter = [BNCURLFilter new]; + for (NSString *string in urls) { + NSURL *URL = [NSURL URLWithString:string]; + XCTAssertTrue([filter shouldIgnoreURL:URL], @"Checking '%@'.", URL); + } +} + +- (void)testAllowedFacebookURLs { + NSArray *urls = @[ + // Facebook URIs do not contain letters other than an fb prefix + @"fb123x://", + // FB URIs with campaign ids are allowed + @"fb1234://helloworld?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D" + ]; + + BNCURLFilter *filter = [BNCURLFilter new]; + for (NSString *string in urls) { + NSURL *URL = [NSURL URLWithString:string]; + XCTAssertFalse([filter shouldIgnoreURL:URL], @"Checking '%@'", URL); + } +} + +- (void)testCustomPatternList { + BNCURLFilter *filter = [BNCURLFilter new]; + + // sanity check default pattern list + XCTAssertTrue([filter shouldIgnoreURL:[NSURL URLWithString:@"fb123://"]]); + XCTAssertFalse([filter shouldIgnoreURL:[NSURL URLWithString:@"branch123://"]]); + + // confirm new pattern list is enforced + [filter useCustomPatternList:@[@"^branch\\d+:"]]; + XCTAssertFalse([filter shouldIgnoreURL:[NSURL URLWithString:@"fb123://"]]); + XCTAssertTrue([filter shouldIgnoreURL:[NSURL URLWithString:@"branch123://"]]); +} + +// This is an end to end test and relies on a server call +- (void)testUpdatePatternListFromServer { + BNCURLFilter *filter = [BNCURLFilter new]; + + // confirm new pattern list is enforced + [filter useCustomPatternList:@[@"^branch\\d+:"]]; + XCTAssertFalse([filter shouldIgnoreURL:[NSURL URLWithString:@"fb123://"]]); + XCTAssertTrue([filter shouldIgnoreURL:[NSURL URLWithString:@"branch123://"]]); + + __block XCTestExpectation *expectation = [self expectationWithDescription:@"List updated"]; + [filter updatePatternListFromServerWithCompletion:^{ + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:5.0 handler:^(NSError * _Nullable error) { }]; + + // the retrieved list should match default pattern list + XCTAssertTrue([filter shouldIgnoreURL:[NSURL URLWithString:@"fb123://"]]); + XCTAssertFalse([filter shouldIgnoreURL:[NSURL URLWithString:@"branch123://"]]); +} + +@end diff --git a/BranchSDKTests/BNCUserAgentCollectorTests.m b/BranchSDKTests/BNCUserAgentCollectorTests.m new file mode 100644 index 000000000..e54cca1bc --- /dev/null +++ b/BranchSDKTests/BNCUserAgentCollectorTests.m @@ -0,0 +1,111 @@ +// +// BNCUserAgentCollectorTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 8/29/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCPreferenceHelper.h" +#import "BNCDeviceSystem.h" +#import "BNCUserAgentCollector.h" + +// expose private methods for unit testing +@interface BNCUserAgentCollector() + +- (NSString *)loadUserAgentForSystemBuildVersion:(NSString *)systemBuildVersion; +- (void)saveUserAgent:(NSString *)userAgent forSystemBuildVersion:(NSString *)systemBuildVersion; +- (void)collectUserAgentWithCompletion:(void (^)(NSString * _Nullable userAgent))completion; + +@end + +@interface BNCUserAgentCollectorTests : XCTestCase + +@end + +@implementation BNCUserAgentCollectorTests + ++ (void)setUp { + [BNCUserAgentCollectorTests resetPersistentData]; +} + +- (void)setUp { + +} + +- (void)tearDown { + [BNCUserAgentCollectorTests resetPersistentData]; +} + ++ (void)resetPersistentData { + BNCPreferenceHelper *preferences = [BNCPreferenceHelper sharedInstance]; + preferences.browserUserAgentString = nil; + preferences.lastSystemBuildVersion = nil; +} + +- (void)testResetPersistentData { + BNCPreferenceHelper *preferences = [BNCPreferenceHelper sharedInstance]; + XCTAssertNil(preferences.browserUserAgentString); + XCTAssertNil(preferences.lastSystemBuildVersion); +} + +- (void)testSaveAndLoadUserAgent { + NSString *systemBuildVersion = @"test"; + NSString *userAgent = @"UserAgent"; + + BNCUserAgentCollector *collector = [BNCUserAgentCollector new]; + [collector saveUserAgent:userAgent forSystemBuildVersion:systemBuildVersion]; + NSString *expected = [collector loadUserAgentForSystemBuildVersion:systemBuildVersion]; + XCTAssertTrue([userAgent isEqualToString:expected]); +} + +- (void)testCollectUserAgent { + XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"]; + + BNCUserAgentCollector *collector = [BNCUserAgentCollector new]; + [collector collectUserAgentWithCompletion:^(NSString * _Nullable userAgent) { + XCTAssertNotNil(userAgent); + XCTAssertTrue([userAgent containsString:@"AppleWebKit"]); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:4.0 handler:^(NSError * _Nullable error) { + + }]; +} + +- (void)testLoadUserAgent_EmptyDataStore { + XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"]; + + BNCUserAgentCollector *collector = [BNCUserAgentCollector new]; + [collector loadUserAgentWithCompletion:^(NSString * _Nullable userAgent) { + XCTAssertNotNil(userAgent); + XCTAssertTrue([userAgent containsString:@"AppleWebKit"]); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:2.0 handler:^(NSError * _Nullable error) { + + }]; +} + +- (void)testLoadUserAgent_FilledDataStore { + XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"]; + NSString *savedUserAgent = @"UserAgent"; + + BNCUserAgentCollector *collector = [BNCUserAgentCollector new]; + [collector saveUserAgent:savedUserAgent forSystemBuildVersion:[BNCDeviceSystem new].systemBuildVersion]; + [collector loadUserAgentWithCompletion:^(NSString * _Nullable userAgent) { + XCTAssertNotNil(userAgent); + XCTAssertTrue([userAgent isEqualToString:savedUserAgent]); + XCTAssertFalse([userAgent containsString:@"AppleWebKit"]); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:2.0 handler:^(NSError * _Nullable error) { + + }]; +} + +@end diff --git a/BranchSDKTests/Branch-SDK-Tests-Bridging-Header.h b/BranchSDKTests/Branch-SDK-Tests-Bridging-Header.h new file mode 100644 index 000000000..169bd50f3 --- /dev/null +++ b/BranchSDKTests/Branch-SDK-Tests-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Module headers for Branch SDK unit testing. +// + +#import "Branch.h" diff --git a/BranchSDKTests/BranchActivityItemTests.m b/BranchSDKTests/BranchActivityItemTests.m new file mode 100644 index 000000000..f117859f7 --- /dev/null +++ b/BranchSDKTests/BranchActivityItemTests.m @@ -0,0 +1,39 @@ +// +// BranchActivityItemTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 9/21/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "Branch.h" + +@interface BranchActivityItemTests: XCTestCase +@end + +@implementation BranchActivityItemTests + +// Rework this test, it's not reliable. +//- (void)testGetBranchActivityItemWithAllParams { +// NSDictionary *params = @{@"key": @"value"}; +// NSString *feature = @"feature4"; +// NSString *stage = @"stage3"; +// NSArray *tags = @[@"tag3", @"tag4"]; +// NSString *campaign = @"campaign1"; +// NSString *alias = [[NSUUID UUID] UUIDString]; +// BranchActivityItemProvider *provider = [Branch getBranchActivityItemWithParams:params feature:feature stage:stage campaign:campaign tags:tags alias:alias]; +// sleep(2000); +// if ([[provider item] isKindOfClass:[NSURL class]]) { +// NSURL *urlObject = (NSURL *)[provider item]; +// NSString *url = [urlObject absoluteString]; +// +// NSLog(@"Provider URL as String: %@", url); +// +// XCTAssertTrue([url isEqualToString:[@"https://bnctestbed.app.link/" stringByAppendingString:alias]]); +// } else { +// XCTFail("Provider Data is not of type NSURL"); +// } +//} + +@end diff --git a/BranchSDKTests/BranchClassTests.m b/BranchSDKTests/BranchClassTests.m new file mode 100644 index 000000000..d1e7713f1 --- /dev/null +++ b/BranchSDKTests/BranchClassTests.m @@ -0,0 +1,265 @@ +// +// BranchClassTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 9/25/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "Branch.h" +#import "BranchConstants.h" +#import "BNCPasteboard.h" +#import "BNCAppGroupsData.h" +#import "BNCPartnerParameters.h" + +@interface BNCPreferenceHelper(Test) +// Expose internal private method to clear EEA data +- (void)writeObjectToDefaults:(NSString *)key value:(NSObject *)value; +@end + +@interface BranchClassTests : XCTestCase +@property (nonatomic, strong) Branch *branch; +@end + +@implementation BranchClassTests + +- (void)setUp { + [super setUp]; + self.branch = [Branch getInstance]; +} + +- (void)tearDown { + self.branch = nil; + [super tearDown]; +} + +- (void)testIsUserIdentified { + [self.branch setIdentity: @"userId"]; + XCTAssertTrue([self.branch isUserIdentified], @"User should be identified"); +} + +- (void)testDisableAdNetworkCallouts { + [self.branch disableAdNetworkCallouts:YES]; + XCTAssertTrue([BNCPreferenceHelper sharedInstance].disableAdNetworkCallouts, @"AdNetwork callouts should be disabled"); +} + +- (void)testSetNetworkTimeout { + [self.branch setNetworkTimeout:5.0]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].timeout, 5.0, @"Network timeout should be set to 5.0"); +} + +//- (void)testSetMaxRetries { +// [self.branch setMaxRetries:3]; +// XCTAssertEqual([BNCPreferenceHelper sharedInstance].retryCount, 3, @"Max retries should be set to 3"); +//} + +- (void)testSetRetryInterval { + [self.branch setRetryInterval:2.0]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].retryInterval, 2.0, @"Retry interval should be set to 2.0"); +} + +- (void)testSetRequestMetadataKeyAndValue { + [self.branch setRequestMetadataKey:@"key" value:@"value"]; + NSDictionary *metadata = [BNCPreferenceHelper sharedInstance].requestMetadataDictionary; + XCTAssertEqualObjects(metadata[@"key"], @"value"); +} + +- (void)testSetTrackingDisabled { + XCTAssertFalse([BNCPreferenceHelper sharedInstance].trackingDisabled); + + [Branch setTrackingDisabled:YES]; + XCTAssertTrue([BNCPreferenceHelper sharedInstance].trackingDisabled); + + [Branch setTrackingDisabled:NO]; + XCTAssertFalse([BNCPreferenceHelper sharedInstance].trackingDisabled); +} + +- (void)testCheckPasteboardOnInstall { + [self.branch checkPasteboardOnInstall]; + BOOL checkOnInstall = [BNCPasteboard sharedInstance].checkOnInstall; + XCTAssertTrue(checkOnInstall); +} + +- (void)testWillShowPasteboardToast_ShouldReturnYes { + [BNCPreferenceHelper sharedInstance].randomizedBundleToken = nil; + [BNCPasteboard sharedInstance].checkOnInstall = YES; + UIPasteboard.generalPasteboard.URL = [NSURL URLWithString:@"https://example.com"]; + + BOOL result = [self.branch willShowPasteboardToast]; + XCTAssertTrue(result); +} + +- (void)testWillShowPasteboardToast_ShouldReturnNo { + [BNCPreferenceHelper sharedInstance].randomizedBundleToken = @"some_token"; + [BNCPasteboard sharedInstance].checkOnInstall = NO; + + BOOL result = [self.branch willShowPasteboardToast]; + XCTAssertFalse(result); +} + +- (void)testSetAppClipAppGroup { + NSString *testAppGroup = @"testAppGroup"; + [self.branch setAppClipAppGroup:testAppGroup]; + NSString *actualAppGroup = [BNCAppGroupsData shared].appGroup; + + XCTAssertEqualObjects(testAppGroup, actualAppGroup); +} + +- (void)testClearPartnerParameters { + [self.branch addFacebookPartnerParameterWithName:@"ph" value:@"123456789"]; + [[BNCPartnerParameters shared] clearAllParameters]; + + NSDictionary *result = [[BNCPartnerParameters shared] parameterJson]; + XCTAssertEqual([result count], 0, @"Parameters should be empty after calling clearAllParameters"); +} + +- (void)testAddFacebookParameterWithName_Value { + [self.branch addFacebookPartnerParameterWithName:@"name" value:@"3D4F2BF07DC1BE38B20C653EE9A7E446158F84E525BBB98FEDF721CB5A40A346"]; + + NSDictionary *result = [[BNCPartnerParameters shared] parameterJson][@"fb"]; + XCTAssertEqualObjects(result[@"name"], @"3D4F2BF07DC1BE38B20C653EE9A7E446158F84E525BBB98FEDF721CB5A40A346", @"Should add parameter for Facebook"); +} + +- (void)testAddSnapParameterWithName_Value { + [self.branch addSnapPartnerParameterWithName:@"name" value:@"3D4F2BF07DC1BE38B20C653EE9A7E446158F84E525BBB98FEDF721CB5A40A346"]; + + NSDictionary *result = [[BNCPartnerParameters shared] parameterJson][@"snap"]; + XCTAssertEqualObjects(result[@"name"], @"3D4F2BF07DC1BE38B20C653EE9A7E446158F84E525BBB98FEDF721CB5A40A346", @"Should add parameter for Snap"); +} + +- (void)testGetFirstReferringBranchUniversalObject_ClickedBranchLink { + NSString *installParamsString = @"{\"$canonical_identifier\":\"content/12345\",\"$creation_timestamp\":1694557342247,\"$desktop_url\":\"https://example.com/home\",\"$og_description\":\"My Content Description\",\"$og_title\":\"My Content Title\",\"+click_timestamp\":1695749249,\"+clicked_branch_link\":1,\"+is_first_session\":1,\"+match_guaranteed\":1,\"custom\":\"data\",\"key1\":\"value1\",\"~campaign\":\"content 123 launch\",\"~channel\":\"facebook\",\"~creation_source\":3,\"~feature\":\"sharing\",\"~id\":1230269548213984984,\"~referring_link\":\"https://bnctestbed.app.link/uSPHktjO2Cb\"}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams: installParamsString]; + + BranchUniversalObject *result = [self.branch getFirstReferringBranchUniversalObject];\ + XCTAssertNotNil(result); + XCTAssertEqualObjects(result.title, @"My Content Title"); + XCTAssertEqualObjects(result.canonicalIdentifier, @"content/12345"); +} + +- (void)testGetFirstReferringBranchUniversalObject_NotClickedBranchLink { + NSString *installParamsString = @"{\"+clicked_branch_link\":false,\"+is_first_session\":true}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams: installParamsString]; + + BranchUniversalObject *result = [self.branch getFirstReferringBranchUniversalObject]; + XCTAssertNil(result); +} + +- (void)testGetFirstReferringBranchLinkProperties_ClickedBranchLink { + NSString *installParamsString = @"{\"+clicked_branch_link\":1,\"+is_first_session\":1,\"~campaign\":\"content 123 launch\"}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams:installParamsString]; + + BranchLinkProperties *result = [self.branch getFirstReferringBranchLinkProperties]; + XCTAssertNotNil(result); + XCTAssertEqualObjects(result.campaign, @"content 123 launch"); +} + +- (void)testGetFirstReferringBranchLinkProperties_NotClickedBranchLink { + NSString *installParamsString = @"{\"+clicked_branch_link\":false,\"+is_first_session\":true}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams:installParamsString]; + + BranchLinkProperties *result = [self.branch getFirstReferringBranchLinkProperties]; + XCTAssertNil(result); +} + +- (void)testGetFirstReferringParams { + NSString *installParamsString = @"{\"+clicked_branch_link\":true,\"+is_first_session\":true}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams:installParamsString]; + + NSDictionary *result = [self.branch getFirstReferringParams]; + XCTAssertEqualObjects([result objectForKey:@"+clicked_branch_link"], @true); +} + +- (void)testGetLatestReferringParams { + NSString *sessionParamsString = @"{\"+clicked_branch_link\":true,\"+is_first_session\":false}"; + [[BNCPreferenceHelper sharedInstance] setSessionParams:sessionParamsString]; + + NSDictionary *result = [self.branch getLatestReferringParams]; + XCTAssertEqualObjects([result objectForKey:@"+clicked_branch_link"], @true); +} + +//- (void)testGetLatestReferringParamsSynchronous { +// NSString *sessionParamsString = @"{\"+clicked_branch_link\":true,\"+is_first_session\":false}"; +// [[BNCPreferenceHelper sharedInstance] setSessionParams:sessionParamsString]; +// +// NSDictionary *result = [self.branch getLatestReferringParamsSynchronous]; +// XCTAssertEqualObjects([result objectForKey:@"+clicked_branch_link"], @true); +//} + +- (void)testGetLatestReferringBranchUniversalObject_ClickedBranchLink { + NSString *sessionParamsString = @"{\"+clicked_branch_link\":1,\"+is_first_session\":false,\"$og_title\":\"My Latest Content\"}"; + [[BNCPreferenceHelper sharedInstance] setSessionParams:sessionParamsString]; + + BranchUniversalObject *result = [self.branch getLatestReferringBranchUniversalObject]; + XCTAssertNotNil(result); + XCTAssertEqualObjects(result.title, @"My Latest Content"); +} + +- (void)testGetLatestReferringBranchLinkProperties_ClickedBranchLink { + NSString *sessionParamsString = @"{\"+clicked_branch_link\":true,\"+is_first_session\":false,\"~campaign\":\"latest campaign\"}"; + [[BNCPreferenceHelper sharedInstance] setSessionParams:sessionParamsString]; + + BranchLinkProperties *result = [self.branch getLatestReferringBranchLinkProperties]; + XCTAssertNotNil(result); + XCTAssertEqualObjects(result.campaign, @"latest campaign"); +} + +- (void)testGetShortURL { + NSString *shortURL = [self.branch getShortURL]; + XCTAssertNotNil(shortURL, @"URL should not be nil"); + XCTAssertTrue([shortURL hasPrefix:@"https://"], @"URL should start with 'https://'"); +} + +- (void)testGetLongURLWithParamsAndChannelAndTagsAndFeatureAndStageAndAlias { + NSDictionary *params = @{@"key": @"value"}; + NSString *channel = @"channel1"; + NSArray *tags = @[@"tag1", @"tag2"]; + NSString *feature = @"feature1"; + NSString *stage = @"stage1"; + NSString *alias = @"alias1"; + + NSString *generatedURL = [self.branch getLongURLWithParams:params andChannel:channel andTags:tags andFeature:feature andStage:stage andAlias:alias]; + NSString *expectedURL = @"https://bnc.lt/a/key_live_hcnegAumkH7Kv18M8AOHhfgiohpXq5tB?tags=tag1&tags=tag2&alias=alias1&feature=feature1&stage=stage1&source=ios&data=eyJrZXkiOiJ2YWx1ZSJ9"; + + XCTAssertEqualObjects(generatedURL, expectedURL, @"URL should match the expected format"); +} + +- (void)testSetDMAParamsForEEA { + XCTAssertFalse([[BNCPreferenceHelper sharedInstance] eeaRegionInitialized]); + + [Branch setDMAParamsForEEA:FALSE AdPersonalizationConsent:TRUE AdUserDataUsageConsent:TRUE]; + XCTAssertTrue([[BNCPreferenceHelper sharedInstance] eeaRegionInitialized]); + XCTAssertFalse([BNCPreferenceHelper sharedInstance].eeaRegion); + XCTAssertTrue([BNCPreferenceHelper sharedInstance].adPersonalizationConsent); + XCTAssertTrue([BNCPreferenceHelper sharedInstance].adUserDataUsageConsent); + + // Manually clear values after testing + // By design, this API is meant to be set once and always set. However, in a test scenario it needs to be cleared. + [[BNCPreferenceHelper sharedInstance] writeObjectToDefaults:@"bnc_dma_eea" value:nil]; + [[BNCPreferenceHelper sharedInstance] writeObjectToDefaults:@"bnc_dma_ad_personalization" value:nil]; + [[BNCPreferenceHelper sharedInstance] writeObjectToDefaults:@"bnc_dma_ad_user_data" value:nil]; +} + +- (void)testSetConsumerProtectionAttributionLevel { + // Set to Reduced and check + Branch *branch = [Branch getInstance]; + [branch setConsumerProtectionAttributionLevel:BranchAttributionLevelReduced]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].attributionLevel, BranchAttributionLevelReduced); + + // Set to Minimal and check + [branch setConsumerProtectionAttributionLevel:BranchAttributionLevelMinimal]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].attributionLevel, BranchAttributionLevelMinimal); + + // Set to None and check + [branch setConsumerProtectionAttributionLevel:BranchAttributionLevelNone]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].attributionLevel, BranchAttributionLevelNone); + + // Set to Full and check + [branch setConsumerProtectionAttributionLevel:BranchAttributionLevelFull]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].attributionLevel, BranchAttributionLevelFull); + +} + + +@end diff --git a/BranchSDKTests/BranchConfigurationControllerTests.m b/BranchSDKTests/BranchConfigurationControllerTests.m new file mode 100644 index 000000000..74acc4106 --- /dev/null +++ b/BranchSDKTests/BranchConfigurationControllerTests.m @@ -0,0 +1,105 @@ +// +// BranchConfigurationControllerTests.m +// Branch-SDK-Tests +// +// Created by Nidhi Dixit on 6/12/25. +// + + +#import +#import "BranchConstants.h" +#import "BNCRequestFactory.h" +#import "BNCEncodingUtils.h" + +#if SWIFT_PACKAGE +@import BranchSwiftSDK; +#else +#import "BranchSDK/BranchSDK-Swift.h" +#endif + +@interface BranchConfigurationControllerTests : XCTestCase +@end + +@implementation BranchConfigurationControllerTests + +- (void)testSingletonInstance { + + ConfigurationController *instance1 = [ConfigurationController shared]; + XCTAssertNotNil(instance1); + + ConfigurationController *instance2 = [ConfigurationController shared]; + XCTAssertEqual(instance1, instance2); +} + +- (void)testPropertySettersAndGetters { + ConfigurationController *configController = [ConfigurationController shared]; + + NSString *keySource = BRANCH_KEY_SOURCE_GET_INSTANCE_API; + configController.branchKeySource = keySource; + XCTAssertTrue([configController.branchKeySource isEqualToString:keySource]); + + configController.deferInitForPluginRuntime = YES; + XCTAssertTrue(configController.deferInitForPluginRuntime); + configController.deferInitForPluginRuntime = NO; + XCTAssertFalse(configController.deferInitForPluginRuntime); + + configController.checkPasteboardOnInstall = YES; + XCTAssertTrue(configController.checkPasteboardOnInstall); + configController.checkPasteboardOnInstall = NO; + XCTAssertFalse(configController.checkPasteboardOnInstall); +} + +- (void)testGetConfiguration { + ConfigurationController *configController = [ConfigurationController shared]; + configController.branchKeySource = BRANCH_KEY_SOURCE_INFO_PLIST; + configController.deferInitForPluginRuntime = YES; + configController.checkPasteboardOnInstall = YES; + + NSDictionary *configDict = [configController getConfiguration]; + XCTAssertNotNil(configDict); + + XCTAssertTrue([configDict[BRANCH_REQUEST_KEY_BRANCH_KEY_SOURCE] isEqualToString:BRANCH_KEY_SOURCE_INFO_PLIST]); + XCTAssertEqualObjects(configDict[BRANCH_REQUEST_KEY_DEFER_INIT_FOR_PLUGIN_RUNTIME], @(YES)); + XCTAssertEqualObjects(configDict[BRANCH_REQUEST_KEY_CHECK_PASTEBOARD_ON_INSTALL], @(YES)); + + NSDictionary *frameworks = configDict[BRANCH_REQUEST_KEY_LINKED_FRAMEORKS]; + XCTAssertNotNil(frameworks); + + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_SUPPORT], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_ATT_TRACKING_MANAGER], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_FIREBASE_CRASHLYTICS], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_SAFARI_SERVICES], @(NO)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_APP_ADS_ONDEVICE_CONVERSION], @(NO)); + +} + +- (void)testInstallRequestParams { + ConfigurationController *configController = [ConfigurationController shared]; + configController.branchKeySource = BRANCH_KEY_SOURCE_INFO_PLIST; + configController.deferInitForPluginRuntime = YES; + configController.checkPasteboardOnInstall = YES; + + NSString* requestUUID = [[NSUUID UUID ] UUIDString]; + NSNumber* requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:requestUUID TimeStamp:requestCreationTimeStamp]; + NSDictionary *installDict = [factory dataForInstallWithURLString:@"https://branch.io"]; + + NSDictionary *configDict = installDict[BRANCH_REQUEST_KEY_OPERATIONAL_METRICS]; + XCTAssertNotNil(configDict); + + XCTAssertTrue([configDict[BRANCH_REQUEST_KEY_BRANCH_KEY_SOURCE] isEqualToString:BRANCH_KEY_SOURCE_INFO_PLIST]); + XCTAssertEqualObjects(configDict[BRANCH_REQUEST_KEY_DEFER_INIT_FOR_PLUGIN_RUNTIME], @(YES)); + XCTAssertEqualObjects(configDict[BRANCH_REQUEST_KEY_CHECK_PASTEBOARD_ON_INSTALL], @(YES)); + + NSDictionary *frameworks = configDict[BRANCH_REQUEST_KEY_LINKED_FRAMEORKS]; + XCTAssertNotNil(frameworks); + + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_SUPPORT], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_ATT_TRACKING_MANAGER], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_FIREBASE_CRASHLYTICS], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_SAFARI_SERVICES], @(NO)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_APP_ADS_ONDEVICE_CONVERSION], @(NO)); + +} + +@end diff --git a/BranchSDKTests/BranchEvent.Test.m b/BranchSDKTests/BranchEvent.Test.m new file mode 100644 index 000000000..ddb3d220f --- /dev/null +++ b/BranchSDKTests/BranchEvent.Test.m @@ -0,0 +1,575 @@ +// +// BranchEvent.Test.m +// Branch-SDK-Tests +// +// Created by Edward Smith on 8/15/17. +// Copyright © 2017 Branch Metrics. All rights reserved. +// +#import +#import "BNCPreferenceHelper.h" +#import "BranchConstants.h" +#import "BranchEvent.h" +#import "BNCDeviceInfo.h" +#import "NSError+Branch.h" + +@interface Branch (BranchEventTest) +- (void) processNextQueueItem; +@end + +@interface BranchEvent() + +- (NSString *)jsonStringForAdType:(BranchEventAdType)adType; + +// private BranchEvent methods used to check data before sending to network service. +- (NSDictionary *)buildEventDictionary; +- (BranchEventRequest *)buildRequestWithEventDictionary:(NSDictionary *)eventDictionary; + +@end + +@interface BranchEventTest : XCTestCase +@end + +@implementation BranchEventTest + +- (void)setUp { + [BNCPreferenceHelper sharedInstance].randomizedBundleToken = @"575759106028389737"; + [[BNCPreferenceHelper sharedInstance] clearInstrumentationDictionary]; +} + +- (void)tearDown { + +} + +// TODO: fix this test +- (void)testDescription { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventPurchase]; + event.transactionID = @"1234"; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"10.50"]; + event.eventDescription= @"Event description."; + event.customData = (NSMutableDictionary*) @{ + @"Key1": @"Value1" + }; + + NSString *d = event.description; +// BNCTAssertEqualMaskedString(d, +// @""); +} + +- (void)testExampleSyntax { + BranchUniversalObject *contentItem = [BranchUniversalObject new]; + contentItem.canonicalIdentifier = @"item/123"; + contentItem.canonicalUrl = @"https://branch.io/item/123"; + contentItem.contentMetadata.ratingAverage = 5.0; + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventCompleteRegistration]; + event.eventDescription = @"Product Search"; + event.searchQuery = @"product name"; + event.customData = @{ @"rating": @"5" }; + + [event logEvent]; +} + +- (void)testStandardInviteEvent { + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventInvite]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"INVITE"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomInviteEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"INVITE"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"INVITE"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardLoginEvent { + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventLogin]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"LOGIN"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomLoginEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"LOGIN"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"LOGIN"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardReserveEvent { + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventReserve]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"RESERVE"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomReserveEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"RESERVE"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"RESERVE"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardSubscribeEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventSubscribe]; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"1.0"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"SUBSCRIBE"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"currency"] isEqualToString:BNCCurrencyUSD]); + XCTAssert([eventData[@"revenue"] isEqual:[NSDecimalNumber decimalNumberWithString:@"1.0"]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomSubscribeEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"SUBSCRIBE"]; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"1.0"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"SUBSCRIBE"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"currency"] isEqualToString:BNCCurrencyUSD]); + XCTAssert([eventData[@"revenue"] isEqual:[NSDecimalNumber decimalNumberWithString:@"1.0"]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardStartTrialEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventStartTrial]; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"1.0"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"START_TRIAL"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"currency"] isEqualToString:BNCCurrencyUSD]); + XCTAssert([eventData[@"revenue"] isEqual:[NSDecimalNumber decimalNumberWithString:@"1.0"]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomStartTrialEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"START_TRIAL"]; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"1.0"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"START_TRIAL"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"currency"] isEqualToString:BNCCurrencyUSD]); + XCTAssert([eventData[@"revenue"] isEqual:[NSDecimalNumber decimalNumberWithString:@"1.0"]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardClickAdEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventClickAd]; + event.adType = BranchEventAdTypeBanner; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"CLICK_AD"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"ad_type"] isEqual:[event jsonStringForAdType:event.adType]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomClickAdEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"CLICK_AD"]; + event.adType = BranchEventAdTypeBanner; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"CLICK_AD"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"ad_type"] isEqual:[event jsonStringForAdType:event.adType]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardViewAdEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + event.adType = BranchEventAdTypeBanner; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"VIEW_AD"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"ad_type"] isEqual:[event jsonStringForAdType:event.adType]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomViewAdEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"VIEW_AD"]; + event.adType = BranchEventAdTypeBanner; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"VIEW_AD"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"ad_type"] isEqual:[event jsonStringForAdType:event.adType]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardOptInEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventOptIn]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"OPT_IN"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomOptInEvent { + BranchEvent *event = [BranchEvent customEventWithName:@"OPT_IN"]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"OPT_IN"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardOptOutEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventOptOut]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"OPT_OUT"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomOptOutEvent { + BranchEvent *event = [BranchEvent customEventWithName:@"OPT_OUT"]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"OPT_OUT"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + + +- (void)testStandardInitiateStreamEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventInitiateStream]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"INITIATE_STREAM"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomInitiateStreamEvent { + BranchEvent *event = [BranchEvent customEventWithName:@"INITIATE_STREAM"]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"INITIATE_STREAM"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardCompleteStreamEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventCompleteStream]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"COMPLETE_STREAM"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomCompleteStreamEvent { + BranchEvent *event = [BranchEvent customEventWithName:@"COMPLETE_STREAM"]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"COMPLETE_STREAM"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testJsonStringForAdTypeNone { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertNil([event jsonStringForAdType:BranchEventAdTypeNone]); +} + +- (void)testJsonStringForAdTypeBanner { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertTrue([[event jsonStringForAdType:BranchEventAdTypeBanner] isEqualToString:@"BANNER"]); +} + +- (void)testJsonStringForAdTypeInterstitial { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertTrue([[event jsonStringForAdType:BranchEventAdTypeInterstitial] isEqualToString:@"INTERSTITIAL"]); +} + +- (void)testJsonStringForAdTypeRewardedVideo { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertTrue([[event jsonStringForAdType:BranchEventAdTypeRewardedVideo] isEqualToString:@"REWARDED_VIDEO"]); +} + +- (void)testJsonStringForAdTypeNative { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertTrue([[event jsonStringForAdType:BranchEventAdTypeNative] isEqualToString:@"NATIVE"]); +} + +- (void) testCustomEventWithContentItem { + BranchUniversalObject *buo = [[BranchUniversalObject new] initWithTitle:@"buoTitle"]; + BranchEvent *event = [BranchEvent customEventWithName:@"testEvent" contentItem:buo]; + + XCTAssertTrue(event.contentItems.count == 1); + XCTAssertTrue([event.contentItems.firstObject.title isEqualToString:@"buoTitle"]); +} + +- (void)testLogEventWithCompletion_InvalidEventName { + XCTestExpectation *expectation = [self expectationWithDescription:@"Logging Event"]; + BranchEvent *event = [BranchEvent customEventWithName:@""]; + + [event logEventWithCompletion:^(BOOL success, NSError * _Nullable error) { + XCTAssertFalse(success, @"Success should be NO for invalid event name"); + XCTAssertNotNil(error, @"Error should not be nil for invalid event name"); + XCTAssertEqual(error.code, BNCGeneralError, @"Error code should match expected value for invalid event name"); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:5 handler:nil]; +} + + +@end diff --git a/BranchSDKTests/BranchEvent.Test.swift b/BranchSDKTests/BranchEvent.Test.swift new file mode 100644 index 000000000..49d819cc9 --- /dev/null +++ b/BranchSDKTests/BranchEvent.Test.swift @@ -0,0 +1,129 @@ +// +// BranchEvent.Test.swift +// Branch-SDK-Tests +// +// Created by edward on 10/9/17. +// Copyright © 2017 Branch, Inc. All rights reserved. +// + +import XCTest +/* +// TODO: fix this test class, requires modules which our testbed is not using +final class BranchEventTestSwift : XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + Branch.getInstance("key_live_foo") + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testBranchEvent() throws { + + // Set up the Branch Universal Object -- + + let branchUniversalObject = BranchUniversalObject.init() + branchUniversalObject.canonicalIdentifier = "item/12345" + branchUniversalObject.canonicalUrl = "https://branch.io/deepviews" + branchUniversalObject.title = "My Content Title" + branchUniversalObject.contentDescription = "my_product_description1" + branchUniversalObject.imageUrl = "https://test_img_url" + branchUniversalObject.keywords = [ "My_Keyword1", "My_Keyword2" ] + branchUniversalObject.creationDate = Date.init(timeIntervalSince1970:1501869445321.0/1000.0) + branchUniversalObject.expirationDate = Date.init(timeIntervalSince1970:212123232544.0/1000.0) + branchUniversalObject.locallyIndex = true + branchUniversalObject.publiclyIndex = false + + branchUniversalObject.contentMetadata.contentSchema = .commerceProduct + branchUniversalObject.contentMetadata.quantity = 2 + branchUniversalObject.contentMetadata.price = 23.20 + branchUniversalObject.contentMetadata.currency = .USD + branchUniversalObject.contentMetadata.sku = "1994320302" + branchUniversalObject.contentMetadata.productName = "my_product_name1" + branchUniversalObject.contentMetadata.productBrand = "my_prod_Brand1" + branchUniversalObject.contentMetadata.productCategory = .babyToddler + branchUniversalObject.contentMetadata.productVariant = "3T" + branchUniversalObject.contentMetadata.condition = .fair + + branchUniversalObject.contentMetadata.ratingAverage = 5; + branchUniversalObject.contentMetadata.ratingCount = 5; + branchUniversalObject.contentMetadata.ratingMax = 7; + branchUniversalObject.contentMetadata.rating = 6; + branchUniversalObject.contentMetadata.addressStreet = "Street_name1" + branchUniversalObject.contentMetadata.addressCity = "city1" + branchUniversalObject.contentMetadata.addressRegion = "Region1" + branchUniversalObject.contentMetadata.addressCountry = "Country1" + branchUniversalObject.contentMetadata.addressPostalCode = "postal_code" + branchUniversalObject.contentMetadata.latitude = 12.07 + branchUniversalObject.contentMetadata.longitude = -97.5 + branchUniversalObject.contentMetadata.imageCaptions = [ + "my_img_caption1", + "my_img_caption_2" + ] + branchUniversalObject.contentMetadata.customMetadata = [ + "Custom_Content_metadata_key1": "Custom_Content_metadata_val1", + "Custom_Content_metadata_key2": "Custom_Content_metadata_val2" + ] + + // Set up the event properties -- + + let event = BranchEvent.standardEvent(.purchase) + event.transactionID = "12344555" + event.currency = .USD; + event.revenue = 1.5 + event.shipping = 10.2 + event.tax = 12.3 + event.coupon = "test_coupon"; + event.affiliation = "test_affiliation"; + event.eventDescription = "Event _description"; + event.searchQuery = "Query" + event.customData = [ + "Custom_Event_Property_Key1": "Custom_Event_Property_val1", + "Custom_Event_Property_Key2": "Custom_Event_Property_val2" + ] + + var testDictionary = event.dictionary() + var dictionary = self.mutableDictionaryFromBundleJSON(withKey: "V2EventProperties") + XCTAssert((dictionary?.isEqual(to: testDictionary))!) + + testDictionary = branchUniversalObject.dictionary() as! [AnyHashable : Any] + dictionary = self.mutableDictionaryFromBundleJSON(withKey: "BranchUniversalObjectJSON") + dictionary!["$publicly_indexable"] = nil // Remove this value since we don't add false values. + XCTAssert((dictionary?.isEqual(to: testDictionary))!) + + event.contentItems = [ branchUniversalObject ] + event.logEvent() + } + + func testExampleSyntaxSwift() throws { + let contentItem = BranchUniversalObject.init() + contentItem.canonicalIdentifier = "item/123" + contentItem.canonicalUrl = "https://branch.io/item/123" + contentItem.contentMetadata.ratingAverage = 5.0; + + var event = BranchEvent.standardEvent(.spendCredits) + event.transactionID = "tx1234" + event.eventDescription = "Product Search" + event.searchQuery = "user search query terms for product xyz" + event.customData["Custom_Event_Property_Key1"] = "Custom_Event_Property_val1" + event.contentItems = [ contentItem ] + event.logEvent() + + event = BranchEvent.standardEvent(.viewItem) + event.logEvent(); + + // Quickly log an event: + BranchEvent.standardEvent(.viewItem).logEvent() + + // Quickly log an event with content: + let branchUniversalObject = BranchUniversalObject.init() + branchUniversalObject.canonicalIdentifier = "item/12345" + branchUniversalObject.canonicalUrl = "https://branch.io/deepviews" + branchUniversalObject.title = "My Content Title" + BranchEvent.standardEvent(.viewItem, withContentItem: branchUniversalObject).logEvent() + } +} +*/ diff --git a/BranchSDKTests/BranchLastAttributedTouchDataTests.m b/BranchSDKTests/BranchLastAttributedTouchDataTests.m new file mode 100644 index 000000000..908711125 --- /dev/null +++ b/BranchSDKTests/BranchLastAttributedTouchDataTests.m @@ -0,0 +1,63 @@ +// +// BranchLastAttributedTouchDataTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 9/18/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCJsonLoader.h" +#import "BranchLastAttributedTouchData.h" + +@interface BranchLastAttributedTouchDataTests : XCTestCase + +@end + +@implementation BranchLastAttributedTouchDataTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testBuildFromJSON { + NSDictionary *json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"latd"]; + XCTAssertNotNil(json); + + BranchLastAttributedTouchData *latd = [BranchLastAttributedTouchData buildFromJSON:json]; + XCTAssertNotNil(latd); + XCTAssertNotNil(latd.lastAttributedTouchJSON); + XCTAssertNotNil(latd.attributionWindow); +} + +- (void)testBuildFromJSON_EmptyData { + NSDictionary *json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"latd_empty_data"]; + XCTAssertNotNil(json); + + BranchLastAttributedTouchData *latd = [BranchLastAttributedTouchData buildFromJSON:json]; + XCTAssertNotNil(latd); + XCTAssertTrue(latd.lastAttributedTouchJSON.count == 0); +} + +- (void)testBuildFromJSON_MissingData { + NSDictionary *json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"latd_missing_data"]; + XCTAssertNotNil(json); + + BranchLastAttributedTouchData *latd = [BranchLastAttributedTouchData buildFromJSON:json]; + XCTAssertNil(latd); +} + +- (void)testBuildFromJSON_MissingWindow { + NSDictionary *json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"latd_missing_window"]; + XCTAssertNotNil(json); + + BranchLastAttributedTouchData *latd = [BranchLastAttributedTouchData buildFromJSON:json]; + XCTAssertNotNil(latd); + XCTAssertNil(latd.attributionWindow); +} + +@end diff --git a/BranchSDKTests/BranchLoggerTests.m b/BranchSDKTests/BranchLoggerTests.m new file mode 100644 index 000000000..1a4be3490 --- /dev/null +++ b/BranchSDKTests/BranchLoggerTests.m @@ -0,0 +1,261 @@ +// +// BranchLoggerTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 2/5/24. +// Copyright © 2024 Branch, Inc. All rights reserved. +// + +#import +#import "BranchLogger.h" +#import "Branch.h" + +@interface BranchLoggerTests : XCTestCase + +@end + +@implementation BranchLoggerTests + +// public API test +- (void)testEnableLoggingSetsCorrectDefaultLevel { + [[Branch getInstance] enableLogging]; + XCTAssertEqual([BranchLogger shared].logLevelThreshold, BranchLogLevelDebug, "Default log level should be Debug."); +} + +- (void)testLoggingEnabled_NOByDefault { + BranchLogger *logger = [BranchLogger new]; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + [logger logError:@"msg" error:nil]; + + XCTAssertTrue(count == 0); +} + +- (void)testLoggingEnabled_Yes { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 2); +} + +- (void)testLoggingIgnoresNil { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:nil error:nil]; + XCTAssertTrue(count == 0); +} + +- (void)testLoggingIgnoresEmptyString { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"" error:nil]; + XCTAssertTrue(count == 0); +} + +- (void)testLoggingEnabled_YesThenNo { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + // one call + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + + // disable, second call is ignored + logger.loggingEnabled = NO; + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); +} + +- (void)testLogLevel_DebugByDefault { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logWarning:@"msg" error:nil]; + XCTAssertTrue(count == 2); + [logger logDebug:@"msg" error:nil]; + XCTAssertTrue(count == 3); + + // this should be ignored and the counter not incremented + [logger logVerbose:@"msg" error:nil]; + XCTAssertTrue(count == 3); +} + +- (void)testLogLevel_Error { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.logLevelThreshold = BranchLogLevelError; + + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + + // these should be ignored and the counter not incremented + [logger logWarning:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logDebug:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logVerbose:@"msg" error:nil]; + XCTAssertTrue(count == 1); +} + +- (void)testLogLevel_Warning { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.logLevelThreshold = BranchLogLevelWarning; + + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logWarning:@"msg" error:nil]; + XCTAssertTrue(count == 2); + + // this should be ignored and the counter not incremented + [logger logDebug:@"msg" error:nil]; + XCTAssertTrue(count == 2); + [logger logVerbose:@"msg" error:nil]; + XCTAssertTrue(count == 2); +} + +- (void)testLogLevel_Verbose { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.logLevelThreshold = BranchLogLevelVerbose; + + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logWarning:@"msg" error:nil]; + XCTAssertTrue(count == 2); + [logger logDebug:@"msg" error:nil]; + XCTAssertTrue(count == 3); + [logger logVerbose:@"msg" error:nil]; + XCTAssertTrue(count == 4); +} + +- (void)testLogFormat_Default { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + NSString *expectedMessage = @"[BranchLoggerTests testLogFormat_Default] msg"; + + XCTAssertTrue([expectedMessage isEqualToString:message]); + XCTAssertTrue(logLevel == BranchLogLevelError); + XCTAssertNil(error); + }; + + [logger logError:@"msg" error:nil]; +} + +- (void)testLogFormat_NSError { + __block NSError *originalError = [NSError errorWithDomain:@"com.domain.test" code:200 userInfo:@{@"Error Message": @"Test Error"}]; + + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + NSString *expectedMessage = @"[BranchLoggerTests testLogFormat_NSError] msg"; + + XCTAssertTrue([expectedMessage isEqualToString:message]); + XCTAssertTrue(logLevel == BranchLogLevelError); + XCTAssertTrue(originalError == error); + }; + + [logger logError:@"msg" error:originalError]; +} + +- (void)testLogFormat_includeCallerDetailsNO { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.includeCallerDetails = NO; + + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + NSString *expectedMessage = @"msg"; + + XCTAssertTrue([expectedMessage isEqualToString:message]); + XCTAssertTrue(logLevel == BranchLogLevelError); + XCTAssertNil(error); + }; + + [logger logError:@"msg" error:nil]; +} + +- (void)testLogFormat_includeCallerDetailsNO_NSError { + __block NSError *originalError = [NSError errorWithDomain:@"com.domain.test" code:200 userInfo:@{@"Error Message": @"Test Error"}]; + + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.includeCallerDetails = NO; + + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + NSString *expectedMessage = @"msg"; + + XCTAssertTrue([expectedMessage isEqualToString:message]); + XCTAssertTrue(logLevel == BranchLogLevelError); + XCTAssertTrue(originalError == error); + }; + + [logger logError:@"msg" error:originalError]; +} + +- (void)testDefaultBranchLogFormat { + NSError *error = [NSError errorWithDomain:@"com.domain.test" code:200 userInfo:@{@"Error Message": @"Test Error"}]; + + NSString *expectedMessage = @"[BranchSDK][Error]msg NSError: Error Domain=com.domain.test Code=200 \"(null)\" UserInfo={Error Message=Test Error}"; + NSString *formattedMessage = [BranchLogger formatMessage:@"msg" logLevel:BranchLogLevelError error:error]; + + XCTAssertTrue([expectedMessage isEqualToString:formattedMessage]); +} + +@end diff --git a/BranchSDKTests/BranchPluginSupportTests.m b/BranchSDKTests/BranchPluginSupportTests.m new file mode 100644 index 000000000..d46b620fc --- /dev/null +++ b/BranchSDKTests/BranchPluginSupportTests.m @@ -0,0 +1,91 @@ +// +// BranchPluginSupportTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 1/25/22. +// Copyright © 2022 Branch, Inc. All rights reserved. +// + +#import +#import "BranchPluginSupport.h" + +@interface BranchPluginSupportTests : XCTestCase +@property (nonatomic, strong, readwrite) NSDictionary *deviceDescription; +@end + +@implementation BranchPluginSupportTests + +- (void)setUp { + self.deviceDescription = [[BranchPluginSupport new] deviceDescription]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testAppVersion { + // checks test app version + XCTAssert([@"1.0" isEqualToString:_deviceDescription[@"app_version"]]); +} + +- (void)testBrandName { + XCTAssert([@"Apple" isEqualToString:_deviceDescription[@"brand"]]); +} + +- (void)testModelName_Simulator { + // intel processor + bool x86_64 = [@"x86_64" isEqualToString:_deviceDescription[@"model"]]; + + // apple processor + bool arm64 = [@"arm64" isEqualToString:_deviceDescription[@"model"]]; + + XCTAssert(x86_64 || arm64); +} + +- (void)testOSName { + XCTAssertNotNil(_deviceDescription[@"os"]); + XCTAssert([_deviceDescription[@"os"] isEqualToString:[UIDevice currentDevice].systemName]); +} + +- (void)testOSVersion { + XCTAssertNotNil(_deviceDescription[@"os_version"]); + XCTAssert([_deviceDescription[@"os_version"] isEqualToString:[UIDevice currentDevice].systemVersion]); +} + +- (void)testEnvironment { + XCTAssert([@"FULL_APP" isEqualToString:_deviceDescription[@"environment"]]); +} + +- (void)testScreenWidth { + XCTAssert(_deviceDescription[@"screen_width"].intValue > 320); +} + +- (void)testScreenHeight { + XCTAssert(_deviceDescription[@"screen_height"].intValue > 320); +} + +- (void)testScreenScale { + XCTAssert(_deviceDescription[@"screen_dpi"].intValue > 0); +} + +- (void)testCountry { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale containsString:_deviceDescription[@"country"]]); +} + +- (void)testLanguage { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale containsString:_deviceDescription[@"language"]]); +} + +- (void)testLocalIPAddress { + NSString *address = _deviceDescription[@"local_ip"]; + XCTAssertNotNil(address); + + // shortest ipv4 is 7 + XCTAssert(address.length >= 7); +} + +@end diff --git a/BranchSDKTests/BranchQRCodeTests.m b/BranchSDKTests/BranchQRCodeTests.m new file mode 100644 index 000000000..3d1e1ffc6 --- /dev/null +++ b/BranchSDKTests/BranchQRCodeTests.m @@ -0,0 +1,154 @@ +// +// BranchQRCodeTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 4/14/22. +// Copyright © 2022 Branch, Inc. All rights reserved. +// + +#import +#import "Branch.h" +#import "BranchQRCode.h" +#import "BNCQRCodeCache.h" + +@interface BranchQRCodeTests : XCTestCase + +@end + +@implementation BranchQRCodeTests + +- (void)testNormalQRCodeDataWithAllSettings { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *qrCode = [BranchQRCode new]; + qrCode.width = @(1000); + qrCode.margin = @(1); + qrCode.codeColor = [UIColor blueColor]; + qrCode.backgroundColor = [UIColor whiteColor]; + qrCode.centerLogo = @"https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg"; + qrCode.imageFormat = BranchQRCodeImageFormatPNG; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [qrCode getQRCodeAsData:buo linkProperties:lp completion:^(NSData * _Nonnull qrCode, NSError * _Nonnull error) { + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + +- (void)testNormalQRCodeAsDataWithNoSettings { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *qrCode = [BranchQRCode new]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [qrCode getQRCodeAsData:buo linkProperties:lp completion:^(NSData * _Nonnull qrCode, NSError * _Nonnull error) { + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + +- (void)testNormalQRCodeWithInvalidLogoURL { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *qrCode = [BranchQRCode new]; + qrCode.centerLogo = @"https://branch.branch/notARealImageURL.jpg"; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [qrCode getQRCodeAsData:buo linkProperties:lp completion:^(NSData * _Nonnull qrCode, NSError * _Nonnull error) { + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + +- (void)testNormalQRCodeAsImage { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *qrCode = [BranchQRCode new]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [qrCode getQRCodeAsImage:buo linkProperties:lp completion:^(UIImage * _Nonnull qrCode, NSError * _Nonnull error) { + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + +- (void)testQRCodeCache { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *myQRCode = [BranchQRCode new]; + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [myQRCode getQRCodeAsData:buo linkProperties:lp completion:^(NSData * _Nonnull qrCode, NSError * _Nonnull error) { + + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + + NSMutableDictionary *parameters = [NSMutableDictionary new]; + NSMutableDictionary *settings = [NSMutableDictionary new]; + + settings[@"image_format"] = @"PNG"; + settings[@"width"] = @(300); + settings[@"margin"] = @(1); + + parameters[@"qr_code_settings"] = settings; + parameters[@"data"] = [NSMutableDictionary new]; + parameters[@"branch_key"] = [Branch branchKey]; + + + NSData *cachedQRCode = [[BNCQRCodeCache sharedInstance] checkQRCodeCache:parameters]; + + XCTAssertEqual(cachedQRCode, qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + + +@end diff --git a/BranchSDKTests/BranchSDKTests.m b/BranchSDKTests/BranchSDKTests.m new file mode 100644 index 000000000..7a37169d8 --- /dev/null +++ b/BranchSDKTests/BranchSDKTests.m @@ -0,0 +1,36 @@ +// +// BranchSDKTests.m +// BranchSDKTests +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import + +@interface BranchSDKTests : XCTestCase + +@end + +@implementation BranchSDKTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/BranchSDKTests/BranchSDKTests.xctestplan b/BranchSDKTests/BranchSDKTests.xctestplan new file mode 100644 index 000000000..d72383a21 --- /dev/null +++ b/BranchSDKTests/BranchSDKTests.xctestplan @@ -0,0 +1,33 @@ +{ + "configurations" : [ + { + "id" : "9EAB663B-7807-43EE-AD4E-658E8734932A", + "name" : "Test Scheme Action", + "options" : { + + } + } + ], + "defaultOptions" : { + "targetForVariableExpansion" : { + "containerPath" : "container:BranchSDK.xcodeproj", + "identifier" : "E7CA755E2E1B59F5002EFB40", + "name" : "BranchSDKTestsHostApp" + } + }, + "testTargets" : [ + { + "parallelizable" : false, + "skippedTests" : [ + "BNCDisableAdNetworkCalloutsTests", + "BranchActivityItemTests" + ], + "target" : { + "containerPath" : "container:BranchSDK.xcodeproj", + "identifier" : "E7CA74EA2E1B4F75002EFB40", + "name" : "BranchSDKTests" + } + } + ], + "version" : 1 +} diff --git a/BranchSDKTests/BranchShareLinkTests.m b/BranchSDKTests/BranchShareLinkTests.m new file mode 100644 index 000000000..c41fdb618 --- /dev/null +++ b/BranchSDKTests/BranchShareLinkTests.m @@ -0,0 +1,38 @@ +// +// BranchShareLinkTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 5/5/22. +// Copyright © 2022 Branch, Inc. All rights reserved. +// + +#import +#import "BranchShareLink.h" +#import "BranchLinkProperties.h" +#import "Branch.h" + +@interface BranchShareLinkTests : XCTestCase + +@end + +@implementation BranchShareLinkTests + +- (void)testAddLPLinkMetadata { + BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:@"test/001"]; + BranchLinkProperties *lp = [[BranchLinkProperties alloc] init]; + + BranchShareLink *bsl = [[BranchShareLink alloc] initWithUniversalObject:buo linkProperties:lp]; + + if (@available(iOS 13.0, macCatalyst 13.1, *)) { + NSURL *imageURL = [NSURL URLWithString:@"https://cdn.branch.io/branch-assets/1598575682753-og_image.png"]; + NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; + UIImage *iconImage = [UIImage imageWithData:imageData]; + + [bsl addLPLinkMetadata:@"Test Preview Title" icon:iconImage]; + XCTAssertNotNil([bsl lpMetaData]); + } else { + XCTAssertTrue(true); + } +} + +@end diff --git a/BranchSDKTests/BranchUniversalObjectTests.m b/BranchSDKTests/BranchUniversalObjectTests.m new file mode 100644 index 000000000..9a7112e31 --- /dev/null +++ b/BranchSDKTests/BranchUniversalObjectTests.m @@ -0,0 +1,446 @@ +// +// BranchUniversalObjectTests.m +// Branch-TestBed +// +// Created by Edward Smith on 8/15/17. +// Copyright © 2017 Branch Metrics. All rights reserved. +// + +#import +#import "BranchUniversalObject.h" + +@interface BranchUniversalObjectTests : XCTestCase +@end + +@implementation BranchUniversalObjectTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +#pragma mark BranchContentMetadata tests + +- (BranchContentMetadata *)branchContentMetadataWithAllPropertiesSet { + BranchContentMetadata *metadata = [BranchContentMetadata new]; + metadata.contentSchema = BranchContentSchemaOther; + metadata.quantity = 10; + metadata.price = [[NSDecimalNumber alloc] initWithDouble:5.5]; + metadata.currency = BNCCurrencyUSD; + metadata.sku = @"testSKU"; + metadata.productName = @"testProductName"; + metadata.productBrand = @"testProductBrand"; + metadata.productCategory = BNCProductCategoryApparel; + metadata.productVariant = @"testProductVariant"; + metadata.condition = BranchConditionNew; + metadata.ratingAverage = 3.5; + metadata.ratingCount = 2; + metadata.ratingMax = 4; + metadata.rating = 3; + metadata.addressStreet = @"195 Page Mill Road"; + metadata.addressCity = @"Palo Alto"; + metadata.addressRegion = @"CA"; + metadata.addressCountry = @"USA"; + metadata.addressPostalCode = @"94306"; + metadata.latitude = 37.426; + metadata.longitude = -122.138; + + metadata.imageCaptions = @[ + @"Hello World", + @"Goodbye World" + ].mutableCopy; + + metadata.customMetadata = @{ + @"custom0": @"custom data 0" + }.mutableCopy; + + return metadata; +} + +- (void)verifyBranchContentMetadataWithAllProperties:(BranchContentMetadata *)metadata { + XCTAssertNotNil(metadata); + + XCTAssertEqual(BranchContentSchemaOther, metadata.contentSchema); + XCTAssertTrue([@(10) isEqualToNumber:@(metadata.quantity)]); + XCTAssertTrue([[[NSDecimalNumber alloc] initWithDouble:5.5] isEqualToNumber:metadata.price]); + + XCTAssertEqual(BNCCurrencyUSD, metadata.currency); + XCTAssertTrue([@"testSKU" isEqualToString:metadata.sku]); + XCTAssertTrue([@"testProductName" isEqualToString:metadata.productName]); + XCTAssertTrue([@"testProductBrand" isEqualToString:metadata.productBrand]); + XCTAssertEqual(BNCProductCategoryApparel, metadata.productCategory); + XCTAssertTrue([@"testProductVariant" isEqualToString:metadata.productVariant]); + XCTAssertEqual(BranchConditionNew, metadata.condition); + XCTAssertTrue([@(3.5) isEqualToNumber:@(metadata.ratingAverage)]); + XCTAssertTrue([@(2) isEqualToNumber:@(metadata.ratingCount)]); + XCTAssertTrue([@(4) isEqualToNumber:@(metadata.ratingMax)]); + XCTAssertTrue([@(3) isEqualToNumber:@(metadata.rating)]); + + XCTAssertTrue([@"195 Page Mill Road" isEqualToString:metadata.addressStreet]); + XCTAssertTrue([@"Palo Alto" isEqualToString:metadata.addressCity]); + XCTAssertTrue([@"CA" isEqualToString:metadata.addressRegion]); + XCTAssertTrue([@"USA" isEqualToString:metadata.addressCountry]); + XCTAssertTrue([@"94306" isEqualToString:metadata.addressPostalCode]); + + XCTAssertTrue([@(37.426) isEqualToNumber:@(metadata.latitude)]); + XCTAssertTrue([@(-122.138) isEqualToNumber:@(metadata.longitude)]); + + XCTAssertNotNil(metadata.imageCaptions); + XCTAssertTrue(metadata.imageCaptions.count == 2); + XCTAssertTrue([metadata.imageCaptions[0] isEqualToString:@"Hello World"]); + XCTAssertTrue([metadata.imageCaptions[1] isEqualToString:@"Goodbye World"]); + + XCTAssertNotNil(metadata.customMetadata); + XCTAssertTrue(metadata.customMetadata.allKeys.count == 1); +} + +- (void)verifyBranchContentMetadataDictionaryWithAllPropertiesSet:(NSDictionary *)dict { + XCTAssertTrue([@"OTHER" isEqualToString:dict[@"$content_schema"]]); + XCTAssertTrue([@(10) isEqualToNumber:dict[@"$quantity"]]); + XCTAssertTrue([[[NSDecimalNumber alloc] initWithDouble:5.5] isEqualToNumber:dict[@"$price"]]); + XCTAssertTrue([@"USD" isEqualToString:dict[@"$currency"]]); + XCTAssertTrue([@"testSKU" isEqualToString:dict[@"$sku"]]); + XCTAssertTrue([@"testProductName" isEqualToString:dict[@"$product_name"]]); + XCTAssertTrue([@"testProductBrand" isEqualToString:dict[@"$product_brand"]]); + XCTAssertTrue([@"Apparel & Accessories" isEqualToString:dict[@"$product_category"]]); + XCTAssertTrue([@"testProductVariant" isEqualToString:dict[@"$product_variant"]]); + XCTAssertTrue([@"NEW" isEqualToString:dict[@"$condition"]]); + + XCTAssertTrue([@(3.5) isEqualToNumber:dict[@"$rating_average"]]); + XCTAssertTrue([@(2) isEqualToNumber:dict[@"$rating_count"]]); + XCTAssertTrue([@(4) isEqualToNumber:dict[@"$rating_max"]]); + XCTAssertTrue([@(3) isEqualToNumber:dict[@"$rating"]]); + + XCTAssertTrue([@"195 Page Mill Road" isEqualToString:dict[@"$address_street"]]); + XCTAssertTrue([@"Palo Alto" isEqualToString:dict[@"$address_city"]]); + XCTAssertTrue([@"CA" isEqualToString:dict[@"$address_region"]]); + XCTAssertTrue([@"USA" isEqualToString:dict[@"$address_country"]]); + XCTAssertTrue([@"94306" isEqualToString:dict[@"$address_postal_code"]]); + + XCTAssertTrue([@(37.426) isEqualToNumber:dict[@"$latitude"]]); + XCTAssertTrue([@(-122.138) isEqualToNumber:dict[@"$longitude"]]); + + XCTAssertTrue([dict[@"$image_captions"] isKindOfClass:NSArray.class]); + NSArray *tmp = dict[@"$image_captions"]; + XCTAssertTrue(tmp.count == 2); + XCTAssertTrue([tmp[0] isEqualToString:@"Hello World"]); + XCTAssertTrue([tmp[1] isEqualToString:@"Goodbye World"]); + + XCTAssertTrue([@"custom data 0" isEqualToString:dict[@"custom0"]]); +} + +- (void)testBranchContentMetadataCreation_NoPropertiesSet { + BranchContentMetadata *metadata = [BranchContentMetadata new]; + + // most properties default to nil. primitives default to 0 + XCTAssertNil(metadata.contentSchema); + XCTAssertEqual(0, metadata.quantity); + XCTAssertNil(metadata.price); + XCTAssertNil(metadata.currency); + XCTAssertNil(metadata.sku); + XCTAssertNil(metadata.productName); + XCTAssertNil(metadata.productBrand); + XCTAssertNil(metadata.productCategory); + XCTAssertNil(metadata.productVariant); + XCTAssertNil(metadata.condition); + XCTAssertEqual(0, metadata.ratingAverage); + XCTAssertEqual(0, metadata.ratingCount); + XCTAssertEqual(0, metadata.ratingMax); + XCTAssertEqual(0, metadata.rating); + XCTAssertNil(metadata.addressStreet); + XCTAssertNil(metadata.addressCity); + XCTAssertNil(metadata.addressRegion); + XCTAssertNil(metadata.addressCountry); + XCTAssertNil(metadata.addressPostalCode); + XCTAssertEqual(0, metadata.latitude); + XCTAssertEqual(0, metadata.longitude); + + // defaults to an empty array + XCTAssertNotNil(metadata.imageCaptions); + XCTAssertTrue(metadata.imageCaptions.count == 0); + + // defaults to an empty dictionary + XCTAssertNotNil(metadata.customMetadata); + XCTAssertTrue(metadata.customMetadata.allKeys.count == 0); +} + +- (void)testBranchContentMetadataCreation_AllPropertiesSet { + BranchContentMetadata *metadata = [self branchContentMetadataWithAllPropertiesSet]; + [self verifyBranchContentMetadataWithAllProperties:metadata]; +} + +- (void)testBranchContentMetadataDictionary_NoPropertiesSet { + BranchContentMetadata *metadata = [BranchContentMetadata new]; + NSDictionary *dict = metadata.dictionary; + + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 0); +} + +- (void)testBranchContentMetadataDictionary_AllPropertiesSet { + BranchContentMetadata *metadata = [self branchContentMetadataWithAllPropertiesSet]; + NSDictionary *dict = metadata.dictionary; + + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 23); + [self verifyBranchContentMetadataDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchContentMetadata_contentMetadataWithDictionary { + BranchContentMetadata *original = [self branchContentMetadataWithAllPropertiesSet]; + NSDictionary *dict = [original dictionary]; + + BranchContentMetadata *metadata = [BranchContentMetadata contentMetadataWithDictionary:dict]; + [self verifyBranchContentMetadataWithAllProperties:metadata]; +} + +- (void)testBranchContentMetadataDescription_NoPropertiesSet { + BranchContentMetadata *metadata = [BranchContentMetadata new]; + NSString *desc = [metadata description]; + XCTAssertTrue([desc containsString:@"BranchContentMetadata"]); + XCTAssertTrue([desc containsString:@"schema: (null) userData: 0 items"]); +} + +- (void)testBranchContentMetadataDescription_AllPropertiesSet { + BranchContentMetadata *metadata = [self branchContentMetadataWithAllPropertiesSet]; + NSString *desc = [metadata description]; + XCTAssertTrue([desc containsString:@"BranchContentMetadata"]); + XCTAssertTrue([desc containsString:@"schema: OTHER userData: 1 items"]); +} + +#pragma mark BranchUniversalObject tests + +- (BranchUniversalObject *)branchUniversalObjectWithAllPropertiesSet { + BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:@"io.branch.testObject"]; + buo.canonicalUrl = @"https://branch.io"; + buo.title = @"Test Title"; + buo.contentDescription = @"the quick brown fox jumps over the lazy dog"; + buo.imageUrl = @"https://branch.io"; + buo.keywords = @[@"keyword1", @"keyword2"]; + buo.expirationDate = [NSDate dateWithTimeIntervalSinceNow:1]; + buo.locallyIndex = YES; + buo.publiclyIndex = YES; + + buo.contentMetadata = [self branchContentMetadataWithAllPropertiesSet]; + return buo; +} + +- (void)verifyBranchUniversalObjectWithAllPropertiesSet:(BranchUniversalObject *)buo { + XCTAssertNotNil(buo); + XCTAssertTrue([@"https://branch.io" isEqualToString:buo.canonicalUrl]); + XCTAssertTrue([@"Test Title" isEqualToString:buo.title]); + XCTAssertTrue([@"the quick brown fox jumps over the lazy dog" isEqualToString:buo.contentDescription]); + XCTAssertTrue([@"https://branch.io" isEqualToString:buo.imageUrl]); + + XCTAssertTrue(buo.keywords.count == 2); + XCTAssertTrue([buo.keywords[0] isEqualToString:@"keyword1"]); + XCTAssertTrue([buo.keywords[1] isEqualToString:@"keyword2"]); + + XCTAssertTrue([buo.creationDate compare:buo.expirationDate] == NSOrderedAscending); + + XCTAssertTrue(buo.locallyIndex); + XCTAssertTrue(buo.publiclyIndex); + + [self verifyBranchContentMetadataWithAllProperties:buo.contentMetadata]; +} + +- (void)verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:(NSDictionary *)dict { + XCTAssertTrue([@"io.branch.testObject" isEqualToString:dict[@"$canonical_identifier"]]); + XCTAssertTrue([@"https://branch.io" isEqualToString:dict[@"$canonical_url"]]); + XCTAssertTrue([@"Test Title" isEqualToString:dict[@"$og_title"]]); + XCTAssertTrue([@"the quick brown fox jumps over the lazy dog" isEqualToString:dict[@"$og_description"]]); + XCTAssertTrue([@"https://branch.io" isEqualToString:dict[@"$og_image_url"]]); + + XCTAssertTrue(dict[@"$locally_indexable"]); + XCTAssertTrue(dict[@"$publicly_indexable"]); + + XCTAssertTrue([dict[@"$creation_timestamp"] isKindOfClass:NSNumber.class]); + XCTAssertTrue([dict[@"$exp_date"] isKindOfClass:NSNumber.class]); + NSNumber *creationDate = dict[@"$creation_timestamp"]; + NSNumber *expirationDate = dict[@"$exp_date"]; + XCTAssertTrue([creationDate compare:expirationDate] == NSOrderedAscending); + + XCTAssertTrue([dict[@"$keywords"] isKindOfClass:NSArray.class]); + NSArray *tmp = dict[@"$keywords"]; + XCTAssertTrue(tmp.count == 2); + XCTAssertTrue([tmp[0] isEqualToString:@"keyword1"]); + XCTAssertTrue([tmp[1] isEqualToString:@"keyword2"]); + + // the BranchContentMetadata dictionary is NOT in a sub dictionary, it is merged in at the top level + [self verifyBranchContentMetadataDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchUniversalObjectCreation { + BranchUniversalObject *buo = [BranchUniversalObject new]; + XCTAssertNotNil(buo); + + XCTAssertNil(buo.canonicalIdentifier); + XCTAssertNil(buo.canonicalUrl); + XCTAssertNil(buo.title); + XCTAssertNil(buo.contentDescription); + XCTAssertNil(buo.imageUrl); + XCTAssertNil(buo.keywords); + XCTAssertNil(buo.creationDate); + XCTAssertNil(buo.expirationDate); + XCTAssertFalse(buo.locallyIndex); + XCTAssertFalse(buo.publiclyIndex); + + XCTAssertNotNil(buo.contentMetadata); +} + +- (void)testBranchUniversalObjectCreation_initWithCanonicalIdentifier { + BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:@"io.branch.testObject"]; + XCTAssertNotNil(buo); + + XCTAssertTrue([@"io.branch.testObject" isEqualToString:buo.canonicalIdentifier]); + XCTAssertNil(buo.canonicalUrl); + XCTAssertNil(buo.title); + XCTAssertNil(buo.contentDescription); + XCTAssertNil(buo.imageUrl); + XCTAssertNil(buo.keywords); + XCTAssertNotNil(buo.creationDate); + XCTAssertNil(buo.expirationDate); + XCTAssertFalse(buo.locallyIndex); + XCTAssertFalse(buo.publiclyIndex); + + XCTAssertNotNil(buo.contentMetadata); +} + +- (void)testBranchUniversalObjectCreation_initWithTitle { + BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithTitle:@"Test Title"]; + XCTAssertNotNil(buo); + + XCTAssertNil(buo.canonicalIdentifier); + XCTAssertNil(buo.canonicalUrl); + XCTAssertTrue([@"Test Title" isEqualToString:buo.title]); + XCTAssertNil(buo.contentDescription); + XCTAssertNil(buo.imageUrl); + XCTAssertNil(buo.keywords); + XCTAssertNotNil(buo.creationDate); + XCTAssertNil(buo.expirationDate); + XCTAssertFalse(buo.locallyIndex); + XCTAssertFalse(buo.publiclyIndex); + + XCTAssertNotNil(buo.contentMetadata); +} + +- (void)testBranchUniversalObject_AllPropertiesSet { + BranchUniversalObject *buo = [self branchUniversalObjectWithAllPropertiesSet]; + [self verifyBranchUniversalObjectWithAllPropertiesSet:buo]; +} + +- (void)testBranchUniversalObjectDescription_AllPropertiesSet { + BranchUniversalObject *buo = [self branchUniversalObjectWithAllPropertiesSet]; + NSString *desc = buo.description; + + // Verifies a few properties used to generate the description string + XCTAssertTrue([desc containsString:@"BranchUniversalObject"]); + XCTAssertTrue([desc containsString:@"canonicalIdentifier: io.branch.testObject"]); + XCTAssertTrue([desc containsString:@"title: Test Title"]); + XCTAssertTrue([desc containsString:@"contentDescription: the quick brown fox jumps over the lazy dog"]); +} + +- (void)testBranchUniversalObjectDictionary_AllPropertiesSet { + BranchUniversalObject *buo = [self branchUniversalObjectWithAllPropertiesSet]; + NSDictionary *dict = buo.dictionary; + + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 33); + [self verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchUniversalObject_objectWithDictionary { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + NSDictionary *dict = [original dictionary]; + + BranchUniversalObject *buo = [BranchUniversalObject objectWithDictionary:dict]; + [self verifyBranchUniversalObjectWithAllPropertiesSet:buo]; +} + +- (void)testBranchUniversalObject_getDictionaryWithCompleteLinkProperties_NoLinkPropertiesSet { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + NSDictionary *dict = [original getDictionaryWithCompleteLinkProperties:linkProperties]; + + XCTAssertNotNil(dict); + XCTAssertTrue([@(0) isEqualToNumber:dict[@"~duration"]]); +} + +- (void)testBranchUniversalObject_getDictionaryWithCompleteLinkProperties_AllLinkPropertiesSet { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + + linkProperties.tags = @[@"tag1", @"tag2"]; + linkProperties.feature = @"test feature"; + linkProperties.alias = @"test alias"; + linkProperties.channel = @"test channel"; + linkProperties.matchDuration = 10; + + // BranchUniversalObject.controlParams overwrites BranchContentMetadata.customMetadata + linkProperties.controlParams = @{ + @"testControlParam": @"test control param", + //@"custom0": @"test control param" + }; + + NSDictionary *dict = [original getDictionaryWithCompleteLinkProperties:linkProperties]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 39); + + XCTAssertTrue([@(10) isEqualToNumber:dict[@"~duration"]]); + XCTAssertTrue([@"test alias" isEqualToString:dict[@"~alias"]]); + XCTAssertTrue([@"test channel" isEqualToString:dict[@"~channel"]]); + XCTAssertTrue([@"test feature" isEqualToString:dict[@"~feature"]]); + + XCTAssertTrue([@"test control param" isEqualToString:dict[@"testControlParam"]]); + + // BranchUniversalObject fields are at the top level of the dictionary + [self verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchUniversalObject_getParamsForServerRequestWithAddedLinkProperties_NoLinkPropertiesSet { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + + // Nothing is added with this call + NSDictionary *dict = [original getParamsForServerRequestWithAddedLinkProperties:linkProperties]; + + XCTAssertNotNil(dict); + + // BranchUniversalObject fields are at the top level of the dictionary + [self verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchUniversalObject_getParamsForServerRequestWithAddedLinkProperties_AllLinkPropertiesSet { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + linkProperties.tags = @[@"tag1", @"tag2"]; + linkProperties.feature = @"test feature"; + linkProperties.alias = @"test alias"; + linkProperties.channel = @"test channel"; + linkProperties.matchDuration = 10; + + // BranchUniversalObject.controlParams overwrites BranchContentMetadata.customMetadata + linkProperties.controlParams = @{ + @"testControlParam": @"test control param", + //@"custom0": @"test control param" + }; + + NSDictionary *dict = [original getParamsForServerRequestWithAddedLinkProperties:linkProperties]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 34); + + // only the control parameters are in the dictionary + XCTAssertTrue([@"test control param" isEqualToString:dict[@"testControlParam"]]); + XCTAssertNil(dict[@"~duration"]); + XCTAssertNil(dict[@"~alias"]); + XCTAssertNil(dict[@"~channel"]); + XCTAssertNil(dict[@"~feature"]); + + // BranchUniversalObject fields are at the top level of the dictionary + [self verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:dict]; +} + +@end diff --git a/BranchSDKTests/DispatchToIsolationQueueTests.m b/BranchSDKTests/DispatchToIsolationQueueTests.m new file mode 100644 index 000000000..89043aa94 --- /dev/null +++ b/BranchSDKTests/DispatchToIsolationQueueTests.m @@ -0,0 +1,76 @@ +// +// BNCPreInitBlockTests.m +// Branch-SDK-Tests +// +// Created by Benas Klastaitis on 12/9/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +// #import "Branch.h" + +@interface DispatchToIsolationQueueTests : XCTestCase +// @property (nonatomic, strong, readwrite) Branch *branch; +// @property (nonatomic, strong, readwrite) BNCPreferenceHelper *prefHelper; +@end + +// this is an integration test, needs to be moved to a new target +@implementation DispatchToIsolationQueueTests + +- (void)setUp { + // self.branch = [Branch getInstance]; + // self.prefHelper = [[BNCPreferenceHelper alloc] init]; +} + +- (void)tearDown { + // [self.prefHelper setRequestMetadataKey:@"$marketing_cloud_visitor_id" value:@"dummy"]; +} + +- (void)testPreInitBlock { + // __block XCTestExpectation *expectation = [self expectationWithDescription:@""]; + + // [self.branch dispatchToIsolationQueue:^{ + // dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // [self.branch setRequestMetadataKey:@"$marketing_cloud_visitor_id" value:@"adobeID123"]; + // dispatch_semaphore_signal(semaphore); + // }); + // dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + // }]; + + // [self.branch initSessionWithLaunchOptions:nil andRegisterDeepLinkHandlerUsingBranchUniversalObject: + // ^ (BranchUniversalObject * _Nullable universalObject, + // BranchLinkProperties * _Nullable linkProperties, + // NSError * _Nullable error) { + // [expectation fulfill]; + // }]; + + // // test that session initialization blocking works + // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // id initializationStatus = [self.branch valueForKey:@"initializationStatus"]; + // XCTAssertTrue([self enumIntValueFromId:initializationStatus] == 0);// uninitialized + // XCTAssertNil([[self.prefHelper requestMetadataDictionary] objectForKey:@"$marketing_cloud_visitor_id"]); + // }); + + // // test that initialization does happen afterwards and that pre init block was executed + // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // id initializationStatus = [self.branch valueForKey:@"initializationStatus"]; + // XCTAssertTrue([self enumIntValueFromId:initializationStatus] == 2);// initialized + + // XCTAssertTrue([[[self.prefHelper requestMetadataDictionary] objectForKey:@"$marketing_cloud_visitor_id"] isEqualToString:@"adobeID123"]); + // }); + + + // [self waitForExpectationsWithTimeout:6 handler:^(NSError * _Nullable error) { + // NSLog(@"%@", error); + // }]; +} + +// -(int)enumIntValueFromId:(id)enumValueId { +// if (![enumValueId respondsToSelector:@selector(intValue)]) +// return -1; + +// return [enumValueId intValue]; +// } + +@end diff --git a/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/Info.plist b/BranchSDKTests/Info.plist similarity index 86% rename from TestDeepLinking/TestDeepLinkingUITestsWithHostApp/Info.plist rename to BranchSDKTests/Info.plist index 64d65ca49..ba72822e8 100644 --- a/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/Info.plist +++ b/BranchSDKTests/Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) + en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -13,9 +13,11 @@ CFBundleName $(PRODUCT_NAME) CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) + BNDL CFBundleShortVersionString 1.0 + CFBundleSignature + ???? CFBundleVersion 1 diff --git a/BranchSDKTests/NSErrorBranchTests.m b/BranchSDKTests/NSErrorBranchTests.m new file mode 100644 index 000000000..4399b7484 --- /dev/null +++ b/BranchSDKTests/NSErrorBranchTests.m @@ -0,0 +1,54 @@ +/** + @file NSErrorBranchCategoryTests.m + @package Branch-SDK + @brief Branch error tests. + + @author Edward Smith + @date August 2017 + @copyright Copyright © 2017 Branch. All rights reserved. +*/ + +#import +#import "NSError+Branch.h" + +@interface NSErrorBranchTests : XCTestCase +@end + +@implementation NSErrorBranchTests + +- (void)testErrorDomain { + XCTAssertTrue([@"io.branch.sdk.error" isEqualToString:[NSError bncErrorDomain]]); +} + +- (void)testError { + NSError *error = [NSError branchErrorWithCode:BNCInitError]; + XCTAssert(error.domain == [NSError bncErrorDomain]); + XCTAssert(error.code == BNCInitError); + XCTAssert([error.localizedDescription isEqualToString: + @"The Branch user session has not been initialized."] + ); +} + +- (void)testErrorWithUnderlyingError { + NSError *underlyingError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileNoSuchFileError userInfo:nil]; + NSError *error = [NSError branchErrorWithCode:BNCServerProblemError error:underlyingError]; + + XCTAssert(error.domain == [NSError bncErrorDomain]); + XCTAssert(error.code == BNCServerProblemError); + XCTAssert([error.localizedDescription isEqualToString: @"Trouble reaching the Branch servers, please try again shortly."]); + + XCTAssert(error.userInfo[NSUnderlyingErrorKey] == underlyingError); + XCTAssert([error.localizedFailureReason isEqualToString:@"The file doesn’t exist."]); +} + +- (void)testErrorWithMessage { + NSString *message = [NSString stringWithFormat:@"Network operation of class '%@' does not conform to the BNCNetworkOperationProtocol.", NSStringFromClass([self class])]; + NSError *error = [NSError branchErrorWithCode:BNCNetworkServiceInterfaceError localizedMessage:message]; + + XCTAssert(error.domain == [NSError bncErrorDomain]); + XCTAssert(error.code == BNCNetworkServiceInterfaceError); + XCTAssert([error.localizedDescription isEqualToString: @"The underlying network service does not conform to the BNCNetworkOperationProtocol."]); + XCTAssert([error.localizedFailureReason isEqualToString: @"Network operation of class 'NSErrorBranchTests' does not conform to the BNCNetworkOperationProtocol."]); +} + +@end diff --git a/BranchSDKTests/NSMutableDictionaryBranchTests.m b/BranchSDKTests/NSMutableDictionaryBranchTests.m new file mode 100644 index 000000000..9fadbefb2 --- /dev/null +++ b/BranchSDKTests/NSMutableDictionaryBranchTests.m @@ -0,0 +1,389 @@ +// +// NSMutableDictionaryBranchTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 2/9/24. +// Copyright © 2024 Branch, Inc. All rights reserved. +// + +#import +#import "NSMutableDictionary+Branch.h" + +@interface NSMutableDictionaryBranchTests : XCTestCase + +@end + +@implementation NSMutableDictionaryBranchTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testSafeSetObject_StringString { + NSMutableDictionary *dict = [NSMutableDictionary new]; + + [dict bnc_safeSetObject:@"foo" forKey:@"bar"]; + XCTAssertTrue(dict.count == 1); + XCTAssertTrue([@"foo" isEqualToString:dict[@"bar"]]); +} + +- (void)testSafeSetObject_NilString { + NSMutableDictionary *dict = [NSMutableDictionary new]; + + [dict bnc_safeSetObject:nil forKey:@"bar"]; + XCTAssertTrue(dict.count == 0); +} + +- (void)testSafeSetObject_StringNil { + NSMutableDictionary *dict = [NSMutableDictionary new]; + + [dict bnc_safeSetObject:@"foo" forKey:nil]; + XCTAssertTrue(dict.count == 0); +} + +- (void)testSafeAddEntriesFromDictionary { + + // NSStrings are never copied, so use NSMutableStrings + NSMutableDictionary *other = [NSMutableDictionary new]; + other[@"foo"] = [[NSMutableString alloc] initWithString:@"bar"]; + other[@"hello"] = [[NSMutableString alloc] initWithString:@"world"]; + + NSMutableDictionary *dict = [NSMutableDictionary new]; + [dict bnc_safeAddEntriesFromDictionary:other]; + + NSArray *keyset = [other allKeys]; + for (id key in keyset) { + id original = other[key]; + id copy = dict[key]; + + // same object value + XCTAssertTrue([original isEqual:copy]); + + // different object instance + XCTAssertTrue(original != copy); + } +} + +- (void)testSafeAddEntriesFromDictionary_NestedArray { + + // NSStrings are never copied, so use NSMutableStrings + NSMutableDictionary *other = [NSMutableDictionary new]; + other[@"foo"] = [[NSMutableString alloc] initWithString:@"bar"]; + other[@"hello"] = [[NSMutableString alloc] initWithString:@"world"]; + + NSMutableArray *array = [NSMutableArray new]; + [array addObject:[[NSMutableString alloc] initWithString:@"dog"]]; + [array addObject:[[NSMutableString alloc] initWithString:@"cat"]]; + [array addObject:[[NSMutableString alloc] initWithString:@"child"]]; + + other[@"good"] = array; + + NSMutableDictionary *dict = [NSMutableDictionary new]; + [dict bnc_safeAddEntriesFromDictionary:other]; + + NSArray *keyset = [other allKeys]; + for (id key in keyset) { + id original = other[key]; + id copy = dict[key]; + + // same object value + XCTAssertTrue([original isEqual:copy]); + + // different object instance + XCTAssertTrue(original != copy); + } + + // confirm that copyItems is a one layer deep copy + NSArray *arrayCopy = dict[@"good"]; + XCTAssertTrue(array.count == arrayCopy.count); + XCTAssertTrue(array != arrayCopy); + + for (int i=0; i +#import "NSString+Branch.h" + +#define _countof(array) (sizeof(array)/sizeof(array[0])) + +@interface NSStringBranchTests : XCTestCase +@end + +@implementation NSStringBranchTests + +- (void)testMaskEqual { + XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"0123"]); + XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"012"]); + XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"01234"]); + XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"01*3"]); + XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"01*4"]); + XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"*123"]); + XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"012*"]); + XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語123日本語"]); + XCTAssertFalse([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語1234本語"]); + XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語***日本語"]); + XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"***123日本語"]); +} + +@end diff --git a/BranchSDKTestsHostApp/AppDelegate.h b/BranchSDKTestsHostApp/AppDelegate.h new file mode 100644 index 000000000..ba35f21cd --- /dev/null +++ b/BranchSDKTestsHostApp/AppDelegate.h @@ -0,0 +1,14 @@ +// +// AppDelegate.h +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import + +@interface AppDelegate : UIResponder + + +@end + diff --git a/BranchSDKTestsHostApp/AppDelegate.m b/BranchSDKTestsHostApp/AppDelegate.m new file mode 100644 index 000000000..3c267c2e5 --- /dev/null +++ b/BranchSDKTestsHostApp/AppDelegate.m @@ -0,0 +1,40 @@ +// +// AppDelegate.m +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + + +#pragma mark - UISceneSession lifecycle + + +- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; +} + + +- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. +} + + +@end diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/BranchSDKTestsHostApp/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AccentColor.colorset/Contents.json rename to BranchSDKTestsHostApp/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/BranchSDKTestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/BranchSDKTestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..230588010 --- /dev/null +++ b/BranchSDKTestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/Contents.json b/BranchSDKTestsHostApp/Assets.xcassets/Contents.json similarity index 100% rename from DeepLinkDemo/DeepLinkDemo/Assets.xcassets/Contents.json rename to BranchSDKTestsHostApp/Assets.xcassets/Contents.json diff --git a/DeepLinkDemo/DeepLinkDemo/Base.lproj/LaunchScreen.storyboard b/BranchSDKTestsHostApp/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from DeepLinkDemo/DeepLinkDemo/Base.lproj/LaunchScreen.storyboard rename to BranchSDKTestsHostApp/Base.lproj/LaunchScreen.storyboard diff --git a/TestHost/Base.lproj/Main.storyboard b/BranchSDKTestsHostApp/Base.lproj/Main.storyboard similarity index 95% rename from TestHost/Base.lproj/Main.storyboard rename to BranchSDKTestsHostApp/Base.lproj/Main.storyboard index 25a763858..808a21ce7 100644 --- a/TestHost/Base.lproj/Main.storyboard +++ b/BranchSDKTestsHostApp/Base.lproj/Main.storyboard @@ -9,7 +9,7 @@ - + diff --git a/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo.entitlements b/BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements similarity index 50% rename from DeepLinkDemo/DeepLinkDemo/DeepLinkDemo.entitlements rename to BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements index 51c38f856..9ad5d115f 100644 --- a/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo.entitlements +++ b/BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements @@ -4,9 +4,11 @@ com.apple.developer.associated-domains - applinks:timber.test-app.link - applinks:timber.test-app.link - applinks:timber.test-app.link + applinks:bnc.lt + applinks:bnctestbed.app.link + applinks:bnctestbed.test-app.link + applinks:bnctestbed-alternate.app.link + applinks:bnctestbed-alternate.test-app.link diff --git a/TestHost/Info.plist b/BranchSDKTestsHostApp/Info.plist similarity index 59% rename from TestHost/Info.plist rename to BranchSDKTestsHostApp/Info.plist index dd3c9afda..f0cb4d34f 100644 --- a/TestHost/Info.plist +++ b/BranchSDKTestsHostApp/Info.plist @@ -2,6 +2,17 @@ + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + branchtest + + + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -14,12 +25,19 @@ UISceneConfigurationName Default Configuration UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate + SceneDelegate UISceneStoryboardFile Main + branch_key + + live + key_live_hcnegAumkH7Kv18M8AOHhfgiohpXq5tB + test + key_test_hdcBLUy1xZ1JD0tKg7qrLcgirFmPPVJc + diff --git a/BranchSDKTestsHostApp/SceneDelegate.h b/BranchSDKTestsHostApp/SceneDelegate.h new file mode 100644 index 000000000..ae4e37f24 --- /dev/null +++ b/BranchSDKTestsHostApp/SceneDelegate.h @@ -0,0 +1,15 @@ +// +// SceneDelegate.h +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import + +@interface SceneDelegate : UIResponder + +@property (strong, nonatomic) UIWindow * window; + +@end + diff --git a/BranchSDKTestsHostApp/SceneDelegate.m b/BranchSDKTestsHostApp/SceneDelegate.m new file mode 100644 index 000000000..be25ed27f --- /dev/null +++ b/BranchSDKTestsHostApp/SceneDelegate.m @@ -0,0 +1,57 @@ +// +// SceneDelegate.m +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import "SceneDelegate.h" + +@interface SceneDelegate () + +@end + +@implementation SceneDelegate + + +- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). +} + + +- (void)sceneDidDisconnect:(UIScene *)scene { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). +} + + +- (void)sceneDidBecomeActive:(UIScene *)scene { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. +} + + +- (void)sceneWillResignActive:(UIScene *)scene { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). +} + + +- (void)sceneWillEnterForeground:(UIScene *)scene { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. +} + + +- (void)sceneDidEnterBackground:(UIScene *)scene { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. +} + + +@end diff --git a/BranchSDKTestsHostApp/ViewController.h b/BranchSDKTestsHostApp/ViewController.h new file mode 100644 index 000000000..83b3d1118 --- /dev/null +++ b/BranchSDKTestsHostApp/ViewController.h @@ -0,0 +1,14 @@ +// +// ViewController.h +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/BranchSDKTestsHostApp/ViewController.m b/BranchSDKTestsHostApp/ViewController.m new file mode 100644 index 000000000..0a3c38aa1 --- /dev/null +++ b/BranchSDKTestsHostApp/ViewController.m @@ -0,0 +1,22 @@ +// +// ViewController.m +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + + +@end diff --git a/BranchSDKTestsHostApp/cannedData/example.json b/BranchSDKTestsHostApp/cannedData/example.json new file mode 100644 index 000000000..d3be9b233 --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/example.json @@ -0,0 +1,31 @@ +{ + "user_string": "test user", + "user_number": 3.14, + "user_dict": { + "id": "273e4c5da13b978ee2f78f8997abd972959c184aaffb8cad716721a00a08d32b", + "name": "hello@branch.io" + }, + "user_dict_mixed": { + "id": 123, + "name": "hello@branch.io" + }, + "user_dict_numbers": { + "id": 123, + "name": 42 + }, + "user_array": [ + "123", + "abc", + "xyz" + ], + "user_array_mixed": [ + "abc", + 123, + "xyz" + ], + "user_array_numbers": [ + 1, + 2, + 3 + ] +} diff --git a/BranchSDKTestsHostApp/cannedData/latd.json b/BranchSDKTestsHostApp/cannedData/latd.json new file mode 100644 index 000000000..cc8d42631 --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/latd.json @@ -0,0 +1,7 @@ +{ + "last_attributed_touch_data": { + "$3p": "hello", + "~campaign": "world" + }, + "attribution_window": 30 +} diff --git a/BranchSDKTestsHostApp/cannedData/latd_empty_data.json b/BranchSDKTestsHostApp/cannedData/latd_empty_data.json new file mode 100644 index 000000000..5561c6a3c --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/latd_empty_data.json @@ -0,0 +1,4 @@ +{ + "last_attributed_touch_data": { }, + "attribution_window": 30 +} diff --git a/BranchSDKTestsHostApp/cannedData/latd_missing_data.json b/BranchSDKTestsHostApp/cannedData/latd_missing_data.json new file mode 100644 index 000000000..5dfcf058b --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/latd_missing_data.json @@ -0,0 +1,3 @@ +{ + "attribution_window": 30 +} diff --git a/BranchSDKTestsHostApp/cannedData/latd_missing_window.json b/BranchSDKTestsHostApp/cannedData/latd_missing_window.json new file mode 100644 index 000000000..7e4649891 --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/latd_missing_window.json @@ -0,0 +1,6 @@ +{ + "last_attributed_touch_data": { + "$3p": "hello", + "~campaign": "world" + } +} diff --git a/BranchSDKTestsHostApp/main.m b/BranchSDKTestsHostApp/main.m new file mode 100644 index 000000000..abfb64588 --- /dev/null +++ b/BranchSDKTestsHostApp/main.m @@ -0,0 +1,18 @@ +// +// main.m +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + NSString * appDelegateClassName; + @autoreleasepool { + // Setup code that might create autoreleased objects goes here. + appDelegateClassName = NSStringFromClass([AppDelegate class]); + } + return UIApplicationMain(argc, argv, nil, appDelegateClassName); +} diff --git a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.pbxproj b/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.pbxproj deleted file mode 100644 index 6117713fe..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,586 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 55; - objects = { - -/* Begin PBXBuildFile section */ - 180748E82833A914006DB0FA /* ReadLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 180748E72833A914006DB0FA /* ReadLogViewController.swift */; }; - 180748EA2833CC85006DB0FA /* ParentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 180748E92833CC85006DB0FA /* ParentViewController.swift */; }; - 182B1F43282E0ECE00EA8C70 /* AddMetaDataVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 182B1F42282E0ECE00EA8C70 /* AddMetaDataVC.swift */; }; - 182B1F45282E210B00EA8C70 /* MetaDataTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 182B1F44282E210B00EA8C70 /* MetaDataTableViewCell.swift */; }; - 183F6FA2282D109800E293F6 /* TrackContentVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183F6FA1282D109800E293F6 /* TrackContentVC.swift */; }; - 1877918A283C8D2400229CD5 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18779189283C8D2400229CD5 /* Utils.swift */; }; - 1889ACED283BE1C9009E3601 /* NSURLSessionBranch.m in Sources */ = {isa = PBXBuildFile; fileRef = 1889ACEC283BE1C9009E3601 /* NSURLSessionBranch.m */; }; - 18AC5ADE283F61430098736E /* LogFileListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18AC5ADD283F61430098736E /* LogFileListViewController.swift */; }; - 2A2347C154C6746FA55C3649 /* Pods_DeepLinkDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDBB5A837B0C008CA5BEC1EF /* Pods_DeepLinkDemo.framework */; }; - 7E1A39D42818289B002B302D /* DispalyVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E1A39D32818289B002B302D /* DispalyVC.swift */; }; - 7E2AE639280ED92800142446 /* CreateObjectReferenceObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E2AE638280ED92800142446 /* CreateObjectReferenceObject.swift */; }; - 7E2AE63B280EE1F700142446 /* GenerateURLVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E2AE63A280EE1F700142446 /* GenerateURLVC.swift */; }; - 7E2AE63F280EE23500142446 /* NavigateContentVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E2AE63E280EE23500142446 /* NavigateContentVC.swift */; }; - 7E37E69B280CF9D1003E42DB /* CommonMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E37E69A280CF9D1003E42DB /* CommonMethod.swift */; }; - 7E37E69D280D061E003E42DB /* SIAlertView in Resources */ = {isa = PBXBuildFile; fileRef = 7E37E69C280D061E003E42DB /* SIAlertView */; }; - 7E37E6A1280D12E2003E42DB /* img.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E37E6A0280D12E2003E42DB /* img.png */; }; - 7E6505F6281B003C006179FF /* ReadVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E6505F5281B003C006179FF /* ReadVC.swift */; }; - 7E7477CA2809C46C0088A7D3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E7477C92809C46C0088A7D3 /* AppDelegate.swift */; }; - 7E7477CE2809C46C0088A7D3 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E7477CD2809C46C0088A7D3 /* HomeViewController.swift */; }; - 7E7477D12809C46C0088A7D3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7E7477CF2809C46C0088A7D3 /* Main.storyboard */; }; - 7E7477D32809C46D0088A7D3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7E7477D22809C46D0088A7D3 /* Assets.xcassets */; }; - 7E7477D62809C46D0088A7D3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7E7477D42809C46D0088A7D3 /* LaunchScreen.storyboard */; }; - 7ED8BFED2835EFA90080C0CB /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED8BFEC2835EFA90080C0CB /* Reachability.swift */; }; - 7ED8BFEF2835EFB40080C0CB /* CommonAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED8BFEE2835EFB40080C0CB /* CommonAlert.swift */; }; - 7EE84374281CDFAE00A1561C /* StartupOptionsData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EE84373281CDFAE00A1561C /* StartupOptionsData.swift */; }; - 7EF58D5B2812CF2300BA92D5 /* WebViewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EF58D5A2812CF2300BA92D5 /* WebViewVC.swift */; }; - B7B7DC2A2859974E00D45FC5 /* TextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7B7DC292859974E00D45FC5 /* TextViewController.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 180748E72833A914006DB0FA /* ReadLogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadLogViewController.swift; sourceTree = ""; }; - 180748E92833CC85006DB0FA /* ParentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentViewController.swift; sourceTree = ""; }; - 182B1F42282E0ECE00EA8C70 /* AddMetaDataVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddMetaDataVC.swift; sourceTree = ""; }; - 182B1F44282E210B00EA8C70 /* MetaDataTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetaDataTableViewCell.swift; sourceTree = ""; }; - 183F6FA1282D109800E293F6 /* TrackContentVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackContentVC.swift; sourceTree = ""; }; - 18779189283C8D2400229CD5 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; - 1889ACEB283BE1C9009E3601 /* NSURLSessionBranch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSURLSessionBranch.h; sourceTree = ""; }; - 1889ACEC283BE1C9009E3601 /* NSURLSessionBranch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSURLSessionBranch.m; sourceTree = ""; }; - 18AC5ADD283F61430098736E /* LogFileListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogFileListViewController.swift; sourceTree = ""; }; - 7E1A39D32818289B002B302D /* DispalyVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispalyVC.swift; sourceTree = ""; }; - 7E2AE638280ED92800142446 /* CreateObjectReferenceObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateObjectReferenceObject.swift; sourceTree = ""; }; - 7E2AE63A280EE1F700142446 /* GenerateURLVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateURLVC.swift; sourceTree = ""; }; - 7E2AE63E280EE23500142446 /* NavigateContentVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigateContentVC.swift; sourceTree = ""; }; - 7E37E69A280CF9D1003E42DB /* CommonMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonMethod.swift; sourceTree = ""; }; - 7E37E69C280D061E003E42DB /* SIAlertView */ = {isa = PBXFileReference; lastKnownFileType = folder; path = SIAlertView; sourceTree = ""; }; - 7E37E69E280D0676003E42DB /* Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Header.h; sourceTree = ""; }; - 7E37E69F280D06FF003E42DB /* DeepLinkDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DeepLinkDemo-Bridging-Header.h"; sourceTree = ""; }; - 7E37E6A0280D12E2003E42DB /* img.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img.png; sourceTree = ""; }; - 7E6505F5281B003C006179FF /* ReadVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadVC.swift; sourceTree = ""; }; - 7E7477C62809C46C0088A7D3 /* DeepLinkDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DeepLinkDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E7477C92809C46C0088A7D3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7E7477CD2809C46C0088A7D3 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; - 7E7477D02809C46C0088A7D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 7E7477D22809C46D0088A7D3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7E7477D52809C46D0088A7D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 7E7477D72809C46D0088A7D3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7ED8BFEB2835EFA90080C0CB /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; - 7ED8BFEC2835EFA90080C0CB /* Reachability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reachability.swift; sourceTree = ""; }; - 7ED8BFEE2835EFB40080C0CB /* CommonAlert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommonAlert.swift; sourceTree = ""; }; - 7EE84373281CDFAE00A1561C /* StartupOptionsData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartupOptionsData.swift; sourceTree = ""; }; - 7EF58D5A2812CF2300BA92D5 /* WebViewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewVC.swift; sourceTree = ""; }; - 7EF58D5C2816D14700BA92D5 /* DeepLinkDemo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DeepLinkDemo.entitlements; sourceTree = ""; }; - 88EDCA13B444CE5565DC92FA /* Pods-DeepLinkDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DeepLinkDemo.release.xcconfig"; path = "Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo.release.xcconfig"; sourceTree = ""; }; - B7B7DC292859974E00D45FC5 /* TextViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewController.swift; sourceTree = ""; }; - C06885D21868B25319262FC1 /* Pods-DeepLinkDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DeepLinkDemo.debug.xcconfig"; path = "Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo.debug.xcconfig"; sourceTree = ""; }; - DDBB5A837B0C008CA5BEC1EF /* Pods_DeepLinkDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DeepLinkDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7E7477C32809C46C0088A7D3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2A2347C154C6746FA55C3649 /* Pods_DeepLinkDemo.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 0D26D1E3284DFA33003FAB18 /* Constants */ = { - isa = PBXGroup; - children = ( - 18779189283C8D2400229CD5 /* Utils.swift */, - 7ED8BFEE2835EFB40080C0CB /* CommonAlert.swift */, - 7E37E69A280CF9D1003E42DB /* CommonMethod.swift */, - ); - path = Constants; - sourceTree = ""; - }; - 29D53CAAE9E9EF2F96296086 /* Frameworks */ = { - isa = PBXGroup; - children = ( - DDBB5A837B0C008CA5BEC1EF /* Pods_DeepLinkDemo.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 7E2AE642280EFF1200142446 /* Controllers */ = { - isa = PBXGroup; - children = ( - 7E7477CD2809C46C0088A7D3 /* HomeViewController.swift */, - B7B7DC292859974E00D45FC5 /* TextViewController.swift */, - 7E2AE638280ED92800142446 /* CreateObjectReferenceObject.swift */, - 7E2AE63A280EE1F700142446 /* GenerateURLVC.swift */, - 7E2AE63E280EE23500142446 /* NavigateContentVC.swift */, - 7E1A39D32818289B002B302D /* DispalyVC.swift */, - 7EF58D5A2812CF2300BA92D5 /* WebViewVC.swift */, - 7E6505F5281B003C006179FF /* ReadVC.swift */, - 183F6FA1282D109800E293F6 /* TrackContentVC.swift */, - 182B1F42282E0ECE00EA8C70 /* AddMetaDataVC.swift */, - 182B1F44282E210B00EA8C70 /* MetaDataTableViewCell.swift */, - 180748E72833A914006DB0FA /* ReadLogViewController.swift */, - 18AC5ADD283F61430098736E /* LogFileListViewController.swift */, - 180748E92833CC85006DB0FA /* ParentViewController.swift */, - ); - path = Controllers; - sourceTree = ""; - }; - 7E7477BD2809C46C0088A7D3 = { - isa = PBXGroup; - children = ( - 7E7477C82809C46C0088A7D3 /* DeepLinkDemo */, - 7E7477C72809C46C0088A7D3 /* Products */, - DB9F65A595474F5DA261D89A /* Pods */, - 29D53CAAE9E9EF2F96296086 /* Frameworks */, - ); - sourceTree = ""; - }; - 7E7477C72809C46C0088A7D3 /* Products */ = { - isa = PBXGroup; - children = ( - 7E7477C62809C46C0088A7D3 /* DeepLinkDemo.app */, - ); - name = Products; - sourceTree = ""; - }; - 7E7477C82809C46C0088A7D3 /* DeepLinkDemo */ = { - isa = PBXGroup; - children = ( - 7E2AE642280EFF1200142446 /* Controllers */, - 1889ACEB283BE1C9009E3601 /* NSURLSessionBranch.h */, - 1889ACEC283BE1C9009E3601 /* NSURLSessionBranch.m */, - 7ED8BFEA2835EF9E0080C0CB /* Reachability */, - 7EF58D5C2816D14700BA92D5 /* DeepLinkDemo.entitlements */, - 7E37E69C280D061E003E42DB /* SIAlertView */, - 7E7477C92809C46C0088A7D3 /* AppDelegate.swift */, - 7EE84373281CDFAE00A1561C /* StartupOptionsData.swift */, - 0D26D1E3284DFA33003FAB18 /* Constants */, - 7E7477CF2809C46C0088A7D3 /* Main.storyboard */, - 7E37E6A0280D12E2003E42DB /* img.png */, - 7E7477D22809C46D0088A7D3 /* Assets.xcassets */, - 7E7477D42809C46D0088A7D3 /* LaunchScreen.storyboard */, - 7E7477D72809C46D0088A7D3 /* Info.plist */, - 7E37E69E280D0676003E42DB /* Header.h */, - 7E37E69F280D06FF003E42DB /* DeepLinkDemo-Bridging-Header.h */, - ); - path = DeepLinkDemo; - sourceTree = ""; - }; - 7ED8BFEA2835EF9E0080C0CB /* Reachability */ = { - isa = PBXGroup; - children = ( - 7ED8BFEB2835EFA90080C0CB /* Reachability.h */, - 7ED8BFEC2835EFA90080C0CB /* Reachability.swift */, - ); - path = Reachability; - sourceTree = ""; - }; - DB9F65A595474F5DA261D89A /* Pods */ = { - isa = PBXGroup; - children = ( - C06885D21868B25319262FC1 /* Pods-DeepLinkDemo.debug.xcconfig */, - 88EDCA13B444CE5565DC92FA /* Pods-DeepLinkDemo.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7E7477C52809C46C0088A7D3 /* DeepLinkDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7E7477DA2809C46D0088A7D3 /* Build configuration list for PBXNativeTarget "DeepLinkDemo" */; - buildPhases = ( - 8C8C5B24F34C07814525F311 /* [CP] Check Pods Manifest.lock */, - 7E7477C22809C46C0088A7D3 /* Sources */, - 7E7477C32809C46C0088A7D3 /* Frameworks */, - 7E7477C42809C46C0088A7D3 /* Resources */, - 9086714B33BB3D176E3DED70 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = DeepLinkDemo; - productName = DeepLinkDemo; - productReference = 7E7477C62809C46C0088A7D3 /* DeepLinkDemo.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7E7477BE2809C46C0088A7D3 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1330; - LastUpgradeCheck = 1330; - TargetAttributes = { - 7E7477C52809C46C0088A7D3 = { - CreatedOnToolsVersion = 13.3.1; - LastSwiftMigration = 1340; - }; - }; - }; - buildConfigurationList = 7E7477C12809C46C0088A7D3 /* Build configuration list for PBXProject "DeepLinkDemo" */; - compatibilityVersion = "Xcode 13.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7E7477BD2809C46C0088A7D3; - productRefGroup = 7E7477C72809C46C0088A7D3 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7E7477C52809C46C0088A7D3 /* DeepLinkDemo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7E7477C42809C46C0088A7D3 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7E37E6A1280D12E2003E42DB /* img.png in Resources */, - 7E7477D62809C46D0088A7D3 /* LaunchScreen.storyboard in Resources */, - 7E7477D32809C46D0088A7D3 /* Assets.xcassets in Resources */, - 7E37E69D280D061E003E42DB /* SIAlertView in Resources */, - 7E7477D12809C46C0088A7D3 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 8C8C5B24F34C07814525F311 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-DeepLinkDemo-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9086714B33BB3D176E3DED70 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7E7477C22809C46C0088A7D3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 182B1F43282E0ECE00EA8C70 /* AddMetaDataVC.swift in Sources */, - 7E6505F6281B003C006179FF /* ReadVC.swift in Sources */, - 7ED8BFED2835EFA90080C0CB /* Reachability.swift in Sources */, - 7E7477CE2809C46C0088A7D3 /* HomeViewController.swift in Sources */, - 180748E82833A914006DB0FA /* ReadLogViewController.swift in Sources */, - 7E7477CA2809C46C0088A7D3 /* AppDelegate.swift in Sources */, - 7EF58D5B2812CF2300BA92D5 /* WebViewVC.swift in Sources */, - 1877918A283C8D2400229CD5 /* Utils.swift in Sources */, - 1889ACED283BE1C9009E3601 /* NSURLSessionBranch.m in Sources */, - 7E37E69B280CF9D1003E42DB /* CommonMethod.swift in Sources */, - 183F6FA2282D109800E293F6 /* TrackContentVC.swift in Sources */, - 180748EA2833CC85006DB0FA /* ParentViewController.swift in Sources */, - 7E2AE63B280EE1F700142446 /* GenerateURLVC.swift in Sources */, - 7E1A39D42818289B002B302D /* DispalyVC.swift in Sources */, - 182B1F45282E210B00EA8C70 /* MetaDataTableViewCell.swift in Sources */, - 7ED8BFEF2835EFB40080C0CB /* CommonAlert.swift in Sources */, - 7EE84374281CDFAE00A1561C /* StartupOptionsData.swift in Sources */, - 7E2AE639280ED92800142446 /* CreateObjectReferenceObject.swift in Sources */, - 18AC5ADE283F61430098736E /* LogFileListViewController.swift in Sources */, - 7E2AE63F280EE23500142446 /* NavigateContentVC.swift in Sources */, - B7B7DC2A2859974E00D45FC5 /* TextViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 7E7477CF2809C46C0088A7D3 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 7E7477D02809C46C0088A7D3 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 7E7477D42809C46D0088A7D3 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 7E7477D52809C46D0088A7D3 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7E7477D82809C46D0088A7D3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7E7477D92809C46D0088A7D3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 7E7477DB2809C46D0088A7D3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C06885D21868B25319262FC1 /* Pods-DeepLinkDemo.debug.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = DeepLinkDemo/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = SaaS_SDK_TestBed_iOS; - INFOPLIST_KEY_LSApplicationCategoryType = ""; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait; - INFOPLIST_OUTPUT_FORMAT = "same-as-input"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Framework", - ); - MARKETING_VERSION = 1.1; - PLIST_FILE_OUTPUT_FORMAT = "same-as-input"; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.saas.sdk.testbed; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "iOS Saas SDK - Dev"; - STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Debug; - }; - 7E7477DC2809C46D0088A7D3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 88EDCA13B444CE5565DC92FA /* Pods-DeepLinkDemo.release.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = DeepLinkDemo/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = SaaS_SDK_TestBed_iOS; - INFOPLIST_KEY_LSApplicationCategoryType = ""; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait; - INFOPLIST_OUTPUT_FORMAT = "same-as-input"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Framework", - ); - MARKETING_VERSION = 1.1; - ONLY_ACTIVE_ARCH = YES; - PLIST_FILE_OUTPUT_FORMAT = "same-as-input"; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.saas.sdk.testbed; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "iOS Saas SDK - Dev"; - STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7E7477C12809C46C0088A7D3 /* Build configuration list for PBXProject "DeepLinkDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7E7477D82809C46D0088A7D3 /* Debug */, - 7E7477D92809C46D0088A7D3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7E7477DA2809C46D0088A7D3 /* Build configuration list for PBXNativeTarget "DeepLinkDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7E7477DB2809C46D0088A7D3 /* Debug */, - 7E7477DC2809C46D0088A7D3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7E7477BE2809C46C0088A7D3 /* Project object */; -} diff --git a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/DeepLinkDemo/DeepLinkDemo.xcodeproj/xcshareddata/xcschemes/DeepLinkDemo.xcscheme b/DeepLinkDemo/DeepLinkDemo.xcodeproj/xcshareddata/xcschemes/DeepLinkDemo.xcscheme deleted file mode 100644 index a2671aeb8..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcodeproj/xcshareddata/xcschemes/DeepLinkDemo.xcscheme +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/DeepLinkDemo/DeepLinkDemo.xcworkspace/contents.xcworkspacedata b/DeepLinkDemo/DeepLinkDemo.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index dbfeee663..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/DeepLinkDemo/DeepLinkDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/DeepLinkDemo/DeepLinkDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/DeepLinkDemo/DeepLinkDemo/AppDelegate.swift b/DeepLinkDemo/DeepLinkDemo/AppDelegate.swift deleted file mode 100644 index bebb005e5..000000000 --- a/DeepLinkDemo/DeepLinkDemo/AppDelegate.swift +++ /dev/null @@ -1,268 +0,0 @@ -// -// AppDelegate.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/15/22. -// - -import UIKit -import BranchSDK -import IQKeyboardManager -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - static var shared: AppDelegate { - return (UIApplication.shared.delegate as? AppDelegate)! - - } - var launchOption = [UIApplication.LaunchOptionsKey : Any]() - var delegate: AppDelegate! - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { - print("didFinishLaunchingWithOptions") - if #available(iOS 10.0, *) { - let center = UNUserNotificationCenter.current() - UNUserNotificationCenter.current().delegate = self - center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in - if granted { - print("Allowed to send Notification") - } else { - print("Not allowed to send Notification") - } - } - }else{ - let notificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) - UIApplication.shared.registerUserNotificationSettings(notificationSettings) - _ = application.beginBackgroundTask(withName: "showNotification", expirationHandler: nil) - } - - Utils.shared.clearAllLogFiles() - Utils.shared.setLogFile("AppLaunch") - IQKeyboardManager.shared().isEnabled = true - StartupOptionsData.setActiveSetDebugEnabled(true) - StartupOptionsData.setPendingSetDebugEnabled(true) - Utils.shared.setLogFile("AppDelegate") - return true - } - - - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - - //check for link_click_id - if url.absoluteString.contains("link_click_id") == true{ - return Branch.getInstance().application(app, open: url, options: options) - } - return true - } - - - func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { - // handler for Universal Links - return Branch.getInstance().continue(userActivity) - } - - func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { - // handler for Push Notifications - Branch.getInstance().handlePushNotification(userInfo) - } - - - - func application(_ application: UIApplication, didReceiveRemoteNotification launchOptions: [AnyHashable: Any]) -> Void { - Branch.getInstance().handlePushNotification(launchOptions) - } - - func application(_ application: UIApplication, didReceive notification: UILocalNotification){ - print(#function) - } - - func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, completionHandler: @escaping () -> Void){ - print(#function) - } - - - // Respond to URL scheme links - func application(_ application: UIApplication, - open url: URL, - sourceApplication: String?, - annotation: Any) -> Bool { - - let branchHandled = Branch.getInstance().application(application, - open: url, - sourceApplication: sourceApplication, - annotation: annotation - ) - if(!branchHandled) { - // If not handled by Branch, do other deep link routing for the Facebook SDK, Pinterest SDK, etc - - } - return true - } - - // Respond to Universal Links - func application(_ - application: UIApplication, - continue userActivity: NSUserActivity, - restorationHandler: @escaping ([Any]?) -> Void - ) -> Bool { - let branchHandled = Branch.getInstance().continue(userActivity) - if (userActivity.activityType == NSUserActivityTypeBrowsingWeb) { - if let url = userActivity.webpageURL, - !branchHandled { - - } - } - - // Apply your logic to determine the return value of this method - return true - } - - - func pushNewView() { - if let controller = NavigateContentVC() as? NavigateContentVC { - if let window = self.window, let rootViewController = window.rootViewController { - var currentController = rootViewController - while let presentedController = currentController.presentedViewController { - currentController = presentedController - } - currentController.present(controller, animated: true, completion: nil) - } - } - } - func handleDeepLinkObject(object: BranchUniversalObject, linkProperties:BranchLinkProperties, error:NSError) { - - NSLog("Deep linked with object: %@.", object); - let deeplinkText = object.contentMetadata.customMetadata.value(forKey: "deeplink_text") - let textDetail = "Successfully Deeplinked:\n\n%@\nSession Details:\n\n%@, \(String(describing: deeplinkText)) \(String(describing: Branch.getInstance().getLatestReferringParams()?.description))" - NSLog(textDetail) - self.pushNewView() - } - - - - - func getBranchData(_ launchOptions: [UIApplication.LaunchOptionsKey : Any]?) { - - Branch.getInstance().initSession( - launchOptions: launchOptions, - automaticallyDisplayDeepLinkController: false, - deepLinkHandler: { params, error in - - defer { - let notificationName = Notification.Name("BranchCallbackCompleted") - NotificationCenter.default.post(name: notificationName, object: nil) - } - - guard error == nil else { - NSLog("Branch TestBed: Initialization failed: " + error!.localizedDescription) - return - } - - guard let paramsDictionary = (params as? Dictionary) else { - NSLog("No Branch parameters returned") - return - } - - let clickedBranchLink = params?[BRANCH_INIT_KEY_CLICKED_BRANCH_LINK] as! Bool? - if let referringLink = paramsDictionary["~referring_link"] as! String?, - let trackerId = paramsDictionary["ios_tracker_id"] as! String?, - let clickedBranchLink = clickedBranchLink, - clickedBranchLink { - var adjustUrl = URLComponents(string: referringLink) - var adjust_tracker:URLQueryItem - if referringLink.starts(with: "https://") || referringLink.starts(with: "http://") { - adjust_tracker = URLQueryItem(name: "adjust_t", value: trackerId) - } else { - adjust_tracker = URLQueryItem(name: "adjust_tracker", value: trackerId) - } - let adjust_campaign = URLQueryItem(name: "adjust_campaign", value: paramsDictionary[BRANCH_INIT_KEY_CAMPAIGN] as? String) - let adjust_adgroup = URLQueryItem(name: "adjust_adgroup", value: paramsDictionary[BRANCH_INIT_KEY_CHANNEL] as? String) - let adjust_creative = URLQueryItem(name: "adjust_creative", value: paramsDictionary[BRANCH_INIT_KEY_FEATURE] as? String) - let queryItems = [adjust_tracker,adjust_campaign,adjust_adgroup,adjust_creative] - adjustUrl?.queryItems = queryItems -// if let url = adjustUrl?.url { -// //Adjust.appWillOpen(url) -// } - } - // Deeplinking logic for use when automaticallyDisplayDeepLinkController = false - if let clickedBranchLink = clickedBranchLink, - clickedBranchLink { - let nc = self.window!.rootViewController as! UINavigationController - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "DispalyVC") as? DispalyVC { - let linkurl = UserDefaults.standard.value(forKey: "link") as? String ?? "" - //let referringLink = paramsDictionary["~referring_link"] as! String - let content = String(format:"\nReferring link: %@ \n\nSession Details:\n %@", linkurl, paramsDictionary.jsonStringRepresentation!) - vc.textDescription = content - vc.appData = paramsDictionary - vc.linkURL = linkurl - nc.pushViewController(vc, animated: true) - } - } else { - NSLog("Branch TestBed: Finished init with params\n%@", paramsDictionary.description) - } - }) - } - - - func handleURL(_ url: URL) { - guard url.pathComponents.count >= 3 else { return } - - let section = url.pathComponents[1] - let detail = url.pathComponents[2] - - switch section { - case "post": - guard let id = Int(detail) else { break } - // navigateToItem(id) - case "settings": - //navigateToSettings(detail) - break - default: break - } - } - -} - - -@available(iOS 10.0, *) -extension AppDelegate: UNUserNotificationCenterDelegate{ - - func getApprovalForSendingNotification(){ - if #available(iOS 11.0, *) { - let center = UNUserNotificationCenter.current() - UNUserNotificationCenter.current().delegate = self - center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in - if granted { - print("Allowed to send Notification") - } else { - print("Not allowed to send Notification") - } - } - }else{ - let notificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) - UIApplication.shared.registerUserNotificationSettings(notificationSettings) - } - } - func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { - completionHandler([.alert, .badge, .sound]) - } - func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { - print(response) - let content = response.notification.request.content - print(content.userInfo) - Branch.getInstance().handlePushNotification(content.userInfo) - } - -} -extension Dictionary { - var jsonStringRepresentation: String? { - guard let theJSONData = try? JSONSerialization.data(withJSONObject: self, - options: [.prettyPrinted]) else { - return nil - } - - return String(data: theJSONData, encoding: .ascii) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9221b9bb1..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/Contents.json b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/Contents.json deleted file mode 100644 index d18ba8435..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/Contents.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "icons8-left-100.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/icons8-left-100.png b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/icons8-left-100.png deleted file mode 100644 index b1952be8a..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/icons8-left-100.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/Contents.json b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/Contents.json deleted file mode 100644 index aca8f0cf5..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "filename" : "img.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/img.png b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/img.png deleted file mode 100644 index 95f2e9562..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/img.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/Base.lproj/Main.storyboard b/DeepLinkDemo/DeepLinkDemo/Base.lproj/Main.storyboard deleted file mode 100644 index 7c5844536..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Base.lproj/Main.storyboard +++ /dev/null @@ -1,2685 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/DeepLinkDemo/DeepLinkDemo/Constants/CommonAlert.swift b/DeepLinkDemo/DeepLinkDemo/Constants/CommonAlert.swift deleted file mode 100644 index feb4c06e4..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Constants/CommonAlert.swift +++ /dev/null @@ -1,22 +0,0 @@ - -import UIKit - -class CommonAlert { - - static let shared = CommonAlert() - - func showActionAlertView(title:String,message:String,actions:[UIAlertAction],preferredStyle:UIAlertController.Style = .alert,viewController:UIViewController?) -> Void { - let alertController = UIAlertController(title: title, message:message, preferredStyle: preferredStyle) - if actions.isEmpty { - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in - viewController?.dismiss(animated: true, completion: nil) - })) - }else{ - for action in actions { - alertController.addAction(action) - } - } - - viewController?.present(alertController, animated: true, completion: nil) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Constants/CommonMethod.swift b/DeepLinkDemo/DeepLinkDemo/Constants/CommonMethod.swift deleted file mode 100644 index de52c755b..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Constants/CommonMethod.swift +++ /dev/null @@ -1,59 +0,0 @@ -// CommonMethod.swift -// DeepLinkDemo -// Created by Rakesh kumar on 4/18/22. - - -import Foundation -import UIKit -import BranchSDK -import SystemConfiguration - - -class CommonMethod { - - static let sharedInstance = CommonMethod() - var branchUniversalObject = BranchUniversalObject() - var linkProperties = BranchLinkProperties() - var contentMetaData : BranchContentMetadata? = nil - - var branchData = [String: AnyObject]() - - func navigatetoContent(onCompletion:@escaping (NSDictionary?) -> Void) -> Void { - guard let data = branchData as? [String: AnyObject] else { return } - onCompletion(data as NSDictionary) - } - - func showActionAlertView(title:String,message:String,actions:[UIAlertAction],preferredStyle:UIAlertController.Style = .alert,viewController:UIViewController?) -> Void { - let alertController = UIAlertController(title: title, message:message, preferredStyle: preferredStyle) - if actions.isEmpty { - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in - viewController?.dismiss(animated: true, completion: nil) - - })) - } else { - for action in actions { - alertController.addAction(action) - } - } - } - - func isInternetAvailable() -> Bool { - var zeroAddress = sockaddr_in() - zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress)) - zeroAddress.sin_family = sa_family_t(AF_INET) - let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) { - $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in - SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress) - } - } - - var flags = SCNetworkReachabilityFlags() - - if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) { - return false - } - let isReachable = flags.contains(.reachable) - let needsConnection = flags.contains(.connectionRequired) - return (isReachable && !needsConnection) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Constants/Utils.swift b/DeepLinkDemo/DeepLinkDemo/Constants/Utils.swift deleted file mode 100644 index b0182457b..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Constants/Utils.swift +++ /dev/null @@ -1,87 +0,0 @@ -// -// Utils.swift -// DeepLinkDemo -// -// Created by Apple on 24/05/22. -// - -import Foundation -import UIKit - -class Utils: NSObject { - - static let shared = Utils() - var logFileName: String? - var prevCommandLogFileName: String? - - func clearAllLogFiles(){ - - let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! - - do { - let fileURLs = try FileManager.default.contentsOfDirectory(at: documentsUrl, - includingPropertiesForKeys: nil, - options: .skipsHiddenFiles) - for fileURL in fileURLs { - try FileManager.default.removeItem(at: fileURL) - } - } catch { - NSLog("Failed to delete the file %@", error.localizedDescription) - } - - } - - - func removeItem(_ relativeFilePath: String) { - guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } - let absoluteFilePath = documentsDirectory.appendingPathComponent(relativeFilePath) - try? FileManager.default.removeItem(at: absoluteFilePath) - } - - func setLogFile(_ fileName: String?) { - if fileName == nil { - logFileName = nil - return - } - let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).map(\.path)[0] - let pathForLog = "\(documentsDirectory)/\(fileName ?? "app").log" - self.removeItem(pathForLog) - if (logFileName == nil) { - logFileName = pathForLog - prevCommandLogFileName = logFileName - } else { - prevCommandLogFileName = logFileName - logFileName = pathForLog - } - let cstr = (pathForLog as NSString).utf8String - freopen(cstr, "a+", stderr) - - } - - func printLogMessage(_ message: String) { - objc_sync_enter(self) - do { - print(message) // print to console - - if !FileManager.default.fileExists(atPath: logFileName!) { // does it exits? - FileManager.default.createFile(atPath: logFileName!, contents: nil) - } - - if let data = message.data(using: .utf8) { - let fileHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: logFileName!)) - if #available(iOS 13.4, *) { - print(" ============= ********** Writing in file " + logFileName!) - try fileHandle.seekToEnd() - try fileHandle.write(contentsOf: data) - try fileHandle.close() - } else { - print("Unable to write log: iOS Version not supported") - } - } - } catch let error as NSError { // something wrong - print("Unable to write log: \(error.debugDescription)") // debug printout - } - objc_sync_exit(self) - } -} - diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/AddMetaDataVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/AddMetaDataVC.swift deleted file mode 100644 index 76884a790..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/AddMetaDataVC.swift +++ /dev/null @@ -1,117 +0,0 @@ -// -// AddMetaDataVC.swift -// DeepLinkDemo -// -// Created by Apple on 13/05/22. -// - -import UIKit -import BranchSDK - -class AddMetaDataVC: ParentViewController { - - @IBOutlet weak var metaDataTblVw: UITableView! - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - - self.metaDataTblVw.keyboardDismissMode = .onDrag - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("AddMetadata") - } - - - @IBAction func backBtnAction(){ - self.navigationController?.popToRootViewController(animated: true) - } - - @objc func submitBtnAction(){ - if let cell = metaDataTblVw.cellForRow(at: IndexPath(row: 0, section: 0)) as? MetaDataTableViewCell{ - -// let branchUniversalObject = CommonMethod.sharedInstance.branchUniversalObject -// branchUniversalObject.canonicalIdentifier = branchUniversalObject.canonicalIdentifier -// branchUniversalObject.canonicalUrl = "https://branch.io/item/12345" -// branchUniversalObject.title = branchUniversalObject.title - let contentMetadata = BranchContentMetadata() - let contentSchemaSelected : BranchContentSchema = BranchContentSchema(rawValue: cell.contentSchema.text!) - contentMetadata.contentSchema = contentSchemaSelected - let quantityEntered = Double(cell.quantity.text ?? "0") - contentMetadata.quantity = quantityEntered ?? 0 - let formattedPrice = NSDecimalNumber(string: cell.price.text ?? "0.0") - if cell.price.text != "" { - contentMetadata.price = formattedPrice - let currencySelected: BNCCurrency = BNCCurrency(rawValue: cell.currencyName.text!) - contentMetadata.currency = currencySelected - } - contentMetadata.sku = cell.sku.text - contentMetadata.productName = cell.productName.text - contentMetadata.productBrand = cell.productBrand.text - let productCategorySelected: BNCProductCategory = BNCProductCategory(rawValue: cell.productCategory.text!) - contentMetadata.productCategory = productCategorySelected - contentMetadata.productVariant = cell.productVariant.text - let conditionSelected: BranchCondition = BranchCondition(rawValue: cell.productCondition.text!) - contentMetadata.condition = conditionSelected - contentMetadata.customMetadata = [ - "custom_key1": cell.customMetadata.text!, - ] - contentMetadata.addressStreet = cell.street.text - contentMetadata.addressCity = cell.city.text - contentMetadata.addressRegion = cell.region.text - contentMetadata.addressCountry = cell.country.text - contentMetadata.addressPostalCode = cell.postalCode.text - - contentMetadata.latitude = Double(cell.latitude.text ?? "0.0") ?? 0.0 - contentMetadata.longitude = Double(cell.longitude.text ?? "0.0") ?? 0.0 - - contentMetadata.ratingAverage = Double(cell.averageRating.text ?? "0.0") ?? 0.0 - contentMetadata.ratingMax = Double(cell.maximumRating.text ?? "0.0") ?? 0.0 - contentMetadata.ratingCount = Int(cell.ratingCount.text ?? "0") ?? 0 - contentMetadata.rating = Double(cell.rating.text ?? "0.0") ?? 0.0 - - contentMetadata.imageCaptions = [cell.imageCaption.text ?? ""] - CommonMethod.sharedInstance.contentMetaData = contentMetadata - print("ContentMetaData:", contentMetadata) - - let metadataDetail = String(format: "%@", contentMetadata) - NSLog("Metadata", metadataDetail); - Utils.shared.setLogFile("AddMetadata") - - self.navigationController?.popViewController(animated: true) - } - } - -} - -extension AddMetaDataVC: UITableViewDataSource, UITableViewDelegate{ - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCell(withIdentifier: "MetaDataTableViewCell", for: indexPath) as? MetaDataTableViewCell{ - cell.submitBtn.addTarget(self, action: #selector(submitBtnAction), for: UIControl.Event.touchUpInside) - cell.pickerDelegate = self - return cell - } - return UITableViewCell() - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return UITableView.automaticDimension - } -} - - -extension AddMetaDataVC: PickerViewDelegate{ - func removePickerView() { - self.view.endEditing(true) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/CreateObjectReferenceObject.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/CreateObjectReferenceObject.swift deleted file mode 100644 index 061f256d1..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/CreateObjectReferenceObject.swift +++ /dev/null @@ -1,268 +0,0 @@ -// CreateObjectReferenceObject.swift -// DeepLinkDemo -// Created by Rakesh kumar on 4/19/22. - -import UIKit -import BranchSDK - - -class CreateObjectReferenceObject: ParentViewController { - @IBOutlet weak var txtFldContentTitle: UITextField! - @IBOutlet weak var txtFldCanonicalIdentifier: UITextField! - @IBOutlet weak var txtFldDescription: UITextField! - @IBOutlet weak var txtFldImageUrl: UITextField! - @IBOutlet weak var scrollViewMain: UIScrollView! - - var screenMode = 0 - var txtFldValue = "" - var responseStatus = "" - - enum ScreenMode { - static let createBUO = 0 - static let readdeeplink = 1 - static let sharedeeplink = 2 - static let navigatetoContent = 3 - static let handlLinkinWebview = 4 - static let createdeeplink = 5 - static let sendnotification = 6 - static let trackContent = 7 - static let displayContent = 8 - } - - override func viewDidLoad() { - super.viewDidLoad() - - uiSetUp() - - super.reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if self.screenMode == ScreenMode.trackContent { - Utils.shared.setLogFile("TrackContent") - } - else { - Utils.shared.setLogFile("CreateBUO") - } - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollViewMain.contentSize.height = scrollViewMain.subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? scrollViewMain.contentSize.height - } - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - @objc func addMetaDataAction(sender: UIButton) { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "AddMetaDataVC") as? AddMetaDataVC { - self.navigationController?.pushViewController(vc, animated: true) - } - } - fileprivate func handleOkBtnAction(dict : [String:Any], alertMessage: String) { - Utils.shared.setLogFile("CreateBUO") - if self.screenMode == ScreenMode.displayContent { - launchGenerateURLVC(dict: dict, displayContent: true) - }else if self.screenMode == ScreenMode.trackContent { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, message: alertMessage, TrackContent: true) - }else if self.screenMode == ScreenMode.sendnotification { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, forNotification: true) - }else if self.screenMode == ScreenMode.createdeeplink { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, CreateDeepLink: true) - }else if self.screenMode == ScreenMode.sharedeeplink { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, ShareDeepLink: true) - }else if self.screenMode == ScreenMode.readdeeplink { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict) - }else if self.screenMode == ScreenMode.navigatetoContent { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, NavigateToContent: true) - }else if self.screenMode == ScreenMode.handlLinkinWebview { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, handleLinkInWebview: true) - }else { - self.navigationController?.popToRootViewController(animated: true) - } - } - - func launchGenerateURLVC(dict: [String:Any], message: String? = "", ShareDeepLink: Bool? = false, displayContent: Bool? = false, NavigateToContent: Bool? = false, TrackContent: Bool? = false, handleLinkInWebview: Bool? = false, CreateDeepLink: Bool? = false, forNotification: Bool? = false) { - if self.screenMode == ScreenMode.trackContent { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController { - vc.isTrackContent = TrackContent! - vc.forNotification = forNotification! - vc.isCreateDeepLink = CreateDeepLink! - vc.isShareDeepLink = ShareDeepLink! - vc.isNavigateToContent = NavigateToContent! - vc.handleLinkInWebview = handleLinkInWebview! - vc.isDisplayContent = displayContent! - vc.dictData = dict - vc.textViewText = message! - vc.responseStatus = self.responseStatus - self.navigationController?.pushViewController(vc, animated: true) - } - } else { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "GenerateURLVC") as? GenerateURLVC { - vc.isTrackContent = TrackContent! - vc.forNotification = forNotification! - vc.isCreateDeepLink = CreateDeepLink! - vc.isShareDeepLink = ShareDeepLink! - vc.isNavigateToContent = NavigateToContent! - vc.handleLinkInWebview = handleLinkInWebview! - vc.isDisplayContent = displayContent! - vc.dictData = dict - self.navigationController?.pushViewController(vc, animated: true) - } - } - } - - @objc func submitAction(sender : UIButton) { - - self.view.endEditing(true) - CommonMethod.sharedInstance.branchUniversalObject = BranchUniversalObject(canonicalIdentifier: txtFldCanonicalIdentifier.text!) - CommonMethod.sharedInstance.branchUniversalObject.title = txtFldContentTitle.text! - CommonMethod.sharedInstance.branchUniversalObject.contentDescription = txtFldDescription.text! - CommonMethod.sharedInstance.branchUniversalObject.imageUrl = txtFldImageUrl.text! - let linkProperties = BranchLinkProperties() - - - var dict = [String:Any]() - dict["$canonicalIdentifier"] = txtFldCanonicalIdentifier.text! - dict["title"] = txtFldContentTitle.text! - dict["description"] = txtFldDescription.text! - dict["imgurl"] = txtFldImageUrl.text! - - CommonMethod.sharedInstance.branchUniversalObject.locallyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.publiclyIndex = true - if CommonMethod.sharedInstance.contentMetaData != nil { - CommonMethod.sharedInstance.branchUniversalObject.contentMetadata = CommonMethod.sharedInstance.contentMetaData! - } - print("universalObject:", CommonMethod.sharedInstance.branchUniversalObject) - NSLog("CommonMethod.sharedInstance.branchUniversalObject:",CommonMethod.sharedInstance.branchUniversalObject) - - if self.screenMode == ScreenMode.trackContent { - let selectedEvent: BranchStandardEvent = BranchStandardEvent(rawValue: txtFldValue) - BranchEvent.standardEvent(selectedEvent, withContentItem: CommonMethod.sharedInstance.branchUniversalObject).logEvent {[weak self] isLogged, loggingErr in - if isLogged { - self?.responseStatus = "Success" - NSLog("BranchEvent Logged") - Utils.shared.setLogFile("TrackContent") - - DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { - //AJAY - let alertMessage = self?.getAPIDetailFromLogFile(fileName: "TrackContent.log") - - self?.handleOkBtnAction(dict: dict, alertMessage: alertMessage ?? "") - } - }else{ - NSLog("BranchEvent failed to log \(loggingErr?.localizedDescription ?? "NA")") - } - } - - } - else { - CommonMethod.sharedInstance.branchUniversalObject.listOnSpotlight(with: linkProperties) { (url, error) in - if (error == nil) { - NSLog("Successfully indexed on spotlight \(url)") - } - } - let alert = UIAlertController(title: "Alert", message: "BranchUniversalObject reference created", preferredStyle: .alert) - alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in - UserDefaults.standard.set("buo", forKey: "isStatus") - UserDefaults.standard.set(true, forKey: "isCreatedBUO") - self.handleOkBtnAction(dict: dict, alertMessage: "") - })) - self.present(alert, animated: true, completion: nil) - } - } - - private func loadTextWithFileName(_ fileName: String) -> String? { - if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { - let fileURL = dir.appendingPathComponent(fileName) - guard let text = try? String(contentsOf: fileURL, encoding: .utf8) else { - return nil - } - return text - } - return nil - } - - fileprivate func getAPIDetailFromLogFile(fileName: String) -> String{ - var alertMessage = "LogFilePath : \(self.getLogFilepath(fileName)!) \n\n" - alertMessage = alertMessage + "\n\n" - if let fileContent = self.loadTextWithFileName(fileName), !fileContent.isEmpty { - - if let startlocation = fileContent.range(of: "BranchSDK API LOG START OF FILE"),let endlocation = fileContent.range(of: "BranchSDK API LOG END OF FILE"){ - let apiResponse = fileContent[startlocation.lowerBound.. String? { - let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first - let fileURL = dir?.appendingPathComponent(fileName) - let fileURLStr = fileURL?.path - return fileURLStr - } -} - -extension CreateObjectReferenceObject { - func uiSetUp() { - - let addMetaDataBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-90, y: txtFldImageUrl.frame.maxY+30, width: 180, height: 55)) - addMetaDataBtn.setTitle("Add Metadata", for: .normal) - addMetaDataBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - addMetaDataBtn.layer.cornerRadius = 8 - addMetaDataBtn.setTitleColor(UIColor.white, for: .normal) - addMetaDataBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - addMetaDataBtn.addTarget(self, action: #selector(addMetaDataAction), for: .touchUpInside) - scrollViewMain.addSubview(addMetaDataBtn) - - let submitBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-60, y: addMetaDataBtn.frame.maxY+30, width: 120, height: 55)) - submitBtn.setTitle("Submit", for: .normal) - submitBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - submitBtn.layer.cornerRadius = 8 - submitBtn.setTitleColor(UIColor.white, for: .normal) - submitBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - submitBtn.addTarget(self, action: #selector(self.submitAction), for: .touchUpInside) - scrollViewMain.addSubview(submitBtn) - - - txtFldContentTitle.setLeftPaddingPoints(10) - txtFldDescription.setLeftPaddingPoints(10) - txtFldImageUrl.setLeftPaddingPoints(10) - txtFldCanonicalIdentifier.setLeftPaddingPoints(10) - txtFldCanonicalIdentifier.attributedPlaceholder = NSAttributedString( - string: "Canonical Identifier", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - - txtFldContentTitle.attributedPlaceholder = NSAttributedString( - string: "Content Title", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - - txtFldDescription.attributedPlaceholder = NSAttributedString( - string: "Content Description", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldImageUrl.attributedPlaceholder = NSAttributedString( - string: "Image URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/DispalyVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/DispalyVC.swift deleted file mode 100644 index b98f2ccab..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/DispalyVC.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// DispalyVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/26/22. -// - -import UIKit -import BranchSDK - -class DispalyVC: ParentViewController { - - @IBOutlet weak var pageTitle: UILabel! - - @IBOutlet weak var textViewDescription: UITextView! - - var textDescription = "" - var linkURL = "" - var appData : Dictionary = Dictionary() - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - - debugPrint("textDescription", textDescription) - - if appData["nav_to"] is String { - self.pageTitle.text = "Navigate To Content" - let content = String(format:"\nReferring link: %@ \n\nSession Details:\n %@", linkURL, appData.jsonStringRepresentation!) - self.textViewDescription.text = content - } else if appData["display_Cont"] is String { - self.pageTitle.text = "Display Content" - let content = String(format:"\nReferring link: %@ \n\nSession Details:\n %@", linkURL, appData.jsonStringRepresentation!) - self.textViewDescription.text = content - } - else{ - self.pageTitle.text = "Read Deep Linking" - self.textViewDescription.text = String(format:"%@", textDescription) - } - - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if appData["nav_to"] is String { - Utils.shared.setLogFile("NavigateContentDetail") - } else if appData["display_Cont"] is String { - Utils.shared.setLogFile("DisplayContentDetail") - } else { - Utils.shared.setLogFile("ReadDeepLinkingDetail") - } - } - - - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/GenerateURLVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/GenerateURLVC.swift deleted file mode 100644 index a1db4f8f6..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/GenerateURLVC.swift +++ /dev/null @@ -1,257 +0,0 @@ -// -// GenerateURLVC.swift -// DeepLinkDemo -// Created by Rakesh kumar on 4/19/22. - -import UIKit -import BranchSDK -class GenerateURLVC: ParentViewController { - @IBOutlet weak var txtFldCChannel: UITextField! - @IBOutlet weak var txtFldFeature: UITextField! - @IBOutlet weak var txtFldChampaignName: UITextField! - @IBOutlet weak var txtFldStage: UITextField! - @IBOutlet weak var txtFldDeskTopUrl: UITextField! - @IBOutlet weak var txtFldAndroidUrl: UITextField! - @IBOutlet weak var txtFldiOSTopUrl: UITextField! - @IBOutlet weak var txtFldAdditionalData: UITextField! - @IBOutlet weak var scrollViewMain: UIScrollView! - - var responseStatus = "" - var screenMode = 0 - - var dictData = [String:Any]() - - var isShareDeepLink = false - - var isDisplayContent = false - - var isNavigateToContent = false - - var isTrackContent = false - - var handleLinkInWebview = false - - var isCreateDeepLink = false - - var forNotification = false - - override func viewDidLoad() { - super.viewDidLoad() - uiSetUp() - - NSLog("dictData", dictData) - super.reachabilityCheck() - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollViewMain.contentSize.height = scrollViewMain.subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? scrollViewMain.contentSize.height - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("CreateDeeplink") - } - - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - func fireLocalNotification(linkurl: String){ - let dict = [ - "aps": [ - "alert":[ - "title":"Hi", - "body":"Hi, How Are You Dear" - ] - ], - "mutable-content" : false, - "branch": "\(linkurl)" - ] as [String : Any] - let notification = UILocalNotification() - notification.fireDate = Date(timeIntervalSinceNow: 1) - notification.alertBody = "Notification for handling deeplink" - notification.alertAction = "TestBed App" - notification.soundName = UILocalNotificationDefaultSoundName - notification.userInfo = dict - UIApplication.shared.scheduleLocalNotification(notification) - // sleep(2) - // self.navigationController?.popToRootViewController(animated: true) - } - - fileprivate func processShortURLGenerated(_ url: String?) { - NSLog("Check out my ShortUrl!! \(url ?? "")") - Utils.shared.setLogFile("CreateDeeplink") - let alertMessage = self.getAPIDetailFromLogFile("CreateDeeplink.log") - DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { - UserDefaults.standard.set("createdeeplinking", forKey: "isStatus") - UserDefaults.standard.set(true, forKey: "isCreatedDeepLink") - UserDefaults.standard.set("\(url ?? "")", forKey: "link") - if self.forNotification == true { - self.fireLocalNotification(linkurl: "\(url ?? "")") - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, forNotification: true) - }else if self.isShareDeepLink == true { - let bsl = BranchShareLink(universalObject: CommonMethod.sharedInstance.branchUniversalObject, linkProperties: CommonMethod.sharedInstance.linkProperties) - if #available(iOS 13.0, *) { - let metaData: LPLinkMetadata = LPLinkMetadata() - let iconImage = UIImage(named: "qentelli_logo") - metaData.iconProvider = NSItemProvider(object: iconImage!) - metaData.title = "Share Deeplink from the app" - metaData.url = URL(string: "\(url ?? "")") - bsl.lpMetaData = metaData - } - bsl.presentActivityViewController(from: self, anchor: nil) - } else if self.isTrackContent == true { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, TrackContentWeb: true) - } else if self.isNavigateToContent == true { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, NavigateToContent: true) - } else if self.isDisplayContent == true { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, displayContent: true) - } else if self.handleLinkInWebview == true { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, handleLinkInWebview: true) - } else if self.isCreateDeepLink == true{ - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, CreateDeepLink: true) - } else { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage) - } - } - } - - func launchTextViewController(url: String? = "",message: String? = "", ShareDeepLink: Bool? = false, displayContent: Bool? = false, NavigateToContent: Bool? = false, TrackContent: Bool? = false, TrackContentWeb: Bool? = false, handleLinkInWebview: Bool? = false, CreateDeepLink: Bool? = false, forNotification: Bool? = false) { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController { - vc.isTrackContent = TrackContent! - vc.forNotification = forNotification! - vc.isCreateDeepLink = CreateDeepLink! - vc.isShareDeepLink = ShareDeepLink! - vc.isNavigateToContent = NavigateToContent! - vc.handleLinkInWebview = handleLinkInWebview! - vc.isDisplayContent = displayContent! - vc.isTrackContenttoWeb = TrackContentWeb! - vc.textViewText = message ?? "" - vc.responseStatus = self.responseStatus - vc.url = url ?? "" - self.navigationController?.pushViewController(vc, animated: true) - } - } - - private func loadTextWithFileName(_ fileName: String) -> String? { - if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { - let fileURL = dir.appendingPathComponent(fileName) - guard let text = try? String(contentsOf: fileURL, encoding: .utf8) else { - return nil - } - return text - } - return nil - } - - fileprivate func getAPIDetailFromLogFile(_ fileName: String) -> String{ - var alertMessage = "LogFilePath : \(self.getLogFilepath(fileName)!) \n\n" - alertMessage = alertMessage + "\n\n" - if let fileContent = self.loadTextWithFileName(fileName), !fileContent.isEmpty { - let startlocation = fileContent.range(of: "BranchSDK API LOG START OF FILE") - let endlocation = fileContent.range(of: "BranchSDK API LOG END OF FILE") - if ((startlocation?.lowerBound != startlocation?.upperBound) && (endlocation?.lowerBound != endlocation?.upperBound)){ - let apiResponse = fileContent[startlocation!.lowerBound.. String? { - let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first - let fileURL = dir?.appendingPathComponent(fileName) - let fileURLStr = fileURL?.path - return fileURLStr - } - - @IBAction func submitAction(sender : UIButton) { - self.view.endEditing(true) - let linkProperties = BranchLinkProperties() - linkProperties.feature = txtFldFeature.text - linkProperties.channel = txtFldCChannel.text - linkProperties.campaign = txtFldChampaignName.text - linkProperties.stage = txtFldStage.text - linkProperties.addControlParam("$desktop_url", withValue: txtFldDeskTopUrl.text) - linkProperties.addControlParam("$ios_url", withValue: txtFldiOSTopUrl.text) - linkProperties.addControlParam("$android_url", withValue: txtFldAndroidUrl.text) - linkProperties.addControlParam("custom", withValue: txtFldAdditionalData.text) - if isNavigateToContent == true { - linkProperties.addControlParam("nav_to", withValue: "landing_page") - } else if isDisplayContent == true { - linkProperties.addControlParam("display_Cont", withValue: "landing_page") - } - - - CommonMethod.sharedInstance.branchUniversalObject.getShortUrl(with: linkProperties, andCallback: {[weak self] url, error in - - if error == nil { - self?.responseStatus = "Success" - self?.processShortURLGenerated(url) - } else { - self?.responseStatus = "Failure" - } - }) - - - } - -} - -extension GenerateURLVC { - func uiSetUp() { - let submitBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-60, y: txtFldAdditionalData.frame.maxY+15, width: 120, height: 55)) - submitBtn.setTitle("Submit", for: .normal) - submitBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - submitBtn.layer.cornerRadius = 8 - submitBtn.setTitleColor(UIColor.white, for: .normal) - submitBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - submitBtn.addTarget(self, action: #selector(self.submitAction), for: .touchUpInside) - scrollViewMain.addSubview(submitBtn) - - txtFldCChannel.setLeftPaddingPoints(10) - txtFldFeature.setLeftPaddingPoints(10) - txtFldChampaignName.setLeftPaddingPoints(10) - txtFldStage.setLeftPaddingPoints(10) - txtFldDeskTopUrl.setLeftPaddingPoints(10) - txtFldAdditionalData.setLeftPaddingPoints(10) - txtFldAndroidUrl.setLeftPaddingPoints(10) - txtFldiOSTopUrl.setLeftPaddingPoints(10) - - txtFldCChannel.attributedPlaceholder = NSAttributedString( - string: "Channel name like Facebook", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldFeature.attributedPlaceholder = NSAttributedString( - string: "Feature eg: Sharing", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldChampaignName.attributedPlaceholder = NSAttributedString( - string: "Campaign name", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldStage.attributedPlaceholder = NSAttributedString( - string: "Stage", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldDeskTopUrl.attributedPlaceholder = NSAttributedString( - string: "Desktop URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldAndroidUrl.attributedPlaceholder = NSAttributedString( - string: "Android URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldiOSTopUrl.attributedPlaceholder = NSAttributedString( - string: "iOS URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldAdditionalData.attributedPlaceholder = NSAttributedString( - string: "Additional Data", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/HomeViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/HomeViewController.swift deleted file mode 100644 index b4880dce9..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/HomeViewController.swift +++ /dev/null @@ -1,452 +0,0 @@ -// ViewController.swift -// DeepLinkDemo -// Created by Rakesh kumar on 4/15/22 - -import UIKit -import BranchSDK -class HomeViewController: UITableViewController { - private var reachability:Reachability? - - @IBOutlet weak var btnCreatBUO: UIButton! - @IBOutlet weak var btnTrackingEnabled: UIButton! - @IBOutlet weak var btnCreateDeepLinking: UIButton! - @IBOutlet weak var btnShareLink: UIButton! - @IBOutlet weak var btnSendNotification: UIButton! - @IBOutlet weak var btnTrackUser: UIButton! - @IBOutlet weak var btnLoadWebView: UIButton! - @IBOutlet weak var btReadDeeplink: UIButton! - @IBOutlet weak var btnTrackContent: UIButton! - @IBOutlet weak var btnNavigateToContent: UIButton! - @IBOutlet weak var btnDisplayContent: UIButton! - @IBOutlet weak var btnReadLog: UIButton! - @IBOutlet weak var btnSetDMAParams: UIButton! - @IBOutlet weak var btnSendV2Event: UIButton! - @IBOutlet weak var btnSetAttributionLevel: UIButton! - - @IBOutlet weak var switchControl: UISwitch! - - @IBOutlet weak var labelStatus: UILabel! - - let branchObj:Branch! = nil - var logData: String! = "" - var branchSDKInitialized = false; - - override func viewDidLoad() { - super.viewDidLoad() - - btnTrackingEnabled.layer.cornerRadius = 8.0 - btnCreatBUO.layer.cornerRadius = 8.0 - btnCreateDeepLinking.layer.cornerRadius = 8.0 - btnShareLink.layer.cornerRadius = 8.0 - btnShareLink.layer.cornerRadius = 8.0 - btnTrackUser.layer.cornerRadius = 8.0 - btnSendNotification.layer.cornerRadius = 8.0 - btReadDeeplink.layer.cornerRadius = 8.0 - btnTrackContent.layer.cornerRadius = 8.0 - btnNavigateToContent.layer.cornerRadius = 8.0 - btnReadLog.layer.cornerRadius = 8.0 - btnLoadWebView.layer.cornerRadius = 8.0 - btnSetDMAParams.layer.cornerRadius = 8.0 - btnSendV2Event.layer.cornerRadius = 8.0 - btnSetAttributionLevel.layer.cornerRadius = 8.0 - - NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil) - - reachabilityCheck(textValue:"") - - if Branch.trackingDisabled(){ - switchControl.isOn = false - }else{ - switchControl.isOn = true - } - - btnReadLog.isHidden = true - - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("Homepage") - } - - func reachabilityCheck(textValue:String?) { - CommonMethod.sharedInstance.contentMetaData = nil - reachability = Reachability()! - reachability!.whenReachable = { reachability in - Branch.setBranchKey("key_test_om2EWe1WBeBYmpz9Z1mdpopouDmoN72T") - DispatchQueue.main.async { - if textValue == "displayContent" { - self.initBranch() - self.launchBUOVC(mode: 8) - } else if textValue == "navigatetoContent" { - self.initBranch() - self.launchBUOVC(mode: 3) - } else if textValue == "sendNotification" { - self.initBranch() - self.launchBUOVC(mode: 6) - } else if textValue == "loadUrlInWeb" { - self.initBranch() - self.launchBUOVC(mode: 4) - } else if textValue == "createDeep" { - self.initBranch() - self.launchBUOVC(mode: 5) - } else if textValue == "shareDeeplinking" { - self.initBranch() - self.launchBUOVC(mode: 2) - } else if textValue == "readDeeplinking" { - self.initBranch() - self.launchBUOVC(mode: 1) - } else if textValue == "trackContent" { - self.initBranch() - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "TrackContentVC") as? TrackContentVC { - self.navigationController?.pushViewController(vc, animated: true) - } - } else if textValue == "trackUser" { - self.initBranch() - Branch.getInstance().setIdentity("qentelli_test_user") { params, error in - - if let referringParams = params as? [String :AnyObject] { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController { - vc.isTrackUser = true - vc.textViewText = "Result \(referringParams)" - vc.responseStatus = "Success" - self.navigationController?.pushViewController(vc, animated: true) - } - }else{ - NSLog("track user error--> \(error!.localizedDescription)") - } - } - } else if textValue == "swichAction" { - - } else if textValue == "createObject" { - self.initBranch() - self.launchBUOVC(mode: 0) - } else if textValue == "readSystemLog" { - self.initBranch() - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "LogFileListViewController") as? LogFileListViewController { - self.navigationController?.pushViewController(vc, animated: true) - } - } else if textValue == "setDMAParams" { - self.setDMAParamsWrapper() - } else if textValue == "sendV2Event" { - self.sendV2EventWrapper() - } else if textValue == "setAttributionLevel" { - self.setAttributionLevelWrapper() - } - } - } - - reachability?.whenUnreachable = { reachability in - DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) { - self.networkError() - } - } - do { - try reachability?.startNotifier() - } catch { - NSLog("Unable to start notifier") - } - } - func launchBUOVC(mode: Int) { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "CreateObjectReferenceObject") as? CreateObjectReferenceObject { - vc.screenMode = mode - self.navigationController?.pushViewController(vc, animated: true) - } - } - - func networkError() { - CommonAlert.shared.showActionAlertView(title: "Failure", message: "Your internet/network connection appears to be offline. Please check your internet/network connection.", actions: [], preferredStyle: .alert, viewController: self) - } - - func enableBranchLogging(callback: @escaping BranchLogCallback){ - Branch.enableLogging(at: .verbose, withCallback: callback) - } - - func initBranch(){ - if branchSDKInitialized { - return - } - self.enableBranchLogging(){(message:String, loglevel:BranchLogLevel, error:Error?)->() in - if (message.contains("BranchSDK")){ - self.logData = self.logData + message + "\n" - Utils.shared.printLogMessage(message + "\n") - } - } - AppDelegate.shared.getBranchData(AppDelegate.shared.launchOption) - branchSDKInitialized = true - } - - func logEvent(){ - let event = BranchEvent.standardEvent(.purchase) - // Add a populated `BranchUniversalObject` to the event - let buo = BranchUniversalObject(canonicalIdentifier: "item/12345") - event.contentItems = [ buo ] - // Add additional event data - event.alias = "my custom alias" - event.transactionID = "12344555" - event.eventDescription = "event_description" - event.searchQuery = "item 123" - event.customData = [ - "Custom_Event_Property_Key1": "Custom_Event_Property_val1", - "Custom_Event_Property_Key2": "Custom_Event_Property_val2" - ] - // Log the event - event.logEvent() - } - - func setAttributionLevelWrapper() { - self.logData = "Error: Missing testData.\n" - - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController - vc?.isSetAttributionLevel = true - - do { - let argCount = ProcessInfo.processInfo.arguments.count - if argCount >= 2 { - - for i in (1 ..< argCount) { - let data = ProcessInfo.processInfo.arguments[i].data(using: .utf8)! - - if let jsonObject = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [String:AnyObject] - { - if jsonObject["consumer_protection_attribution_level"] != nil { - let attribution_level = jsonObject["consumer_protection_attribution_level"] as! String - self.logData = "" - self.enableBranchLogging(){(msg:String,msg2:BranchLogLevel,msg3:Error?)->() in - if (msg.contains("BranchSDK")){ - self.logData = self.logData + msg + "\n" - } - vc?.updateText(msg: self.logData) - } - if(self.branchSDKInitialized){ - Branch.getInstance().resetUserSession() - } - - switch attribution_level { - case "0": - Branch.getInstance().setConsumerProtectionAttributionLevel(.full) - case "1": - Branch.getInstance().setConsumerProtectionAttributionLevel(.reduced) - case "2": - Branch.getInstance().setConsumerProtectionAttributionLevel(.minimal) - case "3": - Branch.getInstance().setConsumerProtectionAttributionLevel(.none) - default: - Branch.getInstance().setConsumerProtectionAttributionLevel(.full) - } - - AppDelegate.shared.getBranchData(AppDelegate.shared.launchOption) - self.branchSDKInitialized = true - } else { - self.logData = "Missing params from JSON Object: \n" + jsonObject.description - } - } else { - self.logData = "Bad JSON : \n" + ProcessInfo.processInfo.arguments[i] - } - } - - - } - } catch let error as NSError { - print(error) - self.logData += error.localizedDescription - } - vc?.updateText(msg: self.logData) - self.navigationController?.pushViewController(vc!, animated: true) - } - - func setDMAParamsWrapper() { - self.logData = "Error: Missing testData.\n" - - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController - vc?.isSetDMAParams = true - - do { - let argCount = ProcessInfo.processInfo.arguments.count - if argCount >= 2 { - - for i in (1 ..< argCount) { - let data = ProcessInfo.processInfo.arguments[i].data(using: .utf8)! - - if let jsonObject = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [String:AnyObject] - { - if ((jsonObject["dma_eea"] != nil) && (jsonObject["dma_eea"] != nil) && (jsonObject["dma_eea"] != nil)) { - let dma_eea = jsonObject["dma_eea"] as! Bool - let dma_ad_personalization = jsonObject["dma_ad_personalization"] as! Bool - let dma_ad_user_data = jsonObject["dma_ad_user_data"] as! Bool - self.logData = "" - self.enableBranchLogging(){(msg:String,msg2:BranchLogLevel,msg3:Error?)->() in - if (msg.contains("BranchSDK")){ - self.logData = self.logData + msg + "\n" - } - vc?.updateText(msg: self.logData) - } - if(self.branchSDKInitialized){ - Branch.getInstance().resetUserSession() - } - - Branch.setDMAParamsForEEA(dma_eea, adPersonalizationConsent: dma_ad_personalization, adUserDataUsageConsent: dma_ad_user_data) - AppDelegate.shared.getBranchData(AppDelegate.shared.launchOption) - self.branchSDKInitialized = true - } else { - self.logData = "Missing params from JSON Object: \n" + jsonObject.description - } - } else { - self.logData = "Bad JSON : \n" + ProcessInfo.processInfo.arguments[i] - } - } - - - } - } catch let error as NSError { - print(error) - self.logData += error.localizedDescription - } - vc?.updateText(msg: self.logData) - self.navigationController?.pushViewController(vc!, animated: true) - } - - func sendV2EventWrapper(){ - self.logData = "" - - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController - - self.enableBranchLogging(){(msg:String,msg2:BranchLogLevel,msg3:Error?)->() in - if (msg.contains("BranchSDK")){ - self.logData = self.logData + msg + "\n" - vc?.updateText(msg: self.logData) - } - } - self.logEvent() - self.navigationController?.pushViewController(vc!, animated: true) - vc?.isSendV2Event = true - vc?.updateText(msg: self.logData) - self.branchSDKInitialized = true - } - - @IBAction func sendNotificationAction(_ sender: Any) { - reachabilityCheck(textValue: "sendNotification") - } - - @objc func methodOfReceivedNotification(notification: Notification) { - - Branch.getInstance().initSession( launchOptions: AppDelegate.shared.launchOption, - andRegisterDeepLinkHandlerUsingBranchUniversalObject: { [self] universalObject, linkProperties, error in - if universalObject != nil { - NSLog("UniversalObject", universalObject ?? "NA") - NSLog("LinkProperties", linkProperties ?? "NA") - NSLog("UniversalObject Metadata:", universalObject?.contentMetadata.customMetadata ?? "NA") - if let isRead = UserDefaults.standard.value(forKey: "isRead") as? Bool, isRead == true { - if let dictData = universalObject?.contentMetadata.customMetadata as? NSDictionary { - let referedlink = dictData.value(forKey: "~referring_link") as? String ?? "" - // let linkurl = UserDefaults.standard.value(forKey: "link") as? String ?? "" - NSLog("referedlink:", referedlink) - UserDefaults.standard.set(referedlink, forKey: "link") - NSLog("Deep linked with object: %@.", universalObject ?? BranchUniversalObject()); - let deeplinkText = universalObject?.contentMetadata.customMetadata.value(forKey: "deeplink_text") - let textDetail = "Successfully Deeplinked:\n\n%@\nSession Details:\n\n%@, \(String(describing: deeplinkText)) \(String(describing: Branch.getInstance().getLatestReferringParams()?.description))" - UserDefaults.standard.setValue(textDetail, forKey: "textDetail") - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "DispalyVC") as? DispalyVC { - vc.textDescription = textDetail - self.navigationController?.pushViewController(vc, animated: true) - } - } - } else { - NSLog("No Deep linked object"); - } - } - }) - } - - @IBAction func displayContentBtnAction(_ sender: Any) { - reachabilityCheck(textValue: "displayContent") - } - - @IBAction func navigatetoContentBtnAction(_ sender: Any) { - reachabilityCheck(textValue: "navigatetoContent") - } - - @IBAction func loadUrlInWebViewAction(_ sender: Any) { - reachabilityCheck(textValue: "loadUrlInWeb") - } - - @IBAction func createDeeplinking(_ sender: Any) { - reachabilityCheck(textValue: "createDeep") - } - - @IBAction func shareDeeplinking(_ sender: Any) { - reachabilityCheck(textValue: "shareDeeplinking") - } - - @IBAction func readDeeplinking(_ sender: Any) { - reachabilityCheck(textValue: "readDeeplinking") - } - - @IBAction func trackContentAction(_ sender: Any) { - reachabilityCheck(textValue: "trackContent") - } - - @IBAction func trackUserAction(_ sender: Any) { - reachabilityCheck(textValue: "trackUser") - } - - @IBAction func swichAction(_ sender: UISwitch) { - reachabilityCheck(textValue: "swichAction") - if sender.isOn == true { - NSLog("is OFF", "ison") - btnTrackingEnabled.setTitle("Tracking Enabled", for: .normal) - btnTrackingEnabled.titleLabel?.font = UIFont.boldSystemFont(ofSize: 36) - Branch.setTrackingDisabled(true) - - } else { - NSLog("is ON", "isOFF") - Branch.setTrackingDisabled(false) - btnTrackingEnabled.setTitle("Tracking Disabled", for: .normal) - btnTrackingEnabled.titleLabel?.font = UIFont(name: "Helvetica", size:36) - } - } - - @IBAction func createObject(_ sender: Any) { - reachabilityCheck(textValue: "createObject") - - } - - @IBAction func readSystemLog(){ - reachabilityCheck(textValue: "readSystemLog") - - - } - - @IBAction func setDMAParams(){ - reachabilityCheck(textValue: "setDMAParams") - } - - @IBAction func sendV2Event(){ - reachabilityCheck(textValue: "sendV2Event") - } - - @IBAction func setAttributionLevel(){ - reachabilityCheck(textValue: "setAttributionLevel") - } -} - -extension UITextField { - func setLeftPaddingPoints(_ amount:CGFloat){ - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height)) - self.leftView = paddingView - self.leftViewMode = .always - } - func setRightPaddingPoints(_ amount:CGFloat) { - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height)) - self.rightView = paddingView - self.rightViewMode = .always - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/LogFileListViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/LogFileListViewController.swift deleted file mode 100644 index 844af618d..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/LogFileListViewController.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// LogFileListViewController.swift -// DeepLinkDemo -// -// Created by Apple on 26/05/22. -// - -import UIKit - -class LogFileListViewController: UIViewController { - - var fileNames = [String]() - - @IBOutlet weak var logFileListTblView: UITableView! - - override func viewDidLoad() { - super.viewDidLoad() - - fileNames = getAllLogFileNames() - } - - func getAllLogFileNames() -> [String]{ - let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! - - do { - var fileName = [String]() - let fileURLs = try FileManager.default.contentsOfDirectory(at: documentsUrl, - includingPropertiesForKeys: nil, - options: .skipsHiddenFiles) - for fileURL in fileURLs { - fileName.append(fileURL.lastPathComponent) - } - - return fileName - } catch { - NSLog("Failed to delete/read the file in document directory %@", error.localizedDescription) - } - return [""] - } - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - -} - - -extension LogFileListViewController: UITableViewDataSource, UITableViewDelegate{ - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return fileNames.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCell(withIdentifier: "LogTableViewCell", for: indexPath) as? LogTableViewCell{ - cell.nameLbl.text = fileNames[indexPath.row] - return cell - } - return UITableViewCell() - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 60 - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let selectedFile = fileNames[indexPath.row] - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "ReadLogViewController") as? ReadLogViewController { - vc.selectedFileName = selectedFile - self.navigationController?.pushViewController(vc, animated: true) - } - - } -} - - -class LogTableViewCell: UITableViewCell{ - - @IBOutlet weak var nameLbl: UILabel! -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/MetaDataTableViewCell.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/MetaDataTableViewCell.swift deleted file mode 100644 index bc5170c63..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/MetaDataTableViewCell.swift +++ /dev/null @@ -1,224 +0,0 @@ -// -// MetaDataTableViewCell.swift -// DeepLinkDemo -// -// Created by Apple on 13/05/22. -// - -import UIKit -import BranchSDK - -protocol PickerViewDelegate{ - func removePickerView() -} -class MetaDataTableViewCell: UITableViewCell { - - var pickerDelegate: PickerViewDelegate! - - private let contentSchemaNames = ["COMMERCE_AUCTION", "COMMERCE_BUSINESS", "COMMERCE_OTHER", - "COMMERCE_PRODUCT", "COMMERCE_RESTAURANT", "COMMERCE_SERVICE", - "COMMERCE_TRAVEL_FLIGHT", "COMMERCE_TRAVEL_HOTEL", "COMMERCE_TRAVEL_OTHER", - "GAME_STATE", "MEDIA_IMAGE", "MEDIA_MIXED", "MEDIA_MUSIC", "MEDIA_OTHER", - "MEDIA_VIDEO", "OTHER", "TEXT_ARTICLE", "TEXT_BLOG", "TEXT_OTHER", - "TEXT_RECIPE", "TEXT_REVIEW", "TEXT_SEARCH_RESULTS", "TEXT_STORY", - "TEXT_TECHNICAL_DOC"] - - private let productCategories = ["Animals & Pet Supplies", "Apparel & Accessories", "Arts & Entertainment", - "Baby & Toddler", "Business & Industrial", "Cameras & Optics", - "Electronics", "Food, Beverages & Tobacco", "Furniture", "Hardware", - "Health & Beauty", "Home & Garden", "Luggage & Bags", "Mature", - "Media", "Media", "Office Supplies", "Religious & Ceremonial", - "Software", "Sporting Goods", "Toys & Games", "Vehicles & Parts"] - - - private let productConditions = ["EXCELLENT", "NEW", "GOOD", "FAIR", "POOR", "USED", "REFURBISHED", "OTHER"] - - - private let currencyNames = ["USD", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", "BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BYR", "CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", "CRC", "CUC", "CUP", "CVE", "CZK", "DJF", "DKK", "DOP", "DZD", "EGP", "ERN", "ETB", "EUR", "FJD", "FKP", "GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD", "HKD", "HNL", "HRK", "HTG", "HUF", "IDR", "ILS", "INR", "IQD", "IRR", "ISK", "JMD", "JOD", "JPY", "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", "LAK", "LBP", "LKR", "LRD", "LSL", "LYD", "MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN", "NAD", "NGN", "NIO", "NOK", "NPR", "NZD", "OMR", "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG", "QAR", "RON", "RSD", "RUB", "RWF", "SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STD", "SYP", "SZL", "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS", "UAH", "UGX", "USN", "UYI", "UYU", "UZS", "VEF", "VND", "VUV", "WST", "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XFU", "XOF", "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX", "YER", "ZAR", "ZMW"] - - private var pickerView = UIPickerView() - - @IBOutlet weak var contentSchema: UITextField! - @IBOutlet weak var productName: UITextField! - @IBOutlet weak var productBrand: UITextField! - @IBOutlet weak var productVariant: UITextField! - @IBOutlet weak var productCategory: UITextField! - @IBOutlet weak var productCondition: UITextField! - @IBOutlet weak var street: UITextField! - @IBOutlet weak var city: UITextField! - @IBOutlet weak var region: UITextField! - @IBOutlet weak var country: UITextField! - @IBOutlet weak var postalCode: UITextField! - @IBOutlet weak var latitude: UITextField! - @IBOutlet weak var longitude: UITextField! - @IBOutlet weak var sku: UITextField! - @IBOutlet weak var rating: UITextField! - @IBOutlet weak var averageRating: UITextField! - @IBOutlet weak var maximumRating: UITextField! - @IBOutlet weak var ratingCount: UITextField! - @IBOutlet weak var imageCaption: UITextField! - @IBOutlet weak var quantity: UITextField! - @IBOutlet weak var price: UITextField! - @IBOutlet weak var currencyName: UITextField! - @IBOutlet weak var customMetadata: UITextField! - - @IBOutlet weak var submitBtn: UIButton! - - fileprivate func setAtrributePlaceHolder(targetField: UITextField, placeholderTxt: String){ - targetField.setLeftPaddingPoints(10) - targetField.attributedPlaceholder = NSAttributedString( - string: placeholderTxt, - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - - } - - fileprivate func prepareUI(){ - self.setAtrributePlaceHolder(targetField: self.productName, placeholderTxt: "Product Name") - self.setAtrributePlaceHolder(targetField: self.productBrand, placeholderTxt: "Product Brand") - self.setAtrributePlaceHolder(targetField: self.productVariant, placeholderTxt: "Product Variant") - self.setAtrributePlaceHolder(targetField: self.street, placeholderTxt: "Street") - self.setAtrributePlaceHolder(targetField: self.city, placeholderTxt: "City") - self.setAtrributePlaceHolder(targetField: self.region, placeholderTxt: "Region") - self.setAtrributePlaceHolder(targetField: self.country, placeholderTxt: "Country") - self.setAtrributePlaceHolder(targetField: self.postalCode, placeholderTxt: "Postal Code") - self.setAtrributePlaceHolder(targetField: self.latitude, placeholderTxt: "Latitude") - self.setAtrributePlaceHolder(targetField: self.longitude, placeholderTxt: "Longitude") - self.setAtrributePlaceHolder(targetField: self.sku, placeholderTxt: "SKU") - self.setAtrributePlaceHolder(targetField: self.rating, placeholderTxt: "Rating") - self.setAtrributePlaceHolder(targetField: self.averageRating, placeholderTxt: "Average Rating") - self.setAtrributePlaceHolder(targetField: self.maximumRating, placeholderTxt: "Maximum Rating") - self.setAtrributePlaceHolder(targetField: self.ratingCount, placeholderTxt: "Rating Count") - self.setAtrributePlaceHolder(targetField: self.imageCaption, placeholderTxt: "Image Caption") - self.setAtrributePlaceHolder(targetField: self.quantity, placeholderTxt: "Quantity") - self.setAtrributePlaceHolder(targetField: self.price, placeholderTxt: "Price") - self.setAtrributePlaceHolder(targetField: self.customMetadata, placeholderTxt: "Custom Metadata") - - } - - fileprivate func setupPickerViewDataSource() { - pickerView.dataSource = self - pickerView.delegate = self - - let toolBar = UIToolbar(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.size.width,height: 44.0)) - let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(tapDone)) - let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(tapCancel)) - toolBar.setItems([cancelButton, flexibleSpace, doneButton], animated: false) - - contentSchema.inputView = pickerView - contentSchema.inputAccessoryView = toolBar - contentSchema.text = contentSchemaNames.first - - currencyName.inputView = pickerView - currencyName.inputAccessoryView = toolBar - currencyName.text = currencyNames.first - - productCondition.inputView = pickerView - productCondition.inputAccessoryView = toolBar - productCondition.text = productConditions.first - - productCategory.inputView = pickerView - productCategory.inputAccessoryView = toolBar - productCategory.text = productCategories.first - - productCategory.setLeftPaddingPoints(10) - productCondition.setLeftPaddingPoints(10) - currencyName.setLeftPaddingPoints(10) - contentSchema.setLeftPaddingPoints(10) - - - - } - - override func awakeFromNib() { - super.awakeFromNib() - - prepareUI() - - setupPickerViewDataSource() - - self.selectionStyle = .none - } - - @objc func tapDone() { - if contentSchema.isFirstResponder{ - let selectedRow = pickerView.selectedRow(inComponent: 0) - if contentSchemaNames.indices.contains(selectedRow){ - contentSchema.text = contentSchemaNames[selectedRow] - } - contentSchema.resignFirstResponder() - } else if currencyName.isFirstResponder{ - let selectedRow = pickerView.selectedRow(inComponent: 0) - if currencyNames.indices.contains(selectedRow){ - currencyName.text = currencyNames[selectedRow] - } - currencyName.resignFirstResponder() - } else if productCondition.isFirstResponder{ - let selectedRow = pickerView.selectedRow(inComponent: 0) - if productConditions.indices.contains(selectedRow){ - productCondition.text = productConditions[selectedRow] - } - productCondition.resignFirstResponder() - } else if productCategory.isFirstResponder{ - let selectedRow = pickerView.selectedRow(inComponent: 0) - if productCategories.indices.contains(selectedRow){ - productCategory.text = productCategories[selectedRow] - } - productCategory.resignFirstResponder() - } - self.endEditing(true) - } - - @objc func tapCancel() { - self.endEditing(true) - } - - -} - - -extension MetaDataTableViewCell: UIPickerViewDataSource, UIPickerViewDelegate{ - - func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { - if contentSchema.isFirstResponder{ - return contentSchemaNames.count - } else if currencyName.isFirstResponder{ - return currencyNames.count - } else if productCondition.isFirstResponder{ - return productConditions.count - } else if productCategory.isFirstResponder{ - return productCategories.count - } - return 0 - } - - func numberOfComponents(in pickerView: UIPickerView) -> Int { - return 1 - } - - func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { - if contentSchema.isFirstResponder{ - return contentSchemaNames[row] - } else if currencyName.isFirstResponder{ - return currencyNames[row] - } else if productCondition.isFirstResponder{ - return productConditions[row] - } else if productCategory.isFirstResponder{ - return productCategories[row] - } - return nil - } - - func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { - if contentSchema.isFirstResponder{ - contentSchema.text = contentSchemaNames[row] - } else if currencyName.isFirstResponder{ - currencyName.text = currencyNames[row] - } else if productCondition.isFirstResponder{ - productCondition.text = productConditions[row] - } else if productCategory.isFirstResponder{ - productCategory.text = productCategories[row] - } - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/NavigateContentVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/NavigateContentVC.swift deleted file mode 100644 index 225b64e8c..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/NavigateContentVC.swift +++ /dev/null @@ -1,108 +0,0 @@ -// -// NavigateContentVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/19/22. -// - -import UIKit - -class NavigateContentVC: ParentViewController { - @IBOutlet weak var txtFldCChannel: UITextField! - @IBOutlet weak var txtFldFeature: UITextField! - @IBOutlet weak var txtFldChampaignName: UITextField! - @IBOutlet weak var txtFldStage: UITextField! - @IBOutlet weak var txtFldDeskTopUrl: UITextField! - @IBOutlet weak var txtFldAdditionalData: UITextField! - @IBOutlet weak var scrollViewMain: UIScrollView! - private var reachability:Reachability? - - override func viewDidLoad() { - super.viewDidLoad() - uiSetUp() - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("NavigateContent") - } - - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollViewMain.contentSize.height = scrollViewMain.subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? scrollViewMain.contentSize.height - } - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - @objc func submitAction(sender : UIButton) { - self.view.endEditing(true) - CommonMethod.sharedInstance.branchUniversalObject.publiclyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.locallyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.contentMetadata.customMetadata["key1"] = txtFldDeskTopUrl.text! - CommonMethod.sharedInstance.linkProperties.channel = txtFldCChannel.text! - CommonMethod.sharedInstance.linkProperties.feature = txtFldFeature.text! - CommonMethod.sharedInstance.linkProperties.campaign = txtFldChampaignName.text! - CommonMethod.sharedInstance.linkProperties.stage = txtFldStage.text! - CommonMethod.sharedInstance.linkProperties.addControlParam("$desktop_url", withValue: txtFldDeskTopUrl.text!) - CommonMethod.sharedInstance.linkProperties.addControlParam("custom_data", withValue: "yes") - CommonMethod.sharedInstance.branchUniversalObject.getShortUrl(with:CommonMethod.sharedInstance.linkProperties, andCallback: { (optUrl: String?, error: Error?) in - if error == nil, let url = optUrl { - NSLog("got my Branch link to share: %@", url) - Utils.shared.setLogFile("NavigateContent") - DispatchQueue.main.async { - UserDefaults.standard.set(true, forKey: "isCreatedDeepLink") - UserDefaults.standard.set(url, forKey: "link") - self.navigationController?.popToRootViewController(animated: true) - } - } - }) - } -} - -extension NavigateContentVC { - - func uiSetUp() { - let submitBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-60, y: txtFldAdditionalData.frame.maxY+30, width: 120, height: 55)) - submitBtn.setTitle("Submit", for: .normal) - submitBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - submitBtn.layer.cornerRadius = 8 - submitBtn.setTitleColor(UIColor.white, for: .normal) - submitBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - submitBtn.addTarget(self, action: #selector(self.submitAction), for: .touchUpInside) - scrollViewMain.addSubview(submitBtn) - txtFldCChannel.setLeftPaddingPoints(10) - txtFldFeature.setLeftPaddingPoints(10) - txtFldChampaignName.setLeftPaddingPoints(10) - txtFldStage.setLeftPaddingPoints(10) - txtFldDeskTopUrl.setLeftPaddingPoints(10) - txtFldAdditionalData.setLeftPaddingPoints(10) - txtFldCChannel.attributedPlaceholder = NSAttributedString( - string: "Channel name like Facebook", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldFeature.attributedPlaceholder = NSAttributedString( - string: "Feature eg: Sharing", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldChampaignName.attributedPlaceholder = NSAttributedString( - string: "Champaign name", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldStage.attributedPlaceholder = NSAttributedString( - string: "Stage", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldDeskTopUrl.attributedPlaceholder = NSAttributedString( - string: "Desktop URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldAdditionalData.attributedPlaceholder = NSAttributedString( - string: "Additional Data", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ParentViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ParentViewController.swift deleted file mode 100644 index 241dd72e9..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ParentViewController.swift +++ /dev/null @@ -1,39 +0,0 @@ -// ParentViewController.swift -// DeepLinkDemo -// Created by Apple on 17/05/22. - -import UIKit -class ParentViewController: UIViewController { - private var reachability:Reachability? - - override func viewDidLoad() { - super.viewDidLoad() - reachabilityCheck() - } - - override var preferredStatusBarStyle: UIStatusBarStyle { - return .lightContent - } - - - func reachabilityCheck() { - reachability = Reachability()! - reachability!.whenReachable = { reachability in - } - reachability?.whenUnreachable = { reachability in - DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { - self.networkError() - } - } - do { - try reachability?.startNotifier() - } catch { - NSLog("Unable to start notifier") - } - } - - func networkError() { - CommonAlert.shared.showActionAlertView(title: "Failure", message: "Your internet/network connection appears to be offline. Please check your internet/network connection.", actions: [], preferredStyle: .alert, viewController: self) - } - -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadDeeplinkingVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ReadDeeplinkingVC.swift deleted file mode 100644 index 6d72dfa49..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadDeeplinkingVC.swift +++ /dev/null @@ -1,108 +0,0 @@ -// -// ReadDeeplinkingVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/19/22. - -import UIKit -import Branch - -class ReadDeeplinkingVC: ParentViewController { - @IBOutlet weak var txtFldCChannel: UITextField! - @IBOutlet weak var txtFldFeature: UITextField! - @IBOutlet weak var txtFldChampaignName: UITextField! - @IBOutlet weak var txtFldStage: UITextField! - @IBOutlet weak var txtFldDeskTopUrl: UITextField! - @IBOutlet weak var txtFldAdditionalData: UITextField! - @IBOutlet weak var scrollViewMain: UIScrollView! - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - uiSetUp() - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("ReadDeeplinking") - } - - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollViewMain.contentSize.height = scrollViewMain.subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? scrollViewMain.contentSize.height - } - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - @objc func submitAction(sender : UIButton) { - self.view.endEditing(true) - - CommonMethod.sharedInstance.branchUniversalObject.publiclyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.locallyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.contentMetadata.customMetadata["key1"] = txtFldDeskTopUrl.text! - - CommonMethod.sharedInstance.linkProperties.channel = txtFldCChannel.text! - CommonMethod.sharedInstance.linkProperties.feature = txtFldFeature.text! - CommonMethod.sharedInstance.linkProperties.campaign = txtFldChampaignName.text! - CommonMethod.sharedInstance.linkProperties.stage = txtFldStage.text! - CommonMethod.sharedInstance.linkProperties.addControlParam("$desktop_url", withValue: txtFldDeskTopUrl.text!) - CommonMethod.sharedInstance.linkProperties.addControlParam("custom_data", withValue: "yes") - CommonMethod.sharedInstance.branchUniversalObject.getShortUrl(with:CommonMethod.sharedInstance.linkProperties, andCallback: { (optUrl: String?, error: Error?) in - if error == nil, let url = optUrl { - NSLog("got my Branch link to share: %@", url) - DispatchQueue.main.async { - UserDefaults.standard.set(true, forKey: "isCreatedDeepLink") - UserDefaults.standard.set(url, forKey: "link") - self.navigationController?.popToRootViewController(animated: true) - } - } - }) - } -} - -extension ReadDeeplinkingVC { - - func uiSetUp() { - let submitBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-60, y: txtFldAdditionalData.frame.maxY+30, width: 120, height: 55)) - submitBtn.setTitle("Submit", for: .normal) - submitBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - submitBtn.layer.cornerRadius = 8 - submitBtn.setTitleColor(UIColor.white, for: .normal) - submitBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - submitBtn.addTarget(self, action: #selector(self.submitAction), for: .touchUpInside) - scrollViewMain.addSubview(submitBtn) - txtFldCChannel.setLeftPaddingPoints(10) - txtFldFeature.setLeftPaddingPoints(10) - txtFldChampaignName.setLeftPaddingPoints(10) - txtFldStage.setLeftPaddingPoints(10) - txtFldDeskTopUrl.setLeftPaddingPoints(10) - txtFldAdditionalData.setLeftPaddingPoints(10) - txtFldCChannel.attributedPlaceholder = NSAttributedString( - string: "Channel name like Facebook", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldFeature.attributedPlaceholder = NSAttributedString( - string: "Feature eg: Sharing", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldChampaignName.attributedPlaceholder = NSAttributedString( - string: "Campaign name", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldStage.attributedPlaceholder = NSAttributedString( - string: "Stage", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldDeskTopUrl.attributedPlaceholder = NSAttributedString( - string: "Desktop URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldAdditionalData.attributedPlaceholder = NSAttributedString( - string: "Additional Data", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadLogViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ReadLogViewController.swift deleted file mode 100644 index d88749390..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadLogViewController.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// ReadLogViewController.swift -// DeepLinkDemo -// -// Created by Apple on 17/05/22. -// - -import UIKit - -class ReadLogViewController: ParentViewController { - - @IBOutlet weak var textViewDescription: UITextView! - - var selectedFileName = "" - - override func viewDidLoad() { - super.viewDidLoad() - - self.textViewDescription.text = loadTextWithFileName(selectedFileName) - reachabilityCheck() - } - - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - private func loadTextWithFileName(_ fileName: String) -> String? { - if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { - let fileURL = dir.appendingPathComponent(fileName) - guard let text = try? String(contentsOf: fileURL, encoding: .utf8) else { - return nil - } - return text - } - return nil - } - -} - - diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ReadVC.swift deleted file mode 100644 index 08fe32021..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadVC.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// ReadVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/28/22. -// - -import UIKit -import BranchSDK -class ReadVC: ParentViewController { - - @IBOutlet weak var btnback: UIButton! - @IBOutlet weak var labelTxt: UILabel! - @IBOutlet weak var btnShare: UIButton! - var strTxt = "" - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - labelTxt.text = "Success\nUrl is generated.\nHere is the Short URL\(strTxt)" - btnShare.layer.cornerRadius = 8.0 - let tap = UITapGestureRecognizer(target: self, action: #selector(self.onClicLabel(sender:))) - labelTxt.isUserInteractionEnabled = true - labelTxt.addGestureRecognizer(tap) - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - } - - - // And that's the function :) - @objc func onClicLabel(sender:UITapGestureRecognizer) { - - UserDefaults.standard.set(true, forKey: "isRead") - let anURL = URL(string: strTxt) - Branch.getInstance().handleDeepLink(anURL) - } - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - @IBAction func btnrReadDeeplink(_ sender: Any) { - UserDefaults.standard.set(true, forKey: "isRead") - let anURL = URL(string: strTxt) - Branch.getInstance().handleDeepLink(anURL) - } - -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ShareDynamicallyVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ShareDynamicallyVC.swift deleted file mode 100644 index cb71f1bed..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ShareDynamicallyVC.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// ShareDynamicallyVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/19/22. -// - -import UIKit -class ShareDynamicallyVC: ParentViewController { -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/TextViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/TextViewController.swift deleted file mode 100644 index b55b15c90..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/TextViewController.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// TextViewController.swift -// DeepLinkDemo -// -// Created by ajaykumar on 15/06/22. -// - -import Foundation -import UIKit -import CoreSpotlight; -import MobileCoreServices; - -class TextViewController: UIViewController { - - var isShareDeepLink = false - var isNavigateToContent = false - var isDisplayContent = false - var isTrackContent = false - var isTrackContenttoWeb = false - var handleLinkInWebview = false - var isCreateDeepLink = false - var forNotification = false - var isTrackUser = false - var isSetDMAParams = false - var isSendV2Event = false - var isSetAttributionLevel = false - - var url = "" - var responseStatus = "" - var dictData = [String:Any]() - var textViewText = "" - - @IBOutlet weak var statusLabel: UILabel! - - @IBOutlet weak var logDataTextView: UITextView! - - - override func viewDidLoad() { - super.viewDidLoad() - logDataTextView.text = textViewText - statusLabel.text = responseStatus - logDataTextView.isEditable = false - } - - @IBAction func BackButtonAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - @IBAction func nextButtonAction(_ sender: Any) { - if self.isTrackContent == true { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "GenerateURLVC") as? GenerateURLVC { - vc.isTrackContent = true - vc.forNotification = false - vc.isCreateDeepLink = false - vc.isShareDeepLink = false - vc.isNavigateToContent = false - vc.dictData = dictData - self.navigationController?.pushViewController(vc, animated: true) - } - } else if self.isTrackUser == true { - self.navigationController?.popToRootViewController(animated: true) - } else if self.forNotification == true { - self.navigationController?.popToRootViewController(animated: true) - } else if self.isTrackContenttoWeb || self.isCreateDeepLink { - launchWebView() - } else if self.isNavigateToContent || self.isDisplayContent || self.handleLinkInWebview { - launchReadVC() - } else if self.isSetDMAParams == true { - self.navigationController?.popToRootViewController(animated: true) - } else if self.isSendV2Event == true { - self.navigationController?.popToRootViewController(animated: true) - } else if self.isSetAttributionLevel == true { - self.navigationController?.popToRootViewController(animated: true) - } - else { - launchReadVC() - } - } - - func launchReadVC(){ - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "ReadVC") as? ReadVC { - vc.strTxt = url - self.navigationController?.pushViewController(vc, animated: true) - } - } - - func launchWebView(){ - //Fixed - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "WebViewVC") as? WebViewVC { - self.navigationController?.pushViewController(vc, animated: true) - } - } - - func updateText(msg: String) -> () { - DispatchQueue.main.async() { - self.logDataTextView?.text = msg - } - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/TrackContentVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/TrackContentVC.swift deleted file mode 100644 index 9efe7653d..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/TrackContentVC.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// TrackContentVC.swift -// DeepLinkDemo -// -// Created by Apple on 12/05/22. -// - -import UIKit -import BranchSDK - -class TrackContentVC: ParentViewController { - - @IBOutlet weak var txtFldOptions: UITextField! - - var pickerView = UIPickerView() - - var trackContenOptions = [String]() - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - - trackContenOptions = ["ADD_TO_CART", "ADD_TO_WISHLIST", "VIEW_CART", "INITIATE_PURCHASE", "ADD_PAYMENT_INFO", "PURCHASE", "SPEND_CREDITS", "SUBSCRIBE", "START_TRIAL", "CLICK_AD", "VIEW_AD", "SEARCH", "VIEW_ITEM", "VIEW_ITEMS", "RATE", "SHARE", "START_TRIAL", "CLICK_AD", "COMPLETE_REGISTRATION", "COMPLETE_TUTORIAL", "ACHIEVE_LEVEL", "UNLOCK_ACHIEVEMENT", "INVITE", "LOGIN", "RESERVE", "OPT_IN", "OPT_OUT"] - - pickerView.dataSource = self - pickerView.delegate = self - - txtFldOptions.inputView = pickerView - let toolBar = UIToolbar(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.size.width,height: 44.0)) - let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: target, action: #selector(tapDone)) - let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: target, action: #selector(tapCancel)) - toolBar.setItems([cancelButton, flexibleSpace, doneButton], animated: false) - txtFldOptions.inputAccessoryView = toolBar - - txtFldOptions.text = trackContenOptions.first - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - } - - - @objc func tapDone() { - let selectedRow = pickerView.selectedRow(inComponent: 0) - if trackContenOptions.indices.contains(selectedRow){ - txtFldOptions.text = trackContenOptions[selectedRow] - } - txtFldOptions.resignFirstResponder() - self.view.endEditing(true) - } - @objc func tapCancel() { - self.view.endEditing(true) - } - - @IBAction func backBtnAction(){ - self.navigationController?.popToRootViewController(animated: true) - } - - @IBAction func nextBtnAction(){ - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "CreateObjectReferenceObject") as? CreateObjectReferenceObject { - vc.screenMode = 7 - vc.txtFldValue = String(txtFldOptions.text ?? "") - self.navigationController?.pushViewController(vc, animated: true) - } - } - -} - -extension TrackContentVC: UIPickerViewDataSource, UIPickerViewDelegate{ - - func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { - return trackContenOptions.count - } - - func numberOfComponents(in pickerView: UIPickerView) -> Int { - return 1 - } - - func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { - return trackContenOptions[row] - } - - func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { - txtFldOptions.text = trackContenOptions[row] - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ViewController.swift deleted file mode 100644 index 359d647da..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ViewController.swift +++ /dev/null @@ -1,20 +0,0 @@ -// ViewController.swift -// DeepLinkDemo -// Created by Apple on 17/05/22 -import UIKit - -class ViewController: ParentViewController { - - override func viewDidLoad() { - super.viewDidLoad() - super.reachabilityCheck() - } - - - - override var preferredStatusBarStyle: UIStatusBarStyle { - return .lightContent - } - - -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/WebViewVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/WebViewVC.swift deleted file mode 100644 index b244ac66a..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/WebViewVC.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// WebViewVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/22/22. -// - -import UIKit -import WebKit -import SafariServices - -class WebViewVC: ParentViewController, WKNavigationDelegate { - - @IBOutlet weak var webViewContainer: UIView! - - var webViewDetail: WKWebView = WKWebView() - private var reachability:Reachability? - - override func viewDidLoad() { - super.viewDidLoad() - - loadWKWebview() - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("HandleLinksInapp") - } - - fileprivate func loadWKWebview(){ - let webConfiguration = WKWebViewConfiguration() - let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: self.webViewContainer.frame.size.width, height: self.webViewContainer.frame.size.height)) - self.webViewDetail = WKWebView (frame: customFrame , configuration: webConfiguration) - webViewDetail.translatesAutoresizingMaskIntoConstraints = false - self.webViewContainer.addSubview(webViewDetail) - self.view.addConstraint(NSLayoutConstraint(item: webViewDetail, attribute: .trailing, relatedBy: .equal, toItem: self.webViewContainer, attribute: .trailing, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: webViewDetail, attribute: .leading, relatedBy: .equal, toItem: self.webViewContainer, attribute: .leading, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: webViewDetail, attribute: .top, relatedBy: .equal, toItem: self.webViewContainer, attribute: .top, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: webViewDetail, attribute: .bottom, relatedBy: .equal, toItem: self.webViewContainer, attribute: .bottom, multiplier: 1, constant: 0)) - - webViewDetail.navigationDelegate = self - if let deeplinkurl: String = UserDefaults.standard.string(forKey: "link"){ - webViewDetail.load(URLRequest(url: URL(string: deeplinkurl)!)) - } - } - - @IBAction func backBtnTapped(){ - self.navigationController?.popToRootViewController(animated: true) - } - -} - -extension WebViewVC: SFSafariViewControllerDelegate{ - func safariViewControllerDidFinish(_ controller: SFSafariViewController) { - self.dismiss(animated: true) - self.navigationController?.popViewController(animated: true) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo-Bridging-Header.h b/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo-Bridging-Header.h deleted file mode 100644 index 28c03fdc2..000000000 --- a/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo-Bridging-Header.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// DeepLinkDemo-Bridging-Header.h -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/18/22. -// - -#ifndef DeepLinkDemo_Bridging_Header_h -#define DeepLinkDemo_Bridging_Header_h -#import "SIAlertView.h" - -#endif /* DeepLinkDemo_Bridging_Header_h */ diff --git a/DeepLinkDemo/DeepLinkDemo/Header.h b/DeepLinkDemo/DeepLinkDemo/Header.h deleted file mode 100644 index d3e5fefff..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Header.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// Header.h -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/18/22. -// - -#ifndef Header_h -#define Header_h -#import "SIAlertView.h" - -#endif /* Header_h */ diff --git a/DeepLinkDemo/DeepLinkDemo/Info.plist b/DeepLinkDemo/DeepLinkDemo/Info.plist deleted file mode 100644 index 6ce93adf7..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Info.plist +++ /dev/null @@ -1,54 +0,0 @@ - - - - - CFBundleSignature - ???? - CFBundleURLTypes - - - CFBundleURLSchemes - - Timber - - - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - UIBackgroundModes - - fetch - processing - remote-notification - - UIStatusBarStyle - UIStatusBarStyleLightContent - adjust_app_token - x66ziay2jtvk - amplitude_api_key - 3dc11880800fe99b829ca66886abf9e5 - appboy_api_key - d781dccf-9f96-46a8-878a-a1bef7bb6968 - appmetrica_api_key - 4805cb1a-2e2c-4a03-af63-4c712939817b - appsflyer_api_key - 84qHoE3ZXh7SetmHU6boi5 - branch_key - - live - key_live_nf8w3l1WBpzWdlC00KsLNdmbuEccK6Yr - test - key_test_om2EWe1WBeBYmpz9Z1mdpopouDmoN72T - - branch_universal_link_domains - - timber.app.link - timber-alternate.app.link - timber.test.app.link - timber-alternate.test.app.link - - - diff --git a/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.h b/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.h deleted file mode 100644 index 125b19377..000000000 --- a/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// NSURLSession+Branch.h -// -// Created by Ernest Cho on 10/11/18. -// Copyright © 2018 Branch Metrics, Inc. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NSURLSession (Branch) - -@end - -NS_ASSUME_NONNULL_END diff --git a/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.m b/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.m deleted file mode 100644 index 379c8e752..000000000 --- a/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.m +++ /dev/null @@ -1,94 +0,0 @@ -// -// NSURLSession+Branch.m -// -// Created by Ernest Cho on 10/11/18. -// Copyright © 2018 Branch Metrics, Inc. All rights reserved. -// - -#import "NSURLSessionBranch.h" -#import -#import "BranchLogger.h" - -@implementation NSURLSession (Branch) - -+ (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self swizzleSelector:@selector(dataTaskWithRequest:completionHandler:) - withSelector:@selector(xxx_dataTaskWithRequest:completionHandler:)]; - }); -} - -// swaps originalSelector with swizzledSelector -+ (void)swizzleSelector:(SEL)originalSelector withSelector:(SEL)swizzledSelector { - Class class = [self class]; - - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); - - method_exchangeImplementations(originalMethod, swizzledMethod); -} - -- (void)logNetworkTrafficRequest:(NSURLRequest *)request data:(NSData *)data response:(NSURLResponse *)response { - [[BranchLogger shared] logDebug: @"BranchSDK API LOG START OF FILE" error:nil]; - - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:(@"---------------------------------------------------------------------BranchSDK LOG START ---------------------------------------------------------------------" ) error:nil]; - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:([NSString stringWithFormat: @"BranchSDK Request log: %@", request]) error:nil]; - - NSData *body = [request HTTPBody]; - if (body) { - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"BranchSDK Request Body: %@", [NSString stringWithUTF8String:body.bytes]] error:nil]; - } - - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"BranchSDK Response: %@", response] error:nil]; - - if (data.bytes) { - [[BranchLogger shared] logDebug:(@"\n\n") error:nil]; - [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"BranchSDK Response Data: %@", [NSString stringWithUTF8String:data.bytes]] error:nil]; - } - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:(@"---------------------------------------------------------------------BranchSDK LOG END ---------------------------------------------------------------------" ) error:nil]; - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:(@"BranchSDK API LOG END OF FILE") error:nil]; - -} - -// replacement method for dataTaskWithRequest -- (NSURLSessionDataTask *)xxx_dataTaskWithRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler { - - // create a new block that just calls the original block after logging the request - void (^completionHandlerWithLogging)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) { - if (completionHandler) { - - [self logNetworkTrafficRequest:request data:data response:response]; - completionHandler(data, response, error); - } - }; - - return [self xxx_dataTaskWithRequest:request completionHandler:completionHandlerWithLogging]; -} - -- (NSData *)dataFromJSONFileNamed:(NSString *)fileName { - // If this class is part of the Test target, [self class] returns the Test Bundle - // NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:fileName ofType:@"json"]; - - NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"json"]; - NSString *jsonString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; - return [jsonString dataUsingEncoding:NSUTF8StringEncoding]; -} - -- (NSDictionary *)dictionaryFromJSONFileNamed:(NSString *)fileName { - NSData *jsonData = [self dataFromJSONFileNamed:fileName]; - id dict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; - if ([dict isKindOfClass:NSDictionary.class]) { - return dict; - } - return nil; -} - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.h b/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.h deleted file mode 100644 index ad32df88d..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Reachability.h -// Reachability -// -// Created by Yuki Nagai on 11/2/15. -// Copyright © 2015 Ashley Mills. All rights reserved. -// - -#import - -//! Project version number for Reachability. -FOUNDATION_EXPORT double ReachabilityVersionNumber; - -//! Project version string for Reachability. -FOUNDATION_EXPORT const unsigned char ReachabilityVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - - diff --git a/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.swift b/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.swift deleted file mode 100644 index 9f5f4d7ae..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.swift +++ /dev/null @@ -1,270 +0,0 @@ -/* - Copyright (c) 2014, Ashley Mills - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -import SystemConfiguration -import Foundation - -public enum ReachabilityError: Error { - case FailedToCreateWithAddress(sockaddr_in) - case FailedToCreateWithHostname(String) - case UnableToSetCallback - case UnableToSetDispatchQueue -} - -public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification") - -func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) { - - guard let info = info else { return } - - let reachability = Unmanaged.fromOpaque(info).takeUnretainedValue() - - DispatchQueue.main.async { - reachability.reachabilityChanged() - } -} - -public class Reachability { - - public typealias NetworkReachable = (Reachability) -> () - public typealias NetworkUnreachable = (Reachability) -> () - - public enum NetworkStatus: CustomStringConvertible { - - case notReachable, reachableViaWiFi, reachableViaWWAN - - public var description: String { - switch self { - case .reachableViaWWAN: return "Cellular" - case .reachableViaWiFi: return "WiFi" - case .notReachable: return "No Connection" - } - } - } - - public var whenReachable: NetworkReachable? - public var whenUnreachable: NetworkUnreachable? - public var reachableOnWWAN: Bool - - // The notification center on which "reachability changed" events are being posted - public var notificationCenter: NotificationCenter = NotificationCenter.default - public var currentReachabilityString: String { - return "\(currentReachabilityStatus)" - } - - public var currentReachabilityStatus: NetworkStatus { - guard isReachable else { return .notReachable } - if isReachableViaWiFi { - return .reachableViaWiFi - } - if isRunningOnDevice { - return .reachableViaWWAN - } - return .notReachable - } - - fileprivate var previousFlags: SCNetworkReachabilityFlags? - fileprivate var isRunningOnDevice: Bool = { - #if (arch(i386) || arch(x86_64)) && os(iOS) - return false - #else - return true - #endif - }() - fileprivate var notifierRunning = false - fileprivate var reachabilityRef: SCNetworkReachability? - fileprivate let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability") - required public init(reachabilityRef: SCNetworkReachability) { - reachableOnWWAN = true - self.reachabilityRef = reachabilityRef - } - - public convenience init?(hostname: String) { - guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { return nil } - self.init(reachabilityRef: ref) - } - - public convenience init?() { - var zeroAddress = sockaddr() - zeroAddress.sa_len = UInt8(MemoryLayout.size) - zeroAddress.sa_family = sa_family_t(AF_INET) - guard let ref: SCNetworkReachability = withUnsafePointer(to: &zeroAddress, { - SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) - }) else { return nil } - self.init(reachabilityRef: ref) - } - - deinit { - stopNotifier() - reachabilityRef = nil - whenReachable = nil - whenUnreachable = nil - } -} - -public extension Reachability { - - // MARK: - *** Notifier methods *** - func startNotifier() throws { - guard let reachabilityRef = reachabilityRef, !notifierRunning else { return } - var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) - context.info = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) - if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) { - stopNotifier() - throw ReachabilityError.UnableToSetCallback - } - if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) { - stopNotifier() - throw ReachabilityError.UnableToSetDispatchQueue - } - // Perform an intial check - reachabilitySerialQueue.async { - self.reachabilityChanged() - } - notifierRunning = true - } - - func stopNotifier() { - defer { notifierRunning = false } - guard let reachabilityRef = reachabilityRef else { return } - SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil) - SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil) - } - - // MARK: - *** Connection test methods *** - var isReachable: Bool { - - guard isReachableFlagSet else { return false } - - if isConnectionRequiredAndTransientFlagSet { - return false - } - if isRunningOnDevice { - if isOnWWANFlagSet && !reachableOnWWAN { - // We don't want to connect when on 3G. - return false - } - } - return true - } - - var isReachableViaWWAN: Bool { - // Check we're not on the simulator, we're REACHABLE and check we're on WWAN - return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet - } - - var isReachableViaWiFi: Bool { - // Check we're reachable - guard isReachableFlagSet else { return false } - // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi - guard isRunningOnDevice else { return true } - // Check we're NOT on WWAN - return !isOnWWANFlagSet - } - - var description: String { - - let W = isRunningOnDevice ? (isOnWWANFlagSet ? "W" : "-") : "X" - let R = isReachableFlagSet ? "R" : "-" - let c = isConnectionRequiredFlagSet ? "c" : "-" - let t = isTransientConnectionFlagSet ? "t" : "-" - let i = isInterventionRequiredFlagSet ? "i" : "-" - let C = isConnectionOnTrafficFlagSet ? "C" : "-" - let D = isConnectionOnDemandFlagSet ? "D" : "-" - let l = isLocalAddressFlagSet ? "l" : "-" - let d = isDirectFlagSet ? "d" : "-" - return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)" - } -} - -fileprivate extension Reachability { - - func reachabilityChanged() { - let flags = reachabilityFlags - guard previousFlags != flags else { return } - let block = isReachable ? whenReachable : whenUnreachable - block?(self) - if ReachabilityChangedNotification.rawValue != "" { - self.notificationCenter.post(name: ReachabilityChangedNotification, object:self) - } - previousFlags = flags - } - - var isOnWWANFlagSet: Bool { - #if os(iOS) - return reachabilityFlags.contains(.isWWAN) - #else - return false - #endif - } - var isReachableFlagSet: Bool { - return reachabilityFlags.contains(.reachable) - } - var isConnectionRequiredFlagSet: Bool { - return reachabilityFlags.contains(.connectionRequired) - } - var isInterventionRequiredFlagSet: Bool { - return reachabilityFlags.contains(.interventionRequired) - } - var isConnectionOnTrafficFlagSet: Bool { - return reachabilityFlags.contains(.connectionOnTraffic) - } - var isConnectionOnDemandFlagSet: Bool { - return reachabilityFlags.contains(.connectionOnDemand) - } - var isConnectionOnTrafficOrDemandFlagSet: Bool { - return !reachabilityFlags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty - } - var isTransientConnectionFlagSet: Bool { - return reachabilityFlags.contains(.transientConnection) - } - var isLocalAddressFlagSet: Bool { - return reachabilityFlags.contains(.isLocalAddress) - } - var isDirectFlagSet: Bool { - return reachabilityFlags.contains(.isDirect) - } - var isConnectionRequiredAndTransientFlagSet: Bool { - return reachabilityFlags.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection] - } - - var reachabilityFlags: SCNetworkReachabilityFlags { - - guard let reachabilityRef = reachabilityRef else { return SCNetworkReachabilityFlags() } - - var flags = SCNetworkReachabilityFlags() - let gotFlags = withUnsafeMutablePointer(to: &flags) { - SCNetworkReachabilityGetFlags(reachabilityRef, UnsafeMutablePointer($0)) - } - - if gotFlags { - return flags - } else { - return SCNetworkReachabilityFlags() - } - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d.png deleted file mode 100644 index fa432a55d..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d@2x.png deleted file mode 100644 index 8f359b8a5..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel.png deleted file mode 100644 index 88d1564f9..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel@2x.png deleted file mode 100644 index 0ac483b72..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d.png deleted file mode 100644 index 47f5163cc..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d@2x.png deleted file mode 100644 index 6d21603e1..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default.png deleted file mode 100644 index 17eab5920..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default@2x.png deleted file mode 100644 index d5f08e6c0..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d.png deleted file mode 100644 index 0a531501e..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d@2x.png deleted file mode 100644 index e614fafec..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive.png deleted file mode 100644 index 28f3264e5..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive@2x.png deleted file mode 100644 index 1a82328a0..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.h b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.h deleted file mode 100644 index 49eaae22f..000000000 --- a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.h +++ /dev/null @@ -1,69 +0,0 @@ -// SIAlertView.h -// SIAlertView -// Created by Kevin Cao on 13-4-29. -// Copyright (c) 2013年 Sumi Interactive. All rights reserved. - -#import -extern NSString *const SIAlertViewWillShowNotification; -extern NSString *const SIAlertViewDidShowNotification; -extern NSString *const SIAlertViewWillDismissNotification; -extern NSString *const SIAlertViewDidDismissNotification; -typedef NS_ENUM(NSInteger, SIAlertViewButtonType) { - SIAlertViewButtonTypeDefault = 0, - SIAlertViewButtonTypeDestructive, - SIAlertViewButtonTypeCancel -}; -typedef NS_ENUM(NSInteger, SIAlertViewBackgroundStyle) { - SIAlertViewBackgroundStyleGradient = 0, - SIAlertViewBackgroundStyleSolid, -}; -typedef NS_ENUM(NSInteger, SIAlertViewButtonsListStyle) { - SIAlertViewButtonsListStyleNormal = 0, - SIAlertViewButtonsListStyleRows -}; -typedef NS_ENUM(NSInteger, SIAlertViewTransitionStyle) { - SIAlertViewTransitionStyleSlideFromBottom = 0, - SIAlertViewTransitionStyleSlideFromTop, - SIAlertViewTransitionStyleFade, - SIAlertViewTransitionStyleBounce, - SIAlertViewTransitionStyleDropDown -}; -@class SIAlertView; -typedef void(^SIAlertViewHandler)(SIAlertView *alertView); -@interface SIAlertView : UIView -@property (nonatomic, copy) NSString *title; -@property (nonatomic, copy) NSString *message; -@property (nonatomic, assign) SIAlertViewTransitionStyle transitionStyle; // default is SIAlertViewTransitionStyleSlideFromBottom -@property (nonatomic, assign) SIAlertViewBackgroundStyle backgroundStyle; // default is SIAlertViewBackgroundStyleGradient -@property (nonatomic, assign) SIAlertViewButtonsListStyle buttonsListStyle; // default is SIAlertViewButtonsListStyleNormal -@property (nonatomic, copy) SIAlertViewHandler willShowHandler; -@property (nonatomic, copy) SIAlertViewHandler didShowHandler; -@property (nonatomic, copy) SIAlertViewHandler willDismissHandler; -@property (nonatomic, copy) SIAlertViewHandler didDismissHandler; -@property (nonatomic, readonly, getter = isVisible) BOOL visible; -@property (nonatomic, readonly, getter = isParallaxEffectEnabled) BOOL enabledParallaxEffect; -@property (nonatomic, strong) UIColor *viewBackgroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *titleColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *messageColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIFont *titleFont NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIFont *messageFont NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIFont *buttonFont NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *buttonColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *cancelButtonColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *destructiveButtonColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, assign) CGFloat cornerRadius NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; // default is 2.0 -@property (nonatomic, assign) CGFloat shadowRadius NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; // default is 8.0 - -@property (nonatomic) BOOL shouldRemoveAfterTouch; - -- (void)setDefaultButtonImage:(UIImage *)defaultButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -- (void)setCancelButtonImage:(UIImage *)cancelButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -- (void)setDestructiveButtonImage:(UIImage *)destructiveButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; - -- (instancetype)initWithTitle:(NSString *)title andMessage:(NSString *)message NS_DESIGNATED_INITIALIZER; -- (void)addButtonWithTitle:(NSString *)title type:(SIAlertViewButtonType)type handler:(SIAlertViewHandler)handler; - -- (void)show; -- (void)dismissAnimated:(BOOL)animated; - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.m b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.m deleted file mode 100644 index e2f988e2d..000000000 --- a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.m +++ /dev/null @@ -1,1253 +0,0 @@ -// SIAlertView.m -// SIAlertView -// Created by Kevin Cao on 13-4-29. -// Copyright (c) 2013年 Sumi Interactive. All rights reserved. - -#import "SIAlertView.h" -#import "UIWindow+SIUtils.h" -#import -NSString *const SIAlertViewWillShowNotification = @"SIAlertViewWillShowNotification"; -NSString *const SIAlertViewDidShowNotification = @"SIAlertViewDidShowNotification"; -NSString *const SIAlertViewWillDismissNotification = @"SIAlertViewWillDismissNotification"; -NSString *const SIAlertViewDidDismissNotification = @"SIAlertViewDidDismissNotification"; -#define DEBUG_LAYOUT 0 -#define MESSAGE_MIN_LINE_COUNT 3 -#define MESSAGE_MAX_LINE_COUNT 15 -#define GAP 10 -#define CANCEL_BUTTON_PADDING_TOP 5 -#define CONTENT_PADDING_LEFT 10 -#define CONTENT_PADDING_TOP 12 -#define CONTENT_PADDING_BOTTOM 10 -#define BUTTON_HEIGHT 45.0//([[UIScreen mainScreen] bounds].size.height/(2208.0/147.0))//47 -#define CONTAINER_WIDTH 300 - -const UIWindowLevel UIWindowLevelSIAlert = 1996.0; // don't overlap system's alert -const UIWindowLevel UIWindowLevelSIAlertBackground = 1985.0; // below the alert window - -@class SIAlertBackgroundWindow; -static NSMutableArray *__si_alert_queue; -static BOOL __si_alert_animating; -static SIAlertBackgroundWindow *__si_alert_background_window; -static SIAlertView *__si_alert_current_view; - -@interface SIAlertView () - -@property (nonatomic, strong) NSMutableArray *items; -@property (nonatomic, weak) UIWindow *oldKeyWindow; -@property (nonatomic, strong) UIWindow *alertWindow; -#ifdef __IPHONE_7_0 -@property (nonatomic, assign) UIViewTintAdjustmentMode oldTintAdjustmentMode; -#endif -@property (nonatomic, assign, getter = isVisible) BOOL visible; - -@property (nonatomic, strong) UILabel *titleLabel; -@property (nonatomic, strong) UILabel *messageLabel; -@property (nonatomic, strong) UIView *containerView; -@property (nonatomic, strong) NSMutableArray *buttons; - -@property (nonatomic, assign, getter = isLayoutDirty) BOOL layoutDirty; - -+ (NSMutableArray *)sharedQueue; -+ (SIAlertView *)currentAlertView; - -+ (BOOL)isAnimating; -+ (void)setAnimating:(BOOL)animating; - -+ (void)showBackground; -+ (void)hideBackgroundAnimated:(BOOL)animated; - -- (void)setup; -- (void)invalidateLayout; -- (void)resetTransition; - -@end - -#pragma mark - SIBackgroundWindow - -@interface SIAlertBackgroundWindow : UIWindow - -@end - -@interface SIAlertBackgroundWindow () - -@property (nonatomic, assign) SIAlertViewBackgroundStyle style; - -@end - -@implementation SIAlertBackgroundWindow - -- (instancetype)initWithFrame:(CGRect)frame andStyle:(SIAlertViewBackgroundStyle)style -{ - self = [super initWithFrame:frame]; - if (self) { - self.style = style; - self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.opaque = NO; - self.windowLevel = UIWindowLevelSIAlertBackground; - } - return self; -} - -- (void)drawRect:(CGRect)rect -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - switch (self.style) { - case SIAlertViewBackgroundStyleGradient: - { - size_t locationsCount = 2; - CGFloat locations[2] = {0.0f, 1.0f}; - CGFloat colors[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f}; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount); - CGColorSpaceRelease(colorSpace); - - CGPoint center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2); - CGFloat radius = MIN(self.bounds.size.width, self.bounds.size.height) ; - CGContextDrawRadialGradient (context, gradient, center, 0, center, radius, kCGGradientDrawsAfterEndLocation); - CGGradientRelease(gradient); - break; - } - case SIAlertViewBackgroundStyleSolid: - { - [[UIColor colorWithWhite:0 alpha:0.5] set]; - CGContextFillRect(context, self.bounds); - break; - } - } -} - -@end - -#pragma mark - SIAlertItem -@interface SIAlertItem : NSObject -@property (nonatomic, copy) NSString *title; -@property (nonatomic, assign) SIAlertViewButtonType type; -@property (nonatomic, copy) SIAlertViewHandler action; -@end -@implementation SIAlertItem -@end - -#pragma mark - SIAlertViewController -@interface SIAlertViewController : UIViewController -@property (nonatomic, strong) SIAlertView *alertView; -@end - -@implementation SIAlertViewController - -#pragma mark - View life cycle - -- (void)loadView -{ - self.view = self.alertView; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - [self.alertView setup]; -} - -- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration -{ - [self.alertView resetTransition]; - [self.alertView invalidateLayout]; -} - -#ifdef __IPHONE_7_0 -- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration -{ - if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { - [self setNeedsStatusBarAppearanceUpdate]; - } -} -#endif - -- (UIInterfaceOrientationMask)supportedInterfaceOrientations -{ - UIViewController *viewController = [self.alertView.oldKeyWindow currentViewController]; - if (viewController) { - return [viewController supportedInterfaceOrientations]; - } - return UIInterfaceOrientationMaskAll; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation -{ - UIViewController *viewController = [self.alertView.oldKeyWindow currentViewController]; - if (viewController) { - return [viewController shouldAutorotateToInterfaceOrientation:toInterfaceOrientation]; - } - return YES; -} - -- (BOOL)shouldAutorotate -{ - UIViewController *viewController = [self.alertView.oldKeyWindow currentViewController]; - if (viewController) { - return [viewController shouldAutorotate]; - } - return YES; -} - -#ifdef __IPHONE_7_0 -- (UIStatusBarStyle)preferredStatusBarStyle -{ - UIWindow *window = self.alertView.oldKeyWindow; - if (!window) { - window = [UIApplication sharedApplication].windows[0]; - } - return [[window viewControllerForStatusBarStyle] preferredStatusBarStyle]; -} - -- (BOOL)prefersStatusBarHidden -{ - UIWindow *window = self.alertView.oldKeyWindow; - if (!window) { - window = [UIApplication sharedApplication].windows[0]; - } - return [[window viewControllerForStatusBarHidden] prefersStatusBarHidden]; -} -#endif - -@end - -#pragma mark - SIAlert - -@implementation SIAlertView - -+ (void)initialize { - if (self != [SIAlertView class]) - return; - SIAlertView *appearance = [self appearance]; - appearance.viewBackgroundColor = [UIColor whiteColor]; - appearance.titleColor = [UIColor blackColor]; - appearance.messageColor = [UIColor darkGrayColor]; - appearance.titleFont = [UIFont fontWithName:@"SegoeUI" size:20.0]; // FONT_MAVEN_REGULAR - appearance.messageFont = [UIFont fontWithName:@"SegoeUI-Light" size:18.0];// FONT_MAVEN_LIGHT_300 - appearance.buttonFont = [UIFont fontWithName:@"SegoeUI" size:20.0];// FONT_MAVEN_REGULAR - appearance.buttonColor = [UIColor whiteColor];//[UIColor colorWithRed:39.0/255.0 green:75.0/255.0 blue:160.0/255.0 alpha:1.0]; - appearance.cancelButtonColor = [UIColor whiteColor]; - appearance.destructiveButtonColor = [UIColor whiteColor];//[UIColor colorWithRed:77.0/255.0 green:184.0/255.0 blue:49.0/255.0 alpha:1.0]; - appearance.destructiveButtonColor = [UIColor whiteColor]; - appearance.cornerRadius = 5.0; - appearance.shadowRadius = 5.0; -} -/* -- (instancetype)init -{ - return [self initWithTitle:nil andMessage:nil]; -}*/ - -- (instancetype)initWithTitle:(NSString *)title andMessage:(NSString *)message { - self = [super initWithFrame:CGRectZero]; - if (self) { - - if (title.length > 0) { // Check Added because nill could not be passed (from swift) - _title = title; - } else { - _title = nil; - } - _message = message; - _enabledParallaxEffect = YES; - self.items = [[NSMutableArray alloc] init]; - } - return self; -} - -#pragma mark - Class methods - -+ (NSMutableArray *)sharedQueue -{ - if (!__si_alert_queue) { - __si_alert_queue = [NSMutableArray array]; - } - return __si_alert_queue; -} - -+ (SIAlertView *)currentAlertView -{ - return __si_alert_current_view; -} - -+ (void)setCurrentAlertView:(SIAlertView *)alertView -{ - __si_alert_current_view = alertView; -} - -+ (BOOL)isAnimating -{ - return __si_alert_animating; -} - -+ (void)setAnimating:(BOOL)animating { - __si_alert_animating = animating; -} - -+ (void)showBackground { - if (!__si_alert_background_window) { - CGRect frame = [UIScreen mainScreen].bounds; - if([[UIScreen mainScreen] respondsToSelector:@selector(fixedCoordinateSpace)]) - { - frame = [[UIScreen mainScreen].fixedCoordinateSpace convertRect:frame fromCoordinateSpace:[UIScreen mainScreen].coordinateSpace]; - } - - __si_alert_background_window = [[SIAlertBackgroundWindow alloc] initWithFrame:frame - andStyle:[SIAlertView currentAlertView].backgroundStyle]; - [__si_alert_background_window makeKeyAndVisible]; - __si_alert_background_window.alpha = 0; - [UIView animateWithDuration:0.3 - animations:^{ - __si_alert_background_window.alpha = 1; - }]; - } -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - UITouch *touch = [touches anyObject]; - CGPoint location = [touch locationInView:self]; -// NSLog(@"%@",self.containerView); - if (self.shouldRemoveAfterTouch && self.containerView) { - if (!(((location.y > CGRectGetMinY(self.containerView.frame)) && (location.y < CGRectGetMaxY(self.containerView.frame))) && ((location.x > CGRectGetMinX(self.containerView.frame)) && (location.x < CGRectGetMaxX(self.containerView.frame))))) { - self.shouldRemoveAfterTouch = NO; - [self dismissAnimated:YES]; - } - } -} - -+ (void)hideBackgroundAnimated:(BOOL)animated -{ - if (!animated) { - [__si_alert_background_window removeFromSuperview]; - __si_alert_background_window = nil; - return; - } - [UIView animateWithDuration:0.3 - animations:^{ - __si_alert_background_window.alpha = 0; - } - completion:^(BOOL finished) { - [__si_alert_background_window removeFromSuperview]; - __si_alert_background_window = nil; - }]; -} - -#pragma mark - Setters - -- (void)setTitle:(NSString *)title -{ - _title = title; - [self invalidateLayout]; -} - -- (void)setMessage:(NSString *)message -{ - _message = message; - [self invalidateLayout]; -} - -#pragma mark - Public - -- (void)addButtonWithTitle:(NSString *)title type:(SIAlertViewButtonType)type handler:(SIAlertViewHandler)handler -{ - SIAlertItem *item = [[SIAlertItem alloc] init]; - item.title = title; - item.type = type; - item.action = handler; - [self.items addObject:item]; -} - -- (void)show -{ - if (self.isVisible) { - return; - } - - self.oldKeyWindow = [UIApplication sharedApplication].keyWindow; -#ifdef __IPHONE_7_0 - if ([self.oldKeyWindow respondsToSelector:@selector(setTintAdjustmentMode:)]) { // for iOS 7 - self.oldTintAdjustmentMode = self.oldKeyWindow.tintAdjustmentMode; - self.oldKeyWindow.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed; - } -#endif - - if (![[SIAlertView sharedQueue] containsObject:self]) { - [[SIAlertView sharedQueue] addObject:self]; - } - - if ([SIAlertView isAnimating]) { - return; // wait for next turn - } - - if ([SIAlertView currentAlertView].isVisible) { - SIAlertView *alert = [SIAlertView currentAlertView]; - [alert dismissAnimated:YES cleanup:NO]; - return; - } - - if (self.willShowHandler) { - self.willShowHandler(self); - } - - [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewWillShowNotification object:self userInfo:nil]; - - self.visible = YES; - - [SIAlertView setAnimating:YES]; - [SIAlertView setCurrentAlertView:self]; - - // transition background - [SIAlertView showBackground]; - - SIAlertViewController *viewController = [[SIAlertViewController alloc] initWithNibName:nil bundle:nil]; - viewController.alertView = self; - - if (!self.alertWindow) { - UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - window.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - window.opaque = NO; - window.windowLevel = UIWindowLevelSIAlert; - window.rootViewController = viewController; - self.alertWindow = window; - } - [self.alertWindow makeKeyAndVisible]; - - [self validateLayout]; - [self.containerView setClipsToBounds:YES]; - - CGFloat yAxisOfBackgroundLayer = self.containerView.frame.size.height - BUTTON_HEIGHT - 0.5; - UIView *backgroundLayerOfButtons = [[UIView alloc] init]; - backgroundLayerOfButtons.frame = CGRectMake(0, yAxisOfBackgroundLayer, self.containerView.frame.size.width, self.containerView.frame.size.height - yAxisOfBackgroundLayer); - backgroundLayerOfButtons.backgroundColor = [UIColor colorWithRed:04.0/255.0 green:202.0/255.0 blue:169.0/255.0 alpha:1.0]; - [self.containerView insertSubview:backgroundLayerOfButtons atIndex:0]; - - [self transitionInCompletion:^{ - if (self.didShowHandler) { - self.didShowHandler(self); - } - [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewDidShowNotification object:self userInfo:nil]; - #ifdef __IPHONE_7_0 - [self addParallaxEffect]; - #endif - - [SIAlertView setAnimating:NO]; - - NSInteger index = [[SIAlertView sharedQueue] indexOfObject:self]; - if (index < [SIAlertView sharedQueue].count - 1) { - [self dismissAnimated:YES cleanup:NO]; // dismiss to show next alert view - } - }]; -} - -- (void)dismissAnimated:(BOOL)animated -{ - [self dismissAnimated:animated cleanup:YES]; -} - -- (void)dismissAnimated:(BOOL)animated cleanup:(BOOL)cleanup -{ - BOOL isVisible = self.isVisible; - - if (isVisible) { - if (self.willDismissHandler) { - self.willDismissHandler(self); - } - [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewWillDismissNotification object:self userInfo:nil]; - #ifdef __IPHONE_7_0 - [self removeParallaxEffect]; - #endif - } - - void (^dismissComplete)(void) = ^{ - self.visible = NO; - - [self teardown]; - - [SIAlertView setCurrentAlertView:nil]; - - SIAlertView *nextAlertView; - NSInteger index = [[SIAlertView sharedQueue] indexOfObject:self]; - if (index != NSNotFound && index < [SIAlertView sharedQueue].count - 1) { - nextAlertView = [SIAlertView sharedQueue][index + 1]; - } - - if (cleanup) { - [[SIAlertView sharedQueue] removeObject:self]; - } - - [SIAlertView setAnimating:NO]; - - if (isVisible) { - if (self.didDismissHandler) { - self.didDismissHandler(self); - } - [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewDidDismissNotification object:self userInfo:nil]; - } - - // check if we should show next alert - if (!isVisible) { - return; - } - - if (nextAlertView) { - [nextAlertView show]; - } else { - // show last alert view - if ([SIAlertView sharedQueue].count > 0) { - SIAlertView *alert = [SIAlertView sharedQueue].lastObject; - [alert show]; - } - } - }; - - if (animated && isVisible) { - [SIAlertView setAnimating:YES]; - [self transitionOutCompletion:dismissComplete]; - - if ([SIAlertView sharedQueue].count == 1) { - [SIAlertView hideBackgroundAnimated:YES]; - } - - } else { - dismissComplete(); - - if ([SIAlertView sharedQueue].count == 0) { - [SIAlertView hideBackgroundAnimated:YES]; - } - } - - UIWindow *window = self.oldKeyWindow; -#ifdef __IPHONE_7_0 - if ([window respondsToSelector:@selector(setTintAdjustmentMode:)]) { - window.tintAdjustmentMode = self.oldTintAdjustmentMode; - } -#endif - if (!window) { - window = [UIApplication sharedApplication].windows[0]; - } - [window makeKeyWindow]; - window.hidden = NO; -} - -#pragma mark - Transitions - -- (void)transitionInCompletion:(void(^)(void))completion -{ - switch (self.transitionStyle) { - case SIAlertViewTransitionStyleSlideFromBottom: - { - CGRect rect = self.containerView.frame; - CGRect originalRect = rect; - rect.origin.y = self.bounds.size.height; - self.containerView.frame = rect; - [UIView animateWithDuration:0.3 - animations:^{ - self.containerView.frame = originalRect; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleSlideFromTop: - { - CGRect rect = self.containerView.frame; - CGRect originalRect = rect; - rect.origin.y = -rect.size.height; - self.containerView.frame = rect; - [UIView animateWithDuration:0.3 - animations:^{ - self.containerView.frame = originalRect; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleFade: - { - self.containerView.alpha = 0; - [UIView animateWithDuration:0.3 - animations:^{ - self.containerView.alpha = 1; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleBounce: - { - CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; - animation.values = @[@(0.01), @(1.2), @(0.9), @(1)]; - animation.keyTimes = @[@(0), @(0.4), @(0.6), @(1)]; - animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; - animation.duration = 0.5; - animation.delegate = self; - [animation setValue:completion forKey:@"handler"]; - [self.containerView.layer addAnimation:animation forKey:@"bouce"]; - } - break; - case SIAlertViewTransitionStyleDropDown: - { - CGFloat y = self.containerView.center.y; - CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.y"]; - animation.values = @[@(y - self.bounds.size.height), @(y + 20), @(y - 10), @(y)]; - animation.keyTimes = @[@(0), @(0.5), @(0.75), @(1)]; - animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; - animation.duration = 0.4; - animation.delegate = self; - [animation setValue:completion forKey:@"handler"]; - [self.containerView.layer addAnimation:animation forKey:@"dropdown"]; - } - break; - default: - break; - } -} - -- (void)transitionOutCompletion:(void(^)(void))completion -{ - switch (self.transitionStyle) { - case SIAlertViewTransitionStyleSlideFromBottom: - { - CGRect rect = self.containerView.frame; - rect.origin.y = self.bounds.size.height; - [UIView animateWithDuration:0.3 - delay:0 - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - self.containerView.frame = rect; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleSlideFromTop: - { - CGRect rect = self.containerView.frame; - rect.origin.y = -rect.size.height; - [UIView animateWithDuration:0.3 - delay:0 - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - self.containerView.frame = rect; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleFade: - { - [UIView animateWithDuration:0.25 - animations:^{ - self.containerView.alpha = 0; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleBounce: - { - CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; - animation.values = @[@(1), @(1.2), @(0.01)]; - animation.keyTimes = @[@(0), @(0.4), @(1)]; - animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; - animation.duration = 0.35; - animation.delegate = self; - [animation setValue:completion forKey:@"handler"]; - [self.containerView.layer addAnimation:animation forKey:@"bounce"]; - self.containerView.transform = CGAffineTransformMakeScale(0.01, 0.01); - } - break; - case SIAlertViewTransitionStyleDropDown: - { - CGPoint point = self.containerView.center; - point.y += self.bounds.size.height; - [UIView animateWithDuration:0.3 - delay:0 - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - self.containerView.center = point; - CGFloat angle = ((CGFloat)arc4random_uniform(100) - 50.f) / 100.f; - self.containerView.transform = CGAffineTransformMakeRotation(angle); - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - default: - break; - } -} - -- (void)resetTransition -{ - [self.containerView.layer removeAllAnimations]; -} - -#pragma mark - Layout - -- (void)layoutSubviews -{ - [super layoutSubviews]; - [self validateLayout]; -} - -- (void)invalidateLayout -{ - self.layoutDirty = YES; - [self setNeedsLayout]; -} - -- (void)validateLayout -{ - if (!self.isLayoutDirty) { - return; - } - self.layoutDirty = NO; -#if DEBUG_LAYOUT -// NSLog(@"%@, %@", self, NSStringFromSelector(_cmd)); -#endif - - CGFloat height = [self preferredHeight]; - CGFloat left = (self.bounds.size.width - CONTAINER_WIDTH) * 0.5; - CGFloat top = (self.bounds.size.height - height) * 0.5; - self.containerView.transform = CGAffineTransformIdentity; - self.containerView.frame = CGRectMake(left, top, CONTAINER_WIDTH, height); - self.containerView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.containerView.bounds cornerRadius:self.containerView.layer.cornerRadius].CGPath; - - CGFloat y = CONTENT_PADDING_TOP; - if (self.titleLabel) { - self.titleLabel.text = self.title; - CGFloat height = [self heightForTitleLabel]; - self.titleLabel.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, height); - y += height; - } - if (self.messageLabel) { - if (y > CONTENT_PADDING_TOP) { - y += GAP; - } - self.messageLabel.text = self.message; - CGFloat height = [self heightForMessageLabel]; - self.messageLabel.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, height); - y += height; - } - if (self.items.count > 0) { - if (y > CONTENT_PADDING_TOP) { - y += GAP; - } - // y = self.containerView.bounds.size.height - BUTTON_HEIGHT; - if (self.items.count == 2 && self.buttonsListStyle == SIAlertViewButtonsListStyleNormal) { - //CGFloat width = (self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2 - GAP) * 0.5; - CGFloat width = (self.containerView.bounds.size.width - 0.5) * 0.5; - UIButton *button = self.buttons[0]; -// button.frame = CGRectMake(CONTENT_PADDING_LEFT, y, width, BUTTON_HEIGHT); - button.frame = CGRectMake(0, y, width, BUTTON_HEIGHT); - button = self.buttons[1]; -// button.frame = CGRectMake(CONTENT_PADDING_LEFT + width + GAP, y, width, BUTTON_HEIGHT); - button.frame = CGRectMake(width + 0.5, y, width, BUTTON_HEIGHT); - } else { - for (NSUInteger i = 0; i < self.buttons.count; i++) { - UIButton *button = self.buttons[i]; -// button.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, BUTTON_HEIGHT); - button.frame = CGRectMake(0, y, self.containerView.bounds.size.width, BUTTON_HEIGHT); - if (self.buttons.count > 1) { - if (i == self.buttons.count - 1 && ((SIAlertItem *)self.items[i]).type == SIAlertViewButtonTypeCancel) { - CGRect rect = button.frame; - rect.origin.y += CANCEL_BUTTON_PADDING_TOP; - button.frame = rect; - } - //y += BUTTON_HEIGHT + GAP; - y += BUTTON_HEIGHT + 0.5; - } - } - } - } -} - -- (CGFloat)preferredHeight -{ - CGFloat height = CONTENT_PADDING_TOP; - if (self.title) { - height += [self heightForTitleLabel]; - } - if (self.message) { - if (height > CONTENT_PADDING_TOP) { - height += GAP; - } - height += [self heightForMessageLabel]; - } - if (self.items.count > 0) { - if (height > CONTENT_PADDING_TOP) { - height += GAP; - } - if (self.items.count <= 2 && self.buttonsListStyle == SIAlertViewButtonsListStyleNormal) { - height += BUTTON_HEIGHT; - } else { -// height += (BUTTON_HEIGHT + GAP) * self.items.count - GAP; - height += (BUTTON_HEIGHT + 1.5) * self.items.count - 1.5; - if (self.buttons.count > 2 && ((SIAlertItem *)(self.items).lastObject).type == SIAlertViewButtonTypeCancel) { - height += CANCEL_BUTTON_PADDING_TOP; - } - } - } - //height += CONTENT_PADDING_BOTTOM; - return height; -} - -- (CGFloat)heightForTitleLabel { - if (self.titleLabel) { - float maxHeightOfTitleLabel = 2 * self.titleLabel.font.lineHeight; - (self.titleLabel).numberOfLines = 2; - (self.titleLabel).lineBreakMode = NSLineBreakByWordWrapping; - - #ifdef __IPHONE_7_0 - NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineBreakMode = self.titleLabel.lineBreakMode; - - NSDictionary *attributes = @{NSFontAttributeName:self.titleLabel.font, - NSParagraphStyleAttributeName: paragraphStyle.copy}; - - // NSString class method: boundingRectWithSize:options:attributes:context is - // available only on ios7.0 sdk. - CGRect rect = [self.titleLabel.text boundingRectWithSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, maxHeightOfTitleLabel) - options:NSStringDrawingUsesLineFragmentOrigin - attributes:attributes - context:nil]; - return ceil(rect.size.height); - #else - CGSize size = [self.title sizeWithFont:self.titleLabel.font - minFontSize: - #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 - self.titleLabel.font.pointSize * self.titleLabel.minimumScaleFactor - #else - self.titleLabel.minimumFontSize - #endif - actualFontSize:nil - forWidth:CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2 - lineBreakMode:self.titleLabel.lineBreakMode]; - return size.height; - #endif - } - - return 0; -} - -- (CGFloat)heightForMessageLabel -{ - CGFloat minHeight = MESSAGE_MIN_LINE_COUNT * self.messageLabel.font.lineHeight; - if (self.messageLabel) { - CGFloat maxHeight = MESSAGE_MAX_LINE_COUNT * self.messageLabel.font.lineHeight; - - #ifdef __IPHONE_7_0 - NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineBreakMode = self.messageLabel.lineBreakMode; - - NSDictionary *attributes = @{NSFontAttributeName:self.messageLabel.font, - NSParagraphStyleAttributeName: paragraphStyle.copy}; - - // NSString class method: boundingRectWithSize:options:attributes:context is - // available only on ios7.0 sdk. - //NSLog(@"Text of Message=>%@",self.messageLabel.text); - // NSLog(@"Widthof Expected label =>%d \n and height expected =>%f",(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2), maxHeight); - CGRect rect = [self.messageLabel.text boundingRectWithSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, maxHeight) - options:NSStringDrawingUsesLineFragmentOrigin - attributes:attributes - context:nil]; - // NSLog(@"estimated height of Message label =>%f \n exact height of Message label=>%f",rect.size.height,MAX(minHeight, ceil(rect.size.height))); - return MAX(minHeight, ceil(rect.size.height)); - #else - CGSize size = [self.message sizeWithFont:self.messageLabel.font - constrainedToSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, maxHeight) - lineBreakMode:self.messageLabel.lineBreakMode]; - - return MAX(minHeight, size.height); - #endif - } - - return minHeight; -} - -#pragma mark - Setup - -- (void)setup -{ - [self setupContainerView]; - [self updateTitleLabel]; - [self updateMessageLabel]; - [self setupButtons]; - [self invalidateLayout]; -} - -- (void)teardown -{ - [self.containerView removeFromSuperview]; - self.containerView = nil; - self.titleLabel = nil; - self.messageLabel = nil; - [self.buttons removeAllObjects]; - [self.alertWindow removeFromSuperview]; - self.alertWindow = nil; - self.layoutDirty = NO; -} - -- (void)setupContainerView -{ - self.containerView = [[UIView alloc] initWithFrame:self.bounds]; - self.containerView.backgroundColor = _viewBackgroundColor ? _viewBackgroundColor : [UIColor whiteColor]; - self.containerView.layer.cornerRadius = self.cornerRadius; - self.containerView.layer.shadowOffset = CGSizeZero; - self.containerView.layer.shadowRadius = self.shadowRadius; - self.containerView.layer.shadowOpacity = 0.5; - [self addSubview:self.containerView]; -} - -- (void)updateTitleLabel -{ - if (self.title) { - if (!self.titleLabel) { - self.titleLabel = [[UILabel alloc] initWithFrame:self.bounds]; - self.titleLabel.textAlignment = NSTextAlignmentCenter; - self.titleLabel.backgroundColor = [UIColor clearColor]; - self.titleLabel.font = self.titleFont; - self.titleLabel.textColor = self.titleColor; - self.titleLabel.adjustsFontSizeToFitWidth = YES; -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 - self.titleLabel.minimumScaleFactor = 0.75; -#else - self.titleLabel.minimumFontSize = self.titleLabel.font.pointSize * 0.75; -#endif - [self.containerView addSubview:self.titleLabel]; -#if DEBUG_LAYOUT - self.titleLabel.backgroundColor = [UIColor redColor]; -#endif - } - self.titleLabel.text = self.title; - } else { - [self.titleLabel removeFromSuperview]; - self.titleLabel = nil; - } - [self invalidateLayout]; -} - -- (void)updateMessageLabel -{ - if (self.message) { - if (!self.messageLabel) { - self.messageLabel = [[UILabel alloc] initWithFrame:self.bounds]; - self.messageLabel.textAlignment = NSTextAlignmentCenter; - self.messageLabel.backgroundColor = [UIColor clearColor]; - self.messageLabel.font = self.messageFont; - self.messageLabel.textColor = self.messageColor; - self.messageLabel.numberOfLines = MESSAGE_MAX_LINE_COUNT; - (self.messageLabel).lineBreakMode = NSLineBreakByWordWrapping; - [self.containerView addSubview:self.messageLabel]; -#if DEBUG_LAYOUT - self.messageLabel.backgroundColor = [UIColor redColor]; -#endif - } - self.messageLabel.text = self.message; - } else { - [self.messageLabel removeFromSuperview]; - self.messageLabel = nil; - } - [self invalidateLayout]; -} - -- (void)setupButtons -{ - self.buttons = [[NSMutableArray alloc] initWithCapacity:self.items.count]; - for (NSUInteger i = 0; i < self.items.count; i++) { - UIButton *button = [self buttonForItemIndex:i]; - [self.buttons addObject:button]; - [self.containerView addSubview:button]; - } -} - -- (UIButton *)buttonForItemIndex:(NSUInteger)index -{ - //CGFloat heightOfButton = [[CommonFunctions shareCommonMethods] targetYOrHeightSize:150.0]; - - SIAlertItem *item = self.items[index]; - UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; - button.tag = index; - button.autoresizingMask = UIViewAutoresizingFlexibleWidth; - button.titleLabel.font = self.buttonFont; - [button setTitle:item.title forState:UIControlStateNormal]; - UIImage *normalImage = nil; - UIImage *highlightedImage = [self imageWithColor:[UIColor clearColor] andFrame:CGRectMake(0, 0, 400, BUTTON_HEIGHT)]; - switch (item.type) { - case SIAlertViewButtonTypeCancel: - //normalImage = [UIImage imageNamed:@"SIAlertView.bundle/button-cancel"]; - //highlightedImage = [UIImage imageNamed:@"SIAlertView.bundle/button-cancel-d"]; - normalImage = [self imageWithColor:[UIColor colorWithRed:04.0/255.0 green:202.0/255.0 blue:169.0/255.0 alpha:1.0] andFrame:CGRectMake(0, 0, 400, BUTTON_HEIGHT)]; - - [button setTitleColor:self.cancelButtonColor forState:UIControlStateNormal]; - //[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - //[button.layer setBorderColor:[COLOR_JUGNOO_MEALS_THEME CGColor]]; - //[button.layer setBorderWidth:2.0]; - break; - case SIAlertViewButtonTypeDestructive: - normalImage = [self imageWithColor:[UIColor colorWithRed:04.0/255.0 green:202.0/255.0 blue:169.0/255.0 alpha:1.0] andFrame:CGRectMake(0, 0, 400, BUTTON_HEIGHT)]; - //highlightedImage = [UIImage imageNamed:@"SIAlertView.bundle/button-destructive-d"]; - [button setTitleColor:self.destructiveButtonColor forState:UIControlStateNormal]; - //[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - //[button.layer setBorderColor:[[UIColor whiteColor] CGColor]]; - //[button.layer setBorderWidth:2.0]; - break; - case SIAlertViewButtonTypeDefault: - default: - //normalImage = [UIImage imageNamed:@"SIAlertView.bundle/button-default"]; - //highlightedImage = [UIImage imageNamed:@"SIAlertView.bundle/button-default-d"]; - normalImage = [self imageWithColor:[UIColor colorWithRed:04.0/255.0 green:202.0/255.0 blue:169.0/255.0 alpha:1.0] andFrame:CGRectMake(0, 0, 400, BUTTON_HEIGHT)]; - [button setTitleColor:self.buttonColor forState:UIControlStateNormal]; - //[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - //[button.layer setBorderColor:[[UIColor whiteColor] CGColor]]; - //[button.layer setBorderWidth:2.0]; - break; - } - /*CGFloat hInset = floorf(normalImage.size.width / 2); - CGFloat vInset = floorf(normalImage.size.height / 2); - UIEdgeInsets insets = UIEdgeInsetsMake(vInset, hInset, vInset, hInset); - normalImage = [normalImage resizableImageWithCapInsets:insets]; - highlightedImage = [highlightedImage resizableImageWithCapInsets:insets];*/ - [button setClipsToBounds:YES]; - //[button.layer setCornerRadius:4.0]; - [button setBackgroundImage:normalImage forState:UIControlStateNormal]; - [button setBackgroundImage:highlightedImage forState:UIControlStateHighlighted]; - // [button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside]; - - return button; -} - -- (UIImage *)imageWithColor:(UIColor *)color andFrame:(CGRect)customFrame { - UIGraphicsBeginImageContext(customFrame.size); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [color CGColor]); - CGContextFillRect(context, customFrame); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - -#pragma mark - Actions - -- (void)buttonAction:(UIButton *)button -{ - [SIAlertView setAnimating:YES]; // set this flag to YES in order to prevent showing another alert in action block - SIAlertItem *item = self.items[button.tag]; - if (item.action) { - item.action(self); - } - [self dismissAnimated:YES]; -} - -#pragma mark - CAAnimation delegate - -- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag -{ - void(^completion)(void) = [anim valueForKey:@"handler"]; - if (completion) { - completion(); - } -} - -#pragma mark - UIAppearance setters - -- (void)setViewBackgroundColor:(UIColor *)viewBackgroundColor -{ - if (_viewBackgroundColor == viewBackgroundColor) { - return; - } - _viewBackgroundColor = viewBackgroundColor; - self.containerView.backgroundColor = viewBackgroundColor; -} - -- (void)setTitleFont:(UIFont *)titleFont -{ - if (_titleFont == titleFont) { - return; - } - _titleFont = titleFont; - self.titleLabel.font = titleFont; - [self invalidateLayout]; -} - -- (void)setMessageFont:(UIFont *)messageFont -{ - if (_messageFont == messageFont) { - return; - } - _messageFont = messageFont; - self.messageLabel.font = messageFont; - [self invalidateLayout]; -} - -- (void)setTitleColor:(UIColor *)titleColor -{ - if (_titleColor == titleColor) { - return; - } - _titleColor = titleColor; - self.titleLabel.textColor = titleColor; -} - -- (void)setMessageColor:(UIColor *)messageColor -{ - if (_messageColor == messageColor) { - return; - } - _messageColor = messageColor; - self.messageLabel.textColor = messageColor; -} - -- (void)setButtonFont:(UIFont *)buttonFont -{ - if (_buttonFont == buttonFont) { - return; - } - _buttonFont = buttonFont; - for (UIButton *button in self.buttons) { - button.titleLabel.font = buttonFont; - } -} - -- (void)setCornerRadius:(CGFloat)cornerRadius -{ - if (_cornerRadius == cornerRadius) { - return; - } - _cornerRadius = cornerRadius; - self.containerView.layer.cornerRadius = cornerRadius; -} - -- (void)setShadowRadius:(CGFloat)shadowRadius -{ - if (_shadowRadius == shadowRadius) { - return; - } - _shadowRadius = shadowRadius; - self.containerView.layer.shadowRadius = shadowRadius; -} - -- (void)setButtonColor:(UIColor *)buttonColor -{ - if (_buttonColor == buttonColor) { - return; - } - _buttonColor = buttonColor; - [self setColor:buttonColor toButtonsOfType:SIAlertViewButtonTypeDefault]; -} - -- (void)setCancelButtonColor:(UIColor *)buttonColor -{ - if (_cancelButtonColor == buttonColor) { - return; - } - _cancelButtonColor = buttonColor; - [self setColor:buttonColor toButtonsOfType:SIAlertViewButtonTypeCancel]; -} - -- (void)setDestructiveButtonColor:(UIColor *)buttonColor -{ - if (_destructiveButtonColor == buttonColor) { - return; - } - _destructiveButtonColor = buttonColor; - [self setColor:buttonColor toButtonsOfType:SIAlertViewButtonTypeDestructive]; -} - - -- (void)setDefaultButtonImage:(UIImage *)defaultButtonImage forState:(UIControlState)state -{ - [self setButtonImage:defaultButtonImage forState:state andButtonType:SIAlertViewButtonTypeDefault]; -} - - -- (void)setCancelButtonImage:(UIImage *)cancelButtonImage forState:(UIControlState)state -{ - [self setButtonImage:cancelButtonImage forState:state andButtonType:SIAlertViewButtonTypeCancel]; -} - - -- (void)setDestructiveButtonImage:(UIImage *)destructiveButtonImage forState:(UIControlState)state -{ - [self setButtonImage:destructiveButtonImage forState:state andButtonType:SIAlertViewButtonTypeDestructive]; -} - - -- (void)setButtonImage:(UIImage *)image forState:(UIControlState)state andButtonType:(SIAlertViewButtonType)type -{ - for (NSUInteger i = 0; i < self.items.count; i++) - { - SIAlertItem *item = self.items[i]; - if(item.type == type) - { - UIButton *button = self.buttons[i]; - [button setBackgroundImage:image forState:state]; - } - } -} - - --(void)setColor:(UIColor *)color toButtonsOfType:(SIAlertViewButtonType)type { - for (NSUInteger i = 0; i < self.items.count; i++) { - SIAlertItem *item = self.items[i]; - if(item.type == type) { - UIButton *button = self.buttons[i]; - [button setTitleColor:color forState:UIControlStateNormal]; - //[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - } - } -} - -# pragma mark - -# pragma mark Enable parallax effect (iOS7 only) - -#ifdef __IPHONE_7_0 -- (void)addParallaxEffect -{ - if (_enabledParallaxEffect && NSClassFromString(@"UIInterpolatingMotionEffect")) - { - UIInterpolatingMotionEffect *effectHorizontal = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"position.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; - UIInterpolatingMotionEffect *effectVertical = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"position.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; - effectHorizontal.maximumRelativeValue = @(20.0f); - effectHorizontal.minimumRelativeValue = @(-20.0f); - effectVertical.maximumRelativeValue = @(50.0f); - effectVertical.minimumRelativeValue = @(-50.0f); - [self.containerView addMotionEffect:effectHorizontal]; - [self.containerView addMotionEffect:effectVertical]; - } -} - -- (void)removeParallaxEffect -{ - if (_enabledParallaxEffect && NSClassFromString(@"UIInterpolatingMotionEffect")) - { - [self.containerView.motionEffects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - [self.containerView removeMotionEffect:obj]; - }]; - } -} -#endif - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.h b/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.h deleted file mode 100644 index 3d5abf36f..000000000 --- a/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// UIWindow+SIUtils.h -// SIAlertView -// -// Created by Kevin Cao on 13-11-1. -// Copyright (c) 2013年 Sumi Interactive. All rights reserved. -// - -#import - -@interface UIWindow (SIUtils) - -- (UIViewController *)currentViewController; - -#ifdef __IPHONE_7_0 -- (UIViewController *)viewControllerForStatusBarStyle; -- (UIViewController *)viewControllerForStatusBarHidden; -#endif - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.m b/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.m deleted file mode 100644 index 2967def19..000000000 --- a/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.m +++ /dev/null @@ -1,42 +0,0 @@ -// UIWindow+SIUtils.m -// SIAlertView -// Created by Kevin Cao on 13-11-1. -// Copyright (c) 2013年 Sumi Interactive. All rights reserved. - -#import "UIWindow+SIUtils.h" - -@implementation UIWindow (SIUtils) - -- (UIViewController *)currentViewController -{ - UIViewController *viewController = self.rootViewController; - while (viewController.presentedViewController) { - viewController = viewController.presentedViewController; - } - return viewController; -} - -#ifdef __IPHONE_7_0 - -- (UIViewController *)viewControllerForStatusBarStyle { - UIViewController *currentViewController = [self currentViewController]; - - while ([currentViewController childViewControllerForStatusBarStyle]) { - currentViewController = [currentViewController childViewControllerForStatusBarStyle]; - } - return currentViewController; -} - -- (UIViewController *)viewControllerForStatusBarHidden -{ - UIViewController *currentViewController = [self currentViewController]; - - while ([currentViewController childViewControllerForStatusBarHidden]) { - currentViewController = [currentViewController childViewControllerForStatusBarHidden]; - } - return currentViewController; -} - -#endif - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/StartupOptionsData.swift b/DeepLinkDemo/DeepLinkDemo/StartupOptionsData.swift deleted file mode 100644 index f0a6697b4..000000000 --- a/DeepLinkDemo/DeepLinkDemo/StartupOptionsData.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// StartupOptionsData.swift -// TestBed-Swift -// -// Created by David Westgate on 9/17/17. -// Copyright © 2017 Branch Metrics. All rights reserved. -// - -import Foundation - -struct StartupOptionsData { - - static let userDefaults = UserDefaults.standard - - static func getActiveBranchKey() -> String? { - if let value = userDefaults.string(forKey: "activeBranchKey") { - return value - } else { - let value = "" - userDefaults.setValue(value, forKey: "activeBranchKey") - return value - } - } - - static func setActiveBranchKey(_ value: String) { - userDefaults.setValue(value, forKey: "activeBranchKey") - } - - static func getPendingBranchKey() -> String? { - if let value = userDefaults.string(forKey: "pendingBranchKey") { - return value - } else { - let value = "" - userDefaults.setValue(value, forKey: "pendingBranchKey") - return value - } - } - - static func setPendingBranchKey(_ value: String) { - userDefaults.setValue(value, forKey: "pendingBranchKey") - } - - static func getActiveSetDebugEnabled() -> Bool? { - return userDefaults.bool(forKey: "activeSetDebug") - } - - static func setActiveSetDebugEnabled(_ value: Bool) { - userDefaults.setValue(value, forKey: "activeSetDebug") - } - - static func getPendingSetDebugEnabled() -> Bool? { - return userDefaults.bool(forKey: "pendingSetDebug") - } - - static func setPendingSetDebugEnabled(_ value: Bool) { - userDefaults.setValue(value, forKey: "pendingSetDebug") - } - -} diff --git a/DeepLinkDemo/DeepLinkDemo/img.png b/DeepLinkDemo/DeepLinkDemo/img.png deleted file mode 100644 index 95f2e9562..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/img.png and /dev/null differ diff --git a/DeepLinkDemo/IPA/Info.plist b/DeepLinkDemo/IPA/Info.plist deleted file mode 100644 index 42890b144..000000000 --- a/DeepLinkDemo/IPA/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - - compileBitcode - - destination - export - method - development - provisioningProfiles - - io.branch.saas.sdk.testbed - iOS Saas SDK - Dev - - signingCertificate - Apple Development - signingStyle - manual - stripSwiftSymbols - - teamID - R63EM248DP - thinning - <none> - - diff --git a/DeepLinkDemo/Podfile b/DeepLinkDemo/Podfile deleted file mode 100644 index b7266ceb5..000000000 --- a/DeepLinkDemo/Podfile +++ /dev/null @@ -1,12 +0,0 @@ -# Uncomment the next line to define a global platform for your project - platform :ios, '12.0' - -target 'DeepLinkDemo' do - # Comment the next line if you don't want to use dynamic frameworks - use_frameworks! - pod 'IQKeyboardManager' - pod 'BranchSDK', :path => './../' - - # Pods for DeepLinkDemo - -end diff --git a/DeepLinkDemo/Podfile.lock b/DeepLinkDemo/Podfile.lock deleted file mode 100644 index e5b283e13..000000000 --- a/DeepLinkDemo/Podfile.lock +++ /dev/null @@ -1,23 +0,0 @@ -PODS: - - BranchSDK (3.4.4) - - IQKeyboardManager (6.5.19) - -DEPENDENCIES: - - BranchSDK (from `./../`) - - IQKeyboardManager - -SPEC REPOS: - trunk: - - IQKeyboardManager - -EXTERNAL SOURCES: - BranchSDK: - :path: "./../" - -SPEC CHECKSUMS: - BranchSDK: 28bec34fb99c53ab8e86b7bf69cc55a4505fe0b3 - IQKeyboardManager: c8665b3396bd0b79402b4c573eac345a31c7d485 - -PODFILE CHECKSUM: 8c4b32f5c4a14defd62bc8a2d1e49cee9e7c2173 - -COCOAPODS: 1.15.2 diff --git a/DeepLinkDemo/README.md b/DeepLinkDemo/README.md deleted file mode 100644 index e95c403f6..000000000 --- a/DeepLinkDemo/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Branch SaaS SDK IOS TestApp - diff --git a/Framework/BranchSDK.h b/Framework/BranchSDK.h index f28711897..6f0f795e9 100644 --- a/Framework/BranchSDK.h +++ b/Framework/BranchSDK.h @@ -58,3 +58,4 @@ FOUNDATION_EXPORT const unsigned char BranchSDKVersionString[]; // BNCLinkCache.h uses BNCLinkData.h #import +#import diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 2e36ecb83..000000000 --- a/Gemfile +++ /dev/null @@ -1,10 +0,0 @@ -source 'https://rubygems.org' - -gem 'cocoapods', '~> 1.9' -gem 'activesupport', '~> 7.0', '<= 7.0.8' -gem 'fastlane', '~> 2.69' -gem 'pattern_patch', '~> 0.5' -gem 'slather' - -plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') -eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/Package.swift b/Package.swift index 0ae916e32..b22166781 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.3 +c// swift-tools-version:5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -9,25 +9,26 @@ let package = Package( .tvOS(.v12), ], products: [ + // Main product that clients will import .library( name: "BranchSDK", - targets: ["BranchSDK"]), + targets: ["BranchSDK", "BranchSwiftSDK"]), ], dependencies: [ + // Add external dependencies here if needed + // .package(url: "https://github.com/google/GoogleUtilities.git", from: "7.0.0"), + // .package(url: "https://github.com/firebase/nanopb.git", from: "2.30909.0"), ], targets: [ + // Main Objective-C SDK target .target( name: "BranchSDK", - path: "Sources", - sources: [ - "BranchSDK/" - ], - resources: [ - .copy("Resources/PrivacyInfo.xcprivacy"), - ], - publicHeadersPath: "BranchSDK/Public/", + dependencies: [], + path: "Sources/BranchSDK", + publicHeadersPath: "Public", cSettings: [ - .headerSearchPath("BranchSDK/Private"), + .headerSearchPath("Private"), + .define("SWIFT_PACKAGE") ], linkerSettings: [ .linkedFramework("CoreServices"), @@ -37,5 +38,14 @@ let package = Package( .linkedFramework("AdServices", .when(platforms: [.iOS])) ] ), + // Swift Concurrency layer (depends on main SDK) + .target( + name: "BranchSwiftSDK", + dependencies: ["BranchSDK"], + path: "Sources/BranchSwiftSDK", + swiftSettings: [ + .define("SWIFT_PACKAGE") + ] + ) ] ) diff --git a/Sources/BranchSDK/BNCRequestFactory.m b/Sources/BranchSDK/BNCRequestFactory.m index 226d77f07..f51276663 100644 --- a/Sources/BranchSDK/BNCRequestFactory.m +++ b/Sources/BranchSDK/BNCRequestFactory.m @@ -32,10 +32,21 @@ #import "BNCAppleReceipt.h" #import "BNCAppGroupsData.h" #import "BNCSKAdNetwork.h" + +// Swift integration - BranchSwiftSDK module is loaded dynamically at runtime +// No compile-time import needed to avoid circular dependencies in SPM +#if !SWIFT_PACKAGE +// Swift bridging header - auto-generated by Xcode when Swift files are present +#if __has_include("BranchSDK/BranchSDK-Swift.h") +#import "BranchSDK/BranchSDK-Swift.h" +#endif +#endif + + #import "BNCReferringURLUtility.h" #import "BNCPasteboard.h" #import "BNCODMInfoCollector.h" -#import "BranchConfigurationController.h" +#import "Private/BranchConfigurationController.h" @interface BNCRequestFactory() @@ -431,7 +442,31 @@ - (void)addLocalURLToOpenJSON:(NSMutableDictionary *)json { // If the client uses a UIPasteControl, force a new open to fetch the payload - (void)addOperationalMetrics:(NSMutableDictionary *)json { - [self safeSetValue:[[BranchConfigurationController sharedInstance] getConfiguration] forKey:BRANCH_REQUEST_KEY_OPERATIONAL_METRICS onDict:json]; + // Try Swift ConfigurationController first, fallback to Objective-C if not available + id configuration = nil; + + // Check if Swift ConfigurationController is available + Class swiftConfigClass = NSClassFromString(@"ConfigurationController"); + if (swiftConfigClass) { + SEL sharedSelector = NSSelectorFromString(@"shared"); + if ([swiftConfigClass respondsToSelector:sharedSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id sharedInstance = [swiftConfigClass performSelector:sharedSelector]; + SEL getConfigSelector = NSSelectorFromString(@"getConfiguration"); + if ([sharedInstance respondsToSelector:getConfigSelector]) { + configuration = [sharedInstance performSelector:getConfigSelector]; + } +#pragma clang diagnostic pop + } + } + + // Fallback to Objective-C implementation + if (!configuration) { + configuration = [[BranchConfigurationController sharedInstance] getConfiguration]; + } + + [self safeSetValue:configuration forKey:BRANCH_REQUEST_KEY_OPERATIONAL_METRICS onDict:json]; } diff --git a/Sources/BranchSDK/BNCServerRequestOperation.m b/Sources/BranchSDK/BNCServerRequestOperation.m new file mode 100644 index 000000000..c06159fbf --- /dev/null +++ b/Sources/BranchSDK/BNCServerRequestOperation.m @@ -0,0 +1,294 @@ +// +// BNCServerRequestOperation.m +// BranchSDK +// +// Created by Nidhi Dixit on 7/22/25. +// Updated: Modern Swift Concurrency bridge +// + +#import "Private/BNCServerRequestOperation.h" +#import "BranchOpenRequest.h" +#import "BranchInstallRequest.h" +#import "BranchEvent.h" +#import "BranchLogger.h" +#import "NSError+Branch.h" +#import "BNCCallbackMap.h" + +// Swift integration - BranchSwiftSDK module is loaded dynamically at runtime +// No compile-time import needed to avoid circular dependencies in SPM +#if !SWIFT_PACKAGE +// Swift bridging header - auto-generated by Xcode when Swift files are present +#if __has_include("BranchSDK/BranchSDK-Swift.h") +#import "BranchSDK/BranchSDK-Swift.h" +#endif +#endif + +@interface BNCServerRequestOperation () +@property (nonatomic, assign, readwrite, getter = isExecuting) BOOL executing; +@property (nonatomic, assign, readwrite, getter = isFinished) BOOL finished; +@property (nonatomic, strong, nullable) id swiftOperation; // BranchRequestOperation for iOS 13+ +@end + +@implementation BNCServerRequestOperation { + BNCServerRequest *_request; +} + +@synthesize executing = _executing; +@synthesize finished = _finished; + +- (instancetype)initWithRequest:(BNCServerRequest *)request { + self = [super init]; + if (self) { + _request = request; + _executing = NO; + _finished = NO; + } + return self; +} + +- (BOOL)isAsynchronous { + return YES; +} + + /*TODO - This can be used for initSafetyCheck and adding dependencies +- (BOOL)isReady { + BOOL ready = [super isReady]; + if (ready) { + + } + return ready; +}*/ + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _executing = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _finished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)start { + // Use modern Swift Concurrency implementation on iOS 13+ + if (@available(iOS 13.0, tvOS 13.0, *)) { + if ([self shouldUseSwiftImplementation]) { + [self startWithSwiftOperation]; + return; + } + } + + // Fallback to legacy Objective-C implementation + [self startObjectiveCOperation]; +} + +#pragma mark - Swift Concurrency Bridge (iOS 13+) + +- (BOOL)shouldUseSwiftImplementation API_AVAILABLE(ios(13.0), tvos(13.0)) { + // Enable Swift implementation by default on supported platforms + // Can be controlled by feature flag if needed + return YES; +} + +- (void)startWithSwiftOperation API_AVAILABLE(ios(13.0), tvos(13.0)) { + // Create Swift operation with modern async/await + // Try module-qualified name first, then unqualified name + Class swiftOperationClass = NSClassFromString(@"BranchRequestOperation"); + if (!swiftOperationClass) { + swiftOperationClass = NSClassFromString(@"Branch.BranchRequestOperation"); + } + if (!swiftOperationClass) { + swiftOperationClass = NSClassFromString(@"BranchSDK.BranchRequestOperation"); + } + if (!swiftOperationClass) { + [[BranchLogger shared] logWarning:@"BranchRequestOperation (Swift) not available. Falling back to Objective-C implementation." error:nil]; + [self startObjectiveCOperation]; + return; + } + + // Initialize Swift operation + SEL initSelector = NSSelectorFromString(@"initWithRequest:serverInterface:branchKey:preferenceHelper:"); + + // Allocate instance first + id swiftInstance = [swiftOperationClass alloc]; + + // Check if instance responds to initializer + if (![swiftInstance respondsToSelector:initSelector]) { + [[BranchLogger shared] logWarning:@"BranchRequestOperation initializer not found. Falling back to Objective-C implementation." error:nil]; + [self startObjectiveCOperation]; + return; + } + + BNCPreferenceHelper *preferenceHelper = self.preferenceHelper ?: [BNCPreferenceHelper sharedInstance]; + + // Create Swift operation using dynamic invocation + NSMethodSignature *signature = [swiftInstance methodSignatureForSelector:initSelector]; + if (!signature) { + [[BranchLogger shared] logWarning:@"Could not get method signature for Swift initializer. Falling back to Objective-C implementation." error:nil]; + [self startObjectiveCOperation]; + return; + } + + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:initSelector]; + [invocation setTarget:swiftInstance]; + [invocation setArgument:&_request atIndex:2]; + [invocation setArgument:&_serverInterface atIndex:3]; + [invocation setArgument:&_branchKey atIndex:4]; + [invocation setArgument:&preferenceHelper atIndex:5]; + [invocation invoke]; + + id __unsafe_unretained tempOperation; + [invocation getReturnValue:&tempOperation]; + self.swiftOperation = tempOperation; + + if (!self.swiftOperation) { + [[BranchLogger shared] logWarning:@"Failed to create Swift operation. Falling back to Objective-C implementation." error:nil]; + [self startObjectiveCOperation]; + return; + } + + [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"Using Swift Concurrency implementation for request: %@", self.request.requestUUID] error:nil]; + + // Forward operation lifecycle to Swift implementation + SEL startSelector = NSSelectorFromString(@"start"); + if ([self.swiftOperation respondsToSelector:startSelector]) { + [self.swiftOperation performSelector:startSelector]; + } + + // Monitor Swift operation state and reflect in Objective-C operation + [self observeSwiftOperation]; +} + +- (void)observeSwiftOperation API_AVAILABLE(ios(13.0), tvos(13.0)) { + // Add KVO observers for Swift operation state + [self.swiftOperation addObserver:self + forKeyPath:@"isExecuting" + options:NSKeyValueObservingOptionNew + context:nil]; + [self.swiftOperation addObserver:self + forKeyPath:@"isFinished" + options:NSKeyValueObservingOptionNew + context:nil]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if (object == self.swiftOperation) { + if ([keyPath isEqualToString:@"isExecuting"]) { + self.executing = [[change objectForKey:NSKeyValueChangeNewKey] boolValue]; + } else if ([keyPath isEqualToString:@"isFinished"]) { + self.finished = [[change objectForKey:NSKeyValueChangeNewKey] boolValue]; + // Clean up observers when finished + [self.swiftOperation removeObserver:self forKeyPath:@"isExecuting"]; + [self.swiftOperation removeObserver:self forKeyPath:@"isFinished"]; + } + } +} + +#pragma mark - Legacy Objective-C Implementation + +- (void)startObjectiveCOperation { + if (self.isCancelled) { + [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"Operation cancelled before starting: %@", self.request.requestUUID] error:nil]; + self.finished = YES; + return; + } + + self.executing = YES; + [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"BNCServerRequestOperation (Objective-C) starting for request: %@", self.request.requestUUID] error:nil]; + + // Check if tracking is disabled + if (Branch.trackingDisabled) { + [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"Tracking disabled. Skipping request: %@", self.request.requestUUID] error:nil]; + self.executing = NO; + self.finished = YES; + return; + } + + BNCPreferenceHelper *preferenceHelper = self.preferenceHelper ?: [BNCPreferenceHelper sharedInstance]; + + // Session validation for requests + if (!([self.request isKindOfClass:[BranchInstallRequest class]])) { + if (!preferenceHelper.randomizedBundleToken) { + [[BranchLogger shared] logError:[NSString stringWithFormat:@"User session not initialized (missing bundle token). Dropping request: %@", self.request.requestUUID] error:nil]; + BNCPerformBlockOnMainThreadSync(^{ + [self.request processResponse:nil error:[NSError branchErrorWithCode:BNCInitError]]; + }); + self.executing = NO; + self.finished = YES; + return; + } + } else if (!([self.request isKindOfClass:[BranchOpenRequest class]])) { + if (!preferenceHelper.randomizedDeviceToken || !preferenceHelper.sessionID || !preferenceHelper.randomizedBundleToken) { + [[BranchLogger shared] logError:[NSString stringWithFormat:@"Missing session items (device token or session ID or bundle token). Dropping request: %@", self.request.requestUUID] error:nil]; + BNCPerformBlockOnMainThreadSync(^{ + [self.request processResponse:nil error:[NSError branchErrorWithCode:BNCInitError]]; + }); + self.executing = NO; + self.finished = YES; + return; + } + } + + // TODO: Handle specific `BranchOpenRequest` lock + // `waitForOpenResponseLock` will block the current thread (the NSOperation's background thread) + // until the global open response lock is released. This ensures proper sequencing + // if another init session is in progress. + /* if ([self.request isKindOfClass:[BranchOpenRequest class]]) { + [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"BranchOpenRequest detected. Waiting for open response lock for %@", self.request.requestUUID] error:nil]; + [BranchOpenRequest waitForOpenResponseLock]; + }*/ + + [self.request makeRequest:self.serverInterface + key:self.branchKey + callback:^(BNCServerResponse *response, NSError *error) { + BNCPerformBlockOnMainThreadSync(^{ + [self.request processResponse:response error:error]; + if ([self.request isKindOfClass:[BranchEventRequest class]]) { + [[BNCCallbackMap shared] callCompletionForRequest:self.request withSuccessStatus:(error == nil) error:error]; + } + }); + [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"BNCServerRequestOperation (Objective-C) finished for request: %@", self.request.requestUUID] error:nil]; + self.executing = NO; + self.finished = YES; + + }]; +} + +- (void)cancel { + [super cancel]; // Sets `isCancelled` to YES + + // Forward cancellation to Swift operation if active + if (@available(iOS 13.0, tvOS 13.0, *)) { + if (self.swiftOperation) { + SEL cancelSelector = NSSelectorFromString(@"cancel"); + if ([self.swiftOperation respondsToSelector:cancelSelector]) { + [self.swiftOperation performSelector:cancelSelector]; + } + } + } + + if (!self.isExecuting) { + self.finished = YES; + [[BranchLogger shared] logWarning:[NSString stringWithFormat:@"BNCServerRequestOperation cancelled before execution for request: %@", self.request.requestUUID] error:nil]; + } else { + [[BranchLogger shared] logWarning:[NSString stringWithFormat:@"BNCServerRequestOperation cancelled during execution for request: %@", self.request.requestUUID] error:nil]; + } +} + +static inline void BNCPerformBlockOnMainThreadSync(dispatch_block_t block) { + if (block) { + if ([NSThread isMainThread]) { + block(); + } else { + dispatch_sync(dispatch_get_main_queue(), block); + } + } +} + +@end diff --git a/Sources/BranchSDK/BNCServerRequestQueue.m b/Sources/BranchSDK/BNCServerRequestQueue.m index c518fccce..097012ea0 100755 --- a/Sources/BranchSDK/BNCServerRequestQueue.m +++ b/Sources/BranchSDK/BNCServerRequestQueue.m @@ -9,143 +9,116 @@ #import "BNCServerRequestQueue.h" #import "BNCPreferenceHelper.h" - -// Analytics requests #import "BranchInstallRequest.h" #import "BranchOpenRequest.h" #import "BranchEvent.h" - #import "BranchLogger.h" +#import "Private/BNCServerRequestOperation.h" +#import "Branch.h" -@interface BNCServerRequestQueue() -@property (strong, nonatomic) NSMutableArray *queue; -@end +@interface BNCServerRequestQueue () +@property (strong, nonatomic) NSOperationQueue *operationQueue; +@property (strong, nonatomic) BNCServerInterface *serverInterface; +@property (copy, nonatomic) NSString *branchKey; +@property (strong, nonatomic) BNCPreferenceHelper *preferenceHelper; + +@end + @implementation BNCServerRequestQueue - (instancetype)init { self = [super init]; - if (!self) return self; - - self.queue = [NSMutableArray new]; + if (self) { + self.operationQueue = [NSOperationQueue new]; + // Set maxConcurrentOperationCount to 1 for serial execution + self.operationQueue.maxConcurrentOperationCount = 1; + self.operationQueue.name = @"com.branch.sdk.serverRequestQueue"; + } return self; } -- (void)enqueue:(BNCServerRequest *)request { - @synchronized (self) { - if (request) { - [self.queue addObject:request]; - } - } +- (void)configureWithServerInterface:(BNCServerInterface *)serverInterface + branchKey:(NSString *)branchKey + preferenceHelper:(BNCPreferenceHelper *)preferenceHelper { + self.serverInterface = serverInterface; + self.branchKey = branchKey; + self.preferenceHelper = preferenceHelper; } -- (void)insert:(BNCServerRequest *)request at:(NSUInteger)index { - @synchronized (self) { - if (index > self.queue.count) { - [[BranchLogger shared] logError:@"Invalid queue operation: index out of bound!" error:nil]; - return; - } - if (request) { - [self.queue insertObject:request atIndex:index]; - } - } +- (void)enqueue:(BNCServerRequest *)request{ + [self enqueue:request withPriority:NSOperationQueuePriorityNormal]; } -- (BNCServerRequest *)dequeue { - @synchronized (self) { - BNCServerRequest *request = nil; - if (self.queue.count > 0) { - request = [self.queue objectAtIndex:0]; - [self.queue removeObjectAtIndex:0]; - } - return request; +- (void)enqueue:(BNCServerRequest *)request withPriority:(NSOperationQueuePriority)priority{ + if (!request) { + [[BranchLogger shared] logError:@"Attempted to enqueue nil request." error:nil]; + return; } -} + + BNCServerRequestOperation *operation = [[BNCServerRequestOperation alloc] initWithRequest:request]; + + operation.serverInterface = self.serverInterface; + operation.branchKey = self.branchKey; + operation.preferenceHelper = self.preferenceHelper; + operation.queuePriority = priority; -- (BNCServerRequest *)removeAt:(NSUInteger)index { - @synchronized (self) { - BNCServerRequest *request = nil; - if (index >= self.queue.count) { - [[BranchLogger shared] logError:@"Invalid queue operation: index out of bound!" error:nil]; - return nil; - } - request = [self.queue objectAtIndex:index]; - [self.queue removeObjectAtIndex:index]; - return request; - } -} + [self.operationQueue addOperation:operation]; -- (void)remove:(BNCServerRequest *)request { - @synchronized (self) { - [self.queue removeObject:request]; - } -} - -- (BNCServerRequest *)peek { - @synchronized (self) { - return [self peekAt:0]; - } -} - -- (BNCServerRequest *)peekAt:(NSUInteger)index { - @synchronized (self) { - if (index >= self.queue.count) { - [[BranchLogger shared] logError:@"Invalid queue operation: index out of bound!" error:nil]; - return nil; - } - BNCServerRequest *request = nil; - request = [self.queue objectAtIndex:index]; - return request; - } + [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"Enqueued request: %@. Current queue depth: %lu", request.requestUUID, (unsigned long)self.operationQueue.operationCount] error:nil]; } - (NSInteger)queueDepth { - @synchronized (self) { - return (NSInteger) self.queue.count; - } -} - -- (NSString *)description { - @synchronized(self) { - return [self.queue description]; - } + return (NSInteger) self.operationQueue.operationCount; } + - (void)clearQueue { - @synchronized (self) { - [self.queue removeAllObjects]; - } + [[BranchLogger shared] logDebug:@"Clearing all pending operations from the queue." error:nil]; + [self.operationQueue cancelAllOperations]; } +// These methods now need to iterate through the operations in the NSOperationQueue. - (BOOL)containsInstallOrOpen { - @synchronized (self) { - for (NSUInteger i = 0; i < self.queue.count; i++) { - BNCServerRequest *req = [self.queue objectAtIndex:i]; - // Install extends open, so only need to check open. - if ([req isKindOfClass:[BranchOpenRequest class]]) { + for (NSOperation *op in self.operationQueue.operations) { + if ([op isKindOfClass:[BNCServerRequestOperation class]]) { + BNCServerRequestOperation *requestOp = (BNCServerRequestOperation *)op; + if ([requestOp.request isKindOfClass:[BranchOpenRequest class]]) { return YES; } } - return NO; } + return NO; } - (BranchOpenRequest *)findExistingInstallOrOpen { - @synchronized (self) { - for (NSUInteger i = 0; i < self.queue.count; i++) { - BNCServerRequest *request = [self.queue objectAtIndex:i]; - - // Install subclasses open, so only need to check open - // Request should not be the one added from archived queue - if ([request isKindOfClass:[BranchOpenRequest class]] && !((BranchOpenRequest *)request).isFromArchivedQueue) { - return (BranchOpenRequest *)request; + for (NSOperation *op in self.operationQueue.operations) { + if ([op isKindOfClass:[BNCServerRequestOperation class]]) { + BNCServerRequestOperation *requestOp = (BNCServerRequestOperation *)op; + BNCServerRequest *request = requestOp.request; + if ([request isKindOfClass:[BranchOpenRequest class]]) { + BranchOpenRequest *openRequest = (BranchOpenRequest *)request; + return openRequest; } } - return nil; } + return nil; } +- (NSString *)description { + NSMutableArray *requestUUIDs = [NSMutableArray array]; + for (NSOperation *op in self.operationQueue.operations) { + if ([op isKindOfClass:[BNCServerRequestOperation class]]) { + if (!op.isFinished && !op.isCancelled) { + [requestUUIDs addObject:((BNCServerRequestOperation *)op).request.requestUUID]; + } else { + [requestUUIDs addObject:[NSString stringWithFormat:@"(Completed/Cancelled: %@)", ((BNCServerRequestOperation *)op).request.requestUUID]]; + } + } + } + return [NSString stringWithFormat:@" Operations (%ld): %@", self, (long)self.queueDepth, [requestUUIDs description]]; +} + (instancetype)getInstance { static BNCServerRequestQueue *sharedQueue = nil; diff --git a/Sources/BranchSDK/Branch-Bridging-Header.h b/Sources/BranchSDK/Branch-Bridging-Header.h new file mode 100644 index 000000000..2f5344502 --- /dev/null +++ b/Sources/BranchSDK/Branch-Bridging-Header.h @@ -0,0 +1,14 @@ +// +// Branch-Bridging-Header.h +// Branch SDK +// +// Bridging header to expose Objective-C types to Swift within the Branch target +// + +#import "Public/Branch.h" +#import "Public/BNCServerRequest.h" +#import "Public/BNCServerInterface.h" +#import "Public/BNCServerResponse.h" +#import "Public/BNCPreferenceHelper.h" +#import "Public/BranchLogger.h" +#import "Private/NSError+Branch.h" diff --git a/Sources/BranchSDK/Branch.m b/Sources/BranchSDK/Branch.m index e0977f8df..32ba64178 100644 --- a/Sources/BranchSDK/Branch.m +++ b/Sources/BranchSDK/Branch.m @@ -45,7 +45,18 @@ #import "BNCServerAPI.h" #import "BranchPluginSupport.h" #import "BranchLogger.h" -#import "BranchConfigurationController.h" +#import "Private/BranchConfigurationController.h" + + + +// Swift integration - BranchSwiftSDK module is loaded dynamically at runtime +// No compile-time import needed to avoid circular dependencies in SPM +#if !SWIFT_PACKAGE +// Swift bridging header - auto-generated by Xcode when Swift files are present +#if __has_include("BranchSDK-Swift.h") +#import "BranchSDK-Swift.h" +#endif +#endif #if !TARGET_OS_TV #import "BNCUserAgentCollector.h" @@ -249,7 +260,7 @@ - (id)initWithInterface:(BNCServerInterface *)interface BranchJsonConfig *config = BranchJsonConfig.instance; self.deferInitForPluginRuntime = config.deferInitForPluginRuntime; [BranchConfigurationController sharedInstance].deferInitForPluginRuntime = self.deferInitForPluginRuntime; - + if (config.apiUrl) { [Branch setAPIUrl:config.apiUrl]; } @@ -276,6 +287,7 @@ - (id)initWithInterface:(BNCServerInterface *)interface } } + [self.requestQueue configureWithServerInterface:_serverInterface branchKey:key preferenceHelper:preferenceHelper]; return self; } @@ -1144,7 +1156,6 @@ - (void)sendServerRequest:(BNCServerRequest*)request { [self initSafetyCheck]; dispatch_async(self.isolationQueue, ^(){ [self.requestQueue enqueue:request]; - [self processNextQueueItem]; }); } @@ -1344,7 +1355,6 @@ - (void)getSpotlightUrlWithParams:(NSDictionary *)params callback:(callbackWithP dispatch_async(self.isolationQueue, ^(){ BranchSpotlightUrlRequest *req = [[BranchSpotlightUrlRequest alloc] initWithParams:params callback:callback]; [self.requestQueue enqueue:req]; - [self processNextQueueItem]; }); } @@ -1640,7 +1650,6 @@ - (void)generateShortUrl:(NSArray *)tags linkCache:self.linkCache callback:callback]; [self.requestQueue enqueue:req]; - [self processNextQueueItem]; }); } @@ -1869,14 +1878,6 @@ - (void)setNetworkCount:(NSInteger)networkCount { } } -- (void)insertRequestAtFront:(BNCServerRequest *)req { - if (self.networkCount == 0) { - [self.requestQueue insert:req at:0]; - } else { - [self.requestQueue insert:req at:1]; - } -} - static inline void BNCPerformBlockOnMainThreadSync(dispatch_block_t block) { if (block) { if ([NSThread isMainThread]) { @@ -1896,7 +1897,7 @@ - (void) processRequest:(BNCServerRequest*)req error:(NSError*)error { // If the request was successful, or was a bad user request, continue processing. - if (!error || + /* if (!error || error.code == BNCTrackingDisabledError || error.code == BNCBadRequestError || error.code == BNCDuplicateResourceError) { @@ -1950,7 +1951,7 @@ - (void) processRequest:(BNCServerRequest*)req } }); } - } + }*/ } - (BOOL)isReplayableRequest:(BNCServerRequest *)request { @@ -1974,6 +1975,7 @@ - (BOOL)isReplayableRequest:(BNCServerRequest *)request { } - (void)processNextQueueItem { + /* dispatch_semaphore_wait(self.processing_sema, DISPATCH_TIME_FOREVER); [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"Processing next queue item. Network Count: %ld. Queue depth: %ld", (long)self.networkCount, (long)self.requestQueue.queueDepth] error:nil]; @@ -2021,7 +2023,7 @@ - (void)processNextQueueItem { } else { dispatch_semaphore_signal(self.processing_sema); - } + }*/ } - (void)clearNetworkQueue { @@ -2160,7 +2162,7 @@ - (void)initializeSessionAndCallCallback:(BOOL)callCallback sceneIdentifier:(NSS req.callback = initSessionCallback; req.urlString = urlString; - [self.requestQueue insert:req at:0]; + [self.requestQueue enqueue:req withPriority:NSOperationQueuePriorityHigh]; NSString *message = [NSString stringWithFormat:@"Request %@ callback %@ link %@", req, req.callback, req.urlString]; [[BranchLogger shared] logDebug:message error:nil]; @@ -2174,7 +2176,7 @@ - (void)initializeSessionAndCallCallback:(BOOL)callCallback sceneIdentifier:(NSS req.urlString = urlString; // put it behind the one that's already on queue - [self.requestQueue insert:req at:1]; + [self.requestQueue enqueue:req withPriority:NSOperationQueuePriorityHigh]; [[BranchLogger shared] logDebug:@"Link resolution request" error:nil]; NSString *message = [NSString stringWithFormat:@"Request %@ callback %@ link %@", req, req.callback, req.urlString]; @@ -2184,8 +2186,6 @@ - (void)initializeSessionAndCallCallback:(BOOL)callCallback sceneIdentifier:(NSS self.initializationStatus = BNCInitStatusInitializing; [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"initializationStatus %ld", self.initializationStatus] error:nil]; - - [self processNextQueueItem]; }); } } diff --git a/Sources/BranchSDK/BranchConfigurationController.m b/Sources/BranchSDK/BranchConfigurationController.m index e9a0f35dc..e2d16c29c 100644 --- a/Sources/BranchSDK/BranchConfigurationController.m +++ b/Sources/BranchSDK/BranchConfigurationController.m @@ -5,7 +5,7 @@ // Created by Nidhi Dixit on 6/2/25. // -#import "BranchConfigurationController.h" +#import "Private/BranchConfigurationController.h" #import "BNCPreferenceHelper.h" #import "BranchLogger.h" #import "BranchConstants.h" diff --git a/Sources/BranchSDK/Private/BNCServerRequestOperation.h b/Sources/BranchSDK/Private/BNCServerRequestOperation.h new file mode 100644 index 000000000..41bc1e074 --- /dev/null +++ b/Sources/BranchSDK/Private/BNCServerRequestOperation.h @@ -0,0 +1,25 @@ +// +// BNCServerRequestOperation.h +// BranchSDK +// +// Created by Nidhi Dixit on 7/22/25. +// + + +#import +#import "BNCServerRequest.h" +#import "BNCCallbacks.h" + + +@interface BNCServerRequestOperation : NSOperation + +@property (nonatomic, strong, readonly) BNCServerRequest *request; + +@property (nonatomic, strong) BNCServerInterface *serverInterface; +@property (nonatomic, copy) NSString *branchKey; +@property (nonatomic, strong) BNCPreferenceHelper *preferenceHelper; + +- (instancetype)initWithRequest:(BNCServerRequest *)request NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; // Prevent calling default init + +@end diff --git a/Sources/BranchSDK/Private/BNCConfig.h b/Sources/BranchSDK/Public/BNCConfig.h similarity index 100% rename from Sources/BranchSDK/Private/BNCConfig.h rename to Sources/BranchSDK/Public/BNCConfig.h diff --git a/Sources/BranchSDK/Public/BNCServerRequestQueue.h b/Sources/BranchSDK/Public/BNCServerRequestQueue.h index 1c9d9391f..81d85192d 100755 --- a/Sources/BranchSDK/Public/BNCServerRequestQueue.h +++ b/Sources/BranchSDK/Public/BNCServerRequestQueue.h @@ -7,23 +7,22 @@ // #import "BNCServerRequest.h" +#import +#import "BNCServerRequest.h" + @class BranchOpenRequest; @interface BNCServerRequestQueue : NSObject ++ (instancetype)getInstance; + +- (void)configureWithServerInterface:(BNCServerInterface *)serverInterface + branchKey:(NSString *)branchKey + preferenceHelper:(BNCPreferenceHelper *)preferenceHelper; - (void)enqueue:(BNCServerRequest *)request; -- (BNCServerRequest *)dequeue; -- (BNCServerRequest *)peek; -- (BNCServerRequest *)peekAt:(NSUInteger)index; -- (void)insert:(BNCServerRequest *)request at:(NSUInteger)index; -- (BNCServerRequest *)removeAt:(NSUInteger)index; -- (void)remove:(BNCServerRequest *)request; +- (void)enqueue:(BNCServerRequest *)request withPriority:(NSOperationQueuePriority)priority; - (void)clearQueue; -- (NSInteger)queueDepth; - - (BOOL)containsInstallOrOpen; - - (BranchOpenRequest *)findExistingInstallOrOpen; -+ (id)getInstance; @end diff --git a/Sources/BranchSDK/Private/BranchConstants.h b/Sources/BranchSDK/Public/BranchConstants.h similarity index 100% rename from Sources/BranchSDK/Private/BranchConstants.h rename to Sources/BranchSDK/Public/BranchConstants.h diff --git a/Sources/BranchSDK/Public/BranchSDK.h b/Sources/BranchSDK/Public/BranchSDK.h index e4914c80a..4a54d863b 100644 --- a/Sources/BranchSDK/Public/BranchSDK.h +++ b/Sources/BranchSDK/Public/BranchSDK.h @@ -19,6 +19,7 @@ FOUNDATION_EXPORT const unsigned char BranchSDKVersionString[]; #import "BranchScene.h" #import "BranchDelegate.h" +#import "BNCConfig.h" #import "BranchEvent.h" #import "BranchLinkProperties.h" @@ -58,3 +59,5 @@ FOUNDATION_EXPORT const unsigned char BranchSDKVersionString[]; // BNCLinkCache.h uses BNCLinkData.h #import "BNCLinkData.h" + +#import "BranchConstants.h" diff --git a/Sources/BranchSDK_ObjC/BranchConstants.m b/Sources/BranchSDK_ObjC/BranchConstants.m new file mode 100644 index 000000000..d5ee04498 --- /dev/null +++ b/Sources/BranchSDK_ObjC/BranchConstants.m @@ -0,0 +1,201 @@ +// +// BranchConstants.m +// Branch-TestBed +// +// Created by Graham Mueller on 6/10/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import "BranchConstants.h" + +NSString * const BRANCH_REQUEST_KEY_RANDOMIZED_BUNDLE_TOKEN = @"randomized_bundle_token"; +NSString * const BRANCH_REQUEST_KEY_DEVELOPER_IDENTITY = @"identity"; +NSString * const BRANCH_REQUEST_KEY_RANDOMIZED_DEVICE_TOKEN = @"randomized_device_token"; +NSString * const BRANCH_REQUEST_KEY_SESSION_ID = @"session_id"; +NSString * const BRANCH_REQUEST_KEY_ACTION = @"event"; +NSString * const BRANCH_REQUEST_KEY_STATE = @"metadata"; +NSString * const BRANCH_REQUEST_KEY_BUCKET = @"bucket"; +NSString * const BRANCH_REQUEST_KEY_AMOUNT = @"amount"; +NSString * const BRANCH_REQUEST_KEY_LENGTH = @"length"; +NSString * const BRANCH_REQUEST_KEY_DIRECTION = @"direction"; +NSString * const BRANCH_REQUEST_KEY_STARTING_TRANSACTION_ID = @"begin_after_id"; +NSString * const BRANCH_REQUEST_KEY_URL_SOURCE = @"source"; +NSString * const BRANCH_REQUEST_KEY_URL_TAGS = @"tags"; +NSString * const BRANCH_REQUEST_KEY_URL_LINK_TYPE = @"type"; +NSString * const BRANCH_REQUEST_KEY_URL_ALIAS = @"alias"; +NSString * const BRANCH_REQUEST_KEY_URL_CHANNEL = @"channel"; +NSString * const BRANCH_REQUEST_KEY_URL_FEATURE = @"feature"; +NSString * const BRANCH_REQUEST_KEY_URL_STAGE = @"stage"; +NSString * const BRANCH_REQUEST_KEY_URL_CAMPAIGN = @"campaign"; +NSString * const BRANCH_REQUEST_KEY_URL_DURATION = @"duration"; +NSString * const BRANCH_REQUEST_KEY_URL_DATA = @"data"; +NSString * const BRANCH_REQUEST_KEY_URL_IGNORE_UA_STRING = @"ignore_ua_string"; +NSString * const BRANCH_REQUEST_KEY_HARDWARE_ID = @"hardware_id"; +NSString * const BRANCH_REQUEST_KEY_HARDWARE_ID_TYPE = @"hardware_id_type"; +NSString * const BRANCH_REQUEST_KEY_IS_HARDWARE_ID_REAL = @"is_hardware_id_real"; +NSString * const BRANCH_REQUEST_KEY_IOS_VENDOR_ID = @"ios_vendor_id"; +NSString * const BRANCH_REQUEST_KEY_OPTED_IN_STATUS = @"opted_in_status"; +NSString * const BRANCH_REQUEST_KEY_FIRST_OPT_IN = @"first_opt_in"; +NSString * const BRANCH_REQUEST_KEY_DEBUG = @"debug"; +NSString * const BRANCH_REQUEST_KEY_BUNDLE_ID = @"ios_bundle_id"; +NSString * const BRANCH_REQUEST_KEY_TEAM_ID = @"ios_team_id"; +NSString * const BRANCH_REQUEST_KEY_APP_VERSION = @"app_version"; +NSString * const BRANCH_REQUEST_KEY_OS = @"os"; +NSString * const BRANCH_REQUEST_KEY_OS_VERSION = @"os_version"; +NSString * const BRANCH_REQUEST_KEY_URI_SCHEME = @"uri_scheme"; +NSString * const BRANCH_REQUEST_KEY_LINK_IDENTIFIER = @"link_identifier"; +NSString * const BRANCH_REQUEST_KEY_SPOTLIGHT_IDENTIFIER = @"spotlight_identifier"; +NSString * const BRANCH_REQUEST_KEY_UNIVERSAL_LINK_URL = @"universal_link_url"; +NSString * const BRANCH_REQUEST_KEY_LOCAL_URL = @"local_url"; +NSString * const BRANCH_REQUEST_KEY_INITIAL_REFERRER = @"initial_referrer"; +NSString * const BRANCH_REQUEST_KEY_BRAND = @"brand"; +NSString * const BRANCH_REQUEST_KEY_MODEL = @"model"; +NSString * const BRANCH_REQUEST_KEY_SCREEN_WIDTH = @"screen_width"; +NSString * const BRANCH_REQUEST_KEY_SCREEN_HEIGHT = @"screen_height"; +NSString * const BRANCH_REQUEST_KEY_IS_SIMULATOR = @"is_simulator"; +NSString * const BRANCH_REQUEST_KEY_LOG = @"log"; +NSString * const BRANCH_REQUEST_KEY_INSTRUMENTATION = @"instrumentation"; +NSString * const BRANCH_REQUEST_KEY_APPLE_RECEIPT = @"apple_receipt"; +NSString * const BRANCH_REQUEST_KEY_APPLE_TESTFLIGHT = @"apple_testflight"; + +NSString * const BRANCH_REQUEST_KEY_APP_CLIP_BUNDLE_ID = @"app_clip_bundle_id"; +NSString * const BRANCH_REQUEST_KEY_LATEST_APP_CLIP_INSTALL_TIME = @"latest_app_clip_time"; +NSString * const BRANCH_REQUEST_KEY_APP_CLIP_RANDOMIZED_DEVICE_TOKEN = @"app_clip_randomized_device_token"; +NSString * const BRANCH_REQUEST_KEY_APP_CLIP_RANDOMIZED_BUNDLE_TOKEN = @"app_clip_randomized_bundle_token"; + +NSString * const BRANCH_REQUEST_KEY_PARTNER_PARAMETERS = @"partner_data"; + +NSString * const BRANCH_REQUEST_METADATA_KEY_SCANTIME_WINDOW = @"skan_time_window"; +NSString * const BRANCH_REQUEST_KEY_REFERRER_GBRAID = @"gbraid"; +NSString * const BRANCH_REQUEST_KEY_REFERRER_GBRAID_TIMESTAMP = @"gbraid_timestamp"; +NSString * const BRANCH_REQUEST_KEY_IS_DEEPLINK_GBRAID = @"is_deeplink_gbraid"; +NSString * const BRANCH_REQUEST_KEY_GCLID = @"gclid"; +NSString * const BRANCH_REQUEST_KEY_ODM_INFO = @"odm_info"; +NSString * const BRANCH_REQUEST_KEY_ODM_FIRST_OPEN_TIMESTAMP = @"odm_first_open_timestamp"; +NSString * const BRANCH_REQUEST_KEY_META_CAMPAIGN_IDS = @"meta_campaign_ids"; +NSString * const BRANCH_URL_QUERY_PARAMETERS_NAME_KEY = @"name"; +NSString * const BRANCH_URL_QUERY_PARAMETERS_VALUE_KEY = @"value"; +NSString * const BRANCH_URL_QUERY_PARAMETERS_TIMESTAMP_KEY = @"timestamp"; +NSString * const BRANCH_URL_QUERY_PARAMETERS_IS_DEEPLINK_KEY = @"isDeepLink"; +NSString * const BRANCH_URL_QUERY_PARAMETERS_VALIDITY_WINDOW_KEY = @"validityWindow"; +NSString * const BRANCH_REQUEST_KEY_SCCID = @"sccid"; +NSString * const BRANCH_REQUEST_KEY_WEB_LINK_CONTEXT = @"web_link_context"; +NSString * const BRANCH_REQUEST_KEY_UX_TYPE = @"ux_type"; +NSString * const BRANCH_REQUEST_KEY_URL_LOAD_MS = @"url_load_ms"; + +NSString * const BRANCH_REQUEST_ENDPOINT_APP_LINK_SETTINGS = @"app-link-settings"; +NSString * const BRANCH_REQUEST_ENDPOINT_USER_COMPLETED_ACTION = @"event"; +NSString * const BRANCH_REQUEST_ENDPOINT_GET_SHORT_URL = @"url"; +NSString * const BRANCH_REQUEST_ENDPOINT_OPEN = @"open"; +NSString * const BRANCH_REQUEST_ENDPOINT_INSTALL = @"install"; +NSString * const BRANCH_REQUEST_ENDPOINT_REGISTER_VIEW = @"register-view"; +NSString * const BRANCH_REQUEST_ENDPOINT_LATD = @"cpid/latd"; + +NSString * const BRANCH_RESPONSE_KEY_RANDOMIZED_BUNDLE_TOKEN = @"randomized_bundle_token"; +NSString * const BRANCH_RESPONSE_KEY_SESSION_ID = @"session_id"; +NSString * const BRANCH_RESPONSE_KEY_USER_URL = @"link"; +NSString * const BRANCH_RESPONSE_KEY_INSTALL_PARAMS = @"referring_data"; +NSString * const BRANCH_RESPONSE_KEY_REFERRER = @"referrer"; +NSString * const BRANCH_RESPONSE_KEY_REFERREE = @"referree"; +NSString * const BRANCH_RESPONSE_KEY_URL = @"url"; +NSString * const BRANCH_RESPONSE_KEY_SPOTLIGHT_IDENTIFIER = @"spotlight_identifier"; +NSString * const BRANCH_RESPONSE_KEY_DEVELOPER_IDENTITY = @"identity"; +NSString * const BRANCH_RESPONSE_KEY_RANDOMIZED_DEVICE_TOKEN = @"randomized_device_token"; +NSString * const BRANCH_RESPONSE_KEY_SESSION_DATA = @"data"; +NSString * const BRANCH_RESPONSE_KEY_CLICKED_BRANCH_LINK = @"+clicked_branch_link"; +NSString * const BRANCH_RESPONSE_KEY_BRANCH_VIEW_DATA = @"branch_view_data"; +NSString * const BRANCH_RESPONSE_KEY_BRANCH_REFERRING_LINK = @"~referring_link"; +NSString * const BRANCH_RESPONSE_KEY_INVOKE_REGISTER_APP = @"invoke_register_app"; +NSString * const BRANCH_RESPONSE_KEY_UPDATE_CONVERSION_VALUE = @"update_conversion_value"; +NSString * const BRANCH_RESPONSE_KEY_COARSE_KEY = @"coarse_key"; +NSString * const BRANCH_RESPONSE_KEY_UPDATE_IS_LOCKED = @"locked"; +NSString * const BRANCH_RESPONSE_KEY_ASCENDING_ONLY = @"ascending_only"; +NSString * const BRANCH_RESPONSE_KEY_INVOKE_FEATURES = @"invoke_features"; +NSString * const BRANCH_RESPONSE_KEY_ENHANCED_WEB_LINK_UX = @"enhanced_web_link_ux"; +NSString * const BRANCH_RESPONSE_KEY_WEB_LINK_REDIRECT_URL = @"web_link_redirect_url"; + +NSString * const BRANCH_LINK_DATA_KEY_OG_TITLE = @"$og_title"; +NSString * const BRANCH_LINK_DATA_KEY_OG_DESCRIPTION = @"$og_description"; +NSString * const BRANCH_LINK_DATA_KEY_OG_IMAGE_URL = @"$og_image_url"; +NSString * const BRANCH_LINK_DATA_KEY_TITLE = @"+spotlight_title"; +NSString * const BRANCH_LINK_DATA_KEY_DESCRIPTION = @"+spotlight_description"; +NSString * const BRANCH_LINK_DATA_KEY_PUBLICLY_INDEXABLE = @"$publicly_indexable"; +NSString * const BRANCH_LINK_DATA_KEY_LOCALLY_INDEXABLE = @"$locally_indexable"; + +NSString * const BRANCH_LINK_DATA_KEY_TYPE = @"+spotlight_type"; +NSString * const BRANCH_LINK_DATA_KEY_THUMBNAIL_URL = @"+spotlight_thumbnail_url"; +NSString * const BRANCH_LINK_DATA_KEY_KEYWORDS = @"$keywords"; +NSString * const BRANCH_LINK_DATA_KEY_CANONICAL_IDENTIFIER = @"$canonical_identifier"; +NSString * const BRANCH_LINK_DATA_KEY_CANONICAL_URL = @"$canonical_url"; +NSString * const BRANCH_LINK_DATA_KEY_CONTENT_EXPIRATION_DATE = @"$exp_date"; +NSString * const BRANCH_LINK_DATA_KEY_CONTENT_TYPE = @"$content_type"; +NSString * const BRANCH_LINK_DATA_KEY_EMAIL_SUBJECT = @"$email_subject"; +NSString * const BRANCH_LINK_DATA_KEY_EMAIL_HTML_HEADER = @"$email_html_header"; +NSString * const BRANCH_LINK_DATA_KEY_EMAIL_HTML_FOOTER = @"$email_html_footer"; +NSString * const BRANCH_LINK_DATA_KEY_EMAIL_HTML_LINK_TEXT = @"$email_html_link_text"; + +NSString * const BRANCH_SPOTLIGHT_PREFIX = @"io.branch.link.v1"; + +NSString * const BRANCH_MANIFEST_VERSION_KEY = @"mv"; +NSString * const BRANCH_HASH_MODE_KEY = @"h"; +NSString * const BRANCH_MANIFEST_KEY = @"m"; +NSString * const BRANCH_PATH_KEY = @"p"; +NSString * const BRANCH_FILTERED_KEYS = @"ck"; +NSString * const BRANCH_MAX_TEXT_LEN_KEY = @"mtl"; +NSString * const BRANCH_MAX_VIEW_HISTORY_LENGTH = @"mhl"; +NSString * const BRANCH_MAX_PACKET_SIZE_KEY = @"mps"; +NSString * const BRANCH_CONTENT_DISCOVER_KEY = @"cd"; +NSString * const BRANCH_BUNDLE_IDENTIFIER = @"pn"; +NSString * const BRANCH_TIME_STAMP_KEY = @"ts"; +NSString * const BRANCH_TIME_STAMP_CLOSE_KEY = @"tc"; +NSString * const BRANCH_NAV_PATH_KEY = @"n"; +NSString * const BRANCH_REFERRAL_LINK_KEY = @"rl"; +NSString * const BRANCH_CONTENT_LINK_KEY = @"cl"; +NSString * const BRANCH_CONTENT_META_DATA_KEY = @"cm"; +NSString * const BRANCH_VIEW_KEY = @"v"; +NSString * const BRANCH_CONTENT_DATA_KEY = @"cd"; +NSString * const BRANCH_CONTENT_KEYS_KEY = @"ck"; +NSString * const BRANCH_PACKAGE_NAME_KEY = @"p"; +NSString * const BRANCH_ENTITIES_KEY = @"e"; + +NSString * const BRANCH_REQUEST_KEY_APPLE_ATTRIBUTION_TOKEN = @"apple_attribution_token"; + +NSString * const BRANCH_CRASHLYTICS_SDK_VERSION_KEY = @"io.branch.sdk.version"; +NSString * const BRANCH_CRASHLYTICS_LOW_MEMORY_KEY = @"io.branch.device.lowmemory"; + +NSString * const BRANCH_REQUEST_KEY_EXTERNAL_INTENT_URI = @"external_intent_uri"; + +NSString * const BRANCH_REQUEST_KEY_SKAN_POSTBACK_INDEX = @"skan_postback_index"; +NSString * const BRANCH_REQUEST_KEY_VALUE_POSTBACK_SEQUENCE_INDEX_0 = @"postback-sequence-index-0"; +NSString * const BRANCH_REQUEST_KEY_VALUE_POSTBACK_SEQUENCE_INDEX_1 = @"postback-sequence-index-1"; +NSString * const BRANCH_REQUEST_KEY_VALUE_POSTBACK_SEQUENCE_INDEX_2 = @"postback-sequence-index-2"; + +NSString * const BRANCH_REQUEST_KEY_DMA_EEA = @"dma_eea"; +NSString * const BRANCH_REQUEST_KEY_DMA_AD_PEROSALIZATION = @"dma_ad_personalization"; +NSString * const BRANCH_REQUEST_KEY_DMA_AD_USER_DATA = @"dma_ad_user_data"; + +NSString * const BRANCH_REQUEST_KEY_CPP_LEVEL = @"cpp_level"; + +NSString * const BRANCH_REQUEST_KEY_REQUEST_UUID = @"branch_sdk_request_unique_id"; +NSString * const BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP = @"branch_sdk_request_timestamp"; + +NSString * const WEB_UX_IN_APP_WEBVIEW = @"IN_APP_WEBVIEW"; +NSString * const WEB_UX_EXTERNAL_BROWSER = @"EXTERNAL_BROWSER"; + +NSString * const BRANCH_REQUEST_KEY_OPERATIONAL_METRICS = @"operational_metrics"; +NSString * const BRANCH_REQUEST_KEY_DEFER_INIT_FOR_PLUGIN_RUNTIME = @"deferInitForPluginRuntime"; +NSString * const BRANCH_REQUEST_KEY_CHECK_PASTEBOARD_ON_INSTALL= @"checkPasteboardOnInstall"; + +NSString * const BRANCH_REQUEST_KEY_BRANCH_KEY_SOURCE = @"branch_key_source"; +NSString * const BRANCH_KEY_SOURCE_UNKNOWN = @"Unknown"; +NSString * const BRANCH_KEY_SOURCE_CONFIG_JSON = @"config_json"; +NSString * const BRANCH_KEY_SOURCE_INFO_PLIST = @"info_plist"; +NSString * const BRANCH_KEY_SOURCE_GET_INSTANCE_API = @"getInstance_api"; +NSString * const BRANCH_KEY_SOURCE_SET_BRANCH_KEY_API= @"setBranchKey_api"; + +NSString * const BRANCH_REQUEST_KEY_LINKED_FRAMEORKS = @"linked_frameworks"; +NSString * const FRAMEWORK_ATT_TRACKING_MANAGER = @"ATTrackingManager"; +NSString * const FRAMEWORK_AD_SUPPORT = @"AdSupport"; +NSString * const FRAMEWORK_AD_SAFARI_SERVICES = @"SafariServices"; +NSString * const FRAMEWORK_AD_APP_ADS_ONDEVICE_CONVERSION = @"AppAdsOnDeviceConversion"; +NSString * const FRAMEWORK_AD_FIREBASE_CRASHLYTICS = @"FirebaseCrashlytics"; diff --git a/Sources/BranchSDK_ObjC/Public/BranchConstants.h b/Sources/BranchSDK_ObjC/Public/BranchConstants.h new file mode 100644 index 000000000..b08ec65f7 --- /dev/null +++ b/Sources/BranchSDK_ObjC/Public/BranchConstants.h @@ -0,0 +1,204 @@ +// +// BranchConstants.h +// Branch-TestBed +// +// Created by Graham Mueller on 6/10/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#if __has_feature(modules) +@import Foundation; +#else +#import +#endif + +extern NSString * const BRANCH_REQUEST_KEY_DEVELOPER_IDENTITY; +extern NSString * const BRANCH_REQUEST_KEY_RANDOMIZED_BUNDLE_TOKEN; +extern NSString * const BRANCH_REQUEST_KEY_RANDOMIZED_DEVICE_TOKEN; +extern NSString * const BRANCH_REQUEST_KEY_SESSION_ID; +extern NSString * const BRANCH_REQUEST_KEY_ACTION; +extern NSString * const BRANCH_REQUEST_KEY_STATE; +extern NSString * const BRANCH_REQUEST_KEY_BUCKET; +extern NSString * const BRANCH_REQUEST_KEY_AMOUNT; +extern NSString * const BRANCH_REQUEST_KEY_LENGTH; +extern NSString * const BRANCH_REQUEST_KEY_DIRECTION; +extern NSString * const BRANCH_REQUEST_KEY_STARTING_TRANSACTION_ID; +extern NSString * const BRANCH_REQUEST_KEY_URL_SOURCE; +extern NSString * const BRANCH_REQUEST_KEY_URL_TAGS; +extern NSString * const BRANCH_REQUEST_KEY_URL_LINK_TYPE; +extern NSString * const BRANCH_REQUEST_KEY_URL_ALIAS; +extern NSString * const BRANCH_REQUEST_KEY_URL_CHANNEL; +extern NSString * const BRANCH_REQUEST_KEY_URL_FEATURE; +extern NSString * const BRANCH_REQUEST_KEY_URL_STAGE; +extern NSString * const BRANCH_REQUEST_KEY_URL_CAMPAIGN; +extern NSString * const BRANCH_REQUEST_KEY_URL_DURATION; +extern NSString * const BRANCH_REQUEST_KEY_URL_DATA; +extern NSString * const BRANCH_REQUEST_KEY_URL_IGNORE_UA_STRING; +extern NSString * const BRANCH_REQUEST_KEY_HARDWARE_ID; +extern NSString * const BRANCH_REQUEST_KEY_HARDWARE_ID_TYPE; +extern NSString * const BRANCH_REQUEST_KEY_IS_HARDWARE_ID_REAL; +extern NSString * const BRANCH_REQUEST_KEY_IOS_VENDOR_ID; +extern NSString * const BRANCH_REQUEST_KEY_OPTED_IN_STATUS; +extern NSString * const BRANCH_REQUEST_KEY_FIRST_OPT_IN; +extern NSString * const BRANCH_REQUEST_KEY_DEBUG; +extern NSString * const BRANCH_REQUEST_KEY_BUNDLE_ID; +extern NSString * const BRANCH_REQUEST_KEY_TEAM_ID; +extern NSString * const BRANCH_REQUEST_KEY_APP_VERSION; +extern NSString * const BRANCH_REQUEST_KEY_OS; +extern NSString * const BRANCH_REQUEST_KEY_OS_VERSION; +extern NSString * const BRANCH_REQUEST_KEY_URI_SCHEME; +extern NSString * const BRANCH_REQUEST_KEY_LINK_IDENTIFIER; +extern NSString * const BRANCH_REQUEST_KEY_SPOTLIGHT_IDENTIFIER; +extern NSString * const BRANCH_REQUEST_KEY_UNIVERSAL_LINK_URL; +extern NSString * const BRANCH_REQUEST_KEY_LOCAL_URL; +extern NSString * const BRANCH_REQUEST_KEY_INITIAL_REFERRER; +extern NSString * const BRANCH_REQUEST_KEY_BRAND; +extern NSString * const BRANCH_REQUEST_KEY_MODEL; +extern NSString * const BRANCH_REQUEST_KEY_SCREEN_WIDTH; +extern NSString * const BRANCH_REQUEST_KEY_SCREEN_HEIGHT; +extern NSString * const BRANCH_REQUEST_KEY_IS_SIMULATOR; +extern NSString * const BRANCH_REQUEST_KEY_LOG; +extern NSString * const BRANCH_REQUEST_KEY_EXTERNAL_INTENT_URI; +extern NSString * const BRANCH_REQUEST_KEY_INSTRUMENTATION; +extern NSString * const BRANCH_REQUEST_KEY_APPLE_RECEIPT; +extern NSString * const BRANCH_REQUEST_KEY_APPLE_TESTFLIGHT; + +extern NSString * const BRANCH_REQUEST_KEY_APP_CLIP_BUNDLE_ID; +extern NSString * const BRANCH_REQUEST_KEY_LATEST_APP_CLIP_INSTALL_TIME; +extern NSString * const BRANCH_REQUEST_KEY_APP_CLIP_RANDOMIZED_DEVICE_TOKEN; +extern NSString * const BRANCH_REQUEST_KEY_APP_CLIP_RANDOMIZED_BUNDLE_TOKEN; + +extern NSString * const BRANCH_REQUEST_KEY_PARTNER_PARAMETERS; + +extern NSString * const BRANCH_REQUEST_METADATA_KEY_SCANTIME_WINDOW; +extern NSString * const BRANCH_REQUEST_KEY_REFERRER_GBRAID; +extern NSString * const BRANCH_REQUEST_KEY_REFERRER_GBRAID_TIMESTAMP; +extern NSString * const BRANCH_REQUEST_KEY_IS_DEEPLINK_GBRAID; +extern NSString * const BRANCH_REQUEST_KEY_GCLID; +extern NSString * const BRANCH_REQUEST_KEY_ODM_INFO; +extern NSString * const BRANCH_REQUEST_KEY_ODM_FIRST_OPEN_TIMESTAMP; +extern NSString * const BRANCH_REQUEST_KEY_META_CAMPAIGN_IDS; +extern NSString * const BRANCH_URL_QUERY_PARAMETERS_NAME_KEY; +extern NSString * const BRANCH_URL_QUERY_PARAMETERS_VALUE_KEY; +extern NSString * const BRANCH_URL_QUERY_PARAMETERS_TIMESTAMP_KEY; +extern NSString * const BRANCH_URL_QUERY_PARAMETERS_IS_DEEPLINK_KEY; +extern NSString * const BRANCH_URL_QUERY_PARAMETERS_VALIDITY_WINDOW_KEY; +extern NSString * const BRANCH_REQUEST_KEY_SCCID; +extern NSString * const BRANCH_REQUEST_KEY_WEB_LINK_CONTEXT; +extern NSString * const BRANCH_REQUEST_KEY_UX_TYPE; +extern NSString * const BRANCH_REQUEST_KEY_URL_LOAD_MS; + +extern NSString * const BRANCH_REQUEST_ENDPOINT_APP_LINK_SETTINGS; +extern NSString * const BRANCH_REQUEST_ENDPOINT_USER_COMPLETED_ACTION; +extern NSString * const BRANCH_REQUEST_ENDPOINT_GET_SHORT_URL; +extern NSString * const BRANCH_REQUEST_ENDPOINT_OPEN; +extern NSString * const BRANCH_REQUEST_ENDPOINT_INSTALL; +extern NSString * const BRANCH_REQUEST_ENDPOINT_REGISTER_VIEW; +extern NSString * const BRANCH_REQUEST_ENDPOINT_LATD; + +extern NSString * const BRANCH_RESPONSE_KEY_RANDOMIZED_BUNDLE_TOKEN; +extern NSString * const BRANCH_RESPONSE_KEY_SESSION_ID; +extern NSString * const BRANCH_RESPONSE_KEY_USER_URL; +extern NSString * const BRANCH_RESPONSE_KEY_INSTALL_PARAMS; +extern NSString * const BRANCH_RESPONSE_KEY_REFERRER; +extern NSString * const BRANCH_RESPONSE_KEY_REFERREE; +extern NSString * const BRANCH_RESPONSE_KEY_URL; +extern NSString * const BRANCH_RESPONSE_KEY_SPOTLIGHT_IDENTIFIER; +extern NSString * const BRANCH_RESPONSE_KEY_DEVELOPER_IDENTITY; +extern NSString * const BRANCH_RESPONSE_KEY_RANDOMIZED_DEVICE_TOKEN; +extern NSString * const BRANCH_RESPONSE_KEY_SESSION_DATA; +extern NSString * const BRANCH_RESPONSE_KEY_CLICKED_BRANCH_LINK; +extern NSString * const BRANCH_RESPONSE_KEY_BRANCH_VIEW_DATA; +extern NSString * const BRANCH_RESPONSE_KEY_BRANCH_REFERRING_LINK; +extern NSString * const BRANCH_RESPONSE_KEY_INVOKE_REGISTER_APP; +extern NSString * const BRANCH_RESPONSE_KEY_UPDATE_CONVERSION_VALUE; +extern NSString * const BRANCH_RESPONSE_KEY_COARSE_KEY; +extern NSString * const BRANCH_RESPONSE_KEY_UPDATE_IS_LOCKED; +extern NSString * const BRANCH_RESPONSE_KEY_ASCENDING_ONLY; +extern NSString * const BRANCH_RESPONSE_KEY_INVOKE_FEATURES; +extern NSString * const BRANCH_RESPONSE_KEY_ENHANCED_WEB_LINK_UX; +extern NSString * const BRANCH_RESPONSE_KEY_WEB_LINK_REDIRECT_URL; + +extern NSString * const BRANCH_LINK_DATA_KEY_OG_TITLE; +extern NSString * const BRANCH_LINK_DATA_KEY_OG_DESCRIPTION; +extern NSString * const BRANCH_LINK_DATA_KEY_OG_IMAGE_URL; +extern NSString * const BRANCH_LINK_DATA_KEY_TITLE; +extern NSString * const BRANCH_LINK_DATA_KEY_DESCRIPTION; +extern NSString * const BRANCH_LINK_DATA_KEY_PUBLICLY_INDEXABLE; +extern NSString * const BRANCH_LINK_DATA_KEY_LOCALLY_INDEXABLE; +extern NSString * const BRANCH_LINK_DATA_KEY_TYPE; +extern NSString * const BRANCH_LINK_DATA_KEY_THUMBNAIL_URL; +extern NSString * const BRANCH_LINK_DATA_KEY_KEYWORDS; +extern NSString * const BRANCH_LINK_DATA_KEY_CANONICAL_IDENTIFIER; +extern NSString * const BRANCH_LINK_DATA_KEY_CANONICAL_URL; +extern NSString * const BRANCH_LINK_DATA_KEY_CONTENT_EXPIRATION_DATE; +extern NSString * const BRANCH_LINK_DATA_KEY_CONTENT_TYPE; +extern NSString * const BRANCH_LINK_DATA_KEY_EMAIL_SUBJECT; +extern NSString * const BRANCH_LINK_DATA_KEY_EMAIL_HTML_HEADER; +extern NSString * const BRANCH_LINK_DATA_KEY_EMAIL_HTML_FOOTER; +extern NSString * const BRANCH_LINK_DATA_KEY_EMAIL_HTML_LINK_TEXT; + +extern NSString * const BRANCH_SPOTLIGHT_PREFIX; + +extern NSString * const BRANCH_MANIFEST_VERSION_KEY; +extern NSString * const BRANCH_HASH_MODE_KEY; +extern NSString * const BRANCH_MANIFEST_KEY; +extern NSString * const BRANCH_PATH_KEY; +extern NSString * const BRANCH_FILTERED_KEYS; +extern NSString * const BRANCH_MAX_TEXT_LEN_KEY; +extern NSString * const BRANCH_MAX_VIEW_HISTORY_LENGTH; +extern NSString * const BRANCH_MAX_PACKET_SIZE_KEY; +extern NSString * const BRANCH_CONTENT_DISCOVER_KEY; +extern NSString * const BRANCH_BUNDLE_IDENTIFIER; +extern NSString * const BRANCH_TIME_STAMP_KEY; +extern NSString * const BRANCH_TIME_STAMP_CLOSE_KEY; +extern NSString * const BRANCH_NAV_PATH_KEY; +extern NSString * const BRANCH_REFERRAL_LINK_KEY; +extern NSString * const BRANCH_CONTENT_LINK_KEY; +extern NSString * const BRANCH_CONTENT_META_DATA_KEY; +extern NSString * const BRANCH_VIEW_KEY; +extern NSString * const BRANCH_CONTENT_DATA_KEY; +extern NSString * const BRANCH_CONTENT_KEYS_KEY; +extern NSString * const BRANCH_PACKAGE_NAME_KEY; +extern NSString * const BRANCH_ENTITIES_KEY; + +extern NSString * const BRANCH_REQUEST_KEY_APPLE_ATTRIBUTION_TOKEN; + +extern NSString * const BRANCH_CRASHLYTICS_SDK_VERSION_KEY; +extern NSString * const BRANCH_CRASHLYTICS_LOW_MEMORY_KEY; + +extern NSString * const BRANCH_REQUEST_KEY_SKAN_POSTBACK_INDEX; +extern NSString * const BRANCH_REQUEST_KEY_VALUE_POSTBACK_SEQUENCE_INDEX_0; +extern NSString * const BRANCH_REQUEST_KEY_VALUE_POSTBACK_SEQUENCE_INDEX_1; +extern NSString * const BRANCH_REQUEST_KEY_VALUE_POSTBACK_SEQUENCE_INDEX_2; + +extern NSString * const BRANCH_REQUEST_KEY_DMA_EEA; +extern NSString * const BRANCH_REQUEST_KEY_DMA_AD_PEROSALIZATION; +extern NSString * const BRANCH_REQUEST_KEY_DMA_AD_USER_DATA; + +extern NSString * const BRANCH_REQUEST_KEY_CPP_LEVEL; + +extern NSString * const BRANCH_REQUEST_KEY_REQUEST_UUID; +extern NSString * const BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP; + +extern NSString * const WEB_UX_IN_APP_WEBVIEW; +extern NSString * const WEB_UX_EXTERNAL_BROWSER; + +// Operational Metrics Param Keys +extern NSString * const BRANCH_REQUEST_KEY_OPERATIONAL_METRICS; +extern NSString * const BRANCH_REQUEST_KEY_DEFER_INIT_FOR_PLUGIN_RUNTIME; +extern NSString * const BRANCH_REQUEST_KEY_CHECK_PASTEBOARD_ON_INSTALL; + +extern NSString * const BRANCH_REQUEST_KEY_BRANCH_KEY_SOURCE; +extern NSString * const BRANCH_KEY_SOURCE_UNKNOWN; +extern NSString * const BRANCH_KEY_SOURCE_GET_INSTANCE_API; +extern NSString * const BRANCH_KEY_SOURCE_SET_BRANCH_KEY_API; +extern NSString * const BRANCH_KEY_SOURCE_CONFIG_JSON; +extern NSString * const BRANCH_KEY_SOURCE_INFO_PLIST; + +extern NSString * const BRANCH_REQUEST_KEY_LINKED_FRAMEORKS; +extern NSString * const FRAMEWORK_ATT_TRACKING_MANAGER; +extern NSString * const FRAMEWORK_AD_SUPPORT; +extern NSString * const FRAMEWORK_AD_SAFARI_SERVICES; +extern NSString * const FRAMEWORK_AD_APP_ADS_ONDEVICE_CONVERSION; +extern NSString * const FRAMEWORK_AD_FIREBASE_CRASHLYTICS; diff --git a/Sources/BranchSwiftSDK/BranchRequestOperation.swift b/Sources/BranchSwiftSDK/BranchRequestOperation.swift new file mode 100644 index 000000000..425694691 --- /dev/null +++ b/Sources/BranchSwiftSDK/BranchRequestOperation.swift @@ -0,0 +1,300 @@ +// +// BranchRequestOperation.swift +// BranchSDK +// +// Created by Branch SDK Team +// Modern Swift Concurrency implementation for request processing +// + +import Foundation + +// Import BranchSDK when building as Swift Package +#if SWIFT_PACKAGE +import BranchSDK +#endif + +// When building as part of Xcode project, types are available through module +// No additional import needed - Swift sees Objective-C through the module + +/// Modern Swift Concurrency-based operation for processing Branch server requests. +/// This class provides a structured concurrency approach similar to Android's Kotlin Coroutines implementation, +/// replacing manual GCD dispatch queues with async/await patterns. +/// +/// Key features: +/// - Structured concurrency with proper cancellation support +/// - Actor-based thread safety +/// - Automatic main thread dispatching for callbacks +/// - Session validation matching Android implementation +/// - Performance optimized with cooperative thread pool +@available(iOS 13.0, tvOS 13.0, *) +@objc(BranchRequestOperation) +public final class BranchRequestOperation: Operation, @unchecked Sendable { + + // MARK: - Properties + + /// The server request to be processed + private let request: BNCServerRequest + + /// Server interface for network operations + private let serverInterface: BNCServerInterface + + /// Branch API key + private let branchKey: String + + /// Preference helper for session data + private let preferenceHelper: BNCPreferenceHelper + + /// Task handle for async execution + private var executionTask: Task? + + // MARK: - Operation State Management + + private var _isExecuting = false { + willSet { + willChangeValue(forKey: "isExecuting") + } + didSet { + didChangeValue(forKey: "isExecuting") + } + } + + private var _isFinished = false { + willSet { + willChangeValue(forKey: "isFinished") + } + didSet { + didChangeValue(forKey: "isFinished") + } + } + + public override var isExecuting: Bool { _isExecuting } + public override var isFinished: Bool { _isFinished } + public override var isAsynchronous: Bool { true } + + // MARK: - Initialization + + /// Creates a new request operation with modern Swift Concurrency + /// - Parameters: + /// - request: The server request to process + /// - serverInterface: Network interface for API calls + /// - branchKey: Branch API key + /// - preferenceHelper: Helper for accessing session preferences + @objc(initWithRequest:serverInterface:branchKey:preferenceHelper:) + public init( + request: BNCServerRequest, + serverInterface: BNCServerInterface, + branchKey: String, + preferenceHelper: BNCPreferenceHelper + ) { + self.request = request + self.serverInterface = serverInterface + self.branchKey = branchKey + self.preferenceHelper = preferenceHelper + super.init() + } + + // MARK: - Operation Lifecycle + + public override func start() { + guard !isCancelled else { + BranchLogger.shared().logDebug( + "Operation cancelled before starting: \(request.requestUUID ?? "unknown")", + error: nil + ) + finish() + return + } + + _isExecuting = true + + BranchLogger.shared().logVerbose( + "BranchRequestOperation starting for request: \(request.requestUUID ?? "unknown")", + error: nil + ) + + // Launch async task with structured concurrency + executionTask = Task { [weak self] in + await self?.executeRequest() + } + } + + public override func cancel() { + executionTask?.cancel() + super.cancel() + + if !isExecuting { + BranchLogger.shared().logWarning( + "BranchRequestOperation cancelled before execution for request: \(request.requestUUID ?? "unknown")", + error: nil + ) + } else { + BranchLogger.shared().logWarning( + "BranchRequestOperation cancelled during execution for request: \(request.requestUUID ?? "unknown")", + error: nil + ) + } + } + + // MARK: - Request Execution (Swift Concurrency) + + /// Executes the request using modern async/await patterns + /// Similar to Android's suspend fun executeRequest() + private func executeRequest() async { + // Early return if cancelled + guard !Task.isCancelled else { + finish() + return + } + + // Check if tracking is disabled + guard !Branch.trackingDisabled() else { + BranchLogger.shared().logDebug( + "Tracking disabled. Skipping request: \(request.requestUUID ?? "unknown")", + error: nil + ) + finish() + return + } + + // Validate session (similar to Android session checks) + guard validateSession() else { + // BNCInitError code from NSError+Branch.h + await processError(1001, message: "Session validation failed") + finish() + return + } + + // Execute network request with continuation-based callback bridge + await withCheckedContinuation { (continuation: CheckedContinuation) in + request.make( + serverInterface, + key: branchKey + ) { [weak self] response, error in + guard let self = self else { + continuation.resume() + return + } + + // Handle response on main thread (equivalent to Android's Dispatchers.Main) + Task { @MainActor in + await self.handleResponse(response, error: error) + continuation.resume() + } + } + } + + BranchLogger.shared().logVerbose( + "BranchRequestOperation finished for request: \(request.requestUUID ?? "unknown")", + error: nil + ) + + finish() + } + + // MARK: - Session Validation + + /// Validates session requirements based on request type + /// Matches Android's session validation logic in BranchRequestQueue.kt + /// - Returns: true if session is valid for this request type + private func validateSession() -> Bool { + let requestClassName = String(describing: type(of: request)) + let requestUUID = request.requestUUID ?? "unknown" + + // Install requests only need bundle token + if requestClassName.contains("BranchInstallRequest") { + guard preferenceHelper.randomizedBundleToken != nil else { + BranchLogger.shared().logError( + "User session not initialized (missing bundle token). Dropping request: \(requestUUID)", + error: nil + ) + return false + } + return true + } + + // Open requests need bundle token + if requestClassName.contains("BranchOpenRequest") { + guard preferenceHelper.randomizedBundleToken != nil else { + BranchLogger.shared().logError( + "User session not initialized (missing bundle token). Dropping request: \(requestUUID)", + error: nil + ) + return false + } + return true + } + + // All other requests need full session (device token, session ID, bundle token) + guard preferenceHelper.randomizedDeviceToken != nil, + preferenceHelper.sessionID != nil, + preferenceHelper.randomizedBundleToken != nil else { + BranchLogger.shared().logError( + "Missing session items (device token or session ID or bundle token). Dropping request: \(requestUUID)", + error: nil + ) + return false + } + + return true + } + + // MARK: - Response Handling + + /// Handles the server response on main thread + /// Equivalent to Android's withContext(Dispatchers.Main) { handleResponse() } + /// - Parameters: + /// - response: Server response (if successful) + /// - error: Error (if failed) + @MainActor + private func handleResponse(_ response: BNCServerResponse?, error: Error?) async { + // Process response on main thread + request.processResponse(response, error: error) + + // Handle event-specific callbacks + // Check if request is BranchEventRequest by class name (Objective-C class) + let requestClassName = String(describing: type(of: request)) + if requestClassName.contains("BranchEventRequest") { + // Use dynamic method invocation for Objective-C callback + let callbackMap = NSClassFromString("BNCCallbackMap") + let sharedSelector = NSSelectorFromString("shared") + if let callbackMapClass = callbackMap as? NSObject.Type, + callbackMapClass.responds(to: sharedSelector), + let shared = callbackMapClass.perform(sharedSelector)?.takeUnretainedValue() { + let callSelector = NSSelectorFromString("callCompletionForRequest:withSuccessStatus:error:") + if shared.responds(to: callSelector) { + // Perform with proper selector invocation + typealias CallCompletionFunc = @convention(c) (AnyObject, Selector, AnyObject, Bool, Error?) -> Void + let implementation = shared.method(for: callSelector) + let callCompletion = unsafeBitCast(implementation, to: CallCompletionFunc.self) + callCompletion(shared, callSelector, request as AnyObject, error == nil, error) + + } + } + } + } + + /// Processes error and calls request failure handler on main thread + /// - Parameters: + /// - errorCode: Branch error code (Int value) + /// - message: Error message + @MainActor + private func processError(_ errorCode: Int, message: String) async { + // Create NSError with BNCInitError code + let error = NSError( + domain: "io.branch.sdk.error", + code: errorCode, + userInfo: [NSLocalizedDescriptionKey: message] + ) + BranchLogger.shared().logError(message, error: error) + request.processResponse(nil, error: error) + } + + // MARK: - State Management + + /// Marks the operation as finished + /// Triggers KVO notifications for operation queue management + private func finish() { + _isExecuting = false + _isFinished = true + } +} diff --git a/Sources/BranchSwiftSDK/BranchRequestQueue.swift b/Sources/BranchSwiftSDK/BranchRequestQueue.swift new file mode 100644 index 000000000..6cd9ab99a --- /dev/null +++ b/Sources/BranchSwiftSDK/BranchRequestQueue.swift @@ -0,0 +1,322 @@ +// +// BranchRequestQueue.swift +// BranchSDK +// +// Created by Branch SDK Team +// Modern Actor-based request queue with Swift Concurrency +// + +import Foundation + +// Import BranchSDK when building as Swift Package +#if SWIFT_PACKAGE +import BranchSDK +#endif + +// When building as part of Xcode project, types are available through module +// No additional import needed - Swift sees Objective-C through the module + +/// Modern actor-based request queue using Swift Concurrency patterns. +/// This implementation replaces manual NSOperationQueue management with structured concurrency, +/// similar to Android's Kotlin Coroutines BranchRequestQueue.kt implementation. +/// +/// Key features: +/// - Actor isolation for thread-safe queue management +/// - Serial request processing with structured concurrency +/// - Automatic request prioritization +/// - Session-aware request handling +/// - Modern async/await API +/// +/// Architecture parallels: +/// - Android: CoroutineScope + Channel -> iOS: Actor + AsyncStream +/// - Android: Dispatchers.IO -> iOS: Task.detached +/// - Android: Dispatchers.Main -> iOS: MainActor +@available(iOS 13.0, tvOS 13.0, *) +public actor BranchRequestQueue { + + // MARK: - Properties + + /// Operation queue for managing request operations + /// Serial execution (maxConcurrentOperationCount = 1) ensures proper request ordering + private let operationQueue: OperationQueue + + /// Server interface for network operations + private var serverInterface: BNCServerInterface? + + /// Branch API key + private var branchKey: String? + + /// Preference helper for session management + private var preferenceHelper: BNCPreferenceHelper? + + /// Processing channel for triggering queue processing + /// Similar to Android's Channel for processing triggers + private let (processingStream, processingContinuation) = AsyncStream.makeStream() + + /// Queue state tracking + private var isProcessing = false + + /// Singleton instance + private static let _shared = BranchRequestQueue() + + // MARK: - Singleton Access + + /// Returns the shared instance of BranchRequestQueue + /// Thread-safe singleton pattern using actor isolation + public static func shared() -> BranchRequestQueue { + return _shared + } + + // MARK: - Initialization + + private init() { + operationQueue = OperationQueue() + operationQueue.maxConcurrentOperationCount = 1 // Serial execution + operationQueue.name = "com.branch.sdk.requestQueue.modern" + operationQueue.qualityOfService = .userInitiated + + BranchLogger.shared().logDebug("BranchRequestQueue (Swift Actor) initialized", error: nil) + } + + // MARK: - Configuration + + /// Configures the queue with required dependencies + /// - Parameters: + /// - serverInterface: Network interface for API calls + /// - branchKey: Branch API key + /// - preferenceHelper: Helper for session preferences + public func configure( + serverInterface: BNCServerInterface, + branchKey: String, + preferenceHelper: BNCPreferenceHelper + ) { + self.serverInterface = serverInterface + self.branchKey = branchKey + self.preferenceHelper = preferenceHelper + + BranchLogger.shared().logDebug( + "BranchRequestQueue configured with key: \(branchKey.prefix(8))...", + error: nil + ) + } + + // MARK: - Queue Operations + + /// Enqueues a request with default priority + /// - Parameter request: The server request to enqueue + public func enqueue(_ request: BNCServerRequest) async { + await enqueue(request, priority: .normal) + } + + /// Enqueues a request with specified priority + /// Similar to Android's enqueue() with priority handling + /// - Parameters: + /// - request: The server request to enqueue + /// - priority: Operation queue priority + public func enqueue(_ request: BNCServerRequest, priority: Operation.QueuePriority) async { + guard let serverInterface = serverInterface, + let branchKey = branchKey, + let preferenceHelper = preferenceHelper else { + BranchLogger.shared().logError( + "BranchRequestQueue not configured. Call configure() first.", + error: nil + ) + return + } + + guard let requestUUID = request.requestUUID else { + BranchLogger.shared().logError("Request missing UUID. Cannot enqueue.", error: nil) + return + } + + // Create modern Swift operation + let operation = BranchRequestOperation( + request: request, + serverInterface: serverInterface, + branchKey: branchKey, + preferenceHelper: preferenceHelper + ) + operation.queuePriority = priority + + // Add to operation queue + operationQueue.addOperation(operation) + + BranchLogger.shared().logVerbose( + "Enqueued request: \(requestUUID). Current queue depth: \(queueDepth)", + error: nil + ) + + // Trigger processing + processingContinuation.yield() + } + + /// Returns current queue depth + /// Equivalent to Android's queueDepth property + public var queueDepth: Int { + return operationQueue.operationCount + } + + /// Clears all pending operations from the queue + /// Similar to Android's clearQueue() + public func clearQueue() { + BranchLogger.shared().logDebug( + "Clearing all pending operations from queue. Current depth: \(queueDepth)", + error: nil + ) + operationQueue.cancelAllOperations() + } + + // MARK: - Queue Inspection + + /// Checks if queue contains install or open request + /// - Returns: true if install or open request is present + public func containsInstallOrOpen() -> Bool { + for operation in operationQueue.operations { + if let requestOp = operation as? BranchRequestOperation, + let mirror = Mirror(reflecting: requestOp).descendant("request"), + let request = mirror as? BNCServerRequest { + let requestClassName = String(describing: type(of: request)) + if requestClassName.contains("BranchOpenRequest") || + requestClassName.contains("BranchInstallRequest") { + return true + } + } + } + return false + } + + /// Finds existing install or open request in queue + /// - Returns: The open request if found, nil otherwise (as AnyObject) + public func findExistingInstallOrOpen() -> AnyObject? { + for operation in operationQueue.operations { + if let requestOp = operation as? BranchRequestOperation, + let mirror = Mirror(reflecting: requestOp).descendant("request"), + let request = mirror as? BNCServerRequest { + let requestClassName = String(describing: type(of: request)) + if requestClassName.contains("BranchOpenRequest") || + requestClassName.contains("BranchInstallRequest") { + return request + } + } + } + return nil + } + + // MARK: - Queue State Description + + /// Returns detailed description of queue state + /// Useful for debugging and logging + public var description: String { + let operations = operationQueue.operations + let operationDescriptions = operations.compactMap { operation -> String? in + if let requestOp = operation as? BranchRequestOperation, + let mirror = Mirror(reflecting: requestOp).descendant("request"), + let request = mirror as? BNCServerRequest, + let uuid = request.requestUUID { + if operation.isFinished || operation.isCancelled { + return "(Completed/Cancelled: \(uuid))" + } else { + return uuid + } + } + return nil + } + + return """ + + Queue Depth: \(queueDepth) + Operations: [\(operationDescriptions.joined(separator: ", "))] + """ + } +} + +// MARK: - Objective-C Bridge + +/// Objective-C compatible wrapper for BranchRequestQueue +/// Provides seamless interop with existing Objective-C code +@available(iOS 13.0, tvOS 13.0, *) +@objc(BranchRequestQueueModern) +public class BranchRequestQueueBridge: NSObject { + + private let queue: BranchRequestQueue + + @objc public static let shared = BranchRequestQueueBridge() + + private override init() { + queue = BranchRequestQueue.shared() + super.init() + } + + /// Configures the queue (Objective-C compatible) + @objc public func configure( + serverInterface: BNCServerInterface, + branchKey: String, + preferenceHelper: BNCPreferenceHelper + ) { + Task { + await queue.configure( + serverInterface: serverInterface, + branchKey: branchKey, + preferenceHelper: preferenceHelper + ) + } + } + + /// Enqueues a request with default priority (Objective-C compatible) + @objc public func enqueue(_ request: BNCServerRequest) { + Task { + await queue.enqueue(request) + } + } + + /// Enqueues a request with priority (Objective-C compatible) + @objc public func enqueue(_ request: BNCServerRequest, priority: Operation.QueuePriority) { + Task { + await queue.enqueue(request, priority: priority) + } + } + + /// Enqueues with completion callback (Objective-C compatible) + @objc public func enqueue(_ request: BNCServerRequest, completion: @escaping (Error?) -> Void) { + Task { + await queue.enqueue(request) + await MainActor.run { + completion(nil) + } + } + } + + /// Current queue depth (Objective-C compatible) + @objc public var queueDepth: Int { + var depth = 0 + Task { + depth = await queue.queueDepth + } + return depth + } + + /// Clears queue (Objective-C compatible) + @objc public func clearQueue() { + Task { + await queue.clearQueue() + } + } + + /// Checks for install/open request (Objective-C compatible) + @objc public func containsInstallOrOpen() -> Bool { + var contains = false + Task { + contains = await queue.containsInstallOrOpen() + } + return contains + } + + /// Finds install/open request (Objective-C compatible) + @objc public func findExistingInstallOrOpen() -> AnyObject? { + var openRequest: AnyObject? + Task { + openRequest = await queue.findExistingInstallOrOpen() + } + return openRequest + } +} diff --git a/Sources/BranchSwiftSDK/ConfigurationController.swift b/Sources/BranchSwiftSDK/ConfigurationController.swift new file mode 100644 index 000000000..b6215d039 --- /dev/null +++ b/Sources/BranchSwiftSDK/ConfigurationController.swift @@ -0,0 +1,93 @@ +// +// ConfigurationController.swift +// BranchSDK +// +// Created by Nidhi Dixit on 6/17/25. +// + + +import Foundation + +#if SWIFT_PACKAGE +import BranchSDK +#endif + +// MARK: - Branch Constants (Swift equivalents from BranchConstants.h) + +/// Branch request key constants +/// These match the Objective-C constants defined in BranchConstants.m (lines 186-196) +private let BRANCH_REQUEST_KEY_BRANCH_KEY_SOURCE = "branch_key_source" +private let BRANCH_REQUEST_KEY_CHECK_PASTEBOARD_ON_INSTALL = "checkPasteboardOnInstall" +private let BRANCH_REQUEST_KEY_DEFER_INIT_FOR_PLUGIN_RUNTIME = "deferInitForPluginRuntime" +private let BRANCH_REQUEST_KEY_LINKED_FRAMEORKS = "linked_frameworks" // Note: typo "FRAMEORKS" in constant name is intentional + +/// Framework identification constants +/// These match the Objective-C constants defined in BranchConstants.m (lines 197-201) +private let FRAMEWORK_ATT_TRACKING_MANAGER = "ATTrackingManager" +private let FRAMEWORK_AD_SUPPORT = "AdSupport" +private let FRAMEWORK_AD_SAFARI_SERVICES = "SafariServices" +private let FRAMEWORK_AD_APP_ADS_ONDEVICE_CONVERSION = "AppAdsOnDeviceConversion" +private let FRAMEWORK_AD_FIREBASE_CRASHLYTICS = "FirebaseCrashlytics" + +@objcMembers +public class ConfigurationController: NSObject { + + // MARK: - Properties + public var branchKeySource: String? + public var deferInitForPluginRuntime: Bool = false + public var checkPasteboardOnInstall: Bool = false + + // MARK: - Singleton + // Note: Removed @MainActor to allow synchronous access from Objective-C code + // Thread safety is handled internally within the class methods + @objc public static let shared = ConfigurationController() + + private override init() { + // Private initializer to enforce singleton usage. + super.init() + } + + public func getConfiguration() -> [String: Any] { + var config: [String: Any] = [:] + + config.merge(branchKeyInfo()) { (_, new) in new } + config.merge(featureFlagsInfo()) { (_, new) in new } + config.merge(frameworkIntegrationInfo()) { (_, new) in new } + + return config + } + + // MARK: - Private Helper Methods + private func branchKeyInfo() -> [String: String] { + return [ + BRANCH_REQUEST_KEY_BRANCH_KEY_SOURCE: self.branchKeySource ?? "Unknown" + ] + } + + private func featureFlagsInfo() -> [String: Bool] { + return [ + BRANCH_REQUEST_KEY_CHECK_PASTEBOARD_ON_INSTALL: self.checkPasteboardOnInstall, + BRANCH_REQUEST_KEY_DEFER_INIT_FOR_PLUGIN_RUNTIME: self.deferInitForPluginRuntime + ] + } + + private func frameworkIntegrationInfo() -> [String: Any] { + var info: [String: Any] = [:] + + let linkedFrameworks: [String: Bool] = [ + FRAMEWORK_AD_SUPPORT: isClassAvailable(className: "ASIdentifierManager"), + FRAMEWORK_ATT_TRACKING_MANAGER: isClassAvailable(className: "ATTrackingManager"), + FRAMEWORK_AD_FIREBASE_CRASHLYTICS: isClassAvailable(className: "FIRCrashlytics"), + FRAMEWORK_AD_SAFARI_SERVICES: isClassAvailable(className: "SFSafariViewController"), + FRAMEWORK_AD_APP_ADS_ONDEVICE_CONVERSION: isClassAvailable(className: "ODCConversionManager") + ] + + info[BRANCH_REQUEST_KEY_LINKED_FRAMEORKS] = linkedFrameworks + + return info + } + + private func isClassAvailable(className: String) -> Bool { + return NSClassFromString(className) != nil + } +} diff --git a/TestDeepLinking/Podfile b/TestDeepLinking/Podfile deleted file mode 100644 index 1a6061452..000000000 --- a/TestDeepLinking/Podfile +++ /dev/null @@ -1,8 +0,0 @@ -platform :ios, '9.0' - -target 'TestDeepLinking' do - # if swift - use_frameworks! - - pod 'Branch' -end diff --git a/TestDeepLinking/TestDeepLinking.xcodeproj/project.pbxproj b/TestDeepLinking/TestDeepLinking.xcodeproj/project.pbxproj deleted file mode 100644 index 31dd25628..000000000 --- a/TestDeepLinking/TestDeepLinking.xcodeproj/project.pbxproj +++ /dev/null @@ -1,733 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 51; - objects = { - -/* Begin PBXBuildFile section */ - 032DAEE82607431D00891641 /* TestDeepLinkWithoutApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 032DAED2260742D100891641 /* TestDeepLinkWithoutApp.m */; }; - 032DAEFE2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 032DAEFD2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m */; }; - 033608162605E2110032A5DC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033608152605E2110032A5DC /* AppDelegate.swift */; }; - 033608182605E2110032A5DC /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033608172605E2110032A5DC /* SceneDelegate.swift */; }; - 0336081A2605E2110032A5DC /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033608192605E2110032A5DC /* ViewController.swift */; }; - 0336081D2605E2110032A5DC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0336081B2605E2110032A5DC /* Main.storyboard */; }; - 0336081F2605E2150032A5DC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0336081E2605E2150032A5DC /* Assets.xcassets */; }; - 033608222605E2150032A5DC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 033608202605E2150032A5DC /* LaunchScreen.storyboard */; }; - 033608302605F1E30032A5DC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0336082F2605F1E30032A5DC /* CoreServices.framework */; }; - 033608322605F1F10032A5DC /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608312605F1F10032A5DC /* SystemConfiguration.framework */; }; - 033608342605F20C0032A5DC /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608332605F20C0032A5DC /* CoreTelephony.framework */; }; - 033608362605F2130032A5DC /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608352605F2130032A5DC /* WebKit.framework */; }; - 033608382605F21B0032A5DC /* CoreSpotlight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608372605F21B0032A5DC /* CoreSpotlight.framework */; }; - 0336083B2605F2370032A5DC /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608392605F2370032A5DC /* AdSupport.framework */; }; - 0336083C2605F2370032A5DC /* iAd.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0336083A2605F2370032A5DC /* iAd.framework */; }; - 0336083E2605F2880032A5DC /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608392605F2370032A5DC /* AdSupport.framework */; }; - 033608402605F4470032A5DC /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608392605F2370032A5DC /* AdSupport.framework */; }; - 03DE13B32606A1B4006D18F5 /* TestDeepLinking.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 03DE13B22606A0C4006D18F5 /* TestDeepLinking.entitlements */; }; - 03DE13BA2606BFC4006D18F5 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03DE13B92606BFC4006D18F5 /* AdServices.framework */; }; - 69BEC330F5B8AF8CE3C32174 /* Pods_TestDeepLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 815FC6A40AFE1F218C25C738 /* Pods_TestDeepLinking.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 032DAEDF2607430600891641 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0336080A2605E2100032A5DC /* Project object */; - proxyType = 1; - remoteGlobalIDString = 033608112605E2110032A5DC; - remoteInfo = TestDeepLinking; - }; - 032DAF002607491B00891641 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0336080A2605E2100032A5DC /* Project object */; - proxyType = 1; - remoteGlobalIDString = 033608112605E2110032A5DC; - remoteInfo = TestDeepLinking; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 032DAED2260742D100891641 /* TestDeepLinkWithoutApp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestDeepLinkWithoutApp.m; sourceTree = ""; }; - 032DAEDA2607430600891641 /* TestDeepLinkingUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestDeepLinkingUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 032DAEDE2607430600891641 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 032DAEFB2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestDeepLinkingUITestsWithHostApp.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 032DAEFD2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestDeepLinkingUITestsWithHostApp.m; sourceTree = ""; }; - 032DAEFF2607491B00891641 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 032DAF122607504000891641 /* TestDeepLinking.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TestDeepLinking.xctestplan; sourceTree = ""; }; - 033608122605E2110032A5DC /* TestDeepLinking.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestDeepLinking.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 033608152605E2110032A5DC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 033608172605E2110032A5DC /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 033608192605E2110032A5DC /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 0336081C2605E2110032A5DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 0336081E2605E2150032A5DC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 033608212605E2150032A5DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 033608232605E2150032A5DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 0336082F2605F1E30032A5DC /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; - 033608312605F1F10032A5DC /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - 033608332605F20C0032A5DC /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; - 033608352605F2130032A5DC /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 033608372605F21B0032A5DC /* CoreSpotlight.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreSpotlight.framework; path = System/Library/Frameworks/CoreSpotlight.framework; sourceTree = SDKROOT; }; - 033608392605F2370032A5DC /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; - 0336083A2605F2370032A5DC /* iAd.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = iAd.framework; path = System/Library/Frameworks/iAd.framework; sourceTree = SDKROOT; }; - 03DE13B22606A0C4006D18F5 /* TestDeepLinking.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TestDeepLinking.entitlements; sourceTree = ""; }; - 03DE13B92606BFC4006D18F5 /* AdServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdServices.framework; path = ../../AdServices.framework; sourceTree = ""; }; - 0EE470FCEAEA1ECC99DC0A89 /* Pods-TestDeepLinking.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestDeepLinking.release.xcconfig"; path = "Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking.release.xcconfig"; sourceTree = ""; }; - 815FC6A40AFE1F218C25C738 /* Pods_TestDeepLinking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TestDeepLinking.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 86113F63A46AE44E1E8B1648 /* Pods-TestDeepLinking.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestDeepLinking.debug.xcconfig"; path = "Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 032DAED72607430600891641 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 032DAEF82607491B00891641 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0336080F2605E2110032A5DC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 033608362605F2130032A5DC /* WebKit.framework in Frameworks */, - 033608402605F4470032A5DC /* AdSupport.framework in Frameworks */, - 033608342605F20C0032A5DC /* CoreTelephony.framework in Frameworks */, - 03DE13BA2606BFC4006D18F5 /* AdServices.framework in Frameworks */, - 0336083E2605F2880032A5DC /* AdSupport.framework in Frameworks */, - 033608382605F21B0032A5DC /* CoreSpotlight.framework in Frameworks */, - 033608322605F1F10032A5DC /* SystemConfiguration.framework in Frameworks */, - 033608302605F1E30032A5DC /* CoreServices.framework in Frameworks */, - 0336083B2605F2370032A5DC /* AdSupport.framework in Frameworks */, - 0336083C2605F2370032A5DC /* iAd.framework in Frameworks */, - 69BEC330F5B8AF8CE3C32174 /* Pods_TestDeepLinking.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 032DAEDB2607430600891641 /* TestDeepLinkingUITests */ = { - isa = PBXGroup; - children = ( - 032DAED2260742D100891641 /* TestDeepLinkWithoutApp.m */, - 032DAEDE2607430600891641 /* Info.plist */, - ); - path = TestDeepLinkingUITests; - sourceTree = ""; - }; - 032DAEFC2607491B00891641 /* TestDeepLinkingUITestsWithHostApp */ = { - isa = PBXGroup; - children = ( - 032DAEFD2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m */, - 032DAEFF2607491B00891641 /* Info.plist */, - ); - path = TestDeepLinkingUITestsWithHostApp; - sourceTree = ""; - }; - 033608092605E2100032A5DC = { - isa = PBXGroup; - children = ( - 033608142605E2110032A5DC /* TestDeepLinking */, - 032DAEDB2607430600891641 /* TestDeepLinkingUITests */, - 032DAEFC2607491B00891641 /* TestDeepLinkingUITestsWithHostApp */, - 033608132605E2110032A5DC /* Products */, - 0336082E2605F1E30032A5DC /* Frameworks */, - FBA3F883B3850B5894EAA121 /* Pods */, - ); - sourceTree = ""; - }; - 033608132605E2110032A5DC /* Products */ = { - isa = PBXGroup; - children = ( - 033608122605E2110032A5DC /* TestDeepLinking.app */, - 032DAEDA2607430600891641 /* TestDeepLinkingUITests.xctest */, - 032DAEFB2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 033608142605E2110032A5DC /* TestDeepLinking */ = { - isa = PBXGroup; - children = ( - 03DE13B22606A0C4006D18F5 /* TestDeepLinking.entitlements */, - 033608152605E2110032A5DC /* AppDelegate.swift */, - 032DAF122607504000891641 /* TestDeepLinking.xctestplan */, - 033608172605E2110032A5DC /* SceneDelegate.swift */, - 033608192605E2110032A5DC /* ViewController.swift */, - 0336081B2605E2110032A5DC /* Main.storyboard */, - 0336081E2605E2150032A5DC /* Assets.xcassets */, - 033608202605E2150032A5DC /* LaunchScreen.storyboard */, - 033608232605E2150032A5DC /* Info.plist */, - ); - path = TestDeepLinking; - sourceTree = ""; - }; - 0336082E2605F1E30032A5DC /* Frameworks */ = { - isa = PBXGroup; - children = ( - 03DE13B92606BFC4006D18F5 /* AdServices.framework */, - 033608392605F2370032A5DC /* AdSupport.framework */, - 0336083A2605F2370032A5DC /* iAd.framework */, - 033608372605F21B0032A5DC /* CoreSpotlight.framework */, - 033608352605F2130032A5DC /* WebKit.framework */, - 033608332605F20C0032A5DC /* CoreTelephony.framework */, - 033608312605F1F10032A5DC /* SystemConfiguration.framework */, - 0336082F2605F1E30032A5DC /* CoreServices.framework */, - 815FC6A40AFE1F218C25C738 /* Pods_TestDeepLinking.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - FBA3F883B3850B5894EAA121 /* Pods */ = { - isa = PBXGroup; - children = ( - 86113F63A46AE44E1E8B1648 /* Pods-TestDeepLinking.debug.xcconfig */, - 0EE470FCEAEA1ECC99DC0A89 /* Pods-TestDeepLinking.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 032DAED92607430600891641 /* TestDeepLinkingUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 032DAEE12607430600891641 /* Build configuration list for PBXNativeTarget "TestDeepLinkingUITests" */; - buildPhases = ( - 032DAED62607430600891641 /* Sources */, - 032DAED72607430600891641 /* Frameworks */, - 032DAED82607430600891641 /* Resources */, - 032DAF0826074B6A00891641 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - 032DAEE02607430600891641 /* PBXTargetDependency */, - ); - name = TestDeepLinkingUITests; - productName = TestDeepLinkingUITests; - productReference = 032DAEDA2607430600891641 /* TestDeepLinkingUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; - 032DAEFA2607491B00891641 /* TestDeepLinkingUITestsWithHostApp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 032DAF022607491B00891641 /* Build configuration list for PBXNativeTarget "TestDeepLinkingUITestsWithHostApp" */; - buildPhases = ( - 032DAEF72607491B00891641 /* Sources */, - 032DAEF82607491B00891641 /* Frameworks */, - 032DAEF92607491B00891641 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 032DAF012607491B00891641 /* PBXTargetDependency */, - ); - name = TestDeepLinkingUITestsWithHostApp; - productName = TestDeepLinkingUITestsWithHostApp; - productReference = 032DAEFB2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; - 033608112605E2110032A5DC /* TestDeepLinking */ = { - isa = PBXNativeTarget; - buildConfigurationList = 033608262605E2150032A5DC /* Build configuration list for PBXNativeTarget "TestDeepLinking" */; - buildPhases = ( - A6E708B8F29A1D55D1D76DE9 /* [CP] Check Pods Manifest.lock */, - 0336080E2605E2110032A5DC /* Sources */, - 0336080F2605E2110032A5DC /* Frameworks */, - 033608102605E2110032A5DC /* Resources */, - 249508BA477D5282ACF2EE9E /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = TestDeepLinking; - productName = TestDeepLinking; - productReference = 033608122605E2110032A5DC /* TestDeepLinking.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 0336080A2605E2100032A5DC /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1200; - LastUpgradeCheck = 1200; - TargetAttributes = { - 032DAED92607430600891641 = { - CreatedOnToolsVersion = 12.3; - }; - 032DAEFA2607491B00891641 = { - CreatedOnToolsVersion = 12.3; - TestTargetID = 033608112605E2110032A5DC; - }; - 033608112605E2110032A5DC = { - CreatedOnToolsVersion = 12.0.1; - LastSwiftMigration = 1230; - }; - }; - }; - buildConfigurationList = 0336080D2605E2100032A5DC /* Build configuration list for PBXProject "TestDeepLinking" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 033608092605E2100032A5DC; - productRefGroup = 033608132605E2110032A5DC /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 033608112605E2110032A5DC /* TestDeepLinking */, - 032DAED92607430600891641 /* TestDeepLinkingUITests */, - 032DAEFA2607491B00891641 /* TestDeepLinkingUITestsWithHostApp */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 032DAED82607430600891641 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 032DAEF92607491B00891641 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 033608102605E2110032A5DC /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03DE13B32606A1B4006D18F5 /* TestDeepLinking.entitlements in Resources */, - 033608222605E2150032A5DC /* LaunchScreen.storyboard in Resources */, - 0336081F2605E2150032A5DC /* Assets.xcassets in Resources */, - 0336081D2605E2110032A5DC /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 032DAF0826074B6A00891641 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "xcrun simctl terminate booted io.branch.TestiOSDeepLink\nxcrun simctl uninstall booted io.branch.TestiOSDeepLink\n\n"; - }; - 249508BA477D5282ACF2EE9E /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - A6E708B8F29A1D55D1D76DE9 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-TestDeepLinking-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 032DAED62607430600891641 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 032DAEE82607431D00891641 /* TestDeepLinkWithoutApp.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 032DAEF72607491B00891641 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 032DAEFE2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0336080E2605E2110032A5DC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0336081A2605E2110032A5DC /* ViewController.swift in Sources */, - 033608162605E2110032A5DC /* AppDelegate.swift in Sources */, - 033608182605E2110032A5DC /* SceneDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 032DAEE02607430600891641 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 033608112605E2110032A5DC /* TestDeepLinking */; - targetProxy = 032DAEDF2607430600891641 /* PBXContainerItemProxy */; - }; - 032DAF012607491B00891641 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 033608112605E2110032A5DC /* TestDeepLinking */; - targetProxy = 032DAF002607491B00891641 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 0336081B2605E2110032A5DC /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 0336081C2605E2110032A5DC /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 033608202605E2150032A5DC /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 033608212605E2150032A5DC /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 032DAEE22607430600891641 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XHGU2TWQZE; - INFOPLIST_FILE = TestDeepLinkingUITests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.trusona.TestDeepLinkingUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 032DAEE32607430600891641 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XHGU2TWQZE; - INFOPLIST_FILE = TestDeepLinkingUITests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.trusona.TestDeepLinkingUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 032DAF032607491B00891641 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XHGU2TWQZE; - INFOPLIST_FILE = TestDeepLinkingUITestsWithHostApp/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.trusona.TestDeepLinkingUITestsWithHostApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestDeepLinking; - }; - name = Debug; - }; - 032DAF042607491B00891641 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XHGU2TWQZE; - INFOPLIST_FILE = TestDeepLinkingUITestsWithHostApp/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.trusona.TestDeepLinkingUITestsWithHostApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestDeepLinking; - }; - name = Release; - }; - 033608242605E2150032A5DC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 033608252605E2150032A5DC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 033608272605E2150032A5DC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 86113F63A46AE44E1E8B1648 /* Pods-TestDeepLinking.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = TestDeepLinking/TestDeepLinking.entitlements; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = R63EM248DP; - EXCLUDED_ARCHS = arm64; - INFOPLIST_FILE = TestDeepLinking/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestiOSDeepLink; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Debug; - }; - 033608282605E2150032A5DC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0EE470FCEAEA1ECC99DC0A89 /* Pods-TestDeepLinking.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = TestDeepLinking/TestDeepLinking.entitlements; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = R63EM248DP; - EXCLUDED_ARCHS = arm64; - INFOPLIST_FILE = TestDeepLinking/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestiOSDeepLink; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 032DAEE12607430600891641 /* Build configuration list for PBXNativeTarget "TestDeepLinkingUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 032DAEE22607430600891641 /* Debug */, - 032DAEE32607430600891641 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 032DAF022607491B00891641 /* Build configuration list for PBXNativeTarget "TestDeepLinkingUITestsWithHostApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 032DAF032607491B00891641 /* Debug */, - 032DAF042607491B00891641 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0336080D2605E2100032A5DC /* Build configuration list for PBXProject "TestDeepLinking" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 033608242605E2150032A5DC /* Debug */, - 033608252605E2150032A5DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 033608262605E2150032A5DC /* Build configuration list for PBXNativeTarget "TestDeepLinking" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 033608272605E2150032A5DC /* Debug */, - 033608282605E2150032A5DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 0336080A2605E2100032A5DC /* Project object */; -} diff --git a/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/TestDeepLinking/TestDeepLinking.xcworkspace/contents.xcworkspacedata b/TestDeepLinking/TestDeepLinking.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index ba8e3820e..000000000 --- a/TestDeepLinking/TestDeepLinking.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/TestDeepLinking/TestDeepLinking.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TestDeepLinking/TestDeepLinking.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/TestDeepLinking/TestDeepLinking.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/TestDeepLinking/TestDeepLinking/AppDelegate.swift b/TestDeepLinking/TestDeepLinking/AppDelegate.swift deleted file mode 100644 index 8f1e6984d..000000000 --- a/TestDeepLinking/TestDeepLinking/AppDelegate.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// AppDelegate.swift -// TestDeepLinking -// -// Created by Nidhi on 3/20/21. -// - -import UIKit -import Branch - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - - BranchScene.shared().initSession(launchOptions: launchOptions, registerDeepLinkHandler: { (params, error, scene) in - let presentedVC : ViewController = UIApplication.shared.keyWindow?.rootViewController as! ViewController - let jsonData = try! JSONSerialization.data(withJSONObject:params, options: JSONSerialization.WritingOptions.prettyPrinted) - - let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String - - presentedVC.addText(jsonString) - }) - return true - } - - // MARK: UISceneSession Lifecycle - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - // Called when a new scene session is being created. - // Use this method to select a configuration to create the new scene with. - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - - func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { - // Called when the user discards a scene session. - // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. - // Use this method to release any resources that were specific to the discarded scenes, as they will not return. - } - - -} - diff --git a/TestDeepLinking/TestDeepLinking/Assets.xcassets/AccentColor.colorset/Contents.json b/TestDeepLinking/TestDeepLinking/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb8789700..000000000 --- a/TestDeepLinking/TestDeepLinking/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestDeepLinking/TestDeepLinking/Assets.xcassets/AppIcon.appiconset/Contents.json b/TestDeepLinking/TestDeepLinking/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9221b9bb1..000000000 --- a/TestDeepLinking/TestDeepLinking/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestDeepLinking/TestDeepLinking/Assets.xcassets/Contents.json b/TestDeepLinking/TestDeepLinking/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596a..000000000 --- a/TestDeepLinking/TestDeepLinking/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestDeepLinking/TestDeepLinking/Base.lproj/LaunchScreen.storyboard b/TestDeepLinking/TestDeepLinking/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 865e9329f..000000000 --- a/TestDeepLinking/TestDeepLinking/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TestDeepLinking/TestDeepLinking/Base.lproj/Main.storyboard b/TestDeepLinking/TestDeepLinking/Base.lproj/Main.storyboard deleted file mode 100644 index 99cb43c0a..000000000 --- a/TestDeepLinking/TestDeepLinking/Base.lproj/Main.storyboard +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TestDeepLinking/TestDeepLinking/Info.plist b/TestDeepLinking/TestDeepLinking/Info.plist deleted file mode 100644 index 74d99de4a..000000000 --- a/TestDeepLinking/TestDeepLinking/Info.plist +++ /dev/null @@ -1,79 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLSchemes - - testiOSDeepLink - - - - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneConfigurationName - Default Configuration - UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main - - - - - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - branch_key - key_live_fk7pNcsmBjFPVS2VGlvrZaiazxkxxZ7r - - diff --git a/TestDeepLinking/TestDeepLinking/SceneDelegate.swift b/TestDeepLinking/TestDeepLinking/SceneDelegate.swift deleted file mode 100644 index dfeac44f1..000000000 --- a/TestDeepLinking/TestDeepLinking/SceneDelegate.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// SceneDelegate.swift -// TestDeepLinking -// -// Created by Nidhi on 3/20/21. -// - -import UIKit -import Branch - -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - - var window: UIWindow? - - - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - guard let _ = (scene as? UIWindowScene) else { return } - if let userActivity = connectionOptions.userActivities.first { - - BranchScene.shared().scene(scene, continue: userActivity) - } - } - - func sceneDidDisconnect(_ scene: UIScene) { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene connects. - // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). - } - - func sceneDidBecomeActive(_ scene: UIScene) { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. - } - - func sceneWillResignActive(_ scene: UIScene) { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). - } - - func sceneWillEnterForeground(_ scene: UIScene) { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. - } - - func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - } - - func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { - BranchScene.shared().scene(scene, continue: userActivity) - } - func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { - BranchScene.shared().scene(scene, openURLContexts: URLContexts) - } - - -} - diff --git a/TestDeepLinking/TestDeepLinking/TestDeepLinking.entitlements b/TestDeepLinking/TestDeepLinking/TestDeepLinking.entitlements deleted file mode 100644 index 343898fc9..000000000 --- a/TestDeepLinking/TestDeepLinking/TestDeepLinking.entitlements +++ /dev/null @@ -1,13 +0,0 @@ - - - - - com.apple.developer.associated-domains - - mnl7s.app.link - mnl7s-alternate.app.link - mnl7s.test-app.link - mnl7s-alternate.test-app.link - - - diff --git a/TestDeepLinking/TestDeepLinking/TestDeepLinking.xctestplan b/TestDeepLinking/TestDeepLinking/TestDeepLinking.xctestplan deleted file mode 100644 index 90b72d85e..000000000 --- a/TestDeepLinking/TestDeepLinking/TestDeepLinking.xctestplan +++ /dev/null @@ -1,36 +0,0 @@ -{ - "configurations" : [ - { - "id" : "21B9F7C4-BF2C-40DB-B313-9320AC57EB78", - "name" : "Configuration 1", - "options" : { - - } - } - ], - "defaultOptions" : { - "codeCoverage" : false, - "targetForVariableExpansion" : { - "containerPath" : "container:TestDeepLinking.xcodeproj", - "identifier" : "033608112605E2110032A5DC", - "name" : "TestDeepLinking" - } - }, - "testTargets" : [ - { - "target" : { - "containerPath" : "container:TestDeepLinking.xcodeproj", - "identifier" : "032DAED92607430600891641", - "name" : "TestDeepLinkingUITests" - } - }, - { - "target" : { - "containerPath" : "container:TestDeepLinking.xcodeproj", - "identifier" : "032DAEFA2607491B00891641", - "name" : "TestDeepLinkingUITestsWithHostApp" - } - } - ], - "version" : 1 -} diff --git a/TestDeepLinking/TestDeepLinking/ViewController.swift b/TestDeepLinking/TestDeepLinking/ViewController.swift deleted file mode 100644 index 0f5a341aa..000000000 --- a/TestDeepLinking/TestDeepLinking/ViewController.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// ViewController.swift -// TestDeepLinking -// -// Created by Nidhi on 3/20/21. -// - -import UIKit - -class ViewController: UIViewController { - - @IBOutlet var textView: UITextView! - override func viewDidLoad() { - super.viewDidLoad() - } - - func addText(_ text: String) { - textView.text = "" - textView.insertText(text) - } -} - diff --git a/TestDeepLinking/TestDeepLinkingUITests/Info.plist b/TestDeepLinking/TestDeepLinkingUITests/Info.plist deleted file mode 100644 index 64d65ca49..000000000 --- a/TestDeepLinking/TestDeepLinkingUITests/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/TestDeepLinking/TestDeepLinkingUITests/TestDeepLinkWithoutApp.m b/TestDeepLinking/TestDeepLinkingUITests/TestDeepLinkWithoutApp.m deleted file mode 100644 index 22a741930..000000000 --- a/TestDeepLinking/TestDeepLinkingUITests/TestDeepLinkWithoutApp.m +++ /dev/null @@ -1,64 +0,0 @@ -// -// TestDeepLinkWithoutApp.m -// TestDeepLinking -// -// Created by Nidhi on 3/21/21. -// - -#import - -@interface TestDeepLinkWithoutApp : XCTestCase - -@end - -@implementation TestDeepLinkWithoutApp - -- (void)setUp { - self.continueAfterFailure = YES; - [self addUIInterruptionMonitorWithDescription:@"Open App" handler:^BOOL(XCUIElement * _Nonnull interruptingElement) { - [interruptingElement description]; - XCUIElement *button = interruptingElement.buttons[@"Open"]; - if ([button exists]) { - [button tap]; - return YES; - } - return NO; - }]; - -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. -} - -- (void)test0OpenLinkWithoutApp { - - XCUIApplication *safariApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.mobilesafari"]; - //[safariApp setLaunchArguments: @[@"-u",@"https://ndixit-branch.github.io/TestWebPage.html"]]; - [safariApp launch]; - - sleep(1.0); - [safariApp.buttons[@"URL"] tap]; - //[safariApp.otherElements[@"URL"] tap]; - [safariApp.textFields[@"Search or enter website name"] tap]; - [safariApp typeText:@"https://mnl7s.app.link/CwOJ5aTaNeb"]; - [safariApp.buttons[@"Go"] tap]; - XCUIElement *testBedLink = [[safariApp.webViews descendantsMatchingType:XCUIElementTypeLink] elementBoundByIndex:0]; - - [testBedLink tap]; - - sleep(10); - [safariApp terminate]; - -// XCUIApplication *app = [[XCUIApplication alloc] initWithBundleIdentifier:@"io.branch.TestiOSDeepLink"]; -// -// if ([ app waitForExistenceWithTimeout:5] != NO) { -// NSString *deepLinkData = app.textViews[@"DeepLinkData"].value; -// XCTAssertTrue([deepLinkData containsString:self.deeplinkDataToCheck]); -// } else { -// XCTFail("Application not launched"); -// } -// -} - -@end diff --git a/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/TestDeepLinkingUITestsWithHostApp.m b/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/TestDeepLinkingUITestsWithHostApp.m deleted file mode 100644 index 7e40b4ba8..000000000 --- a/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/TestDeepLinkingUITestsWithHostApp.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// TestDeepLinkingUITestsWithHostApp.m -// TestDeepLinkingUITestsWithHostApp -// -// Created by Nidhi on 3/21/21. -// - -#import - -@interface TestDeepLinkingUITestsWithHostApp : XCTestCase - -@end - -@implementation TestDeepLinkingUITestsWithHostApp - -- (void)setUp { - self.continueAfterFailure = YES; -} - -- (void)tearDown { -} - -- (void)test1OpenApp { - XCUIApplication *app = [[XCUIApplication alloc] init]; - [app launch]; - - sleep(3); - if ([ app waitForExistenceWithTimeout:15] != NO) { - NSString *deepLinkData = app.textViews[@"tvID"].value; - NSLog(@"==== %@" , deepLinkData); - XCTAssertTrue([deepLinkData containsString:@"https:\\/\\/mnl7s.app.link\\/CwOJ5aTaNeb"]); - } else { - XCTFail("Application not launched"); - } -} - - -@end diff --git a/TestHost/AppDelegate.swift b/TestHost/AppDelegate.swift deleted file mode 100644 index c77614d85..000000000 --- a/TestHost/AppDelegate.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// AppDelegate.swift -// TestHost -// -// Created by Ernest Cho on 7/29/22. -// - -import UIKit -import BranchSDK - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - // MARK: UISceneSession Lifecycle - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - // Called when a new scene session is being created. - // Use this method to select a configuration to create the new scene with. - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - - func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { - // Called when the user discards a scene session. - // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. - // Use this method to release any resources that were specific to the discarded scenes, as they will not return. - } - - -} - diff --git a/TestHost/Assets.xcassets/AccentColor.colorset/Contents.json b/TestHost/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb8789700..000000000 --- a/TestHost/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestHost/Assets.xcassets/AppIcon.appiconset/Contents.json b/TestHost/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9221b9bb1..000000000 --- a/TestHost/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestHost/Assets.xcassets/Contents.json b/TestHost/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596a..000000000 --- a/TestHost/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestHost/Base.lproj/LaunchScreen.storyboard b/TestHost/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 865e9329f..000000000 --- a/TestHost/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TestHost/NSURLSession+Branch.h b/TestHost/NSURLSession+Branch.h deleted file mode 100644 index 28073f0a1..000000000 --- a/TestHost/NSURLSession+Branch.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// NSURLSession+Branch.h -// BranchSearchDemo -// -// Created by Ernest Cho on 10/11/18. -// Copyright © 2018 Branch Metrics, Inc. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NSURLSession (Branch) - -@end - -NS_ASSUME_NONNULL_END diff --git a/TestHost/NSURLSession+Branch.m b/TestHost/NSURLSession+Branch.m deleted file mode 100644 index 594fc6b11..000000000 --- a/TestHost/NSURLSession+Branch.m +++ /dev/null @@ -1,64 +0,0 @@ -// -// NSURLSession+Branch.m -// BranchSearchDemo -// -// Created by Ernest Cho on 8/19/20. -// Copyright © 2020 Branch Metrics, Inc. All rights reserved. -// - -#import "NSURLSession+Branch.h" -#import - -@implementation NSURLSession (Branch) - -+ (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self swizzleSelector:@selector(dataTaskWithRequest:completionHandler:) - withSelector:@selector(xxx_dataTaskWithRequest:completionHandler:)]; - }); -} - -// swaps originalSelector with swizzledSelector -+ (void)swizzleSelector:(SEL)originalSelector withSelector:(SEL)swizzledSelector { - Class class = [self class]; - - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); - - method_exchangeImplementations(originalMethod, swizzledMethod); -} - -- (void)logNetworkTrafficRequest:(NSURLRequest *)request data:(NSData *)data response:(NSURLResponse *)response { - NSLog(@"NSURLSessionDataTask Request: %@", request); - - NSData *body = [request HTTPBody]; - if (body) { - NSLog(@"NSURLSessionDataTask Request Body: %@", [NSString stringWithUTF8String:body.bytes]); - } - - NSLog(@"NSURLSessionDataTask Response: %@", response); - - if (data.bytes) { - NSLog(@"NSURLSessionDataTask Response Data: %@", [NSString stringWithUTF8String:data.bytes]); - } -} - -// replacement method for dataTaskWithRequest -- (NSURLSessionDataTask *)xxx_dataTaskWithRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler { - - // create a new block that just calls the original block after logging the request - void (^completionHandlerWithLogging)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) { - if (completionHandler) { - - [self logNetworkTrafficRequest:request data:data response:response]; - - completionHandler(data, response, error); - } - }; - - return [self xxx_dataTaskWithRequest:request completionHandler:completionHandlerWithLogging]; -} - -@end diff --git a/TestHost/SceneDelegate.swift b/TestHost/SceneDelegate.swift deleted file mode 100644 index ee2ca8f1b..000000000 --- a/TestHost/SceneDelegate.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// SceneDelegate.swift -// TestHost -// -// Created by Ernest Cho on 7/29/22. -// - -import UIKit -import BranchSDK - -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - - var window: UIWindow? - - - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - guard let _ = (scene as? UIWindowScene) else { return } - - if let userActivity = connectionOptions.userActivities.first { - BranchScene.shared().scene(scene, continue: userActivity) - } - } - - func sceneDidDisconnect(_ scene: UIScene) { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene connects. - // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). - } - - func sceneDidBecomeActive(_ scene: UIScene) { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. - } - - func sceneWillResignActive(_ scene: UIScene) { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). - } - - func sceneWillEnterForeground(_ scene: UIScene) { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. - } - - func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - } - - -} - diff --git a/TestHost/TestHost-Bridging-Header.h b/TestHost/TestHost-Bridging-Header.h deleted file mode 100644 index 1b2cb5d6d..000000000 --- a/TestHost/TestHost-Bridging-Header.h +++ /dev/null @@ -1,4 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - diff --git a/TestHost/ViewController.swift b/TestHost/ViewController.swift deleted file mode 100644 index ab76ab909..000000000 --- a/TestHost/ViewController.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// ViewController.swift -// TestHost -// -// Created by Ernest Cho on 7/29/22. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } - - -} - diff --git a/TestHostTests/TestHostTests.swift b/TestHostTests/TestHostTests.swift deleted file mode 100644 index 231b61ed4..000000000 --- a/TestHostTests/TestHostTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// TestHostTests.swift -// TestHostTests -// -// Created by Ernest Cho on 7/29/22. -// - -import XCTest -@testable import TestHost - -class TestHostTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/TestHostUITests/TestHostUITests.swift b/TestHostUITests/TestHostUITests.swift deleted file mode 100644 index 2f5a1af58..000000000 --- a/TestHostUITests/TestHostUITests.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// TestHostUITests.swift -// TestHostUITests -// -// Created by Ernest Cho on 7/29/22. -// - -import XCTest - -class TestHostUITests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false - - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // UI tests must launch the application that they test. - let app = XCUIApplication() - app.launch() - - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testLaunchPerformance() throws { - if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { - // This measures how long it takes to launch your application. - measure(metrics: [XCTApplicationLaunchMetric()]) { - XCUIApplication().launch() - } - } - } -} diff --git a/TestHostUITests/TestHostUITestsLaunchTests.swift b/TestHostUITests/TestHostUITestsLaunchTests.swift deleted file mode 100644 index a49cc5663..000000000 --- a/TestHostUITests/TestHostUITestsLaunchTests.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// TestHostUITestsLaunchTests.swift -// TestHostUITests -// -// Created by Ernest Cho on 7/29/22. -// - -import XCTest - -class TestHostUITestsLaunchTests: XCTestCase { - - override class var runsForEachTargetApplicationUIConfiguration: Bool { - true - } - - override func setUpWithError() throws { - continueAfterFailure = false - } - - func testLaunch() throws { - let app = XCUIApplication() - app.launch() - - // Insert steps here to perform after app launch but before taking a screenshot, - // such as logging into a test account or navigating somewhere in the app - - let attachment = XCTAttachment(screenshot: app.screenshot()) - attachment.name = "Launch Screen" - attachment.lifetime = .keepAlways - add(attachment) - } -} diff --git a/fastlane/.gitignore b/fastlane/.gitignore deleted file mode 100644 index 23d325c5e..000000000 --- a/fastlane/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -report.* -test_output -README.md -.version diff --git a/fastlane/Appfile b/fastlane/Appfile deleted file mode 100644 index 180306309..000000000 --- a/fastlane/Appfile +++ /dev/null @@ -1,6 +0,0 @@ -# app_identifier("[[APP_IDENTIFIER]]") # The bundle identifier of your app -# apple_id("[[APPLE_ID]]") # Your Apple email address - - -# For more information about the Appfile, see: -# https://docs.fastlane.tools/advanced/#appfile diff --git a/fastlane/Fastfile b/fastlane/Fastfile deleted file mode 100644 index 6b9f7fda6..000000000 --- a/fastlane/Fastfile +++ /dev/null @@ -1,48 +0,0 @@ -require_relative 'lib/helper/cocoapods_helper' -require_relative 'lib/helper/version_helper' - -fastlane_version "2.69.0" - -lane :prepare_pods do - # This helps optimize CI with caching by testing whether a pod install is necessary - # from cocoapods_helper - # pod_install_if_required '../Branch-TestBed' - # Can also turn on verbose output and disable repo update - # pod_install_if_required '../Branch-TestBed', verbose: true, repo_update: false -end - -lane :unit_tests do - prepare_pods - # This testplan only runs unit tests for PR verification. - scan scheme: 'Branch-TestBed-CI' - slather( - cobertura_xml: true, - output_directory: "./fastlane/test_output", - proj: "./Branch-TestBed/Branch-TestBed.xcodeproj", - #workspace: "./Branch-TestBed/Branch-TestBed.xcworkspace", - scheme: "Branch-TestBed-CI" - ) -end - -lane :integration_tests do - prepare_pods - # This testplan includes unit tests as well as integration tests. - scan scheme: 'Branch-TestBed' -end - -# bundle exec fastlane version_bump version:patch # default -# bundle exec fastlane version_bump version:minor -# bundle exec fastlane version_bump version:major -# bundle exec fastlane version_bump version:1.41.0 -lane :version_bump do |opts| - # from version_helper - next_version = update_sdk_version opts - sh 'git', 'commit', '-a', '-m', "[release] #{next_version}" -end - -lane :current_version do - UI.message 'Generating fastlane/.version with podspec version' - File.open('.version', 'w') do |f| - f.puts current_pod_version - end -end diff --git a/fastlane/Matchfile b/fastlane/Matchfile deleted file mode 100644 index e8fc3631e..000000000 --- a/fastlane/Matchfile +++ /dev/null @@ -1,14 +0,0 @@ -# branch private repo for fastlane match -git_url("git@github.com:BranchMetrics/ios-signing-certificates.git") - -storage_mode("git") - -type("development") # The default type, can be: appstore, adhoc, enterprise or development - -app_identifier(["io.branch.sdk.Branch-TestBed"]) -username("sdk-team@branch.io") - -# For all available options run `fastlane match --help` -# Remove the # in the beginning of the line to enable the other options - -# The docs are available on https://docs.fastlane.tools/actions/match diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile deleted file mode 100644 index e69de29bb..000000000 diff --git a/fastlane/Scanfile b/fastlane/Scanfile deleted file mode 100644 index 11cd4873f..000000000 --- a/fastlane/Scanfile +++ /dev/null @@ -1,6 +0,0 @@ -project 'Branch-TestBed/Branch-TestBed.xcodeproj' -device 'iPhone 12' -output_types 'junit,html' -code_coverage true -clean true -output_directory 'fastlane/test_output/' \ No newline at end of file diff --git a/fastlane/lib/helper/cocoapods_helper.rb b/fastlane/lib/helper/cocoapods_helper.rb deleted file mode 100644 index fe71d4dee..000000000 --- a/fastlane/lib/helper/cocoapods_helper.rb +++ /dev/null @@ -1,86 +0,0 @@ -require 'cocoapods' -require 'pathname' - -module CocoapodsHelper - UI = FastlaneCore::UI - - class CocoapodsHelperException < RuntimeError; end - - # Following the lead of npm ci (https://docs.npmjs.com/cli/v7/commands/npm-ci): - # The Podfile.lock must exist. - # The Podfile and Podfile.lock must be in sync. - # A pod install may be required, but it is an error to generate a change to - # the Podfile.lock, including when it's missing. If pod install is run, it - # may regenerate Pods/Manifest.lock or the entire Pods folder if the cache - # is out of sync. - def pod_install_required?(podfile_folder) - podfile_folder = File.expand_path podfile_folder - podfile_path = File.join podfile_folder, 'Podfile' - raise ArgumentError, "No Podfile at #{podfile_folder}" unless File.readable?(podfile_path) - - # Podfile must be evalled in its current directory in order to resolve - # the require_relative at the top. - podfile = Dir.chdir(podfile_folder) { Pod::Podfile.from_file podfile_path } - - # From here on we expect pod install to succeed. We just check whether it's - # necessary. The Podfile.from_file call above can raise if the Podfile - # contains errors. In that case, pod install will also fail, so we allow - # the exception to be raised instead of returning true. - - lockfile_path = File.join podfile_folder, 'Podfile.lock' - manifest_path = File.join podfile_folder, 'Pods', 'Manifest.lock' - - # Don't regenerate the lockfile - raise CocoapodsHelperException, "#{lockfile_path} missing or not readable." unless File.readable?(lockfile_path) - - return true unless File.readable?(manifest_path) - - # This validates the Podfile.lock for yaml formatting at least and makes - # the lockfile hash available to check the Podfile checksum later. - lockfile = Pod::Lockfile.from_file Pathname.new lockfile_path - lockfile_contents = File.read lockfile_path - - begin - # diff the contents of Podfile.lock and Pods/Manifest.lock - # This is just what is done in the "[CP] Check Pods Manifest.lock" script - # build phase in a project using CocoaPods. This is a stricter requirement - # than semantic comparison of the two lockfile hashes. - return true unless lockfile_contents == File.read(manifest_path) - - # compare checksum of Podfile with checksum in Podfile.lock in case Podfile - # updated since last pod install/update. - return false if lockfile.to_hash["PODFILE CHECKSUM"] == podfile.checksum - rescue StandardError, Pod::PlainInformative => e - # Any error from Pod::Lockfile.from_file or File.read after verifying a - # file exists and is readable. pod install will regenerate these files. - UI.error e.message - return true - end - - # Don't regenerate the lockfile. - raise CocoapodsHelperException, "Podfile checksum #{podfile.checksum} does not match PODFILE CHECKSUM in Podfile.lock." - end - - def pod_install_if_required(podfile_folder, verbose: false, repo_update: true) - podfile_folder = File.expand_path podfile_folder - install_required = pod_install_required? podfile_folder - UI.message "pod install #{install_required ? '' : 'not '}required in #{podfile_folder}" - return unless install_required - - command = %w[pod install] - command << '--silent' unless verbose - command << '--repo-update' if repo_update - - Dir.chdir(podfile_folder) { Fastlane::Action.sh(*command) } - end - - def current_pod_version - # Get current version from podspec - podspec = File.open('../BranchSDK.podspec', 'r') do |f| - eval f.read - end - podspec.version - end -end - -include CocoapodsHelper diff --git a/fastlane/lib/helper/version_helper.rb b/fastlane/lib/helper/version_helper.rb deleted file mode 100644 index 5bde29d52..000000000 --- a/fastlane/lib/helper/version_helper.rb +++ /dev/null @@ -1,89 +0,0 @@ -require 'CFPropertyList' -require 'pattern_patch' -require 'xcodeproj' - -module VersionHelper - # Updates the SDK version from the Fastfile lane opts - def update_sdk_version(opts) - # Shell out to agvtool to increment the build number - Dir.chdir('../carthage-files') { Fastlane::Action.sh(%w[agvtool bump]) } - # Update the MARKETING_VERSION using patch, minor, major or an actual version number - next_version = update_project_marketing_version '../carthage-files/BranchSDK.xcodeproj', opts[:version] - - # Update BNCConfig.m - PatternPatch::Patch.new( - regexp: /(BNC_SDK_VERSION.*@")(.*)(";)/, - text: "\\1#{next_version}\\3", - mode: :replace - ).apply '../Branch-SDK/BNCConfig.m' - - # Update Branch.podspec - PatternPatch::Patch.new( - regexp: /(s.version.*=\s*")(.*)(")/, - text: "\\1#{next_version}\\3", - mode: :replace - ).apply '../Branch.podspec' - - update_testbed_framework_info_plist next_version - - next_version - end - - # agvtool doesn't do this for the marketing version - # Pass an actual version or major, minor or patch for an automatic bump - # If the version includes a suffix like -beta.1, that will be removed in - # the automatic bump. - def new_version(version, next_version) - # Remove any suffix beginning with a hyphen, e.g. 1.2.3-beta.1 -> 1.2.3 - components = version.sub(/-.*$/, '').split '.' - - case next_version - when 'patch', nil - components[2] = components[2].to_i + 1 - when 'minor' - components[1] = components[1].to_i + 1 - when 'major' - components[0] = components[0].to_i + 1 - else - return next_version - end - - components.join '.' - end - - # Update MARKETING_VERSION to the specified version in the specified project - # at project_path. - def update_project_marketing_version(project_path, version) - # raises - project = Xcodeproj::Project.open project_path - framework_targets = project.native_targets.reject &:test_target_type? - current_marketing_version = framework_targets.first.resolved_build_setting('MARKETING_VERSION')['Release'] - - next_version = new_version current_marketing_version, version - - # TODO: Isn't this a project-level setting? - framework_targets.reject(&:test_target_type?).each do |target| - target.build_configuration_list.set_setting 'MARKETING_VERSION', next_version - end - - # raises - project.save - - next_version - end - - def update_testbed_framework_info_plist(marketing_version) - plist = CFPropertyList::List.new file: '../Branch-TestBed/Framework-Info.plist' - data = CFPropertyList.native_types(plist.value) - - data['CFBundleShortVersionString'] = marketing_version - # Ordinarily CFBundleVersion is the project version (build number), not the marketing version - # Following the lead of the existing script here. - data['CFBundleVersion'] = marketing_version - - plist.value = CFPropertyList.guess data - plist.save '../Branch-TestBed/Framework-Info.plist', CFPropertyList::List::FORMAT_BINARY - end -end - -include VersionHelper