diff --git a/.github/workflows/draft-new-beta-release.yml b/.github/workflows/draft-new-beta-release.yml index e248c328..9e7d58ce 100644 --- a/.github/workflows/draft-new-beta-release.yml +++ b/.github/workflows/draft-new-beta-release.yml @@ -10,8 +10,8 @@ on: jobs: draft-new-beta-release: name: Draft a new Beta release - runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/heads/fix/') || startsWith(github.ref, 'refs/heads/feat/') + runs-on: macOS-latest + if: startsWith(github.ref, 'refs/heads/fix/') || startsWith(github.ref, 'refs/heads/feat/') || startsWith(github.ref, 'refs/heads/feature/') steps: - name: Checkout source branch uses: actions/checkout@v4 diff --git a/.github/workflows/publish-new-release.yml b/.github/workflows/publish-new-release.yml index 6355543f..4f5e0d32 100644 --- a/.github/workflows/publish-new-release.yml +++ b/.github/workflows/publish-new-release.yml @@ -10,7 +10,7 @@ on: jobs: release: name: Publish new release - runs-on: macOS-latest + runs-on: ubuntu-latest if: (startsWith(github.event.pull_request.head.ref, 'release/') || startsWith(github.event.pull_request.head.ref, 'hotfix-release/')) && github.event.pull_request.merged == true # only merged pull requests must trigger this job steps: - name: Extract version from branch name (for release branches) @@ -47,28 +47,6 @@ jobs: run: | DEBUG=conventional-github-releaser npx conventional-github-releaser -p angular --config github-release.config.js - - name: Install xcpretty - run: gem install xcpretty - - - name: Install Cocoapods - run: gem install cocoapods - - - name: Pod install - run: pod install --repo-update - - - name: Generate XCFramework - run: | - sh ./scripts/generate-xcframework.sh - - - name: Upload Release Artifact - run: | - zip -r Rudder-xcframeworks.zip xcframeworks - shasum -a 256 Rudder-xcframeworks.zip >Rudder-xcframeworks.sha256 - gh release upload v${{ steps.extract-version.outputs.release_version }} Rudder-xcframeworks.zip - gh release upload v${{ steps.extract-version.outputs.release_version }} Rudder-xcframeworks.sha256 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Create pull request into develop uses: repo-sync/pull-request@v2 with: @@ -94,3 +72,43 @@ jobs: branches: "release/*" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + xcframework: + name: Generate and Upload XCFramework + runs-on: macos-latest + needs: release + steps: + - name: Extract version from branch name (for release branches) + id: extract-version + run: | + BRANCH_NAME="${{ github.event.pull_request.head.ref }}" + VERSION=${BRANCH_NAME#hotfix-} + VERSION=${VERSION#release/} + echo "release_version=$VERSION" >> $GITHUB_OUTPUT + + - name: Checkout source branch + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install xcpretty + run: gem install xcpretty + + - name: Install Cocoapods + run: gem install cocoapods + + - name: Pod install + run: pod install --repo-update + + - name: Generate XCFramework + run: | + sh ./scripts/generate-xcframework.sh + + - name: Upload Release Artifact + run: | + zip -r Rudder-xcframeworks.zip xcframeworks + shasum -a 256 Rudder-xcframeworks.zip >Rudder-xcframeworks.sha256 + gh release upload v${{ steps.extract-version.outputs.release_version }} Rudder-xcframeworks.zip + gh release upload v${{ steps.extract-version.outputs.release_version }} Rudder-xcframeworks.sha256 + env: + GH_TOKEN: ${{ secrets.PAT }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eff5218..c8b59d7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,34 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.25.1](https://github.com/rudderlabs/rudder-sdk-ios/compare/v1.25.0...v1.25.1) (2024-02-07) + + +### Bug Fixes + +* correct file name of LICENSE.md file in Podspec ([#465](https://github.com/rudderlabs/rudder-sdk-ios/issues/465)) ([c46edc6](https://github.com/rudderlabs/rudder-sdk-ios/commit/c46edc64ffb39a44bb5e6d4f37247a68c72d3d18)) + +## [1.25.0](https://github.com/rudderlabs/rudder-sdk-ios/compare/v1.24.2...v1.25.0) (2024-02-05) + + +### Features + +* add privacy manifest file to ios sdk ([#453](https://github.com/rudderlabs/rudder-sdk-ios/issues/453)) ([0b1b207](https://github.com/rudderlabs/rudder-sdk-ios/commit/0b1b2077ffc00bdfa34082e1d4b5ac1b48569b15)) + + +### Bug Fixes + +* handling the serialization of special floating point values while serializing any object ([#447](https://github.com/rudderlabs/rudder-sdk-ios/issues/447)) ([50d06a6](https://github.com/rudderlabs/rudder-sdk-ios/commit/50d06a68742c7da0160b398801616dda2662cc3b)) +* nil check errors after de-serialization ([#460](https://github.com/rudderlabs/rudder-sdk-ios/issues/460)) ([abd6dc3](https://github.com/rudderlabs/rudder-sdk-ios/commit/abd6dc3b381d70f048a208dd217f28d51db1654f)) +* sending detailed device model (context.device.model) info in granular detail. Eg: As `iPhone 13,1` for `iPhone 12 Mini` instead of just `iPhone` ([#448](https://github.com/rudderlabs/rudder-sdk-ios/issues/448)) ([ec8e9d3](https://github.com/rudderlabs/rudder-sdk-ios/commit/ec8e9d3c6911c010cbd68130a92ef895d4bde183)) + +### [1.24.2](https://github.com/rudderlabs/rudder-sdk-ios/compare/v1.24.1...v1.24.2) (2024-01-03) + + +### Bug Fixes + +* updated version of MetricsReporter in package.swift ([#433](https://github.com/rudderlabs/rudder-sdk-ios/issues/433)) ([8870ccd](https://github.com/rudderlabs/rudder-sdk-ios/commit/8870ccd41e3341e75edd8882fa2c12b33283ba9f)) + ### [1.24.1](https://github.com/rudderlabs/rudder-sdk-ios/compare/v1.24.0...v1.24.1) (2023-12-20) ## [1.24.0](https://github.com/rudderlabs/rudder-sdk-ios/compare/v1.23.1...v1.24.0) (2023-12-18) diff --git a/Examples/RudderSampleApptvOSObjC/RudderSampleApptvOSObjC.xcodeproj/project.pbxproj b/Examples/RudderSampleApptvOSObjC/RudderSampleApptvOSObjC.xcodeproj/project.pbxproj index e1fda393..f6716158 100644 --- a/Examples/RudderSampleApptvOSObjC/RudderSampleApptvOSObjC.xcodeproj/project.pbxproj +++ b/Examples/RudderSampleApptvOSObjC/RudderSampleApptvOSObjC.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 601AB269529B9CADA5EC9AC8 /* Pods_RudderSampleApptvOSObjC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38BCBDFF738EC338B5CA07E0 /* Pods_RudderSampleApptvOSObjC.framework */; }; - ED0CA6E72A7D058100899C1C /* RudderConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = ED0CA6E42A7D058100899C1C /* RudderConfig.plist */; }; ED0CA6E82A7D058100899C1C /* SampleRudderConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = ED0CA6E52A7D058100899C1C /* SampleRudderConfig.plist */; }; ED0CA6E92A7D058100899C1C /* RudderConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0CA6E62A7D058100899C1C /* RudderConfig.swift */; }; F636324327291C0D0086D05A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F636324227291C0D0086D05A /* AppDelegate.m */; }; @@ -17,6 +16,7 @@ F636324B27291C0F0086D05A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F636324A27291C0F0086D05A /* Assets.xcassets */; }; F636324E27291C0F0086D05A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F636324C27291C0F0086D05A /* LaunchScreen.storyboard */; }; F636325027291C0F0086D05A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F636324F27291C0F0086D05A /* main.m */; }; + F641160A2B6C2E170015CB42 /* RudderConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = F64116092B6C2E170015CB42 /* RudderConfig.plist */; }; F6FDD63F27296E910024E78F /* CustomIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = F6FDD63B27296E910024E78F /* CustomIntegration.m */; }; F6FDD64027296E910024E78F /* CustomFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = F6FDD63C27296E910024E78F /* CustomFactory.m */; }; /* End PBXBuildFile section */ @@ -26,7 +26,6 @@ 3B292BF359E4526CC983C4B1 /* Pods-RudderSampleApptvOSObjC.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderSampleApptvOSObjC.debug.xcconfig"; path = "Target Support Files/Pods-RudderSampleApptvOSObjC/Pods-RudderSampleApptvOSObjC.debug.xcconfig"; sourceTree = ""; }; D3066D19C139C74D40518844 /* Pods-RudderSampleApptvOSObjC.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderSampleApptvOSObjC.release.xcconfig"; path = "Target Support Files/Pods-RudderSampleApptvOSObjC/Pods-RudderSampleApptvOSObjC.release.xcconfig"; sourceTree = ""; }; ED0CA6E02A7D057800899C1C /* RudderSampleApptvOSObjC-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RudderSampleApptvOSObjC-Bridging-Header.h"; sourceTree = ""; }; - ED0CA6E42A7D058100899C1C /* RudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = RudderConfig.plist; sourceTree = ""; }; ED0CA6E52A7D058100899C1C /* SampleRudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SampleRudderConfig.plist; sourceTree = ""; }; ED0CA6E62A7D058100899C1C /* RudderConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RudderConfig.swift; sourceTree = ""; }; F636323E27291C0D0086D05A /* RudderSampleApptvOSObjC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RudderSampleApptvOSObjC.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -41,6 +40,7 @@ F636325727291C640086D05A /* Rudder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Rudder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F636325B27291D4A0086D05A /* Rudder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Rudder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F636325F27291EBC0086D05A /* Rudder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Rudder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F64116092B6C2E170015CB42 /* RudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = RudderConfig.plist; sourceTree = ""; }; F6FDD63B27296E910024E78F /* CustomIntegration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomIntegration.m; sourceTree = ""; }; F6FDD63C27296E910024E78F /* CustomFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomFactory.m; sourceTree = ""; }; F6FDD63D27296E910024E78F /* CustomIntegration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomIntegration.h; sourceTree = ""; }; @@ -72,7 +72,6 @@ ED0CA6E32A7D058100899C1C /* RudderConfig */ = { isa = PBXGroup; children = ( - ED0CA6E42A7D058100899C1C /* RudderConfig.plist */, ED0CA6E52A7D058100899C1C /* SampleRudderConfig.plist */, ED0CA6E62A7D058100899C1C /* RudderConfig.swift */, ); @@ -101,6 +100,7 @@ F636324027291C0D0086D05A /* RudderSampleApptvOSObjC */ = { isa = PBXGroup; children = ( + F64116092B6C2E170015CB42 /* RudderConfig.plist */, ED0CA6E32A7D058100899C1C /* RudderConfig */, F636324127291C0D0086D05A /* AppDelegate.h */, F636324227291C0D0086D05A /* AppDelegate.m */, @@ -190,8 +190,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - ED0CA6E72A7D058100899C1C /* RudderConfig.plist in Resources */, F636324E27291C0F0086D05A /* LaunchScreen.storyboard in Resources */, + F641160A2B6C2E170015CB42 /* RudderConfig.plist in Resources */, ED0CA6E82A7D058100899C1C /* SampleRudderConfig.plist in Resources */, F636324B27291C0F0086D05A /* Assets.xcassets in Resources */, F636324927291C0D0086D05A /* Main.storyboard in Resources */, diff --git a/Examples/RudderSampleAppwatchOSObjC/RudderSampleAppwatchOSObjC.xcodeproj/project.pbxproj b/Examples/RudderSampleAppwatchOSObjC/RudderSampleAppwatchOSObjC.xcodeproj/project.pbxproj index 9c3c6c27..dbf6eba3 100644 --- a/Examples/RudderSampleAppwatchOSObjC/RudderSampleAppwatchOSObjC.xcodeproj/project.pbxproj +++ b/Examples/RudderSampleAppwatchOSObjC/RudderSampleAppwatchOSObjC.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 9FE3D0956553F6943CE0B97E /* Pods_RudderSampleAppwatchOSObjC_WatchKit_Extension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 868D4D5936FB0FE3FC86FD07 /* Pods_RudderSampleAppwatchOSObjC_WatchKit_Extension.framework */; }; - ED0CA6FD2A7D0A3300899C1C /* RudderConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = ED0CA6FA2A7D0A3300899C1C /* RudderConfig.plist */; }; ED0CA6FE2A7D0A3300899C1C /* SampleRudderConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = ED0CA6FB2A7D0A3300899C1C /* SampleRudderConfig.plist */; }; ED0CA6FF2A7D0A3300899C1C /* RudderConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0CA6FC2A7D0A3300899C1C /* RudderConfig.swift */; }; F6F43B902757417F0036CC12 /* RudderSampleAppwatchOSObjC WatchKit App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = F6F43B8F2757417F0036CC12 /* RudderSampleAppwatchOSObjC WatchKit App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -69,7 +68,6 @@ B2D78A99EAE3F5AD5397B003 /* Pods-RudderSampleAppwatchOSObjC WatchKit Extension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderSampleAppwatchOSObjC WatchKit Extension.release.xcconfig"; path = "Target Support Files/Pods-RudderSampleAppwatchOSObjC WatchKit Extension/Pods-RudderSampleAppwatchOSObjC WatchKit Extension.release.xcconfig"; sourceTree = ""; }; EBDE6B2F2AB87F17F98D5D23 /* Pods-RudderSampleAppwatchOSObjC WatchKit Extension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderSampleAppwatchOSObjC WatchKit Extension.debug.xcconfig"; path = "Target Support Files/Pods-RudderSampleAppwatchOSObjC WatchKit Extension/Pods-RudderSampleAppwatchOSObjC WatchKit Extension.debug.xcconfig"; sourceTree = ""; }; ED0CA6F62A7D0A2600899C1C /* RudderSampleAppwatchOSObjC WatchKit Extension-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RudderSampleAppwatchOSObjC WatchKit Extension-Bridging-Header.h"; sourceTree = ""; }; - ED0CA6FA2A7D0A3300899C1C /* RudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = RudderConfig.plist; sourceTree = ""; }; ED0CA6FB2A7D0A3300899C1C /* SampleRudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SampleRudderConfig.plist; sourceTree = ""; }; ED0CA6FC2A7D0A3300899C1C /* RudderConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RudderConfig.swift; sourceTree = ""; }; F6F43B8B2757417E0036CC12 /* RudderSampleAppwatchOSObjC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RudderSampleAppwatchOSObjC.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -137,7 +135,6 @@ ED0CA6F92A7D0A3300899C1C /* RudderConfig */ = { isa = PBXGroup; children = ( - ED0CA6FA2A7D0A3300899C1C /* RudderConfig.plist */, ED0CA6FB2A7D0A3300899C1C /* SampleRudderConfig.plist */, ED0CA6FC2A7D0A3300899C1C /* RudderConfig.swift */, ); @@ -315,7 +312,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - ED0CA6FD2A7D0A3300899C1C /* RudderConfig.plist in Resources */, F6F43BAF275741820036CC12 /* Assets.xcassets in Resources */, ED0CA6FE2A7D0A3300899C1C /* SampleRudderConfig.plist in Resources */, ); diff --git a/Package.resolved b/Package.resolved index 9120172c..73744db1 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/rudderlabs/crash-reporter-ios", "state": { "branch": null, - "revision": "5b7cf9025d126c4a0b363a8ba6eb1aebd11137ec", - "version": "1.0.0" + "revision": "ee563535b64d9d5feacd0fa243663b2658033a19", + "version": "1.0.1" } }, { @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/rudderlabs/metrics-reporter-ios", "state": { "branch": null, - "revision": "c0cf7734cf7befcab0cf8a9f5569ec6da1c4c35c", - "version": "1.1.0" + "revision": "c5fe7cc861a83ec75978a516c02398c2a2cb1f20", + "version": "1.2.1" } }, { diff --git a/Package.swift b/Package.swift index 0411764b..bc9caf7c 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.2 +// swift-tools-version:5.3 import PackageDescription @@ -24,6 +24,9 @@ let package = Package( ], path: "Sources", sources: ["Classes/"], + resources: [ + .copy("PrivacyInfo.xcprivacy") + ], publicHeadersPath: "Classes/Headers/Public/", cSettings: [ .headerSearchPath("Classes/Headers/") diff --git a/Podfile.lock b/Podfile.lock index 327c3ffd..ae552b9b 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -3,7 +3,7 @@ PODS: - RSCrashReporter (= 1.0.1) - RudderKit (= 1.4.0) - RSCrashReporter (1.0.1) - - Rudder (1.24.1): + - Rudder (1.25.0): - MetricsReporter (= 1.2.1) - RudderKit (1.4.0) - SQLCipher (4.5.4): @@ -33,10 +33,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: MetricsReporter: 99596ee5003c69949ed2f50acc34aee83c42f843 RSCrashReporter: 6b8376ac729b0289ebe0908553e5f56d8171f313 - Rudder: 8091e861028a12add1107b03d224d4abf08c597f + Rudder: 959b31df6a700432d3535b7d115afe0840d7b6c4 RudderKit: d9d6997696e1642b753d8bdf94e57af643a68f03 SQLCipher: 905b145f65f349f26da9e60a19901ad24adcd381 PODFILE CHECKSUM: b6937cee06e0633464427ff0d975d40e17419e9f -COCOAPODS: 1.14.2 +COCOAPODS: 1.14.3 diff --git a/PrivacyInfo.xcprivacy b/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..76846602 --- /dev/null +++ b/PrivacyInfo.xcprivacy @@ -0,0 +1,100 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + App Version + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + NSPrivacyCollectedDataTypePurposeAnalytics + + + + NSPrivacyCollectedDataType + App Name + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + NSPrivacyCollectedDataTypePurposeAnalytics + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeCrashData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeDeviceID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + NSPrivacyCollectedDataTypePurposeDeveloperAdvertising + NSPrivacyCollectedDataTypePurposeThirdPartyAdvertising + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeProductInteraction + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeOtherDataTypes + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyTrackingDomains + + rudderstack.com + + + diff --git a/README.md b/README.md index fa060b76..8255cf22 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@

- +

@@ -39,7 +39,7 @@ The iOS SDK is available through [**CocoaPods**](https://cocoapods.org), [**Cart To install the SDK, simply add the following line to your Podfile: ```xcode -pod 'Rudder', '1.24.1' +pod 'Rudder', '1.25.1' ``` ### Carthage @@ -47,7 +47,7 @@ pod 'Rudder', '1.24.1' For Carthage support, add the following line to your `Cartfile`: ```xcode -github "rudderlabs/rudder-sdk-ios" "v1.24.1" +github "rudderlabs/rudder-sdk-ios" "v1.25.1" ``` > Remember to include the following code in all `.m` and `.h` files where you want to refer to or use the RudderStack SDK classes, as shown: @@ -71,7 +71,7 @@ You can also add the RudderStack iOS SDK via Swift Package Mangaer, via one of t * Enter the package repository (`git@github.com:rudderlabs/rudder-sdk-ios.git`) in the search bar. -* In **Dependency Rule**, select **Up to Next Major Version** and enter `1.24.1` as the value, as shown: +* In **Dependency Rule**, select **Up to Next Major Version** and enter `1.25.1` as the value, as shown: ![Setting dependency](https://user-images.githubusercontent.com/59817155/145574696-8c849749-13e0-40d5-aacb-3fccb5c8e67d.png) @@ -99,7 +99,7 @@ let package = Package( ], dependencies: [ // Dependencies declare other packages that this package depends on. - .package(url: "git@github.com:rudderlabs/rudder-sdk-ios.git", from: "1.24.1") + .package(url: "git@github.com:rudderlabs/rudder-sdk-ios.git", from: "1.25.1") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Rudder.podspec b/Rudder.podspec index a950b170..197256ac 100644 --- a/Rudder.podspec +++ b/Rudder.podspec @@ -11,10 +11,13 @@ Pod::Spec.new do |s| DESC s.homepage = "https://github.com/rudderlabs/rudder-sdk-ios" - s.license = { :type => "Apache", :file => "LICENSE" } + s.license = { :type => "Apache", :file => "LICENSE.md" } s.author = { "RudderStack" => "sdk@rudderstack.com" } s.source = { :git => "https://github.com/rudderlabs/rudder-sdk-ios.git", :tag => "v#{s.version}" } + s.resource_bundles = { s.name => 'PrivacyInfo.xcprivacy' } + + s.ios.deployment_target = '12.0' s.tvos.deployment_target = '11.0' s.watchos.deployment_target = '7.0' diff --git a/Rudder.xcodeproj/project.pbxproj b/Rudder.xcodeproj/project.pbxproj index de90c300..5546c02a 100644 --- a/Rudder.xcodeproj/project.pbxproj +++ b/Rudder.xcodeproj/project.pbxproj @@ -9,11 +9,12 @@ /* Begin PBXBuildFile section */ 06CABC332630C6B00097BEFF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06CABC322630C6B00097BEFF /* Foundation.framework */; }; 06CABC352630C6D30097BEFF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06CABC2E2630C6660097BEFF /* UIKit.framework */; }; - 238487371079D14D0B098555 /* Pods_RudderTests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8ACE1A679CAD30B58E39A88 /* Pods_RudderTests_tvOS.framework */; }; - 431F0AE2E4A192AE78D34326 /* Pods_RudderTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E491712EDB73E1E33A1C1129 /* Pods_RudderTests_iOS.framework */; }; - 9C58FA70616A3762BE1FBE9B /* Pods_Rudder_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED1B2AD2F9D4E0F26745091B /* Pods_Rudder_iOS.framework */; }; - 9FEE83571C0E25C88369FE41 /* Pods_RudderTests_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FFA1BAA6275D5530AC912B3 /* Pods_RudderTests_watchOS.framework */; }; - BF320707E73393A5EC3DB72B /* Pods_Rudder_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AB3A24BE91BE2AEE0CA3FF1 /* Pods_Rudder_watchOS.framework */; }; + 1D5DDBF3C5A9A0D68C4DCC99 /* Pods_RudderTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 568C1D5AB430F01BD4CEC4E8 /* Pods_RudderTests_iOS.framework */; }; + 538850DAB473A7B4EF67C5A1 /* Pods_RudderTests_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73BB5CB3025EF1333EC829A3 /* Pods_RudderTests_watchOS.framework */; }; + 5CC283FA80A5DD6ABCECDF5D /* Pods_RudderTests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 858E45719C417D040F7CD6E0 /* Pods_RudderTests_tvOS.framework */; }; + 69916F668AEF36CF5297393D /* Pods_Rudder_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 694E65090E456D8291C08327 /* Pods_Rudder_tvOS.framework */; }; + 8C4C8BBBE37C05B2416E6F67 /* Pods_Rudder_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBE6B383CC53988816505FCA /* Pods_Rudder_watchOS.framework */; }; + 9E5B402374D94EBF4BFAB648 /* Pods_Rudder_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A275CE257CE8C3C78CB2A16 /* Pods_Rudder_iOS.framework */; }; ED0CA6EA2A7D08B900899C1C /* RSTransformationEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F6F2FA752A53D8310025D510 /* RSTransformationEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; ED0CA6EB2A7D08B900899C1C /* RSTransformationEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F6F2FA752A53D8310025D510 /* RSTransformationEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; ED0CA6EC2A7D08D800899C1C /* RSTransformationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = F6F2FA732A53CD9F0025D510 /* RSTransformationRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -715,7 +716,6 @@ F6F2FA782A53D8520025D510 /* RSTransformationEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = F6F2FA772A53D8520025D510 /* RSTransformationEvent.m */; }; F6F2FA7A2A53D8BF0025D510 /* RSTransformationMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = F6F2FA792A53D8BF0025D510 /* RSTransformationMetadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; F6F2FA7C2A53D8E50025D510 /* RSTransformationMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = F6F2FA7B2A53D8E50025D510 /* RSTransformationMetadata.m */; }; - F7A8C3320A3B92B920A6B7EF /* Pods_Rudder_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93E378BE7E662EC3466AD22C /* Pods_Rudder_tvOS.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -743,28 +743,29 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 047016191610999BB5D6639D /* Pods-RudderTests-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-iOS.debug.xcconfig"; path = "Target Support Files/Pods-RudderTests-iOS/Pods-RudderTests-iOS.debug.xcconfig"; sourceTree = ""; }; + 024DFF0FE82BFA633C7A0ACF /* Pods-Rudder-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-tvOS.release.xcconfig"; path = "Target Support Files/Pods-Rudder-tvOS/Pods-Rudder-tvOS.release.xcconfig"; sourceTree = ""; }; 06CABB842630C3CA0097BEFF /* Rudder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Rudder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 06CABC2E2630C6660097BEFF /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 06CABC322630C6B00097BEFF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 0AB3A24BE91BE2AEE0CA3FF1 /* Pods_Rudder_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Rudder_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C12A2068DA24653A547FFC5 /* Pods-RudderTests-watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-watchOS.release.xcconfig"; path = "Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS.release.xcconfig"; sourceTree = ""; }; - 46E7849777925491E280B136 /* Pods-RudderTests-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-tvOS.release.xcconfig"; path = "Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS.release.xcconfig"; sourceTree = ""; }; - 594C68EBA69B23ED13FCDF7D /* Pods-RudderTests-watchOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-watchOS.debug.xcconfig"; path = "Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS.debug.xcconfig"; sourceTree = ""; }; - 62E2A1E694983F13BA03EB9D /* Pods-Rudder-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-iOS.release.xcconfig"; path = "Target Support Files/Pods-Rudder-iOS/Pods-Rudder-iOS.release.xcconfig"; sourceTree = ""; }; - 6725E430849222D61D5E0234 /* Pods-Rudder-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Rudder-tvOS/Pods-Rudder-tvOS.debug.xcconfig"; sourceTree = ""; }; - 67B6FB354D9492FE1F10F098 /* Pods-RudderTests-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS.debug.xcconfig"; sourceTree = ""; }; - 696BB56E6F38B30EA9E87E59 /* Pods-RudderTests-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-iOS.release.xcconfig"; path = "Target Support Files/Pods-RudderTests-iOS/Pods-RudderTests-iOS.release.xcconfig"; sourceTree = ""; }; - 6B7B1FD50E9D829FF642DF10 /* Pods-Rudder-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-tvOS.release.xcconfig"; path = "Target Support Files/Pods-Rudder-tvOS/Pods-Rudder-tvOS.release.xcconfig"; sourceTree = ""; }; - 93E378BE7E662EC3466AD22C /* Pods_Rudder_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Rudder_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9FFA1BAA6275D5530AC912B3 /* Pods_RudderTests_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RudderTests_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A1322AEF7B87457F0BB3A90F /* Pods-Rudder-watchOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-watchOS.debug.xcconfig"; path = "Target Support Files/Pods-Rudder-watchOS/Pods-Rudder-watchOS.debug.xcconfig"; sourceTree = ""; }; - A8923DB47023C19C14199A71 /* Pods-Rudder-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-iOS.debug.xcconfig"; path = "Target Support Files/Pods-Rudder-iOS/Pods-Rudder-iOS.debug.xcconfig"; sourceTree = ""; }; - A8ACE1A679CAD30B58E39A88 /* Pods_RudderTests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RudderTests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E491712EDB73E1E33A1C1129 /* Pods_RudderTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RudderTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1826685173321FC0D2D525F6 /* Pods-RudderTests-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS.debug.xcconfig"; sourceTree = ""; }; + 4C7350A8F5EF4005A9C8002C /* Pods-Rudder-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-iOS.debug.xcconfig"; path = "Target Support Files/Pods-Rudder-iOS/Pods-Rudder-iOS.debug.xcconfig"; sourceTree = ""; }; + 568C1D5AB430F01BD4CEC4E8 /* Pods_RudderTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RudderTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 588BDCDCC681265EFA53EC1A /* Pods-Rudder-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Rudder-tvOS/Pods-Rudder-tvOS.debug.xcconfig"; sourceTree = ""; }; + 59CAC564577C2DF84C1C4FA7 /* Pods-RudderTests-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-iOS.debug.xcconfig"; path = "Target Support Files/Pods-RudderTests-iOS/Pods-RudderTests-iOS.debug.xcconfig"; sourceTree = ""; }; + 694E65090E456D8291C08327 /* Pods_Rudder_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Rudder_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6A275CE257CE8C3C78CB2A16 /* Pods_Rudder_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Rudder_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6EB16DBB6C33BA3C3E7ACCF7 /* Pods-Rudder-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-iOS.release.xcconfig"; path = "Target Support Files/Pods-Rudder-iOS/Pods-Rudder-iOS.release.xcconfig"; sourceTree = ""; }; + 73BB5CB3025EF1333EC829A3 /* Pods_RudderTests_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RudderTests_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 791CB89B417016D590354A7F /* Pods-RudderTests-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-iOS.release.xcconfig"; path = "Target Support Files/Pods-RudderTests-iOS/Pods-RudderTests-iOS.release.xcconfig"; sourceTree = ""; }; + 858E45719C417D040F7CD6E0 /* Pods_RudderTests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RudderTests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8864716542CDA61025379626 /* Pods-Rudder-watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-watchOS.release.xcconfig"; path = "Target Support Files/Pods-Rudder-watchOS/Pods-Rudder-watchOS.release.xcconfig"; sourceTree = ""; }; + 8993C949BB21E74269543A5A /* Pods-RudderTests-watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-watchOS.release.xcconfig"; path = "Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS.release.xcconfig"; sourceTree = ""; }; + 94FCF9CB2A6B261F650FA34A /* Pods-RudderTests-watchOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-watchOS.debug.xcconfig"; path = "Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS.debug.xcconfig"; sourceTree = ""; }; + A5B61F726E782A95371426B4 /* Pods-RudderTests-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderTests-tvOS.release.xcconfig"; path = "Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS.release.xcconfig"; sourceTree = ""; }; + AEA654A683B9C42785EF4586 /* Pods-Rudder-watchOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-watchOS.debug.xcconfig"; path = "Target Support Files/Pods-Rudder-watchOS/Pods-Rudder-watchOS.debug.xcconfig"; sourceTree = ""; }; + CBE6B383CC53988816505FCA /* Pods_Rudder_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Rudder_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; ED04A2482986C1750080A88D /* xccov-to-generic.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "xccov-to-generic.sh"; sourceTree = ""; }; ED056314291AABFD00BAEE65 /* sonar-project.properties */ = {isa = PBXFileReference; lastKnownFileType = text; path = "sonar-project.properties"; sourceTree = ""; }; - ED1B2AD2F9D4E0F26745091B /* Pods_Rudder_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Rudder_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; ED1C4C8829E6CCC7007007C9 /* find-tag.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "find-tag.sh"; sourceTree = ""; }; ED252CF52AA8780600B17ACF /* UserSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionTests.swift; sourceTree = ""; }; ED38D36C29CB01A0003A7544 /* DataResidencyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataResidencyTests.swift; sourceTree = ""; }; @@ -1020,7 +1021,6 @@ F6F2FA772A53D8520025D510 /* RSTransformationEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RSTransformationEvent.m; sourceTree = ""; }; F6F2FA792A53D8BF0025D510 /* RSTransformationMetadata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RSTransformationMetadata.h; sourceTree = ""; }; F6F2FA7B2A53D8E50025D510 /* RSTransformationMetadata.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RSTransformationMetadata.m; sourceTree = ""; }; - F8F5D21AB948C5691AD2ADA9 /* Pods-Rudder-watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rudder-watchOS.release.xcconfig"; path = "Target Support Files/Pods-Rudder-watchOS/Pods-Rudder-watchOS.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1031,7 +1031,7 @@ 06CABC332630C6B00097BEFF /* Foundation.framework in Frameworks */, 06CABC352630C6D30097BEFF /* UIKit.framework in Frameworks */, EDEF1B312A835A90002B3E57 /* Security.framework in Frameworks */, - 9C58FA70616A3762BE1FBE9B /* Pods_Rudder_iOS.framework in Frameworks */, + 9E5B402374D94EBF4BFAB648 /* Pods_Rudder_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1041,7 +1041,7 @@ files = ( ED998F0F2A69003600031B06 /* Foundation.framework in Frameworks */, ED998F102A69003600031B06 /* UIKit.framework in Frameworks */, - F7A8C3320A3B92B920A6B7EF /* Pods_Rudder_tvOS.framework in Frameworks */, + 69916F668AEF36CF5297393D /* Pods_Rudder_tvOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1051,7 +1051,7 @@ files = ( ED998FDF2A69024E00031B06 /* Foundation.framework in Frameworks */, ED998FE02A69024E00031B06 /* UIKit.framework in Frameworks */, - BF320707E73393A5EC3DB72B /* Pods_Rudder_watchOS.framework in Frameworks */, + 8C4C8BBBE37C05B2416E6F67 /* Pods_Rudder_watchOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1060,7 +1060,7 @@ buildActionMask = 2147483647; files = ( ED9990312A69102400031B06 /* Rudder.framework in Frameworks */, - 238487371079D14D0B098555 /* Pods_RudderTests_tvOS.framework in Frameworks */, + 5CC283FA80A5DD6ABCECDF5D /* Pods_RudderTests_tvOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1069,7 +1069,7 @@ buildActionMask = 2147483647; files = ( ED99903F2A69103B00031B06 /* Rudder.framework in Frameworks */, - 431F0AE2E4A192AE78D34326 /* Pods_RudderTests_iOS.framework in Frameworks */, + 1D5DDBF3C5A9A0D68C4DCC99 /* Pods_RudderTests_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1078,7 +1078,7 @@ buildActionMask = 2147483647; files = ( ED99904D2A69104B00031B06 /* Rudder.framework in Frameworks */, - 9FEE83571C0E25C88369FE41 /* Pods_RudderTests_watchOS.framework in Frameworks */, + 538850DAB473A7B4EF67C5A1 /* Pods_RudderTests_watchOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1116,12 +1116,12 @@ EDEF1B302A835A90002B3E57 /* Security.framework */, 06CABC322630C6B00097BEFF /* Foundation.framework */, 06CABC2E2630C6660097BEFF /* UIKit.framework */, - ED1B2AD2F9D4E0F26745091B /* Pods_Rudder_iOS.framework */, - 93E378BE7E662EC3466AD22C /* Pods_Rudder_tvOS.framework */, - 0AB3A24BE91BE2AEE0CA3FF1 /* Pods_Rudder_watchOS.framework */, - E491712EDB73E1E33A1C1129 /* Pods_RudderTests_iOS.framework */, - A8ACE1A679CAD30B58E39A88 /* Pods_RudderTests_tvOS.framework */, - 9FFA1BAA6275D5530AC912B3 /* Pods_RudderTests_watchOS.framework */, + 6A275CE257CE8C3C78CB2A16 /* Pods_Rudder_iOS.framework */, + 694E65090E456D8291C08327 /* Pods_Rudder_tvOS.framework */, + CBE6B383CC53988816505FCA /* Pods_Rudder_watchOS.framework */, + 568C1D5AB430F01BD4CEC4E8 /* Pods_RudderTests_iOS.framework */, + 858E45719C417D040F7CD6E0 /* Pods_RudderTests_tvOS.framework */, + 73BB5CB3025EF1333EC829A3 /* Pods_RudderTests_watchOS.framework */, ); name = Frameworks; sourceTree = ""; @@ -1129,18 +1129,18 @@ DFB2363B6EC8D146934DE8DD /* Pods */ = { isa = PBXGroup; children = ( - A8923DB47023C19C14199A71 /* Pods-Rudder-iOS.debug.xcconfig */, - 62E2A1E694983F13BA03EB9D /* Pods-Rudder-iOS.release.xcconfig */, - 6725E430849222D61D5E0234 /* Pods-Rudder-tvOS.debug.xcconfig */, - 6B7B1FD50E9D829FF642DF10 /* Pods-Rudder-tvOS.release.xcconfig */, - A1322AEF7B87457F0BB3A90F /* Pods-Rudder-watchOS.debug.xcconfig */, - F8F5D21AB948C5691AD2ADA9 /* Pods-Rudder-watchOS.release.xcconfig */, - 047016191610999BB5D6639D /* Pods-RudderTests-iOS.debug.xcconfig */, - 696BB56E6F38B30EA9E87E59 /* Pods-RudderTests-iOS.release.xcconfig */, - 67B6FB354D9492FE1F10F098 /* Pods-RudderTests-tvOS.debug.xcconfig */, - 46E7849777925491E280B136 /* Pods-RudderTests-tvOS.release.xcconfig */, - 594C68EBA69B23ED13FCDF7D /* Pods-RudderTests-watchOS.debug.xcconfig */, - 0C12A2068DA24653A547FFC5 /* Pods-RudderTests-watchOS.release.xcconfig */, + 4C7350A8F5EF4005A9C8002C /* Pods-Rudder-iOS.debug.xcconfig */, + 6EB16DBB6C33BA3C3E7ACCF7 /* Pods-Rudder-iOS.release.xcconfig */, + 588BDCDCC681265EFA53EC1A /* Pods-Rudder-tvOS.debug.xcconfig */, + 024DFF0FE82BFA633C7A0ACF /* Pods-Rudder-tvOS.release.xcconfig */, + AEA654A683B9C42785EF4586 /* Pods-Rudder-watchOS.debug.xcconfig */, + 8864716542CDA61025379626 /* Pods-Rudder-watchOS.release.xcconfig */, + 59CAC564577C2DF84C1C4FA7 /* Pods-RudderTests-iOS.debug.xcconfig */, + 791CB89B417016D590354A7F /* Pods-RudderTests-iOS.release.xcconfig */, + 1826685173321FC0D2D525F6 /* Pods-RudderTests-tvOS.debug.xcconfig */, + A5B61F726E782A95371426B4 /* Pods-RudderTests-tvOS.release.xcconfig */, + 94FCF9CB2A6B261F650FA34A /* Pods-RudderTests-watchOS.debug.xcconfig */, + 8993C949BB21E74269543A5A /* Pods-RudderTests-watchOS.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -1858,7 +1858,7 @@ isa = PBXNativeTarget; buildConfigurationList = 06CABB982630C3CA0097BEFF /* Build configuration list for PBXNativeTarget "Rudder-iOS" */; buildPhases = ( - AFEA49832884FFAB57FDF230 /* [CP] Check Pods Manifest.lock */, + 3F508465A1EB54A57BCE5026 /* [CP] Check Pods Manifest.lock */, 06CABB7F2630C3CA0097BEFF /* Headers */, 06CABB802630C3CA0097BEFF /* Sources */, 06CABB812630C3CA0097BEFF /* Frameworks */, @@ -1877,7 +1877,7 @@ isa = PBXNativeTarget; buildConfigurationList = ED998F122A69003600031B06 /* Build configuration list for PBXNativeTarget "Rudder-tvOS" */; buildPhases = ( - 3D29E465A99831E1830BA50E /* [CP] Check Pods Manifest.lock */, + F047EAAD4A3D4944740FAC24 /* [CP] Check Pods Manifest.lock */, ED998E482A69003600031B06 /* Headers */, ED998EAE2A69003600031B06 /* Sources */, ED998F0E2A69003600031B06 /* Frameworks */, @@ -1896,7 +1896,7 @@ isa = PBXNativeTarget; buildConfigurationList = ED998FE22A69024E00031B06 /* Build configuration list for PBXNativeTarget "Rudder-watchOS" */; buildPhases = ( - FA646B8CEFE5AE97B9FF54B7 /* [CP] Check Pods Manifest.lock */, + 1FB91ACA73E16AC7C0D42A08 /* [CP] Check Pods Manifest.lock */, ED998F182A69024E00031B06 /* Headers */, ED998F7E2A69024E00031B06 /* Sources */, ED998FDE2A69024E00031B06 /* Frameworks */, @@ -1915,11 +1915,11 @@ isa = PBXNativeTarget; buildConfigurationList = ED9990342A69102400031B06 /* Build configuration list for PBXNativeTarget "RudderTests-tvOS" */; buildPhases = ( - 7BD8C108C1E023AEC53DA6B9 /* [CP] Check Pods Manifest.lock */, + AD6452261C56A78ADD9E66F5 /* [CP] Check Pods Manifest.lock */, ED9990292A69102400031B06 /* Sources */, ED99902A2A69102400031B06 /* Frameworks */, ED99902B2A69102400031B06 /* Resources */, - D500A6672225011FA2D992BA /* [CP] Embed Pods Frameworks */, + 2CB207CD8FB9B53F4930095F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -1935,11 +1935,11 @@ isa = PBXNativeTarget; buildConfigurationList = ED9990422A69103B00031B06 /* Build configuration list for PBXNativeTarget "RudderTests-iOS" */; buildPhases = ( - ECDDBE7C2C4DEAE0E3739C04 /* [CP] Check Pods Manifest.lock */, + 953A3028C6A5333C104A17FA /* [CP] Check Pods Manifest.lock */, ED9990372A69103A00031B06 /* Sources */, ED9990382A69103A00031B06 /* Frameworks */, ED9990392A69103A00031B06 /* Resources */, - 2DD0BFC71FCF57B2030F35F0 /* [CP] Embed Pods Frameworks */, + 2330930E4DE01C746D069354 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -1955,11 +1955,11 @@ isa = PBXNativeTarget; buildConfigurationList = ED9990502A69104B00031B06 /* Build configuration list for PBXNativeTarget "RudderTests-watchOS" */; buildPhases = ( - 410B5B108347EF9C66CDB8CA /* [CP] Check Pods Manifest.lock */, + 3E02581B428CBD1F96FD1A69 /* [CP] Check Pods Manifest.lock */, ED9990452A69104B00031B06 /* Sources */, ED9990462A69104B00031B06 /* Frameworks */, ED9990472A69104B00031B06 /* Resources */, - 4C1BBEB758DC89CDF90C677E /* [CP] Embed Pods Frameworks */, + 95609E0B374DE1F330EABE65 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -2097,7 +2097,29 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 2DD0BFC71FCF57B2030F35F0 /* [CP] Embed Pods Frameworks */ = { + 1FB91ACA73E16AC7C0D42A08 /* [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-Rudder-watchOS-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; + }; + 2330930E4DE01C746D069354 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2114,29 +2136,24 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RudderTests-iOS/Pods-RudderTests-iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 3D29E465A99831E1830BA50E /* [CP] Check Pods Manifest.lock */ = { + 2CB207CD8FB9B53F4930095F /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Rudder-tvOS-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); 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"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 410B5B108347EF9C66CDB8CA /* [CP] Check Pods Manifest.lock */ = { + 3E02581B428CBD1F96FD1A69 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2158,24 +2175,7 @@ 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; }; - 4C1BBEB758DC89CDF90C677E /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 7BD8C108C1E023AEC53DA6B9 /* [CP] Check Pods Manifest.lock */ = { + 3F508465A1EB54A57BCE5026 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2190,14 +2190,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RudderTests-tvOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Rudder-iOS-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; }; - AFEA49832884FFAB57FDF230 /* [CP] Check Pods Manifest.lock */ = { + 953A3028C6A5333C104A17FA /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2212,31 +2212,31 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Rudder-iOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-RudderTests-iOS-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; }; - D500A6672225011FA2D992BA /* [CP] Embed Pods Frameworks */ = { + 95609E0B374DE1F330EABE65 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RudderTests-tvOS/Pods-RudderTests-tvOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RudderTests-watchOS/Pods-RudderTests-watchOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - ECDDBE7C2C4DEAE0E3739C04 /* [CP] Check Pods Manifest.lock */ = { + AD6452261C56A78ADD9E66F5 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2251,14 +2251,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RudderTests-iOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-RudderTests-tvOS-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; }; - FA646B8CEFE5AE97B9FF54B7 /* [CP] Check Pods Manifest.lock */ = { + F047EAAD4A3D4944740FAC24 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2273,7 +2273,7 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Rudder-watchOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-Rudder-tvOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -2809,7 +2809,7 @@ }; 06CABB992630C3CA0097BEFF /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A8923DB47023C19C14199A71 /* Pods-Rudder-iOS.debug.xcconfig */; + baseConfigurationReference = 4C7350A8F5EF4005A9C8002C /* Pods-Rudder-iOS.debug.xcconfig */; buildSettings = { ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2854,7 +2854,7 @@ }; 06CABB9A2630C3CA0097BEFF /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 62E2A1E694983F13BA03EB9D /* Pods-Rudder-iOS.release.xcconfig */; + baseConfigurationReference = 6EB16DBB6C33BA3C3E7ACCF7 /* Pods-Rudder-iOS.release.xcconfig */; buildSettings = { ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2898,7 +2898,7 @@ }; ED998F132A69003600031B06 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6725E430849222D61D5E0234 /* Pods-Rudder-tvOS.debug.xcconfig */; + baseConfigurationReference = 588BDCDCC681265EFA53EC1A /* Pods-Rudder-tvOS.debug.xcconfig */; buildSettings = { ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2943,7 +2943,7 @@ }; ED998F142A69003600031B06 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6B7B1FD50E9D829FF642DF10 /* Pods-Rudder-tvOS.release.xcconfig */; + baseConfigurationReference = 024DFF0FE82BFA633C7A0ACF /* Pods-Rudder-tvOS.release.xcconfig */; buildSettings = { ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2987,7 +2987,7 @@ }; ED998FE32A69024E00031B06 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A1322AEF7B87457F0BB3A90F /* Pods-Rudder-watchOS.debug.xcconfig */; + baseConfigurationReference = AEA654A683B9C42785EF4586 /* Pods-Rudder-watchOS.debug.xcconfig */; buildSettings = { ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -3032,7 +3032,7 @@ }; ED998FE42A69024E00031B06 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F8F5D21AB948C5691AD2ADA9 /* Pods-Rudder-watchOS.release.xcconfig */; + baseConfigurationReference = 8864716542CDA61025379626 /* Pods-Rudder-watchOS.release.xcconfig */; buildSettings = { ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -3076,7 +3076,7 @@ }; ED9990352A69102400031B06 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 67B6FB354D9492FE1F10F098 /* Pods-RudderTests-tvOS.debug.xcconfig */; + baseConfigurationReference = 1826685173321FC0D2D525F6 /* Pods-RudderTests-tvOS.debug.xcconfig */; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_STYLE = Automatic; @@ -3098,7 +3098,7 @@ }; ED9990362A69102400031B06 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 46E7849777925491E280B136 /* Pods-RudderTests-tvOS.release.xcconfig */; + baseConfigurationReference = A5B61F726E782A95371426B4 /* Pods-RudderTests-tvOS.release.xcconfig */; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_STYLE = Automatic; @@ -3120,7 +3120,7 @@ }; ED9990432A69103B00031B06 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 047016191610999BB5D6639D /* Pods-RudderTests-iOS.debug.xcconfig */; + baseConfigurationReference = 59CAC564577C2DF84C1C4FA7 /* Pods-RudderTests-iOS.debug.xcconfig */; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_STYLE = Automatic; @@ -3152,7 +3152,7 @@ }; ED9990442A69103B00031B06 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 696BB56E6F38B30EA9E87E59 /* Pods-RudderTests-iOS.release.xcconfig */; + baseConfigurationReference = 791CB89B417016D590354A7F /* Pods-RudderTests-iOS.release.xcconfig */; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_STYLE = Automatic; @@ -3184,7 +3184,7 @@ }; ED9990512A69104B00031B06 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 594C68EBA69B23ED13FCDF7D /* Pods-RudderTests-watchOS.debug.xcconfig */; + baseConfigurationReference = 94FCF9CB2A6B261F650FA34A /* Pods-RudderTests-watchOS.debug.xcconfig */; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_STYLE = Automatic; @@ -3206,7 +3206,7 @@ }; ED9990522A69104B00031B06 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C12A2068DA24653A547FFC5 /* Pods-RudderTests-watchOS.release.xcconfig */; + baseConfigurationReference = 8993C949BB21E74269543A5A /* Pods-RudderTests-watchOS.release.xcconfig */; buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_STYLE = Automatic; diff --git a/Sources/Classes/Headers/Public/RSUtils.h b/Sources/Classes/Headers/Public/RSUtils.h index c58bf77c..2465e73f 100644 --- a/Sources/Classes/Headers/Public/RSUtils.h +++ b/Sources/Classes/Headers/Public/RSUtils.h @@ -8,6 +8,7 @@ #import #import +#import "RSMessage.h" #import "RSDBMessage.h" #import "RSServerConfigSource.h" @@ -26,17 +27,15 @@ NS_ASSUME_NONNULL_BEGIN + (NSString*) getLocale; + (NSString*) getDateString: (NSDate*) date; + (NSMutableArray *) sortArray:(NSMutableArray*) mutableArrayOfNumbers inOrder:(ORDER) order; -+ (NSString*) getStringFromDict:(NSDictionary *) dict; + (unsigned int) getUTF8LengthForDict:(NSDictionary *)message; + (unsigned int) getUTF8Length: (NSString*) message; -+ (NSDictionary*) serializeDict: (NSDictionary* _Nullable) dict; -+ (NSArray*) serializeArray: (NSArray*) array; + (int) getNumberOfBatches:(RSDBMessage*) dbMessage withFlushQueueSize: (int) queueSize; + (NSMutableArray*) getBatch:(NSMutableArray*) messageDetails withQueueSize: (int) queueSize; +(NSArray*) getArrayFromCSVString: (NSString *) csvString; -+ (NSString*) getCSVString:(NSArray*) inputStrings; -+ (NSString*) getJSONCSVString:(NSArray*) inputStrings; -+ (id _Nullable) deSerializeJSONString:(NSString*) jsonString; ++ (NSString*) getCSVStringFromArray:(NSArray*) inputStrings; ++ (id) sanitizeObject: (id) val; ++ (NSString* _Nullable) serialize:(id) object; ++ (id _Nullable) deserialize:(NSString*) jsonString; + (BOOL) isValidURL:(NSURL*) url; + (NSString*) appendSlashToUrl:(NSString*) url; + (NSString* _Nullable) getBase64EncodedString:(NSString* __nonnull) inputString; @@ -46,6 +45,7 @@ NS_ASSUME_NONNULL_BEGIN + (BOOL)removeFile:(NSString *)fileName; + (BOOL) isDBMessageEmpty:(RSDBMessage*)dbMessage; + (BOOL) isEmptyString:(NSString *)value; ++ (BOOL) isSpecialFloatingNumber:(NSNumber *)number; extern unsigned int MAX_EVENT_SIZE; extern unsigned int MAX_BATCH_SIZE; diff --git a/Sources/Classes/Headers/RSVersion.h b/Sources/Classes/Headers/RSVersion.h index 51d13777..b007f44f 100644 --- a/Sources/Classes/Headers/RSVersion.h +++ b/Sources/Classes/Headers/RSVersion.h @@ -8,6 +8,6 @@ #ifndef RSVersion_h #define RSVersion_h -NSString *const SDK_VERSION = @"1.24.1"; +NSString *const SDK_VERSION = @"1.25.1"; #endif /* RSVersion_h */ diff --git a/Sources/Classes/RSCloudModeManager.m b/Sources/Classes/RSCloudModeManager.m index afc60ea4..0072f065 100644 --- a/Sources/Classes/RSCloudModeManager.m +++ b/Sources/Classes/RSCloudModeManager.m @@ -49,7 +49,7 @@ - (void) startCloudModeProcessor { if (payload != nil) { response = [strongSelf->networkManager sendNetworkRequest:payload toEndpoint:BATCH_ENDPOINT withRequestMethod:POST]; if (response.state == NETWORK_SUCCESS) { - [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Updating status as CLOUDMODEPROCESSING DONE for events (%@)",[RSUtils getCSVString:dbMessage.messageIds]]]; + [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Updating status as CLOUDMODEPROCESSING DONE for events (%@)",[RSUtils getCSVStringFromArray:dbMessage.messageIds]]]; [RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_SUCCESS forMetricType:COUNT withProperties:nil andValue:(float)dbMessage.messages.count]; [strongSelf->dbPersistentManager updateEventsWithIds:dbMessage.messageIds withStatus:CLOUD_MODE_PROCESSING_DONE]; [strongSelf->dbPersistentManager clearProcessedEventsFromDB]; diff --git a/Sources/Classes/RSConstants.m b/Sources/Classes/RSConstants.m index b4195e55..865b7338 100644 --- a/Sources/Classes/RSConstants.m +++ b/Sources/Classes/RSConstants.m @@ -17,7 +17,7 @@ @implementation RSConstants int const RSSleepTimeout = 10; long const RSSessionInActivityMinTimeOut = 0; long const RSSessionInActivityDefaultTimeOut = 300000; -NSString *const RSControlPlaneUrl = @"https://api.rudderlabs.com/"; +NSString *const RSControlPlaneUrl = @"https://api.rudderstack.com/"; bool const RSTrackLifeCycleEvents = YES; bool const RSRecordScreenViews = NO; bool const RSEnableBackgroundMode = NO; diff --git a/Sources/Classes/RSContext.m b/Sources/Classes/RSContext.m index 086042e2..0f7558d9 100644 --- a/Sources/Classes/RSContext.m +++ b/Sources/Classes/RSContext.m @@ -49,9 +49,8 @@ - (instancetype)initWithConfig:(RSConfig *) config { // no persisted traits, create new and persist [self createAndPersistTraits]; } else { - NSError *error; - NSDictionary *traitsDict = [NSJSONSerialization JSONObjectWithData:[traitsJson dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error]; - if (error == nil) { + NSDictionary *traitsDict = [RSUtils deserialize:traitsJson]; + if (traitsDict != nil) { _traits = [traitsDict mutableCopy]; _traits[@"anonymousId"] = _anonymousId; [self persistTraits]; @@ -64,9 +63,8 @@ - (instancetype)initWithConfig:(RSConfig *) config { // get saved external Ids from prefs NSString *externalIdJson = [preferenceManager getExternalIds]; if (externalIdJson != nil) { - NSError *error; - NSDictionary *externalIdDict = [NSJSONSerialization JSONObjectWithData:[externalIdJson dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error]; - if (error == nil) { + NSDictionary *externalIdDict = [RSUtils deserialize:externalIdJson]; + if (externalIdDict != nil) { _externalIds = [externalIdDict mutableCopy]; } } @@ -82,11 +80,11 @@ - (instancetype) initWithDict:(NSDictionary*) dict { _traits = dict[@"traits"]; _library = [[RSLibraryInfo alloc] initWithDict:dict[@"library"]]; _os = [[RSOSInfo alloc] initWithDict:dict[@"os"]]; - _screen = [[RSScreenInfo alloc] initWithDict:dict[@"screen"]]; + _screen = [[RSScreenInfo alloc] initWithDict:dict[@"screen"]]; _userAgent = dict[@"userAgent"]; _locale = dict[@"locale"]; _device = [[RSDeviceInfo alloc] initWithDict:dict[@"device"]]; - _network = [[RSNetwork alloc] initWithDict:dict[@"network"]]; + _network = [[RSNetwork alloc] initWithDict:dict[@"network"]]; _timezone = dict[@"timezone"]; _sessionId = dict[@"sessionId"]; if(dict[@"sessionStart"]) { @@ -144,9 +142,12 @@ - (void) persistTraitsOnQueue { } -(void) persistTraits { - NSData *traitsJsonData = [NSJSONSerialization dataWithJSONObject:[RSUtils serializeDict:self->_traits] options:0 error:nil]; - NSString *traitsString = [[NSString alloc] initWithData:traitsJsonData encoding:NSUTF8StringEncoding]; - [self->preferenceManager saveTraits:traitsString]; + NSString* traitsString = [RSUtils serialize:[self->_traits copy]]; + if (traitsString != nil) { + [self->preferenceManager saveTraits:traitsString]; + } else { + [RSLogger logError:@"RSContext: persistTraits: Failed to serialize traits"]; + } } - (void)updateTraitsDict:(NSMutableDictionary *)traitsDict { @@ -215,9 +216,12 @@ - (void)persistExternalIds { dispatch_sync(queue, ^{ if (self->_externalIds != nil) { // update persistence storage - NSData *externalIdJsonData = [NSJSONSerialization dataWithJSONObject:[RSUtils serializeArray:[self->_externalIds copy]] options:0 error:nil]; - NSString *externalIdJson = [[NSString alloc] initWithData:externalIdJsonData encoding:NSUTF8StringEncoding]; - [self->preferenceManager saveExternalIds:externalIdJson]; + NSString *externalIdJson = [RSUtils serialize: [self->_externalIds copy]]; + if(externalIdJson != nil) { + [self->preferenceManager saveExternalIds:externalIdJson]; + } else { + [RSLogger logError:@"RSContext: persistExternalIds: Failed to serialize externalIds"]; + } } }); } @@ -275,7 +279,7 @@ - (void)setConsentData:(NSArray *)deniedConsentIds { NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init]; dispatch_sync(queue, ^{ [tempDict setObject:[_app dict] forKey:@"app"]; - [tempDict setObject:[RSUtils serializeDict:_traits] forKey:@"traits"]; + [tempDict setObject:_traits forKey:@"traits"]; [tempDict setObject:[_library dict] forKey:@"library"]; [tempDict setObject:[_os dict] forKey:@"os"]; [tempDict setObject:[_screen dict] forKey:@"screen"]; diff --git a/Sources/Classes/RSDBPersistentManager.m b/Sources/Classes/RSDBPersistentManager.m index 5010164c..0f84a73e 100644 --- a/Sources/Classes/RSDBPersistentManager.m +++ b/Sources/Classes/RSDBPersistentManager.m @@ -447,7 +447,7 @@ - (void) clearOldEventsWithThreshold:(int) threshold { } - (void)clearEventsFromDB:(NSMutableArray *)messageIds { - NSString *deleteSqlString = [[NSString alloc] initWithFormat:@"DELETE FROM %@ WHERE %@ IN (%@);", TABLE_EVENTS, COL_ID, [RSUtils getCSVString:messageIds]]; + NSString *deleteSqlString = [[NSString alloc] initWithFormat:@"DELETE FROM %@ WHERE %@ IN (%@);", TABLE_EVENTS, COL_ID, [RSUtils getCSVStringFromArray:messageIds]]; [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSDBPersistentManager: deleteEventSql: %@", deleteSqlString]]; @synchronized (self) { if([self execSQL:deleteSqlString]) { @@ -564,7 +564,7 @@ -(void) updateEventWithId:(NSNumber *) messageId withStatus:(EVENT_PROCESSING_ST } -(void) updateEventsWithIds:(NSArray*) messageIds withStatus:(EVENT_PROCESSING_STATUS) status { - NSString *messageIdsCsv = [RSUtils getCSVString:messageIds]; + NSString *messageIdsCsv = [RSUtils getCSVStringFromArray:messageIds]; if(messageIdsCsv != nil) { NSString* updateEventStatusSQL = [[NSString alloc] initWithFormat:@"UPDATE %@ SET %@ = %@ | %d WHERE %@ IN (%@);", TABLE_EVENTS, COL_STATUS, COL_STATUS, status, COL_ID, messageIdsCsv]; @synchronized (self) { diff --git a/Sources/Classes/RSDeviceInfo.m b/Sources/Classes/RSDeviceInfo.m index 09167cd8..6280f0a2 100644 --- a/Sources/Classes/RSDeviceInfo.m +++ b/Sources/Classes/RSDeviceInfo.m @@ -10,6 +10,7 @@ #import "RSContext.h" #import #import "RSConstants.h" +#import #if TARGET_OS_WATCH #import #endif @@ -22,15 +23,14 @@ - (instancetype) initWithConfig: (RSConfig *) config { if (self) { #if !TARGET_OS_WATCH _identifier = config.collectDeviceId ? [[[[UIDevice currentDevice] identifierForVendor] UUIDString]lowercaseString] : nil; - _model = [[UIDevice currentDevice] model]; _name = [[UIDevice currentDevice] name]; _type = [[UIDevice currentDevice] systemName]; #else _identifier = config.collectDeviceId ? [[[[WKInterfaceDevice currentDevice] identifierForVendor]UUIDString] lowercaseString] : nil; - _model = [[WKInterfaceDevice currentDevice]model]; _name = [[WKInterfaceDevice currentDevice]name]; _type = [[WKInterfaceDevice currentDevice]systemName]; #endif + _model = [self getDeviceModel]; _manufacturer = @"Apple"; _attTrackingStatus = RSATTNotDetermined; } @@ -53,6 +53,41 @@ - (instancetype) initWithDict:(NSDictionary*) dict { return self; } +- (NSString*) getDeviceModel { + NSString* platformString = [self getPlatformString]; + if(platformString != nil) { + return platformString; + } +#if !TARGET_OS_WATCH + return [[UIDevice currentDevice] model]; +#else + return [[WKInterfaceDevice currentDevice]model]; +#endif + +} + +- (NSString *) getPlatformString { + const char *sysctl_name = "hw.model"; +#if TARGET_OS_IOS + BOOL isiOSAppOnMac = NO; + if (@available(iOS 14.0, *)) { + isiOSAppOnMac = [NSProcessInfo processInfo].isiOSAppOnMac; + } + if (!isiOSAppOnMac){ + sysctl_name = "hw.machine"; + } +#elif TARGET_OS_TV || TARGET_OS_WATCH + sysctl_name = "hw.machine"; +#endif + size_t size; + sysctlbyname(sysctl_name, NULL, &size, NULL, 0); + char *machine = calloc(1, size); + sysctlbyname(sysctl_name, machine, &size, NULL, 0); + NSString *platform = [NSString stringWithUTF8String:machine]; + free(machine); + return platform; +} + - (NSDictionary *)dict { NSMutableDictionary *tempDict; @synchronized (tempDict){ diff --git a/Sources/Classes/RSDeviceModeManager.m b/Sources/Classes/RSDeviceModeManager.m index 84cb358d..c9e5ccdb 100644 --- a/Sources/Classes/RSDeviceModeManager.m +++ b/Sources/Classes/RSDeviceModeManager.m @@ -176,7 +176,7 @@ - (void) replayMessageQueue { NSArray *messageIds = dbMessage.messageIds; NSArray *messages = dbMessage.messages; for (int i=0; idbPersistentManager fetchEventsFromDB:DMT_BATCH_SIZE ForMode:DEVICEMODE]; RSTransformationRequest* request = [strongSelf __getDeviceModeTransformationRequest:dbMessage]; - NSString* payload = [RSUtils getStringFromDict:[request toDict]]; + NSString* payload = [RSUtils serialize:[request toDict]]; + if(payload == nil) { + [RSLogger logDebug:@"RSDeviceModeTransformationManager: TransformationProcessor: Payload is nil. Aborting the TransformationProcessor."]; + break; + } [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSDeviceModeTransformationManager: TransformationProcessor: Payload: %@", payload]]; [RSLogger logInfo:[[NSString alloc] initWithFormat:@"RSDeviceModeTransformationManager: TransformationProcessor: EventCount: %lu", (unsigned long)dbMessage.messageIds.count]]; RSNetworkResponse* response = [strongSelf->networkManager sendNetworkRequest:payload toEndpoint:TRANSFORM_ENDPOINT withRequestMethod:POST]; @@ -96,7 +100,7 @@ - (void) transformationProcessor { [strongSelf completeDeviceModeEventProcessing:dbMessage]; } else { deviceModeSleepCount = 0; - id object = [RSUtils deSerializeJSONString:responsePayload]; + id object = [RSUtils deserialize:responsePayload]; if(object != nil && [object isKindOfClass:[NSDictionary class]]) { NSArray* transformedBatch = object[@"transformedBatch"]; if(transformedBatch != nil && transformedBatch.count > 0) { @@ -112,7 +116,7 @@ - (void) transformationProcessor { } } } - [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSDeviceModeTransformationManager: TransformationProcessor: Updating status as DEVICE_MODE_PROCESSING DONE for events (%@)",[RSUtils getCSVString:dbMessage.messageIds]]]; + [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSDeviceModeTransformationManager: TransformationProcessor: Updating status as DEVICE_MODE_PROCESSING DONE for events (%@)",[RSUtils getCSVStringFromArray:dbMessage.messageIds]]]; [strongSelf->dbPersistentManager updateEventsWithIds:dbMessage.messageIds withStatus:DEVICE_MODE_PROCESSING_DONE]; [strongSelf->dbPersistentManager clearProcessedEventsFromDB]; } @@ -135,8 +139,8 @@ - (RSTransformationRequest *) __getDeviceModeTransformationRequest:(RSDBMessage NSMutableArray* messages = dbMessage.messages; NSMutableArray* messageIds = dbMessage.messageIds; for(int i=0; i* destinationIds = [self getDestinationIdsWithTransformationsForMessage:message]; if(destinationIds== nil || [destinationIds count]==0) continue; @@ -157,7 +161,7 @@ - (RSTransformationRequest *) __getDeviceModeTransformationRequest:(RSDBMessage - (void)completeDeviceModeEventProcessing:(RSDBMessage *)dbMessage { - [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSDeviceModeTransformationManager: TransformationProcessor: Updating status as DEVICE_MODE_PROCESSING DONE for events (%@)",[RSUtils getCSVString:dbMessage.messageIds]]]; + [RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSDeviceModeTransformationManager: TransformationProcessor: Updating status as DEVICE_MODE_PROCESSING DONE for events (%@)",[RSUtils getCSVStringFromArray:dbMessage.messageIds]]]; [self->dbPersistentManager updateEventsWithIds:dbMessage.messageIds withStatus:DEVICE_MODE_PROCESSING_DONE]; [self->dbPersistentManager clearProcessedEventsFromDB]; } diff --git a/Sources/Classes/RSEventRepository.m b/Sources/Classes/RSEventRepository.m index f2e0c7e1..19602a9f 100644 --- a/Sources/Classes/RSEventRepository.m +++ b/Sources/Classes/RSEventRepository.m @@ -230,15 +230,19 @@ - (void) dump:(RSMessage *)message { message = [self applyConsents:message]; [self applySession:message withUserSession:userSession andRudderConfig:config]; - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[message dict] options:0 error:nil]; - NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - [RSLogger logDebug:[[NSString alloc] initWithFormat:@"dump: %@", jsonString]]; + NSString * jsonString = [RSUtils serialize: [message dict]]; + if(jsonString == nil) { + [RSLogger logError:@"dump: Event is not a valid JSON object, discarding the event"]; + return; + } + unsigned int messageSize = [RSUtils getUTF8Length:jsonString]; if (messageSize > MAX_EVENT_SIZE) { [RSLogger logError:[NSString stringWithFormat:@"dump: Event size exceeds the maximum permitted event size(%iu)", MAX_EVENT_SIZE]]; [RSMetricsReporter report:SDKMETRICS_EVENTS_DISCARDED forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_MSG_SIZE_INVALID} andValue:1]; return; } + [RSLogger logDebug:[[NSString alloc] initWithFormat:@"dump: %@", jsonString]]; NSNumber* rowId = [self->dbpersistenceManager saveEvent:jsonString]; [self->deviceModeManager makeFactoryDump: message FromHistory:NO withRowId:rowId]; } diff --git a/Sources/Classes/RSMessage.m b/Sources/Classes/RSMessage.m index 9e6eed80..01609061 100644 --- a/Sources/Classes/RSMessage.m +++ b/Sources/Classes/RSMessage.m @@ -79,18 +79,18 @@ - (instancetype) initWithDict: (NSDictionary*) dict { [tempDict setValue:_groupId forKey:@"groupId"]; } if (_traits != nil) { - [tempDict setValue:[RSUtils serializeDict:_traits] forKey:@"traits"]; + [tempDict setValue:_traits forKey:@"traits"]; } [tempDict setValue:_anonymousId forKey:@"anonymousId"]; if (_userId != nil) { [tempDict setValue:_userId forKey:@"userId"]; } if (_properties != nil) { - [tempDict setValue:[RSUtils serializeDict:_properties] forKey:@"properties"]; + [tempDict setValue: _properties forKey:@"properties"]; } [tempDict setValue:_event forKey:@"event"]; if (_userProperties != nil) { - [tempDict setValue:[RSUtils serializeDict:_userProperties] forKey:@"userProperties"]; + [tempDict setValue:_userProperties forKey:@"userProperties"]; } [tempDict setValue:_integrations forKey:@"integrations"]; diff --git a/Sources/Classes/RSNetwork.m b/Sources/Classes/RSNetwork.m index 244edf9d..830a0843 100644 --- a/Sources/Classes/RSNetwork.m +++ b/Sources/Classes/RSNetwork.m @@ -78,7 +78,7 @@ - (instancetype) initWithDict:(NSDictionary*) dict { @synchronized (tempDict) { tempDict = [[NSMutableDictionary alloc] init]; if(_carrier.count !=0) { - [tempDict setValue:[RSUtils getCSVString:_carrier] forKey:@"carrier"]; + [tempDict setValue:[RSUtils getCSVStringFromArray:_carrier] forKey:@"carrier"]; } #if !TARGET_OS_WATCH [tempDict setValue:[NSNumber numberWithBool:_wifi] forKey:@"wifi"]; diff --git a/Sources/Classes/RSPreferenceManager.m b/Sources/Classes/RSPreferenceManager.m index aa448d91..48a19a60 100644 --- a/Sources/Classes/RSPreferenceManager.m +++ b/Sources/Classes/RSPreferenceManager.m @@ -141,12 +141,17 @@ - (void)clearAnonymousId { - (void) clearAnonymousIdFromTraits { NSString* traitsStr = [self getTraits]; - NSError *error; - NSMutableDictionary* traitsDict = [NSJSONSerialization JSONObjectWithData:[traitsStr dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error]; - if(error == nil && traitsDict != nil) { - [traitsDict removeObjectForKey:@"anonymousId"]; - NSString* finalTraitsStr = [RSUtils getStringFromDict:traitsDict]; - [self saveTraits:finalTraitsStr]; + if (traitsStr != nil) { + NSMutableDictionary* traitsDict = [RSUtils deserialize:traitsStr]; + if(traitsDict != nil) { + [traitsDict removeObjectForKey:@"anonymousId"]; + NSString* finalTraitsStr = [RSUtils serialize:traitsDict]; + if (finalTraitsStr != nil) { + [self saveTraits:finalTraitsStr]; + } else { + [RSLogger logError:@"RSPreferenceManager: clearAnonymousIdFromTraits: Failed to serialize traitsDict"]; + } + } } } @@ -286,9 +291,8 @@ - (RSServerConfigSource * __nullable)getServerSourceConfig { if (configStr == nil) { return nil; } - NSError *error; - NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:[configStr dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error]; - if (error == nil && configDict != nil) { + NSDictionary *configDict = [RSUtils deserialize:configStr]; + if (configDict != nil) { RSServerConfigSource *config = [[RSServerConfigSource alloc] initWithConfigDict:configDict]; return config; } diff --git a/Sources/Classes/RSServerConfigManager.m b/Sources/Classes/RSServerConfigManager.m index 2ba3b3f7..ad6e9fe2 100644 --- a/Sources/Classes/RSServerConfigManager.m +++ b/Sources/Classes/RSServerConfigManager.m @@ -66,11 +66,10 @@ - (RSServerConfigSource* _Nullable) _retrieveConfig { } - (RSServerConfigSource *_Nullable)_parseConfig:(NSString *)configStr { - NSError *error; - NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:[configStr dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&error]; + NSDictionary *configDict = [RSUtils deserialize:configStr]; RSServerConfigSource *source; - if (error == nil && configDict != nil) { + if (configDict != nil) { source = [[RSServerConfigSource alloc] initWithConfigDict:configDict]; for (RSServerDestination *destination in source.destinations) { if (destination.shouldApplyDeviceModeTransformation) { diff --git a/Sources/Classes/RSUtils.m b/Sources/Classes/RSUtils.m index fdb4781a..0a84090e 100644 --- a/Sources/Classes/RSUtils.m +++ b/Sources/Classes/RSUtils.m @@ -25,18 +25,16 @@ + (NSString*) getDateString:(NSDate *)date { return [dateFormatter stringFromDate:date]; } -+ (NSString*) getStringFromDict:(NSDictionary *) dict { - NSData *dictData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil]; - if(dictData == nil) - return @""; - NSString *dictString = [[NSString alloc] initWithData:dictData encoding:NSUTF8StringEncoding]; - return dictString; -} - + (NSString *)getTimestamp { return [self getDateString:[[NSDate alloc] init]]; } +// returns number of seconds elapsed since 1970 ++ (long) getTimeStampLong{ + NSDate *date = [[NSDate alloc] init]; + return [date timeIntervalSince1970]; +} + + (NSString *)getFilePath:(NSString *)fileName { #if TARGET_OS_TV NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); @@ -57,11 +55,6 @@ + (BOOL)removeFile:(NSString *)fileName { return [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; } -// returns number of seconds elapsed since 1970 -+ (long) getTimeStampLong{ - NSDate *date = [[NSDate alloc] init]; - return [date timeIntervalSince1970]; -} + (NSString *) getUniqueId { NSUUID *uuid = [NSUUID UUID]; @@ -79,7 +72,7 @@ + (NSString*) getLocale { } + (unsigned int) getUTF8LengthForDict:(NSDictionary *)message { - NSString* msgString = [self getStringFromDict:message]; + NSString* msgString = [self serialize:message]; if(msgString == nil) return 0; return [self getUTF8Length:msgString]; @@ -89,96 +82,20 @@ + (unsigned int) getUTF8Length:(NSString *)message { return (unsigned int)[[message dataUsingEncoding:NSUTF8StringEncoding] length]; } -+ (id) serializeValue: (id) val { - if ([val isKindOfClass:[NSString class]] || - [val isKindOfClass:[NSNumber class]] || - [val isKindOfClass:[NSNull class]] - ) { - return val; - } else if ([val isKindOfClass:[NSArray class]]) { - // handle array - NSMutableArray *array = [[NSMutableArray alloc] init]; - for (id i in val) { - [array addObject:[self serializeValue:i]]; - } - return [array copy]; - } else if ([val isKindOfClass:[NSDictionary class]] || - [val isKindOfClass:[NSMutableDictionary class]] - ) { - // handle dictionary - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; - NSArray *keys = [val allKeys]; - for (NSString *key in keys) { - id value = [val objectForKey:key]; - if (![key isKindOfClass:[NSString class]]) { - [RSLogger logDebug:@"key should be string. changing it to its description"]; - } - [dict setValue:[self serializeValue:value] forKey:[key description]]; - } - return [dict copy]; - } else if ([val isKindOfClass:[NSDate class]]) { - // handle date // isofy - return [self getDateString:val]; - } else if ([val isKindOfClass:[NSURL class]]) { - // handle url - return [val absoluteString]; - } - [RSLogger logDebug:@"properties value is not serializable. using description"]; - return [val description]; -} - + (NSArray *) sortArray:(NSMutableArray*) arrayOfNumbers inOrder:(ORDER) order { NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:order == ASCENDING]; [arrayOfNumbers sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; return [arrayOfNumbers copy]; } -+ (NSDictionary *)serializeDict:(NSDictionary*)dict { - // if dict is not null - if (dict) { - NSMutableDictionary *returnDict = [[NSMutableDictionary alloc] initWithCapacity:dict.count]; - NSArray *keys = [dict allKeys]; - for (NSString* key in keys) { - id val = [self serializeValue: [dict objectForKey:key]]; - [returnDict setValue:val forKey:key]; - } - - return [returnDict copy]; - } - return dict; -} - -+ (NSArray*) serializeArray:(NSArray*) array { - if (array) { - NSMutableArray *returnArray = [[NSMutableArray alloc] init]; - for (id i in array) { - [returnArray addObject:[self serializeValue:i]]; - } - return [returnArray copy]; - } - return array; -} - +(NSArray*) getArrayFromCSVString: (NSString *) csvString { return [csvString componentsSeparatedByString:@","]; } -+(NSString*) getCSVString:(NSArray*) inputStrings { ++(NSString*) getCSVStringFromArray:(NSArray*) inputStrings { return [inputStrings componentsJoinedByString:@","]; } -+(NSString*) getJSONCSVString:(NSArray*) inputStrings { - NSMutableString *JSONCSVString = [[NSMutableString alloc] init]; - for (int index = 0; index < inputStrings.count; index++) { - [JSONCSVString appendFormat:@"\"%@\"", inputStrings[index]]; - if (index != inputStrings.count -1) { - [JSONCSVString appendString:@","]; - } - } - return [JSONCSVString copy]; -} - - + (int) getNumberOfBatches:(RSDBMessage*) dbMessage withFlushQueueSize: (int) queueSize { int messageCount = (int)dbMessage.messageIds.count; if (messageCount % queueSize == 0) { @@ -195,17 +112,6 @@ + (NSArray*) getBatch:(NSArray*) messageDetails withQueueSize: (int) queueSize { return [[NSMutableArray alloc] initWithArray:[messageDetails subarrayWithRange:NSMakeRange(0, queueSize)]]; } -+ (id _Nullable) deSerializeJSONString:(NSString*) jsonString { - NSError *error = nil; - NSData* data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; - id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; - if(error) { - [RSLogger logError:[[NSString alloc] initWithFormat:@"Failed to serialize the given string back to object %@", jsonString]]; - return nil; - } - return object; -} - + (BOOL) isValidURL:(NSURL*) url { return url && [url scheme] && [url host]; } @@ -252,6 +158,107 @@ + (BOOL) isEmptyString:(NSString*)value { return (value == nil || value.length == 0); } ++ (NSString* _Nullable) serialize:(id) object { + @try { + id sanitizedObject = [self sanitizeObject:object]; + NSData *objectData = [NSJSONSerialization dataWithJSONObject:sanitizedObject options:0 error:nil]; + if (objectData != nil) { + NSString *objectString = [[NSString alloc] initWithData:objectData encoding:NSUTF8StringEncoding]; + return objectString; + } + } @catch (NSException *exception) { + [RSLogger logError:[[NSString alloc] initWithFormat:@"RSUtils: serialize: Failed to serialize the given object due to %@", exception]]; + } + return nil; +} + ++ (id _Nullable) deserialize:(NSString*) jsonString { + @try { + NSError *error = nil; + NSData* data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + if(error) { + [RSLogger logError:[[NSString alloc] initWithFormat:@"RSUtils: deserialize: Failed to de-serialize the given string back to an object %@", jsonString]]; + return nil; + } + return object; + } @catch (NSException *exception) { + [RSLogger logError:[[NSString alloc] initWithFormat:@"RSUtils: deserialize: Failed to de-serialize the given string back to an object due to %@", exception]]; + } + return nil; +} + +// will stringify NSDate, NSURL Objects, invalid numbers (INFINITY, -INFINITY, NAN) to strings to ensure serialization doesn't fails ++ (id) sanitizeObject: (id) val { + // return immediately if the object is valid + if([NSJSONSerialization isValidJSONObject:val]) { + return val; + } + + // if the object is invalid, sanitize it + if ([val isKindOfClass:[NSString class]] || [val isKindOfClass:[NSNull class]]) { + return val; + } else if ([val isKindOfClass:[NSNumber class]]) { + // convert invalid numbers to strings + if ([self isSpecialFloatingNumber:(NSNumber *) val]) { + return [self serializeSpecialFloatingNumber:val]; + } + return val; + } else if ([val isKindOfClass:[NSDate class]]) { + // handle date // isofy + return [self getDateString:val]; + } else if ([val isKindOfClass:[NSURL class]]) { + // handle url + NSString* urlString = [val absoluteString]; + return urlString !=nil ? urlString: @""; + } else if ([val isKindOfClass:[NSArray class]]) { + // handle array + return [self sanitizeArray:val]; + } else if ([val isKindOfClass:[NSDictionary class]] || [val isKindOfClass:[NSMutableDictionary class]]) { + // handle dictionary + return [self sanitizeDictionary:val]; + } + [RSLogger logDebug:@"properties value is not serializable. using description"]; + return [val description]; +} + ++ (NSMutableDictionary *)sanitizeDictionary:(id)val { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + NSArray *keys = [val allKeys]; + for (NSString *key in keys) { + id value = [val objectForKey:key]; + if (![key isKindOfClass:[NSString class]]) { + [RSLogger logDebug:@"key should be string. changing it to its description"]; + } + [dict setValue:[self sanitizeObject:value] forKey:[key description]]; + } + return dict; +} + ++ (id)sanitizeArray:(id)val { + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (id i in val) { + [array addObject:[self sanitizeObject:i]]; + } + return [array copy]; +} + ++ (BOOL) isSpecialFloatingNumber:(NSNumber *)number { + return ([number isEqualToNumber:[NSDecimalNumber notANumber]] + || isinf([number doubleValue])); +} + ++ (NSString*) serializeSpecialFloatingNumber: (NSNumber *) number { + if ([number isEqualToNumber:[NSDecimalNumber notANumber]]) { + return @"NaN"; + } else if ([number isEqualToNumber:[NSNumber numberWithDouble:INFINITY]]) { + return @"Infinity"; + } else if ([number isEqualToNumber:[NSNumber numberWithDouble:-INFINITY]]) { + return @"-Infinity"; + } + return [number stringValue]; +} + unsigned int MAX_EVENT_SIZE = 32 * 1024; // 32 KB unsigned int MAX_BATCH_SIZE = 500 * 1024; // 500 KB diff --git a/Tests/RudderUtilsTest.swift b/Tests/RudderUtilsTest.swift index 4b6dae8b..e5c25d6a 100644 --- a/Tests/RudderUtilsTest.swift +++ b/Tests/RudderUtilsTest.swift @@ -11,20 +11,13 @@ import Rudder class RudderUtilsTest: XCTestCase { - override func setUpWithError() throws { - - } - - override func tearDownWithError() throws { - } - func testGetCSVString() throws { let bio:[String] = ["Desu","Mobile Engineer", "RudderStack"] - let bioCSV = RSUtils.getCSVString(bio) + let bioCSV = RSUtils.getCSVString(from: bio) print(bioCSV) XCTAssert(bioCSV == "Desu,Mobile Engineer,RudderStack") let carriers:[String] = ["Airtel"] - let carriersCSV = RSUtils.getCSVString(carriers) + let carriersCSV = RSUtils.getCSVString(from: carriers) print(carriersCSV) XCTAssertEqual(carriersCSV, "Airtel") @@ -32,7 +25,7 @@ class RudderUtilsTest: XCTestCase { func testGetJSONCSVString() throws { let bio:[String] = ["Desu","Mobile Engineer", "RudderStack"] - let bioJSONCSV = RSUtils.getJSONCSVString(bio) + let bioJSONCSV = RSUtils.getCSVString(from: bio) print(bioJSONCSV == "\"Desu\",\"Mobile Engineer\",\"RudderStack\"") } @@ -65,7 +58,7 @@ class RudderUtilsTest: XCTestCase { "company" : "RudderStack", "city" : "Hyderabad"] - let response = RSUtils.deSerializeJSONString(jsonString) + let response = RSUtils.deserialize(jsonString) let parsedDict:[String:String]? = response as? [String:String] ?? nil XCTAssert(parsedDict == dictObj) @@ -77,4 +70,277 @@ class RudderUtilsTest: XCTestCase { XCTAssertEqual(RSUtils.sortArray(NSMutableArray(array:numsArr), in: ASCENDING), NSMutableArray(array:[2,3,5,6,12])) XCTAssertEqual(RSUtils.sortArray(NSMutableArray(array:numsArr), in: DESCENDING), NSMutableArray(array:[12,6,5,3,2])) } + + func testSanitizeDictionary() { + let dirtyDict: [String:Any] = [ + "infinity": Double.infinity, + "NaN": Double.nan, + "negativeInfinity": -Double.infinity, + "max": Double.greatestFiniteMagnitude, + "min": Double.leastNormalMagnitude, + "normal": 1.0, + "zero": 0.0, + "negativeNormal": -1.0, + "general": 35, + "date": Date(), + "url": URL(string: "https://www.rudderstack.com")! + ] + + if let cleanDict = RSUtils.sanitizeObject(dirtyDict) as? [String:Any] { + XCTAssertTrue(cleanDict["infinity"] is String) + XCTAssertEqual(cleanDict["infinity"] as? String, "Infinity") + XCTAssertTrue(cleanDict["negativeInfinity"] is String) + XCTAssertEqual(cleanDict["negativeInfinity"] as? String, "-Infinity") + XCTAssertTrue(cleanDict["NaN"] is String) + XCTAssertEqual(cleanDict["NaN"] as? String, "NaN") + XCTAssertTrue(cleanDict["date"] is String) + XCTAssertTrue(cleanDict["url"] is String) + XCTAssertEqual(cleanDict["url"] as? String, "https://www.rudderstack.com") + XCTAssertTrue(cleanDict["max"] is Double) + XCTAssertEqual(cleanDict["max"] as? Double, Double.greatestFiniteMagnitude) + XCTAssertTrue(cleanDict["min"] is Double) + XCTAssertEqual(cleanDict["min"] as? Double, Double.leastNormalMagnitude) + XCTAssertTrue(cleanDict["normal"] is Double) + XCTAssertEqual(cleanDict["normal"] as? Double, 1.0) + XCTAssertTrue(cleanDict["zero"] is Double) + XCTAssertEqual(cleanDict["zero"] as? Double, 0.0) + XCTAssertTrue(cleanDict["negativeNormal"] is Double) + XCTAssertEqual(cleanDict["negativeNormal"] as? Double, -1.0) + XCTAssertTrue(cleanDict["general"] is Int) + XCTAssertEqual(cleanDict["general"] as? Int, 35) + } else { + XCTFail("Clean Dict shouldn't be nil") + } + } + + func testSanitizeArray() { + let dirtyArray: [Any] = [ + Double.infinity, + Double.nan, + -Double.infinity, + Double.greatestFiniteMagnitude, + Double.leastNormalMagnitude, + 1.0, + 0.0, + -1.0, + 35, + Date(), + URL(string: "https://www.rudderstack.com")! + ] + + if let cleanArray = RSUtils.sanitizeObject(dirtyArray) as? [Any] { + XCTAssertTrue(cleanArray[0] is String) + XCTAssertEqual(cleanArray[0] as? String, "Infinity") + XCTAssertTrue(cleanArray[1] is String) + XCTAssertEqual(cleanArray[1] as? String, "NaN") + XCTAssertTrue(cleanArray[2] is String) + XCTAssertEqual(cleanArray[2] as? String, "-Infinity") + XCTAssertTrue(cleanArray[3] is Double) + XCTAssertEqual(cleanArray[3] as? Double, Double.greatestFiniteMagnitude) + XCTAssertTrue(cleanArray[4] is Double) + XCTAssertEqual(cleanArray[4] as? Double, Double.leastNormalMagnitude) + XCTAssertTrue(cleanArray[5] is Double) + XCTAssertEqual(cleanArray[5] as? Double, 1.0) + XCTAssertTrue(cleanArray[6] is Double) + XCTAssertEqual(cleanArray[6] as? Double, 0.0) + XCTAssertTrue(cleanArray[7] is Double) + XCTAssertEqual(cleanArray[7] as? Double, -1.0) + XCTAssertTrue(cleanArray[8] is Int) + XCTAssertEqual(cleanArray[8] as? Int, 35) + XCTAssertTrue(cleanArray[9] is String) + XCTAssertTrue(cleanArray[10] is String) + XCTAssertEqual(cleanArray[10] as? String, "https://www.rudderstack.com") + } else { + XCTFail("Clean Array shouldn't be nil") + } + } + + func testSanitizeNestedDictionary() { + let dirtyDict: [String:Any] = [ + "date": Date(), + "url": URL(string: "https://www.rudderstack.com")!, + "nestedDict": [ + "infinity": Double.infinity, + "NaN": Double.nan, + "negativeInfinity": -Double.infinity, + "max": Double.greatestFiniteMagnitude, + ], + "nestedArray": [ + Double.infinity, + Double.nan, + Double.greatestFiniteMagnitude, + [ + "date": Date(), + "url": URL(string: "https://www.rudderstack.com")!, + ] + ] + ] + + if let cleanDict = RSUtils.sanitizeObject(dirtyDict) as? [String:Any] { + XCTAssertTrue(cleanDict["date"] is String) + XCTAssertTrue(cleanDict["url"] is String) + XCTAssertEqual(cleanDict["url"] as? String, "https://www.rudderstack.com") + XCTAssertTrue(cleanDict["nestedDict"] is [String:Any]) + if let nestedDict = cleanDict["nestedDict"] as? [String:Any] { + XCTAssertTrue(nestedDict["infinity"] is String) + XCTAssertEqual(nestedDict["infinity"] as? String, "Infinity") + XCTAssertTrue(nestedDict["negativeInfinity"] is String) + XCTAssertEqual(nestedDict["negativeInfinity"] as? String, "-Infinity") + XCTAssertTrue(nestedDict["NaN"] is String) + XCTAssertEqual(nestedDict["NaN"] as? String, "NaN") + XCTAssertTrue(nestedDict["max"] is Double) + XCTAssertEqual(nestedDict["max"] as? Double, Double.greatestFiniteMagnitude) + } else { + XCTFail("Nested Dict shouldn't be nil") + } + XCTAssertTrue(cleanDict["nestedArray"] is [Any]) + if let nestedArray = cleanDict["nestedArray"] as? [Any] { + XCTAssertTrue(nestedArray[0] is String) + XCTAssertEqual(nestedArray[0] as? String, "Infinity") + XCTAssertTrue(nestedArray[1] is String) + XCTAssertEqual(nestedArray[1] as? String, "NaN") + XCTAssertTrue(nestedArray[2] is Double) + XCTAssertEqual(nestedArray[2] as? Double, Double.greatestFiniteMagnitude) + XCTAssertTrue(nestedArray[3] is [String:Any]) + if let nestedDict = nestedArray[3] as? [String:Any] { + XCTAssertTrue(nestedDict["date"] is String) + XCTAssertTrue(nestedDict["url"] is String) + XCTAssertEqual(nestedDict["url"] as? String, "https://www.rudderstack.com") + } else { + XCTFail("Nested Dict shouldn't be nil") + } + } else { + XCTFail("Nested Array shouldn't be nil") + } + } + } + + func testSanitizeNestedArray() { + let dirtyArray: [Any] = [ + Double.infinity, + Double.nan, + -Double.infinity, + Double.greatestFiniteMagnitude, + Double.leastNormalMagnitude, + 1.0, + 0.0, + -1.0, + 35, + Date(), + URL(string: "https://www.rudderstack.com")!, + [ + "date": Date(), + "url": URL(string: "https://www.rudderstack.com")!, + "nestedDict": [ + "infinity": Double.infinity, + "NaN": Double.nan, + "negativeInfinity": -Double.infinity, + "max": Double.greatestFiniteMagnitude, + ], + "nestedArray": [ + Double.infinity, + Double.nan, + Double.greatestFiniteMagnitude, + [ + "date": Date(), + "url": URL(string: "https://www.rudderstack.com")!, + ] + ] + ] + ] + + if let cleanArray = RSUtils.sanitizeObject(dirtyArray) as? [Any] { + XCTAssertTrue(cleanArray[0] is String) + XCTAssertEqual(cleanArray[0] as? String, "Infinity") + XCTAssertTrue(cleanArray[1] is String) + XCTAssertEqual(cleanArray[1] as? String, "NaN") + XCTAssertTrue(cleanArray[2] is String) + XCTAssertEqual(cleanArray[2] as? String, "-Infinity") + XCTAssertTrue(cleanArray[3] is Double) + XCTAssertEqual(cleanArray[3] as? Double, Double.greatestFiniteMagnitude) + XCTAssertTrue(cleanArray[4] is Double) + XCTAssertEqual(cleanArray[4] as? Double, Double.leastNormalMagnitude) + XCTAssertTrue(cleanArray[5] is Double) + XCTAssertEqual(cleanArray[5] as? Double, 1.0) + XCTAssertTrue(cleanArray[6] is Double) + XCTAssertEqual(cleanArray[6] as? Double, 0.0) + XCTAssertTrue(cleanArray[7] is Double) + XCTAssertEqual(cleanArray[7] as? Double, -1.0) + XCTAssertTrue(cleanArray[8] is Int) + XCTAssertEqual(cleanArray[8] as? Int, 35) + XCTAssertTrue(cleanArray[9] is String) + XCTAssertTrue(cleanArray[10] is String) + XCTAssertEqual(cleanArray[10] as? String, "https://www.rudderstack.com") + XCTAssertTrue(cleanArray[11] is [String:Any]) + if let nestedDict = cleanArray[11] as? [String:Any] { + XCTAssertTrue(nestedDict["date"] is String) + XCTAssertTrue(nestedDict["url"] is String) + XCTAssertEqual(nestedDict["url"] as? String, "https://www.rudderstack.com") + XCTAssertTrue(nestedDict["nestedDict"] is [String:Any]) + if let nestedDict = nestedDict["nestedDict"] as? [String:Any] { + XCTAssertTrue(nestedDict["infinity"] is String) + XCTAssertEqual(nestedDict["infinity"] as? String, "Infinity") + XCTAssertTrue(nestedDict["negativeInfinity"] is String) + XCTAssertEqual(nestedDict["negativeInfinity"] as? String, "-Infinity") + XCTAssertTrue(nestedDict["NaN"] is String) + XCTAssertEqual(nestedDict["NaN"] as? String, "NaN") + XCTAssertTrue(nestedDict["max"] is Double) + XCTAssertEqual(nestedDict["max"] as? Double, Double.greatestFiniteMagnitude) + } else { + XCTFail("Nested Dict shouldn't be nil") + } + XCTAssertTrue(nestedDict["nestedArray"] is [Any]) + if let nestedArray = nestedDict["nestedArray"] as? [Any] { + XCTAssertTrue(nestedArray[0] is String) + XCTAssertEqual(nestedArray[0] as? String, "Infinity") + XCTAssertTrue(nestedArray[1] is String) + XCTAssertEqual(nestedArray[1] as? String, "NaN") + XCTAssertTrue(nestedArray[2] is Double) + XCTAssertEqual(nestedArray[2] as? Double, Double.greatestFiniteMagnitude) + XCTAssertTrue(nestedArray[3] is [String:Any]) + if let nestedDict = nestedArray[3] as? [String:Any] { + XCTAssertTrue(nestedDict["date"] is String) + XCTAssertTrue(nestedDict["url"] is String) + XCTAssertEqual(nestedDict["url"] as? String, "https://www.rudderstack.com") + } else { + XCTFail("Nested Dict shouldn't be nil") + } + } else { + XCTFail("Nested Array shouldn't be nil") + } + } else { + XCTFail("Nested Dict shouldn't be nil") + } + } + } + + func testIsInvalidNumber() { + XCTAssertTrue(RSUtils.isSpecialFloating(Double.infinity as NSNumber)) + XCTAssertTrue(RSUtils.isSpecialFloating(Double.nan as NSNumber)) + XCTAssertTrue(RSUtils.isSpecialFloating(-Double.infinity as NSNumber)) + XCTAssertFalse(RSUtils.isSpecialFloating(Double.greatestFiniteMagnitude as NSNumber)) + XCTAssertFalse(RSUtils.isSpecialFloating(Double.leastNormalMagnitude as NSNumber)) + XCTAssertFalse(RSUtils.isSpecialFloating(1.0)) + XCTAssertFalse(RSUtils.isSpecialFloating(0.0)) + XCTAssertFalse(RSUtils.isSpecialFloating(-1.0)) + XCTAssertFalse(RSUtils.isSpecialFloating(35)) + } + + func testSerialize() { + let dictObj : [String:Any] = [ + "name" : "Desu Sai Venkat", + "company" : "RudderStack", + "date": Date(), + "infinity": Double.infinity, + "url": URL(string: "https://www.rudderstack.com")!, + "NaN": Double.nan, + "city" : "Hyderabad"] + let jsonString = RSUtils.serialize(dictObj) + XCTAssertNotNil(jsonString) + // ensure that url, nan, date are sanitized in the string + XCTAssertTrue(jsonString!.contains("rudderstack.com")) + XCTAssertTrue(jsonString!.contains("NaN")) + XCTAssertTrue(jsonString!.contains("date")) + XCTAssertTrue(jsonString!.contains("Infinity")) + } } diff --git a/package.json b/package.json index 4f8a7ae2..75e1db1e 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,4 @@ { - "version": "1.24.1", + "version": "1.25.1", "description": "Rudder is a platform for collecting, storing and routing customer event data to dozens of tools" } diff --git a/sonar-project.properties b/sonar-project.properties index 99cb3842..3eff9016 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,7 +6,7 @@ sonar.qualitygate.wait=false sonar.projectKey=rudderlabs_rudder-sdk-ios sonar.organization=rudderlabs sonar.projectName=RudderStack iOS SDK -sonar.projectVersion=1.24.1 +sonar.projectVersion=1.25.1 # C/C++/Objective-C related details # sonar.cfamily.compile-commands=compile_commands.json