From c4c6275465e6c4dff454f3dc4a041e1d193c9d6f Mon Sep 17 00:00:00 2001 From: Kevin Farst <58189473+kevinfarst-earnin@users.noreply.github.com> Date: Thu, 24 Sep 2020 17:24:54 -0700 Subject: [PATCH] [MOBFND-134] Upgrade to version 4.0.5 (#7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update Nimble to build with Xcode 10.2 * Add name and properties to auto screen reporting * Make seg_topViewController handle tab and custom container VCs * Simplify SEGScreenReporting protocol Inspired by comments from @f2prateek, simplify the the `SEGScreenReporting` protocol to replace the name and properties fields with a single method (`seg_trackScreen`) that can be implemented when screen tracking for a specific view controller that needs a custom name, properties, or options. * Add tests for seg_topViewController * adding “name” field to payload;updated nimble to version 7.3.4 * Fix GCD mutual dependency (#785) * Add iOS Backgrounded Event. (#831) * Add iOS Backgrounded Event. * Bump Xcode CI version * Bump pods * Updated properties * Simplified App Backgrounded call * Fixed test since we dropped the param. * Reverted xcode CI version number * LIB-1212: Promoting 3.7.0-beta.4 to release. (#834) (#836) * Prepare for release 3.7.0 * Updated cartfile. * Updated version in SEGAnalytics.m * Updated version in readme instructions. * Preparing 3.8.0-beta.0 release. (#837) (#838) * Preparing 3.8.0-beta.0 release. * `CoreTelephony` library is now only included on iOS targets. This was done so that tvOS targets could build without linker errors. (#842) * Add support for SSL Pinning (#839) * Support SSL pinning Client integrations can optionally pass in a NSURLSessionDelegate in the SEGAnalyticsConfiguration object. If set, NSURLSessionDelegate callbacks are forwarded to the client code where SSL pinning checks can be implemented * test httpSessionDelegate configuration * Fix for LIB-1416 & Github #846 (#853) * Fix for LIB-1416 & Github #846 - Stops blindly passing dictionaries. - Property dictionaries are checked for NSCoding conformance to ensure they can be serialized. - Property dictionaries are deep copied so contents can’t change while the pipeline is in progress. - Puts a try/catch arrangement as a temporary guard against crashes for serialization failures until the storage format can be changed. * Fixed missing ; * Added test for deepCopy/conformance additions. * Swapped JSON in for the storage format instead of plists. (#854) * Converted file storage to JSON from plist. * Updated string storage to account for JSON vs plist differences. * update podfile lock. * Remove some NSNull hacks. * Updated tests to validate null values. * Fixed LIB-1462 (#855) * Reload static context data when the app returns from background. (#856) * Respond to changes regarding advertising ID. * Removed unnecessary context. * Remove extraneous NSNull handling causing tests to fail. * Added weakify/strongify macros. * Removed extraneous NSNull checking. * Put locking around static context access. * Prepare for release 3.8.0-beta.1 * Fix changelog for 3.8.0-beta.1 * Updated carthage versions. * Update config.yml * [tvOS] Move SEGQueue from UserDefaults to caches directory (#861) * Stops using UserDefaults for queue on tvOS and uses NSCachesDirectory Changes storage to fileStorage and userDefaultsStorage. Utilizes userDefaults on tvOS for information such as anonymousID and configuration, but moves tvOS's queue into the NSCachesDirectory. The reasoning is that tvOS has a 1mb limit for UserDefaults and the queue can grow rapidly in size, leading to app crashes when saving more than 1mb of data to UserDefaults. * Adds a constant for key. Seperate cache dir and appSupport dir functions. Removes unused init. * Adds functionality to remove old UserDefaults queue on tvOS. Updates migrated removal block to account for tvOS now that the queue is no longer in UserDefaults. Adds back in a #else and #endif that was accidently removed. * Adds tvOS unit test target * Adds new AnalyticsTestsTVOS scheme * Updates pods to include all test pods for AnalyticsTestsTVOS * Fixes unit test import for QuickTVOS * Add tvOS options for make file * Enabled code coverage on tvOS tests * Fix up unit test warning "result of expect is never nil" * Adds test to ensure that UserDefaults SEGQueue is cleared on initialization for tvOS & iOS * Adds test to ensure SEGQueue is empty when missing form file storage * Reverts unnecessary import for QuickTVOS * Adds test for FileStorage caches directory helper * Fix up: Adds SwiftTryCatch pod to tvOS test target * Fix up makefile to have correct build target for build-ios & build-tvos * Fix up: updates xcodebuild destination to match devices found on circleci * Break up ios and tvos build/test steps * Circleci: Cache pods * Fix up: tvOS test build * Fix up spacing * Fix up flaky unit test Co-authored-by: Connor Ricks * Fix issues around plist->json conversion & nil values (#862) * Fixing a crash from plist->json conversion where result is not actually a dictionary. * Made code flow the same as non-conversion. * Set compatibility to 10.0. * Fixed issues around setting nil values even though they are expected. * Address Issue #851; Expect dictionary as well for for integration enablement (#863) * Address Issue #851; Expect dictionary as well for for integration enablement. * Fixed broken test. * Differences observed in how iOS/android pass userId/anonId; Corrected. (#864) * Disabled tvOS tests temporarily. * Updated podfile lock. * Fixed LIB-1698; Differences observed in how ios/android pass userId/anonId in traits. * Another podfile lock update. * Fixed test. * Set swift version for tests. * Reverted podfile lock changes due to incompatibilities. * Look at previously cached settings before blowing them away. (#866) * Bsneed/timestamps (#876) * LIB-1656: Added nanosecond timestamps * Actually use the timestamp we’re carrying around. * In case the context is modified, preserve the timestamp. * Bump timestamp nanosecond precision to 9. * Only carry over the timestamp during a modify if there was one to begin with. * Added experimental options to configuration. * Added a second version of 8601 date creation. * Respect experimental value now present in config. * Added nanosecond time test. Co-authored-by: Brandon Sneed * Prepare for release 3.8.0-beta.2. * Fixed warning. * Updated carthage files. * Implement maximum batch request size (#874) * Implement maximum request size * Add test when batch exceeds the size * Execute check before gzip * Remove stub request * Added Integration Middleware capabilities (#879) * Added integration middleware support. * Fixed warnings; Updated project to recommended settings. * only signal the runner if there’s actually middleware to be processed. * Added & Updated tests. * Added experimental raw filter block. * Removed unnecessary logs. * Added logic to allow tests to function. Co-authored-by: Brandon Sneed * Prepare for release 3.8.0. * Updated carthage files. * Prepare for release 4.0.0-beta.0. * Updated carthage files. * fixed a crash in file storage when trying to get a string stored using old SDK version (#880) * fixed a crash in file storage when trying to get a string stored using old SDK version (#880) * Fixed issue where build/version were removed from Application Opened events from background state. * Publish filenames used for data storage (#865) * Publish filenames used for data storage (#865) * Remove tvos test from scheme setup. * Fixed selector reference. * Removed unused code. * Misc Fixes (#884) * Add name and properties to auto screen reporting * Make seg_topViewController handle tab and custom container VCs * Simplify SEGScreenReporting protocol Inspired by comments from @f2prateek, simplify the the `SEGScreenReporting` protocol to replace the name and properties fields with a single method (`seg_trackScreen`) that can be implemented when screen tracking for a specific view controller that needs a custom name, properties, or options. * Update Nimble to build with Xcode 10.2 * Add tests for seg_topViewController * fixed a crash in file storage when trying to get a string stored using old SDK version (#880) * Fixed issue where build/version were removed from Application Opened events from background state. * Publish filenames used for data storage (#865) * Remove tvos test from scheme setup. * Fixed selector reference. * Removed unused code. Co-authored-by: David Whetstone Co-authored-by: Sergei Guselnikov Co-authored-by: Brandon Sneed Co-authored-by: Błażej Biesiada * Update CHANGELOG.md * Add ability to set default settings is segment.com can't be reached. (#888) * Added integration middleware support. * Fixed warnings; Updated project to recommended settings. * only signal the runner if there’s actually middleware to be processed. * Added & Updated tests. * Added experimental raw filter block. * Removed unnecessary logs. * Added logic to allow tests to function. * Allow for user-supplied settings. * Make sure segment.io is still present in the integrations list. * Added ability to set default settings if segment.com can’t be reached. * Removed test code. Co-authored-by: Brandon Sneed * Fixed defaultSettings documentation. * Add previouslyCachedSettings count (#889) * Add previouslyCachedSettings count (#889) * Prepare for release 3.8.1 * Updated carthage files to 3.8.1 * Prepare for release 3.8.2. * Update CHANGELOG.md * Updated carthage files for 3.8.2 * Allow customers to set default settings values if segment.com unreachable. (#891) * Added integration middleware support. * Fixed warnings; Updated project to recommended settings. * only signal the runner if there’s actually middleware to be processed. * Added & Updated tests. * Added experimental raw filter block. * Removed unnecessary logs. * Added logic to allow tests to function. * Allow for user-supplied settings. * Make sure segment.io is still present in the integrations list. * Added ability to set default settings if segment.com can’t be reached. * Removed test code. Co-authored-by: Brandon Sneed * Makes IDFA support externally/customer driven. (#892) * Remove IDFA related bits and push to customers. * Check if ad block is nil before executing * Fixed header reference. * Adjusted IDFA test. Co-authored-by: Brandon Sneed * Prepare for release 4.0.0-beta.1 * Updated tests to remove Alamofire (#895) Co-authored-by: Cody Garvin * Renamed middleware methods to match a.js naming. (#896) * Renamed middleware methods to match a.js naming. * Updated a comment re integration/destination. Co-authored-by: Brandon Sneed * Add ability to set default settings is segment.com can't be reached. Backported from #888 (#897) Co-authored-by: Brandon Sneed * change logic for naming conventions (#885) * Prepare for release 3.9.0 * Updated carthage files for 3.9.0 * Merged 3.9 changelog; Bumped CI xcode version. * change logic for naming conventions (#885) * LIB-83: Fixed crash on UISceneDelegate applications (#899) Co-authored-by: Cody Garvin * Added application object back to notifications (#900) Co-authored-by: Cody Garvin * LIB-35: Updated class names for Swift (#902) Co-authored-by: Cody Garvin * Added Swift Package Manager support (#904) * Add global state management (#905) * First pass at basic state management * First bit of state being shared. * Wrapped up state management. * Commented out old iAd references. * Filled in missing fields and adding messageId * Removed comments * Removed unused code. * Adjustments to nullability Co-authored-by: Brandon Sneed * Prepare for release 4.0.1. * Update cartfile.resolved. * LIBMOBILE-77: Removed Quick and Nimble, updated unit tests (#909) * Spm update (#911) * LIBMOBILE-77: Removed Quick and Nimble, updated unit tests * Issue 906: Updated package to supports all types of libraries * Payload Info & Traits Fixes (#912) * Moved some fields from SEGContext to more appropriate SEGPayload. * Fix trait storage/init issue. * Fixed traits usage w/ tests. Co-authored-by: Brandon Sneed * Separate public utils from private utils appropriately (#913) * Separated public utils from private utils * Made SEGAnalyticsUtils public. * Fixed header includes. Co-authored-by: Brandon Sneed * Prepare for release 4.0.2 * Fix SwiftUI previews in macOS Catalyst builds (#914) * Fix Swift Package Manager macOS Catalyst builds Link CoreTelephony to address a link error on macOS Catalyst. * Add macOS to the conditionals for linking CoreTelephony. * Full example (#915) * Added initial full example app * Added full example app with Swift Package Manager Co-authored-by: Cody Garvin * LIBMOBILE-109: Updated an issue with new traits not overriding old traits (#917) * Prepare for release 4.0.3 * Miscellaneous Fixes (#920) * Fixed issue with userId not being cleared properly in a reset. * Removed SwiftTryCatch dependency * Removed unnecessary bridging header item in tests. * Updated to swift 5 syntax. * Workaround for issue where UIBackgroundTaskIdentifier is diff types between Objc / Swift * Removed unused code. * Fixed issue w/ deadlock setting device token * Fixed tests. Co-authored-by: Brandon Sneed * Fixed SEGLog permissions (#921) * Migs647/macconversion (#918) * Added Catalyst compatibility * Added MacOS support * Updated example apps to use SPM * Repaired example SPM dependencies * Fixed makefile for carthage to handle iOS only * Prepare for release 4.0.4 * Added Carthage and SwiftPM badge * Disregard payloads that fail conversion from plist to json backing (#925) * Deprecated configuration access and updated associated tests * [LIBMOBILE-149] Fixed double device payload * Added stubs for edge functions. (#932) Co-authored-by: Brandon Sneed * Fixed property access * Fixed issue where non-serializable types would get into payload (#937) Co-authored-by: Brandon Sneed * Prepare for release 4.0.5 * Rename Reachability to SEGReachability Co-authored-by: David Whetstone Co-authored-by: Daniel Jackins Co-authored-by: dsjackins Co-authored-by: Fathy Boundjadj Co-authored-by: Carlos Kelly Co-authored-by: Brandon Sneed Co-authored-by: Dan Morrow Co-authored-by: Ujjawal Garg <47793370+ujjawalgarg@users.noreply.github.com> Co-authored-by: Brandon Sneed Co-authored-by: Ben Humphries Co-authored-by: Connor Ricks Co-authored-by: Cristian Lupu Co-authored-by: Sergei Guselnikov Co-authored-by: Błażej Biesiada Co-authored-by: alanjcharles <50601149+alanjcharles@users.noreply.github.com> Co-authored-by: Cody Garvin Co-authored-by: Cody Garvin Co-authored-by: Ko Co-authored-by: Matt Gallagher Co-authored-by: Mike Ciesielka --- .circleci/config.yml | 5 +- .gitignore | 4 + Analytics.podspec | 4 +- Analytics.xcodeproj/project.pbxproj | 207 ++--- .../xcshareddata/xcschemes/Analytics.xcscheme | 2 +- .../xcschemes/AnalyticsTests.xcscheme | 2 +- Analytics/Classes/.gitkeep | 0 Analytics/{ => Classes}/Analytics.h | 3 +- Analytics/Classes/Integrations/SEGPayload.m | 35 - Analytics/Classes/Internal/SEGUtils.h | 17 - .../{Integrations => }/SEGAliasPayload.h | 2 +- .../{Integrations => }/SEGAliasPayload.m | 0 Analytics/Classes/SEGAnalytics.h | 11 +- Analytics/Classes/SEGAnalytics.m | 165 +++- Analytics/Classes/SEGAnalyticsConfiguration.h | 73 +- Analytics/Classes/SEGAnalyticsConfiguration.m | 33 +- Analytics/Classes/SEGAnalyticsUtils.h | 10 + Analytics/Classes/SEGAnalyticsUtils.m | 23 + .../Classes/{Middlewares => }/SEGContext.h | 7 +- .../Classes/{Middlewares => }/SEGContext.m | 4 +- Analytics/Classes/{Crypto => }/SEGCrypto.h | 0 .../{Integrations => }/SEGGroupPayload.h | 2 +- .../{Integrations => }/SEGGroupPayload.m | 0 .../Classes/{Internal => }/SEGHTTPClient.h | 1 + .../Classes/{Internal => }/SEGHTTPClient.m | 0 .../{Integrations => }/SEGIdentifyPayload.h | 6 +- .../{Integrations => }/SEGIdentifyPayload.m | 8 +- .../{Integrations => }/SEGIntegration.h | 1 + .../SEGIntegrationFactory.h | 0 Analytics/Classes/{Internal => }/SEGMacros.h | 0 .../Classes/{Middlewares => }/SEGMiddleware.h | 24 +- .../Classes/{Middlewares => }/SEGMiddleware.m | 31 +- .../Classes/{Integrations => }/SEGPayload.h | 10 +- Analytics/Classes/SEGPayload.m | 44 + .../{Vendor => Classes}/SEGReachability.h | 1 + .../{Vendor => Classes}/SEGReachability.m | 0 .../{Integrations => }/SEGScreenPayload.h | 1 + .../{Integrations => }/SEGScreenPayload.m | 0 .../{Internal => }/SEGScreenReporting.h | 0 .../{Internal => }/SEGSegmentIntegration.h | 1 + .../{Internal => }/SEGSegmentIntegration.m | 387 +++------ .../Classes/SEGSegmentIntegrationFactory.h | 20 + .../SEGSegmentIntegrationFactory.m | 0 Analytics/Classes/{Internal => }/SEGStorage.h | 0 .../{Integrations => }/SEGTrackPayload.h | 1 + .../{Integrations => }/SEGTrackPayload.m | 0 Analytics/Info.plist | 2 +- .../{Classes => }/Internal/NSData+SEGGZIP.h | 0 .../{Classes => }/Internal/NSData+SEGGZIP.m | 0 .../Internal/NSViewController+SEGScreen.h | 21 + .../Internal/NSViewController+SEGScreen.m | 99 +++ .../Crypto => Internal}/SEGAES256Crypto.h | 1 + .../Crypto => Internal}/SEGAES256Crypto.m | 0 .../{Classes => }/Internal/SEGFileStorage.h | 1 + Analytics/Internal/SEGFileStorage.m | 277 +++++++ .../SEGIntegrationsManager.h | 2 +- .../SEGIntegrationsManager.m | 226 +++-- Analytics/Internal/SEGMacros.h | 28 + Analytics/Internal/SEGState.h | 45 + Analytics/Internal/SEGState.m | 212 +++++ .../Internal/SEGStoreKitTracker.h | 1 + .../Internal/SEGStoreKitTracker.m | 0 .../Internal/SEGUserDefaultsStorage.h | 1 + .../Internal/SEGUserDefaultsStorage.m | 0 Analytics/Internal/SEGUtils.h | 82 ++ Analytics/Internal/SEGUtils.m | 673 +++++++++++++++ .../Internal/UIViewController+SEGScreen.h | 13 + .../Internal/UIViewController+SEGScreen.m | 124 +++ .../AnalyticsTests-Bridging-Header.h | 4 +- AnalyticsTests/AnalyticsTests.swift | 360 ++++---- AnalyticsTests/AnalyticsUtilTests.swift | 199 +++-- AnalyticsTests/AutoScreenReportingTest.swift | 115 +-- AnalyticsTests/ContextTest.swift | 120 ++- AnalyticsTests/CryptoTest.swift | 88 +- AnalyticsTests/EndToEndTests.swift | 111 +-- AnalyticsTests/FileStorageTest.swift | 235 +++--- AnalyticsTests/HTTPClientTest.swift | 380 +++++---- AnalyticsTests/IntegrationsManagerTest.swift | 175 ++-- AnalyticsTests/MiddlewareTests.swift | 190 +++-- AnalyticsTests/SerializationTests.m | 22 +- AnalyticsTests/StoreKitTrackerTests.swift | 50 +- AnalyticsTests/TrackingTests.swift | 155 ++-- AnalyticsTests/UserDefaultsStorageTest.swift | 155 ++-- AnalyticsTests/Utils/ObjcUtils.h | 11 + AnalyticsTests/Utils/ObjcUtils.m | 20 + AnalyticsTests/Utils/TestUtils.swift | 101 ++- CHANGELOG.md | 112 +++ Examples/CarthageExample/Cartfile | 2 +- Examples/CarthageExample/Cartfile.resolved | 2 +- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + Examples/CarthageExample/Makefile | 2 +- .../project.pbxproj | 444 ++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/swiftpm/Package.resolved | 16 + .../Analytics Example/AppDelegate.swift | 43 + .../AppIcon.appiconset/Contents.json | 101 +++ .../AppIcon.appiconset/Icon.png | Bin 0 -> 102508 bytes .../AppIcon.appiconset/Icon_120.png | Bin 0 -> 10223 bytes .../AppIcon.appiconset/Icon_180.png | Bin 0 -> 17086 bytes .../Assets.xcassets/Contents.json | 6 + .../SegmentLogo.imageset/Contents.json | 22 + .../SegmentLogo.imageset/Segment_Logo.png | Bin 0 -> 9072 bytes .../SegmentLogo.imageset/Segment_Logo@2x.png | Bin 0 -> 25167 bytes .../Splash.imageset/Contents.json | 21 + .../Splash.imageset/Splash.png | Bin 0 -> 33969 bytes .../Base.lproj/LaunchScreen.storyboard | 42 + .../Base.lproj/Main.storyboard | 109 +++ .../Controllers/AnonymousViewController.swift | 75 ++ .../Controllers/InviteViewController.swift | 63 ++ .../Controllers/LoginViewController.swift | 27 + .../Controllers/SignInViewController.swift | 63 ++ .../Controllers/SignoutViewController.swift | 63 ++ .../Controllers/SignupViewController.swift | 81 ++ .../Controllers/StartViewController.swift | 96 +++ .../Controllers/StepsViewController.swift | 154 ++++ .../Controllers/TrialEndViewController.swift | 84 ++ .../Analytics Example/Info.plist | 64 ++ .../Analytics Example/SceneDelegate.swift | 53 ++ .../project.pbxproj | 454 ++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/swiftpm/Package.resolved | 16 + .../Analytics Example.entitlements | 10 + .../Analytics Example/AppDelegate.swift | 43 + .../AppIcon.appiconset/Contents.json | 101 +++ .../AppIcon.appiconset/Icon.png | Bin 0 -> 102508 bytes .../AppIcon.appiconset/Icon_120.png | Bin 0 -> 10223 bytes .../AppIcon.appiconset/Icon_180.png | Bin 0 -> 17086 bytes .../Assets.xcassets/Contents.json | 6 + .../SegmentLogo.imageset/Contents.json | 22 + .../SegmentLogo.imageset/Segment_Logo.png | Bin 0 -> 9072 bytes .../SegmentLogo.imageset/Segment_Logo@2x.png | Bin 0 -> 25167 bytes .../Splash.imageset/Contents.json | 21 + .../Splash.imageset/Splash.png | Bin 0 -> 33969 bytes .../Base.lproj/LaunchScreen.storyboard | 42 + .../Base.lproj/Main.storyboard | 109 +++ .../Controllers/AnonymousViewController.swift | 75 ++ .../Controllers/InviteViewController.swift | 63 ++ .../Controllers/LoginViewController.swift | 27 + .../Controllers/SignInViewController.swift | 63 ++ .../Controllers/SignoutViewController.swift | 63 ++ .../Controllers/SignupViewController.swift | 81 ++ .../Controllers/StartViewController.swift | 96 +++ .../Controllers/StepsViewController.swift | 154 ++++ .../Controllers/TrialEndViewController.swift | 84 ++ .../Analytics Example/Info.plist | 64 ++ .../Analytics Example/SceneDelegate.swift | 53 ++ .../SegmentMac.xcodeproj/project.pbxproj | 381 +++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/swiftpm/Package.resolved | 16 + .../SegmentMac/SegmentMac/AppDelegate.swift | 24 + .../AppIcon.appiconset/Contents.json | 68 ++ .../AppIcon.appiconset/Segment_Logo-1024.png | Bin 0 -> 66945 bytes .../AppIcon.appiconset/Segment_Logo-128.png | Bin 0 -> 8128 bytes .../AppIcon.appiconset/Segment_Logo-16.png | Bin 0 -> 854 bytes .../AppIcon.appiconset/Segment_Logo-256.png | Bin 0 -> 16421 bytes .../AppIcon.appiconset/Segment_Logo-257.png | Bin 0 -> 16421 bytes .../AppIcon.appiconset/Segment_Logo-32.png | Bin 0 -> 1959 bytes .../AppIcon.appiconset/Segment_Logo-33.png | Bin 0 -> 1959 bytes .../AppIcon.appiconset/Segment_Logo-512.png | Bin 0 -> 34641 bytes .../AppIcon.appiconset/Segment_Logo-513.png | Bin 0 -> 34641 bytes .../AppIcon.appiconset/Segment_Logo-64.png | Bin 0 -> 4048 bytes .../SegmentMac/Assets.xcassets/Contents.json | 6 + .../Segment_Log.imageset/Contents.json | 21 + .../Segment_Log.imageset/Segment_Log.png | Bin 0 -> 53075 bytes .../SegmentMac/Base.lproj/Main.storyboard | 777 ++++++++++++++++++ Examples/SegmentMac/SegmentMac/Info.plist | 36 + .../SegmentMac/SegmentMac.entitlements | 14 + .../SegmentMac/ViewController.swift | 57 ++ Makefile | 4 +- Package.swift | 40 + Podfile | 5 - Podfile.lock | 31 +- README.md | 2 + RELEASING.md | 3 +- 177 files changed, 8552 insertions(+), 1822 deletions(-) delete mode 100644 Analytics/Classes/.gitkeep rename Analytics/{ => Classes}/Analytics.h (88%) delete mode 100644 Analytics/Classes/Integrations/SEGPayload.m delete mode 100644 Analytics/Classes/Internal/SEGUtils.h rename Analytics/Classes/{Integrations => }/SEGAliasPayload.h (92%) rename Analytics/Classes/{Integrations => }/SEGAliasPayload.m (100%) create mode 100644 Analytics/Classes/SEGAnalyticsUtils.h create mode 100644 Analytics/Classes/SEGAnalyticsUtils.m rename Analytics/Classes/{Middlewares => }/SEGContext.h (90%) rename Analytics/Classes/{Middlewares => }/SEGContext.m (95%) rename Analytics/Classes/{Crypto => }/SEGCrypto.h (100%) rename Analytics/Classes/{Integrations => }/SEGGroupPayload.h (94%) rename Analytics/Classes/{Integrations => }/SEGGroupPayload.m (100%) rename Analytics/Classes/{Internal => }/SEGHTTPClient.h (98%) rename Analytics/Classes/{Internal => }/SEGHTTPClient.m (100%) rename Analytics/Classes/{Integrations => }/SEGIdentifyPayload.h (79%) rename Analytics/Classes/{Integrations => }/SEGIdentifyPayload.m (72%) rename Analytics/Classes/{Integrations => }/SEGIntegration.h (99%) rename Analytics/Classes/{Integrations => }/SEGIntegrationFactory.h (100%) rename Analytics/Classes/{Internal => }/SEGMacros.h (100%) rename Analytics/Classes/{Middlewares => }/SEGMiddleware.h (64%) rename Analytics/Classes/{Middlewares => }/SEGMiddleware.m (55%) rename Analytics/Classes/{Integrations => }/SEGPayload.h (81%) create mode 100644 Analytics/Classes/SEGPayload.m rename Analytics/{Vendor => Classes}/SEGReachability.h (99%) rename Analytics/{Vendor => Classes}/SEGReachability.m (100%) rename Analytics/Classes/{Integrations => }/SEGScreenPayload.h (95%) rename Analytics/Classes/{Integrations => }/SEGScreenPayload.m (100%) rename Analytics/Classes/{Internal => }/SEGScreenReporting.h (100%) rename Analytics/Classes/{Internal => }/SEGSegmentIntegration.h (95%) rename Analytics/Classes/{Internal => }/SEGSegmentIntegration.m (60%) create mode 100644 Analytics/Classes/SEGSegmentIntegrationFactory.h rename Analytics/Classes/{Internal => }/SEGSegmentIntegrationFactory.m (100%) rename Analytics/Classes/{Internal => }/SEGStorage.h (100%) rename Analytics/Classes/{Integrations => }/SEGTrackPayload.h (94%) rename Analytics/Classes/{Integrations => }/SEGTrackPayload.m (100%) rename Analytics/{Classes => }/Internal/NSData+SEGGZIP.h (100%) rename Analytics/{Classes => }/Internal/NSData+SEGGZIP.m (100%) create mode 100644 Analytics/Internal/NSViewController+SEGScreen.h create mode 100644 Analytics/Internal/NSViewController+SEGScreen.m rename Analytics/{Classes/Crypto => Internal}/SEGAES256Crypto.h (96%) rename Analytics/{Classes/Crypto => Internal}/SEGAES256Crypto.m (100%) rename Analytics/{Classes => }/Internal/SEGFileStorage.h (95%) create mode 100644 Analytics/Internal/SEGFileStorage.m rename Analytics/{Classes/Integrations => Internal}/SEGIntegrationsManager.h (97%) rename Analytics/{Classes/Integrations => Internal}/SEGIntegrationsManager.m (77%) create mode 100644 Analytics/Internal/SEGMacros.h create mode 100644 Analytics/Internal/SEGState.h create mode 100644 Analytics/Internal/SEGState.m rename Analytics/{Classes => }/Internal/SEGStoreKitTracker.h (91%) rename Analytics/{Classes => }/Internal/SEGStoreKitTracker.m (100%) rename Analytics/{Classes => }/Internal/SEGUserDefaultsStorage.h (94%) rename Analytics/{Classes => }/Internal/SEGUserDefaultsStorage.m (100%) create mode 100644 Analytics/Internal/SEGUtils.h create mode 100644 Analytics/Internal/SEGUtils.m create mode 100644 Analytics/Internal/UIViewController+SEGScreen.h create mode 100644 Analytics/Internal/UIViewController+SEGScreen.m create mode 100644 AnalyticsTests/Utils/ObjcUtils.h create mode 100644 AnalyticsTests/Utils/ObjcUtils.m create mode 100644 Examples/CarthageExample/CarthageExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Examples/FullExampleFlow/Analytics Example.xcodeproj/project.pbxproj create mode 100644 Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Examples/FullExampleFlow/Analytics Example/AppDelegate.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon.png create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_120.png create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_180.png create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Contents.json create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Contents.json create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Segment_Logo.png create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Segment_Logo@2x.png create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Splash.imageset/Contents.json create mode 100644 Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Splash.imageset/Splash.png create mode 100644 Examples/FullExampleFlow/Analytics Example/Base.lproj/LaunchScreen.storyboard create mode 100644 Examples/FullExampleFlow/Analytics Example/Base.lproj/Main.storyboard create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/AnonymousViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/InviteViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/LoginViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/SignInViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/SignoutViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/SignupViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/StartViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/StepsViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Controllers/TrialEndViewController.swift create mode 100644 Examples/FullExampleFlow/Analytics Example/Info.plist create mode 100644 Examples/FullExampleFlow/Analytics Example/SceneDelegate.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.pbxproj create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Analytics Example.entitlements create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/AppDelegate.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon.png create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_120.png create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_180.png create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Contents.json create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Contents.json create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Segment_Logo.png create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Segment_Logo@2x.png create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Splash.imageset/Contents.json create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Splash.imageset/Splash.png create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Base.lproj/LaunchScreen.storyboard create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Base.lproj/Main.storyboard create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/AnonymousViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/InviteViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/LoginViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignInViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignoutViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignupViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/StartViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/StepsViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/TrialEndViewController.swift create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/Info.plist create mode 100644 Examples/FullExampleFlowCatalyst/Analytics Example/SceneDelegate.swift create mode 100644 Examples/SegmentMac/SegmentMac.xcodeproj/project.pbxproj create mode 100644 Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Examples/SegmentMac/SegmentMac/AppDelegate.swift create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-1024.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-128.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-16.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-256.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-257.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-32.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-33.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-512.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-513.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-64.png create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/Contents.json create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/Segment_Log.imageset/Contents.json create mode 100644 Examples/SegmentMac/SegmentMac/Assets.xcassets/Segment_Log.imageset/Segment_Log.png create mode 100644 Examples/SegmentMac/SegmentMac/Base.lproj/Main.storyboard create mode 100644 Examples/SegmentMac/SegmentMac/Info.plist create mode 100644 Examples/SegmentMac/SegmentMac/SegmentMac.entitlements create mode 100644 Examples/SegmentMac/SegmentMac/ViewController.swift create mode 100644 Package.swift diff --git a/.circleci/config.yml b/.circleci/config.yml index b8c1df26d..fec820d77 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,9 +1,8 @@ -version: 2 - +version: 2.1 jobs: build_and_test: macos: - xcode: "11.3.1" + xcode: "11.5.0" steps: - checkout - run: xcrun simctl list diff --git a/.gitignore b/.gitignore index e7f55eeae..d56c3b6e8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,10 @@ DerivedData # Bundler .bundle +# Swift Package Manager +.build +.swiftpm + Carthage # CocoaPods typically recommends against ignoring the Pods directory diff --git a/Analytics.podspec b/Analytics.podspec index c25989f0d..ddca15edb 100644 --- a/Analytics.podspec +++ b/Analytics.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Analytics" - s.version = "3.9.0" + s.version = "4.0.5" s.summary = "The hassle-free way to add analytics to your iOS app." s.description = <<-DESC @@ -22,6 +22,6 @@ Pod::Spec.new do |s| s.source_files = [ 'Analytics/Classes/**/*', - 'Analytics/Vendor/**/*' + 'Analytics/Internal/**/*' ] end diff --git a/Analytics.xcodeproj/project.pbxproj b/Analytics.xcodeproj/project.pbxproj index 0cdcb5611..2e3c5a484 100644 --- a/Analytics.xcodeproj/project.pbxproj +++ b/Analytics.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ 630FC8EA2107F2A500A759C5 /* SEGScreenReporting.h in Headers */ = {isa = PBXBuildFile; fileRef = 5AF0EDFEDC0EE79A0A0EB713 /* SEGScreenReporting.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E265C791FB1178C0030E08E /* IntegrationsManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E265C781FB1178C0030E08E /* IntegrationsManagerTest.swift */; }; 6EEC1C712017EA370089C478 /* EndToEndTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EEC1C702017EA370089C478 /* EndToEndTests.swift */; }; + 96A12C2824B680DB00949804 /* NSViewController+SEGScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 96A12C2624B680DB00949804 /* NSViewController+SEGScreen.h */; }; + 96A12C2924B680DB00949804 /* NSViewController+SEGScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 96A12C2724B680DB00949804 /* NSViewController+SEGScreen.m */; }; 9D8CE59023EE014E00197D0C /* CryptoTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EADEB8E91DECD335005322DA /* CryptoTest.swift */; }; 9D8CE59123EE014E00197D0C /* UserDefaultsStorageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EADEB8E61DECD335005322DA /* UserDefaultsStorageTest.swift */; }; 9D8CE59223EE014E00197D0C /* TrackingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA542761EB4035400945DA7 /* TrackingTests.swift */; }; @@ -30,7 +32,11 @@ 9D8CE5A023EE014E00197D0C /* Analytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADEB85B1DECD080005322DA /* Analytics.framework */; }; A31958EF2385AC3A00A47EFA /* SerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A31958EE2385AC3A00A47EFA /* SerializationTests.m */; }; A31CAFC224635F8400443BA4 /* AutoScreenReportingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AF0E8457CCFC077382BF449 /* AutoScreenReportingTest.swift */; }; + A34CC6DD249AAEBB00C5E368 /* SEGState.m in Sources */ = {isa = PBXBuildFile; fileRef = A34CC6DB249AAEBA00C5E368 /* SEGState.m */; }; + A34CC6DE249AAEBB00C5E368 /* SEGState.h in Headers */ = {isa = PBXBuildFile; fileRef = A34CC6DC249AAEBB00C5E368 /* SEGState.h */; settings = {ATTRIBUTES = (Private, ); }; }; A352176023AD5825005B07F6 /* SEGMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A352175F23AD5825005B07F6 /* SEGMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A3BECDD024BCE1E3009E2BD3 /* ObjcUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = A3BECDCF24BCE1E3009E2BD3 /* ObjcUtils.m */; }; + A3BECDD324BCFACA009E2BD3 /* ObjcUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = A3BECDCF24BCE1E3009E2BD3 /* ObjcUtils.m */; }; E4ACAD51DB827114D8626C74 /* Pods_AnalyticsTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5238C0454BF56A36A536C5C1 /* Pods_AnalyticsTests.framework */; }; EA88A5981DED7608009FB66A /* SEGSerializableValue.h in Headers */ = {isa = PBXBuildFile; fileRef = EA88A5971DED7608009FB66A /* SEGSerializableValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; EA8F09741E24C5C600B8B93F /* MiddlewareTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA8F09731E24C5C600B8B93F /* MiddlewareTests.swift */; }; @@ -61,7 +67,7 @@ EADEB8C01DECD12B005322DA /* SEGTrackPayload.m in Sources */ = {isa = PBXBuildFile; fileRef = EADEB88B1DECD12B005322DA /* SEGTrackPayload.m */; }; EADEB8C11DECD12B005322DA /* NSData+SEGGZIP.h in Headers */ = {isa = PBXBuildFile; fileRef = EADEB88D1DECD12B005322DA /* NSData+SEGGZIP.h */; settings = {ATTRIBUTES = (Private, ); }; }; EADEB8C21DECD12B005322DA /* NSData+SEGGZIP.m in Sources */ = {isa = PBXBuildFile; fileRef = EADEB88E1DECD12B005322DA /* NSData+SEGGZIP.m */; }; - EADEB8C31DECD12B005322DA /* SEGAnalyticsUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = EADEB88F1DECD12B005322DA /* SEGAnalyticsUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; + EADEB8C31DECD12B005322DA /* SEGAnalyticsUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = EADEB88F1DECD12B005322DA /* SEGAnalyticsUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; EADEB8C41DECD12B005322DA /* SEGAnalyticsUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = EADEB8901DECD12B005322DA /* SEGAnalyticsUtils.m */; }; EADEB8C51DECD12B005322DA /* SEGFileStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = EADEB8911DECD12B005322DA /* SEGFileStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; EADEB8C61DECD12B005322DA /* SEGFileStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = EADEB8921DECD12B005322DA /* SEGFileStorage.m */; }; @@ -125,10 +131,16 @@ 63E090D722DD49C300DEC7EC /* UIViewController+SegScreenTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+SegScreenTest.h"; sourceTree = ""; }; 66058A0DB75544E7C2766C31 /* Pods_AnalyticsTestsTVOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AnalyticsTestsTVOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6E265C781FB1178C0030E08E /* IntegrationsManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationsManagerTest.swift; sourceTree = ""; }; - 6EEC1C702017EA370089C478 /* EndToEndTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndToEndTests.swift; sourceTree = ""; }; + 6EEC1C702017EA370089C478 /* EndToEndTests.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = EndToEndTests.swift; sourceTree = ""; tabWidth = 4; }; + 96A12C2624B680DB00949804 /* NSViewController+SEGScreen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSViewController+SEGScreen.h"; sourceTree = ""; }; + 96A12C2724B680DB00949804 /* NSViewController+SEGScreen.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSViewController+SEGScreen.m"; sourceTree = ""; }; 9D8CE5A723EE014E00197D0C /* AnalyticsTestsTVOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AnalyticsTestsTVOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A31958EE2385AC3A00A47EFA /* SerializationTests.m */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = SerializationTests.m; sourceTree = ""; tabWidth = 4; }; + A34CC6DB249AAEBA00C5E368 /* SEGState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SEGState.m; sourceTree = ""; }; + A34CC6DC249AAEBB00C5E368 /* SEGState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SEGState.h; sourceTree = ""; }; A352175F23AD5825005B07F6 /* SEGMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SEGMacros.h; sourceTree = ""; }; + A3BECDCE24BCE1E3009E2BD3 /* ObjcUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjcUtils.h; sourceTree = ""; }; + A3BECDCF24BCE1E3009E2BD3 /* ObjcUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjcUtils.m; sourceTree = ""; }; B0D1E9E4405FD8386DCCD150 /* Pods-AnalyticsTestsTVOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AnalyticsTestsTVOS.release.xcconfig"; path = "Target Support Files/Pods-AnalyticsTestsTVOS/Pods-AnalyticsTestsTVOS.release.xcconfig"; sourceTree = ""; }; EA88A5971DED7608009FB66A /* SEGSerializableValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SEGSerializableValue.h; sourceTree = ""; }; EA8F09731E24C5C600B8B93F /* MiddlewareTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MiddlewareTests.swift; sourceTree = ""; }; @@ -256,16 +268,6 @@ name = Frameworks; sourceTree = ""; }; - EAA5427A1EB42B8C00945DA7 /* Vendor */ = { - isa = PBXGroup; - children = ( - EAA5427B1EB42B8C00945DA7 /* SEGReachability.h */, - EAA5427C1EB42B8C00945DA7 /* SEGReachability.m */, - ); - name = Vendor; - path = Analytics/Vendor; - sourceTree = SOURCE_ROOT; - }; EADEB8511DECD080005322DA = { isa = PBXGroup; children = ( @@ -292,8 +294,8 @@ isa = PBXGroup; children = ( EADEB8751DECD12B005322DA /* Classes */, - EADEB85E1DECD080005322DA /* Analytics.h */, EADEB85F1DECD080005322DA /* Info.plist */, + EADEB88C1DECD12B005322DA /* Internal */, ); path = Analytics; sourceTree = ""; @@ -321,77 +323,69 @@ 5AF0E8457CCFC077382BF449 /* AutoScreenReportingTest.swift */, 63E090D722DD49C300DEC7EC /* UIViewController+SegScreenTest.h */, ); - indentWidth = 2; + indentWidth = 4; path = AnalyticsTests; sourceTree = ""; - tabWidth = 2; + tabWidth = 4; }; EADEB8751DECD12B005322DA /* Classes */ = { isa = PBXGroup; children = ( - EAA5427A1EB42B8C00945DA7 /* Vendor */, - EADEB8771DECD12B005322DA /* Crypto */, - EADEB87B1DECD12B005322DA /* Integrations */, - EADEB88C1DECD12B005322DA /* Internal */, - EADEB8A41DECD12B005322DA /* Middlewares */, - EA88A5971DED7608009FB66A /* SEGSerializableValue.h */, + EADEB85E1DECD080005322DA /* Analytics.h */, + EADEB87C1DECD12B005322DA /* SEGAliasPayload.h */, + EADEB87D1DECD12B005322DA /* SEGAliasPayload.m */, EADEB8A91DECD12B005322DA /* SEGAnalytics.h */, EADEB8AA1DECD12B005322DA /* SEGAnalytics.m */, EADEB8AB1DECD12B005322DA /* SEGAnalyticsConfiguration.h */, EADEB8AC1DECD12B005322DA /* SEGAnalyticsConfiguration.m */, - ); - path = Classes; - sourceTree = ""; - }; - EADEB8771DECD12B005322DA /* Crypto */ = { - isa = PBXGroup; - children = ( - EADEB8781DECD12B005322DA /* SEGAES256Crypto.h */, - EADEB8791DECD12B005322DA /* SEGAES256Crypto.m */, + EADEB8A51DECD12B005322DA /* SEGContext.h */, + EADEB8A61DECD12B005322DA /* SEGContext.m */, EADEB87A1DECD12B005322DA /* SEGCrypto.h */, - ); - path = Crypto; - sourceTree = ""; - }; - EADEB87B1DECD12B005322DA /* Integrations */ = { - isa = PBXGroup; - children = ( - EADEB87C1DECD12B005322DA /* SEGAliasPayload.h */, - EADEB87D1DECD12B005322DA /* SEGAliasPayload.m */, EADEB87E1DECD12B005322DA /* SEGGroupPayload.h */, EADEB87F1DECD12B005322DA /* SEGGroupPayload.m */, + EADEB8931DECD12B005322DA /* SEGHTTPClient.h */, + EADEB8941DECD12B005322DA /* SEGHTTPClient.m */, EADEB8801DECD12B005322DA /* SEGIdentifyPayload.h */, EADEB8811DECD12B005322DA /* SEGIdentifyPayload.m */, EADEB8821DECD12B005322DA /* SEGIntegration.h */, EADEB8831DECD12B005322DA /* SEGIntegrationFactory.h */, - EADEB8841DECD12B005322DA /* SEGIntegrationsManager.h */, - EADEB8851DECD12B005322DA /* SEGIntegrationsManager.m */, + EADEB8A71DECD12B005322DA /* SEGMiddleware.h */, + EADEB8A81DECD12B005322DA /* SEGMiddleware.m */, EADEB8861DECD12B005322DA /* SEGPayload.h */, EADEB8871DECD12B005322DA /* SEGPayload.m */, + EAA5427B1EB42B8C00945DA7 /* SEGReachability.h */, + EAA5427C1EB42B8C00945DA7 /* SEGReachability.m */, EADEB8881DECD12B005322DA /* SEGScreenPayload.h */, EADEB8891DECD12B005322DA /* SEGScreenPayload.m */, + 5AF0EDFEDC0EE79A0A0EB713 /* SEGScreenReporting.h */, + EADEB8971DECD12B005322DA /* SEGSegmentIntegration.h */, + EADEB8981DECD12B005322DA /* SEGSegmentIntegration.m */, + EADEB8991DECD12B005322DA /* SEGSegmentIntegrationFactory.h */, + EADEB89A1DECD12B005322DA /* SEGSegmentIntegrationFactory.m */, + EA88A5971DED7608009FB66A /* SEGSerializableValue.h */, + EADEB89B1DECD12B005322DA /* SEGStorage.h */, EADEB88A1DECD12B005322DA /* SEGTrackPayload.h */, EADEB88B1DECD12B005322DA /* SEGTrackPayload.m */, + EADEB88F1DECD12B005322DA /* SEGAnalyticsUtils.h */, + EADEB8901DECD12B005322DA /* SEGAnalyticsUtils.m */, ); - path = Integrations; + path = Classes; sourceTree = ""; }; EADEB88C1DECD12B005322DA /* Internal */ = { isa = PBXGroup; children = ( + A34CC6DC249AAEBB00C5E368 /* SEGState.h */, + A34CC6DB249AAEBA00C5E368 /* SEGState.m */, EADEB88D1DECD12B005322DA /* NSData+SEGGZIP.h */, EADEB88E1DECD12B005322DA /* NSData+SEGGZIP.m */, - EADEB88F1DECD12B005322DA /* SEGAnalyticsUtils.h */, - EADEB8901DECD12B005322DA /* SEGAnalyticsUtils.m */, + EADEB8781DECD12B005322DA /* SEGAES256Crypto.h */, + EADEB8791DECD12B005322DA /* SEGAES256Crypto.m */, EADEB8911DECD12B005322DA /* SEGFileStorage.h */, EADEB8921DECD12B005322DA /* SEGFileStorage.m */, - EADEB8931DECD12B005322DA /* SEGHTTPClient.h */, - EADEB8941DECD12B005322DA /* SEGHTTPClient.m */, - EADEB8971DECD12B005322DA /* SEGSegmentIntegration.h */, - EADEB8981DECD12B005322DA /* SEGSegmentIntegration.m */, - EADEB8991DECD12B005322DA /* SEGSegmentIntegrationFactory.h */, - EADEB89A1DECD12B005322DA /* SEGSegmentIntegrationFactory.m */, - EADEB89B1DECD12B005322DA /* SEGStorage.h */, + EADEB8841DECD12B005322DA /* SEGIntegrationsManager.h */, + EADEB8851DECD12B005322DA /* SEGIntegrationsManager.m */, + A352175F23AD5825005B07F6 /* SEGMacros.h */, EADEB89C1DECD12B005322DA /* SEGStoreKitTracker.h */, EADEB89D1DECD12B005322DA /* SEGStoreKitTracker.m */, EADEB89E1DECD12B005322DA /* SEGUserDefaultsStorage.h */, @@ -401,28 +395,20 @@ A352175F23AD5825005B07F6 /* SEGMacros.h */, EADEB8A21DECD12B005322DA /* UIViewController+SEGScreen.h */, EADEB8A31DECD12B005322DA /* UIViewController+SEGScreen.m */, - 5AF0EDFEDC0EE79A0A0EB713 /* SEGScreenReporting.h */, + 96A12C2624B680DB00949804 /* NSViewController+SEGScreen.h */, + 96A12C2724B680DB00949804 /* NSViewController+SEGScreen.m */, ); path = Internal; sourceTree = ""; }; - EADEB8A41DECD12B005322DA /* Middlewares */ = { - isa = PBXGroup; - children = ( - EADEB8A51DECD12B005322DA /* SEGContext.h */, - EADEB8A61DECD12B005322DA /* SEGContext.m */, - EADEB8A71DECD12B005322DA /* SEGMiddleware.h */, - EADEB8A81DECD12B005322DA /* SEGMiddleware.m */, - ); - path = Middlewares; - sourceTree = ""; - }; EADEB8E11DECD335005322DA /* Utils */ = { isa = PBXGroup; children = ( EADEB8E21DECD335005322DA /* NSData+SEGGUNZIPP.h */, EADEB8E31DECD335005322DA /* NSData+SEGGUNZIPP.m */, EADEB8E41DECD335005322DA /* TestUtils.swift */, + A3BECDCE24BCE1E3009E2BD3 /* ObjcUtils.h */, + A3BECDCF24BCE1E3009E2BD3 /* ObjcUtils.m */, ); path = Utils; sourceTree = ""; @@ -444,6 +430,8 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 96A12C2824B680DB00949804 /* NSViewController+SEGScreen.h in Headers */, + A34CC6DE249AAEBB00C5E368 /* SEGState.h in Headers */, EADEB8DC1DECD12B005322DA /* SEGAnalytics.h in Headers */, EADEB8B81DECD12B005322DA /* SEGIntegrationFactory.h in Headers */, EADEB8CB1DECD12B005322DA /* SEGSegmentIntegration.h in Headers */, @@ -489,7 +477,7 @@ 9D8CE58F23EE014E00197D0C /* Sources */, 9D8CE59F23EE014E00197D0C /* Frameworks */, 9D8CE5A223EE014E00197D0C /* Resources */, - D2ED3899A800F2659A9CF6C2 /* [CP] Embed Pods Frameworks */, + F59284A917BD27204F7B1F64 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -527,7 +515,7 @@ EADEB8661DECD0EF005322DA /* Sources */, EADEB8671DECD0EF005322DA /* Frameworks */, EADEB8681DECD0EF005322DA /* Resources */, - 87F85ADB13C707FFFF3F27B0 /* [CP] Embed Pods Frameworks */, + 7B56FD82419D9D8206680C38 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -546,26 +534,31 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0810; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 1130; ORGANIZATIONNAME = Segment; TargetAttributes = { + 9D8CE58B23EE014E00197D0C = { + LastSwiftMigration = 1130; + }; EADEB85A1DECD080005322DA = { CreatedOnToolsVersion = 8.1; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; EADEB8691DECD0EF005322DA = { CreatedOnToolsVersion = 8.1; + LastSwiftMigration = 1150; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = EADEB8551DECD080005322DA /* Build configuration list for PBXProject "Analytics" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( English, en, + Base, ); mainGroup = EADEB8511DECD080005322DA; productRefGroup = EADEB85C1DECD080005322DA /* Products */; @@ -604,28 +597,18 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 87F85ADB13C707FFFF3F27B0 /* [CP] Embed Pods Frameworks */ = { + 7B56FD82419D9D8206680C38 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-AnalyticsTests/Pods-AnalyticsTests-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", - "${BUILT_PRODUCTS_DIR}/Alamofire-Synchronous-iOS/Alamofire_Synchronous.framework", - "${BUILT_PRODUCTS_DIR}/Nimble-iOS/Nimble.framework", "${BUILT_PRODUCTS_DIR}/Nocilla-iOS/Nocilla.framework", - "${BUILT_PRODUCTS_DIR}/Quick-iOS/Quick.framework", - "${BUILT_PRODUCTS_DIR}/SwiftTryCatch-iOS/SwiftTryCatch.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire_Synchronous.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nocilla.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Quick.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftTryCatch.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -655,6 +638,36 @@ showEnvVarsInLog = 0; }; C870F10FB942774C9D2460DD /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-AnalyticsTests/Pods-AnalyticsTests-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", + "${BUILT_PRODUCTS_DIR}/Alamofire-Synchronous-iOS/Alamofire_Synchronous.framework", + "${BUILT_PRODUCTS_DIR}/Nimble-iOS/Nimble.framework", + "${BUILT_PRODUCTS_DIR}/Nocilla-iOS/Nocilla.framework", + "${BUILT_PRODUCTS_DIR}/Quick-iOS/Quick.framework", + "${BUILT_PRODUCTS_DIR}/SwiftTryCatch-iOS/SwiftTryCatch.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire_Synchronous.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nocilla.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Quick.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftTryCatch.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AnalyticsTests/Pods-AnalyticsTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 8DF48941AA6B976CE2A0FC2C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -676,28 +689,18 @@ 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; }; - D2ED3899A800F2659A9CF6C2 /* [CP] Embed Pods Frameworks */ = { + F59284A917BD27204F7B1F64 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-AnalyticsTestsTVOS/Pods-AnalyticsTestsTVOS-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/Alamofire-tvOS/Alamofire.framework", - "${BUILT_PRODUCTS_DIR}/Alamofire-Synchronous-tvOS/Alamofire_Synchronous.framework", - "${BUILT_PRODUCTS_DIR}/Nimble-tvOS/Nimble.framework", "${BUILT_PRODUCTS_DIR}/Nocilla-tvOS/Nocilla.framework", - "${BUILT_PRODUCTS_DIR}/Quick-tvOS/Quick.framework", - "${BUILT_PRODUCTS_DIR}/SwiftTryCatch-tvOS/SwiftTryCatch.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire_Synchronous.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nocilla.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Quick.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftTryCatch.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -718,6 +721,7 @@ 9D8CE59423EE014E00197D0C /* SerializationTests.m in Sources */, 9D8CE59523EE014E00197D0C /* HTTPClientTest.swift in Sources */, 9D8CE59623EE014E00197D0C /* AnalyticsTests.swift in Sources */, + A3BECDD324BCFACA009E2BD3 /* ObjcUtils.m in Sources */, 9D8CE59723EE014E00197D0C /* FileStorageTest.swift in Sources */, 9D8CE59823EE014E00197D0C /* AnalyticsUtilTests.swift in Sources */, 9D8CE59923EE014E00197D0C /* StoreKitTrackerTests.swift in Sources */, @@ -738,6 +742,7 @@ EADEB8BE1DECD12B005322DA /* SEGScreenPayload.m in Sources */, EADEB8B61DECD12B005322DA /* SEGIdentifyPayload.m in Sources */, EADEB8CE1DECD12B005322DA /* SEGSegmentIntegrationFactory.m in Sources */, + 96A12C2924B680DB00949804 /* NSViewController+SEGScreen.m in Sources */, EADEB8C01DECD12B005322DA /* SEGTrackPayload.m in Sources */, EADEB8AF1DECD12B005322DA /* SEGAES256Crypto.m in Sources */, EADEB8C81DECD12B005322DA /* SEGHTTPClient.m in Sources */, @@ -755,6 +760,7 @@ EADEB8D51DECD12B005322DA /* SEGUtils.m in Sources */, EAA5427E1EB42B8C00945DA7 /* SEGReachability.m in Sources */, EADEB8B41DECD12B005322DA /* SEGGroupPayload.m in Sources */, + A34CC6DD249AAEBB00C5E368 /* SEGState.m in Sources */, EADEB8D71DECD12B005322DA /* UIViewController+SEGScreen.m in Sources */, EADEB8D11DECD12B005322DA /* SEGStoreKitTracker.m in Sources */, ); @@ -771,6 +777,7 @@ A31958EF2385AC3A00A47EFA /* SerializationTests.m in Sources */, EADEB8EE1DECD335005322DA /* HTTPClientTest.swift in Sources */, EADEB8F31DECD335005322DA /* AnalyticsTests.swift in Sources */, + A3BECDD024BCE1E3009E2BD3 /* ObjcUtils.m in Sources */, EADEB8F11DECD335005322DA /* FileStorageTest.swift in Sources */, F61EB4AF1F996DEF0038C8C0 /* AnalyticsUtilTests.swift in Sources */, EAA542801EB4382100945DA7 /* StoreKitTrackerTests.swift in Sources */, @@ -834,6 +841,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -843,6 +851,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -850,6 +859,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -893,6 +903,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -902,6 +913,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -909,6 +921,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -949,7 +962,9 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -958,9 +973,11 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.segment.Analytics; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvos appletvsimulator"; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvos appletvsimulator macosx"; TARGETED_DEVICE_FAMILY = "1,2,3"; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -972,7 +989,9 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -981,9 +1000,11 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.segment.Analytics; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvos appletvsimulator"; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvos appletvsimulator macosx"; TARGETED_DEVICE_FAMILY = "1,2,3"; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -1000,6 +1021,7 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OBJC_BRIDGING_HEADER = "AnalyticsTests/AnalyticsTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -1013,6 +1035,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "AnalyticsTests/AnalyticsTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Analytics.xcodeproj/xcshareddata/xcschemes/Analytics.xcscheme b/Analytics.xcodeproj/xcshareddata/xcschemes/Analytics.xcscheme index cce21eeec..f849d5b41 100644 --- a/Analytics.xcodeproj/xcshareddata/xcschemes/Analytics.xcscheme +++ b/Analytics.xcodeproj/xcshareddata/xcschemes/Analytics.xcscheme @@ -1,6 +1,6 @@ +#import //! Project version number for Analytics. FOUNDATION_EXPORT double AnalyticsVersionNumber; @@ -20,3 +20,4 @@ FOUNDATION_EXPORT const unsigned char AnalyticsVersionString[]; #import "SEGContext.h" #import "SEGMiddleware.h" #import "SEGScreenReporting.h" +#import "SEGAnalyticsUtils.h" diff --git a/Analytics/Classes/Integrations/SEGPayload.m b/Analytics/Classes/Integrations/SEGPayload.m deleted file mode 100644 index a56fb9268..000000000 --- a/Analytics/Classes/Integrations/SEGPayload.m +++ /dev/null @@ -1,35 +0,0 @@ -#import "SEGPayload.h" - - -@implementation SEGPayload - -- (instancetype)initWithContext:(NSDictionary *)context integrations:(NSDictionary *)integrations -{ - if (self = [super init]) { - _context = [context copy]; - _integrations = [integrations copy]; - } - return self; -} - -@end - - -@implementation SEGApplicationLifecyclePayload - -@end - - -@implementation SEGRemoteNotificationPayload - -@end - - -@implementation SEGContinueUserActivityPayload - -@end - - -@implementation SEGOpenURLPayload - -@end diff --git a/Analytics/Classes/Internal/SEGUtils.h b/Analytics/Classes/Internal/SEGUtils.h deleted file mode 100644 index 877fbe193..000000000 --- a/Analytics/Classes/Internal/SEGUtils.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// SEGUtils.h -// -// - -#import -#import "SEGAnalyticsUtils.h" - - -@interface SEGUtils : NSObject - -+ (NSData *_Nullable)dataFromPlist:(nonnull id)plist; -+ (id _Nullable)plistFromData:(NSData *_Nonnull)data; - -+ (id _Nullable)traverseJSON:(id _Nullable)object andReplaceWithFilters:(nonnull NSDictionary*)patterns; - -@end diff --git a/Analytics/Classes/Integrations/SEGAliasPayload.h b/Analytics/Classes/SEGAliasPayload.h similarity index 92% rename from Analytics/Classes/Integrations/SEGAliasPayload.h rename to Analytics/Classes/SEGAliasPayload.h index ed26bbaef..9983151af 100644 --- a/Analytics/Classes/Integrations/SEGAliasPayload.h +++ b/Analytics/Classes/SEGAliasPayload.h @@ -3,7 +3,7 @@ NS_ASSUME_NONNULL_BEGIN - +NS_SWIFT_NAME(AliasPayload) @interface SEGAliasPayload : SEGPayload @property (nonatomic, readonly) NSString *theNewId; diff --git a/Analytics/Classes/Integrations/SEGAliasPayload.m b/Analytics/Classes/SEGAliasPayload.m similarity index 100% rename from Analytics/Classes/Integrations/SEGAliasPayload.m rename to Analytics/Classes/SEGAliasPayload.m diff --git a/Analytics/Classes/SEGAnalytics.h b/Analytics/Classes/SEGAnalytics.h index 9bab573f2..1d92e509b 100644 --- a/Analytics/Classes/SEGAnalytics.h +++ b/Analytics/Classes/SEGAnalytics.h @@ -11,13 +11,13 @@ NS_ASSUME_NONNULL_BEGIN */ @class SEGAnalyticsConfiguration; - +NS_SWIFT_NAME(Analytics) @interface SEGAnalytics : NSObject /** * Used by the analytics client to configure various options. */ -@property (nonatomic, strong, readonly) SEGAnalyticsConfiguration *configuration; +@property (nullable, nonatomic, strong, readonly) SEGAnalyticsConfiguration *configuration DEPRECATED_MSG_ATTRIBUTE("One time use object"); /** * Setup this analytics client instance. @@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN * * @see -setupWithConfiguration: */ -+ (instancetype _Nullable)sharedAnalytics; ++ (instancetype)sharedAnalytics; /*! @method @@ -215,9 +215,8 @@ NS_ASSUME_NONNULL_BEGIN /** Returns the anonymous ID of the current user. */ - (NSString *)getAnonymousId; -/** Returns the configuration used to create the analytics client. */ -- (SEGAnalyticsConfiguration *)configuration; - +/** Returns the registered device token of this device */ +- (NSString *)getDeviceToken; @end diff --git a/Analytics/Classes/SEGAnalytics.m b/Analytics/Classes/SEGAnalytics.m index 59be177c1..05cc66dcc 100644 --- a/Analytics/Classes/SEGAnalytics.m +++ b/Analytics/Classes/SEGAnalytics.m @@ -1,11 +1,11 @@ #import -#import #import "SEGAnalyticsUtils.h" #import "SEGAnalytics.h" #import "SEGIntegrationFactory.h" #import "SEGIntegration.h" #import "SEGSegmentIntegrationFactory.h" #import "UIViewController+SEGScreen.h" +#import "NSViewController+SEGScreen.h" #import "SEGStoreKitTracker.h" #import "SEGHTTPClient.h" #import "SEGStorage.h" @@ -14,7 +14,8 @@ #import "SEGMiddleware.h" #import "SEGContext.h" #import "SEGIntegrationsManager.h" -#import "Internal/SEGUtils.h" +#import "SEGState.h" +#import "SEGUtils.h" static SEGAnalytics *__sharedInstance = nil; @@ -22,11 +23,10 @@ @interface SEGAnalytics () @property (nonatomic, assign) BOOL enabled; -@property (nonatomic, strong) SEGAnalyticsConfiguration *configuration; +@property (nonatomic, strong) SEGAnalyticsConfiguration *oneTimeConfiguration; @property (nonatomic, strong) SEGStoreKitTracker *storeKitTracker; @property (nonatomic, strong) SEGIntegrationsManager *integrationsManager; @property (nonatomic, strong) SEGMiddlewareRunner *runner; - @end @@ -45,22 +45,27 @@ - (instancetype)initWithConfiguration:(SEGAnalyticsConfiguration *)configuration NSCParameterAssert(configuration != nil); if (self = [self init]) { - self.configuration = configuration; + self.oneTimeConfiguration = configuration; self.enabled = YES; // In swift this would not have been OK... But hey.. It's objc // TODO: Figure out if this is really the best way to do things here. self.integrationsManager = [[SEGIntegrationsManager alloc] initWithAnalytics:self]; - self.runner = [[SEGMiddlewareRunner alloc] initWithMiddlewares: - [configuration.middlewares ?: @[] arrayByAddingObject:self.integrationsManager]]; + if (configuration.edgeFunctionMiddleware) { + configuration.sourceMiddleware = @[[configuration.edgeFunctionMiddleware sourceMiddleware]]; + configuration.destinationMiddleware = @[[configuration.edgeFunctionMiddleware destinationMiddleware]]; + } - // Attach to application state change hooks - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + self.runner = [[SEGMiddlewareRunner alloc] initWithMiddleware: + [configuration.sourceMiddleware ?: @[] arrayByAddingObject:self.integrationsManager]]; // Pass through for application state change events id application = configuration.application; if (application) { +#if TARGET_OS_IPHONE + // Attach to application state change hooks + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; for (NSString *name in @[ UIApplicationDidEnterBackgroundNotification, UIApplicationDidFinishLaunchingNotification, UIApplicationWillEnterForegroundNotification, @@ -69,23 +74,48 @@ - (instancetype)initWithConfiguration:(SEGAnalyticsConfiguration *)configuration UIApplicationDidBecomeActiveNotification ]) { [nc addObserver:self selector:@selector(handleAppStateNotification:) name:name object:application]; } +#elif TARGET_OS_OSX + // Attach to application state change hooks + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + for (NSString *name in @[ NSApplicationWillUnhideNotification, + NSApplicationDidFinishLaunchingNotification, + NSApplicationWillResignActiveNotification, + NSApplicationDidHideNotification, + NSApplicationDidBecomeActiveNotification, + NSApplicationWillTerminateNotification]) { + [nc addObserver:self selector:@selector(handleAppStateNotification:) name:name object:application]; + } +#endif } +#if TARGET_OS_IPHONE if (configuration.recordScreenViews) { [UIViewController seg_swizzleViewDidAppear]; } +#elif TARGET_OS_OSX + if (configuration.recordScreenViews) { + [NSViewController seg_swizzleViewDidAppear]; + } +#endif if (configuration.trackInAppPurchases) { _storeKitTracker = [SEGStoreKitTracker trackTransactionsForAnalytics:self]; } #if !TARGET_OS_TV if (configuration.trackPushNotifications && configuration.launchOptions) { +#if TARGET_OS_IOS NSDictionary *remoteNotification = configuration.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; +#else + NSDictionary *remoteNotification = configuration.launchOptions[NSApplicationLaunchUserNotificationKey]; +#endif if (remoteNotification) { [self trackPushNotification:remoteNotification fromLaunch:YES]; } } #endif + + [SEGState sharedInstance].configuration = configuration; + [[SEGState sharedInstance].context updateStaticContext]; } return self; } @@ -101,6 +131,7 @@ - (void)dealloc NSString *const SEGBuildKeyV1 = @"SEGBuildKey"; NSString *const SEGBuildKeyV2 = @"SEGBuildKeyV2"; +#if TARGET_OS_IPHONE - (void)handleAppStateNotification:(NSNotification *)note { SEGApplicationLifecyclePayload *payload = [[SEGApplicationLifecyclePayload alloc] init]; @@ -115,10 +146,26 @@ - (void)handleAppStateNotification:(NSNotification *)note [self _applicationDidEnterBackground]; } } +#elif TARGET_OS_OSX +- (void)handleAppStateNotification:(NSNotification *)note +{ + SEGApplicationLifecyclePayload *payload = [[SEGApplicationLifecyclePayload alloc] init]; + payload.notificationName = note.name; + [self run:SEGEventTypeApplicationLifecycle payload:payload]; + + if ([note.name isEqualToString:NSApplicationDidFinishLaunchingNotification]) { + [self _applicationDidFinishLaunchingWithOptions:note.userInfo]; + } else if ([note.name isEqualToString:NSApplicationWillUnhideNotification]) { + [self _applicationWillEnterForeground]; + } else if ([note.name isEqualToString: NSApplicationDidHideNotification]) { + [self _applicationDidEnterBackground]; + } +} +#endif - (void)_applicationDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - if (!self.configuration.trackApplicationLifecycleEvents) { + if (!self.oneTimeConfiguration.trackApplicationLifecycleEvents) { return; } // Previously SEGBuildKey was stored an integer. This was incorrect because the CFBundleVersion @@ -149,6 +196,7 @@ - (void)_applicationDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions }]; } +#if TARGET_OS_IPHONE [self track:@"Application Opened" properties:@{ @"from_background" : @NO, @"version" : currentVersion ?: @"", @@ -156,6 +204,14 @@ - (void)_applicationDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions @"referring_application" : launchOptions[UIApplicationLaunchOptionsSourceApplicationKey] ?: @"", @"url" : launchOptions[UIApplicationLaunchOptionsURLKey] ?: @"", }]; +#elif TARGET_OS_OSX + [self track:@"Application Opened" properties:@{ + @"from_background" : @NO, + @"version" : currentVersion ?: @"", + @"build" : currentBuild ?: @"", + @"default_launch" : launchOptions[NSApplicationLaunchIsDefaultLaunchKey] ?: @(YES), + }]; +#endif [[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:SEGVersionKey]; @@ -166,7 +222,7 @@ - (void)_applicationDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions - (void)_applicationWillEnterForeground { - if (!self.configuration.trackApplicationLifecycleEvents) { + if (!self.oneTimeConfiguration.trackApplicationLifecycleEvents) { return; } NSString *currentVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; @@ -176,6 +232,16 @@ - (void)_applicationWillEnterForeground @"version" : currentVersion ?: @"", @"build" : currentBuild ?: @"", }]; + + [[SEGState sharedInstance].context updateStaticContext]; +} + +- (void)_applicationDidEnterBackground +{ + if (!self.oneTimeConfiguration.trackApplicationLifecycleEvents) { + return; + } + [self track: @"Application Backgrounded"]; } - (void)_applicationDidEnterBackground @@ -194,6 +260,12 @@ - (NSString *)description return [NSString stringWithFormat:@"<%p:%@, %@>", self, [self class], [self dictionaryWithValuesForKeys:@[ @"configuration" ]]]; } +- (nullable SEGAnalyticsConfiguration *)configuration +{ + // Remove deprecated configuration on 4.2+ + return nil; +} + #pragma mark - Identify - (void)identify:(NSString *)userId @@ -209,7 +281,6 @@ - (void)identify:(NSString *)userId traits:(NSDictionary *)traits - (void)identify:(NSString *)userId traits:(NSDictionary *)traits options:(NSDictionary *)options { NSCAssert2(userId.length > 0 || traits.count > 0, @"either userId (%@) or traits (%@) must be provided.", userId, traits); - // this is done here to match functionality on android where these are inserted BEFORE being spread out amongst destinations. // it will be set globally later when it runs through SEGIntegrationManager.identify. NSString *anonId = [options objectForKey:@"anonymousId"]; @@ -217,16 +288,28 @@ - (void)identify:(NSString *)userId traits:(NSDictionary *)traits options:(NSDic anonId = [self getAnonymousId]; } // configure traits to match what is seen on android. - NSMutableDictionary *newTraits = [traits mutableCopy]; - newTraits[@"anonymousId"] = anonId; + NSMutableDictionary *existingTraitsCopy = [[SEGState sharedInstance].userInfo.traits mutableCopy]; + NSMutableDictionary *traitsCopy = [traits mutableCopy]; + // if no traits were passed in, need to create. + if (existingTraitsCopy == nil) { + existingTraitsCopy = [[NSMutableDictionary alloc] init]; + } + if (traitsCopy == nil) { + traitsCopy = [[NSMutableDictionary alloc] init]; + } + traitsCopy[@"anonymousId"] = anonId; if (userId != nil) { - newTraits[@"userId"] = userId; + traitsCopy[@"userId"] = userId; + [SEGState sharedInstance].userInfo.userId = userId; } - + // merge w/ existing traits and set them. + [existingTraitsCopy addEntriesFromDictionary:traits]; + [SEGState sharedInstance].userInfo.traits = existingTraitsCopy; + [self run:SEGEventTypeIdentify payload: [[SEGIdentifyPayload alloc] initWithUserId:userId anonymousId:anonId - traits:SEGCoerceDictionary(newTraits) + traits:SEGCoerceDictionary(existingTraitsCopy) context:SEGCoerceDictionary([options objectForKey:@"context"]) integrations:[options objectForKey:@"integrations"]]]; } @@ -323,7 +406,7 @@ - (void)trackPushNotification:(NSDictionary *)properties fromLaunch:(BOOL)launch - (void)receivedRemoteNotification:(NSDictionary *)userInfo { - if (self.configuration.trackPushNotifications) { + if (self.oneTimeConfiguration.trackPushNotifications) { [self trackPushNotification:userInfo fromLaunch:NO]; } SEGRemoteNotificationPayload *payload = [[SEGRemoteNotificationPayload alloc] init]; @@ -343,6 +426,7 @@ - (void)registeredForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken NSParameterAssert(deviceToken != nil); SEGRemoteNotificationPayload *payload = [[SEGRemoteNotificationPayload alloc] init]; payload.deviceToken = deviceToken; + [SEGState sharedInstance].context.deviceToken = deviceTokenToString(deviceToken); [self run:SEGEventTypeRegisteredForRemoteNotifications payload:payload]; } @@ -360,17 +444,22 @@ - (void)continueUserActivity:(NSUserActivity *)activity payload.activity = activity; [self run:SEGEventTypeContinueUserActivity payload:payload]; - if (!self.configuration.trackDeepLinks) { + if (!self.oneTimeConfiguration.trackDeepLinks) { return; } if ([activity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { + NSString *urlString = activity.webpageURL.absoluteString; + [SEGState sharedInstance].context.referrer = @{ + @"url" : urlString, + }; + NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:activity.userInfo.count + 2]; [properties addEntriesFromDictionary:activity.userInfo]; - properties[@"url"] = activity.webpageURL.absoluteString; + properties[@"url"] = urlString; properties[@"title"] = activity.title ?: @""; properties = [SEGUtils traverseJSON:properties - andReplaceWithFilters:self.configuration.payloadFilters]; + andReplaceWithFilters:self.oneTimeConfiguration.payloadFilters]; [self track:@"Deep Link Opened" properties:[properties copy]]; } } @@ -379,19 +468,24 @@ - (void)openURL:(NSURL *)url options:(NSDictionary *)options { SEGOpenURLPayload *payload = [[SEGOpenURLPayload alloc] init]; payload.url = [NSURL URLWithString:[SEGUtils traverseJSON:url.absoluteString - andReplaceWithFilters:self.configuration.payloadFilters]]; + andReplaceWithFilters:self.oneTimeConfiguration.payloadFilters]]; payload.options = options; [self run:SEGEventTypeOpenURL payload:payload]; - if (!self.configuration.trackDeepLinks) { + if (!self.oneTimeConfiguration.trackDeepLinks) { return; } + NSString *urlString = url.absoluteString; + [SEGState sharedInstance].context.referrer = @{ + @"url" : urlString, + }; + NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:options.count + 2]; [properties addEntriesFromDictionary:options]; - properties[@"url"] = url.absoluteString; + properties[@"url"] = urlString; properties = [SEGUtils traverseJSON:properties - andReplaceWithFilters:self.configuration.payloadFilters]; + andReplaceWithFilters:self.oneTimeConfiguration.payloadFilters]; [self track:@"Deep Link Opened" properties:[properties copy]]; } @@ -417,7 +511,12 @@ - (void)disable - (NSString *)getAnonymousId { - return [self.integrationsManager getAnonymousId]; + return [SEGState sharedInstance].userInfo.anonymousId; +} + +- (NSString *)getDeviceToken +{ + return [SEGState sharedInstance].context.deviceToken; } - (NSDictionary *)bundledIntegrations @@ -442,7 +541,7 @@ + (NSString *)version { // this has to match the actual version, NOT what's in info.plist // because Apple only accepts X.X.X as versions in the review process. - return @"3.9.0"; + return @"4.0.5"; } #pragma mark - Helpers @@ -452,8 +551,8 @@ - (void)run:(SEGEventType)eventType payload:(SEGPayload *)payload if (!self.enabled) { return; } - - if (self.configuration.experimental.nanosecondTimestamps) { + + if (self.oneTimeConfiguration.experimental.nanosecondTimestamps) { payload.timestamp = iso8601NanoFormattedString([NSDate date]); } else { payload.timestamp = iso8601FormattedString([NSDate date]); @@ -461,7 +560,15 @@ - (void)run:(SEGEventType)eventType payload:(SEGPayload *)payload SEGContext *context = [[[SEGContext alloc] initWithAnalytics:self] modify:^(id _Nonnull ctx) { ctx.eventType = eventType; ctx.payload = payload; + ctx.payload.messageId = GenerateUUIDString(); + if (ctx.payload.userId == nil) { + ctx.payload.userId = [SEGState sharedInstance].userInfo.userId; + } + if (ctx.payload.anonymousId == nil) { + ctx.payload.anonymousId = [SEGState sharedInstance].userInfo.anonymousId; + } }]; + // Could probably do more things with callback later, but we don't use it yet. [self.runner run:context callback:nil]; } diff --git a/Analytics/Classes/SEGAnalyticsConfiguration.h b/Analytics/Classes/SEGAnalyticsConfiguration.h index 8f3386181..a45622fe9 100644 --- a/Analytics/Classes/SEGAnalyticsConfiguration.h +++ b/Analytics/Classes/SEGAnalyticsConfiguration.h @@ -7,29 +7,51 @@ // #import + +#if TARGET_OS_IPHONE #import +#elif TARGET_OS_OSX +#import +#endif +NS_SWIFT_NAME(ApplicationProtocol) @protocol SEGApplicationProtocol + +#if TARGET_OS_IPHONE @property (nullable, nonatomic, assign) id delegate; -- (UIBackgroundTaskIdentifier)seg_beginBackgroundTaskWithName:(nullable NSString *)taskName expirationHandler:(void (^__nullable)(void))handler; -- (void)seg_endBackgroundTask:(UIBackgroundTaskIdentifier)identifier; +- (NSUInteger)seg_beginBackgroundTaskWithName:(nullable NSString *)taskName expirationHandler:(void (^__nullable)(void))handler; +- (void)seg_endBackgroundTask:(NSUInteger)identifier; +#elif TARGET_OS_OSX +@property (nullable, nonatomic, assign) id delegate; +#endif @end - +#if TARGET_OS_IOS @interface UIApplication (SEGApplicationProtocol) @end +#elif TARGET_OS_OSX +@interface NSApplication (SEGApplicationProtocol) +@end +#endif + typedef NSMutableURLRequest *_Nonnull (^SEGRequestFactory)(NSURL *_Nonnull); +typedef NSString *_Nonnull (^SEGAdSupportBlock)(void); @protocol SEGIntegrationFactory; @protocol SEGCrypto; @protocol SEGMiddleware; +@protocol SEGEdgeFunctionMiddleware; + +@class SEGAnalyticsExperimental; +@class SEGDestinationMiddleware; @class SEGAnalyticsExperimental; /** * This object provides a set of properties to control various policies of the analytics client. Other than `writeKey`, these properties can be changed at any time. */ +NS_SWIFT_NAME(AnalyticsConfiguration) @interface SEGAnalyticsConfiguration : NSObject /** @@ -135,9 +157,26 @@ typedef NSMutableURLRequest *_Nonnull (^SEGRequestFactory)(NSURL *_Nonnull); @property (nonatomic, strong, nullable) NSDictionary *defaultSettings; /** - * Set custom middlewares. Will be run before all integrations + * Set custom middlewares. Will be run before all integrations. + * This property is deprecated in favor of the `sourceMiddleware` property. + */ +@property (nonatomic, strong, nullable) NSArray> *middlewares DEPRECATED_MSG_ATTRIBUTE("Use .sourceMiddleware instead."); + +/** + * Set custom source middleware. Will be run before all integrations + */ +@property (nonatomic, strong, nullable) NSArray> *sourceMiddleware; + +/** + * Set custom destination middleware. Will be run before the associated integration for a destination. + */ +@property (nonatomic, strong, nullable) NSArray *destinationMiddleware; + +/** + * Sets edge function middleware. This takes precendence over native middlewares. Any middleware set via `sourceMiddleware` + * or `destinationMiddleware` will be removed. */ -@property (nonatomic, strong, nullable) NSArray> *middlewares; +@property (nonatomic, strong, nullable) id edgeFunctionMiddleware; /** * Register a factory that can be used to create an integration. @@ -180,6 +219,18 @@ typedef NSMutableURLRequest *_Nonnull (^SEGRequestFactory)(NSURL *_Nonnull); */ @property (nonatomic, strong, nullable) id httpSessionDelegate; +/** + * Sets a block to be called when IDFA / AdSupport identifier is created. + * This is to allow for apps that do not want ad tracking to pass App Store guidelines in certain categories while + * still allowing apps that do ad tracking to continue to function. + * + * Example: + * configuration.adSupportBlock = ^{ + * return [[ASIdentifierManager sharedManager] advertisingIdentifier]; + * } + */ +@property (nonatomic, strong, nullable) SEGAdSupportBlock adSupportBlock; + /** Enable experimental features within the Segment Analytics-iOS library. */ @@ -187,7 +238,11 @@ typedef NSMutableURLRequest *_Nonnull (^SEGRequestFactory)(NSURL *_Nonnull); @end +#pragma mark - Experimental + +typedef NSDictionary * _Nonnull (^SEGRawModificationBlock)( NSDictionary * _Nonnull rawPayload); +NS_SWIFT_NAME(AnalyticsExperimental) @interface SEGAnalyticsExperimental : NSObject /** Experimental support for nanosecond timestamps. While the segment pipeline doesn't support this yet @@ -199,4 +254,12 @@ typedef NSMutableURLRequest *_Nonnull (^SEGRequestFactory)(NSURL *_Nonnull); received. */ @property (nonatomic, assign) BOOL nanosecondTimestamps; +/** + Experimental support for transformation of raw dictionaries prior to being sent to segment. + This should generally NOT be used, but is a current stop-gap measure for some customers who need to filter + payload data prior to being received by segment.com. This property will go away in future versions when context + object data is made available earlier in the event pipeline. + */ +@property (nonatomic, strong, nullable) SEGRawModificationBlock rawSegmentModificationBlock; + @end diff --git a/Analytics/Classes/SEGAnalyticsConfiguration.m b/Analytics/Classes/SEGAnalyticsConfiguration.m index b8b79806c..cd7fe0d60 100644 --- a/Analytics/Classes/SEGAnalyticsConfiguration.m +++ b/Analytics/Classes/SEGAnalyticsConfiguration.m @@ -7,9 +7,15 @@ // #import "SEGAnalyticsConfiguration.h" +#import "SEGAnalytics.h" #import "SEGCrypto.h" +#if TARGET_OS_IPHONE +#import +#elif TARGET_OS_OSX +#import +#endif - +#if TARGET_OS_IPHONE @implementation UIApplication (SEGApplicationProtocol) - (UIBackgroundTaskIdentifier)seg_beginBackgroundTaskWithName:(nullable NSString *)taskName expirationHandler:(void (^__nullable)(void))handler @@ -23,11 +29,11 @@ - (void)seg_endBackgroundTask:(UIBackgroundTaskIdentifier)identifier } @end +#endif @implementation SEGAnalyticsExperimental @end - @interface SEGAnalyticsConfiguration () @property (nonatomic, copy, readwrite) NSString *writeKey; @@ -66,10 +72,15 @@ - (instancetype)init @"(fb\\d+://authorize#access_token=)([^ ]+)": @"$1((redacted/fb-auth-token))" }; _factories = [NSMutableArray array]; - Class applicationClass = NSClassFromString(@"UIApplication"); - if (applicationClass) { - _application = [applicationClass performSelector:@selector(sharedApplication)]; +#if TARGET_OS_IPHONE + if ([UIApplication respondsToSelector:@selector(sharedApplication)]) { + _application = [UIApplication performSelector:@selector(sharedApplication)]; + } +#elif TARGET_OS_OSX + if ([NSApplication respondsToSelector:@selector(sharedApplication)]) { + _application = [NSApplication performSelector:@selector(sharedApplication)]; } +#endif } return self; } @@ -84,4 +95,16 @@ - (NSString *)description return [NSString stringWithFormat:@"<%p:%@, %@>", self, self.class, [self dictionaryWithValuesForKeys:@[ @"writeKey", @"shouldUseLocationServices", @"flushAt" ]]]; } +// MARK: remove these when `middlewares` property is removed. + +- (void)setMiddlewares:(NSArray> *)middlewares +{ + self.sourceMiddleware = middlewares; +} + +- (NSArray> *)middlewares +{ + return self.sourceMiddleware; +} + @end diff --git a/Analytics/Classes/SEGAnalyticsUtils.h b/Analytics/Classes/SEGAnalyticsUtils.h new file mode 100644 index 000000000..a2b8b0675 --- /dev/null +++ b/Analytics/Classes/SEGAnalyticsUtils.h @@ -0,0 +1,10 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +// Logging + +void SEGSetShowDebugLogs(BOOL showDebugLogs); +void SEGLog(NSString *format, ...); + +NS_ASSUME_NONNULL_END diff --git a/Analytics/Classes/SEGAnalyticsUtils.m b/Analytics/Classes/SEGAnalyticsUtils.m new file mode 100644 index 000000000..5cd36ef92 --- /dev/null +++ b/Analytics/Classes/SEGAnalyticsUtils.m @@ -0,0 +1,23 @@ +#import "SEGAnalyticsUtils.h" +#import "SEGAnalytics.h" + +static BOOL kAnalyticsLoggerShowLogs = NO; + +// Logging + +void SEGSetShowDebugLogs(BOOL showDebugLogs) +{ + kAnalyticsLoggerShowLogs = showDebugLogs; +} + +void SEGLog(NSString *format, ...) +{ + if (!kAnalyticsLoggerShowLogs) + return; + + va_list args; + va_start(args, format); + NSLogv(format, args); + va_end(args); +} + diff --git a/Analytics/Classes/Middlewares/SEGContext.h b/Analytics/Classes/SEGContext.h similarity index 90% rename from Analytics/Classes/Middlewares/SEGContext.h rename to Analytics/Classes/SEGContext.h index 30ac8353c..48af05526 100644 --- a/Analytics/Classes/Middlewares/SEGContext.h +++ b/Analytics/Classes/SEGContext.h @@ -42,12 +42,13 @@ typedef NS_ENUM(NSInteger, SEGEventType) { SEGEventTypeContinueUserActivity, SEGEventTypeOpenURL, -}; +} NS_SWIFT_NAME(EventType); @class SEGAnalytics; @protocol SEGMutableContext; +NS_SWIFT_NAME(Context) @interface SEGContext : NSObject // Loopback reference to the top level SEGAnalytics object. @@ -58,8 +59,6 @@ typedef NS_ENUM(NSInteger, SEGEventType) { @property (nonatomic, readonly, nonnull) SEGAnalytics *_analytics; @property (nonatomic, readonly) SEGEventType eventType; -@property (nonatomic, readonly, nullable) NSString *userId; -@property (nonatomic, readonly, nullable) NSString *anonymousId; @property (nonatomic, readonly, nullable) NSError *error; @property (nonatomic, readonly, nullable) SEGPayload *payload; @property (nonatomic, readonly) BOOL debug; @@ -73,8 +72,6 @@ typedef NS_ENUM(NSInteger, SEGEventType) { @protocol SEGMutableContext @property (nonatomic) SEGEventType eventType; -@property (nonatomic, nullable) NSString *userId; -@property (nonatomic, nullable) NSString *anonymousId; @property (nonatomic, nullable) SEGPayload *payload; @property (nonatomic, nullable) NSError *error; @property (nonatomic) BOOL debug; diff --git a/Analytics/Classes/Middlewares/SEGContext.m b/Analytics/Classes/SEGContext.m similarity index 95% rename from Analytics/Classes/Middlewares/SEGContext.m rename to Analytics/Classes/SEGContext.m index 71eec8c29..292883be7 100644 --- a/Analytics/Classes/Middlewares/SEGContext.m +++ b/Analytics/Classes/SEGContext.m @@ -25,7 +25,7 @@ @implementation SEGContext - (instancetype)init { - @throw [NSException exceptionWithName:@"Bad Initization" + @throw [NSException exceptionWithName:@"Bad Initialization" reason:@"Please use initWithAnalytics:" userInfo:nil]; } @@ -73,8 +73,6 @@ - (id)copyWithZone:(NSZone *)zone { SEGContext *ctx = [[SEGContext allocWithZone:zone] initWithAnalytics:self._analytics]; ctx.eventType = self.eventType; - ctx.userId = self.userId; - ctx.anonymousId = self.anonymousId; ctx.payload = self.payload; ctx.error = self.error; ctx.debug = self.debug; diff --git a/Analytics/Classes/Crypto/SEGCrypto.h b/Analytics/Classes/SEGCrypto.h similarity index 100% rename from Analytics/Classes/Crypto/SEGCrypto.h rename to Analytics/Classes/SEGCrypto.h diff --git a/Analytics/Classes/Integrations/SEGGroupPayload.h b/Analytics/Classes/SEGGroupPayload.h similarity index 94% rename from Analytics/Classes/Integrations/SEGGroupPayload.h rename to Analytics/Classes/SEGGroupPayload.h index 109e22543..2c823aa0d 100644 --- a/Analytics/Classes/Integrations/SEGGroupPayload.h +++ b/Analytics/Classes/SEGGroupPayload.h @@ -3,7 +3,7 @@ NS_ASSUME_NONNULL_BEGIN - +NS_SWIFT_NAME(GroupPayload) @interface SEGGroupPayload : SEGPayload @property (nonatomic, readonly) NSString *groupId; diff --git a/Analytics/Classes/Integrations/SEGGroupPayload.m b/Analytics/Classes/SEGGroupPayload.m similarity index 100% rename from Analytics/Classes/Integrations/SEGGroupPayload.m rename to Analytics/Classes/SEGGroupPayload.m diff --git a/Analytics/Classes/Internal/SEGHTTPClient.h b/Analytics/Classes/SEGHTTPClient.h similarity index 98% rename from Analytics/Classes/Internal/SEGHTTPClient.h rename to Analytics/Classes/SEGHTTPClient.h index 59a6897cd..ec8867e90 100644 --- a/Analytics/Classes/Internal/SEGHTTPClient.h +++ b/Analytics/Classes/SEGHTTPClient.h @@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN +NS_SWIFT_NAME(HTTPClient) @interface SEGHTTPClient : NSObject @property (nonatomic, strong) SEGRequestFactory requestFactory; diff --git a/Analytics/Classes/Internal/SEGHTTPClient.m b/Analytics/Classes/SEGHTTPClient.m similarity index 100% rename from Analytics/Classes/Internal/SEGHTTPClient.m rename to Analytics/Classes/SEGHTTPClient.m diff --git a/Analytics/Classes/Integrations/SEGIdentifyPayload.h b/Analytics/Classes/SEGIdentifyPayload.h similarity index 79% rename from Analytics/Classes/Integrations/SEGIdentifyPayload.h rename to Analytics/Classes/SEGIdentifyPayload.h index 84eab05d6..b4bf3355c 100644 --- a/Analytics/Classes/Integrations/SEGIdentifyPayload.h +++ b/Analytics/Classes/SEGIdentifyPayload.h @@ -3,13 +3,9 @@ NS_ASSUME_NONNULL_BEGIN - +NS_SWIFT_NAME(IdentifyPayload) @interface SEGIdentifyPayload : SEGPayload -@property (nonatomic, readonly, nullable) NSString *userId; - -@property (nonatomic, readonly, nullable) NSString *anonymousId; - @property (nonatomic, readonly, nullable) JSON_DICT traits; - (instancetype)initWithUserId:(NSString *)userId diff --git a/Analytics/Classes/Integrations/SEGIdentifyPayload.m b/Analytics/Classes/SEGIdentifyPayload.m similarity index 72% rename from Analytics/Classes/Integrations/SEGIdentifyPayload.m rename to Analytics/Classes/SEGIdentifyPayload.m index 40862b3ea..418f71f90 100644 --- a/Analytics/Classes/Integrations/SEGIdentifyPayload.m +++ b/Analytics/Classes/SEGIdentifyPayload.m @@ -1,9 +1,5 @@ #import "SEGIdentifyPayload.h" -@interface SEGIdentifyPayload () -@property (nonatomic, readwrite, nullable) NSString *anonymousId; -@end - @implementation SEGIdentifyPayload - (instancetype)initWithUserId:(NSString *)userId @@ -13,9 +9,9 @@ - (instancetype)initWithUserId:(NSString *)userId integrations:(NSDictionary *)integrations { if (self = [super initWithContext:context integrations:integrations]) { - _userId = [userId copy]; - _anonymousId = [anonymousId copy]; _traits = [traits copy]; + self.anonymousId = [anonymousId copy]; + self.userId = [userId copy]; } return self; } diff --git a/Analytics/Classes/Integrations/SEGIntegration.h b/Analytics/Classes/SEGIntegration.h similarity index 99% rename from Analytics/Classes/Integrations/SEGIntegration.h rename to Analytics/Classes/SEGIntegration.h index 13c8b00b6..0820aafdd 100644 --- a/Analytics/Classes/Integrations/SEGIntegration.h +++ b/Analytics/Classes/SEGIntegration.h @@ -9,6 +9,7 @@ NS_ASSUME_NONNULL_BEGIN +NS_SWIFT_NAME(Integration) @protocol SEGIntegration @optional diff --git a/Analytics/Classes/Integrations/SEGIntegrationFactory.h b/Analytics/Classes/SEGIntegrationFactory.h similarity index 100% rename from Analytics/Classes/Integrations/SEGIntegrationFactory.h rename to Analytics/Classes/SEGIntegrationFactory.h diff --git a/Analytics/Classes/Internal/SEGMacros.h b/Analytics/Classes/SEGMacros.h similarity index 100% rename from Analytics/Classes/Internal/SEGMacros.h rename to Analytics/Classes/SEGMacros.h diff --git a/Analytics/Classes/Middlewares/SEGMiddleware.h b/Analytics/Classes/SEGMiddleware.h similarity index 64% rename from Analytics/Classes/Middlewares/SEGMiddleware.h rename to Analytics/Classes/SEGMiddleware.h index d35042ce3..be1c61170 100644 --- a/Analytics/Classes/Middlewares/SEGMiddleware.h +++ b/Analytics/Classes/SEGMiddleware.h @@ -11,6 +11,7 @@ typedef void (^SEGMiddlewareNext)(SEGContext *_Nullable newContext); +NS_SWIFT_NAME(Middleware) @protocol SEGMiddleware @required @@ -33,6 +34,7 @@ typedef void (^SEGMiddlewareNext)(SEGContext *_Nullable newContext); typedef void (^SEGMiddlewareBlock)(SEGContext *_Nonnull context, SEGMiddlewareNext _Nonnull next); +NS_SWIFT_NAME(BlockMiddleware) @interface SEGBlockMiddleware : NSObject @property (nonnull, nonatomic, readonly) SEGMiddlewareBlock block; @@ -45,14 +47,32 @@ typedef void (^SEGMiddlewareBlock)(SEGContext *_Nonnull context, SEGMiddlewareNe typedef void (^RunMiddlewaresCallback)(BOOL earlyExit, NSArray> *_Nonnull remainingMiddlewares); // XXX TODO: Add some tests for SEGMiddlewareRunner +NS_SWIFT_NAME(MiddlewareRunner) @interface SEGMiddlewareRunner : NSObject // While it is certainly technically possible to change middlewares dynamically on the fly. we're explicitly NOT // gonna support that for now to keep things simple. If there is a real need later we'll see then. @property (nonnull, nonatomic, readonly) NSArray> *middlewares; -- (void)run:(SEGContext *_Nonnull)context callback:(RunMiddlewaresCallback _Nullable)callback; +- (SEGContext * _Nonnull)run:(SEGContext *_Nonnull)context callback:(RunMiddlewaresCallback _Nullable)callback; -- (instancetype _Nonnull)initWithMiddlewares:(NSArray> *_Nonnull)middlewares; +- (instancetype _Nonnull)initWithMiddleware:(NSArray> *_Nonnull)middlewares; @end + +// Container object for middlewares for a specific destination. +NS_SWIFT_NAME(DestinationMiddleware) +@interface SEGDestinationMiddleware : NSObject +@property (nonatomic, strong, nonnull, readonly) NSString *integrationKey; +@property (nonatomic, strong, nullable, readonly) NSArray> *middleware; +- (instancetype _Nonnull)initWithKey:(NSString * _Nonnull)integrationKey middleware:(NSArray> * _Nonnull)middleware; +@end + +NS_SWIFT_NAME(EdgeFunctionMiddleware) +@protocol SEGEdgeFunctionMiddleware +@required +@property (nonatomic, readonly, nullable) NSArray> *sourceMiddleware; +@property (nonatomic, readonly, nullable) NSArray *destinationMiddleware; +- (void)setEdgeFunctionData:(NSDictionary *_Nullable)data; +@end + diff --git a/Analytics/Classes/Middlewares/SEGMiddleware.m b/Analytics/Classes/SEGMiddleware.m similarity index 55% rename from Analytics/Classes/Middlewares/SEGMiddleware.m rename to Analytics/Classes/SEGMiddleware.m index d5dd998fe..a63b05827 100644 --- a/Analytics/Classes/Middlewares/SEGMiddleware.m +++ b/Analytics/Classes/SEGMiddleware.m @@ -10,6 +10,17 @@ #import "SEGMiddleware.h" +@implementation SEGDestinationMiddleware +- (instancetype)initWithKey:(NSString *)integrationKey middleware:(NSArray> *)middleware +{ + if (self = [super init]) { + _integrationKey = integrationKey; + _middleware = middleware; + } + return self; +} +@end + @implementation SEGBlockMiddleware - (instancetype)initWithBlock:(SEGMiddlewareBlock)block @@ -30,7 +41,7 @@ - (void)context:(SEGContext *)context next:(SEGMiddlewareNext)next @implementation SEGMiddlewareRunner -- (instancetype)initWithMiddlewares:(NSArray> *_Nonnull)middlewares +- (instancetype)initWithMiddleware:(NSArray> *_Nonnull)middlewares { if (self = [super init]) { _middlewares = middlewares; @@ -38,29 +49,33 @@ - (instancetype)initWithMiddlewares:(NSArray> *_Nonnull)middle return self; } -- (void)run:(SEGContext *_Nonnull)context callback:(RunMiddlewaresCallback _Nullable)callback +- (SEGContext *)run:(SEGContext *_Nonnull)context callback:(RunMiddlewaresCallback _Nullable)callback { - [self runMiddlewares:self.middlewares context:context callback:callback]; + return [self runMiddlewares:self.middlewares context:context callback:callback]; } // TODO: Maybe rename SEGContext to SEGEvent to be a bit more clear? // We could also use some sanity check / other types of logging here. -- (void)runMiddlewares:(NSArray> *_Nonnull)middlewares +- (SEGContext *)runMiddlewares:(NSArray> *_Nonnull)middlewares context:(SEGContext *_Nonnull)context callback:(RunMiddlewaresCallback _Nullable)callback { + __block SEGContext * _Nonnull result = context; + BOOL earlyExit = context == nil; if (middlewares.count == 0 || earlyExit) { if (callback) { callback(earlyExit, middlewares); } - return; + return context; } - - [middlewares[0] context:context next:^(SEGContext *_Nullable newContext) { + + [middlewares[0] context:result next:^(SEGContext *_Nullable newContext) { NSArray *remainingMiddlewares = [middlewares subarrayWithRange:NSMakeRange(1, middlewares.count - 1)]; - [self runMiddlewares:remainingMiddlewares context:newContext callback:callback]; + result = [self runMiddlewares:remainingMiddlewares context:newContext callback:callback]; }]; + + return result; } @end diff --git a/Analytics/Classes/Integrations/SEGPayload.h b/Analytics/Classes/SEGPayload.h similarity index 81% rename from Analytics/Classes/Integrations/SEGPayload.h rename to Analytics/Classes/SEGPayload.h index cd4ca09ad..6368cc45f 100644 --- a/Analytics/Classes/Integrations/SEGPayload.h +++ b/Analytics/Classes/SEGPayload.h @@ -3,18 +3,22 @@ NS_ASSUME_NONNULL_BEGIN - +NS_SWIFT_NAME(Payload) @interface SEGPayload : NSObject @property (nonatomic, readonly) JSON_DICT context; @property (nonatomic, readonly) JSON_DICT integrations; @property (nonatomic, strong) NSString *timestamp; +@property (nonatomic, strong) NSString *messageId; +@property (nonatomic, strong) NSString *anonymousId; +@property (nonatomic, strong) NSString *userId; - (instancetype)initWithContext:(JSON_DICT)context integrations:(JSON_DICT)integrations; @end +NS_SWIFT_NAME(ApplicationLifecyclePayload) @interface SEGApplicationLifecyclePayload : SEGPayload @property (nonatomic, strong) NSString *notificationName; @@ -25,13 +29,14 @@ NS_ASSUME_NONNULL_BEGIN @end +NS_SWIFT_NAME(ContinueUserActivityPayload) @interface SEGContinueUserActivityPayload : SEGPayload @property (nonatomic, strong) NSUserActivity *activity; @end - +NS_SWIFT_NAME(OpenURLPayload) @interface SEGOpenURLPayload : SEGPayload @property (nonatomic, strong) NSURL *url; @@ -42,6 +47,7 @@ NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END +NS_SWIFT_NAME(RemoteNotificationPayload) @interface SEGRemoteNotificationPayload : SEGPayload // SEGEventTypeHandleActionWithForRemoteNotification diff --git a/Analytics/Classes/SEGPayload.m b/Analytics/Classes/SEGPayload.m new file mode 100644 index 000000000..6fa9bf64a --- /dev/null +++ b/Analytics/Classes/SEGPayload.m @@ -0,0 +1,44 @@ +#import "SEGPayload.h" +#import "SEGState.h" + +@implementation SEGPayload + +@synthesize userId = _userId; +@synthesize anonymousId = _anonymousId; + +- (instancetype)initWithContext:(NSDictionary *)context integrations:(NSDictionary *)integrations +{ + if (self = [super init]) { + // combine existing state with user supplied context. + NSDictionary *internalContext = [SEGState sharedInstance].context.payload; + + NSMutableDictionary *combinedContext = [[NSMutableDictionary alloc] init]; + [combinedContext addEntriesFromDictionary:internalContext]; + [combinedContext addEntriesFromDictionary:context]; + + _context = [combinedContext copy]; + _integrations = [integrations copy]; + _messageId = nil; + _userId = nil; + _anonymousId = nil; + } + return self; +} + +@end + + +@implementation SEGApplicationLifecyclePayload +@end + + +@implementation SEGRemoteNotificationPayload +@end + + +@implementation SEGContinueUserActivityPayload +@end + + +@implementation SEGOpenURLPayload +@end diff --git a/Analytics/Vendor/SEGReachability.h b/Analytics/Classes/SEGReachability.h similarity index 99% rename from Analytics/Vendor/SEGReachability.h rename to Analytics/Classes/SEGReachability.h index 3c622ec68..c57da0874 100644 --- a/Analytics/Vendor/SEGReachability.h +++ b/Analytics/Classes/SEGReachability.h @@ -64,6 +64,7 @@ typedef void (^SEGNetworkReachable)(SEGReachability *reachability); typedef void (^SEGNetworkUnreachable)(SEGReachability *reachability); +NS_SWIFT_NAME(SEGReachability) @interface SEGReachability : NSObject @property (nonatomic, copy, nullable) SEGNetworkReachable reachableBlock; diff --git a/Analytics/Vendor/SEGReachability.m b/Analytics/Classes/SEGReachability.m similarity index 100% rename from Analytics/Vendor/SEGReachability.m rename to Analytics/Classes/SEGReachability.m diff --git a/Analytics/Classes/Integrations/SEGScreenPayload.h b/Analytics/Classes/SEGScreenPayload.h similarity index 95% rename from Analytics/Classes/Integrations/SEGScreenPayload.h rename to Analytics/Classes/SEGScreenPayload.h index 78e6639cd..b9bce04a3 100644 --- a/Analytics/Classes/Integrations/SEGScreenPayload.h +++ b/Analytics/Classes/SEGScreenPayload.h @@ -4,6 +4,7 @@ NS_ASSUME_NONNULL_BEGIN +NS_SWIFT_NAME(ScreenPayload) @interface SEGScreenPayload : SEGPayload @property (nonatomic, readonly) NSString *name; diff --git a/Analytics/Classes/Integrations/SEGScreenPayload.m b/Analytics/Classes/SEGScreenPayload.m similarity index 100% rename from Analytics/Classes/Integrations/SEGScreenPayload.m rename to Analytics/Classes/SEGScreenPayload.m diff --git a/Analytics/Classes/Internal/SEGScreenReporting.h b/Analytics/Classes/SEGScreenReporting.h similarity index 100% rename from Analytics/Classes/Internal/SEGScreenReporting.h rename to Analytics/Classes/SEGScreenReporting.h diff --git a/Analytics/Classes/Internal/SEGSegmentIntegration.h b/Analytics/Classes/SEGSegmentIntegration.h similarity index 95% rename from Analytics/Classes/Internal/SEGSegmentIntegration.h rename to Analytics/Classes/SEGSegmentIntegration.h index c32e01d70..3dacd3557 100644 --- a/Analytics/Classes/Internal/SEGSegmentIntegration.h +++ b/Analytics/Classes/SEGSegmentIntegration.h @@ -17,6 +17,7 @@ extern NSString *const kSEGQueueFilename; extern NSString *const kSEGTraitsFilename; +NS_SWIFT_NAME(SegmentIntegration) @interface SEGSegmentIntegration : NSObject - (id)initWithAnalytics:(SEGAnalytics *)analytics httpClient:(SEGHTTPClient *)httpClient fileStorage:(id)fileStorage userDefaultsStorage:(id)userDefaultsStorage; diff --git a/Analytics/Classes/Internal/SEGSegmentIntegration.m b/Analytics/Classes/SEGSegmentIntegration.m similarity index 60% rename from Analytics/Classes/Internal/SEGSegmentIntegration.m rename to Analytics/Classes/SEGSegmentIntegration.m index 05cfaa462..4a62cb752 100644 --- a/Analytics/Classes/Internal/SEGSegmentIntegration.m +++ b/Analytics/Classes/SEGSegmentIntegration.m @@ -1,13 +1,17 @@ #include -#import #import "SEGAnalytics.h" -#import "SEGAnalyticsUtils.h" +#import "SEGUtils.h" #import "SEGSegmentIntegration.h" #import "SEGReachability.h" #import "SEGHTTPClient.h" #import "SEGStorage.h" #import "SEGMacros.h" +#import "SEGState.h" + +#if TARGET_OS_IPHONE +#import +#endif #if TARGET_OS_IOS #import @@ -18,9 +22,6 @@ NSString *const SEGSegmentRequestDidSucceedNotification = @"SegmentRequestDidSucceed"; NSString *const SEGSegmentRequestDidFailNotification = @"SegmentRequestDidFail"; -NSString *const SEGAdvertisingClassIdentifier = @"ASIdentifierManager"; -NSString *const SEGADClientClass = @"ADClient"; - NSString *const SEGUserIdKey = @"SEGUserId"; NSString *const SEGQueueKey = @"SEGQueue"; NSString *const SEGTraitsKey = @"SEGTraits"; @@ -29,39 +30,15 @@ NSString *const kSEGQueueFilename = @"segmentio.queue.plist"; NSString *const kSEGTraitsFilename = @"segmentio.traits.plist"; -static NSString *GetDeviceModel() -{ - size_t size; - sysctlbyname("hw.machine", NULL, &size, NULL, 0); - char result[size]; - sysctlbyname("hw.machine", result, &size, NULL, 0); - NSString *results = [NSString stringWithCString:result encoding:NSUTF8StringEncoding]; - return results; -} - -static BOOL GetAdTrackingEnabled() -{ - BOOL result = NO; - Class advertisingManager = NSClassFromString(SEGAdvertisingClassIdentifier); - SEL sharedManagerSelector = NSSelectorFromString(@"sharedManager"); - id sharedManager = ((id (*)(id, SEL))[advertisingManager methodForSelector:sharedManagerSelector])(advertisingManager, sharedManagerSelector); - SEL adTrackingEnabledSEL = NSSelectorFromString(@"isAdvertisingTrackingEnabled"); - result = ((BOOL (*)(id, SEL))[sharedManager methodForSelector:adTrackingEnabledSEL])(sharedManager, adTrackingEnabledSEL); - return result; -} - - @interface SEGSegmentIntegration () @property (nonatomic, strong) NSMutableArray *queue; -@property (nonatomic, strong) NSDictionary *_cachedStaticContext; @property (nonatomic, strong) NSURLSessionUploadTask *batchRequest; -@property (nonatomic, assign) UIBackgroundTaskIdentifier flushTaskID; @property (nonatomic, strong) SEGReachability *reachability; @property (nonatomic, strong) NSTimer *flushTimer; @property (nonatomic, strong) dispatch_queue_t serialQueue; @property (nonatomic, strong) dispatch_queue_t backgroundTaskQueue; -@property (nonatomic, strong) NSMutableDictionary *traits; +@property (nonatomic, strong) NSDictionary *traits; @property (nonatomic, assign) SEGAnalytics *analytics; @property (nonatomic, assign) SEGAnalyticsConfiguration *configuration; @property (atomic, copy) NSDictionary *referrer; @@ -72,8 +49,15 @@ @interface SEGSegmentIntegration () @property (nonatomic, strong) id userDefaultsStorage; @property (nonatomic, strong) NSURLSessionDataTask *attributionRequest; +#if TARGET_OS_IPHONE +@property (nonatomic, assign) UIBackgroundTaskIdentifier flushTaskID; +#endif + @end +@interface SEGAnalytics () +@property (nonatomic, strong, readonly) SEGAnalyticsConfiguration *oneTimeConfiguration; +@end @implementation SEGSegmentIntegration @@ -81,19 +65,23 @@ - (id)initWithAnalytics:(SEGAnalytics *)analytics httpClient:(SEGHTTPClient *)ht { if (self = [super init]) { self.analytics = analytics; - self.configuration = analytics.configuration; + self.configuration = analytics.oneTimeConfiguration; self.httpClient = httpClient; - self.httpClient.httpSessionDelegate = analytics.configuration.httpSessionDelegate; + self.httpClient.httpSessionDelegate = analytics.oneTimeConfiguration.httpSessionDelegate; self.fileStorage = fileStorage; self.userDefaultsStorage = userDefaultsStorage; self.apiURL = [SEGMENT_API_BASE URLByAppendingPathComponent:@"import"]; - self.userId = [self getUserId]; self.reachability = [SEGReachability reachabilityWithHostname:@"google.com"]; [self.reachability startNotifier]; - self.cachedStaticContext = [self staticContext]; self.serialQueue = seg_dispatch_queue_create_specific("io.segment.analytics.segmentio", DISPATCH_QUEUE_SERIAL); self.backgroundTaskQueue = seg_dispatch_queue_create_specific("io.segment.analytics.backgroundTask", DISPATCH_QUEUE_SERIAL); +#if TARGET_OS_IPHONE self.flushTaskID = UIBackgroundTaskInvalid; +#endif + + // load traits & user from disk. + [self loadUserId]; + [self loadTraits]; [self dispatchBackground:^{ // Check for previous queue data in NSUserDefaults and remove if present. @@ -119,169 +107,10 @@ - (id)initWithAnalytics:(SEGAnalytics *)analytics httpClient:(SEGHTTPClient *)ht [NSRunLoop.mainRunLoop addTimer:self.flushTimer forMode:NSDefaultRunLoopMode]; - - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(updateStaticContext) - name:UIApplicationWillEnterForegroundNotification - object:nil]; } return self; } -/* - * There is an iOS bug that causes instances of the CTTelephonyNetworkInfo class to - * sometimes get notifications after they have been deallocated. - * Instead of instantiating, using, and releasing instances you * must instead retain - * and never release them to work around the bug. - * - * Ref: http://stackoverflow.com/questions/14238586/coretelephony-crash - */ - -#if TARGET_OS_IOS -static CTTelephonyNetworkInfo *_telephonyNetworkInfo; -#endif - -- (NSDictionary *)staticContext -{ - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; - - dict[@"library"] = @{ - @"name" : @"analytics-ios", - @"version" : [SEGAnalytics version] - }; - - NSMutableDictionary *infoDictionary = [[[NSBundle mainBundle] infoDictionary] mutableCopy]; - [infoDictionary addEntriesFromDictionary:[[NSBundle mainBundle] localizedInfoDictionary]]; - if (infoDictionary.count) { - dict[@"app"] = @{ - @"name" : infoDictionary[@"CFBundleDisplayName"] ?: @"", - @"version" : infoDictionary[@"CFBundleShortVersionString"] ?: @"", - @"build" : infoDictionary[@"CFBundleVersion"] ?: @"", - @"namespace" : [[NSBundle mainBundle] bundleIdentifier] ?: @"", - }; - } - - UIDevice *device = [UIDevice currentDevice]; - - dict[@"device"] = ({ - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; - dict[@"manufacturer"] = @"Apple"; - dict[@"type"] = @"ios"; - dict[@"model"] = GetDeviceModel(); - dict[@"id"] = [[device identifierForVendor] UUIDString]; - dict[@"name"] = [device model]; - if (NSClassFromString(SEGAdvertisingClassIdentifier)) { - dict[@"adTrackingEnabled"] = @(GetAdTrackingEnabled()); - } - if (self.configuration.enableAdvertisingTracking) { - NSString *idfa = SEGIDFA(); - if (idfa.length) dict[@"advertisingId"] = idfa; - } - dict; - }); - - dict[@"os"] = @{ - @"name" : device.systemName, - @"version" : device.systemVersion - }; - - CGSize screenSize = [UIScreen mainScreen].bounds.size; - dict[@"screen"] = @{ - @"width" : @(screenSize.width), - @"height" : @(screenSize.height) - }; - -#if !(TARGET_IPHONE_SIMULATOR) - Class adClient = NSClassFromString(SEGADClientClass); - if (adClient) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - id sharedClient = [adClient performSelector:NSSelectorFromString(@"sharedClient")]; -#pragma clang diagnostic pop - void (^completionHandler)(BOOL iad) = ^(BOOL iad) { - if (iad) { - dict[@"referrer"] = @{ @"type" : @"iad" }; - } - }; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - [sharedClient performSelector:NSSelectorFromString(@"determineAppInstallationAttributionWithCompletionHandler:") - withObject:completionHandler]; -#pragma clang diagnostic pop - } -#endif - - return dict; -} - -- (void)updateStaticContext -{ - self.cachedStaticContext = [self staticContext]; -} - -- (NSDictionary *)cachedStaticContext { - __block NSDictionary *result = nil; - weakify(self); - dispatch_sync(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ - strongify(self); - result = self._cachedStaticContext; - }); - return result; -} - -- (void)setCachedStaticContext:(NSDictionary *)cachedStaticContext { - weakify(self); - dispatch_sync(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ - strongify(self); - self._cachedStaticContext = cachedStaticContext; - }); -} - -- (NSDictionary *)liveContext -{ - NSMutableDictionary *context = [[NSMutableDictionary alloc] init]; - context[@"locale"] = [NSString stringWithFormat: - @"%@-%@", - [NSLocale.currentLocale objectForKey:NSLocaleLanguageCode], - [NSLocale.currentLocale objectForKey:NSLocaleCountryCode]]; - - context[@"timezone"] = [[NSTimeZone localTimeZone] name]; - - context[@"network"] = ({ - NSMutableDictionary *network = [[NSMutableDictionary alloc] init]; - - if (self.reachability.isReachable) { - network[@"wifi"] = @(self.reachability.isReachableViaWiFi); - network[@"cellular"] = @(self.reachability.isReachableViaWWAN); - } - -#if TARGET_OS_IOS - static dispatch_once_t networkInfoOnceToken; - dispatch_once(&networkInfoOnceToken, ^{ - _telephonyNetworkInfo = [[CTTelephonyNetworkInfo alloc] init]; - }); - - CTCarrier *carrier = [_telephonyNetworkInfo subscriberCellularProvider]; - if (carrier.carrierName.length) - network[@"carrier"] = carrier.carrierName; -#endif - - network; - }); - - context[@"traits"] = ({ - NSMutableDictionary *traits = [[NSMutableDictionary alloc] initWithDictionary:[self traits]]; - traits; - }); - - if (self.referrer) { - context[@"referrer"] = [self.referrer copy]; - } - - return [context copy]; -} - - (void)dispatchBackground:(void (^)(void))block { seg_dispatch_specific_async(_serialQueue, block); @@ -292,13 +121,15 @@ - (void)dispatchBackgroundAndWait:(void (^)(void))block seg_dispatch_specific_sync(_serialQueue, block); } +#if TARGET_OS_IPHONE - (void)beginBackgroundTask { [self endBackgroundTask]; seg_dispatch_specific_sync(_backgroundTaskQueue, ^{ - id application = [self.analytics configuration].application; - if (application) { + + id application = [self.analytics oneTimeConfiguration].application; + if (application && [application respondsToSelector:@selector(seg_beginBackgroundTaskWithName:expirationHandler:)]) { self.flushTaskID = [application seg_beginBackgroundTaskWithName:@"Segmentio.Flush" expirationHandler:^{ [self endBackgroundTask]; @@ -316,8 +147,8 @@ - (void)endBackgroundTask // See https://github.com/segmentio/analytics-ios/issues/683 seg_dispatch_specific_sync(_backgroundTaskQueue, ^{ if (self.flushTaskID != UIBackgroundTaskInvalid) { - id application = [self.analytics configuration].application; - if (application) { + id application = [self.analytics oneTimeConfiguration].application; + if (application && [application respondsToSelector:@selector(seg_endBackgroundTask:)]) { [application seg_endBackgroundTask:self.flushTaskID]; } @@ -325,17 +156,22 @@ - (void)endBackgroundTask } }); } +#endif - (NSString *)description { return [NSString stringWithFormat:@"<%p:%@, %@>", self, self.class, self.configuration.writeKey]; } -- (void)saveUserId:(NSString *)userId +- (NSString *)userId { - [self dispatchBackground:^{ - self.userId = userId; + return [SEGState sharedInstance].userInfo.userId; +} +- (void)setUserId:(NSString *)userId +{ + [self dispatchBackground:^{ + [SEGState sharedInstance].userInfo.userId = userId; #if TARGET_OS_TV [self.userDefaultsStorage setString:userId forKey:SEGUserIdKey]; #else @@ -344,11 +180,15 @@ - (void)saveUserId:(NSString *)userId }]; } -- (void)addTraits:(NSDictionary *)traits +- (NSDictionary *)traits { - [self dispatchBackground:^{ - [self.traits addEntriesFromDictionary:traits]; + return [SEGState sharedInstance].userInfo.traits; +} +- (void)setTraits:(NSDictionary *)traits +{ + [self dispatchBackground:^{ + [SEGState sharedInstance].userInfo.traits = traits; #if TARGET_OS_TV [self.userDefaultsStorage setDictionary:[self.traits copy] forKey:SEGTraitsKey]; #else @@ -362,13 +202,14 @@ - (void)addTraits:(NSDictionary *)traits - (void)identify:(SEGIdentifyPayload *)payload { [self dispatchBackground:^{ - [self saveUserId:payload.userId]; - [self addTraits:payload.traits]; + self.userId = payload.userId; + self.traits = payload.traits; }]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [dictionary setValue:payload.traits forKey:@"traits"]; [dictionary setValue:payload.timestamp forKey:@"timestamp"]; + [dictionary setValue:payload.messageId forKey:@"messageId"]; [self enqueueAction:@"identify" dictionary:dictionary context:payload.context integrations:payload.integrations]; } @@ -378,6 +219,7 @@ - (void)track:(SEGTrackPayload *)payload [dictionary setValue:payload.event forKey:@"event"]; [dictionary setValue:payload.properties forKey:@"properties"]; [dictionary setValue:payload.timestamp forKey:@"timestamp"]; + [dictionary setValue:payload.messageId forKey:@"messageId"]; [self enqueueAction:@"track" dictionary:dictionary context:payload.context integrations:payload.integrations]; } @@ -387,6 +229,7 @@ - (void)screen:(SEGScreenPayload *)payload [dictionary setValue:payload.name forKey:@"name"]; [dictionary setValue:payload.properties forKey:@"properties"]; [dictionary setValue:payload.timestamp forKey:@"timestamp"]; + [dictionary setValue:payload.messageId forKey:@"messageId"]; [self enqueueAction:@"screen" dictionary:dictionary context:payload.context integrations:payload.integrations]; } @@ -397,6 +240,7 @@ - (void)group:(SEGGroupPayload *)payload [dictionary setValue:payload.groupId forKey:@"groupId"]; [dictionary setValue:payload.traits forKey:@"traits"]; [dictionary setValue:payload.timestamp forKey:@"timestamp"]; + [dictionary setValue:payload.messageId forKey:@"messageId"]; [self enqueueAction:@"group" dictionary:dictionary context:payload.context integrations:payload.integrations]; } @@ -407,41 +251,11 @@ - (void)alias:(SEGAliasPayload *)payload [dictionary setValue:payload.theNewId forKey:@"userId"]; [dictionary setValue:self.userId ?: [self.analytics getAnonymousId] forKey:@"previousId"]; [dictionary setValue:payload.timestamp forKey:@"timestamp"]; + [dictionary setValue:payload.messageId forKey:@"messageId"]; [self enqueueAction:@"alias" dictionary:dictionary context:payload.context integrations:payload.integrations]; } -- (void)registeredForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken -{ - NSCParameterAssert(deviceToken != nil); - - const unsigned char *buffer = (const unsigned char *)[deviceToken bytes]; - if (!buffer) { - return; - } - NSMutableString *token = [NSMutableString stringWithCapacity:(deviceToken.length * 2)]; - for (NSUInteger i = 0; i < deviceToken.length; i++) { - [token appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)buffer[i]]]; - } - [self.cachedStaticContext[@"device"] setObject:[token copy] forKey:@"token"]; -} - -- (void)continueUserActivity:(NSUserActivity *)activity -{ - if ([activity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { - self.referrer = @{ - @"url" : activity.webpageURL.absoluteString, - }; - } -} - -- (void)openURL:(NSURL *)url options:(NSDictionary *)options -{ - self.referrer = @{ - @"url" : url.absoluteString, - }; -} - #pragma mark - Queueing // Merges user provided integration options with bundled integrations. @@ -462,7 +276,6 @@ - (void)enqueueAction:(NSString *)action dictionary:(NSMutableDictionary *)paylo { // attach these parts of the payload outside since they are all synchronous payload[@"type"] = action; - payload[@"messageId"] = GenerateUUIDString(); [self dispatchBackground:^{ // attach userId and anonymousId inside the dispatch_async in case @@ -470,23 +283,28 @@ - (void)enqueueAction:(NSString *)action dictionary:(NSMutableDictionary *)paylo // Do not override the userId for an 'alias' action. This value is set in [alias:] already. if (![action isEqualToString:@"alias"]) { - [payload setValue:self.userId forKey:@"userId"]; + [payload setValue:[SEGState sharedInstance].userInfo.userId forKey:@"userId"]; } [payload setValue:[self.analytics getAnonymousId] forKey:@"anonymousId"]; [payload setValue:[self integrationsDictionary:integrations] forKey:@"integrations"]; - NSDictionary *staticContext = self.cachedStaticContext; - NSDictionary *liveContext = [self liveContext]; - NSDictionary *customContext = context; - NSMutableDictionary *context = [NSMutableDictionary dictionaryWithCapacity:staticContext.count + liveContext.count + customContext.count]; - [context addEntriesFromDictionary:staticContext]; - [context addEntriesFromDictionary:liveContext]; - [context addEntriesFromDictionary:customContext]; [payload setValue:[context copy] forKey:@"context"]; SEGLog(@"%@ Enqueueing action: %@", self, payload); - [self queuePayload:[payload copy]]; + + NSDictionary *queuePayload = [payload copy]; + + if (self.configuration.experimental.rawSegmentModificationBlock != nil) { + NSDictionary *tempPayload = self.configuration.experimental.rawSegmentModificationBlock(queuePayload); + if (tempPayload == nil) { + SEGLog(@"rawSegmentModificationBlock cannot be used to drop events!"); + } else { + // prevent anything else from modifying it at this point. + queuePayload = [tempPayload copy]; + } + } + [self queuePayload:queuePayload]; }]; } @@ -494,7 +312,7 @@ - (void)queuePayload:(NSDictionary *)payload { @try { // Trim the queue to maxQueueSize - 1 before we add a new element. - trimQueue(self.queue, self.analytics.configuration.maxQueueSize - 1); + trimQueue(self.queue, self.analytics.oneTimeConfiguration.maxQueueSize - 1); [self.queue addObject:payload]; [self persistQueue]; [self flushQueueByLength]; @@ -511,6 +329,17 @@ - (void)flush - (void)flushWithMaxSize:(NSUInteger)maxBatchSize { + void (^startBatch)(void) = ^{ + NSArray *batch; + if ([self.queue count] >= maxBatchSize) { + batch = [self.queue subarrayWithRange:NSMakeRange(0, maxBatchSize)]; + } else { + batch = [NSArray arrayWithArray:self.queue]; + } + [self sendData:batch]; + }; + +#if TARGET_OS_IPHONE [self dispatchBackground:^{ if ([self.queue count] == 0) { SEGLog(@"%@ No queued API calls to flush.", self); @@ -521,16 +350,12 @@ - (void)flushWithMaxSize:(NSUInteger)maxBatchSize SEGLog(@"%@ API request already in progress, not flushing again.", self); return; } - - NSArray *batch; - if ([self.queue count] >= maxBatchSize) { - batch = [self.queue subarrayWithRange:NSMakeRange(0, maxBatchSize)]; - } else { - batch = [NSArray arrayWithArray:self.queue]; - } - - [self sendData:batch]; + // here + startBatch(); }]; +#elif TARGET_OS_OSX + startBatch(); +#endif } - (void)flushQueueByLength @@ -577,7 +402,9 @@ - (void)sendData:(NSArray *)batch SEGLog(@"Flushing batch %@.", payload); self.batchRequest = [self.httpClient upload:payload forWriteKey:self.configuration.writeKey completionHandler:^(BOOL retry) { - [self dispatchBackground:^{ + +#if TARGET_OS_IPHONE + void (^completion)(void) = ^{ if (retry) { [self notifyForName:SEGSegmentRequestDidFailNotification userInfo:batch]; self.batchRequest = nil; @@ -590,12 +417,29 @@ - (void)sendData:(NSArray *)batch [self notifyForName:SEGSegmentRequestDidSucceedNotification userInfo:batch]; self.batchRequest = nil; [self endBackgroundTask]; - }]; + }; +#elif TARGET_OS_OSX + void (^completion)(void) = ^{ + if (retry) { + [self notifyForName:SEGSegmentRequestDidFailNotification userInfo:batch]; + self.batchRequest = nil; + return; + } + + [self.queue removeObjectsInArray:batch]; + [self persistQueue]; + [self notifyForName:SEGSegmentRequestDidSucceedNotification userInfo:batch]; + self.batchRequest = nil; + }; +#endif + + [self dispatchBackground:completion]; }]; [self notifyForName:SEGSegmentDidSendRequestNotification userInfo:batch]; } +#if TARGET_OS_IPHONE - (void)applicationDidEnterBackground { [self beginBackgroundTask]; @@ -603,6 +447,7 @@ - (void)applicationDidEnterBackground // since there is a chance that the user will never launch the app again. [self flush]; } +#endif - (void)applicationWillTerminate { @@ -623,17 +468,17 @@ - (NSMutableArray *)queue return _queue; } -- (NSMutableDictionary *)traits +- (void)loadTraits { - if (!_traits) { + if (![SEGState sharedInstance].userInfo.traits) { + NSDictionary *traits = nil; #if TARGET_OS_TV - _traits = [[self.userDefaultsStorage dictionaryForKey:SEGTraitsKey] ?: @{} mutableCopy]; + traits = [[self.userDefaultsStorage dictionaryForKey:SEGTraitsKey] ?: @{} mutableCopy]; #else - _traits = [[self.fileStorage dictionaryForKey:kSEGTraitsFilename] ?: @{} mutableCopy]; + traits = [[self.fileStorage dictionaryForKey:kSEGTraitsFilename] ?: @{} mutableCopy]; #endif + [SEGState sharedInstance].userInfo.traits = traits; } - - return _traits; } - (NSUInteger)maxBatchSize @@ -641,13 +486,15 @@ - (NSUInteger)maxBatchSize return 100; } -- (NSString *)getUserId +- (void)loadUserId { + NSString *result = nil; #if TARGET_OS_TV - return [[NSUserDefaults standardUserDefaults] valueForKey:SEGUserIdKey]; + result = [[NSUserDefaults standardUserDefaults] valueForKey:SEGUserIdKey]; #else - return [self.fileStorage stringForKey:kSEGUserIdFilename]; + result = [self.fileStorage stringForKey:kSEGUserIdFilename]; #endif + [SEGState sharedInstance].userInfo.userId = result; } - (void)persistQueue @@ -669,11 +516,7 @@ - (void)trackAttributionData:(BOOL)trackAttributionData return; } - NSDictionary *staticContext = self.cachedStaticContext; - NSDictionary *liveContext = [self liveContext]; - NSMutableDictionary *context = [NSMutableDictionary dictionaryWithCapacity:staticContext.count + liveContext.count]; - [context addEntriesFromDictionary:staticContext]; - [context addEntriesFromDictionary:liveContext]; + NSDictionary *context = [SEGState sharedInstance].context.payload; self.attributionRequest = [self.httpClient attributionWithWriteKey:self.configuration.writeKey forDevice:[context copy] completionHandler:^(BOOL success, NSDictionary *properties) { [self dispatchBackground:^{ diff --git a/Analytics/Classes/SEGSegmentIntegrationFactory.h b/Analytics/Classes/SEGSegmentIntegrationFactory.h new file mode 100644 index 000000000..b80a572b0 --- /dev/null +++ b/Analytics/Classes/SEGSegmentIntegrationFactory.h @@ -0,0 +1,20 @@ +#import +#import "SEGIntegrationFactory.h" +#import "SEGHTTPClient.h" +#import "SEGStorage.h" + +NS_ASSUME_NONNULL_BEGIN + + +NS_SWIFT_NAME(SegmentIntegrationFactory) +@interface SEGSegmentIntegrationFactory : NSObject + +@property (nonatomic, strong) SEGHTTPClient *client; +@property (nonatomic, strong) id userDefaultsStorage; +@property (nonatomic, strong) id fileStorage; + +- (instancetype)initWithHTTPClient:(SEGHTTPClient *)client fileStorage:(id)fileStorage userDefaultsStorage:(id)userDefaultsStorage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Analytics/Classes/Internal/SEGSegmentIntegrationFactory.m b/Analytics/Classes/SEGSegmentIntegrationFactory.m similarity index 100% rename from Analytics/Classes/Internal/SEGSegmentIntegrationFactory.m rename to Analytics/Classes/SEGSegmentIntegrationFactory.m diff --git a/Analytics/Classes/Internal/SEGStorage.h b/Analytics/Classes/SEGStorage.h similarity index 100% rename from Analytics/Classes/Internal/SEGStorage.h rename to Analytics/Classes/SEGStorage.h diff --git a/Analytics/Classes/Integrations/SEGTrackPayload.h b/Analytics/Classes/SEGTrackPayload.h similarity index 94% rename from Analytics/Classes/Integrations/SEGTrackPayload.h rename to Analytics/Classes/SEGTrackPayload.h index fc61b3f6d..feefb91a7 100644 --- a/Analytics/Classes/Integrations/SEGTrackPayload.h +++ b/Analytics/Classes/SEGTrackPayload.h @@ -4,6 +4,7 @@ NS_ASSUME_NONNULL_BEGIN +NS_SWIFT_NAME(TrackPayload) @interface SEGTrackPayload : SEGPayload @property (nonatomic, readonly) NSString *event; diff --git a/Analytics/Classes/Integrations/SEGTrackPayload.m b/Analytics/Classes/SEGTrackPayload.m similarity index 100% rename from Analytics/Classes/Integrations/SEGTrackPayload.m rename to Analytics/Classes/SEGTrackPayload.m diff --git a/Analytics/Info.plist b/Analytics/Info.plist index c7281ef54..c7ac749aa 100644 --- a/Analytics/Info.plist +++ b/Analytics/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.9.0 + 4.0.5 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/Analytics/Classes/Internal/NSData+SEGGZIP.h b/Analytics/Internal/NSData+SEGGZIP.h similarity index 100% rename from Analytics/Classes/Internal/NSData+SEGGZIP.h rename to Analytics/Internal/NSData+SEGGZIP.h diff --git a/Analytics/Classes/Internal/NSData+SEGGZIP.m b/Analytics/Internal/NSData+SEGGZIP.m similarity index 100% rename from Analytics/Classes/Internal/NSData+SEGGZIP.m rename to Analytics/Internal/NSData+SEGGZIP.m diff --git a/Analytics/Internal/NSViewController+SEGScreen.h b/Analytics/Internal/NSViewController+SEGScreen.h new file mode 100644 index 000000000..6e4b54bff --- /dev/null +++ b/Analytics/Internal/NSViewController+SEGScreen.h @@ -0,0 +1,21 @@ +// +// NSViewController+SEGScreen.h +// Analytics +// +// Created by Cody Garvin on 7/8/20. +// Copyright © 2020 Segment. All rights reserved. +// + +#import "SEGSerializableValue.h" + +#if TARGET_OS_OSX +#import + +@interface NSViewController (SEGScreen) + ++ (void)seg_swizzleViewDidAppear; ++ (NSViewController *)seg_rootViewControllerFromView:(NSView *)view; + +@end + +#endif diff --git a/Analytics/Internal/NSViewController+SEGScreen.m b/Analytics/Internal/NSViewController+SEGScreen.m new file mode 100644 index 000000000..4558496d5 --- /dev/null +++ b/Analytics/Internal/NSViewController+SEGScreen.m @@ -0,0 +1,99 @@ +// +// NSViewController+SEGScreen.m +// Analytics +// +// Created by Cody Garvin on 7/8/20. +// Copyright © 2020 Segment. All rights reserved. +// + +#import "NSViewController+SEGScreen.h" +#import +#import "SEGAnalytics.h" +#import "SEGAnalyticsUtils.h" +#import "SEGScreenReporting.h" + + +#if TARGET_OS_OSX +@implementation NSViewController (SEGScreen) + ++ (void)seg_swizzleViewDidAppear +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class class = [self class]; + + SEL originalSelector = @selector(viewDidAppear:); + SEL swizzledSelector = @selector(seg_viewDidAppear:); + + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + swizzledSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } + }); +} + ++ (NSViewController *)seg_rootViewControllerFromView:(NSView *)view +{ + NSViewController *rootViewController = view.window.contentViewController; + + if (rootViewController.childViewControllers.count > 0) { + if ([rootViewController conformsToProtocol:@protocol(SEGScreenReporting)] && [rootViewController respondsToSelector:@selector(seg_mainViewController)]) { + __auto_type screenReporting = (NSViewController*)rootViewController; + return screenReporting.seg_mainViewController; + } + + // fall back on first child UIViewController as a "best guess" assumption + __auto_type *firstChildViewController = rootViewController.childViewControllers.firstObject; + if (firstChildViewController != nil) { + return firstChildViewController; + } + } + + return rootViewController; +} + +- (void)seg_viewDidAppear:(BOOL)animated +{ + NSViewController *top = [[self class] seg_rootViewControllerFromView:self.view]; + if (!top) { + SEGLog(@"Could not infer screen."); + return; + } + + NSString *name = [[[top class] description] stringByReplacingOccurrencesOfString:@"ViewController" withString:@""]; + + if (!name || name.length == 0) { + // if no class description found, try view controller's title. + name = [top title]; + // Class name could be just "ViewController". + if (name.length == 0) { + SEGLog(@"Could not infer screen name."); + name = @"Unknown"; + } + } + + if ([top conformsToProtocol:@protocol(SEGScreenReporting)] && [top respondsToSelector:@selector(seg_trackScreen:name:)]) { + __auto_type screenReporting = (NSViewController*)top; + [screenReporting seg_trackScreen:top name:name]; + return; + } + + [[SEGAnalytics sharedAnalytics] screen:name properties:nil options:nil]; + + [self seg_viewDidAppear:animated]; +} +@end +#endif diff --git a/Analytics/Classes/Crypto/SEGAES256Crypto.h b/Analytics/Internal/SEGAES256Crypto.h similarity index 96% rename from Analytics/Classes/Crypto/SEGAES256Crypto.h rename to Analytics/Internal/SEGAES256Crypto.h index 38bd66f9b..c8ff7e3b3 100644 --- a/Analytics/Classes/Crypto/SEGAES256Crypto.h +++ b/Analytics/Internal/SEGAES256Crypto.h @@ -9,6 +9,7 @@ #import "SEGCrypto.h" +NS_SWIFT_NAME(AES256Crypto) @interface SEGAES256Crypto : NSObject @property (nonatomic, readonly, nonnull) NSString *password; diff --git a/Analytics/Classes/Crypto/SEGAES256Crypto.m b/Analytics/Internal/SEGAES256Crypto.m similarity index 100% rename from Analytics/Classes/Crypto/SEGAES256Crypto.m rename to Analytics/Internal/SEGAES256Crypto.m diff --git a/Analytics/Classes/Internal/SEGFileStorage.h b/Analytics/Internal/SEGFileStorage.h similarity index 95% rename from Analytics/Classes/Internal/SEGFileStorage.h rename to Analytics/Internal/SEGFileStorage.h index 6fbcf46ff..ca872c29c 100644 --- a/Analytics/Classes/Internal/SEGFileStorage.h +++ b/Analytics/Internal/SEGFileStorage.h @@ -9,6 +9,7 @@ #import "SEGStorage.h" +NS_SWIFT_NAME(FileStorage) @interface SEGFileStorage : NSObject @property (nonatomic, strong, nullable) id crypto; diff --git a/Analytics/Internal/SEGFileStorage.m b/Analytics/Internal/SEGFileStorage.m new file mode 100644 index 000000000..6392f4f55 --- /dev/null +++ b/Analytics/Internal/SEGFileStorage.m @@ -0,0 +1,277 @@ +// +// SEGFileStorage.m +// Analytics +// +// Copyright © 2016 Segment. All rights reserved. +// + +#import "SEGUtils.h" +#import "SEGFileStorage.h" +#import "SEGCrypto.h" + + +@interface SEGFileStorage () + +@property (nonatomic, strong, nonnull) NSURL *folderURL; + +@end + + +@implementation SEGFileStorage + +- (instancetype)initWithFolder:(NSURL *)folderURL crypto:(id)crypto +{ + if (self = [super init]) { + _folderURL = folderURL; + _crypto = crypto; + [self createDirectoryAtURLIfNeeded:folderURL]; + return self; + } + return nil; +} + +- (void)removeKey:(NSString *)key +{ + NSURL *url = [self urlForKey:key]; + NSError *error = nil; + if (![[NSFileManager defaultManager] removeItemAtURL:url error:&error]) { + SEGLog(@"Unable to remove key %@ - error removing file at path %@", key, url); + } +} + +- (void)resetAll +{ + NSError *error = nil; + if (![[NSFileManager defaultManager] removeItemAtURL:self.folderURL error:&error]) { + SEGLog(@"ERROR: Unable to reset file storage. Path cannot be removed - %@", self.folderURL.path); + } + [self createDirectoryAtURLIfNeeded:self.folderURL]; +} + +- (void)setData:(NSData *)data forKey:(NSString *)key +{ + NSURL *url = [self urlForKey:key]; + + // a nil value was supplied, remove the storage for said key. + if (data == nil) { + [[NSFileManager defaultManager] removeItemAtURL:url error:nil]; + return; + } + + if (self.crypto) { + NSData *encryptedData = [self.crypto encrypt:data]; + [encryptedData writeToURL:url atomically:YES]; + } else { + [data writeToURL:url atomically:YES]; + } + + NSError *error = nil; + if (![url setResourceValue:@YES + forKey:NSURLIsExcludedFromBackupKey + error:&error]) { + SEGLog(@"Error excluding %@ from backup %@", [url lastPathComponent], error); + } +} + +- (NSData *)dataForKey:(NSString *)key +{ + NSURL *url = [self urlForKey:key]; + NSData *data = [NSData dataWithContentsOfURL:url]; + if (!data) { + SEGLog(@"WARNING: No data file for key %@", key); + return nil; + } + if (self.crypto) { + return [self.crypto decrypt:data]; + } + return data; +} + +- (nullable NSDictionary *)dictionaryForKey:(NSString *)key +{ + return [self jsonForKey:key]; +} + +- (void)setDictionary:(nullable NSDictionary *)dictionary forKey:(NSString *)key +{ + [self setJSON:dictionary forKey:key]; +} + +- (nullable NSArray *)arrayForKey:(NSString *)key +{ + return [self jsonForKey:key]; +} + +- (void)setArray:(nullable NSArray *)array forKey:(NSString *)key +{ + [self setJSON:array forKey:key]; +} + +- (nullable NSString *)stringForKey:(NSString *)key +{ + id data = [self jsonForKey:key]; + + if (data == nil) { + return nil; + } + + if ([data isKindOfClass:[NSString class]]) { + return data; + } else if ([data isKindOfClass:[NSDictionary class]]) { + return data[key]; + } + + return nil; +} + +- (void)setString:(nullable NSString *)string forKey:(NSString *)key +{ + [self setJSON:string forKey:key]; +} + + ++ (NSURL *)applicationSupportDirectoryURL +{ + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *storagePath = [paths firstObject]; + return [NSURL fileURLWithPath:storagePath]; +} + ++ (NSURL *)cachesDirectoryURL +{ + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString *storagePath = [paths firstObject]; + return [NSURL fileURLWithPath:storagePath]; +} + +- (NSURL *)urlForKey:(NSString *)key +{ + return [self.folderURL URLByAppendingPathComponent:key]; +} + +#pragma mark - Helpers + +- (id _Nullable)jsonForKey:(NSString *)key +{ + id result = nil; + + NSData *data = [self dataForKey:key]; + if (data) { + BOOL needsConversion = NO; + result = [self jsonFromData:data needsConversion:&needsConversion]; + if (needsConversion) { + @try { + [self setJSON:result forKey:key]; + // maybe a little repetitive, but we want to recreate the same path it would + // take if it weren't being converted. + data = [self dataForKey:key]; + result = [self jsonFromData:data needsConversion:&needsConversion]; + } @catch (NSException *e) { + SEGLog(@"Unable to convert data from plist object to json; Exception: %@, data: %@", e, data); + + [self removeKey:key]; + result = nil; + } + } + } + return result; +} + +- (void)setJSON:(id _Nonnull)json forKey:(NSString *)key +{ + NSDictionary *dict = nil; + + // json doesn't allow stand alone values like plist (previous storage format) does so + // we need to massage it a little. + if (json) { + if ([json isKindOfClass:[NSDictionary class]] || [json isKindOfClass:[NSArray class]]) { + dict = json; + } else { + dict = @{key: json}; + } + } + + NSData *data = [self dataFromJSON:dict]; + [self setData:data forKey:key]; +} + +- (NSData *_Nullable)dataFromJSON:(id)json +{ + if (json == nil) { + return nil; + } + + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:&error]; + if (error) { + SEGLog(@"Unable to serialize data from json object; %@, %@", error, json); + } + return data; +} + +- (id _Nullable)jsonFromData:(NSData *_Nonnull)data needsConversion:(BOOL *)needsConversion +{ + NSError *error = nil; + id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + if (error) { + // maybe it's a plist and needs to be converted. + result = [self plistFromData:data]; + if (result != nil) { + *needsConversion = YES; + } else { + SEGLog(@"Unable to parse json from data %@", error); + } + } + return result; +} + +- (void)createDirectoryAtURLIfNeeded:(NSURL *)url +{ + if (![[NSFileManager defaultManager] fileExistsAtPath:url.path + isDirectory:NULL]) { + NSError *error = nil; + if (![[NSFileManager defaultManager] createDirectoryAtPath:url.path + withIntermediateDirectories:YES + attributes:nil + error:&error]) { + SEGLog(@"error: %@", error.localizedDescription); + } + } +} + +/// Deprecated +- (NSData *_Nullable)dataFromPlist:(nonnull id)plist +{ + NSError *error = nil; + NSData *data = nil; + // Temporary just-in-case fix for issue #846; Follow-on PR to move away from plist storage. + @try { + data = [NSPropertyListSerialization dataWithPropertyList:plist + format:NSPropertyListXMLFormat_v1_0 + options:0 + error:&error]; + } @catch (NSException *e) { + SEGLog(@"Unable to serialize data from plist object; Exception: %@, plist: %@", e, plist); + } @finally { + if (error) { + SEGLog(@"Unable to serialize data from plist object; Error: %@, plist: %@", error, plist); + } + } + return data; +} + +/// Deprecated +- (id _Nullable)plistFromData:(NSData *_Nonnull)data +{ + NSError *error = nil; + id plist = [NSPropertyListSerialization propertyListWithData:data + options:0 + format:nil + error:&error]; + if (error) { + SEGLog(@"Unable to parse plist from data %@", error); + } + return plist; +} + +@end diff --git a/Analytics/Classes/Integrations/SEGIntegrationsManager.h b/Analytics/Internal/SEGIntegrationsManager.h similarity index 97% rename from Analytics/Classes/Integrations/SEGIntegrationsManager.h rename to Analytics/Internal/SEGIntegrationsManager.h index ec17275cb..661888e96 100644 --- a/Analytics/Classes/Integrations/SEGIntegrationsManager.h +++ b/Analytics/Internal/SEGIntegrationsManager.h @@ -22,7 +22,7 @@ extern NSString *_Nonnull SEGAnalyticsIntegrationDidStart; @class SEGAnalytics; - +NS_SWIFT_NAME(IntegrationsManager) @interface SEGIntegrationsManager : NSObject // Exposed for testing. diff --git a/Analytics/Classes/Integrations/SEGIntegrationsManager.m b/Analytics/Internal/SEGIntegrationsManager.m similarity index 77% rename from Analytics/Classes/Integrations/SEGIntegrationsManager.m rename to Analytics/Internal/SEGIntegrationsManager.m index 613554c0c..c39b0201e 100644 --- a/Analytics/Classes/Integrations/SEGIntegrationsManager.m +++ b/Analytics/Internal/SEGIntegrationsManager.m @@ -6,7 +6,9 @@ // Copyright © 2016 Segment. All rights reserved. // +#if TARGET_OS_IPHONE #import +#endif #import #import "SEGAnalyticsUtils.h" #import "SEGAnalytics.h" @@ -24,6 +26,8 @@ #import "SEGGroupPayload.h" #import "SEGScreenPayload.h" #import "SEGAliasPayload.h" +#import "SEGUtils.h" +#import "SEGState.h" NSString *SEGAnalyticsIntegrationDidStart = @"io.segment.analytics.integration.did.start"; NSString *const SEGAnonymousIdKey = @"SEGAnonymousId"; @@ -66,6 +70,7 @@ @interface SEGIntegrationsManager () @property (nonatomic, strong) NSArray *factories; @property (nonatomic, strong) NSMutableDictionary *integrations; @property (nonatomic, strong) NSMutableDictionary *registeredIntegrations; +@property (nonatomic, strong) NSMutableDictionary *integrationMiddleware; @property (nonatomic) volatile BOOL initialized; @property (nonatomic, copy) NSString *cachedAnonymousId; @property (nonatomic, strong) SEGHTTPClient *httpClient; @@ -75,14 +80,19 @@ @interface SEGIntegrationsManager () @end +@interface SEGAnalytics () +@property (nullable, nonatomic, strong, readonly) SEGAnalyticsConfiguration *oneTimeConfiguration; +@end + @implementation SEGIntegrationsManager +@dynamic cachedAnonymousId; @synthesize cachedSettings = _cachedSettings; - (instancetype _Nonnull)initWithAnalytics:(SEGAnalytics *_Nonnull)analytics { - SEGAnalyticsConfiguration *configuration = analytics.configuration; + SEGAnalyticsConfiguration *configuration = analytics.oneTimeConfiguration; NSCParameterAssert(configuration != nil); if (self = [super init]) { @@ -91,7 +101,6 @@ - (instancetype _Nonnull)initWithAnalytics:(SEGAnalytics *_Nonnull)analytics self.serialQueue = seg_dispatch_queue_create_specific("io.segment.analytics", DISPATCH_QUEUE_SERIAL); self.messageQueue = [[NSMutableArray alloc] init]; self.httpClient = [[SEGHTTPClient alloc] initWithRequestFactory:configuration.requestFactory]; - self.userDefaultsStorage = [[SEGUserDefaultsStorage alloc] initWithDefaults:[NSUserDefaults standardUserDefaults] namespacePrefix:nil crypto:configuration.crypto]; #if TARGET_OS_TV self.fileStorage = [[SEGFileStorage alloc] initWithFolder:[SEGFileStorage cachesDirectoryURL] crypto:configuration.crypto]; @@ -105,17 +114,21 @@ - (instancetype _Nonnull)initWithAnalytics:(SEGAnalytics *_Nonnull)analytics self.factories = [factories copy]; self.integrations = [NSMutableDictionary dictionaryWithCapacity:factories.count]; self.registeredIntegrations = [NSMutableDictionary dictionaryWithCapacity:factories.count]; + self.integrationMiddleware = [NSMutableDictionary dictionaryWithCapacity:factories.count]; // Update settings on each integration immediately [self refreshSettings]; - // Attach to application state change hooks - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - // Update settings on foreground id application = configuration.application; if (application) { + // Attach to application state change hooks + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; +#if TARGET_OS_IPHONE [nc addObserver:self selector:@selector(onAppForeground:) name:UIApplicationWillEnterForegroundNotification object:application]; +#elif TARGET_OS_OSX + [nc addObserver:self selector:@selector(onAppForeground:) name:NSApplicationWillUnhideNotification object:application]; +#endif } } return self; @@ -127,19 +140,30 @@ - (void)dealloc [[NSNotificationCenter defaultCenter] removeObserver:self]; } +- (void)setCachedAnonymousId:(NSString *)cachedAnonymousId +{ + [SEGState sharedInstance].userInfo.anonymousId = cachedAnonymousId; +} + +- (NSString *)cachedAnonymousId +{ + NSString *value = [SEGState sharedInstance].userInfo.anonymousId; + return value; +} - (void)onAppForeground:(NSNotification *)note { [self refreshSettings]; } - - (void)handleAppStateNotification:(NSString *)notificationName { SEGLog(@"Application state change notification: %@", notificationName); static NSDictionary *selectorMapping; static dispatch_once_t selectorMappingOnce; dispatch_once(&selectorMappingOnce, ^{ +#if TARGET_OS_IPHONE + selectorMapping = @{ UIApplicationDidFinishLaunchingNotification : NSStringFromSelector(@selector(applicationDidFinishLaunching:)), @@ -154,6 +178,23 @@ - (void)handleAppStateNotification:(NSString *)notificationName UIApplicationDidBecomeActiveNotification : NSStringFromSelector(@selector(applicationDidBecomeActive)) }; +#elif TARGET_OS_OSX + selectorMapping = @{ + NSApplicationDidFinishLaunchingNotification : + NSStringFromSelector(@selector(applicationDidFinishLaunching:)), + NSApplicationDidHideNotification : + NSStringFromSelector(@selector(applicationDidEnterBackground)), + NSApplicationWillUnhideNotification : + NSStringFromSelector(@selector(applicationWillEnterForeground)), + NSApplicationWillTerminateNotification : + NSStringFromSelector(@selector(applicationWillTerminate)), + NSApplicationWillResignActiveNotification : + NSStringFromSelector(@selector(applicationWillResignActive)), + NSApplicationDidBecomeActiveNotification : + NSStringFromSelector(@selector(applicationDidBecomeActive)) + }; +#endif + }); SEL selector = NSSelectorFromString(selectorMapping[notificationName]); if (selector) { @@ -161,7 +202,6 @@ - (void)handleAppStateNotification:(NSString *)notificationName } } - #pragma mark - Public API - (NSString *)description @@ -176,48 +216,17 @@ - (void)identify:(SEGIdentifyPayload *)payload NSCAssert2(payload.userId.length > 0 || payload.traits.count > 0, @"either userId (%@) or traits (%@) must be provided.", payload.userId, payload.traits); NSString *anonymousId = payload.anonymousId; - if (anonymousId) { - [self saveAnonymousId:anonymousId]; - } else { - anonymousId = self.cachedAnonymousId; - } - payload.anonymousId = anonymousId; + NSString *existingAnonymousId = self.cachedAnonymousId; - [self callIntegrationsWithSelector:NSSelectorFromString(@"identify:") - arguments:@[ payload ] - options:payload.options - sync:false]; -} -/* -- (void)identify:(NSString *)userId traits:(NSDictionary *)traits options:(NSDictionary *)options -{ - NSCAssert2(userId.length > 0 || traits.count > 0, @"either userId (%@) or traits (%@) must be provided.", userId, traits); - - NSDictionary *options; - if (p.anonymousId) { - NSMutableDictionary *mutableOptions = [[NSMutableDictionary alloc] initWithDictionary:p.options]; - mutableOptions[@"anonymousId"] = p.anonymousId; - options = [mutableOptions copy]; - } else { - options = p.options; - } - - NSString *anonymousId = [options objectForKey:@"anonymousId"]; - if (anonymousId) { + if (anonymousId == nil) { + payload.anonymousId = anonymousId; + } else if (![anonymousId isEqualToString:existingAnonymousId]) { [self saveAnonymousId:anonymousId]; - } else { - anonymousId = self.cachedAnonymousId; } - SEGIdentifyPayload *payload = [[SEGIdentifyPayload alloc] initWithUserId:userId - anonymousId:anonymousId - traits:SEGCoerceDictionary(traits) - context:SEGCoerceDictionary([options objectForKey:@"context"]) - integrations:[options objectForKey:@"integrations"]]; - [self callIntegrationsWithSelector:NSSelectorFromString(@"identify:") arguments:@[ payload ] - options:options + options:payload.options sync:false]; }*/ @@ -333,6 +342,7 @@ - (NSString *)loadOrGenerateAnonymousID:(BOOL)reset [self.fileStorage setString:anonymousId forKey:kSEGAnonymousIdFilename]; #endif } + return anonymousId; } @@ -362,7 +372,6 @@ - (NSDictionary *)cachedSettings _cachedSettings = [self.fileStorage dictionaryForKey:kSEGCachedSettingsFilename] ?: @{}; #endif } - return _cachedSettings; } @@ -373,7 +382,6 @@ - (void)setCachedSettings:(NSDictionary *)settings // [@{} writeToURL:settingsURL atomically:YES]; return; } - #if TARGET_OS_TV [self.userDefaultsStorage setDictionary:_cachedSettings forKey:kSEGCachedSettingsFilename]; #else @@ -383,6 +391,17 @@ - (void)setCachedSettings:(NSDictionary *)settings [self updateIntegrationsWithSettings:settings[@"integrations"]]; } +- (nonnull NSArray> *)middlewareForIntegrationKey:(NSString *)key +{ + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (SEGDestinationMiddleware *container in self.configuration.destinationMiddleware) { + if ([container.integrationKey isEqualToString:key]) { + [result addObjectsFromArray:container.middleware]; + } + } + return result; +} + - (void)updateIntegrationsWithSettings:(NSDictionary *)projectSettings { seg_dispatch_specific_sync(_serialQueue, ^{ @@ -392,11 +411,18 @@ - (void)updateIntegrationsWithSettings:(NSDictionary *)projectSettings for (id factory in self.factories) { NSString *key = [factory key]; NSDictionary *integrationSettings = [projectSettings objectForKey:key]; + if (isUnitTesting()) { + integrationSettings = @{}; + } if (integrationSettings) { id integration = [factory createWithSettings:integrationSettings forAnalytics:self.analytics]; if (integration != nil) { self.integrations[key] = integration; self.registeredIntegrations[key] = @NO; + + // setup integration middleware + NSArray> *middleware = [self middlewareForIntegrationKey:key]; + self.integrationMiddleware[key] = [[SEGMiddlewareRunner alloc] initWithMiddleware:middleware]; } [[NSNotificationCenter defaultCenter] postNotificationName:SEGAnalyticsIntegrationDidStart object:key userInfo:nil]; } else { @@ -408,6 +434,16 @@ - (void)updateIntegrationsWithSettings:(NSDictionary *)projectSettings }); } +- (void)configureEdgeFunctions:(NSDictionary *)settings +{ + if (self.configuration.edgeFunctionMiddleware) { + NSDictionary *edgeFnSettings = settings[@"edgeFunction"]; + if (edgeFnSettings != nil && edgeFnSettings.count > 0) { + [self.configuration.edgeFunctionMiddleware setEdgeFunctionData:settings[@"edgeFunction"]]; + } + } +} + - (void)refreshSettings { seg_dispatch_specific_async(_serialQueue, ^{ @@ -419,16 +455,19 @@ - (void)refreshSettings seg_dispatch_specific_async(self -> _serialQueue, ^{ if (success) { [self setCachedSettings:settings]; + [self configureEdgeFunctions:settings]; } else { NSDictionary *previouslyCachedSettings = [self cachedSettings]; if (previouslyCachedSettings && [previouslyCachedSettings count] > 0) { [self setCachedSettings:previouslyCachedSettings]; + [self configureEdgeFunctions:settings]; } else if (self.configuration.defaultSettings != nil) { // If settings request fail, load a user-supplied version if present. // but make sure segment.io is in the integrations NSMutableDictionary *newSettings = [self.configuration.defaultSettings serializableMutableDeepCopy]; newSettings[@"integrations"][@"Segment.io"][@"apiKey"] = self.configuration.writeKey; [self setCachedSettings:newSettings]; + // don't configure edge functions here. it'll do the right thing on it's own. } else { // If settings request fail, fall back to using just Segment integration. // Doesn't address situations where this callback never gets called (though we don't expect that to ever happen). @@ -438,6 +477,7 @@ - (void)refreshSettings }, @"plan" : @{@"track" : @{}} }]; + // don't configure edge functions here. it'll do the right thing on it's own. } } self.settingsRequest = nil; @@ -456,7 +496,6 @@ + (BOOL)isIntegration:(NSString *)key enabledInOptions:(NSDictionary *)options } if (options[key]) { id value = options[key]; - // it's been observed that customers sometimes override this with // value's that aren't bool types. if ([value isKindOfClass:[NSNumber class]]) { @@ -505,6 +544,49 @@ - (void)forwardSelector:(SEL)selector arguments:(NSArray *)arguments options:(NS }]; } +/* + This kind of sucks, but we wrote ourselves into a corner here. A larger refactor will need to happen. + I also opted to not put this as a utility function because we shouldn't be doing this in the first place, + so consider it a one-off. If you find yourself needing to do this again, lets talk about a refactor. + */ +- (SEGEventType)eventTypeFromSelector:(SEL)selector +{ + NSString *selectorString = NSStringFromSelector(selector); + SEGEventType result = SEGEventTypeUndefined; + + if ([selectorString hasPrefix:@"identify"]) { + result = SEGEventTypeIdentify; + } else if ([selectorString hasPrefix:@"track"]) { + result = SEGEventTypeTrack; + } else if ([selectorString hasPrefix:@"screen"]) { + result = SEGEventTypeScreen; + } else if ([selectorString hasPrefix:@"group"]) { + result = SEGEventTypeGroup; + } else if ([selectorString hasPrefix:@"alias"]) { + result = SEGEventTypeAlias; + } else if ([selectorString hasPrefix:@"reset"]) { + result = SEGEventTypeReset; + } else if ([selectorString hasPrefix:@"flush"]) { + result = SEGEventTypeFlush; + } else if ([selectorString hasPrefix:@"receivedRemoteNotification"]) { + result = SEGEventTypeReceivedRemoteNotification; + } else if ([selectorString hasPrefix:@"failedToRegisterForRemoteNotificationsWithError"]) { + result = SEGEventTypeFailedToRegisterForRemoteNotifications; + } else if ([selectorString hasPrefix:@"registeredForRemoteNotificationsWithDeviceToken"]) { + result = SEGEventTypeRegisteredForRemoteNotifications; + } else if ([selectorString hasPrefix:@"handleActionWithIdentifier"]) { + result = SEGEventTypeHandleActionWithForRemoteNotification; + } else if ([selectorString hasPrefix:@"continueUserActivity"]) { + result = SEGEventTypeContinueUserActivity; + } else if ([selectorString hasPrefix:@"openURL"]) { + result = SEGEventTypeOpenURL; + } else if ([selectorString hasPrefix:@"application"]) { + result = SEGEventTypeApplicationLifecycle; + } + + return result; +} + - (void)invokeIntegration:(id)integration key:(NSString *)key selector:(SEL)selector arguments:(NSArray *)arguments options:(NSDictionary *)options { if (![integration respondsToSelector:selector]) { @@ -517,8 +599,8 @@ - (void)invokeIntegration:(id)integration key:(NSString *)key se return; } - NSString *eventType = NSStringFromSelector(selector); - if ([eventType hasPrefix:@"track:"]) { + SEGEventType eventType = [self eventTypeFromSelector:selector]; + if (eventType == SEGEventTypeTrack) { SEGTrackPayload *eventPayload = arguments[0]; BOOL enabled = [[self class] isTrackEvent:eventPayload.event enabledForIntegration:key inPlan:self.cachedSettings[@"plan"]]; if (!enabled) { @@ -527,8 +609,31 @@ - (void)invokeIntegration:(id)integration key:(NSString *)key se } } - SEGLog(@"Running: %@ with arguments %@ on integration: %@", eventType, arguments, key); - NSInvocation *invocation = [self invocationForSelector:selector arguments:arguments]; + NSMutableArray *newArguments = [arguments mutableCopy]; + + if (eventType != SEGEventTypeUndefined) { + SEGMiddlewareRunner *runner = self.integrationMiddleware[key]; + if (runner.middlewares.count > 0) { + SEGPayload *payload = nil; + // things like flush have no args. + if (arguments.count > 0) { + payload = arguments[0]; + } + SEGContext *context = [[[SEGContext alloc] initWithAnalytics:self.analytics] modify:^(id _Nonnull ctx) { + ctx.eventType = eventType; + ctx.payload = payload; + }]; + + context = [runner run:context callback:nil]; + // if we weren't given args, don't set them. + if (arguments.count > 0) { + newArguments[0] = context.payload; + } + } + } + + SEGLog(@"Running: %@ with arguments %@ on integration: %@", NSStringFromSelector(selector), newArguments, key); + NSInvocation *invocation = [self invocationForSelector:selector arguments:newArguments]; [invocation invokeWithTarget:integration]; } @@ -590,16 +695,6 @@ - (void)context:(SEGContext *)context next:(void (^_Nonnull)(SEGContext *_Nullab case SEGEventTypeIdentify: { SEGIdentifyPayload *p = (SEGIdentifyPayload *)context.payload; [self identify:p]; - /* - NSDictionary *options; - if (p.anonymousId) { - NSMutableDictionary *mutableOptions = [[NSMutableDictionary alloc] initWithDictionary:p.options]; - mutableOptions[@"anonymousId"] = p.anonymousId; - options = [mutableOptions copy]; - } else { - options = p.options; - } - [self identify:p.userId traits:p.traits options:options];*/ break; } case SEGEventTypeTrack: { @@ -646,10 +741,6 @@ - (void)context:(SEGContext *)context next:(void (^_Nonnull)(SEGContext *_Nullab forRemoteNotification:payload.userInfo]; break; } - case SEGEventTypeApplicationLifecycle: - [self handleAppStateNotification: - [(SEGApplicationLifecyclePayload *)context.payload notificationName]]; - break; case SEGEventTypeContinueUserActivity: [self continueUserActivity: [(SEGContinueUserActivityPayload *)context.payload activity]]; @@ -659,9 +750,14 @@ - (void)context:(SEGContext *)context next:(void (^_Nonnull)(SEGContext *_Nullab [self openURL:payload.url options:payload.options]; break; } + case SEGEventTypeApplicationLifecycle: + [self handleAppStateNotification: + [(SEGApplicationLifecyclePayload *)context.payload notificationName]]; + break; + default: case SEGEventTypeUndefined: NSAssert(NO, @"Received context with undefined event type %@", context); - NSLog(@"[ERROR]: Received context with undefined event type %@", context); + SEGLog(@"[ERROR]: Received context with undefined event type %@", context); break; } next(context); diff --git a/Analytics/Internal/SEGMacros.h b/Analytics/Internal/SEGMacros.h new file mode 100644 index 000000000..f07ad6b7f --- /dev/null +++ b/Analytics/Internal/SEGMacros.h @@ -0,0 +1,28 @@ +// +// SEGMacros.h +// Analytics +// +// Created by Brandon Sneed on 12/20/19. +// Copyright © 2019 Segment. All rights reserved. +// + +#ifndef SEGMacros_h +#define SEGMacros_h + +#import "TargetConditionals.h" + +#define __deprecated__(s) __attribute__((deprecated(s))) + +#define weakify(var) __weak typeof(var) __weak_##var = var; + +#define strongify(var) \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wshadow\"") \ +__strong typeof(var) var = __weak_##var; \ +_Pragma("clang diagnostic pop") + +#if TARGET_OS_IOS == 1 || TARGET_OS_TV == 1 +#define TARGET_UIKIT 1 +#endif + +#endif /* SEGMacros_h */ diff --git a/Analytics/Internal/SEGState.h b/Analytics/Internal/SEGState.h new file mode 100644 index 000000000..7b523b2cb --- /dev/null +++ b/Analytics/Internal/SEGState.h @@ -0,0 +1,45 @@ +// +// SEGState.h +// Analytics +// +// Created by Brandon Sneed on 6/9/20. +// Copyright © 2020 Segment. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class SEGAnalyticsConfiguration; + +@interface SEGUserInfo: NSObject +@property (nonatomic, strong) NSString *anonymousId; +@property (nonatomic, strong, nullable) NSString *userId; +@property (nonatomic, strong, nullable) NSDictionary *traits; +@end + +@interface SEGPayloadContext: NSObject +@property (nonatomic, readonly) NSDictionary *payload; +@property (nonatomic, strong, nullable) NSDictionary *referrer; +@property (nonatomic, strong, nullable) NSString *deviceToken; + +- (void)updateStaticContext; + +@end + + + +@interface SEGState : NSObject + +@property (nonatomic, readonly) SEGUserInfo *userInfo; +@property (nonatomic, readonly) SEGPayloadContext *context; + +@property (nonatomic, strong, nullable) SEGAnalyticsConfiguration *configuration; + ++ (instancetype)sharedInstance; +- (instancetype)init __unavailable; + +- (void)setUserInfo:(SEGUserInfo *)userInfo; +@end + +NS_ASSUME_NONNULL_END diff --git a/Analytics/Internal/SEGState.m b/Analytics/Internal/SEGState.m new file mode 100644 index 000000000..2fbaa0760 --- /dev/null +++ b/Analytics/Internal/SEGState.m @@ -0,0 +1,212 @@ +// +// SEGState.m +// Analytics +// +// Created by Brandon Sneed on 6/9/20. +// Copyright © 2020 Segment. All rights reserved. +// + +#import "SEGState.h" +#import "SEGAnalytics.h" +#import "SEGAnalyticsUtils.h" +#import "SEGReachability.h" +#import "SEGUtils.h" + +typedef void (^SEGStateSetBlock)(void); +typedef _Nullable id (^SEGStateGetBlock)(void); + + +@interface SEGState() +// State Objects +@property (nonatomic, nonnull) SEGUserInfo *userInfo; +@property (nonatomic, nonnull) SEGPayloadContext *context; +// State Accessors +- (void)setValueWithBlock:(SEGStateSetBlock)block; +- (id)valueWithBlock:(SEGStateGetBlock)block; +@end + + +@protocol SEGStateObject +@property (nonatomic, weak) SEGState *state; +- (instancetype)initWithState:(SEGState *)state; +@end + + +@interface SEGUserInfo () +@end + +@interface SEGPayloadContext () +@property (nonatomic, strong) SEGReachability *reachability; +@property (nonatomic, strong) NSDictionary *cachedStaticContext; +@end + +#pragma mark - SEGUserInfo + +@implementation SEGUserInfo + +@synthesize state; + +@synthesize anonymousId = _anonymousId; +@synthesize userId = _userId; +@synthesize traits = _traits; + +- (instancetype)initWithState:(SEGState *)state +{ + if (self = [super init]) { + self.state = state; + } + return self; +} + +- (NSString *)anonymousId +{ + return [state valueWithBlock: ^id{ + return self->_anonymousId; + }]; +} + +- (void)setAnonymousId:(NSString *)anonymousId +{ + [state setValueWithBlock: ^{ + self->_anonymousId = [anonymousId copy]; + }]; +} + +- (NSString *)userId +{ + return [state valueWithBlock: ^id{ + return self->_userId; + }]; +} + +- (void)setUserId:(NSString *)userId +{ + [state setValueWithBlock: ^{ + self->_userId = [userId copy]; + }]; +} + +- (NSDictionary *)traits +{ + return [state valueWithBlock:^id{ + return self->_traits; + }]; +} + +- (void)setTraits:(NSDictionary *)traits +{ + [state setValueWithBlock: ^{ + self->_traits = [traits serializableDeepCopy]; + }]; +} + +@end + + +#pragma mark - SEGPayloadContext + +@implementation SEGPayloadContext + +@synthesize state; +@synthesize reachability; + +@synthesize referrer = _referrer; +@synthesize cachedStaticContext = _cachedStaticContext; +@synthesize deviceToken = _deviceToken; + +- (instancetype)initWithState:(SEGState *)state +{ + if (self = [super init]) { + self.state = state; + self.reachability = [SEGReachability reachabilityWithHostname:@"google.com"]; + [self.reachability startNotifier]; + } + return self; +} + +- (void)updateStaticContext +{ + self.cachedStaticContext = getStaticContext(state.configuration, self.deviceToken); +} + +- (NSDictionary *)payload +{ + NSMutableDictionary *result = [self.cachedStaticContext mutableCopy]; + [result addEntriesFromDictionary:getLiveContext(self.reachability, self.referrer, state.userInfo.traits)]; + return result; +} + +- (NSDictionary *)referrer +{ + return [state valueWithBlock:^id{ + return self->_referrer; + }]; +} + +- (void)setReferrer:(NSDictionary *)referrer +{ + [state setValueWithBlock: ^{ + self->_referrer = [referrer serializableDeepCopy]; + }]; +} + +- (NSString *)deviceToken +{ + return [state valueWithBlock:^id{ + return self->_deviceToken; + }]; +} + +- (void)setDeviceToken:(NSString *)deviceToken +{ + [state setValueWithBlock: ^{ + self->_deviceToken = [deviceToken copy]; + }]; + [self updateStaticContext]; +} + +@end + + +#pragma mark - SEGState + +@implementation SEGState { + dispatch_queue_t _stateQueue; +} + +// TODO: Make this not a singleton.. :( ++ (instancetype)sharedInstance +{ + static SEGState *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init +{ + if (self = [super init]) { + _stateQueue = dispatch_queue_create("com.segment.state.queue", DISPATCH_QUEUE_CONCURRENT); + self.userInfo = [[SEGUserInfo alloc] initWithState:self]; + self.context = [[SEGPayloadContext alloc] initWithState:self]; + } + return self; +} + +- (void)setValueWithBlock:(SEGStateSetBlock)block +{ + dispatch_barrier_async(_stateQueue, block); +} + +- (id)valueWithBlock:(SEGStateGetBlock)block +{ + __block id value = nil; + dispatch_sync(_stateQueue, ^{ + value = block(); + }); + return value; +} + +@end diff --git a/Analytics/Classes/Internal/SEGStoreKitTracker.h b/Analytics/Internal/SEGStoreKitTracker.h similarity index 91% rename from Analytics/Classes/Internal/SEGStoreKitTracker.h rename to Analytics/Internal/SEGStoreKitTracker.h index ce271dc6b..87ede731c 100644 --- a/Analytics/Classes/Internal/SEGStoreKitTracker.h +++ b/Analytics/Internal/SEGStoreKitTracker.h @@ -5,6 +5,7 @@ NS_ASSUME_NONNULL_BEGIN +NS_SWIFT_NAME(StoreKitTracker) @interface SEGStoreKitTracker : NSObject + (instancetype)trackTransactionsForAnalytics:(SEGAnalytics *)analytics; diff --git a/Analytics/Classes/Internal/SEGStoreKitTracker.m b/Analytics/Internal/SEGStoreKitTracker.m similarity index 100% rename from Analytics/Classes/Internal/SEGStoreKitTracker.m rename to Analytics/Internal/SEGStoreKitTracker.m diff --git a/Analytics/Classes/Internal/SEGUserDefaultsStorage.h b/Analytics/Internal/SEGUserDefaultsStorage.h similarity index 94% rename from Analytics/Classes/Internal/SEGUserDefaultsStorage.h rename to Analytics/Internal/SEGUserDefaultsStorage.h index 1d594f722..a67448ec3 100644 --- a/Analytics/Classes/Internal/SEGUserDefaultsStorage.h +++ b/Analytics/Internal/SEGUserDefaultsStorage.h @@ -10,6 +10,7 @@ #import "SEGStorage.h" +NS_SWIFT_NAME(UserDefaultsStorage) @interface SEGUserDefaultsStorage : NSObject @property (nonatomic, strong, nullable) id crypto; diff --git a/Analytics/Classes/Internal/SEGUserDefaultsStorage.m b/Analytics/Internal/SEGUserDefaultsStorage.m similarity index 100% rename from Analytics/Classes/Internal/SEGUserDefaultsStorage.m rename to Analytics/Internal/SEGUserDefaultsStorage.m diff --git a/Analytics/Internal/SEGUtils.h b/Analytics/Internal/SEGUtils.h new file mode 100644 index 000000000..2b067a3fa --- /dev/null +++ b/Analytics/Internal/SEGUtils.h @@ -0,0 +1,82 @@ +// +// SEGUtils.h +// +// + +#import +#import "SEGAnalyticsUtils.h" +#import "SEGSerializableValue.h" + +NS_ASSUME_NONNULL_BEGIN + +@class SEGAnalyticsConfiguration; +@class SEGReachability; + +NS_SWIFT_NAME(Utilities) +@interface SEGUtils : NSObject + ++ (NSData *_Nullable)dataFromPlist:(nonnull id)plist; ++ (id _Nullable)plistFromData:(NSData *)data; + ++ (id _Nullable)traverseJSON:(id _Nullable)object andReplaceWithFilters:(NSDictionary*)patterns; + +@end + +BOOL isUnitTesting(void); + +NSString * _Nullable deviceTokenToString(NSData * _Nullable deviceToken); +NSString *getDeviceModel(void); +BOOL getAdTrackingEnabled(SEGAnalyticsConfiguration *configuration); +NSDictionary *getStaticContext(SEGAnalyticsConfiguration *configuration, NSString * _Nullable deviceToken); +NSDictionary *getLiveContext(SEGReachability *reachability, NSDictionary * _Nullable referrer, NSDictionary * _Nullable traits); + +NSString *GenerateUUIDString(void); + +#if TARGET_OS_IPHONE +NSDictionary *mobileSpecifications(SEGAnalyticsConfiguration *configuration, NSString * _Nullable deviceToken); +#elif TARGET_OS_OSX +NSDictionary *desktopSpecifications(SEGAnalyticsConfiguration *configuration, NSString * _Nullable deviceToken); +#endif + +// Date Utils +NSString *iso8601FormattedString(NSDate *date); +NSString *iso8601NanoFormattedString(NSDate *date); + +void trimQueue(NSMutableArray *array, NSUInteger size); + +// Async Utils +dispatch_queue_t seg_dispatch_queue_create_specific(const char *label, + dispatch_queue_attr_t _Nullable attr); +BOOL seg_dispatch_is_on_specific_queue(dispatch_queue_t queue); +void seg_dispatch_specific(dispatch_queue_t queue, dispatch_block_t block, + BOOL waitForCompletion); +void seg_dispatch_specific_async(dispatch_queue_t queue, + dispatch_block_t block); +void seg_dispatch_specific_sync(dispatch_queue_t queue, dispatch_block_t block); + +// JSON Utils + +JSON_DICT SEGCoerceDictionary(NSDictionary *_Nullable dict); + +NSString *_Nullable SEGIDFA(void); + +NSString *SEGEventNameForScreenTitle(NSString *title); + +@interface NSJSONSerialization (Serializable) ++ (BOOL)isOfSerializableType:(id)obj; +@end + +// Deep copy and check NSCoding conformance +@protocol SEGSerializableDeepCopy +-(id _Nullable) serializableMutableDeepCopy; +-(id _Nullable) serializableDeepCopy; +@end + +@interface NSDictionary(SerializableDeepCopy) +@end + +@interface NSArray(SerializableDeepCopy) +@end + + +NS_ASSUME_NONNULL_END diff --git a/Analytics/Internal/SEGUtils.m b/Analytics/Internal/SEGUtils.m new file mode 100644 index 000000000..602dcdd07 --- /dev/null +++ b/Analytics/Internal/SEGUtils.m @@ -0,0 +1,673 @@ +// +// SEGUtils.m +// +// + +#import "SEGUtils.h" +#import "SEGAnalyticsConfiguration.h" +#import "SEGReachability.h" +#import "SEGAnalytics.h" + +#include + +#if TARGET_OS_IOS && TARGET_OS_MACCATALYST == 0 +#import +#import + +static CTTelephonyNetworkInfo *_telephonyNetworkInfo; +#elif TARGET_OS_OSX +#import +#endif + +// BKS: This doesn't appear to be needed anymore. Will investigate. +//NSString *const SEGADClientClass = @"ADClient"; + +@implementation SEGUtils + ++ (NSData *_Nullable)dataFromPlist:(nonnull id)plist +{ + NSError *error = nil; + NSData *data = [NSPropertyListSerialization dataWithPropertyList:plist + format:NSPropertyListXMLFormat_v1_0 + options:0 + error:&error]; + if (error) { + SEGLog(@"Unable to serialize data from plist object", error, plist); + } + return data; +} + ++ (id _Nullable)plistFromData:(NSData *_Nonnull)data +{ + NSError *error = nil; + id plist = [NSPropertyListSerialization propertyListWithData:data + options:0 + format:nil + error:&error]; + if (error) { + SEGLog(@"Unable to parse plist from data %@", error); + } + return plist; +} + + ++(id)traverseJSON:(id)object andReplaceWithFilters:(NSDictionary*)patterns +{ + if ([object isKindOfClass:NSDictionary.class]) { + NSDictionary* dict = object; + NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:dict.count]; + + for (NSString* key in dict.allKeys) { + newDict[key] = [self traverseJSON:dict[key] andReplaceWithFilters:patterns]; + } + + return newDict; + } + + if ([object isKindOfClass:NSArray.class]) { + NSArray* array = object; + NSMutableArray* newArray = [NSMutableArray arrayWithCapacity:array.count]; + + for (int i = 0; i < array.count; i++) { + newArray[i] = [self traverseJSON:array[i] andReplaceWithFilters:patterns]; + } + + return newArray; + } + + if ([object isKindOfClass:NSString.class]) { + NSError* error = nil; + NSMutableString* str = [object mutableCopy]; + + for (NSString* pattern in patterns) { + NSRegularExpression* re = [NSRegularExpression regularExpressionWithPattern:pattern + options:0 + error:&error]; + + if (error) { + @throw error; + } + + NSInteger matches = [re replaceMatchesInString:str + options:0 + range:NSMakeRange(0, str.length) + withTemplate:patterns[pattern]]; + + if (matches > 0) { + SEGLog(@"%@ Redacted value from action: %@", self, pattern); + } + } + + return str; + } + + return object; +} + +@end + +BOOL isUnitTesting() +{ + static dispatch_once_t pred = 0; + static BOOL _isUnitTesting = NO; + dispatch_once(&pred, ^{ + NSDictionary *env = [NSProcessInfo processInfo].environment; + _isUnitTesting = (env[@"XCTestConfigurationFilePath"] != nil); + }); + return _isUnitTesting; +} + +NSString *deviceTokenToString(NSData *deviceToken) +{ + if (!deviceToken) return nil; + + const unsigned char *buffer = (const unsigned char *)[deviceToken bytes]; + if (!buffer) { + return nil; + } + NSMutableString *token = [NSMutableString stringWithCapacity:(deviceToken.length * 2)]; + for (NSUInteger i = 0; i < deviceToken.length; i++) { + [token appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)buffer[i]]]; + } + return token; +} + +NSString *getDeviceModel() +{ + size_t size; + sysctlbyname("hw.machine", NULL, &size, NULL, 0); + char result[size]; + sysctlbyname("hw.machine", result, &size, NULL, 0); + NSString *results = [NSString stringWithCString:result encoding:NSUTF8StringEncoding]; + return results; +} + +BOOL getAdTrackingEnabled(SEGAnalyticsConfiguration *configuration) +{ + BOOL result = NO; + if ((configuration.adSupportBlock != nil) && (configuration.enableAdvertisingTracking)) { + result = YES; + } + return result; +} + +NSDictionary *getStaticContext(SEGAnalyticsConfiguration *configuration, NSString *deviceToken) +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + + dict[@"library"] = @{ + @"name" : @"analytics-ios", + @"version" : [SEGAnalytics version] + }; + + NSMutableDictionary *infoDictionary = [[[NSBundle mainBundle] infoDictionary] mutableCopy]; + [infoDictionary addEntriesFromDictionary:[[NSBundle mainBundle] localizedInfoDictionary]]; + if (infoDictionary.count) { + dict[@"app"] = @{ + @"name" : infoDictionary[@"CFBundleDisplayName"] ?: @"", + @"version" : infoDictionary[@"CFBundleShortVersionString"] ?: @"", + @"build" : infoDictionary[@"CFBundleVersion"] ?: @"", + @"namespace" : [[NSBundle mainBundle] bundleIdentifier] ?: @"", + }; + } + + NSDictionary *settingsDictionary = nil; +#if TARGET_OS_IPHONE + settingsDictionary = mobileSpecifications(configuration, deviceToken); +#elif TARGET_OS_OSX + settingsDictionary = desktopSpecifications(configuration, deviceToken); +#endif + + if (settingsDictionary != nil) { + dict[@"device"] = settingsDictionary[@"device"]; + dict[@"os"] = settingsDictionary[@"os"]; + dict[@"screen"] = settingsDictionary[@"screen"]; + } + + return dict; +} + +#if TARGET_OS_IPHONE +NSDictionary *mobileSpecifications(SEGAnalyticsConfiguration *configuration, NSString *deviceToken) +{ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + UIDevice *device = [UIDevice currentDevice]; + dict[@"device"] = ({ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + dict[@"manufacturer"] = @"Apple"; +#if TARGET_OS_MACCATALYST + dict[@"type"] = @"macos"; + dict[@"name"] = @"Macintosh"; +#else + dict[@"type"] = @"ios"; + dict[@"name"] = [device model]; +#endif + dict[@"model"] = getDeviceModel(); + dict[@"id"] = [[device identifierForVendor] UUIDString]; + if (getAdTrackingEnabled(configuration)) { + NSString *idfa = configuration.adSupportBlock(); + // This isn't ideal. We're doing this because we can't actually check if IDFA is enabled on + // the customer device. Apple docs and tests show that if it is disabled, one gets back all 0's. + BOOL adTrackingEnabled = (![idfa isEqualToString:@"00000000-0000-0000-0000-000000000000"]); + dict[@"adTrackingEnabled"] = @(adTrackingEnabled); + + if (adTrackingEnabled) { + dict[@"advertisingId"] = idfa; + } + } + if (deviceToken && deviceToken.length > 0) { + dict[@"token"] = deviceToken; + } + dict; + }); + + dict[@"os"] = @{ + @"name" : device.systemName, + @"version" : device.systemVersion + }; + + CGSize screenSize = [UIScreen mainScreen].bounds.size; + dict[@"screen"] = @{ + @"width" : @(screenSize.width), + @"height" : @(screenSize.height) + }; + + // BKS: This bit below doesn't seem to be effective anymore. Will investigate later. + /*#if !(TARGET_IPHONE_SIMULATOR) + Class adClient = NSClassFromString(SEGADClientClass); + if (adClient) { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id sharedClient = [adClient performSelector:NSSelectorFromString(@"sharedClient")]; + #pragma clang diagnostic pop + void (^completionHandler)(BOOL iad) = ^(BOOL iad) { + if (iad) { + dict[@"referrer"] = @{ @"type" : @"iad" }; + } + }; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [sharedClient performSelector:NSSelectorFromString(@"determineAppInstallationAttributionWithCompletionHandler:") + withObject:completionHandler]; + #pragma clang diagnostic pop + } + #endif*/ + + return dict; +} +#endif + +#if TARGET_OS_OSX +NSString *getMacUUID() +{ + char buf[512] = { 0 }; + int bufSize = sizeof(buf); + io_registry_entry_t ioRegistryRoot = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/"); + CFStringRef uuidCf = (CFStringRef) IORegistryEntryCreateCFProperty(ioRegistryRoot, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0); + IOObjectRelease(ioRegistryRoot); + CFStringGetCString(uuidCf, buf, bufSize, kCFStringEncodingMacRoman); + CFRelease(uuidCf); + return [NSString stringWithUTF8String:buf]; +} + +NSDictionary *desktopSpecifications(SEGAnalyticsConfiguration *configuration, NSString *deviceToken) +{ + NSProcessInfo *deviceInfo = [NSProcessInfo processInfo]; + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + dict[@"device"] = ({ + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + dict[@"manufacturer"] = @"Apple"; + dict[@"type"] = @"macos"; + dict[@"model"] = getDeviceModel(); + dict[@"id"] = getMacUUID(); + dict[@"name"] = [deviceInfo hostName]; + + if (getAdTrackingEnabled(configuration)) { + NSString *idfa = configuration.adSupportBlock(); + // This isn't ideal. We're doing this because we can't actually check if IDFA is enabled on + // the customer device. Apple docs and tests show that if it is disabled, one gets back all 0's. + BOOL adTrackingEnabled = (![idfa isEqualToString:@"00000000-0000-0000-0000-000000000000"]); + dict[@"adTrackingEnabled"] = @(adTrackingEnabled); + + if (adTrackingEnabled) { + dict[@"advertisingId"] = idfa; + } + } + if (deviceToken && deviceToken.length > 0) { + dict[@"token"] = deviceToken; + } + dict; + }); + + dict[@"os"] = @{ + @"name" : deviceInfo.operatingSystemVersionString, + @"version" : [NSString stringWithFormat:@"%ld.%ld.%ld", + deviceInfo.operatingSystemVersion.majorVersion, + deviceInfo.operatingSystemVersion.minorVersion, + deviceInfo.operatingSystemVersion.patchVersion] + }; + + CGSize screenSize = [NSScreen mainScreen].frame.size; + dict[@"screen"] = @{ + @"width" : @(screenSize.width), + @"height" : @(screenSize.height) + }; + + return dict; +} + +#endif + +NSDictionary *getLiveContext(SEGReachability *reachability, NSDictionary *referrer, NSDictionary *traits) +{ + NSMutableDictionary *context = [[NSMutableDictionary alloc] init]; + context[@"locale"] = [NSString stringWithFormat: + @"%@-%@", + [NSLocale.currentLocale objectForKey:NSLocaleLanguageCode], + [NSLocale.currentLocale objectForKey:NSLocaleCountryCode]]; + + context[@"timezone"] = [[NSTimeZone localTimeZone] name]; + + context[@"network"] = ({ + NSMutableDictionary *network = [[NSMutableDictionary alloc] init]; + + if (reachability.isReachable) { + network[@"wifi"] = @(reachability.isReachableViaWiFi); + network[@"cellular"] = @(reachability.isReachableViaWWAN); + } + +#if TARGET_OS_IOS && TARGET_OS_MACCATALYST == 0 + static dispatch_once_t networkInfoOnceToken; + dispatch_once(&networkInfoOnceToken, ^{ + _telephonyNetworkInfo = [[CTTelephonyNetworkInfo alloc] init]; + }); + + CTCarrier *carrier = [_telephonyNetworkInfo subscriberCellularProvider]; + if (carrier.carrierName.length) + network[@"carrier"] = carrier.carrierName; +#endif + + network; + }); + + context[@"traits"] = [traits copy]; + + if (referrer) { + context[@"referrer"] = [referrer copy]; + } + + return [context copy]; +} + + +@interface SEGISO8601NanosecondDateFormatter: NSDateFormatter +@end + +@implementation SEGISO8601NanosecondDateFormatter + +- (id)init +{ + self = [super init]; + self.dateFormat = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSS:'Z'"; + self.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + self.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + return self; +} + +const NSInteger __SEG_NANO_MAX_LENGTH = 9; +- (NSString * _Nonnull)stringFromDate:(NSDate *)date +{ + NSCalendar *calendar = [NSCalendar currentCalendar]; + NSDateComponents *dateComponents = [calendar components:NSCalendarUnitSecond | NSCalendarUnitNanosecond fromDate:date]; + NSString *genericDateString = [super stringFromDate:date]; + + NSMutableArray *stringComponents = [[genericDateString componentsSeparatedByString:@"."] mutableCopy]; + NSString *nanoSeconds = [NSString stringWithFormat:@"%li", (long)dateComponents.nanosecond]; + + if (nanoSeconds.length > __SEG_NANO_MAX_LENGTH) { + nanoSeconds = [nanoSeconds substringToIndex:__SEG_NANO_MAX_LENGTH]; + } else { + nanoSeconds = [nanoSeconds stringByPaddingToLength:__SEG_NANO_MAX_LENGTH withString:@"0" startingAtIndex:0]; + } + + NSString *result = [NSString stringWithFormat:@"%@.%@Z", stringComponents[0], nanoSeconds]; + + return result; +} + +@end + + +NSString *GenerateUUIDString() +{ + CFUUIDRef theUUID = CFUUIDCreate(NULL); + NSString *UUIDString = (__bridge_transfer NSString *)CFUUIDCreateString(NULL, theUUID); + CFRelease(theUUID); + return UUIDString; +} + + +// Date Utils +NSString *iso8601NanoFormattedString(NSDate *date) +{ + static NSDateFormatter *dateFormatter; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + dateFormatter = [[SEGISO8601NanosecondDateFormatter alloc] init]; + }); + return [dateFormatter stringFromDate:date]; +} + +NSString *iso8601FormattedString(NSDate *date) +{ + static NSDateFormatter *dateFormatter; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + dateFormatter = [[NSDateFormatter alloc] init]; + dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + dateFormatter.dateFormat = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSS'Z'"; + dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + }); + return [dateFormatter stringFromDate:date]; +} + + +/** trim the queue so that it contains only upto `max` number of elements. */ +void trimQueue(NSMutableArray *queue, NSUInteger max) +{ + if (queue.count < max) { + return; + } + + // Previously we didn't cap the queue. Hence there are cases where + // the queue may already be larger than 1000 events. Delete as many + // events as required to trim the queue size. + NSRange range = NSMakeRange(0, queue.count - max); + [queue removeObjectsInRange:range]; +} + +// Async Utils +dispatch_queue_t +seg_dispatch_queue_create_specific(const char *label, + dispatch_queue_attr_t attr) +{ + dispatch_queue_t queue = dispatch_queue_create(label, attr); + dispatch_queue_set_specific(queue, (__bridge const void *)queue, + (__bridge void *)queue, NULL); + return queue; +} + +BOOL seg_dispatch_is_on_specific_queue(dispatch_queue_t queue) +{ + return dispatch_get_specific((__bridge const void *)queue) != NULL; +} + +void seg_dispatch_specific(dispatch_queue_t queue, dispatch_block_t block, + BOOL waitForCompletion) +{ + dispatch_block_t autoreleasing_block = ^{ + @autoreleasepool + { + block(); + } + }; + if (dispatch_get_specific((__bridge const void *)queue)) { + autoreleasing_block(); + } else if (waitForCompletion) { + dispatch_sync(queue, autoreleasing_block); + } else { + dispatch_async(queue, autoreleasing_block); + } +} + +void seg_dispatch_specific_async(dispatch_queue_t queue, + dispatch_block_t block) +{ + seg_dispatch_specific(queue, block, NO); +} + +void seg_dispatch_specific_sync(dispatch_queue_t queue, + dispatch_block_t block) +{ + seg_dispatch_specific(queue, block, YES); +} + +// JSON Utils + +static id SEGCoerceJSONObject(id obj) +{ + // if the object is a NSString, NSNumber + // then we're good + if ([obj isKindOfClass:[NSString class]] || + [obj isKindOfClass:[NSNumber class]] || + [obj isKindOfClass:[NSNull class]]) { + return obj; + } + + if ([obj isKindOfClass:[NSArray class]]) { + NSMutableArray *array = [NSMutableArray array]; + for (id i in obj) { + NSObject *value = i; + // Hotfix: Storage format should support NSNull instead + if ([value isKindOfClass:[NSNull class]]) { + value = [NSData data]; + } + [array addObject:SEGCoerceJSONObject(value)]; + } + return array; + } + + if ([obj isKindOfClass:[NSDictionary class]]) { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + for (NSString *key in obj) { + NSObject *value = obj[key]; + if (![key isKindOfClass:[NSString class]]) + SEGLog(@"warning: dictionary keys should be strings. got: %@. coercing " + @"to: %@", + [key class], [key description]); + dict[key.description] = SEGCoerceJSONObject(value); + } + return dict; + } + + if ([obj isKindOfClass:[NSDate class]]) + return iso8601FormattedString(obj); + + if ([obj isKindOfClass:[NSURL class]]) + return [obj absoluteString]; + + // default to sending the object's description + SEGLog(@"warning: dictionary values should be valid json types. got: %@. " + @"coercing to: %@", + [obj class], [obj description]); + return [obj description]; +} + +NSDictionary *SEGCoerceDictionary(NSDictionary *dict) +{ + // make sure that a new dictionary exists even if the input is null + dict = dict ?: @{}; + // assert that the proper types are in the dictionary + dict = [dict serializableDeepCopy]; + // coerce urls, and dates to the proper format + return SEGCoerceJSONObject(dict); +} + +NSString *SEGEventNameForScreenTitle(NSString *title) +{ + return [[NSString alloc] initWithFormat:@"Viewed %@ Screen", title]; +} + + +@implementation NSJSONSerialization(Serializable) ++ (BOOL)isOfSerializableType:(id)obj +{ + if ([obj isKindOfClass:[NSArray class]] || + [obj isKindOfClass:[NSDictionary class]] || + [obj isKindOfClass:[NSString class]] || + [obj isKindOfClass:[NSNumber class]] || + [obj isKindOfClass:[NSNull class]]) + return YES; + return NO; +} +@end + + +@implementation NSDictionary(SerializableDeepCopy) + +- (id)serializableDeepCopy:(BOOL)mutable +{ + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:self.count]; + NSArray *keys = [self allKeys]; + for (id key in keys) { + id aValue = [self objectForKey:key]; + id theCopy = nil; + + if (![NSJSONSerialization isOfSerializableType:aValue]) { + NSString *className = NSStringFromClass([aValue class]); +#ifdef DEBUG + NSAssert(FALSE, @"key `%@` is a %@ and can't be serialized for delivery.", key, className); +#else + SEGLog(@"key `%@` is a %@ and can't be serializaed for delivery.", key, className); + // simply leave it out since we can't encode it anyway. + continue; +#endif + } + + if ([aValue conformsToProtocol:@protocol(SEGSerializableDeepCopy)]) { + theCopy = [aValue serializableDeepCopy:mutable]; + } else if ([aValue conformsToProtocol:@protocol(NSCopying)]) { + theCopy = [aValue copy]; + } else { + theCopy = aValue; + } + + [result setValue:theCopy forKey:key]; + } + + if (mutable) { + return result; + } else { + return [result copy]; + } +} + +- (NSDictionary *)serializableDeepCopy { + return [self serializableDeepCopy:NO]; +} + +- (NSMutableDictionary *)serializableMutableDeepCopy { + return [self serializableDeepCopy:YES]; +} + +@end + + +@implementation NSArray(SerializableDeepCopy) + +-(id)serializableDeepCopy:(BOOL)mutable +{ + NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:self.count]; + + for (id aValue in self) { + id theCopy = nil; + + if (![NSJSONSerialization isOfSerializableType:aValue]) { + NSString *className = NSStringFromClass([aValue class]); +#ifdef DEBUG + NSAssert(FALSE, @"found a %@ which can't be serialized for delivery.", className); +#else + SEGLog(@"found a %@ which can't be serializaed for delivery.", className); + // simply leave it out since we can't encode it anyway. + continue; +#endif + } + + if ([aValue conformsToProtocol:@protocol(SEGSerializableDeepCopy)]) { + theCopy = [aValue serializableDeepCopy:mutable]; + } else if ([aValue conformsToProtocol:@protocol(NSCopying)]) { + theCopy = [aValue copy]; + } else { + theCopy = aValue; + } + [result addObject:theCopy]; + } + + if (mutable) { + return result; + } else { + return [result copy]; + } +} + + +- (NSArray *)serializableDeepCopy { + return [self serializableDeepCopy:NO]; +} + +- (NSMutableArray *)serializableMutableDeepCopy { + return [self serializableDeepCopy:YES]; +} + + +@end diff --git a/Analytics/Internal/UIViewController+SEGScreen.h b/Analytics/Internal/UIViewController+SEGScreen.h new file mode 100644 index 000000000..8be5c8565 --- /dev/null +++ b/Analytics/Internal/UIViewController+SEGScreen.h @@ -0,0 +1,13 @@ +#import "SEGSerializableValue.h" + +#if TARGET_OS_IPHONE +#import + +@interface UIViewController (SEGScreen) + ++ (void)seg_swizzleViewDidAppear; ++ (UIViewController *)seg_rootViewControllerFromView:(UIView *)view; + +@end + +#endif diff --git a/Analytics/Internal/UIViewController+SEGScreen.m b/Analytics/Internal/UIViewController+SEGScreen.m new file mode 100644 index 000000000..8fd35623a --- /dev/null +++ b/Analytics/Internal/UIViewController+SEGScreen.m @@ -0,0 +1,124 @@ +#import "UIViewController+SEGScreen.h" +#import +#import "SEGAnalytics.h" +#import "SEGAnalyticsUtils.h" +#import "SEGScreenReporting.h" + + +#if TARGET_OS_IPHONE +@implementation UIViewController (SEGScreen) + ++ (void)seg_swizzleViewDidAppear +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class class = [self class]; + + SEL originalSelector = @selector(viewDidAppear:); + SEL swizzledSelector = @selector(seg_viewDidAppear:); + + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); + + BOOL didAddMethod = + class_addMethod(class, + originalSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + swizzledSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } + }); +} + + ++ (UIViewController *)seg_rootViewControllerFromView:(UIView *)view +{ + UIViewController *root = view.window.rootViewController; + return [self seg_topViewController:root]; +} + ++ (UIViewController *)seg_topViewController:(UIViewController *)rootViewController +{ + UIViewController *nextRootViewController = [self seg_nextRootViewController:rootViewController]; + if (nextRootViewController) { + return [self seg_topViewController:nextRootViewController]; + } + + return rootViewController; +} + ++ (UIViewController *)seg_nextRootViewController:(UIViewController *)rootViewController +{ + UIViewController *presentedViewController = rootViewController.presentedViewController; + if (presentedViewController != nil) { + return presentedViewController; + } + + if ([rootViewController isKindOfClass:[UINavigationController class]]) { + UIViewController *lastViewController = ((UINavigationController *)rootViewController).viewControllers.lastObject; + return lastViewController; + } + + if ([rootViewController isKindOfClass:[UITabBarController class]]) { + __auto_type *currentTabViewController = ((UITabBarController*)rootViewController).selectedViewController; + if (currentTabViewController != nil) { + return currentTabViewController; + } + } + + if (rootViewController.childViewControllers.count > 0) { + if ([rootViewController conformsToProtocol:@protocol(SEGScreenReporting)] && [rootViewController respondsToSelector:@selector(seg_mainViewController)]) { + __auto_type screenReporting = (UIViewController*)rootViewController; + return screenReporting.seg_mainViewController; + } + + // fall back on first child UIViewController as a "best guess" assumption + __auto_type *firstChildViewController = rootViewController.childViewControllers.firstObject; + if (firstChildViewController != nil) { + return firstChildViewController; + } + } + + return nil; +} + +- (void)seg_viewDidAppear:(BOOL)animated +{ + UIViewController *top = [[self class] seg_rootViewControllerFromView:self.view]; + if (!top) { + SEGLog(@"Could not infer screen."); + return; + } + + NSString *name = [[[top class] description] stringByReplacingOccurrencesOfString:@"ViewController" withString:@""]; + + if (!name || name.length == 0) { + // if no class description found, try view controller's title. + name = [top title]; + // Class name could be just "ViewController". + if (name.length == 0) { + SEGLog(@"Could not infer screen name."); + name = @"Unknown"; + } + } + + if ([top conformsToProtocol:@protocol(SEGScreenReporting)] && [top respondsToSelector:@selector(seg_trackScreen:name:)]) { + __auto_type screenReporting = (UIViewController*)top; + [screenReporting seg_trackScreen:top name:name]; + return; + } + + [[SEGAnalytics sharedAnalytics] screen:name properties:nil options:nil]; + + [self seg_viewDidAppear:animated]; +} + +@end +#endif diff --git a/AnalyticsTests/AnalyticsTests-Bridging-Header.h b/AnalyticsTests/AnalyticsTests-Bridging-Header.h index 07afba377..2fb3a9f11 100644 --- a/AnalyticsTests/AnalyticsTests-Bridging-Header.h +++ b/AnalyticsTests/AnalyticsTests-Bridging-Header.h @@ -15,7 +15,5 @@ #import #import "NSData+SEGGUNZIPP.h" -// Temp hack. We should fix the LSNocilla podspec to make this header publicly available -#import "LSMatcher.h" - #import "UIViewController+SegScreenTest.h" +#import "ObjcUtils.h" diff --git a/AnalyticsTests/AnalyticsTests.swift b/AnalyticsTests/AnalyticsTests.swift index 28259ced1..84a952b79 100644 --- a/AnalyticsTests/AnalyticsTests.swift +++ b/AnalyticsTests/AnalyticsTests.swift @@ -7,213 +7,273 @@ // -import Quick -import Nimble -import Analytics +@testable import Analytics +import XCTest -class AnalyticsTests: QuickSpec { - override func spec() { - let config = SEGAnalyticsConfiguration(writeKey: "QUI5ydwIGeFFTa1IvCBUhxL9PyW5B0jE") +class AnalyticsTests: XCTestCase { + + let config = AnalyticsConfiguration(writeKey: "QUI5ydwIGeFFTa1IvCBUhxL9PyW5B0jE") let cachedSettings = [ - "integrations": [ - "Segment.io": ["apiKey": "QUI5ydwIGeFFTa1IvCBUhxL9PyW5B0jE"] - ], - "plan": ["track": [:]], - ] as NSDictionary - var analytics: SEGAnalytics! + "integrations": [ + "Segment.io": ["apiKey": "QUI5ydwIGeFFTa1IvCBUhxL9PyW5B0jE"] + ], + "plan": ["track": [:]], + ] as NSDictionary + var analytics: Analytics! var testMiddleware: TestMiddleware! var testApplication: TestApplication! - beforeEach { - testMiddleware = TestMiddleware() - config.middlewares = [testMiddleware] - testApplication = TestApplication() - config.application = testApplication - config.trackApplicationLifecycleEvents = true + override func setUp() { + super.setUp() + testMiddleware = TestMiddleware() + config.sourceMiddleware = [testMiddleware] + testApplication = TestApplication() + config.application = testApplication + config.trackApplicationLifecycleEvents = true - UserDefaults.standard.set("test SEGQueue should be removed", forKey: "SEGQueue") - expect(UserDefaults.standard.string(forKey: "SEGQueue")).toNot(beNil()) + UserDefaults.standard.set("test SEGQueue should be removed", forKey: "SEGQueue") + XCTAssertNotNil(UserDefaults.standard.string(forKey: "SEGQueue")) - analytics = SEGAnalytics(configuration: config) - analytics.test_integrationsManager()?.test_setCachedSettings(settings: cachedSettings) + analytics = Analytics(configuration: config) + analytics.test_integrationsManager()?.test_setCachedSettings(settings: cachedSettings) } - afterEach { - analytics.reset() + override func tearDown() { + super.tearDown() + analytics.reset() } - it("initialized correctly") { - expect(analytics.configuration.flushAt) == 20 - expect(analytics.configuration.flushInterval) == 30 - expect(analytics.configuration.maxQueueSize) == 1000 - expect(analytics.configuration.writeKey) == "QUI5ydwIGeFFTa1IvCBUhxL9PyW5B0jE" - expect(analytics.configuration.shouldUseLocationServices) == false - expect(analytics.configuration.enableAdvertisingTracking) == true - expect(analytics.configuration.shouldUseBluetooth) == false - expect(analytics.configuration.httpSessionDelegate).to(beNil()) - expect(analytics.getAnonymousId()).toNot(beNil()) + func testInitializedCorrectly() { + XCTAssertEqual(config.flushAt, 20) + XCTAssertEqual(config.flushInterval, 30) + XCTAssertEqual(config.maxQueueSize, 1000) + XCTAssertEqual(config.writeKey, "QUI5ydwIGeFFTa1IvCBUhxL9PyW5B0jE") + XCTAssertEqual(config.shouldUseLocationServices, false) + XCTAssertEqual(config.enableAdvertisingTracking, true) + XCTAssertEqual(config.shouldUseBluetooth, false) + XCTAssertNil(config.httpSessionDelegate) + XCTAssertNotNil(analytics.getAnonymousId()) } - it("clears SEGQueue from UserDefaults after initialized") { - expect(UserDefaults.standard.string(forKey: "SEGQueue")).toEventually(beNil()) + func testClearsSEGQueueFromUserDefaults() { + expectUntil(2.0, expression: UserDefaults.standard.string(forKey: "SEGQueue") == nil) } - it("persists anonymousId") { - let analytics2 = SEGAnalytics(configuration: config) - expect(analytics.getAnonymousId()) == analytics2.getAnonymousId() - } + /* TODO: Fix me when the Context object isn't so wild. + func testCollectsIDFA() { + testMiddleware.swallowEvent = true + analytics.configuration.enableAdvertisingTracking = true + analytics.configuration.adSupportBlock = { () -> String in + return "1234AdsNoMore!" + } - it("persists userId") { - analytics.identify("testUserId1") + analytics.track("test"); - let analytics2 = SEGAnalytics(configuration: config) - analytics2.test_integrationsManager()?.test_setCachedSettings(settings: cachedSettings) + let event = testMiddleware.lastContext?.payload as? TrackPayload + XCTAssertEqual(event?.properties?["url"] as? String, "myapp://auth?token=((redacted/my-auth))&other=stuff") + }*/ - expect(analytics.test_integrationsManager()?.test_segmentIntegration()?.test_userId()) == "testUserId1" - expect(analytics2.test_integrationsManager()?.test_segmentIntegration()?.test_userId()) == "testUserId1" + func testPersistsAnonymousId() { + let analytics2 = Analytics(configuration: config) + XCTAssertEqual(analytics.getAnonymousId(), analytics2.getAnonymousId()) } - /* This test is pretty flaky. - it("continues user activity") { - let activity = NSUserActivity(activityType: NSUserActivityTypeBrowsingWeb) - activity.webpageURL = URL(string: "http://www.segment.com") - analytics.continue(activity) - let referrer = analytics.test_integrationsManager()?.test_segmentIntegration()?.test_referrer() - expect(referrer?["url"] as? String).toEventually(equal("http://www.segment.com")) + func testPersistsUserId() { + analytics.identify("testUserId1") + + let analytics2 = Analytics(configuration: config) + analytics2.test_integrationsManager()?.test_setCachedSettings(settings: cachedSettings) + + XCTAssertEqual(analytics.test_integrationsManager()?.test_segmentIntegration()?.test_userId(), "testUserId1") + XCTAssertEqual(analytics2.test_integrationsManager()?.test_segmentIntegration()?.test_userId(), "testUserId1") } - */ - it("clears user data") { - analytics.identify("testUserId1", traits: [ "Test trait key" : "Test trait value"]) - analytics.reset() - expect(analytics.test_integrationsManager()?.test_segmentIntegration()?.test_userId()).toEventually(beNil()) - expect(analytics.test_integrationsManager()?.test_segmentIntegration()?.test_traits()?.count).toEventually(equal(0)) + func testPersistsTraits() { + analytics.identify("testUserId1", traits: ["trait1": "someTrait"]) + + let analytics2 = Analytics(configuration: config) + analytics2.test_integrationsManager()?.test_setCachedSettings(settings: cachedSettings) + + XCTAssertEqual(analytics.test_integrationsManager()?.test_segmentIntegration()?.test_userId(), "testUserId1") + XCTAssertEqual(analytics2.test_integrationsManager()?.test_segmentIntegration()?.test_userId(), "testUserId1") + + var traits = analytics.test_integrationsManager()?.test_segmentIntegration()?.test_traits() + var storedTraits = analytics2.test_integrationsManager()?.test_segmentIntegration()?.test_traits() + + if let trait1 = traits?["trait1"] as? String { + XCTAssertEqual(trait1, "someTrait") + } else { + XCTAssert(false, "Traits are nil!") + } + + if let storedTrait1 = storedTraits?["trait1"] as? String { + XCTAssertEqual(storedTrait1, "someTrait") + } else { + XCTAssert(false, "Traits were not stored!") + } + + analytics.identify("testUserId1", traits: ["trait2": "someOtherTrait"]) + + traits = analytics.test_integrationsManager()?.test_segmentIntegration()?.test_traits() + storedTraits = analytics2.test_integrationsManager()?.test_segmentIntegration()?.test_traits() + + if let trait1 = traits?["trait2"] as? String { + XCTAssertEqual(trait1, "someOtherTrait") + } else { + XCTAssert(false, "Traits are nil!") + } + + if let storedTrait1 = storedTraits?["trait2"] as? String { + XCTAssertEqual(storedTrait1, "someOtherTrait") + } else { + XCTAssert(false, "Traits were not stored!") + } + + } - it("fires Application Opened for UIApplicationDidFinishLaunching") { - testMiddleware.swallowEvent = true - NotificationCenter.default.post(name: .UIApplicationDidFinishLaunching, object: testApplication, userInfo: [ - UIApplicationLaunchOptionsKey.sourceApplication: "testApp", - UIApplicationLaunchOptionsKey.url: "test://test", - ]) - let event = testMiddleware.lastContext?.payload as? SEGTrackPayload - expect(event?.event) == "Application Opened" - expect(event?.properties?["from_background"] as? Bool) == false - expect(event?.properties?["referring_application"] as? String) == "testApp" - expect(event?.properties?["url"] as? String) == "test://test" + func testClearsUserData() { + analytics.identify("testUserId1", traits: [ "Test trait key" : "Test trait value"]) + analytics.reset() + + expectUntil(2.0, expression: self.analytics.test_integrationsManager()?.test_segmentIntegration()?.test_userId() == nil) + + expectUntil(2.0, expression: self.analytics.test_integrationsManager()?.test_segmentIntegration()?.test_traits()?.count == 0) } - it("fires Application Opened during UIApplicationWillEnterForeground") { - testMiddleware.swallowEvent = true - NotificationCenter.default.post(name: .UIApplicationWillEnterForeground, object: testApplication) - let event = testMiddleware.lastContext?.payload as? SEGTrackPayload - expect(event?.event) == "Application Opened" - expect(event?.properties?["from_background"] as? Bool) == true + func testFiresApplicationOpenedForAppLaunchingEvent() { + testMiddleware.swallowEvent = true + NotificationCenter.default.post(name: UIApplication.didFinishLaunchingNotification, object: testApplication, userInfo: [ + UIApplication.LaunchOptionsKey.sourceApplication: "testApp", + UIApplication.LaunchOptionsKey.url: "test://test", + ]) + let event = testMiddleware.lastContext?.payload as? TrackPayload + XCTAssertEqual(event?.event, "Application Opened") + XCTAssertEqual(event?.properties?["from_background"] as? Bool, false) + XCTAssertEqual(event?.properties?["referring_application"] as? String, "testApp") + XCTAssertEqual(event?.properties?["url"] as? String, "test://test") } - it("fires Application Backgrounded during UIApplicationDidEnterBackground") { - testMiddleware.swallowEvent = true - NotificationCenter.default.post(name: .UIApplicationDidEnterBackground, object: testApplication) - let event = testMiddleware.lastContext?.payload as? SEGTrackPayload - expect(event?.event) == "Application Backgrounded" + func testFiresApplicationEnterForeground() { + testMiddleware.swallowEvent = true + NotificationCenter.default.post(name: UIApplication.willEnterForegroundNotification, object: testApplication) + let event = testMiddleware.lastContext?.payload as? TrackPayload + XCTAssertEqual(event?.event, "Application Opened") + XCTAssertEqual(event?.properties?["from_background"] as? Bool, true) } - it("flushes when UIApplicationDidEnterBackgroundNotification is fired") { - analytics.track("test") - NotificationCenter.default.post(name: .UIApplicationDidEnterBackground, object: testApplication) - expect(testApplication.backgroundTasks.count).toEventually(equal(1)) - expect(testApplication.backgroundTasks[0].isEnded).toEventually(beFalse()) + func testFiresApplicationDuringEnterBackground() { + testMiddleware.swallowEvent = true + NotificationCenter.default.post(name: UIApplication.didEnterBackgroundNotification, object: testApplication) + let event = testMiddleware.lastContext?.payload as? TrackPayload + XCTAssertEqual(event?.event, "Application Backgrounded") } - it("respects maxQueueSize") { - let max = 72 - config.maxQueueSize = UInt(max) + func testFlushesWhenApplicationBackgroundIsFired() { + analytics.track("test") + NotificationCenter.default.post(name: UIApplication.didEnterBackgroundNotification, object: testApplication) - for i in 1...max * 2 { - analytics.track("test #\(i)") - } + expectUntil(2.0, expression: self.testApplication.backgroundTasks.count == 1) + expectUntil(2.0, expression: self.testApplication.backgroundTasks[0].isEnded == false) + } - let integration = analytics.test_integrationsManager()?.test_segmentIntegration() - expect(integration).notTo(beNil()) + func testRespectsMaxQueueSize() { + let max = 72 + config.maxQueueSize = UInt(max) - analytics.flush() - waitUntil(timeout: 60) {done in - let queue = DispatchQueue(label: "test") + for i in 1...max * 2 { + analytics.track("test #\(i)") + } - queue.async { - while(integration?.test_queue()?.count != max) { - sleep(1) - } + let integration = analytics.test_integrationsManager()?.test_segmentIntegration() + XCTAssertNotNil(integration) - done() + analytics.flush() + let currentTime = Date() + while(integration?.test_queue()?.count != max && currentTime < currentTime + 60) { + sleep(1) } - } } - it("protocol conformance should not interfere with UIApplication interface") { - // In Xcode8/iOS10, UIApplication.h typedefs UIBackgroundTaskIdentifier as NSUInteger, - // whereas Swift has UIBackgroundTaskIdentifier typealiaed to Int. - // This is likely due to a custom Swift mapping for UIApplication which got out of sync. - // If we extract the exact UIApplication method names in SEGApplicationProtocol, - // it will cause a type mismatch between the return value from beginBackgroundTask - // and the argument for endBackgroundTask. - // This would impact all code in a project that imports the Segment framework. - // Note that this doesn't appear to be an issue any longer in Xcode9b3. - let task = UIApplication.shared.beginBackgroundTask(expirationHandler: nil) - UIApplication.shared.endBackgroundTask(task) + func testProtocolConformanceShouldNotInterfere() { + // In Xcode8/iOS10, UIApplication.h typedefs UIBackgroundTaskIdentifier as NSUInteger, + // whereas Swift has UIBackgroundTaskIdentifier typealiaed to Int. + // This is likely due to a custom Swift mapping for UIApplication which got out of sync. + // If we extract the exact UIApplication method names in SEGApplicationProtocol, + // it will cause a type mismatch between the return value from beginBackgroundTask + // and the argument for endBackgroundTask. + // This would impact all code in a project that imports the Segment framework. + // Note that this doesn't appear to be an issue any longer in Xcode9b3. + let task = UIApplication.shared.beginBackgroundTask(expirationHandler: nil) + UIApplication.shared.endBackgroundTask(task) } - it("flushes using flushTimer") { - let integration = analytics.test_integrationsManager()?.test_segmentIntegration() - - analytics.track("test") + func testFlushesUsingFlushTimer() { + let integration = analytics.test_integrationsManager()?.test_segmentIntegration() - expect(integration?.test_flushTimer()).toEventuallyNot(beNil()) - expect(integration?.test_batchRequest()).to(beNil()) + analytics.track("test") - integration?.test_flushTimer()?.fire() + expectUntil(2.0, expression: integration?.test_flushTimer() != nil) + XCTAssertNil(integration?.test_batchRequest()) - expect(integration?.test_batchRequest()).toEventuallyNot(beNil()) + integration?.test_flushTimer()?.fire() + expectUntil(2.0, expression: integration?.test_batchRequest() != nil) } - it("respects flushInterval") { - let timer = analytics - .test_integrationsManager()? - .test_segmentIntegration()? - .test_flushTimer() + func testRespectsFlushIntervale() { + let timer = analytics + .test_integrationsManager()? + .test_segmentIntegration()? + .test_flushTimer() - expect(timer).toNot(beNil()) - expect(timer?.timeInterval) == config.flushInterval + XCTAssertNotNil(timer) + XCTAssertEqual(timer?.timeInterval, config.flushInterval) } - it("redacts sensible URLs from deep links tracking") { - testMiddleware.swallowEvent = true - analytics.configuration.trackDeepLinks = true - analytics.open(URL(string: "fb123456789://authorize#access_token=hastoberedacted")!, options: [:]) + func testRedactsSensibleURLsFromDeepLinksTracking() { + testMiddleware.swallowEvent = true + config.trackDeepLinks = true + analytics.open(URL(string: "fb123456789://authorize#access_token=hastoberedacted")!, options: [:]) - let event = testMiddleware.lastContext?.payload as? SEGTrackPayload - expect(event?.event) == "Deep Link Opened" - expect(event?.properties?["url"] as? String) == "fb123456789://authorize#access_token=((redacted/fb-auth-token))" + let event = testMiddleware.lastContext?.payload as? TrackPayload + XCTAssertEqual(event?.event, "Deep Link Opened") + XCTAssertEqual(event?.properties?["url"] as? String, "fb123456789://authorize#access_token=((redacted/fb-auth-token))") } - it("redacts sensible URLs from deep links tracking using custom filters") { - testMiddleware.swallowEvent = true - analytics.configuration.payloadFilters["(myapp://auth\\?token=)([^&]+)"] = "$1((redacted/my-auth))" - analytics.configuration.trackDeepLinks = true - analytics.open(URL(string: "myapp://auth?token=hastoberedacted&other=stuff")!, options: [:]) + func testRedactsSensibleURLsFromDeepLinksWithFilters() { + testMiddleware.swallowEvent = true + config.payloadFilters["(myapp://auth\\?token=)([^&]+)"] = "$1((redacted/my-auth))" + config.trackDeepLinks = true + analytics.open(URL(string: "myapp://auth?token=hastoberedacted&other=stuff")!, options: [:]) - let event = testMiddleware.lastContext?.payload as? SEGTrackPayload - expect(event?.event) == "Deep Link Opened" - expect(event?.properties?["url"] as? String) == "myapp://auth?token=((redacted/my-auth))&other=stuff" + let event = testMiddleware.lastContext?.payload as? TrackPayload + XCTAssertEqual(event?.event, "Deep Link Opened") + XCTAssertEqual(event?.properties?["url"] as? String, "myapp://auth?token=((redacted/my-auth))&other=stuff") + } + + func testDefaultsSEGQueueToEmptyArray() { + let integration = analytics.test_integrationsManager()?.test_segmentIntegration() + XCTAssertNotNil(integration) + integration?.test_fileStorage()?.resetAll() + XCTAssert(integration?.test_queue()?.isEmpty ?? false) } - it("defaults SEGQueue to an empty array when missing from file storage") { - let integration = analytics.test_integrationsManager()?.test_segmentIntegration() - expect(integration).notTo(beNil()) - integration?.test_fileStorage()?.resetAll() - expect(integration?.test_queue()).to(beEmpty()) + func testDeviceTokenRegistration() { + func getStringFrom(token: Data) -> String { + return token.reduce("") { $0 + String(format: "%02.2hhx", $1) } + } + + let deviceToken = GenerateUUIDString() + let data = deviceToken.data(using: .utf8) + if let data = data { + analytics.registeredForRemoteNotifications(withDeviceToken: data) + let deviceTokenString = getStringFrom(token: data) + XCTAssertTrue(deviceTokenString == analytics.getDeviceToken()) + + } else { + XCTAssertNotNil(data) + } } - } } diff --git a/AnalyticsTests/AnalyticsUtilTests.swift b/AnalyticsTests/AnalyticsUtilTests.swift index 8510f3913..a197e07f5 100644 --- a/AnalyticsTests/AnalyticsUtilTests.swift +++ b/AnalyticsTests/AnalyticsUtilTests.swift @@ -7,134 +7,127 @@ // -import Quick -import Nimble import Analytics +import XCTest -class AnalyticsUtilTests: QuickSpec { - override func spec() { - - it("format NSDate objects to RFC 3339 complaint string") { - let date = Date(timeIntervalSince1970: 0) - let formattedString = iso8601FormattedString(date) - expect(formattedString) == "1970-01-01T00:00:00.000Z" - - var components = DateComponents() - components.year = 1992 - components.month = 8 - components.day = 6 - components.hour = 7 - components.minute = 32 - components.second = 4 - components.nanosecond = 335000000 - let calendar = NSCalendar(calendarIdentifier: .gregorian)! - calendar.timeZone = TimeZone(secondsFromGMT: -4 * 60 * 60)! - let date2 = calendar.date(from: components)! - let formattedString2 = iso8601FormattedString(date2) - expect(formattedString2) == "1992-08-06T11:32:04.335Z" +class AnalyticsUtilTests: XCTestCase { + + let filters = [ + "(foo)": "$1-bar" + ] + + func equals(a: Any, b: Any) -> Bool { + let aData = try! JSONSerialization.data(withJSONObject: a, options: .prettyPrinted) as NSData + let bData = try! JSONSerialization.data(withJSONObject: b, options: .prettyPrinted) + + return aData.isEqual(to: bData) } - it("format NSDate objects to RFC 3339 complaint string w/ nanoseconds") { - let date = Date(timeIntervalSince1970: 0) - let formattedString = iso8601NanoFormattedString(date) - expect(formattedString) == "1970-01-01T00:00:00.000000000Z" - - var components = DateComponents() - components.year = 1992 - components.month = 8 - components.day = 6 - components.hour = 7 - components.minute = 32 - components.second = 4 - components.nanosecond = 335000008 - let calendar = NSCalendar(calendarIdentifier: .gregorian)! - calendar.timeZone = TimeZone(secondsFromGMT: -4 * 60 * 60)! - let date2 = calendar.date(from: components)! - let formattedString2 = iso8601NanoFormattedString(date2) - expect(formattedString2) == "1992-08-06T11:32:04.335000008Z" + func testFormatNSDateObjects() { + let date = Date(timeIntervalSince1970: 0) + let formattedString = iso8601FormattedString(date) + XCTAssertEqual(formattedString, "1970-01-01T00:00:00.000Z") + + var components = DateComponents() + components.year = 1992 + components.month = 8 + components.day = 6 + components.hour = 7 + components.minute = 32 + components.second = 4 + components.nanosecond = 335000000 + let calendar = NSCalendar(calendarIdentifier: .gregorian)! + calendar.timeZone = TimeZone(secondsFromGMT: -4 * 60 * 60)! + let date2 = calendar.date(from: components)! + let formattedString2 = iso8601FormattedString(date2) + XCTAssertEqual(formattedString2, "1992-08-06T11:32:04.335Z") + } + + func testFormatNSDateRFC3339() { + let date = Date(timeIntervalSince1970: 0) + let formattedString = iso8601NanoFormattedString(date) + XCTAssertEqual(formattedString, "1970-01-01T00:00:00.000000000Z") + + var components = DateComponents() + components.year = 1992 + components.month = 8 + components.day = 6 + components.hour = 7 + components.minute = 32 + components.second = 4 + components.nanosecond = 335000008 + let calendar = NSCalendar(calendarIdentifier: .gregorian)! + calendar.timeZone = TimeZone(secondsFromGMT: -4 * 60 * 60)! + let date2 = calendar.date(from: components)! + let formattedString2 = iso8601NanoFormattedString(date2) + XCTAssertEqual(formattedString2, "1992-08-06T11:32:04.335000008Z") } - describe("trimQueue", { - it("does nothing when count < max") { + func testTrimQueueDoesNothingCountLessThan() { let queue = NSMutableArray(array: []) for i in 1...4 { - queue.add(i) + queue.add(i) } trimQueue(queue, 5) - expect(queue) == [1, 2, 3, 4] - } + XCTAssertEqual(queue, [1, 2, 3, 4]) + } - it("trims when count > max") { + func testTrimQueueWhenCountGreaterThan() { let queue = NSMutableArray(array: []) for i in 1...10 { - queue.add(i) + queue.add(i) } trimQueue(queue, 5) - expect(queue) == [6, 7, 8, 9, 10] - } + XCTAssertEqual(queue, [6, 7, 8, 9, 10]) + } - it("does not trim when count == max") { + func testTrimQueueWhenCountEqual() { let queue = NSMutableArray(array: []) for i in 1...5 { - queue.add(i) + queue.add(i) } trimQueue(queue, 5) - expect(queue) == [1, 2, 3, 4, 5] - } - }) - - describe("JSON traverse", { - let filters = [ - "(foo)": "$1-bar" - ] - - func equals(a: Any, b: Any) -> Bool { - let aData = try! JSONSerialization.data(withJSONObject: a, options: .prettyPrinted) as NSData - let bData = try! JSONSerialization.data(withJSONObject: b, options: .prettyPrinted) - - return aData.isEqual(to: bData) - } + XCTAssertEqual(queue, [1, 2, 3, 4, 5]) + } - it("works with strings") { - expect(SEGUtils.traverseJSON("a b foo c", andReplaceWithFilters: filters) as? String) == "a b foo-bar c" - } + func testJSONTraverseWithStrings() { + XCTAssertEqual(Utilities.traverseJSON("a b foo c", andReplaceWithFilters: filters) as? String, "a b foo-bar c") + } + + func testJSONTraverseRecursively() { + XCTAssertEqual(Utilities.traverseJSON("a b foo foo c", andReplaceWithFilters: filters) as? String, "a b foo-bar foo-bar c") + } - it("works recursively") { - expect(SEGUtils.traverseJSON("a b foo foo c", andReplaceWithFilters: filters) as? String) == "a b foo-bar foo-bar c" - } - - it("works with nested dictionaries") { + func testJSONWorksNestedDictionaries() { let data = [ - "foo": [1, nil, "qfoob", ["baz": "foo"]], - "bar": "foo" - ] as [String: Any] - - guard let input = SEGUtils.traverseJSON(data, andReplaceWithFilters: filters) as? [String: Any] else { - XCTFail("Failed to create actual result from traversed JSON replace") - return + "foo": [1, nil, "qfoob", ["baz": "foo"]], + "bar": "foo" + ] as [String: Any] + + guard let input = Utilities.traverseJSON(data, andReplaceWithFilters: filters) as? [String: Any] else { + XCTFail("Failed to create actual result from traversed JSON replace") + return } - + let output = [ - "foo": [1, nil, "qfoo-barb", ["baz": "foo-bar"]], - "bar": "foo-bar" - ] as [String: Any] - - expect(NSDictionary(dictionary: output).isEqual(to: input)) == true - } - - it("works with nested arrays") { + "foo": [1, nil, "qfoo-barb", ["baz": "foo-bar"]], + "bar": "foo-bar" + ] as [String: Any] + + XCTAssertEqual(NSDictionary(dictionary: output).isEqual(to: input), true) + } + + func testJSONWorksNestedArrays() { let data = [ - [1, nil, "qfoob", ["baz": "foo"]], - "foo" - ] as [Any] - let input = SEGUtils.traverseJSON(data, andReplaceWithFilters: filters) + [1, nil, "qfoob", ["baz": "foo"]], + "foo" + ] as [Any] + let input = Utilities.traverseJSON(data, andReplaceWithFilters: filters) let output = [ - [1, nil, "qfoo-barb", ["baz": "foo-bar"]], - "foo-bar" - ] as [Any] - - expect(equals(a: input!, b: output)) == true - } - }) - } + [1, nil, "qfoo-barb", ["baz": "foo-bar"]], + "foo-bar" + ] as [Any] + + XCTAssertEqual(equals(a: input!, b: output), true) + } } diff --git a/AnalyticsTests/AutoScreenReportingTest.swift b/AnalyticsTests/AutoScreenReportingTest.swift index 2bb715f87..88567c343 100644 --- a/AnalyticsTests/AutoScreenReportingTest.swift +++ b/AnalyticsTests/AutoScreenReportingTest.swift @@ -4,133 +4,90 @@ // import Foundation -import Quick -import Nimble -import SwiftTryCatch @testable import Analytics +import XCTest -class AutoScreenReportingTests: QuickSpec { - - override func spec() { +class AutoScreenReportingTests: XCTestCase { var window: UIWindow! var rootVC: UIViewController! - beforeEach { - let config = SEGAnalyticsConfiguration(writeKey: "foobar") - config.trackApplicationLifecycleEvents = true - config.recordScreenViews = true - - window = UIWindow() - rootVC = UIViewController() - window.addSubview(rootVC.view) - } + override func setUp() { + super.setUp() + let config = AnalyticsConfiguration(writeKey: "foobar") + config.trackApplicationLifecycleEvents = true + config.recordScreenViews = true - describe("given a single view controller") { + window = UIWindow() + rootVC = UIViewController() + window.addSubview(rootVC.view) + } - it("seg_topViewController returns that view controller") { + func testTopViewControllerReturnController() { let actualVC = UIViewController.seg_topViewController(rootVC) - expect(actualVC) === rootVC - } + XCTAssertEqual(actualVC, rootVC) } - describe("given a presented view controller") { - - var expectedVC: UIViewController! - - beforeEach { + func testTopViewControllerReturnsPresentedController() { + var expectedVC: UIViewController! expectedVC = UIViewController() rootVC.present(expectedVC, animated: false) - } - - it("seg_topViewController returns the presented view controller") { let actualVC = UIViewController.seg_topViewController(rootVC) - expect(actualVC) === expectedVC - } - } - - describe("given a pushed view controller") { + XCTAssertEqual(actualVC, expectedVC) - var expectedVC: UIViewController! + } - beforeEach { + func testTopViewControllerReturnsPushedViewController() { + var expectedVC: UIViewController! expectedVC = UIViewController() let nc = UINavigationController() rootVC.present(nc, animated: false) nc.pushViewController(expectedVC, animated: false) - } - - it("seg_topViewController returns the pushed view controller") { let actualVC = UIViewController.seg_topViewController(rootVC) - expect(actualVC) === expectedVC - } + XCTAssertEqual(actualVC, expectedVC) } - describe("given a child of a UITabBarController") { - - var expectedVC: UIViewController! - - beforeEach { + func testTopViewControllerTeturnsCurrentSelectedController() { + var expectedVC: UIViewController! expectedVC = UIViewController() let tabBarController = UITabBarController() rootVC.present(tabBarController, animated: false) tabBarController.viewControllers = [UIViewController(), expectedVC, UIViewController()] tabBarController.selectedIndex = 1 - } - - it("seg_topViewController returns the currently selected view controller") { let actualVC = UIViewController.seg_topViewController(rootVC) - expect(actualVC) === expectedVC - } + XCTAssertEqual(actualVC, expectedVC) } - describe("given a child of a custom container view controller conforming to SEGScreenReporting") { - - class CustomContainerViewController: UIViewController, SEGScreenReporting { - var selectedIndex: Int = 0 - var seg_mainViewController: UIViewController? { - return childViewControllers[selectedIndex] + func testTopViewControllerReturnsCurrentSelectedViewController() { + class CustomContainerViewController: UIViewController, SEGScreenReporting { + var selectedIndex: Int = 0 + var seg_mainViewController: UIViewController? { + return children[selectedIndex] + } } - } - - var expectedVC: UIViewController! - beforeEach { + var expectedVC: UIViewController! expectedVC = UIViewController() let containerVC = CustomContainerViewController() rootVC.present(containerVC, animated: false) [UIViewController(), expectedVC, UIViewController()].forEach { child in - containerVC.addChildViewController(child) + containerVC.addChild(child) } containerVC.selectedIndex = 1 - } - - it("seg_topViewController returns the currently selected view controller") { let actualVC = UIViewController.seg_topViewController(rootVC) - expect(actualVC) === expectedVC - } + XCTAssertEqual(actualVC, expectedVC) } - describe("given a child of a container view controller NOT conforming to SEGScreenReporting") { - - var expectedVC: UIViewController! - - beforeEach { + func testTopViewControllerReturnsChildViewController() { + var expectedVC: UIViewController! expectedVC = UIViewController() let containerVC = UIViewController() rootVC.present(containerVC, animated: false) [expectedVC, UIViewController(), UIViewController()].forEach { child in - containerVC.addChildViewController(child) + containerVC.addChild(child) } - } - - it("seg_topViewController returns the first child view controller") { let actualVC = UIViewController.seg_topViewController(rootVC) - expect(actualVC) === expectedVC - } + XCTAssertEqual(actualVC, expectedVC) } - } } - - diff --git a/AnalyticsTests/ContextTest.swift b/AnalyticsTests/ContextTest.swift index 58822175a..653bc2caf 100644 --- a/AnalyticsTests/ContextTest.swift +++ b/AnalyticsTests/ContextTest.swift @@ -6,82 +6,76 @@ // Copyright © 2016 Segment. All rights reserved. // -import Quick -import Nimble -import SwiftTryCatch import Analytics +import XCTest -class ContextTests: QuickSpec { - override func spec() { +class ContextTests: XCTestCase { - var analytics: SEGAnalytics! + var analytics: Analytics! - beforeEach { - let config = SEGAnalyticsConfiguration(writeKey: "foobar") - analytics = SEGAnalytics(configuration: config) + override func setUp() { + super.setUp() + let config = AnalyticsConfiguration(writeKey: "foobar") + analytics = Analytics(configuration: config) } - it("throws when used incorrectly") { - var context: SEGContext? - var exception: NSException? - - SwiftTryCatch.tryRun({ - context = SEGContext() - }, catchRun: { e in - exception = e - }, finallyRun: nil) - - expect(context).to(beNil()) - expect(exception).toNot(beNil()) + func testThrowsWhenUsedIncorrectly() { + var context: Context? + var exception: NSException? + + exception = objc_tryCatch { + context = Context() + } + + XCTAssertNil(context) + XCTAssertNotNil(exception) } - - it("initialized correctly") { - let context = SEGContext(analytics: analytics) - expect(context._analytics) == analytics - expect(context.eventType) == SEGEventType.undefined + func testInitializedCorrectly() { + let context = Context(analytics: analytics) + XCTAssertEqual(context._analytics, analytics) + XCTAssertEqual(context.eventType, EventType.undefined) } - it("accepts modifications") { - let context = SEGContext(analytics: analytics) - - let newContext = context.modify { context in - context.userId = "sloth" - context.eventType = .track; - } - expect(newContext.userId) == "sloth" - expect(newContext.eventType) == SEGEventType.track; - + func testAcceptsModifications() { + let context = Context(analytics: analytics) + + let newContext = context.modify { context in + context.payload = TrackPayload() + context.payload?.userId = "sloth" + context.eventType = .track + } + XCTAssertEqual(newContext.payload?.userId, "sloth") + XCTAssertEqual(newContext.eventType, EventType.track) } - it("modifies copy in debug mode to catch bugs") { - let context = SEGContext(analytics: analytics).modify { context in - context.debug = true - } - expect(context.debug) == true - - let newContext = context.modify { context in - context.userId = "123" - } - expect(context) !== newContext - expect(newContext.userId) == "123" - expect(context.userId).to(beNil()) + func testModifiesCopyInDebugMode() { + let context = Context(analytics: analytics).modify { context in + context.debug = true + context.eventType = .track + } + XCTAssertEqual(context.debug, true) + + let newContext = context.modify { context in + context.eventType = .identify + } + XCTAssertNotEqual(context, newContext) + XCTAssertEqual(newContext.eventType, .identify) + XCTAssertEqual(context.eventType, .track) } - it("modifies self in non-debug mode to optimize perf.") { - let context = SEGContext(analytics: analytics).modify { context in - context.debug = false - } - expect(context.debug) == false - - let newContext = context.modify { context in - context.userId = "123" - } - expect(context) === newContext - expect(newContext.userId) == "123" - expect(context.userId) == "123" + func testModifiesSelfInNonDebug() { + let context = Context(analytics: analytics).modify { context in + context.debug = false + context.eventType = .track + } + XCTAssertFalse(context.debug) + + let newContext = context.modify { context in + context.eventType = .identify + } + XCTAssertEqual(context, newContext) + XCTAssertEqual(newContext.eventType, .identify) + XCTAssertEqual(context.eventType, .identify) } - - } - } diff --git a/AnalyticsTests/CryptoTest.swift b/AnalyticsTests/CryptoTest.swift index b56cddf22..053e4f05e 100644 --- a/AnalyticsTests/CryptoTest.swift +++ b/AnalyticsTests/CryptoTest.swift @@ -5,57 +5,57 @@ // Copyright © 2016 Segment. All rights reserved. // -import Quick -import Nimble import Analytics +import XCTest -class CryptoTest : QuickSpec { - override func spec() { - var crypto : SEGAES256Crypto! - beforeEach { - crypto = SEGAES256Crypto(password: "slothysloth") +class CryptoTest : XCTestCase { + + var crypto: AES256Crypto! + override func setUp() { + super.setUp() + crypto = AES256Crypto(password: "slothysloth") } - it("encrypts and decrypts data") { - let strIn = "segment" - let dataIn = strIn.data(using: String.Encoding.utf8)! - let encryptedData = crypto.encrypt(dataIn) - expect(encryptedData).toNot(beNil()) - - let dataOut = crypto.decrypt(encryptedData!) - expect(dataOut) == dataIn - - let strOut = String(data: dataOut!, encoding: String.Encoding.utf8) - expect(strOut) == "segment" + func testEncryptDecryptSuccess() { + let strIn = "segment" + let dataIn = strIn.data(using: String.Encoding.utf8)! + let encryptedData = crypto.encrypt(dataIn) + XCTAssert(encryptedData != nil, "Encrypted data should not be nil") + + let dataOut = crypto.decrypt(encryptedData!) + XCTAssert(dataOut == dataIn, "Data should be the same") + + let strOut = String(data: dataOut!, encoding: String.Encoding.utf8) + XCTAssertEqual(strOut, "segment", "Strings should be the same") } - it("fails for incorrect password") { - let strIn = "segment" - let dataIn = strIn.data(using: String.Encoding.utf8)! - let encryptedData = crypto.encrypt(dataIn) - expect(encryptedData).toNot(beNil()) - - let crypto2 = SEGAES256Crypto(password: "wolf", salt: crypto.salt, iv: crypto.iv) - let dataOut = crypto2.decrypt(encryptedData!) - expect(dataOut) != dataIn - let strOut = String(data: dataOut!, encoding: String.Encoding.utf8) - // no built in way to check password correctness - // http://stackoverflow.com/questions/27712173/determine-if-key-is-incorrect-with-cccrypt-kccoptionpkcs7padding-objective-c - expect(strOut ?? "") != strIn + func testIncorrectPassword() { + let strIn = "segment" + let dataIn = strIn.data(using: String.Encoding.utf8)! + let encryptedData = crypto.encrypt(dataIn) + XCTAssert(encryptedData != nil, "Encrypted data should not be nil") + + let crypto2 = AES256Crypto(password: "wolf", salt: crypto.salt, iv: crypto.iv) + let dataOut = crypto2.decrypt(encryptedData!) + XCTAssertNotEqual(dataOut, dataIn, "In and out should not match") + + let strOut = String(data: dataOut!, encoding: String.Encoding.utf8) + // no built in way to check password correctness + // http://stackoverflow.com/questions/27712173/determine-if-key-is-incorrect-with-cccrypt-kccoptionpkcs7padding-objective-c + XCTAssertNotEqual(strOut ?? "", strIn, "String in and out should not match") } - it("fails for incorrect iv and sault") { - let strIn = "segment" - let dataIn = strIn.data(using: String.Encoding.utf8)! - let encryptedData = crypto.encrypt(dataIn) - expect(encryptedData).toNot(beNil()) - - let crypto2 = SEGAES256Crypto(password: crypto.password) - let dataOut = crypto2.decrypt(encryptedData!) - expect(dataOut) != dataIn - - let strOut = String(data: dataOut!, encoding: String.Encoding.utf8) - expect(strOut ?? "") != strIn + func testFailureForIVAndSault() { + let strIn = "segment" + let dataIn = strIn.data(using: String.Encoding.utf8)! + let encryptedData = crypto.encrypt(dataIn) + XCTAssertNotNil(encryptedData, "Encrypted data should not be nil") + + let crypto2 = AES256Crypto(password: crypto.password) + let dataOut = crypto2.decrypt(encryptedData!) + XCTAssertNotEqual(dataOut, dataIn, "Out and In data should not match") + + let strOut = String(data: dataOut!, encoding: String.Encoding.utf8) + XCTAssertNotEqual(strOut ?? "", strIn, "Out and In strings should not match") } - } } diff --git a/AnalyticsTests/EndToEndTests.swift b/AnalyticsTests/EndToEndTests.swift index 5f787342e..c597b5cda 100644 --- a/AnalyticsTests/EndToEndTests.swift +++ b/AnalyticsTests/EndToEndTests.swift @@ -1,80 +1,43 @@ -import Quick -import Nimble -import Analytics -import Alamofire -import Alamofire_Synchronous - -func hasMatchingId(messageId: String) -> Bool { - // End to End tests require some private credentials, so we can't embed them in source. - // On CI, we inject these values with build settings (see Makefile test task). - let runE2E = ProcessInfo.processInfo.environment["RUN_E2E_TESTS"] - - if runE2E != "true" { - return true - } - - guard let auth = ProcessInfo.processInfo.environment["WEBHOOK_AUTH_USERNAME"] else { - fail("Cannot find webhook username") - return false - } - - let base64Token = SEGHTTPClient.authorizationHeader(auth) - - let headers: HTTPHeaders = [ - "Authorization": "Basic \(base64Token)", - ] - - let response = Alamofire.request("https://webhook-e2e.segment.com/buckets/ios?limit=100", headers: headers).responseJSON() - - // TODO: This should be more strongly typed. - let messages = response.result.value as! [String] - - for message in messages { - if (message.contains("\"properties\":{\"id\":\"\(messageId)\"}")) { - return true - } - } - - return false -} - -// End to End tests as described in https://paper.dropbox.com/doc/Libraries-End-to-End-Tests-ESEakc3LxFrqcHz69AmyN. -// We connect a webhook destination to a Segment source, send some data to the source using the libray. Then we -// verify that the data was sent to the source by finding it from the Webhook destination. -class AnalyticsE2ETests: QuickSpec { - override func spec() { - var analytics: SEGAnalytics! - - beforeEach { - // Write Key for https://app.segment.com/segment-libraries/sources/analytics_ios_e2e_test/overview - let config = SEGAnalyticsConfiguration(writeKey: "3VxTfPsVOoEOSbbzzbFqVNcYMNu2vjnr") - config.flushAt = 1 - - SEGAnalytics.setup(with: config) - - analytics = SEGAnalytics.shared() +@testable import Analytics +import XCTest + +class EndToEndTests: XCTestCase { + + var analytics: Analytics! + var configuration: AnalyticsConfiguration! + + override func setUp() { + super.setUp() + + // Write Key for https://app.segment.com/segment-libraries/sources/analytics_ios_e2e_test/overview + configuration = AnalyticsConfiguration(writeKey: "3VxTfPsVOoEOSbbzzbFqVNcYMNu2vjnr") + configuration.flushAt = 1 + + Analytics.setup(with: configuration) + + analytics = Analytics.shared() } - - afterEach { - analytics.reset() + + override func tearDown() { + super.tearDown() + + analytics.reset() } - - it("track") { - let uuid = UUID().uuidString - self.expectation(forNotification: NSNotification.Name("SegmentRequestDidSucceed"), object: nil, handler: nil) - - analytics.track("E2E Test", properties: ["id": uuid]) - - self.waitForExpectations(timeout: 3 * 60) - - for _ in 1...3 * 30 { - sleep(2) - if hasMatchingId(messageId: uuid) { - return + + func testTrack() { + let uuid = UUID().uuidString + let expectation = XCTestExpectation(description: "SegmentRequestDidSucceed") + + configuration.experimental.rawSegmentModificationBlock = { data in + if let properties = data["properties"] as? Dictionary, + let tempUUID = properties["id"] as? String, tempUUID == uuid { + expectation.fulfill() + } + return data } - } - fail("could not find message with id \(uuid) in Runscope") + analytics.track("E2E Test", properties: ["id": uuid]) + + wait(for: [expectation], timeout: 2.0) } - } } diff --git a/AnalyticsTests/FileStorageTest.swift b/AnalyticsTests/FileStorageTest.swift index 7f1884519..5630e1da8 100644 --- a/AnalyticsTests/FileStorageTest.swift +++ b/AnalyticsTests/FileStorageTest.swift @@ -5,127 +5,142 @@ // Copyright © 2016 Segment. All rights reserved. // -import Quick -import Nimble import Analytics +import XCTest -class FileStorageTest : QuickSpec { - override func spec() { - var storage : SEGFileStorage! - beforeEach { - let url = SEGFileStorage.applicationSupportDirectoryURL() - expect(url).toNot(beNil()) - expect(url?.lastPathComponent) == "Application Support" - storage = SEGFileStorage(folder: url!, crypto: nil) + +class FileStorageTest : XCTestCase { + + var storage : FileStorage! + + override func setUp() { + super.setUp() + let url = FileStorage.applicationSupportDirectoryURL() + XCTAssertNotNil(url, "URL Should not be nil") + XCTAssertEqual(url?.lastPathComponent, "Application Support") + storage = FileStorage(folder: url!, crypto: nil) } - - it("Creates caches directory") { - let url = SEGFileStorage.cachesDirectoryURL() - expect(url).toNot(beNil()) - expect(url?.lastPathComponent) == "Caches" + + override func tearDown() { + super.tearDown() + storage.resetAll() } - - it("creates folder if none exists") { - let tempDir = NSURL(fileURLWithPath: NSTemporaryDirectory()) - let url = tempDir.appendingPathComponent(NSUUID().uuidString) - - expect(try? url?.checkResourceIsReachable()).to(beNil()) - _ = SEGFileStorage(folder: url!, crypto: nil) - - var isDir: ObjCBool = false - let exists = FileManager.default.fileExists(atPath: url!.path, isDirectory: &isDir) - - expect(exists) == true - expect(isDir.boolValue) == true + + func testCreatesCachesDirectory() { + let url = FileStorage.cachesDirectoryURL() + XCTAssertNotNil(url, "URL should not be nil") + XCTAssertEqual(url?.lastPathComponent, "Caches", "Last part of url should be Caches") } - - it("persists and loads data") { - let dataIn = "segment".data(using: String.Encoding.utf8)! - storage.setData(dataIn, forKey: "mydata") - - let dataOut = storage.data(forKey: "mydata") - expect(dataOut) == dataIn - - let strOut = String(data: dataOut!, encoding: String.Encoding.utf8) - expect(strOut) == "segment" + + func testCreatesFolderIfNoneExists() { + let tempDir = NSURL(fileURLWithPath: NSTemporaryDirectory()) + let url = tempDir.appendingPathComponent(NSUUID().uuidString) + + XCTAssertNil(try? url?.checkResourceIsReachable() ?? true) + _ = FileStorage(folder: url!, crypto: nil) + + var isDir: ObjCBool = false + let exists = FileManager.default.fileExists(atPath: url!.path, isDirectory: &isDir) + + XCTAssertEqual(exists, true, "Exists should be true") + XCTAssertEqual(isDir.boolValue, true, "Should be a directory") + } + + func testPersistsAndLoadsData() { + let dataIn = "segment".data(using: String.Encoding.utf8)! + storage.setData(dataIn, forKey: "mydata") + + let dataOut = storage.data(forKey: "mydata") + XCTAssertEqual(dataOut, dataIn, "Out and In data should match") + + let strOut = String(data: dataOut!, encoding: String.Encoding.utf8) + XCTAssertEqual(strOut, "segment") } - - it("persists and loads string") { - let str = "san francisco" - storage.setString(str, forKey: "city") - expect(storage.string(forKey: "city")) == str - - storage.removeKey("city") - expect(storage.string(forKey: "city")).to(beNil()) + + func testPersistsAndLoadsString() { + let str = "san francisco" + storage.setString(str, forKey: "city") + XCTAssertEqual(storage.string(forKey: "city"), str) + + storage.removeKey("city") + XCTAssertNil(storage.string(forKey: "city")) } - - it("persists and loads array") { - let array = [ - "san francisco", - "new york", - "tallinn", - ] - storage.setArray(array, forKey: "cities") - expect(storage.array(forKey: "cities") as? Array) == array - - storage.removeKey("cities") - expect(storage.array(forKey: "cities")).to(beNil()) + + func testPersistsAndLoadsArray() { + let array = [ + "san francisco", + "new york", + "tallinn", + ] + storage.setArray(array, forKey: "cities") + XCTAssertEqual(storage.array(forKey: "cities") as? Array, array) + + storage.removeKey("cities") + XCTAssertNil(storage.array(forKey: "cities")) } - - it("persists and loads dictionary") { - let dict = [ - "san francisco": "tech", - "new york": "finance", - "paris": "fashion", - ] - storage.setDictionary(dict, forKey: "cityMap") - expect(storage.dictionary(forKey: "cityMap") as? Dictionary) == dict - - storage.removeKey("cityMap") - expect(storage.dictionary(forKey: "cityMap")).to(beNil()) + + func testPersistsAndLoadsDictionary() { + let dict = [ + "san francisco": "tech", + "new york": "finance", + "paris": "fashion", + ] + storage.setDictionary(dict, forKey: "cityMap") + XCTAssertEqual(storage.dictionary(forKey: "cityMap") as? Dictionary, dict) + + storage.removeKey("cityMap") + XCTAssertNil(storage.dictionary(forKey: "cityMap")) } - - it("saves file to disk and removes from disk") { - let key = "input.txt" - let url = storage.url(forKey: key) - expect(try? url.checkResourceIsReachable()).to(beNil()) - storage.setString("sloth", forKey: key) - expect(try! url.checkResourceIsReachable()) == true - storage.removeKey(key) - expect(try? url.checkResourceIsReachable()).to(beNil()) + + func testSavesFileToDiskRemovesFromDisk() { + let key = "input.txt" + let url = storage.url(forKey: key) + XCTAssertNil(try? url.checkResourceIsReachable()) + storage.setString("sloth", forKey: key) + XCTAssertEqual(try! url.checkResourceIsReachable(), true) + storage.removeKey(key) + XCTAssertNil(try? url.checkResourceIsReachable()) } - - it("should be binary compatible with old SDKs") { - let key = "traits.plist" - let dictIn = [ - "san francisco": "tech", - "new york": "finance", - "paris": "fashion", - ] - - (dictIn as NSDictionary).write(to: storage.url(forKey: key), atomically: true) - let dictOut = storage.dictionary(forKey: key) - expect(dictOut as? [String: String]) == dictIn + + func testShouldBeBinaryCompatible() { + let key = "traits.plist" + let dictIn = [ + "san francisco": "tech", + "new york": "finance", + "paris": "fashion", + ] + + (dictIn as NSDictionary).write(to: storage.url(forKey: key), atomically: true) + let dictOut = storage.dictionary(forKey: key) + XCTAssertEqual(dictOut as? [String: String], dictIn) } - - it("should work with crypto") { - let url = SEGFileStorage.applicationSupportDirectoryURL() - let crypto = SEGAES256Crypto(password: "thetrees") - let s = SEGFileStorage(folder: url!, crypto: crypto) - let dict = [ - "san francisco": "tech", - "new york": "finance", - "paris": "fashion", - ] - s.setDictionary(dict, forKey: "cityMap") - expect(s.dictionary(forKey: "cityMap") as? Dictionary) == dict - - s.removeKey("cityMap") - expect(s.dictionary(forKey: "cityMap")).to(beNil()) + + func testShouldRemoveDictionaryForInvalidPlistConversion() { + let key = "invalid.plist" + let dictIn: [String: Any] = [ + "timestamp": TimeInterval.nan // `.nan` fails JSONSerialization + ] + + let url = storage.url(forKey: key) + (dictIn as NSDictionary).write(to: url, atomically: true) + let dictOut = storage.dictionary(forKey: key) + XCTAssertNil(dictOut) + XCTAssertNil(try? url.checkResourceIsReachable()) } - - afterEach { - storage.resetAll() + + func testShouldWorkWithCrypto() { + let url = FileStorage.applicationSupportDirectoryURL() + let crypto = AES256Crypto(password: "thetrees") + let s = FileStorage(folder: url!, crypto: crypto) + let dict = [ + "san francisco": "tech", + "new york": "finance", + "paris": "fashion", + ] + s.setDictionary(dict, forKey: "cityMap") + XCTAssertEqual(s.dictionary(forKey: "cityMap") as? Dictionary, dict) + + s.removeKey("cityMap") + XCTAssertNil(s.dictionary(forKey: "cityMap")) } - } } diff --git a/AnalyticsTests/HTTPClientTest.swift b/AnalyticsTests/HTTPClientTest.swift index d25c2b696..45cea2e2f 100644 --- a/AnalyticsTests/HTTPClientTest.swift +++ b/AnalyticsTests/HTTPClientTest.swift @@ -6,260 +6,248 @@ // Copyright © 2016 Segment. All rights reserved. // -import Quick -import Nimble import Nocilla import Analytics +import XCTest -class HTTPClientTest: QuickSpec { - override func spec() { +class HTTPClientTest: XCTestCase { - var client: SEGHTTPClient! + var client: HTTPClient! + let batch: [String: Any] = ["sentAt":"2016-07-19'T'19:25:06Z", "batch":[["type":"track", "event":"foo"]]] + let context: [String: Any] = [ + "os": [ + "name": "iPhone OS", + "version" : "8.1.3", + ], + "ip": "8.8.8.8", + ] - beforeEach { - LSNocilla.sharedInstance().start() - client = SEGHTTPClient(requestFactory: nil) + override func setUp() { + super.setUp() + LSNocilla.sharedInstance().start() + client = HTTPClient(requestFactory: nil) } - afterEach { - LSNocilla.sharedInstance().clearStubs() - LSNocilla.sharedInstance().stop() + + override func tearDown() { + super.tearDown() + LSNocilla.sharedInstance().clearStubs() + LSNocilla.sharedInstance().stop() } - describe("defaultRequestFactory") { - it("preserves url") { - let factory = SEGHTTPClient.defaultRequestFactory() + func testDefaultRequestFactor() { + let factory = HTTPClient.defaultRequestFactory() let url = URL(string: "https://api.segment.io/v1/batch") let request = factory(url!) - expect(request.url) == url - } + XCTAssertEqual(request.url, url, "URLs should be the same") } - describe("settingsForWriteKey") { - it("succeeds for 2xx response") { + func testSettingsForWriteKeySucceeds2xx() { _ = stubRequest("GET", "https://cdn-settings.segment.com/v1/projects/foo/settings" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withHeaders(["Accept-Encoding" : "gzip" ])! - .andReturn(200)! - .withHeaders(["Content-Type" : "application/json"])! - .withBody("{\"integrations\":{\"Segment.io\":{\"apiKey\":\"foo\"}},\"plan\":{\"track\":{}}}" as NSString) - - var done = false - let task = client.settings(forWriteKey: "foo", completionHandler: { success, settings in - expect(success) == true - expect(settings as NSDictionary?) == [ - "integrations": [ - "Segment.io": [ - "apiKey":"foo" - ] - ], - "plan":[ - "track": [:] - ] - ] as NSDictionary - done = true + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withHeaders(["Accept-Encoding" : "gzip" ])! + .andReturn(200)! + .withHeaders(["Content-Type" : "application/json"])! + .withBody("{\"integrations\":{\"Segment.io\":{\"apiKey\":\"foo\"}},\"plan\":{\"track\":{}}}" as NSString) + + let doneExpectation = expectation(description: "Done with url session task") + + _ = client.settings(forWriteKey: "foo", completionHandler: { success, settings in + + XCTAssert(success, "Should be successful") + XCTAssertEqual(settings as NSDictionary?, [ + "integrations": [ + "Segment.io": [ + "apiKey":"foo" + ] + ], + "plan":[ + "track": [:] + ] + ] as NSDictionary) + doneExpectation.fulfill() }) - expect(task.state).toEventually(equal(URLSessionTask.State.completed)) - expect(done).toEventually(beTrue()) - } - it("fails for non 2xx response") { + wait(for: [doneExpectation], timeout: 1.0) + } + + func testSettingsWriteKey2xxResponse() { _ = stubRequest("GET", "https://cdn-settings.segment.com/v1/projects/foo/settings" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withHeaders(["Accept-Encoding" : "gzip" ])! - .andReturn(400)! - .withHeaders(["Content-Type" : "application/json" ])! - .withBody("{\"integrations\":{\"Segment.io\":{\"apiKey\":\"foo\"}},\"plan\":{\"track\":{}}}" as NSString) - var done = false + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withHeaders(["Accept-Encoding" : "gzip" ])! + .andReturn(400)! + .withHeaders(["Content-Type" : "application/json" ])! + .withBody("{\"integrations\":{\"Segment.io\":{\"apiKey\":\"foo\"}},\"plan\":{\"track\":{}}}" as NSString) + + let doneExpectation = expectation(description: "Done with url session task") + client.settings(forWriteKey: "foo", completionHandler: { success, settings in - expect(success) == false - expect(settings).to(beNil()) - done = true + XCTAssertFalse(success, "Success should be false") + XCTAssertNil(settings, "Failure should have nil settings") + + doneExpectation.fulfill() }) - expect(done).toEventually(beTrue()) - } - it("fails for json error") { + wait(for: [doneExpectation], timeout: 1.0) + + } + + func testSettingsWriteKey2xxJSONErrorResponse() { _ = stubRequest("GET", "https://cdn-settings.segment.com/v1/projects/foo/settings" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withHeaders(["Accept-Encoding":"gzip"])! - .andReturn(200)! - .withHeaders(["Content-Type":"application/json"])! - .withBody("{\"integrations" as NSString) + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withHeaders(["Accept-Encoding":"gzip"])! + .andReturn(200)! + .withHeaders(["Content-Type":"application/json"])! + .withBody("{\"integrations" as NSString) + + let doneExpectation = expectation(description: "Done with url session task") - var done = false client.settings(forWriteKey: "foo", completionHandler: { success, settings in - expect(success) == false - expect(settings).to(beNil()) - done = true + XCTAssertFalse(success, "Success should be false") + XCTAssertNil(settings, "Failure should have nil settings") + doneExpectation.fulfill() }) - expect(done).toEventually(beTrue()) - } + wait(for: [doneExpectation], timeout: 1.0) } - describe("upload") { - it("does not ask to retry for json error") { + func testUploadNoRetry() { let batch: [String: Any] = [ - // Dates cannot be serialized as is so the json serialzation will fail. - "sentAt": NSDate(), - "batch": [["type": "track", "event": "foo"]], + // Dates cannot be serialized as is so the json serialzation will fail. + "sentAt": NSDate(), + "batch": [["type": "track", "event": "foo"]], ] - var done = false + let doneExpectation = expectation(description: "Done with url session task") let task = client.upload(batch, forWriteKey: "bar") { retry in - expect(retry) == false - done = true + XCTAssertFalse(retry, "Retry should be false") + doneExpectation.fulfill() } - expect(task).to(beNil()) - expect(done).toEventually(beTrue()) - } - - let batch: [String: Any] = ["sentAt":"2016-07-19'T'19:25:06Z", "batch":[["type":"track", "event":"foo"]]] - + XCTAssertNil(task, "Task should be nil") + wait(for: [doneExpectation], timeout: 1.0) + } - it("does not ask to retry for 2xx response") { + func testUploadNoRetry2xx() { _ = stubRequest("POST", "https://api.segment.io/v1/batch" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withJsonGzippedBody(batch as AnyObject) - .withWriteKey("bar") - .andReturn(200) - var done = false - let task = client.upload(batch, forWriteKey: "bar") { retry in - expect(retry) == false - done = true + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withJsonGzippedBody(batch as AnyObject) + .withWriteKey("bar") + .andReturn(200) + let doneExpectation = expectation(description: "Done with url session task") + _ = client.upload(batch, forWriteKey: "bar") { retry in + XCTAssertFalse(retry, "Retry should be false") + doneExpectation.fulfill() } - expect(done).toEventually(beTrue()) - expect(task?.state).toEventually(equal(URLSessionTask.State.completed)) - } + wait(for: [doneExpectation], timeout: 1.0) + } - it("asks to retry for 3xx response") { + func testUploadRetry3xx() { _ = stubRequest("POST", "https://api.segment.io/v1/batch" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withJsonGzippedBody(batch as AnyObject) - .withWriteKey("bar") - .andReturn(304) - var done = false - let task = client.upload(batch, forWriteKey: "bar") { retry in - expect(retry) == true - done = true + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withJsonGzippedBody(batch as AnyObject) + .withWriteKey("bar") + .andReturn(304) + let doneExpectation = expectation(description: "Done with url session task") + _ = client.upload(batch, forWriteKey: "bar") { retry in + XCTAssert(retry, "Retry should be true") + doneExpectation.fulfill() } - expect(done).toEventually(beTrue()) - expect(task?.state).toEventually(equal(URLSessionTask.State.completed)) - } + wait(for: [doneExpectation], timeout: 1.0) + } - it("does not ask to retry for 4xx response") { + func testUploadNoRetry4xx() { _ = stubRequest("POST", "https://api.segment.io/v1/batch" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withJsonGzippedBody(batch as AnyObject) - .withWriteKey("bar") - .andReturn(401) - var done = false - let task = client.upload(batch, forWriteKey: "bar") { retry in - expect(retry) == false - done = true + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withJsonGzippedBody(batch as AnyObject) + .withWriteKey("bar") + .andReturn(401) + let doneExpectation = expectation(description: "Done with url session task") + _ = client.upload(batch, forWriteKey: "bar") { retry in + XCTAssertFalse(retry, "Retry should be false") + doneExpectation.fulfill() } - expect(done).toEventually(beTrue()) - expect(task?.state).toEventually(equal(URLSessionTask.State.completed)) - } + wait(for: [doneExpectation], timeout: 1.0) + } - it("asks to retry for 429 response") { + func testRetryFor429() { _ = stubRequest("POST", "https://api.segment.io/v1/batch" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withJsonGzippedBody(batch as AnyObject) - .withWriteKey("bar") - .andReturn(429) - var done = false - let task = client.upload(batch, forWriteKey: "bar") { retry in - expect(retry) == true - done = true + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withJsonGzippedBody(batch as AnyObject) + .withWriteKey("bar") + .andReturn(429) + let doneExpectation = expectation(description: "Done with url session task") + _ = client.upload(batch, forWriteKey: "bar") { retry in + XCTAssert(retry, "Retry should be true") + doneExpectation.fulfill() } - expect(done).toEventually(beTrue()) - expect(task?.state).toEventually(equal(URLSessionTask.State.completed)) - } + wait(for: [doneExpectation], timeout: 1.0) + } - it("asks to retry for 5xx response") { + func testRetryFor5xx() { _ = stubRequest("POST", "https://api.segment.io/v1/batch" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withJsonGzippedBody(batch as AnyObject) - .withWriteKey("bar") - .andReturn(504) - var done = false - let task = client.upload(batch, forWriteKey: "bar") { retry in - expect(retry) == true - done = true + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withJsonGzippedBody(batch as AnyObject) + .withWriteKey("bar") + .andReturn(504) + let doneExpectation = expectation(description: "Done with url session task") + _ = client.upload(batch, forWriteKey: "bar") { retry in + XCTAssert(retry, "Retry should be true") + doneExpectation.fulfill() } - expect(done).toEventually(beTrue()) - expect(task?.state).toEventually(equal(URLSessionTask.State.completed)) - } + wait(for: [doneExpectation], timeout: 1.0) + } - it("fails when batch size exceeds the max limit size") { + func testBatchSizeFailure() { let oversizedBatch: [String: Any] = ["sentAt":"2016-07-19'T'19:25:06Z", "batch": Array(repeating: ["type":"track", "event":"foo"], count: 16000)] - var done = false - let task = client.upload(oversizedBatch, forWriteKey: "bar") { retry in - expect(retry) == false - done = true + let doneExpectation = expectation(description: "Done with url session task") + _ = client.upload(oversizedBatch, forWriteKey: "bar") { retry in + XCTAssertFalse(retry, "Retry should be false") + doneExpectation.fulfill() } - expect(done).toEventually(beTrue()) - expect(task).toEventually(beNil()) - } + wait(for: [doneExpectation], timeout: 1.0) } - describe("attribution") { - it("fails for json error") { + func testAttributionFailsForJSONError() { let device = [ - // Dates cannot be serialized as is so the json serialzation will fail. - "sentAt": NSDate(), + // Dates cannot be serialized as is so the json serialzation will fail. + "sentAt": NSDate(), ] - var done = false - let task = client.attribution(withWriteKey: "bar", forDevice: device) { success, properties in - expect(success) == false - done = true + let doneExpectation = expectation(description: "Done with url session task") + _ = client.attribution(withWriteKey: "bar", forDevice: device) { success, properties in + XCTAssertFalse(success, "Retry should be false") + doneExpectation.fulfill() } - expect(task).to(beNil()) - expect(done).toEventually(beTrue()) - } - - let context: [String: Any] = [ - "os": [ - "name": "iPhone OS", - "version" : "8.1.3", - ], - "ip": "8.8.8.8", - ] + wait(for: [doneExpectation], timeout: 1.0) + } - it("succeeds for 2xx response") { + func testAttributionSucceedsFor2xx() { _ = stubRequest("POST", "https://mobile-service.segment.com/v1/attribution" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withWriteKey("foo") - .andReturn(200)! - .withBody("{\"provider\": \"mock\"}" as NSString) - - var done = false - let task = client.attribution(withWriteKey: "foo", forDevice: context) { success, properties in - expect(success) == true - expect(properties as? [String: String]) == [ - "provider": "mock" - ] - done = true + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withWriteKey("foo") + .andReturn(200)! + .withBody("{\"provider\": \"mock\"}" as NSString) + + let doneExpectation = expectation(description: "Done with url session task") + _ = client.attribution(withWriteKey: "foo", forDevice: context) { success, properties in + XCTAssert(success, "Success should be true") + XCTAssertEqual(properties as? [String: String], [ + "provider": "mock" + ]) + doneExpectation.fulfill() } - expect(task.state).toEventually(equal(URLSessionTask.State.completed)) - expect(done).toEventually(beTrue()) - } + wait(for: [doneExpectation], timeout: 1.0) + } - it("fails for non 2xx response") { + func testAttributionFailsForNon2xx() { _ = stubRequest("POST", "https://mobile-service.segment.com/v1/attribution" as NSString) - .withHeader("User-Agent", "analytics-ios/" + SEGAnalytics.version())! - .withWriteKey("foo") - .andReturn(404)! - .withBody("not found" as NSString) - var done = false - let task = client.attribution(withWriteKey: "foo", forDevice: context) { success, properties in - expect(success) == false - expect(properties).to(beNil()) - done = true + .withHeader("User-Agent", "analytics-ios/" + Analytics.version())! + .withWriteKey("foo") + .andReturn(404)! + .withBody("not found" as NSString) + let doneExpectation = expectation(description: "Done with url session task") + _ = client.attribution(withWriteKey: "foo", forDevice: context) { success, properties in + XCTAssertFalse(success, "Success should be false") + XCTAssertNil(properties, "Properties should be nil") + doneExpectation.fulfill() } - expect(task.state).toEventually(equal(URLSessionTask.State.completed)) - expect(done).toEventually(beTrue()) - } + wait(for: [doneExpectation], timeout: 1.0) } - } } diff --git a/AnalyticsTests/IntegrationsManagerTest.swift b/AnalyticsTests/IntegrationsManagerTest.swift index 0942ef89d..49e36bde4 100644 --- a/AnalyticsTests/IntegrationsManagerTest.swift +++ b/AnalyticsTests/IntegrationsManagerTest.swift @@ -1,106 +1,87 @@ import Analytics -import Quick -import Nimble -import SwiftTryCatch - -class IntegrationsManagerTest: QuickSpec { - - override func spec() { - describe("IntegrationsManager") { - context("is track event enabled for integration in plan") { - - it("valid value types are used in integration enablement flags") { - var exception: NSException? = nil - SwiftTryCatch.tryRun({ - SEGIntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": ["blah": 1]]) - SEGIntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": true]) - }, catchRun: { e in - exception = e - }, finallyRun: nil) - - expect(exception).to(beNil()) +import XCTest +class IntegrationsManagerTest: XCTestCase { + + func testValidValueTypesInIntegrationEnablementFlags() { + let exception = objc_tryCatch { + IntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": ["blah": 1]]) + IntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": true]) } - - it("asserts when invalid value types are used integration enablement flags") { - var exception: NSException? = nil - SwiftTryCatch.tryRun({ - SEGIntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": "blah"]) - }, catchRun: { e in - exception = e - }, finallyRun: nil) - - expect(exception).toNot(beNil()) + + XCTAssertNil(exception) + } + + func testAssertsWhenInvalidValueTypesUsedIntegrationEnablement() { + let exception = objc_tryCatch { + IntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": "blah"]) } - - it("asserts when invalid value types are used integration enablement flags") { - var exception: NSException? = nil - SwiftTryCatch.tryRun({ + + XCTAssertNotNil(exception) + } + + func testAssertsWhenInvalidValueTypesIntegrationEnableFlags() { + let exception = objc_tryCatch { // we don't accept array's as values. - SEGIntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": ["key", 1]]) - }, catchRun: { e in - exception = e - }, finallyRun: nil) - - expect(exception).toNot(beNil()) - } - - it("pulls valid integration data when supplied") { - let enabled = SEGIntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": true]) - expect(enabled).to(beTrue()) + IntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": ["key", 1]]) } - it("falls back correctly when values aren't explicitly specified") { - let enabled = SEGIntegrationsManager.isIntegration("comScore", enabledInOptions: ["all": true]) - expect(enabled).to(beTrue()) - let allEnabled = SEGIntegrationsManager.isIntegration("comScore", enabledInOptions: ["All": true]) - expect(allEnabled).to(beTrue()) - } + XCTAssertNotNil(exception) + } - it("returns true when there is no plan") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Amplitude", inPlan:[:]) - expect(enabled).to(beTrue()) - } - - it("returns true when plan is empty") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":[:]]) - expect(enabled).to(beTrue()) - } - - it("returns true when plan enables event") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["hello world":["enabled":true]]]) - expect(enabled).to(beTrue()) - } - - it("returns false when plan disables event") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Amplitude", inPlan:["track":["hello world":["enabled":false]]]) - expect(enabled).to(beFalse()) - } - - it("returns true for Segment integration even when plan disables event") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Segment.io", inPlan:["track":["hello world":["enabled":false]]]) - expect(enabled).to(beTrue()) - } - - it("returns true when plan enables event for integration") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["hello world":["enabled":true, "integrations":["Mixpanel":true]]]]) - expect(enabled).to(beTrue()) - } - - it("returns false when plan disables event for integration") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["hello world":["enabled":true, "integrations":["Mixpanel":false]]]]) - expect(enabled).to(beFalse()) - } - - it("returns false when plan disables new events by default") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["__default":["enabled":false]]]) - expect(enabled).to(beFalse()) - } - - it("returns uses event plan rather over defaults") { - let enabled = SEGIntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["__default":["enabled":false],"hello world":["enabled":true]]]) - expect(enabled).to(beTrue()) - } - } + func testPullsValidIntegrationDataWhenSupplied() { + let enabled = IntegrationsManager.isIntegration("comScore", enabledInOptions: ["comScore": true]) + XCTAssert(enabled) + } + + func testFallsBackCorrectlyWhenNotSpecified() { + let enabled = IntegrationsManager.isIntegration("comScore", enabledInOptions: ["all": true]) + XCTAssert(enabled) + let allEnabled = IntegrationsManager.isIntegration("comScore", enabledInOptions: ["All": true]) + XCTAssert(allEnabled) + } + + func testReturnsTrueWhenThereisNoPlan() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Amplitude", inPlan:[:]) + XCTAssert(enabled) + } + + func testReturnsTrueWhenPlanIsEmpty() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":[:]]) + XCTAssert(enabled) + } + + func testReturnsTrueWhenPlanEnablesEvent() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["hello world":["enabled":true]]]) + XCTAssert(enabled) + } + + func testReturnsFalseWhenPlanDisablesEvent() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Amplitude", inPlan:["track":["hello world":["enabled":false]]]) + XCTAssertFalse(enabled) + } + + func testReturnsTrueForSegmentIntegrationWhenDisablesEvent() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Segment.io", inPlan:["track":["hello world":["enabled":false]]]) + XCTAssert(enabled) + } + + func testReturnsTrueWhenPlanEnablesEventForIntegration() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["hello world":["enabled":true, "integrations":["Mixpanel":true]]]]) + XCTAssert(enabled) + } + + func testReturnsFalseWhenPlanDisablesEventForIntegration() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["hello world":["enabled":true, "integrations":["Mixpanel":false]]]]) + XCTAssertFalse(enabled) + } + + func testReturnsFalseWhenPlanDisablesNewEvents() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["__default":["enabled":false]]]) + XCTAssertFalse(enabled) + } + + func testReturnsUsesEventPlanRatherOverDefaults() { + let enabled = IntegrationsManager.isTrackEvent("hello world", enabledForIntegration: "Mixpanel", inPlan:["track":["__default":["enabled":false],"hello world":["enabled":true]]]) + XCTAssert(enabled) } - } } diff --git a/AnalyticsTests/MiddlewareTests.swift b/AnalyticsTests/MiddlewareTests.swift index 2d8a3c9bd..d4333491c 100644 --- a/AnalyticsTests/MiddlewareTests.swift +++ b/AnalyticsTests/MiddlewareTests.swift @@ -7,79 +7,141 @@ // -import Quick -import Nimble import Analytics +import XCTest // Changing event names and adding custom attributes -let customizeAllTrackCalls = SEGBlockMiddleware { (context, next) in - if context.eventType == .track { - next(context.modify { ctx in - guard let track = ctx.payload as? SEGTrackPayload else { - return - } - let newEvent = "[New] \(track.event)" - var newProps = track.properties ?? [:] - newProps["customAttribute"] = "Hello" - newProps["nullTest"] = NSNull() - ctx.payload = SEGTrackPayload( - event: newEvent, - properties: newProps, - context: track.context, - integrations: track.integrations - ) - }) - } else { - next(context) - } +let customizeAllTrackCalls = BlockMiddleware { (context, next) in + if context.eventType == .track { + next(context.modify { ctx in + guard let track = ctx.payload as? TrackPayload else { + return + } + let newEvent = "[New] \(track.event)" + var newProps = track.properties ?? [:] + newProps["customAttribute"] = "Hello" + newProps["nullTest"] = NSNull() + ctx.payload = TrackPayload( + event: newEvent, + properties: newProps, + context: track.context, + integrations: track.integrations + ) + }) + } else { + next(context) + } } // Simply swallows all calls and does not pass events downstream -let eatAllCalls = SEGBlockMiddleware { (context, next) in +let eatAllCalls = BlockMiddleware { (context, next) in } -class MiddlewareTests: QuickSpec { - override func spec() { - it("receives events") { - let config = SEGAnalyticsConfiguration(writeKey: "TESTKEY") - let passthrough = SEGPassthroughMiddleware() - config.middlewares = [ - passthrough, - ] - let analytics = SEGAnalytics(configuration: config) - analytics.identify("testUserId1") - expect(passthrough.lastContext?.eventType) == SEGEventType.identify - let identify = passthrough.lastContext?.payload as? SEGIdentifyPayload - expect(identify?.userId) == "testUserId1" +class SourceMiddlewareTests: XCTestCase { + + func testReceivesEvents() { + let config = AnalyticsConfiguration(writeKey: "TESTKEY") + let passthrough = PassthroughMiddleware() + config.sourceMiddleware = [ + passthrough, + ] + let analytics = Analytics(configuration: config) + analytics.identify("testUserId1") + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.identify) + let identify = passthrough.lastContext?.payload as? IdentifyPayload + XCTAssertEqual(identify?.userId, "testUserId1") } - - it("modifies and passes event to next") { - let config = SEGAnalyticsConfiguration(writeKey: "TESTKEY") - let passthrough = SEGPassthroughMiddleware() - config.middlewares = [ - customizeAllTrackCalls, - passthrough, - ] - let analytics = SEGAnalytics(configuration: config) - analytics.track("Purchase Success") - expect(passthrough.lastContext?.eventType) == SEGEventType.track - let track = passthrough.lastContext?.payload as? SEGTrackPayload - expect(track?.event) == "[New] Purchase Success" - expect(track?.properties?["customAttribute"] as? String) == "Hello" - let isNull = (track?.properties?["nullTest"] is NSNull) - expect(isNull) == true + + func testModifiesAndPassesEventToNext() { + let config = AnalyticsConfiguration(writeKey: "TESTKEY") + let passthrough = PassthroughMiddleware() + config.sourceMiddleware = [ + customizeAllTrackCalls, + passthrough, + ] + let analytics = Analytics(configuration: config) + analytics.track("Purchase Success") + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.track) + let track = passthrough.lastContext?.payload as? TrackPayload + XCTAssertEqual(track?.event, "[New] Purchase Success") + XCTAssertEqual(track?.properties?["customAttribute"] as? String, "Hello") + let isNull = (track?.properties?["nullTest"] is NSNull) + XCTAssert(isNull) + } + + func testExpectsEventToBeSwallowed() { + let config = AnalyticsConfiguration(writeKey: "TESTKEY") + let passthrough = PassthroughMiddleware() + config.sourceMiddleware = [ + eatAllCalls, + passthrough, + ] + let analytics = Analytics(configuration: config) + analytics.track("Purchase Success") + XCTAssertNil(passthrough.lastContext) } - - it("expects event to be swallowed if next is not called") { - let config = SEGAnalyticsConfiguration(writeKey: "TESTKEY") - let passthrough = SEGPassthroughMiddleware() - config.middlewares = [ - eatAllCalls, - passthrough, - ] - let analytics = SEGAnalytics(configuration: config) - analytics.track("Purchase Success") - expect(passthrough.lastContext).to(beNil()) +} + +class IntegrationMiddlewareTests: XCTestCase { + + func testReceivesEvents() { + let config = AnalyticsConfiguration(writeKey: "TESTKEY") + let passthrough = PassthroughMiddleware() + config.destinationMiddleware = [DestinationMiddleware(key: SegmentIntegrationFactory().key(), middleware: [passthrough])] + let analytics = Analytics(configuration: config) + analytics.identify("testUserId1") + + // pump the runloop until we have a last context. + // integration middleware is held up until initialization is completed. + let currentTime = Date() + while(passthrough.lastContext == nil && currentTime < currentTime + 60) { + sleep(1); + } + + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.identify) + let identify = passthrough.lastContext?.payload as? IdentifyPayload + XCTAssertEqual(identify?.userId, "testUserId1") + } + + func testModifiesAndPassesEventToNext() { + let config = AnalyticsConfiguration(writeKey: "TESTKEY") + let passthrough = PassthroughMiddleware() + config.destinationMiddleware = [DestinationMiddleware(key: SegmentIntegrationFactory().key(), middleware: [customizeAllTrackCalls, passthrough])] + let analytics = Analytics(configuration: config) + analytics.track("Purchase Success") + + // pump the runloop until we have a last context. + // integration middleware is held up until initialization is completed. + let currentTime = Date() + while(passthrough.lastContext == nil && currentTime < currentTime + 60) { + sleep(1) + } + + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.track) + let track = passthrough.lastContext?.payload as? TrackPayload + XCTAssertEqual(track?.event, "[New] Purchase Success") + XCTAssertEqual(track?.properties?["customAttribute"] as? String, "Hello") + let isNull = (track?.properties?["nullTest"] is NSNull) + XCTAssert(isNull, "Should be true") + } + + func testExpectsEventToBeSwallowedIfOtherIsNotCalled() { + // Since we're testing that an event is dropped, the previously used run loop pump won't work here. + var initialized = false + NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: SEGAnalyticsIntegrationDidStart), object: nil, queue: nil) { (notification) in + initialized = true + } + + let config = AnalyticsConfiguration(writeKey: "TESTKEY") + let passthrough = PassthroughMiddleware() + config.destinationMiddleware = [DestinationMiddleware(key: SegmentIntegrationFactory().key(), middleware: [eatAllCalls, passthrough])] + let analytics = Analytics(configuration: config) + analytics.track("Purchase Success") + + while (!initialized) { + sleep(1) + } + + XCTAssertNil(passthrough.lastContext) } - } } diff --git a/AnalyticsTests/SerializationTests.m b/AnalyticsTests/SerializationTests.m index 76c57eb66..0582b53d0 100644 --- a/AnalyticsTests/SerializationTests.m +++ b/AnalyticsTests/SerializationTests.m @@ -9,6 +9,10 @@ #import @import Analytics; +@interface NSJSONSerialization (Serializable) ++ (BOOL)isOfSerializableType:(id)obj; +@end + @protocol SEGSerializableDeepCopy -(id _Nullable) serializableDeepCopy; @end @@ -39,7 +43,7 @@ - (void)testDeepCopyAndConformance { NSDictionary *aCopy = [serializable serializableDeepCopy]; XCTAssert(aCopy != serializable); - + NSDictionary *sub = [serializable objectForKey:@"nested"]; NSDictionary *subCopy = [aCopy objectForKey:@"nested"]; XCTAssert(sub != subCopy); @@ -52,4 +56,20 @@ - (void)testDeepCopyAndConformance { XCTAssertThrows([nonserializable serializableDeepCopy]); } +- (void)testDateIssue { + NSDate *date = [NSDate date]; + NSString *test = @"test"; + + XCTAssertFalse([NSJSONSerialization isOfSerializableType:date]); + XCTAssertTrue([NSJSONSerialization isOfSerializableType:test]); + + NSDictionary *nonserializable = @{@"test": date}; + NSDictionary *serializable = @{@"test": @1}; + XCTAssertThrows([nonserializable serializableDeepCopy]); + XCTAssertNoThrow([serializable serializableDeepCopy]); + + nonserializable = @{@"test": @[date]}; + XCTAssertThrows([nonserializable serializableDeepCopy]); +} + @end diff --git a/AnalyticsTests/StoreKitTrackerTests.swift b/AnalyticsTests/StoreKitTrackerTests.swift index 4fd979427..5be94b17b 100644 --- a/AnalyticsTests/StoreKitTrackerTests.swift +++ b/AnalyticsTests/StoreKitTrackerTests.swift @@ -6,9 +6,8 @@ // Copyright © 2016 Segment. All rights reserved. // -import Quick -import Nimble import Analytics +import XCTest class mockTransaction: SKPaymentTransaction { override var transactionIdentifier: String? { @@ -39,33 +38,30 @@ class mockProductResponse: SKProductsResponse { } } -class StoreKitTrackerTests: QuickSpec { - override func spec() { +class StoreKitTrackerTests: XCTestCase { var test: TestMiddleware! - var tracker: SEGStoreKitTracker! - var analytics: SEGAnalytics! - - beforeEach { - let config = SEGAnalyticsConfiguration(writeKey: "foobar") - test = TestMiddleware() - config.middlewares = [test] - analytics = SEGAnalytics(configuration: config) - tracker = SEGStoreKitTracker.trackTransactions(for: analytics) + var tracker: StoreKitTracker! + var analytics: Analytics! + + override func setUp() { + super.setUp() + let config = AnalyticsConfiguration(writeKey: "foobar") + test = TestMiddleware() + config.sourceMiddleware = [test] + analytics = Analytics(configuration: config) + tracker = StoreKitTracker.trackTransactions(for: analytics) } - - it("SKPaymentQueue Observer") { - let transaction = mockTransaction() - expect(transaction.transactionIdentifier) == "tid" - tracker.paymentQueue(SKPaymentQueue(), updatedTransactions: [transaction]) - - tracker.productsRequest(SKProductsRequest(), didReceive: mockProductResponse()) - - let payload = test.lastContext?.payload as? SEGTrackPayload - - expect(payload?.event) == "Order Completed" + + func testSKPaymentQueueObserver() { + let transaction = mockTransaction() + XCTAssertEqual(transaction.transactionIdentifier, "tid") + tracker.paymentQueue(SKPaymentQueue(), updatedTransactions: [transaction]) + + tracker.productsRequest(SKProductsRequest(), didReceive: mockProductResponse()) + + let payload = test.lastContext?.payload as? TrackPayload + + XCTAssertEqual(payload?.event, "Order Completed") } - - } - } diff --git a/AnalyticsTests/TrackingTests.swift b/AnalyticsTests/TrackingTests.swift index b91bbcc1e..a45a14a33 100644 --- a/AnalyticsTests/TrackingTests.swift +++ b/AnalyticsTests/TrackingTests.swift @@ -7,103 +7,102 @@ // -import Quick -import Nimble import Analytics +import XCTest -class TrackingTests: QuickSpec { - override func spec() { - var passthrough: SEGPassthroughMiddleware! - var analytics: SEGAnalytics! +class TrackingTests: XCTestCase { - beforeEach { - let config = SEGAnalyticsConfiguration(writeKey: "QUI5ydwIGeFFTa1IvCBUhxL9PyW5B0jE") - passthrough = SEGPassthroughMiddleware() - config.middlewares = [ - passthrough, - ] - analytics = SEGAnalytics(configuration: config) - } + var passthrough: PassthroughMiddleware! + var analytics: Analytics! - afterEach { - analytics.reset() + override func setUp() { + super.setUp() + let config = AnalyticsConfiguration(writeKey: "QUI5ydwIGeFFTa1IvCBUhxL9PyW5B0jE") + passthrough = PassthroughMiddleware() + config.sourceMiddleware = [ + passthrough, + ] + analytics = Analytics(configuration: config) } - it("handles identify:") { - analytics.identify("testUserId1", traits: [ - "firstName": "Peter" - ]) - expect(passthrough.lastContext?.eventType) == SEGEventType.identify - let identify = passthrough.lastContext?.payload as? SEGIdentifyPayload - expect(identify?.userId) == "testUserId1" - expect(identify?.anonymousId).toNot(beNil()) - expect(identify?.traits?["firstName"] as? String) == "Peter" + override func tearDown() { + super.tearDown() + analytics.reset() } - it("handles identify with custom anonymousId:") { - analytics.identify("testUserId1", traits: [ - "firstName": "Peter" - ], options: [ - "anonymousId": "a_custom_anonymous_id" + func testHandlesIdentify() { + analytics.identify("testUserId1", traits: [ + "firstName": "Peter" ]) - expect(passthrough.lastContext?.eventType) == SEGEventType.identify - let identify = passthrough.lastContext?.payload as? SEGIdentifyPayload - expect(identify?.userId) == "testUserId1" - expect(identify?.anonymousId) == "a_custom_anonymous_id" - expect(identify?.traits?["firstName"] as? String) == "Peter" + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.identify) + let identify = passthrough.lastContext?.payload as? IdentifyPayload + XCTAssertEqual(identify?.userId, "testUserId1") + XCTAssertNotNil(identify?.anonymousId) + XCTAssertEqual(identify?.traits?["firstName"] as? String, "Peter") } - it("handles track:") { - analytics.track("User Signup", properties: [ - "method": "SSO" - ], options: [ - "context": [ - "device": [ - "token": "1234" - ] - ] - ]) - expect(passthrough.lastContext?.eventType) == SEGEventType.track - let payload = passthrough.lastContext?.payload as? SEGTrackPayload - expect(payload?.event) == "User Signup" - expect(payload?.properties?["method"] as? String) == "SSO" + func testHandlesIdentifyWithCustomAnonymousId() { + analytics.identify("testUserId1", traits: [ + "firstName": "Peter" + ], options: [ + "anonymousId": "a_custom_anonymous_id" + ]) + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.identify) + let identify = passthrough.lastContext?.payload as? IdentifyPayload + XCTAssertEqual(identify?.userId, "testUserId1") + XCTAssertEqual(identify?.anonymousId, "a_custom_anonymous_id") + XCTAssertEqual(identify?.traits?["firstName"] as? String, "Peter") } - it("handles alias:") { - analytics.alias("persistentUserId") - expect(passthrough.lastContext?.eventType) == SEGEventType.alias - let payload = passthrough.lastContext?.payload as? SEGAliasPayload - expect(payload?.theNewId) == "persistentUserId" + func testHandlesTrack() { + analytics.track("User Signup", properties: [ + "method": "SSO" + ], options: [ + "context": [ + "device": [ + "token": "1234" + ] + ] + ]) + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.track) + let payload = passthrough.lastContext?.payload as? TrackPayload + XCTAssertEqual(payload?.event, "User Signup") + XCTAssertEqual(payload?.properties?["method"] as? String, "SSO") } - it("handles screen:") { - analytics.screen("Home", properties: [ - "referrer": "Google" - ]) - expect(passthrough.lastContext?.eventType) == SEGEventType.screen - let screen = passthrough.lastContext?.payload as? SEGScreenPayload - expect(screen?.name) == "Home" - expect(screen?.properties?["referrer"] as? String) == "Google" + func testHandlesAlias() { + analytics.alias("persistentUserId") + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.alias) + let payload = passthrough.lastContext?.payload as? AliasPayload + XCTAssertEqual(payload?.theNewId, "persistentUserId") } - it("handles group:") { - analytics.group("acme-company", traits: [ - "employees": 2333 - ]) - expect(passthrough.lastContext?.eventType) == SEGEventType.group - let payload = passthrough.lastContext?.payload as? SEGGroupPayload - expect(payload?.groupId) == "acme-company" - expect(payload?.traits?["employees"] as? Int) == 2333 + func testHandlesScreen() { + analytics.screen("Home", properties: [ + "referrer": "Google" + ]) + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.screen) + let screen = passthrough.lastContext?.payload as? ScreenPayload + XCTAssertEqual(screen?.name, "Home") + XCTAssertEqual(screen?.properties?["referrer"] as? String, "Google") } - - it("handles null values") { - analytics.track("null test", properties: [ - "nullTest": NSNull() + + func testHandlesGroup() { + analytics.group("acme-company", traits: [ + "employees": 2333 ]) - let payload = passthrough.lastContext?.payload as? SEGTrackPayload - let isNull = (payload?.properties?["nullTest"] is NSNull) - expect(isNull) == true + XCTAssertEqual(passthrough.lastContext?.eventType, EventType.group) + let payload = passthrough.lastContext?.payload as? GroupPayload + XCTAssertEqual(payload?.groupId, "acme-company") + XCTAssertEqual(payload?.traits?["employees"] as? Int, 2333) } - } + func testHandlesNullValues() { + analytics.track("null test", properties: [ + "nullTest": NSNull() + ]) + let payload = passthrough.lastContext?.payload as? TrackPayload + let isNull = (payload?.properties?["nullTest"] is NSNull) + XCTAssert(isNull) + } } diff --git a/AnalyticsTests/UserDefaultsStorageTest.swift b/AnalyticsTests/UserDefaultsStorageTest.swift index 83185270d..5e84830d3 100644 --- a/AnalyticsTests/UserDefaultsStorageTest.swift +++ b/AnalyticsTests/UserDefaultsStorageTest.swift @@ -5,99 +5,96 @@ // Copyright © 2016 Segment. All rights reserved. // -import Quick -import Nimble -import Analytics +@testable import Analytics +import XCTest -class UserDefaultsStorageTest : QuickSpec { - override func spec() { - var storage : SEGUserDefaultsStorage! - beforeEach { -// let crypto = SEGAES256Crypto(password: "thetrees") -// storage = SEGUserDefaultsStorage(defaults: NSUserDefaults.standardUserDefaults(), namespacePrefix: "segment", crypto: crypto) -// storage = SEGUserDefaultsStorage(defaults: NSUserDefaults.standardUserDefaults(), namespacePrefix: nil, crypto: crypto) - storage = SEGUserDefaultsStorage(defaults: UserDefaults.standard, namespacePrefix: nil, crypto: nil) - } +class UserDefaultsStorageTest : XCTestCase { + + var storage : UserDefaultsStorage! - it("persists and loads data") { - let dataIn = "segment".data(using: String.Encoding.utf8)! - storage.setData(dataIn, forKey: "mydata") - - let dataOut = storage.data(forKey: "mydata") - expect(dataOut) == dataIn - - let strOut = String(data: dataOut!, encoding: .utf8) - expect(strOut) == "segment" + override func setUp() { + super.setUp() + storage = UserDefaultsStorage(defaults: UserDefaults.standard, namespacePrefix: nil, crypto: nil) } - it("persists and loads string") { - let str = "san francisco" - storage.setString(str, forKey: "city") - expect(storage.string(forKey: "city")) == str - - storage.removeKey("city") - expect(storage.string(forKey: "city")).to(beNil()) + override func tearDown() { + super.tearDown() + storage.resetAll() } - it("persists and loads array") { - let array = [ - "san francisco", - "new york", - "tallinn", - ] - storage.setArray(array, forKey: "cities") - expect(storage.array(forKey: "cities") as? Array) == array - - storage.removeKey("cities") - expect(storage.array(forKey: "cities")).to(beNil()) + func testPersistsAndLoadsData() { + let dataIn = "segment".data(using: String.Encoding.utf8)! + storage.setData(dataIn, forKey: "mydata") + + let dataOut = storage.data(forKey: "mydata") + XCTAssertEqual(dataOut, dataIn) + + let strOut = String(data: dataOut!, encoding: .utf8) + XCTAssertEqual(strOut, "segment") } - it("persists and loads dictionary") { - let dict = [ - "san francisco": "tech", - "new york": "finance", - "paris": "fashion", - ] - storage.setDictionary(dict, forKey: "cityMap") - expect(storage.dictionary(forKey: "cityMap") as? Dictionary) == dict - - storage.removeKey("cityMap") - expect(storage.dictionary(forKey: "cityMap")).to(beNil()) + func testPersistsAndLoadsString() { + let str = "san francisco" + storage.setString(str, forKey: "city") + XCTAssertEqual(storage.string(forKey: "city"), str) + + storage.removeKey("city") + XCTAssertNil(storage.string(forKey: "city")) } - it("should work with crypto") { - let crypto = SEGAES256Crypto(password: "thetrees") - let s = SEGUserDefaultsStorage(defaults: UserDefaults.standard, namespacePrefix: nil, crypto: crypto) - let dict = [ - "san francisco": "tech", - "new york": "finance", - "paris": "fashion", - ] - s.setDictionary(dict, forKey: "cityMap") - expect(s.dictionary(forKey: "cityMap") as? Dictionary) == dict - - s.removeKey("cityMap") - expect(s.dictionary(forKey: "cityMap")).to(beNil()) + func testPersistsAndLoadsArray() { + let array = [ + "san francisco", + "new york", + "tallinn", + ] + storage.setArray(array, forKey: "cities") + XCTAssertEqual(storage.array(forKey: "cities") as? Array, array) + + storage.removeKey("cities") + XCTAssertNil(storage.array(forKey: "cities")) } + func testPersistsAndLoadsDictionary() { + let dict = [ + "san francisco": "tech", + "new york": "finance", + "paris": "fashion", + ] + storage.setDictionary(dict, forKey: "cityMap") + XCTAssertEqual(storage.dictionary(forKey: "cityMap") as? Dictionary, dict) + + storage.removeKey("cityMap") + XCTAssertNil(storage.dictionary(forKey: "cityMap")) + } - it("should work with namespace") { - let crypto = SEGAES256Crypto(password: "thetrees") - let s = SEGUserDefaultsStorage(defaults: UserDefaults.standard, namespacePrefix: "segment", crypto: crypto) - let dict = [ - "san francisco": "tech", - "new york": "finance", - "paris": "fashion", - ] - s.setDictionary(dict, forKey: "cityMap") - expect(s.dictionary(forKey: "cityMap") as? Dictionary) == dict - - s.removeKey("cityMap") - expect(s.dictionary(forKey: "cityMap")).to(beNil()) + func testShouldWorkWithCrypto() { + let crypto = AES256Crypto(password: "thetrees") + let s = UserDefaultsStorage(defaults: UserDefaults.standard, namespacePrefix: nil, crypto: crypto) + let dict = [ + "san francisco": "tech", + "new york": "finance", + "paris": "fashion", + ] + s.setDictionary(dict, forKey: "cityMap") + XCTAssertEqual(s.dictionary(forKey: "cityMap") as? Dictionary, dict) + + s.removeKey("cityMap") + XCTAssertNil(s.dictionary(forKey: "cityMap")) } - afterEach { - storage.resetAll() + func testShouldWorkWithNamespace() { + let crypto = AES256Crypto(password: "thetrees") + let s = UserDefaultsStorage(defaults: UserDefaults.standard, namespacePrefix: "segment", crypto: crypto) + let dict = [ + "san francisco": "tech", + "new york": "finance", + "paris": "fashion", + ] + s.setDictionary(dict, forKey: "cityMap") + XCTAssertEqual(s.dictionary(forKey: "cityMap") as? Dictionary, dict) + + s.removeKey("cityMap") + XCTAssertNil(s.dictionary(forKey: "cityMap")) } - } } diff --git a/AnalyticsTests/Utils/ObjcUtils.h b/AnalyticsTests/Utils/ObjcUtils.h new file mode 100644 index 000000000..9008f7eca --- /dev/null +++ b/AnalyticsTests/Utils/ObjcUtils.h @@ -0,0 +1,11 @@ +// +// ObjcUtils.h +// AnalyticsTests +// +// Created by Brandon Sneed on 7/13/20. +// Copyright © 2020 Segment. All rights reserved. +// + +#import + +NSException * _Nullable objc_tryCatch(void (^ _Nonnull block)(void)); diff --git a/AnalyticsTests/Utils/ObjcUtils.m b/AnalyticsTests/Utils/ObjcUtils.m new file mode 100644 index 000000000..9e109314e --- /dev/null +++ b/AnalyticsTests/Utils/ObjcUtils.m @@ -0,0 +1,20 @@ +// +// ObjcUtils.m +// AnalyticsTests +// +// Created by Brandon Sneed on 7/13/20. +// Copyright © 2020 Segment. All rights reserved. +// + +#import "ObjcUtils.h" + +// This can cause leaks if self is referenced in block. DO NOT USE IN PRODUCTION. +// But ... for tests, it's ok. +NSException * _Nullable objc_tryCatch(void (^ _Nonnull block)(void)) { + @try { + block(); + return nil; + } @catch (NSException *exception) { + return exception; + } +} diff --git a/AnalyticsTests/Utils/TestUtils.swift b/AnalyticsTests/Utils/TestUtils.swift index 2752b803e..96f1bc617 100644 --- a/AnalyticsTests/Utils/TestUtils.swift +++ b/AnalyticsTests/Utils/TestUtils.swift @@ -6,23 +6,23 @@ // Copyright © 2016 Segment. All rights reserved. // -@testable import Nimble import Nocilla import Analytics +import XCTest -class SEGPassthroughMiddleware: SEGMiddleware { - var lastContext: SEGContext? - - func context(_ context: SEGContext, next: @escaping SEGMiddlewareNext) { +class PassthroughMiddleware: Middleware { + var lastContext: Context? + + func context(_ context: Context, next: @escaping SEGMiddlewareNext) { lastContext = context; next(context) } } -class TestMiddleware: SEGMiddleware { - var lastContext: SEGContext? +class TestMiddleware: Middleware { + var lastContext: Context? var swallowEvent = false - func context(_ context: SEGContext, next: @escaping SEGMiddlewareNext) { + func context(_ context: Context, next: @escaping SEGMiddlewareNext) { lastContext = context if !swallowEvent { next(context) @@ -30,27 +30,27 @@ class TestMiddleware: SEGMiddleware { } } -extension SEGAnalytics { - func test_integrationsManager() -> SEGIntegrationsManager? { - return self.value(forKey: "integrationsManager") as? SEGIntegrationsManager +extension Analytics { + func test_integrationsManager() -> IntegrationsManager? { + return self.value(forKey: "integrationsManager") as? IntegrationsManager } } -extension SEGIntegrationsManager { - func test_integrations() -> [String: SEGIntegration]? { - return self.value(forKey: "integrations") as? [String: SEGIntegration] +extension IntegrationsManager { + func test_integrations() -> [String: Integration]? { + return self.value(forKey: "integrations") as? [String: Integration] } - func test_segmentIntegration() -> SEGSegmentIntegration? { - return self.test_integrations()?["Segment.io"] as? SEGSegmentIntegration + func test_segmentIntegration() -> SegmentIntegration? { + return self.test_integrations()?["Segment.io"] as? SegmentIntegration } func test_setCachedSettings(settings: NSDictionary) { self.perform(Selector(("setCachedSettings:")), with: settings) } } -extension SEGSegmentIntegration { - func test_fileStorage() -> SEGFileStorage? { - return self.value(forKey: "fileStorage") as? SEGFileStorage +extension SegmentIntegration { + func test_fileStorage() -> FileStorage? { + return self.value(forKey: "fileStorage") as? FileStorage } func test_referrer() -> [String: AnyObject]? { return self.value(forKey: "referrer") as? [String: AnyObject] @@ -77,24 +77,21 @@ extension SEGSegmentIntegration { class JsonGzippedBody : LSMatcher, LSMatcheable { - + let expectedJson: AnyObject - + init(_ json: AnyObject) { self.expectedJson = json } - + func matchesJson(_ json: AnyObject) -> Bool { - let actualValue : () -> NSObject = { - return json as! NSObject - } - let failureMessage = FailureMessage() - let location = SourceLocation() - let matches = Nimble.equal(expectedJson).matches(actualValue, failureMessage: failureMessage, location: location) + let expectedDictionary = expectedJson as? [String: AnyHashable] + let jsonDictionary = json as? [String: AnyHashable] + let matches = expectedDictionary == jsonDictionary // print("matches=\(matches) expected \(expectedJson) actual \(json)") return matches } - + override func matches(_ string: String!) -> Bool { if let data = string.data(using: String.Encoding.utf8), let json = try? JSONSerialization.jsonObject(with: data, options: []) { @@ -102,7 +99,7 @@ class JsonGzippedBody : LSMatcher, LSMatcheable { } return false } - + override func matchesData(_ data: Data!) -> Bool { if let data = (data as NSData).seg_gunzipped(), let json = try? JSONSerialization.jsonObject(with: data, options: []) { @@ -110,11 +107,11 @@ class JsonGzippedBody : LSMatcher, LSMatcheable { } return false } - + func matcher() -> LSMatcher! { return self } - + func expectedHeaders() -> [String:String] { let data = try? JSONSerialization.data(withJSONObject: expectedJson, options: []) let contentLength = (data as NSData?)?.seg_gzipped()?.count ?? 0 @@ -151,7 +148,7 @@ typealias AndSegmentWriteKeyMethod = (String) -> LSStubRequestDSL extension LSStubRequestDSL { var withWriteKey: AndSegmentWriteKeyMethod { return { writeKey in - let base64Token = SEGHTTPClient.authorizationHeader(writeKey) + let base64Token = HTTPClient.authorizationHeader(writeKey) return self.withHeaders([ "Authorization": "Basic \(base64Token)", ])! @@ -159,28 +156,46 @@ extension LSStubRequestDSL { } } -class TestApplication: NSObject, SEGApplicationProtocol { +class TestApplication: NSObject, ApplicationProtocol { class BackgroundTask { - let identifier: UInt + let identifier: Int var isEnded = false - - init(identifier: UInt) { + + init(identifier: Int) { self.identifier = identifier } } - + var backgroundTasks = [BackgroundTask]() - - // MARK: - SEGApplicationProtocol + + // MARK: - ApplicationProtocol var delegate: UIApplicationDelegate? = nil func seg_beginBackgroundTask(withName taskName: String?, expirationHandler handler: (() -> Void)? = nil) -> UInt { let backgroundTask = BackgroundTask(identifier: (backgroundTasks.map({ $0.identifier }).max() ?? 0) + 1) backgroundTasks.append(backgroundTask) - return backgroundTask.identifier + return UInt(backgroundTask.identifier) } - + func seg_endBackgroundTask(_ identifier: UInt) { - guard let index = backgroundTasks.index(where: { $0.identifier == identifier }) else { return } + guard let index = backgroundTasks.firstIndex(where: { $0.identifier == identifier }) else { return } backgroundTasks[index].isEnded = true } } + +extension XCTestCase { + + func expectUntil(_ time: TimeInterval, expression: @escaping @autoclosure () throws -> Bool) { + + let expectation = self.expectation(description: "Expect Until") + DispatchQueue.global().async { + while (true) { + if try! expression() { + expectation.fulfill() + return + } + usleep(500) // try every half second + } + } + wait(for: [expectation], timeout: time) + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 960a93ddb..08193dd93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,117 @@ Change Log ========== +Version 4.0.5 (pre-release) (28 August, 2020) +----------------------------- +* [Fix](https://github.com/segmentio/analytics-ios/pull/937) Fixed issue where non-serializable types would get into payload. +* [Fix](https://github.com/segmentio/analytics-ios/pull/931) Fixed double device payload. +* [New](https://github.com/segmentio/analytics-ios/pull/930) Deprecated configuration access and updated associated tests. +* [Fix](https://github.com/segmentio/analytics-ios/pull/925) Disregard payloads that fail conversion from plist to json. +* [New](https://github.com/segmentio/analytics-ios/pull/922) Added Swift and Carthage badging. + +Version 4.0.4 (pre-release) (14 July, 2020) +----------------------------- +* [New](https://github.com/segmentio/analytics-ios/pull/918) Added MacOS support. +* [Fix](https://github.com/segmentio/analytics-ios/pull/921) Fixed SEGLog permissions. +* [Fix](https://github.com/segmentio/analytics-ios/pull/920) Adopted Swift 5 syntax in tests. Removed SwiftTryCatch dependency for tests. Fixed deadlock from #916. + +Version 4.0.3 (pre-release) (6 July, 2020) +----------------------------- +* [Fix](https://github.com/segmentio/analytics-ios/pull/917) Fixed an issue with old traits overwriting new traits. +* [New](https://github.com/segmentio/analytics-ios/pull/915) Added full example flow with Swift Package Manager compatibility. +* [Fix](https://github.com/segmentio/analytics-ios/pull/914) Fix SwiftUI previews in macOS Catalyst builds. + +Version 4.0.2 (pre-release) (25 June, 2020) +----------------------------- +* [New](https://github.com/segmentio/analytics-ios/pull/913) Separate public utils from private utils appropriately. +* [New](https://github.com/segmentio/analytics-ios/pull/912) Payload Info & Traits Fixes. +* [New](https://github.com/segmentio/analytics-ios/pull/911) Updated SPM for code coverage compatibility. +* [New](https://github.com/segmentio/analytics-ios/pull/909) Removed Quick and Nimble, updated unit tests. + +Version 4.0.1 (pre-release) (18 June, 2020) +----------------------------- + * [New](https://github.com/segmentio/analytics-ios/pull/905) Added global state management; Middleware now receive all context data. + * [New](https://github.com/segmentio/analytics-ios/pull/885) change logic for screen naming conventions. + * [New](https://github.com/segmentio/analytics-ios/pull/899) Fixed crash on UISceneDelegate applications. + * [New](https://github.com/segmentio/analytics-ios/pull/896) Renamed middleware methods to match a.js naming. + * [New](https://github.com/segmentio/analytics-ios/pull/904) Added Swift Package Manager support. + * [New](https://github.com/segmentio/analytics-ios/pull/902) Updated class names for Swift. + +Version 4.0.0-beta.1 *(21st May, 2020)* +--------------------------------------- + * [New](https://github.com/segmentio/analytics-ios/pull/892) Makes IDFA support externally/customer driven. + +Version 4.0.0-beta.0 *(22nd April, 2020)* +----------------------------------------- + * [New](https://github.com/segmentio/analytics-ios/pull/879) Added integration middleware functionality. + +Version 3.9.0 *(5th June, 2020)* +-------------------------------- + * [New](https://github.com/segmentio/analytics-ios/pull/897) Backport defaultSettings feature from 4.x to 3.x. + * [Fix](https://github.com/segmentio/analytics-ios/pull/885) Automatic Screen Tracking with consistent naming conventions + +Version 3.8.2 *(21st May, 2020)* +-------------------------------- + * [Fix](https://github.com/segmentio/analytics-ios/pull/880) Adds check to make sure cached settings aren't empty before being used. + +Version 3.8.1 *(12th May, 2020)* +-------------------------------- + * [Fix](https://github.com/segmentio/analytics-ios/pull/880) Fixed a crash in the file storage. + * [Fix](https://github.com/segmentio/analytics-ios/pull/884) Adds back erroneously removed build/version data from App Opened event. + * [Fix](https://github.com/segmentio/analytics-ios/pull/865) Pushlishes filenames use for storage. + * [Fix](https://github.com/segmentio/analytics-ios/pull/771) Fixes incorrect naming in screen reporting. + +Version 3.9.0 *(5th June, 2020)* +-------------------------------- +* [New](https://github.com/segmentio/analytics-ios/pull/897) Backport defaultSettings feature from 4.x to 3.x. +* [Fix](https://github.com/segmentio/analytics-ios/pull/885) Automatic Screen Tracking with consistent naming conventions + +Version 3.8.2 *(21st May, 2020)* +-------------------------------- +* [Fix](https://github.com/segmentio/analytics-ios/pull/880) Adds check to make sure cached settings aren't empty before being used. + + +Version 3.8.1 *(12th May, 2020)* +-------------------------------- + * [Fix](https://github.com/segmentio/analytics-ios/pull/880) Fixed a crash in the file storage. + * [Fix](https://github.com/segmentio/analytics-ios/pull/884) Adds back erroneously removed build/version data from App Opened event. + * [Fix](https://github.com/segmentio/analytics-ios/pull/865) Pushlishes filenames use for storage. + * [Fix](https://github.com/segmentio/analytics-ios/pull/771) Fixes incorrect naming in screen reporting. + +Version 3.8.0 *(22nd April, 2020)* +---------------------------------- + * Promoting 3.8.x series to stable release. This includes all changes since 3.7. + * [Fix](https://github.com/segmentio/analytics-ios/pull/874) Implement maximum batch request size. + +Version 3.8.0-beta.2 *(15th April, 2020)* +----------------------------------------- + * [Fix](https://github.com/segmentio/analytics-ios/pull/861) Move SEGQueue from UserDefaults to caches directory. + * [Fix](https://github.com/segmentio/analytics-ios/pull/862) Fix issues around plist->json conversion and nil values. + * [Fix](https://github.com/segmentio/analytics-ios/pull/851) Expect dictionary as well as bool for integration enablement. + * [Fix](https://github.com/segmentio/analytics-ios/pull/864) Differences observed in how iOS/android pass userId/anonId; Corrected. + * [Fix](https://github.com/segmentio/analytics-ios/pull/866) Look at previously cached settings before blowing them away. + * [Fix](https://github.com/segmentio/analytics-ios/pull/876) Added experimental feature to enable nanosecond granularity on timestamps. + +Version 3.8.0-beta.1 *(7th January, 2020)* +------------------------------------------ + + * [Fix](https://github.com/segmentio/analytics-ios/pull/856) Reload static context data when the app returns from background. + * [Fix](https://github.com/segmentio/analytics-ios/pull/855) Fixes issue where customers can overwrite information regarding integration enablement. + * [Fix](https://github.com/segmentio/analytics-ios/pull/854) Swapped JSON in for the storage format instead of plists. + * [Fix](https://github.com/segmentio/analytics-ios/pull/853) Hardened handling of user-supplied data in event properties. + * [New](https://github.com/segmentio/analytics-ios/pull/839) Added support for SSL pinning. + * [Fix](https://github.com/segmentio/analytics-ios/pull/842) CoreTelephony library is now only included on iOS targets. + +Version 3.8.0-beta.0 *(25th July, 2019)* +---------------------------------------- + + * [New](https://github.com/segmentio/analytics-ios/pull/831): Add iOS Backgrounded Event. + * [Fix](https://github.com/segmentio/analytics-ios/pull/785): Fix GCD mutual dependency + * [Fix](https://github.com/segmentio/analytics-ios/pull/): adding “name” field to payload; updated nimble to version 7.3.4 + +Version 3.7.0 *(22nd July, 2019)* +--------------------------------- + +This release promotes 3.7.0-beta.4 to stable. Version 3.9.0 *(5th June, 2020)* -------------------------------- diff --git a/Examples/CarthageExample/Cartfile b/Examples/CarthageExample/Cartfile index 3c67caf22..4d74c21cf 100644 --- a/Examples/CarthageExample/Cartfile +++ b/Examples/CarthageExample/Cartfile @@ -1,3 +1,3 @@ -github "segmentio/analytics-ios" "3.9.0" +github "segmentio/analytics-ios" "4.0.5" # Use a local project when debugging # git "~/Code/segmentio/analytics-ios/" "master" diff --git a/Examples/CarthageExample/Cartfile.resolved b/Examples/CarthageExample/Cartfile.resolved index fc5aeb40f..bb34841de 100644 --- a/Examples/CarthageExample/Cartfile.resolved +++ b/Examples/CarthageExample/Cartfile.resolved @@ -1 +1 @@ -github "segmentio/analytics-ios" "3.9.0" +github "segmentio/analytics-ios" "4.0.2" diff --git a/Examples/CarthageExample/CarthageExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/CarthageExample/CarthageExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Examples/CarthageExample/CarthageExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/CarthageExample/Makefile b/Examples/CarthageExample/Makefile index d244fd48e..033044c55 100644 --- a/Examples/CarthageExample/Makefile +++ b/Examples/CarthageExample/Makefile @@ -4,4 +4,4 @@ clean: rm -rf Carthage build: - carthage update + carthage update --platform ios diff --git a/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.pbxproj b/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.pbxproj new file mode 100644 index 000000000..269a8fc1f --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.pbxproj @@ -0,0 +1,444 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 52; + objects = { + +/* Begin PBXBuildFile section */ + 9616DB59249050A600F7191B /* SignupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9616DB58249050A600F7191B /* SignupViewController.swift */; }; + 9616DB5B2490583800F7191B /* InviteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9616DB5A2490583800F7191B /* InviteViewController.swift */; }; + 961C617024BE5BED00A8B8E3 /* Analytics in Frameworks */ = {isa = PBXBuildFile; productRef = 961C616F24BE5BED00A8B8E3 /* Analytics */; }; + 961D80C024902143007C4F04 /* AnonymousViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961D80BC24902143007C4F04 /* AnonymousViewController.swift */; }; + 96BC0E4A24A57317000AF2EB /* SignoutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BC0E4924A57317000AF2EB /* SignoutViewController.swift */; }; + 96BC0E4C24A693E3000AF2EB /* SignInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BC0E4B24A693E3000AF2EB /* SignInViewController.swift */; }; + 96BC0E5124AA72F6000AF2EB /* TrialEndViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BC0E5024AA72F6000AF2EB /* TrialEndViewController.swift */; }; + 96D0441F2485B458009C3FD7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D0441E2485B458009C3FD7 /* AppDelegate.swift */; }; + 96D044212485B458009C3FD7 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D044202485B458009C3FD7 /* SceneDelegate.swift */; }; + 96D044232485B458009C3FD7 /* StartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D044222485B458009C3FD7 /* StartViewController.swift */; }; + 96D044262485B458009C3FD7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96D044242485B458009C3FD7 /* Main.storyboard */; }; + 96D044282485B459009C3FD7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96D044272485B459009C3FD7 /* Assets.xcassets */; }; + 96D0442B2485B459009C3FD7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96D044292485B459009C3FD7 /* LaunchScreen.storyboard */; }; + 96EC569B2488567500B636AC /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96EC569A2488567500B636AC /* LoginViewController.swift */; }; + 96EC569D2488568D00B636AC /* StepsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96EC569C2488568D00B636AC /* StepsViewController.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 96D044422485B541009C3FD7 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 9616DB58249050A600F7191B /* SignupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignupViewController.swift; sourceTree = ""; }; + 9616DB5A2490583800F7191B /* InviteViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InviteViewController.swift; sourceTree = ""; }; + 961D80BC24902143007C4F04 /* AnonymousViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnonymousViewController.swift; sourceTree = ""; }; + 96BC0E4924A57317000AF2EB /* SignoutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignoutViewController.swift; sourceTree = ""; }; + 96BC0E4B24A693E3000AF2EB /* SignInViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignInViewController.swift; sourceTree = ""; }; + 96BC0E5024AA72F6000AF2EB /* TrialEndViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrialEndViewController.swift; sourceTree = ""; }; + 96D0441B2485B458009C3FD7 /* Analytics Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Analytics Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 96D0441E2485B458009C3FD7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 96D044202485B458009C3FD7 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 96D044222485B458009C3FD7 /* StartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartViewController.swift; sourceTree = ""; }; + 96D044252485B458009C3FD7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 96D044272485B459009C3FD7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 96D0442A2485B459009C3FD7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 96D0442C2485B459009C3FD7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 96EC569A2488567500B636AC /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; }; + 96EC569C2488568D00B636AC /* StepsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepsViewController.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 96D044182485B458009C3FD7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 961C617024BE5BED00A8B8E3 /* Analytics in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 96D044122485B458009C3FD7 = { + isa = PBXGroup; + children = ( + 96D0441D2485B458009C3FD7 /* Analytics Example */, + 96D0441C2485B458009C3FD7 /* Products */, + 96D0443F2485B541009C3FD7 /* Frameworks */, + ); + sourceTree = ""; + }; + 96D0441C2485B458009C3FD7 /* Products */ = { + isa = PBXGroup; + children = ( + 96D0441B2485B458009C3FD7 /* Analytics Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 96D0441D2485B458009C3FD7 /* Analytics Example */ = { + isa = PBXGroup; + children = ( + 96EC5699248855F800B636AC /* Controllers */, + 96D0441E2485B458009C3FD7 /* AppDelegate.swift */, + 96D044272485B459009C3FD7 /* Assets.xcassets */, + 96D0442C2485B459009C3FD7 /* Info.plist */, + 96D044292485B459009C3FD7 /* LaunchScreen.storyboard */, + 96D044242485B458009C3FD7 /* Main.storyboard */, + 96D044202485B458009C3FD7 /* SceneDelegate.swift */, + ); + path = "Analytics Example"; + sourceTree = ""; + }; + 96D0443F2485B541009C3FD7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + 96EC5699248855F800B636AC /* Controllers */ = { + isa = PBXGroup; + children = ( + 961D80BC24902143007C4F04 /* AnonymousViewController.swift */, + 9616DB5A2490583800F7191B /* InviteViewController.swift */, + 96EC569A2488567500B636AC /* LoginViewController.swift */, + 96BC0E4B24A693E3000AF2EB /* SignInViewController.swift */, + 96BC0E4924A57317000AF2EB /* SignoutViewController.swift */, + 9616DB58249050A600F7191B /* SignupViewController.swift */, + 96D044222485B458009C3FD7 /* StartViewController.swift */, + 96EC569C2488568D00B636AC /* StepsViewController.swift */, + 96BC0E5024AA72F6000AF2EB /* TrialEndViewController.swift */, + ); + path = Controllers; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 96D0441A2485B458009C3FD7 /* Analytics Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 96D0442F2485B459009C3FD7 /* Build configuration list for PBXNativeTarget "Analytics Example" */; + buildPhases = ( + 96D044172485B458009C3FD7 /* Sources */, + 96D044182485B458009C3FD7 /* Frameworks */, + 96D044192485B458009C3FD7 /* Resources */, + 96D044422485B541009C3FD7 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Analytics Example"; + packageProductDependencies = ( + 961C616F24BE5BED00A8B8E3 /* Analytics */, + ); + productName = "Analytics Example"; + productReference = 96D0441B2485B458009C3FD7 /* Analytics Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 96D044132485B458009C3FD7 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1150; + LastUpgradeCheck = 1150; + ORGANIZATIONNAME = "Cody Garvin"; + TargetAttributes = { + 96D0441A2485B458009C3FD7 = { + CreatedOnToolsVersion = 11.5; + }; + }; + }; + buildConfigurationList = 96D044162485B458009C3FD7 /* Build configuration list for PBXProject "Analytics Example" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 96D044122485B458009C3FD7; + packageReferences = ( + 961C616E24BE5BED00A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */, + ); + productRefGroup = 96D0441C2485B458009C3FD7 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 96D0441A2485B458009C3FD7 /* Analytics Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 96D044192485B458009C3FD7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96D0442B2485B459009C3FD7 /* LaunchScreen.storyboard in Resources */, + 96D044282485B459009C3FD7 /* Assets.xcassets in Resources */, + 96D044262485B458009C3FD7 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 96D044172485B458009C3FD7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96EC569B2488567500B636AC /* LoginViewController.swift in Sources */, + 96BC0E4A24A57317000AF2EB /* SignoutViewController.swift in Sources */, + 96BC0E5124AA72F6000AF2EB /* TrialEndViewController.swift in Sources */, + 9616DB59249050A600F7191B /* SignupViewController.swift in Sources */, + 96D044232485B458009C3FD7 /* StartViewController.swift in Sources */, + 9616DB5B2490583800F7191B /* InviteViewController.swift in Sources */, + 96D0441F2485B458009C3FD7 /* AppDelegate.swift in Sources */, + 96D044212485B458009C3FD7 /* SceneDelegate.swift in Sources */, + 961D80C024902143007C4F04 /* AnonymousViewController.swift in Sources */, + 96BC0E4C24A693E3000AF2EB /* SignInViewController.swift in Sources */, + 96EC569D2488568D00B636AC /* StepsViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 96D044242485B458009C3FD7 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 96D044252485B458009C3FD7 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 96D044292485B459009C3FD7 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 96D0442A2485B459009C3FD7 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 96D0442D2485B459009C3FD7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 96D0442E2485B459009C3FD7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 96D044302485B459009C3FD7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = "Analytics Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.Segment.Analytics-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 96D044312485B459009C3FD7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = "Analytics Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.Segment.Analytics-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 96D044162485B458009C3FD7 /* Build configuration list for PBXProject "Analytics Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96D0442D2485B459009C3FD7 /* Debug */, + 96D0442E2485B459009C3FD7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 96D0442F2485B459009C3FD7 /* Build configuration list for PBXNativeTarget "Analytics Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96D044302485B459009C3FD7 /* Debug */, + 96D044312485B459009C3FD7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 961C616E24BE5BED00A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/segmentio/analytics-ios.git"; + requirement = { + branch = migs647/macconversion; + kind = branch; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 961C616F24BE5BED00A8B8E3 /* Analytics */ = { + isa = XCSwiftPackageProductDependency; + package = 961C616E24BE5BED00A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */; + productName = Analytics; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 96D044132485B458009C3FD7 /* Project object */; +} diff --git a/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..5302431a3 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "Analytics", + "repositoryURL": "https://github.com/segmentio/analytics-ios.git", + "state": { + "branch": "migs647/macconversion", + "revision": "bd012c2c3fe26e228bdf386a7e38c0a6b4b761fc", + "version": null + } + } + ] + }, + "version": 1 +} diff --git a/Examples/FullExampleFlow/Analytics Example/AppDelegate.swift b/Examples/FullExampleFlow/Analytics Example/AppDelegate.swift new file mode 100644 index 000000000..8f4a0e8be --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/AppDelegate.swift @@ -0,0 +1,43 @@ +// +// AppDelegate.swift +// Analytics Example +// +// Created by Cody Garvin on 6/1/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + let configuration = AnalyticsConfiguration(writeKey: "8XpdAWa7qJVBJMK8V4FfXQOrnvCzu3Ie") + + // Enable this to record certain application events automatically! + configuration.trackApplicationLifecycleEvents = true + // Enable this to record screen views automatically! + configuration.recordScreenViews = true + Analytics.setup(with: configuration) + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..831a94286 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,101 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "Icon_120.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "Icon_180.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "Icon.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon.png b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..27e190425e02971dbb7a98d0cc834af4e280566e GIT binary patch literal 102508 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 literal 0 HcmV?d00001 diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_120.png b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_120.png new file mode 100644 index 0000000000000000000000000000000000000000..408a7ccf7be2c5a2ebe7f49cf63a9c34c3a2c636 GIT binary patch literal 10223 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 literal 0 HcmV?d00001 diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_180.png b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_180.png new file mode 100644 index 0000000000000000000000000000000000000000..55966b3b686498a2cf10fe0e325ae827de791fc5 GIT binary patch literal 17086 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 B>RbQ- literal 0 HcmV?d00001 diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Contents.json b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Contents.json b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Contents.json new file mode 100644 index 000000000..d7353623d --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "Segment_Logo.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Segment_Logo@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Segment_Logo.png b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Segment_Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5fd84c71234e1c0dfd6bb26e0edd3282f091baf2 GIT binary patch literal 9072 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 JD`6b`e*n4G)=U5Z literal 0 HcmV?d00001 diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Splash.imageset/Contents.json b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Splash.imageset/Contents.json new file mode 100644 index 000000000..e5cd8ada4 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Splash.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Splash.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Splash.imageset/Splash.png b/Examples/FullExampleFlow/Analytics Example/Assets.xcassets/Splash.imageset/Splash.png new file mode 100644 index 0000000000000000000000000000000000000000..9057e4473e74ae8fff9632736b7fa72bf3f7215e GIT binary patch literal 33969 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/FullExampleFlow/Analytics Example/Base.lproj/Main.storyboard b/Examples/FullExampleFlow/Analytics Example/Base.lproj/Main.storyboard new file mode 100644 index 000000000..205a35644 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Base.lproj/Main.storyboard @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/AnonymousViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/AnonymousViewController.swift new file mode 100644 index 000000000..12b002204 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/AnonymousViewController.swift @@ -0,0 +1,75 @@ +// +// AnonymousViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/3/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class AnonymousViewController: StepsViewController { + + let anonymousUserID = "70e4ab26-3c4d-42c9-aed1-2c186738a97d" + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// identify screen load (sends anonymous id) +analytics.screen("Home") + +// identify with anonymous user +analytics.identify(nil, traits: ["subscription": "inactive"]) + +// track CTA tap (sends anonymous id) +analytics.track("CTA Tapped", properties: ["plan": "premium"]) +""" + + // Add the button + let trackButton = UIButton.SegmentButton("Track", target: self, action: #selector(trackUser(_:))) + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [trackButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + continueButton.isEnabled = false + } + + private func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Home") + + // identify anonymous user + analytics.identify(nil, traits: ["subscription": "inactive"]) + } + + @objc + private func trackUser(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("CTA Tapped", properties: ["plan": "premium"]) + + continueButton.isEnabled = true + } + + @objc private func continueToNext(_ sender: Any) { + let signup = SignupViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(signup, animated: true) + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/InviteViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/InviteViewController.swift new file mode 100644 index 000000000..69687f9b0 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/InviteViewController.swift @@ -0,0 +1,63 @@ +// +// InviteViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/25/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class InviteViewController: StepsViewController { + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// Screen +analytics.screen("Invite") + +// Invite user +analytics.track("Invite Sent", properties: ["first": "Jane", "last": "Doe", "email": "jane@abc.com"]) +""" + + // Add the button + let inviteButton = UIButton.SegmentButton("Invite Yser", target: self, action: #selector(createUser(_:))) + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [inviteButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private + func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Invite") + } + + @objc + func createUser(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("Invite Sent", properties: ["first": "Jane", "last": "Doe", "email": "jane@abc.com"]) + continueButton.isEnabled = true + } + + @objc + func continueToNext(_ sender: Any) { + let signoutVC = SignoutViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(signoutVC, animated: true) + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/LoginViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/LoginViewController.swift new file mode 100644 index 000000000..d69eb7f0f --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/LoginViewController.swift @@ -0,0 +1,27 @@ +// +// LoginViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/3/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit + +class LoginViewController: StepsViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + title = "Login Example" + descriptionString = "Login with details using identify" + codeString = """ +// Start by identifying the user +if let analytics = Analytics.shared() +Analytics.shared().identify("1234", + traits: ["email": "jack@segment.com", + "phone": "555-444-3333"]) +""" + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/SignInViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/SignInViewController.swift new file mode 100644 index 000000000..39fcfedb7 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/SignInViewController.swift @@ -0,0 +1,63 @@ +// +// SigninViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/9/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class SigninViewController: StepsViewController { + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// Screen +analytics.screen("Dashboard") + +// Signed in +analytics.track("Signed In", properties: ["username": "pgibbons"]) +""" + + // Add the button + let signinButton = UIButton.SegmentButton("Sign In", target: self, action: #selector(signin(_:))) + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [signinButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private + func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Dashboard") + } + + @objc + func signin(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("Signed In", properties: ["username": "pgibbons"]) + continueButton.isEnabled = true + } + + @objc + func continueToNext(_ sender: Any) { + let trailEndVC = TrialEndViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(trailEndVC, animated: true) + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/SignoutViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/SignoutViewController.swift new file mode 100644 index 000000000..3672c5998 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/SignoutViewController.swift @@ -0,0 +1,63 @@ +// +// SignoutViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/9/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class SignoutViewController: StepsViewController { + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// Screen +analytics.screen("Signout") + +// Signout user +analytics.track("Signed Out", properties: ["username": "pgibbons"]) +""" + + // Add the button + let signoutButton = UIButton.SegmentButton("Signout", target: self, action: #selector(signout(_:))) + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [signoutButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private + func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Signout") + } + + @objc + func signout(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("Signed Out", properties: ["username": "pgibbons"]) + continueButton.isEnabled = true + } + + @objc + func continueToNext(_ sender: Any) { + let signinVC = SigninViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(signinVC, animated: true) + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/SignupViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/SignupViewController.swift new file mode 100644 index 000000000..14050cd41 --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/SignupViewController.swift @@ -0,0 +1,81 @@ +// +// SignupViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/9/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class SignupViewController: StepsViewController { + + private var continueButton: UIButton! + private var trackButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// Screen +analytics.screen("Signup") + +// create user +analytics.track("Create Account", properties: ["Signed Up": ...]) + +// Alias new user id with anonymous id +analytics.alias("AA-BB-CC-NEW-ID") + +// Start trial +analytics.track("Trial Started", properties: ...) +""" + + // Add the button + let createButton = UIButton.SegmentButton("Create Account", target: self, action: #selector(createUser(_:))) + trackButton = UIButton.SegmentButton("Start Trial", target: self, action: #selector(trackUser(_:))) + trackButton.isEnabled = false + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [createButton, UIView.separator(), trackButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private + func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Signup") + } + + @objc + func createUser(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("Create Account", properties: ["Signed Up": ["first": "Peter", "last": "Gibbons", "phone": "pgibbons"]]) + analytics.alias("AA-BB-CC-NEW-ID") + trackButton.isEnabled = true + } + + @objc func trackUser(_ sender: Any) { + let analytics = Analytics.shared() + // track user + analytics.track("Trial Started", properties: ["start_date": "2018-08-27"]) + + continueButton.isEnabled = true + } + + @objc + func continueToNext(_ sender: Any) { + let invite = InviteViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(invite, animated: true) + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/StartViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/StartViewController.swift new file mode 100644 index 000000000..99a42a0fb --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/StartViewController.swift @@ -0,0 +1,96 @@ +// +// ViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/1/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class StartViewController: UIViewController { + + @IBOutlet weak var tableView: UITableView! + @IBOutlet weak var writeKeyField: UITextField! + + private var storedKeys: Array? + + + override func viewDidLoad() { + super.viewDidLoad() + + title = "Start" + + // Do any additional setup after loading the view. + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "writeKeyCell") + + storedKeys = storedWriteKeys() + + Analytics.shared().flush() + } + + @IBAction + func login(_ sender: Any) { + + // Grab the current write key + guard let writeKey = writeKeyField.text else { return } + + // Store off the current write key + saveWriteKey(writeKey) + + let loginController = LoginViewController() + self.navigationController?.pushViewController(loginController, animated: true) + } + + private func storedWriteKeys() -> Array? { + var returnKeys: Array? + + if let existingKeys = UserDefaults.standard.object(forKey: "writekeys") as? Array { + returnKeys = existingKeys + } + + return returnKeys + } + + private func saveWriteKey(_ key: String) { + var writeKeys = [key] + if let keys = storedWriteKeys() { + + if !keys.contains(key) { + writeKeys.append(contentsOf: keys) + } else { + return + } + } + + UserDefaults.standard.set(writeKeys, forKey: "writekeys") + } +} + +extension StartViewController: UITableViewDataSource, UITableViewDelegate { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return storedWriteKeys()?.count ?? 0 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let returnCell = tableView.dequeueReusableCell(withIdentifier: "writeKeyCell") else { + return UITableViewCell() + } + returnCell.textLabel?.text = storedKeys?[indexPath.row] + returnCell.textLabel?.font = UIFont.systemFont(ofSize: 12.0) + return returnCell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + // Grab key from index + writeKeyField.text = storedKeys?[indexPath.row] + } + + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return "Write Keys" + } +} + diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/StepsViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/StepsViewController.swift new file mode 100644 index 000000000..99e4c778c --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/StepsViewController.swift @@ -0,0 +1,154 @@ +// +// StepsViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/3/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit + +class StepsViewController: UIViewController { + + var codeString: String? { + didSet { + codeView.text = codeString + } + } + + var descriptionString: String? { + didSet { + descriptionView.text = descriptionString + } + } + + var propertyViews: [UIView]? { + didSet { + stackView.removeFromSuperview() + setup() + } + } + + private var codeView: UITextView! + private var descriptionView: UILabel! + private var stackView: UIStackView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Titlebar setup + titleBarSetup() + + // Do any additional setup after loading the view. + setup() + } + + private func titleBarSetup() { + + let titleImageView = UIImageView(image: UIImage(named: "SegmentLogo")) + titleImageView.frame = CGRect(x: 0, y: 0, width: 193.0, height: 40.0) + titleImageView.contentMode = .scaleAspectFit + navigationItem.titleView = titleImageView + } + + private func setup() { + view.backgroundColor = UIColor.white + + stackView = UIStackView() + stackView.axis = .vertical + stackView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(stackView) + stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16.0).isActive = true + stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16.0).isActive = true + stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16.0).isActive = true + stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16.0).isActive = true + stackView.alignment = .leading + + if let propertyViews = propertyViews { + for (count, view) in propertyViews.enumerated() { + stackView.insertArrangedSubview(view, at: count) + view.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true + } + } + + let containerView = UIView(frame: .zero) + containerView.translatesAutoresizingMaskIntoConstraints = false + + descriptionView = UILabel(frame: .zero) + descriptionView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(descriptionView) + descriptionView.font = UIFont.systemFont(ofSize: 14.0) + descriptionView.textColor = UIColor.primaryColor02() + descriptionView.topAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.topAnchor).isActive = true + descriptionView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true + descriptionView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + descriptionView.numberOfLines = 0 + descriptionView.text = descriptionString + + codeView = UITextView(frame: .zero) + codeView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(codeView) + codeView.font = UIFont(name: "Menlo-Regular", size: 12.0) + codeView.textColor = UIColor.primaryColor02() + codeView.translatesAutoresizingMaskIntoConstraints = false + codeView.topAnchor.constraint(equalTo: descriptionView.bottomAnchor, constant: 16.0).isActive = true + codeView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true + codeView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + codeView.bottomAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.bottomAnchor).isActive = true + codeView.layer.borderColor = UIColor.primaryColor02().cgColor // 18 / 66 / 74 + codeView.layer.cornerRadius = 6.0 + codeView.text = codeString + + codeView.layer.borderWidth = 1.0 + codeView.backgroundColor = UIColor.secondaryColor01() // 204 / 217 / 222 + + stackView.addArrangedSubview(containerView) + containerView.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true + + // Theme + navigationController?.navigationBar.tintColor = UIColor.primaryColor01() + } +} + +extension UIColor { + // 204/217/222 + static func secondaryColor01() -> UIColor { + return UIColor(red: 0.8, green: 0.85, blue: 0.87, alpha: 1.0) + } + + // 18/66/74 + static func primaryColor02() -> UIColor { + return UIColor(red: 0.07, green: 0.26, blue: 0.29, alpha: 1.0) + } + + // 82 / 189 / 149 + static func primaryColor01() -> UIColor { + return UIColor(red: 0.32, green: 0.74, blue: 0.58, alpha: 1.0) + } + +} + +extension UIButton { + static func SegmentButton(_ title: String, target: Any, action: Selector) -> UIButton { + let trackButton = UIButton() + trackButton.setTitle(title, for: .normal) + trackButton.setTitleColor(UIColor.primaryColor02(), for: .normal) + trackButton.setTitleColor(UIColor.lightGray, for: .disabled) + trackButton.addTarget(target, action: action, for: .touchUpInside) + trackButton.titleLabel?.textColor = UIColor.primaryColor02() + trackButton.layer.borderColor = UIColor.primaryColor02().cgColor + trackButton.layer.borderWidth = 1.0 + trackButton.layer.cornerRadius = 6.0 + trackButton.contentEdgeInsets = UIEdgeInsets(top: 6, left: 8, bottom: 6, right: 8) + return trackButton + } +} + +extension UIView { + static func separator() -> UIView { + let separator = UIView() + separator.heightAnchor.constraint(equalToConstant: 12.0).isActive = true + separator.backgroundColor = .white + return separator + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Controllers/TrialEndViewController.swift b/Examples/FullExampleFlow/Analytics Example/Controllers/TrialEndViewController.swift new file mode 100644 index 000000000..6d68739ea --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Controllers/TrialEndViewController.swift @@ -0,0 +1,84 @@ +// +// TrialEndViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/29/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class TrialEndViewController: StepsViewController { + + let anonymousUserID = "70e4ab26-3c4d-42c9-aed1-2c186738a97d" + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// identify screen load +analytics.screen("Dashboard") + +// identify anonymous user +analytics.track("Trial Ended", properties: [...]) + +// track delete request +analytics.track("Account Delete request", properties: ["account_id": "AA-BB-CC-USER-ID"]) + +// removed user +analytics.track("Account Deleted", properties: ["username": "pgibbons", "account_id": "AA-BB-CC-USER-ID"]) + +// Signed out +analytics.track("Signed Out", properties: ["username": "pgibbons"]) +""" + + // Add the button + let deleteButton = UIButton.SegmentButton("Request Delete Account", target: self, action: #selector(deleteUser(_:))) + continueButton = UIButton.SegmentButton("Done", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [deleteButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Dashboard") + + // identify anonymous user + analytics.track("Trial Ended", properties: ["trial_start": "2020-06-29", "trial_end": "2020-06-30", "trial_plan": "premium"]) + } + + @objc + private func deleteUser(_ sender: Any) { + let analytics = Analytics.shared() + // track delete request + analytics.track("Account Delete request", properties: ["account_id": "AA-BB-CC-USER-ID"]) + + // Some async request + DispatchQueue.global().async { + // removed user + analytics.track("Account Deleted", properties: ["username": "pgibbons", "account_id": "AA-BB-CC-USER-ID"]) + // Signed out + analytics.track("Signed Out", properties: ["username": "pgibbons"]) + DispatchQueue.main.async { + self.continueButton.isEnabled = true + } + } + } + + @objc private func continueToNext(_ sender: Any) { + navigationController?.popToRootViewController(animated: true) + } +} diff --git a/Examples/FullExampleFlow/Analytics Example/Info.plist b/Examples/FullExampleFlow/Analytics Example/Info.plist new file mode 100644 index 000000000..2a3483c0d --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Examples/FullExampleFlow/Analytics Example/SceneDelegate.swift b/Examples/FullExampleFlow/Analytics Example/SceneDelegate.swift new file mode 100644 index 000000000..aae7896aa --- /dev/null +++ b/Examples/FullExampleFlow/Analytics Example/SceneDelegate.swift @@ -0,0 +1,53 @@ +// +// SceneDelegate.swift +// Analytics Example +// +// Created by Cody Garvin on 6/1/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.pbxproj b/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.pbxproj new file mode 100644 index 000000000..b754af4fe --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.pbxproj @@ -0,0 +1,454 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 52; + objects = { + +/* Begin PBXBuildFile section */ + 9616DB59249050A600F7191B /* SignupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9616DB58249050A600F7191B /* SignupViewController.swift */; }; + 9616DB5B2490583800F7191B /* InviteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9616DB5A2490583800F7191B /* InviteViewController.swift */; }; + 961C616A24BE58FE00A8B8E3 /* Analytics in Frameworks */ = {isa = PBXBuildFile; productRef = 961C616924BE58FE00A8B8E3 /* Analytics */; }; + 961D80C024902143007C4F04 /* AnonymousViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961D80BC24902143007C4F04 /* AnonymousViewController.swift */; }; + 96BC0E4A24A57317000AF2EB /* SignoutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BC0E4924A57317000AF2EB /* SignoutViewController.swift */; }; + 96BC0E4C24A693E3000AF2EB /* SignInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BC0E4B24A693E3000AF2EB /* SignInViewController.swift */; }; + 96BC0E5124AA72F6000AF2EB /* TrialEndViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BC0E5024AA72F6000AF2EB /* TrialEndViewController.swift */; }; + 96D0441F2485B458009C3FD7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D0441E2485B458009C3FD7 /* AppDelegate.swift */; }; + 96D044212485B458009C3FD7 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D044202485B458009C3FD7 /* SceneDelegate.swift */; }; + 96D044232485B458009C3FD7 /* StartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D044222485B458009C3FD7 /* StartViewController.swift */; }; + 96D044262485B458009C3FD7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96D044242485B458009C3FD7 /* Main.storyboard */; }; + 96D044282485B459009C3FD7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96D044272485B459009C3FD7 /* Assets.xcassets */; }; + 96D0442B2485B459009C3FD7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96D044292485B459009C3FD7 /* LaunchScreen.storyboard */; }; + 96EC569B2488567500B636AC /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96EC569A2488567500B636AC /* LoginViewController.swift */; }; + 96EC569D2488568D00B636AC /* StepsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96EC569C2488568D00B636AC /* StepsViewController.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 96D044422485B541009C3FD7 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 9616DB58249050A600F7191B /* SignupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignupViewController.swift; sourceTree = ""; }; + 9616DB5A2490583800F7191B /* InviteViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InviteViewController.swift; sourceTree = ""; }; + 961D80BC24902143007C4F04 /* AnonymousViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnonymousViewController.swift; sourceTree = ""; }; + 96A12BC024B6448900949804 /* Analytics Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Analytics Example.entitlements"; sourceTree = ""; }; + 96BC0E4924A57317000AF2EB /* SignoutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignoutViewController.swift; sourceTree = ""; }; + 96BC0E4B24A693E3000AF2EB /* SignInViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignInViewController.swift; sourceTree = ""; }; + 96BC0E5024AA72F6000AF2EB /* TrialEndViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrialEndViewController.swift; sourceTree = ""; }; + 96D0441B2485B458009C3FD7 /* Analytics Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Analytics Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 96D0441E2485B458009C3FD7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 96D044202485B458009C3FD7 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 96D044222485B458009C3FD7 /* StartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartViewController.swift; sourceTree = ""; }; + 96D044252485B458009C3FD7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 96D044272485B459009C3FD7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 96D0442A2485B459009C3FD7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 96D0442C2485B459009C3FD7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 96EC569A2488567500B636AC /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; }; + 96EC569C2488568D00B636AC /* StepsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepsViewController.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 96D044182485B458009C3FD7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 961C616A24BE58FE00A8B8E3 /* Analytics in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 96D044122485B458009C3FD7 = { + isa = PBXGroup; + children = ( + 96D0441D2485B458009C3FD7 /* Analytics Example */, + 96D0441C2485B458009C3FD7 /* Products */, + 96D0443F2485B541009C3FD7 /* Frameworks */, + ); + sourceTree = ""; + }; + 96D0441C2485B458009C3FD7 /* Products */ = { + isa = PBXGroup; + children = ( + 96D0441B2485B458009C3FD7 /* Analytics Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 96D0441D2485B458009C3FD7 /* Analytics Example */ = { + isa = PBXGroup; + children = ( + 96A12BC024B6448900949804 /* Analytics Example.entitlements */, + 96EC5699248855F800B636AC /* Controllers */, + 96D0441E2485B458009C3FD7 /* AppDelegate.swift */, + 96D044272485B459009C3FD7 /* Assets.xcassets */, + 96D0442C2485B459009C3FD7 /* Info.plist */, + 96D044292485B459009C3FD7 /* LaunchScreen.storyboard */, + 96D044242485B458009C3FD7 /* Main.storyboard */, + 96D044202485B458009C3FD7 /* SceneDelegate.swift */, + ); + path = "Analytics Example"; + sourceTree = ""; + }; + 96D0443F2485B541009C3FD7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + 96EC5699248855F800B636AC /* Controllers */ = { + isa = PBXGroup; + children = ( + 961D80BC24902143007C4F04 /* AnonymousViewController.swift */, + 9616DB5A2490583800F7191B /* InviteViewController.swift */, + 96EC569A2488567500B636AC /* LoginViewController.swift */, + 96BC0E4B24A693E3000AF2EB /* SignInViewController.swift */, + 96BC0E4924A57317000AF2EB /* SignoutViewController.swift */, + 9616DB58249050A600F7191B /* SignupViewController.swift */, + 96D044222485B458009C3FD7 /* StartViewController.swift */, + 96EC569C2488568D00B636AC /* StepsViewController.swift */, + 96BC0E5024AA72F6000AF2EB /* TrialEndViewController.swift */, + ); + path = Controllers; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 96D0441A2485B458009C3FD7 /* Analytics Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 96D0442F2485B459009C3FD7 /* Build configuration list for PBXNativeTarget "Analytics Example" */; + buildPhases = ( + 96D044172485B458009C3FD7 /* Sources */, + 96D044182485B458009C3FD7 /* Frameworks */, + 96D044192485B458009C3FD7 /* Resources */, + 96D044422485B541009C3FD7 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Analytics Example"; + packageProductDependencies = ( + 961C616924BE58FE00A8B8E3 /* Analytics */, + ); + productName = "Analytics Example"; + productReference = 96D0441B2485B458009C3FD7 /* Analytics Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 96D044132485B458009C3FD7 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1150; + LastUpgradeCheck = 1150; + ORGANIZATIONNAME = "Cody Garvin"; + TargetAttributes = { + 96D0441A2485B458009C3FD7 = { + CreatedOnToolsVersion = 11.5; + }; + }; + }; + buildConfigurationList = 96D044162485B458009C3FD7 /* Build configuration list for PBXProject "Analytics Example" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 96D044122485B458009C3FD7; + packageReferences = ( + 961C616824BE58FE00A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */, + ); + productRefGroup = 96D0441C2485B458009C3FD7 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 96D0441A2485B458009C3FD7 /* Analytics Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 96D044192485B458009C3FD7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96D0442B2485B459009C3FD7 /* LaunchScreen.storyboard in Resources */, + 96D044282485B459009C3FD7 /* Assets.xcassets in Resources */, + 96D044262485B458009C3FD7 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 96D044172485B458009C3FD7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96EC569B2488567500B636AC /* LoginViewController.swift in Sources */, + 96BC0E4A24A57317000AF2EB /* SignoutViewController.swift in Sources */, + 96BC0E5124AA72F6000AF2EB /* TrialEndViewController.swift in Sources */, + 9616DB59249050A600F7191B /* SignupViewController.swift in Sources */, + 96D044232485B458009C3FD7 /* StartViewController.swift in Sources */, + 9616DB5B2490583800F7191B /* InviteViewController.swift in Sources */, + 96D0441F2485B458009C3FD7 /* AppDelegate.swift in Sources */, + 96D044212485B458009C3FD7 /* SceneDelegate.swift in Sources */, + 961D80C024902143007C4F04 /* AnonymousViewController.swift in Sources */, + 96BC0E4C24A693E3000AF2EB /* SignInViewController.swift in Sources */, + 96EC569D2488568D00B636AC /* StepsViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 96D044242485B458009C3FD7 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 96D044252485B458009C3FD7 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 96D044292485B459009C3FD7 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 96D0442A2485B459009C3FD7 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 96D0442D2485B459009C3FD7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 96D0442E2485B459009C3FD7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 96D044302485B459009C3FD7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = "Analytics Example/Analytics Example.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = "Analytics Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.Segment.Analytics-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; + SUPPORTS_MACCATALYST = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 96D044312485B459009C3FD7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = "Analytics Example/Analytics Example.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = "Analytics Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.Segment.Analytics-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; + SUPPORTS_MACCATALYST = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 96D044162485B458009C3FD7 /* Build configuration list for PBXProject "Analytics Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96D0442D2485B459009C3FD7 /* Debug */, + 96D0442E2485B459009C3FD7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 96D0442F2485B459009C3FD7 /* Build configuration list for PBXNativeTarget "Analytics Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96D044302485B459009C3FD7 /* Debug */, + 96D044312485B459009C3FD7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 961C616824BE58FE00A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/segmentio/analytics-ios.git"; + requirement = { + branch = migs647/macconversion; + kind = branch; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 961C616924BE58FE00A8B8E3 /* Analytics */ = { + isa = XCSwiftPackageProductDependency; + package = 961C616824BE58FE00A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */; + productName = Analytics; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 96D044132485B458009C3FD7 /* Project object */; +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..0f9179535 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "Analytics", + "repositoryURL": "https://github.com/segmentio/analytics-ios.git", + "state": { + "branch": "migs647/macconversion", + "revision": "af24593f99aece20a54ea855ff8220acd5ab01fd", + "version": null + } + } + ] + }, + "version": 1 +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Analytics Example.entitlements b/Examples/FullExampleFlowCatalyst/Analytics Example/Analytics Example.entitlements new file mode 100644 index 000000000..ee95ab7e5 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Analytics Example.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/AppDelegate.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/AppDelegate.swift new file mode 100644 index 000000000..8f4a0e8be --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/AppDelegate.swift @@ -0,0 +1,43 @@ +// +// AppDelegate.swift +// Analytics Example +// +// Created by Cody Garvin on 6/1/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + let configuration = AnalyticsConfiguration(writeKey: "8XpdAWa7qJVBJMK8V4FfXQOrnvCzu3Ie") + + // Enable this to record certain application events automatically! + configuration.trackApplicationLifecycleEvents = true + // Enable this to record screen views automatically! + configuration.recordScreenViews = true + Analytics.setup(with: configuration) + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..831a94286 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,101 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "Icon_120.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "Icon_180.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "Icon.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon.png b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..27e190425e02971dbb7a98d0cc834af4e280566e GIT binary patch literal 102508 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 literal 0 HcmV?d00001 diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_120.png b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_120.png new file mode 100644 index 0000000000000000000000000000000000000000..408a7ccf7be2c5a2ebe7f49cf63a9c34c3a2c636 GIT binary patch literal 10223 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 literal 0 HcmV?d00001 diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_180.png b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/AppIcon.appiconset/Icon_180.png new file mode 100644 index 0000000000000000000000000000000000000000..55966b3b686498a2cf10fe0e325ae827de791fc5 GIT binary patch literal 17086 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 B>RbQ- literal 0 HcmV?d00001 diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Contents.json b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Contents.json b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Contents.json new file mode 100644 index 000000000..d7353623d --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "Segment_Logo.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Segment_Logo@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Segment_Logo.png b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/SegmentLogo.imageset/Segment_Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5fd84c71234e1c0dfd6bb26e0edd3282f091baf2 GIT binary patch literal 9072 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 JD`6b`e*n4G)=U5Z literal 0 HcmV?d00001 diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Splash.imageset/Contents.json b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Splash.imageset/Contents.json new file mode 100644 index 000000000..e5cd8ada4 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Splash.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Splash.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Splash.imageset/Splash.png b/Examples/FullExampleFlowCatalyst/Analytics Example/Assets.xcassets/Splash.imageset/Splash.png new file mode 100644 index 0000000000000000000000000000000000000000..9057e4473e74ae8fff9632736b7fa72bf3f7215e GIT binary patch literal 33969 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Base.lproj/Main.storyboard b/Examples/FullExampleFlowCatalyst/Analytics Example/Base.lproj/Main.storyboard new file mode 100644 index 000000000..205a35644 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Base.lproj/Main.storyboard @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/AnonymousViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/AnonymousViewController.swift new file mode 100644 index 000000000..12b002204 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/AnonymousViewController.swift @@ -0,0 +1,75 @@ +// +// AnonymousViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/3/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class AnonymousViewController: StepsViewController { + + let anonymousUserID = "70e4ab26-3c4d-42c9-aed1-2c186738a97d" + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// identify screen load (sends anonymous id) +analytics.screen("Home") + +// identify with anonymous user +analytics.identify(nil, traits: ["subscription": "inactive"]) + +// track CTA tap (sends anonymous id) +analytics.track("CTA Tapped", properties: ["plan": "premium"]) +""" + + // Add the button + let trackButton = UIButton.SegmentButton("Track", target: self, action: #selector(trackUser(_:))) + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [trackButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + continueButton.isEnabled = false + } + + private func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Home") + + // identify anonymous user + analytics.identify(nil, traits: ["subscription": "inactive"]) + } + + @objc + private func trackUser(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("CTA Tapped", properties: ["plan": "premium"]) + + continueButton.isEnabled = true + } + + @objc private func continueToNext(_ sender: Any) { + let signup = SignupViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(signup, animated: true) + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/InviteViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/InviteViewController.swift new file mode 100644 index 000000000..69687f9b0 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/InviteViewController.swift @@ -0,0 +1,63 @@ +// +// InviteViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/25/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class InviteViewController: StepsViewController { + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// Screen +analytics.screen("Invite") + +// Invite user +analytics.track("Invite Sent", properties: ["first": "Jane", "last": "Doe", "email": "jane@abc.com"]) +""" + + // Add the button + let inviteButton = UIButton.SegmentButton("Invite Yser", target: self, action: #selector(createUser(_:))) + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [inviteButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private + func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Invite") + } + + @objc + func createUser(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("Invite Sent", properties: ["first": "Jane", "last": "Doe", "email": "jane@abc.com"]) + continueButton.isEnabled = true + } + + @objc + func continueToNext(_ sender: Any) { + let signoutVC = SignoutViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(signoutVC, animated: true) + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/LoginViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/LoginViewController.swift new file mode 100644 index 000000000..d69eb7f0f --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/LoginViewController.swift @@ -0,0 +1,27 @@ +// +// LoginViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/3/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit + +class LoginViewController: StepsViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + title = "Login Example" + descriptionString = "Login with details using identify" + codeString = """ +// Start by identifying the user +if let analytics = Analytics.shared() +Analytics.shared().identify("1234", + traits: ["email": "jack@segment.com", + "phone": "555-444-3333"]) +""" + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignInViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignInViewController.swift new file mode 100644 index 000000000..39fcfedb7 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignInViewController.swift @@ -0,0 +1,63 @@ +// +// SigninViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/9/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class SigninViewController: StepsViewController { + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// Screen +analytics.screen("Dashboard") + +// Signed in +analytics.track("Signed In", properties: ["username": "pgibbons"]) +""" + + // Add the button + let signinButton = UIButton.SegmentButton("Sign In", target: self, action: #selector(signin(_:))) + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [signinButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private + func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Dashboard") + } + + @objc + func signin(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("Signed In", properties: ["username": "pgibbons"]) + continueButton.isEnabled = true + } + + @objc + func continueToNext(_ sender: Any) { + let trailEndVC = TrialEndViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(trailEndVC, animated: true) + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignoutViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignoutViewController.swift new file mode 100644 index 000000000..3672c5998 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignoutViewController.swift @@ -0,0 +1,63 @@ +// +// SignoutViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/9/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class SignoutViewController: StepsViewController { + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// Screen +analytics.screen("Signout") + +// Signout user +analytics.track("Signed Out", properties: ["username": "pgibbons"]) +""" + + // Add the button + let signoutButton = UIButton.SegmentButton("Signout", target: self, action: #selector(signout(_:))) + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [signoutButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private + func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Signout") + } + + @objc + func signout(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("Signed Out", properties: ["username": "pgibbons"]) + continueButton.isEnabled = true + } + + @objc + func continueToNext(_ sender: Any) { + let signinVC = SigninViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(signinVC, animated: true) + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignupViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignupViewController.swift new file mode 100644 index 000000000..14050cd41 --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/SignupViewController.swift @@ -0,0 +1,81 @@ +// +// SignupViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/9/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class SignupViewController: StepsViewController { + + private var continueButton: UIButton! + private var trackButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// Screen +analytics.screen("Signup") + +// create user +analytics.track("Create Account", properties: ["Signed Up": ...]) + +// Alias new user id with anonymous id +analytics.alias("AA-BB-CC-NEW-ID") + +// Start trial +analytics.track("Trial Started", properties: ...) +""" + + // Add the button + let createButton = UIButton.SegmentButton("Create Account", target: self, action: #selector(createUser(_:))) + trackButton = UIButton.SegmentButton("Start Trial", target: self, action: #selector(trackUser(_:))) + trackButton.isEnabled = false + continueButton = UIButton.SegmentButton("Continue", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [createButton, UIView.separator(), trackButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private + func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Signup") + } + + @objc + func createUser(_ sender: Any) { + let analytics = Analytics.shared() + // track CTA tap + analytics.track("Create Account", properties: ["Signed Up": ["first": "Peter", "last": "Gibbons", "phone": "pgibbons"]]) + analytics.alias("AA-BB-CC-NEW-ID") + trackButton.isEnabled = true + } + + @objc func trackUser(_ sender: Any) { + let analytics = Analytics.shared() + // track user + analytics.track("Trial Started", properties: ["start_date": "2018-08-27"]) + + continueButton.isEnabled = true + } + + @objc + func continueToNext(_ sender: Any) { + let invite = InviteViewController(nibName: nil, bundle: nil) + navigationController?.pushViewController(invite, animated: true) + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/StartViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/StartViewController.swift new file mode 100644 index 000000000..99a42a0fb --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/StartViewController.swift @@ -0,0 +1,96 @@ +// +// ViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/1/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class StartViewController: UIViewController { + + @IBOutlet weak var tableView: UITableView! + @IBOutlet weak var writeKeyField: UITextField! + + private var storedKeys: Array? + + + override func viewDidLoad() { + super.viewDidLoad() + + title = "Start" + + // Do any additional setup after loading the view. + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "writeKeyCell") + + storedKeys = storedWriteKeys() + + Analytics.shared().flush() + } + + @IBAction + func login(_ sender: Any) { + + // Grab the current write key + guard let writeKey = writeKeyField.text else { return } + + // Store off the current write key + saveWriteKey(writeKey) + + let loginController = LoginViewController() + self.navigationController?.pushViewController(loginController, animated: true) + } + + private func storedWriteKeys() -> Array? { + var returnKeys: Array? + + if let existingKeys = UserDefaults.standard.object(forKey: "writekeys") as? Array { + returnKeys = existingKeys + } + + return returnKeys + } + + private func saveWriteKey(_ key: String) { + var writeKeys = [key] + if let keys = storedWriteKeys() { + + if !keys.contains(key) { + writeKeys.append(contentsOf: keys) + } else { + return + } + } + + UserDefaults.standard.set(writeKeys, forKey: "writekeys") + } +} + +extension StartViewController: UITableViewDataSource, UITableViewDelegate { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return storedWriteKeys()?.count ?? 0 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let returnCell = tableView.dequeueReusableCell(withIdentifier: "writeKeyCell") else { + return UITableViewCell() + } + returnCell.textLabel?.text = storedKeys?[indexPath.row] + returnCell.textLabel?.font = UIFont.systemFont(ofSize: 12.0) + return returnCell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + // Grab key from index + writeKeyField.text = storedKeys?[indexPath.row] + } + + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return "Write Keys" + } +} + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/StepsViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/StepsViewController.swift new file mode 100644 index 000000000..99e4c778c --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/StepsViewController.swift @@ -0,0 +1,154 @@ +// +// StepsViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/3/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit + +class StepsViewController: UIViewController { + + var codeString: String? { + didSet { + codeView.text = codeString + } + } + + var descriptionString: String? { + didSet { + descriptionView.text = descriptionString + } + } + + var propertyViews: [UIView]? { + didSet { + stackView.removeFromSuperview() + setup() + } + } + + private var codeView: UITextView! + private var descriptionView: UILabel! + private var stackView: UIStackView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Titlebar setup + titleBarSetup() + + // Do any additional setup after loading the view. + setup() + } + + private func titleBarSetup() { + + let titleImageView = UIImageView(image: UIImage(named: "SegmentLogo")) + titleImageView.frame = CGRect(x: 0, y: 0, width: 193.0, height: 40.0) + titleImageView.contentMode = .scaleAspectFit + navigationItem.titleView = titleImageView + } + + private func setup() { + view.backgroundColor = UIColor.white + + stackView = UIStackView() + stackView.axis = .vertical + stackView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(stackView) + stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16.0).isActive = true + stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16.0).isActive = true + stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16.0).isActive = true + stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16.0).isActive = true + stackView.alignment = .leading + + if let propertyViews = propertyViews { + for (count, view) in propertyViews.enumerated() { + stackView.insertArrangedSubview(view, at: count) + view.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true + } + } + + let containerView = UIView(frame: .zero) + containerView.translatesAutoresizingMaskIntoConstraints = false + + descriptionView = UILabel(frame: .zero) + descriptionView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(descriptionView) + descriptionView.font = UIFont.systemFont(ofSize: 14.0) + descriptionView.textColor = UIColor.primaryColor02() + descriptionView.topAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.topAnchor).isActive = true + descriptionView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true + descriptionView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + descriptionView.numberOfLines = 0 + descriptionView.text = descriptionString + + codeView = UITextView(frame: .zero) + codeView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(codeView) + codeView.font = UIFont(name: "Menlo-Regular", size: 12.0) + codeView.textColor = UIColor.primaryColor02() + codeView.translatesAutoresizingMaskIntoConstraints = false + codeView.topAnchor.constraint(equalTo: descriptionView.bottomAnchor, constant: 16.0).isActive = true + codeView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true + codeView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + codeView.bottomAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.bottomAnchor).isActive = true + codeView.layer.borderColor = UIColor.primaryColor02().cgColor // 18 / 66 / 74 + codeView.layer.cornerRadius = 6.0 + codeView.text = codeString + + codeView.layer.borderWidth = 1.0 + codeView.backgroundColor = UIColor.secondaryColor01() // 204 / 217 / 222 + + stackView.addArrangedSubview(containerView) + containerView.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true + + // Theme + navigationController?.navigationBar.tintColor = UIColor.primaryColor01() + } +} + +extension UIColor { + // 204/217/222 + static func secondaryColor01() -> UIColor { + return UIColor(red: 0.8, green: 0.85, blue: 0.87, alpha: 1.0) + } + + // 18/66/74 + static func primaryColor02() -> UIColor { + return UIColor(red: 0.07, green: 0.26, blue: 0.29, alpha: 1.0) + } + + // 82 / 189 / 149 + static func primaryColor01() -> UIColor { + return UIColor(red: 0.32, green: 0.74, blue: 0.58, alpha: 1.0) + } + +} + +extension UIButton { + static func SegmentButton(_ title: String, target: Any, action: Selector) -> UIButton { + let trackButton = UIButton() + trackButton.setTitle(title, for: .normal) + trackButton.setTitleColor(UIColor.primaryColor02(), for: .normal) + trackButton.setTitleColor(UIColor.lightGray, for: .disabled) + trackButton.addTarget(target, action: action, for: .touchUpInside) + trackButton.titleLabel?.textColor = UIColor.primaryColor02() + trackButton.layer.borderColor = UIColor.primaryColor02().cgColor + trackButton.layer.borderWidth = 1.0 + trackButton.layer.cornerRadius = 6.0 + trackButton.contentEdgeInsets = UIEdgeInsets(top: 6, left: 8, bottom: 6, right: 8) + return trackButton + } +} + +extension UIView { + static func separator() -> UIView { + let separator = UIView() + separator.heightAnchor.constraint(equalToConstant: 12.0).isActive = true + separator.backgroundColor = .white + return separator + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/TrialEndViewController.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/TrialEndViewController.swift new file mode 100644 index 000000000..6d68739ea --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Controllers/TrialEndViewController.swift @@ -0,0 +1,84 @@ +// +// TrialEndViewController.swift +// Analytics Example +// +// Created by Cody Garvin on 6/29/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit +import Analytics + +class TrialEndViewController: StepsViewController { + + let anonymousUserID = "70e4ab26-3c4d-42c9-aed1-2c186738a97d" + + private var continueButton: UIButton! + + override func viewDidLoad() { + super.viewDidLoad() + + descriptionString = "Login with details using identify" + codeString = """ +// Start with the analytics singleton +let analytics = Analytics.shared() + +// identify screen load +analytics.screen("Dashboard") + +// identify anonymous user +analytics.track("Trial Ended", properties: [...]) + +// track delete request +analytics.track("Account Delete request", properties: ["account_id": "AA-BB-CC-USER-ID"]) + +// removed user +analytics.track("Account Deleted", properties: ["username": "pgibbons", "account_id": "AA-BB-CC-USER-ID"]) + +// Signed out +analytics.track("Signed Out", properties: ["username": "pgibbons"]) +""" + + // Add the button + let deleteButton = UIButton.SegmentButton("Request Delete Account", target: self, action: #selector(deleteUser(_:))) + continueButton = UIButton.SegmentButton("Done", target: self, action: #selector(continueToNext(_:))) + continueButton.isEnabled = false + + propertyViews = [deleteButton, UIView.separator(), continueButton, UIView.separator()] + + // Fire off the beginning analytics + startAnalytics() + } + + private func startAnalytics() { + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("Dashboard") + + // identify anonymous user + analytics.track("Trial Ended", properties: ["trial_start": "2020-06-29", "trial_end": "2020-06-30", "trial_plan": "premium"]) + } + + @objc + private func deleteUser(_ sender: Any) { + let analytics = Analytics.shared() + // track delete request + analytics.track("Account Delete request", properties: ["account_id": "AA-BB-CC-USER-ID"]) + + // Some async request + DispatchQueue.global().async { + // removed user + analytics.track("Account Deleted", properties: ["username": "pgibbons", "account_id": "AA-BB-CC-USER-ID"]) + // Signed out + analytics.track("Signed Out", properties: ["username": "pgibbons"]) + DispatchQueue.main.async { + self.continueButton.isEnabled = true + } + } + } + + @objc private func continueToNext(_ sender: Any) { + navigationController?.popToRootViewController(animated: true) + } +} diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/Info.plist b/Examples/FullExampleFlowCatalyst/Analytics Example/Info.plist new file mode 100644 index 000000000..2a3483c0d --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Examples/FullExampleFlowCatalyst/Analytics Example/SceneDelegate.swift b/Examples/FullExampleFlowCatalyst/Analytics Example/SceneDelegate.swift new file mode 100644 index 000000000..aae7896aa --- /dev/null +++ b/Examples/FullExampleFlowCatalyst/Analytics Example/SceneDelegate.swift @@ -0,0 +1,53 @@ +// +// SceneDelegate.swift +// Analytics Example +// +// Created by Cody Garvin on 6/1/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/Examples/SegmentMac/SegmentMac.xcodeproj/project.pbxproj b/Examples/SegmentMac/SegmentMac.xcodeproj/project.pbxproj new file mode 100644 index 000000000..097eb5d26 --- /dev/null +++ b/Examples/SegmentMac/SegmentMac.xcodeproj/project.pbxproj @@ -0,0 +1,381 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 52; + objects = { + +/* Begin PBXBuildFile section */ + 961C616D24BE5BA200A8B8E3 /* Analytics in Frameworks */ = {isa = PBXBuildFile; productRef = 961C616C24BE5BA200A8B8E3 /* Analytics */; }; + 96A12BAE24B3AEE200949804 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A12BAD24B3AEE200949804 /* AppDelegate.swift */; }; + 96A12BB024B3AEE200949804 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A12BAF24B3AEE200949804 /* ViewController.swift */; }; + 96A12BB224B3AEE400949804 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96A12BB124B3AEE400949804 /* Assets.xcassets */; }; + 96A12BB524B3AEE400949804 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96A12BB324B3AEE400949804 /* Main.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 96A12C2524B65F5F00949804 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 96A12BAA24B3AEE200949804 /* SegmentMac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SegmentMac.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 96A12BAD24B3AEE200949804 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 96A12BAF24B3AEE200949804 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 96A12BB124B3AEE400949804 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 96A12BB424B3AEE400949804 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 96A12BB624B3AEE400949804 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 96A12BB724B3AEE400949804 /* SegmentMac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SegmentMac.entitlements; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 96A12BA724B3AEE200949804 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 961C616D24BE5BA200A8B8E3 /* Analytics in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 96A12BA124B3AEE200949804 = { + isa = PBXGroup; + children = ( + 96A12BAC24B3AEE200949804 /* SegmentMac */, + 96A12BAB24B3AEE200949804 /* Products */, + 96A12C0B24B65C4C00949804 /* Frameworks */, + ); + sourceTree = ""; + }; + 96A12BAB24B3AEE200949804 /* Products */ = { + isa = PBXGroup; + children = ( + 96A12BAA24B3AEE200949804 /* SegmentMac.app */, + ); + name = Products; + sourceTree = ""; + }; + 96A12BAC24B3AEE200949804 /* SegmentMac */ = { + isa = PBXGroup; + children = ( + 96A12BAD24B3AEE200949804 /* AppDelegate.swift */, + 96A12BAF24B3AEE200949804 /* ViewController.swift */, + 96A12BB124B3AEE400949804 /* Assets.xcassets */, + 96A12BB324B3AEE400949804 /* Main.storyboard */, + 96A12BB624B3AEE400949804 /* Info.plist */, + 96A12BB724B3AEE400949804 /* SegmentMac.entitlements */, + ); + path = SegmentMac; + sourceTree = ""; + }; + 96A12C0B24B65C4C00949804 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 96A12BA924B3AEE200949804 /* SegmentMac */ = { + isa = PBXNativeTarget; + buildConfigurationList = 96A12BBA24B3AEE400949804 /* Build configuration list for PBXNativeTarget "SegmentMac" */; + buildPhases = ( + 96A12BA624B3AEE200949804 /* Sources */, + 96A12BA724B3AEE200949804 /* Frameworks */, + 96A12BA824B3AEE200949804 /* Resources */, + 96A12C2524B65F5F00949804 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SegmentMac; + packageProductDependencies = ( + 961C616C24BE5BA200A8B8E3 /* Analytics */, + ); + productName = SegmentMac; + productReference = 96A12BAA24B3AEE200949804 /* SegmentMac.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 96A12BA224B3AEE200949804 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1150; + LastUpgradeCheck = 1150; + ORGANIZATIONNAME = "Cody Garvin"; + TargetAttributes = { + 96A12BA924B3AEE200949804 = { + CreatedOnToolsVersion = 11.5; + }; + }; + }; + buildConfigurationList = 96A12BA524B3AEE200949804 /* Build configuration list for PBXProject "SegmentMac" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 96A12BA124B3AEE200949804; + packageReferences = ( + 961C616B24BE5BA200A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */, + ); + productRefGroup = 96A12BAB24B3AEE200949804 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 96A12BA924B3AEE200949804 /* SegmentMac */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 96A12BA824B3AEE200949804 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96A12BB224B3AEE400949804 /* Assets.xcassets in Resources */, + 96A12BB524B3AEE400949804 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 96A12BA624B3AEE200949804 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96A12BB024B3AEE200949804 /* ViewController.swift in Sources */, + 96A12BAE24B3AEE200949804 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 96A12BB324B3AEE400949804 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 96A12BB424B3AEE400949804 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 96A12BB824B3AEE400949804 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 96A12BB924B3AEE400949804 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 96A12BBB24B3AEE400949804 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = SegmentMac/SegmentMac.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = SegmentMac/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.Segment.SegmentMac; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 96A12BBC24B3AEE400949804 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = SegmentMac/SegmentMac.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = SegmentMac/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.Segment.SegmentMac; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 96A12BA524B3AEE200949804 /* Build configuration list for PBXProject "SegmentMac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96A12BB824B3AEE400949804 /* Debug */, + 96A12BB924B3AEE400949804 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 96A12BBA24B3AEE400949804 /* Build configuration list for PBXNativeTarget "SegmentMac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96A12BBB24B3AEE400949804 /* Debug */, + 96A12BBC24B3AEE400949804 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 961C616B24BE5BA200A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/segmentio/analytics-ios.git"; + requirement = { + branch = migs647/macconversion; + kind = branch; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 961C616C24BE5BA200A8B8E3 /* Analytics */ = { + isa = XCSwiftPackageProductDependency; + package = 961C616B24BE5BA200A8B8E3 /* XCRemoteSwiftPackageReference "analytics-ios" */; + productName = Analytics; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 96A12BA224B3AEE200949804 /* Project object */; +} diff --git a/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..5302431a3 --- /dev/null +++ b/Examples/SegmentMac/SegmentMac.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "Analytics", + "repositoryURL": "https://github.com/segmentio/analytics-ios.git", + "state": { + "branch": "migs647/macconversion", + "revision": "bd012c2c3fe26e228bdf386a7e38c0a6b4b761fc", + "version": null + } + } + ] + }, + "version": 1 +} diff --git a/Examples/SegmentMac/SegmentMac/AppDelegate.swift b/Examples/SegmentMac/SegmentMac/AppDelegate.swift new file mode 100644 index 000000000..ec0d1e83d --- /dev/null +++ b/Examples/SegmentMac/SegmentMac/AppDelegate.swift @@ -0,0 +1,24 @@ +// +// AppDelegate.swift +// SegmentMac +// +// Created by Cody Garvin on 7/6/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + func applicationDidFinishLaunching(_ aNotification: Notification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + + +} + diff --git a/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..b3f2e5f2f --- /dev/null +++ b/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "filename" : "Segment_Logo-16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "Segment_Logo-33.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "Segment_Logo-32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "Segment_Logo-64.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "Segment_Logo-128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "Segment_Logo-257.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "Segment_Logo-256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "Segment_Logo-513.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "Segment_Logo-512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "Segment_Logo-1024.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-1024.png b/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-1024.png new file mode 100644 index 0000000000000000000000000000000000000000..b571a315b6319ed51b467f6683dfeffd51a199d9 GIT binary patch literal 66945 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
X-DC8?@LhV{&BnZiIUN0?9=k(3f?lO)LZKo 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 literal 0 HcmV?d00001 diff --git a/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-257.png b/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-257.png new file mode 100644 index 0000000000000000000000000000000000000000..0e0993ddc65ff631bc2eaaa53df2a388995607ee GIT binary patch literal 16421 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 literal 0 HcmV?d00001 diff --git a/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-32.png b/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-32.png new file mode 100644 index 0000000000000000000000000000000000000000..cb1a61adf93dd2b01cfd5ae96a6f6f901837754a GIT binary patch literal 1959 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 literal 0 HcmV?d00001 diff --git a/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-33.png b/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-33.png new file mode 100644 index 0000000000000000000000000000000000000000..cb1a61adf93dd2b01cfd5ae96a6f6f901837754a GIT binary patch literal 1959 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 literal 0 HcmV?d00001 diff --git a/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-512.png b/Examples/SegmentMac/SegmentMac/Assets.xcassets/AppIcon.appiconset/Segment_Logo-512.png new file mode 100644 index 0000000000000000000000000000000000000000..490efeba7b7d923f51ce43920b31501b838a7ff8 GIT binary patch literal 34641 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
  • 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 apKv)3qnREFy&EO3K~wd<%BOqQFa8Hp#|u;d literal 0 HcmV?d00001 diff --git a/Examples/SegmentMac/SegmentMac/Base.lproj/Main.storyboard b/Examples/SegmentMac/SegmentMac/Base.lproj/Main.storyboard new file mode 100644 index 000000000..00138b032 --- /dev/null +++ b/Examples/SegmentMac/SegmentMac/Base.lproj/Main.storyboard @@ -0,0 +1,777 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/SegmentMac/SegmentMac/Info.plist b/Examples/SegmentMac/SegmentMac/Info.plist new file mode 100644 index 000000000..a8959609d --- /dev/null +++ b/Examples/SegmentMac/SegmentMac/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2020 Cody Garvin. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + NSSupportsAutomaticTermination + + NSSupportsSuddenTermination + + + diff --git a/Examples/SegmentMac/SegmentMac/SegmentMac.entitlements b/Examples/SegmentMac/SegmentMac/SegmentMac.entitlements new file mode 100644 index 000000000..40b639e46 --- /dev/null +++ b/Examples/SegmentMac/SegmentMac/SegmentMac.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/Examples/SegmentMac/SegmentMac/ViewController.swift b/Examples/SegmentMac/SegmentMac/ViewController.swift new file mode 100644 index 000000000..c6263110e --- /dev/null +++ b/Examples/SegmentMac/SegmentMac/ViewController.swift @@ -0,0 +1,57 @@ +// +// ViewController.swift +// SegmentMac +// +// Created by Cody Garvin on 7/6/20. +// Copyright © 2020 Cody Garvin. All rights reserved. +// + +import Cocoa +import Analytics + +class ViewController: NSViewController { + + @IBOutlet weak var signinButton: NSButton! + @IBOutlet weak var associateButton: NSButton! + @IBOutlet weak var signoutButton: NSButton! + + override func viewDidLoad() { + super.viewDidLoad() + + let configuration = AnalyticsConfiguration(writeKey: "8XpdAWa7qJVBJMK8V4FfXQOrnvCzu3Ie") + + // Enable this to record certain application events automatically! + configuration.trackApplicationLifecycleEvents = true + // Enable this to record screen views automatically! + configuration.recordScreenViews = true + Analytics.setup(with: configuration) + + + // Do any additional setup after loading the view. + let analytics = Analytics.shared() + + // identify screen load + analytics.screen("SegmentMac") + } + + override var representedObject: Any? { + didSet { + // Update the view, if already loaded. + } + } + + @IBAction func signinTapped(_ sender: Any) { + associateButton.isEnabled = true + Analytics.shared().track("Signed In") + } + + @IBAction func associateTapped(_ sender: Any) { + signoutButton.isEnabled = true + Analytics.shared().alias("New-Associate-ID") + } + + @IBAction func signoutTapped(_ sender: Any) { + Analytics.shared().track("Signed Out") + } +} + diff --git a/Makefile b/Makefile index 5318f1eb9..b790f5462 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ XC_ARGS := -workspace Analytics.xcworkspace GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES IOS_XCARGS := $(XC_ARGS) -destination "platform=iOS Simulator,name=iPhone 11" -sdk iphonesimulator TVOS_XCARGS := $(XC_ARGS) -destination "platform=tvOS Simulator,name=Apple TV" XC_BUILD_ARGS := -scheme Analytics ONLY_ACTIVE_ARCH=NO -XC_TEST_ARGS := GCC_GENERATE_TEST_COVERAGE_FILES=YES SWIFT_VERSION=4.0 RUN_E2E_TESTS=$(RUN_E2E_TESTS) WEBHOOK_AUTH_USERNAME=$(WEBHOOK_AUTH_USERNAME) +XC_TEST_ARGS := GCC_GENERATE_TEST_COVERAGE_FILES=YES SWIFT_VERSION=5.0 RUN_E2E_TESTS=$(RUN_E2E_TESTS) WEBHOOK_AUTH_USERNAME=$(WEBHOOK_AUTH_USERNAME) bootstrap: .buildscript/bootstrap.sh @@ -14,7 +14,7 @@ lint: pod lib lint --allow-warnings carthage: - carthage build --no-skip-current + carthage build --platform ios --no-skip-current archive: carthage carthage archive Analytics diff --git a/Package.swift b/Package.swift new file mode 100644 index 000000000..f7988e05a --- /dev/null +++ b/Package.swift @@ -0,0 +1,40 @@ +// swift-tools-version:5.2 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Analytics", + platforms: [ + .iOS(.v12), .tvOS(.v12) + ], + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "Analytics", + targets: ["Analytics"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "Analytics", + dependencies: [], + path: "Analytics/", + exclude: ["SwiftSources"], + sources: ["Classes", "Internal"], + publicHeadersPath: "Classes", + cSettings: [ + .headerSearchPath("Internal"), + .headerSearchPath("Classes") + ], + linkerSettings: [ + .linkedFramework("CoreTelephony", .when(platforms: [.iOS, .macOS])) + ] + ), + ] +) diff --git a/Podfile b/Podfile index 9249eedf9..f1f899ee6 100644 --- a/Podfile +++ b/Podfile @@ -1,10 +1,5 @@ def shared_testing_pods - pod 'Quick', '~> 1.2.0' - pod 'Nimble', '~> 7.3.4' pod 'Nocilla', '~> 0.11.0' - pod 'Alamofire', '~> 4.5' - pod 'Alamofire-Synchronous', '~> 4.0' - pod 'SwiftTryCatch', :git => 'https://github.com/segmentio/SwiftTryCatch.git' end target 'AnalyticsTests' do diff --git a/Podfile.lock b/Podfile.lock index 695811b0e..a4984894f 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,45 +1,16 @@ PODS: - - Alamofire (4.6.0) - - Alamofire-Synchronous (4.0.0): - - Alamofire (~> 4.0) - - Nimble (7.3.4) - Nocilla (0.11.0) - - Quick (1.2.0) - - SwiftTryCatch (1.0.0) DEPENDENCIES: - - Alamofire (~> 4.5) - - Alamofire-Synchronous (~> 4.0) - - Nimble (~> 7.3.4) - Nocilla (~> 0.11.0) - - Quick (~> 1.2.0) - - SwiftTryCatch (from `https://github.com/segmentio/SwiftTryCatch.git`) SPEC REPOS: trunk: - - Alamofire - - Alamofire-Synchronous - - Nimble - Nocilla - - Quick - -EXTERNAL SOURCES: - SwiftTryCatch: - :git: https://github.com/segmentio/SwiftTryCatch.git - -CHECKOUT OPTIONS: - SwiftTryCatch: - :commit: f06756adb8dfe164659f866e430daf71439b481f - :git: https://github.com/segmentio/SwiftTryCatch.git SPEC CHECKSUMS: - Alamofire: f41a599bd63041760b26d393ec1069d9d7b917f4 - Alamofire-Synchronous: eedf1e6e961c3795a63c74990b3f7d9fbfac7e50 - Nimble: 051e3d8912d40138fa5591c78594f95fb172af37 Nocilla: 7af7a386071150cc8aa5da4da97d060f049dd61c - Quick: 58d203b1c5e27fff7229c4c1ae445ad7069a7a08 - SwiftTryCatch: 6ef1f543b5d287a4f5763c0de2ee9c8568985269 -PODFILE CHECKSUM: bb5abec39a698f101923cddb294d2dfb1b19f105 +PODFILE CHECKSUM: b1320b7107926418d81b6d48a9c864abdf9c3eaf COCOAPODS: 1.9.1 diff --git a/README.md b/README.md index a9c905752..dcfee4f77 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ [![Version](https://img.shields.io/cocoapods/v/Analytics.svg?style=flat)](https://cocoapods.org//pods/Analytics) [![License](https://img.shields.io/cocoapods/l/Analytics.svg?style=flat)](http://cocoapods.org/pods/Analytics) [![codecov](https://codecov.io/gh/segmentio/analytics-ios/branch/master/graph/badge.svg)](https://codecov.io/gh/segmentio/analytics-ios) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![SwiftPM Compatible](https://img.shields.io/badge/SwiftPM-Compatible-F05138.svg)](https://swift.org/package-manager/) analytics-ios is an iOS client for Segment. diff --git a/RELEASING.md b/RELEASING.md index a0b5f0f74..5f1dcbc4f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,7 +1,7 @@ Releasing ========= - 1. Update the version in `SEGAnalytics.m`, `Analytics.podspec` and `Analytics/Info.plist` to the next release version. + 1. Update the version in `SEGAnalytics.m`, `Analytics.podspec`, `Analytics/Info.plist` and `Examples/CarthageExample/Cartfile` to the next release version. 2. Update the `CHANGELOG.md` for the impending release. 3. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the new version). 4. `git tag -a X.Y.Z -m "Version X.Y.Z"` (where X.Y.Z is the new version). @@ -9,7 +9,6 @@ Releasing 6. `pod trunk push Analytics.podspec`. 7. Next we'll create a dynamic framework for manual installation leveraging Carthage. * `cd Examples/CarthageExample`. - * Update `Cartfile` first line to the correct tag `X.Y.Z` that just got pushed to Github. * `make clean` to be safe then `make build`. * Zip `Carthage/Builds/iOS/Analytics.framework` and `Carthage/Builds/iOS/Analytics.dSYM` into `Archive.zip`. 8. Next, we'll create a Carthage build by running `make archive`.