diff --git a/.circleci/config.yml b/.circleci/config.yml index c372d331..5c6f15ce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -90,6 +90,39 @@ jobs: - store_artifacts: path: test_output destination: scan-output + build_examples: + macos: + xcode: "12.5.0" + resource_class: m2.medium + steps: + - checkout + # Workarounds for Xcode/SPM failing to get packages + - run: sudo defaults write com.apple.dt.Xcode IDEPackageSupportUseBuiltinSCM YES + - run: rm ~/.ssh/id_rsa || true + - run: for ip in $(dig @8.8.8.8 bitbucket.org +short); do ssh-keyscan bitbucket.org,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts || true + - run: for ip in $(dig @8.8.8.8 github.com +short); do ssh-keyscan github.com,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts || true + - run: + # build for ios simulator + command: | + cd Examples/apps/BasicExample + xcodebuild -workspace "BasicExample.xcworkspace" -scheme "BasicExample" -sdk iphonesimulator + - run: + # build for ios simulator + command: | + cd Examples/apps/SegmentUIKitExample + xcodebuild -workspace "SegmentUIKitExample.xcworkspace" -scheme "SegmentUIKitExample" -sdk iphonesimulator + - run: + # build for mac catalyst + command: | + cd Examples/apps/SegmentUIKitExample + xcodebuild -workspace "SegmentUIKitExample.xcworkspace" -scheme "SegmentUIKitExample" -destination 'platform=macOS,variant=Mac Catalyst' + # Collect XML test results data to show in the UI, and save the same XML + # files under test-results folder in the Artifacts tab + - store_test_results: + path: test_output + - store_artifacts: + path: test_output + destination: scan-output workflows: version: 2 build_and_test: @@ -99,6 +132,7 @@ workflows: - build_and_test_ios - build_and_test_tvos - build_and_test_watchos + - build_examples diff --git a/.gitignore b/.gitignore index 4f201677..74c49ed9 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,5 @@ fastlane/test_output iOSInjectionProject/ .DS_Store +Package.resolved +*.xcuserdatad diff --git a/Examples/README.md b/Examples/README.md new file mode 100644 index 00000000..ca05dddb --- /dev/null +++ b/Examples/README.md @@ -0,0 +1,26 @@ +The files contained within this directory are NOT SUPPORTED by Segment. +They are here merely as an example, and for your convenience should you +find it useful. + +--- +MIT License + +Copyright (c) 2021 Segment + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Examples/apps/BasicExample/BasicExample.xcodeproj/project.pbxproj b/Examples/apps/BasicExample/BasicExample.xcodeproj/project.pbxproj new file mode 100644 index 00000000..87e3f1f7 --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample.xcodeproj/project.pbxproj @@ -0,0 +1,390 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 52; + objects = { + +/* Begin PBXBuildFile section */ + 469F7AF9265C25890038E773 /* EventData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 469F7AF8265C25890038E773 /* EventData.swift */; }; + 46E38365265837EA00BA2502 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E38364265837EA00BA2502 /* AppDelegate.swift */; }; + 46E38367265837EA00BA2502 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E38366265837EA00BA2502 /* SceneDelegate.swift */; }; + 46E38369265837EA00BA2502 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E38368265837EA00BA2502 /* ViewController.swift */; }; + 46E3836C265837EA00BA2502 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 46E3836A265837EA00BA2502 /* Main.storyboard */; }; + 46E3836E265837EB00BA2502 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 46E3836D265837EB00BA2502 /* Assets.xcassets */; }; + 46E38371265837EB00BA2502 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 46E3836F265837EB00BA2502 /* LaunchScreen.storyboard */; }; + 46E3837A2658387D00BA2502 /* Sovran in Frameworks */ = {isa = PBXBuildFile; productRef = 46E383792658387D00BA2502 /* Sovran */; }; + 46E3837D265838B800BA2502 /* Segment in Frameworks */ = {isa = PBXBuildFile; productRef = 46E3837C265838B800BA2502 /* Segment */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 469F7AF8265C25890038E773 /* EventData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventData.swift; sourceTree = ""; }; + 46E38361265837EA00BA2502 /* BasicExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BasicExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 46E38364265837EA00BA2502 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 46E38366265837EA00BA2502 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 46E38368265837EA00BA2502 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 46E3836B265837EA00BA2502 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 46E3836D265837EB00BA2502 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 46E38370265837EB00BA2502 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 46E38372265837EB00BA2502 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 46E3835E265837EA00BA2502 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 46E3837D265838B800BA2502 /* Segment in Frameworks */, + 46E3837A2658387D00BA2502 /* Sovran in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 46E38358265837EA00BA2502 = { + isa = PBXGroup; + children = ( + 46E38363265837EA00BA2502 /* BasicExample */, + 46E38362265837EA00BA2502 /* Products */, + 46E3837B265838B800BA2502 /* Frameworks */, + ); + sourceTree = ""; + }; + 46E38362265837EA00BA2502 /* Products */ = { + isa = PBXGroup; + children = ( + 46E38361265837EA00BA2502 /* BasicExample.app */, + ); + name = Products; + sourceTree = ""; + }; + 46E38363265837EA00BA2502 /* BasicExample */ = { + isa = PBXGroup; + children = ( + 46E38364265837EA00BA2502 /* AppDelegate.swift */, + 46E38366265837EA00BA2502 /* SceneDelegate.swift */, + 469F7AF8265C25890038E773 /* EventData.swift */, + 46E38368265837EA00BA2502 /* ViewController.swift */, + 46E3836A265837EA00BA2502 /* Main.storyboard */, + 46E3836D265837EB00BA2502 /* Assets.xcassets */, + 46E3836F265837EB00BA2502 /* LaunchScreen.storyboard */, + 46E38372265837EB00BA2502 /* Info.plist */, + ); + path = BasicExample; + sourceTree = ""; + }; + 46E3837B265838B800BA2502 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 46E38360265837EA00BA2502 /* BasicExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 46E38375265837EB00BA2502 /* Build configuration list for PBXNativeTarget "BasicExample" */; + buildPhases = ( + 46E3835D265837EA00BA2502 /* Sources */, + 46E3835E265837EA00BA2502 /* Frameworks */, + 46E3835F265837EA00BA2502 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BasicExample; + packageProductDependencies = ( + 46E383792658387D00BA2502 /* Sovran */, + 46E3837C265838B800BA2502 /* Segment */, + ); + productName = BasicExample; + productReference = 46E38361265837EA00BA2502 /* BasicExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 46E38359265837EA00BA2502 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1250; + LastUpgradeCheck = 1250; + TargetAttributes = { + 46E38360265837EA00BA2502 = { + CreatedOnToolsVersion = 12.5; + }; + }; + }; + buildConfigurationList = 46E3835C265837EA00BA2502 /* Build configuration list for PBXProject "BasicExample" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 46E38358265837EA00BA2502; + packageReferences = ( + 46E383782658387D00BA2502 /* XCRemoteSwiftPackageReference "Sovran-Swift" */, + ); + productRefGroup = 46E38362265837EA00BA2502 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 46E38360265837EA00BA2502 /* BasicExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 46E3835F265837EA00BA2502 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 46E38371265837EB00BA2502 /* LaunchScreen.storyboard in Resources */, + 46E3836E265837EB00BA2502 /* Assets.xcassets in Resources */, + 46E3836C265837EA00BA2502 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 46E3835D265837EA00BA2502 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 46E38369265837EA00BA2502 /* ViewController.swift in Sources */, + 46E38365265837EA00BA2502 /* AppDelegate.swift in Sources */, + 469F7AF9265C25890038E773 /* EventData.swift in Sources */, + 46E38367265837EA00BA2502 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 46E3836A265837EA00BA2502 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 46E3836B265837EA00BA2502 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 46E3836F265837EB00BA2502 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 46E38370265837EB00BA2502 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 46E38373265837EB00BA2502 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.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; + }; + 46E38374265837EB00BA2502 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.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; + }; + 46E38376265837EB00BA2502 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = BasicExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.segment.BasicExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 46E38377265837EB00BA2502 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = BasicExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.segment.BasicExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 46E3835C265837EA00BA2502 /* Build configuration list for PBXProject "BasicExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 46E38373265837EB00BA2502 /* Debug */, + 46E38374265837EB00BA2502 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 46E38375265837EB00BA2502 /* Build configuration list for PBXNativeTarget "BasicExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 46E38376265837EB00BA2502 /* Debug */, + 46E38377265837EB00BA2502 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 46E383782658387D00BA2502 /* XCRemoteSwiftPackageReference "Sovran-Swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/segmentio/Sovran-Swift.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.1; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 46E383792658387D00BA2502 /* Sovran */ = { + isa = XCSwiftPackageProductDependency; + package = 46E383782658387D00BA2502 /* XCRemoteSwiftPackageReference "Sovran-Swift" */; + productName = Sovran; + }; + 46E3837C265838B800BA2502 /* Segment */ = { + isa = XCSwiftPackageProductDependency; + productName = Segment; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 46E38359265837EA00BA2502 /* Project object */; +} diff --git a/Examples/apps/BasicExample/BasicExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/apps/BasicExample/BasicExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/apps/BasicExample/BasicExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/apps/BasicExample/BasicExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/apps/BasicExample/BasicExample.xcodeproj/xcshareddata/xcschemes/BasicExample.xcscheme b/Examples/apps/BasicExample/BasicExample.xcodeproj/xcshareddata/xcschemes/BasicExample.xcscheme new file mode 100644 index 00000000..59ebc17d --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample.xcodeproj/xcshareddata/xcschemes/BasicExample.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/apps/BasicExample/BasicExample.xcworkspace/contents.xcworkspacedata b/Examples/apps/BasicExample/BasicExample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..d424c276 --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Examples/apps/BasicExample/BasicExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/apps/BasicExample/BasicExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SegmentExample/AppDelegate.swift b/Examples/apps/BasicExample/BasicExample/AppDelegate.swift similarity index 64% rename from SegmentExample/AppDelegate.swift rename to Examples/apps/BasicExample/BasicExample/AppDelegate.swift index 5e78190c..ce56765d 100644 --- a/SegmentExample/AppDelegate.swift +++ b/Examples/apps/BasicExample/BasicExample/AppDelegate.swift @@ -1,8 +1,8 @@ // // AppDelegate.swift -// SegmentExample +// BasicExample // -// Created by Cody Garvin on 12/30/20. +// Created by Brandon Sneed on 5/21/21. // import UIKit @@ -15,23 +15,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. - let config = Configuration(writeKey: "WRITE_KEY") - .flushAt(3) + + let configuration = Configuration(writeKey: "") .trackApplicationLifecycleEvents(true) .flushInterval(10) - let analytics = Analytics(configuration: config) - self.analytics = analytics - - analytics.add(plugin: AfterPlugin(name: "AfterPlugin_EndOfTimeline")) - - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) { - analytics.identify(userId: "Segment Spec: Identify") - analytics.track(name: "Segment Spec: Track", properties: MyTraits(email: "info@segment.com")) - analytics.screen(screenTitle: "Segment Spec: Screen") - analytics.group(groupId: "Segment Spec: Group") - //analytics.alias(newId: "Segment Spec: Alias") - } + analytics = Analytics(configuration: configuration) return true } @@ -53,6 +42,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } -struct MyTraits: Codable { - let email: String? +extension UIApplicationDelegate { + var analytics: Analytics? { + if let appDelegate = self as? AppDelegate { + return appDelegate.analytics + } + return nil + } } diff --git a/SegmentExample/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/apps/BasicExample/BasicExample/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from SegmentExample/Assets.xcassets/AccentColor.colorset/Contents.json rename to Examples/apps/BasicExample/BasicExample/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/SegmentExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/apps/BasicExample/BasicExample/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from SegmentExample/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Examples/apps/BasicExample/BasicExample/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/SegmentExample/Assets.xcassets/Contents.json b/Examples/apps/BasicExample/BasicExample/Assets.xcassets/Contents.json similarity index 100% rename from SegmentExample/Assets.xcassets/Contents.json rename to Examples/apps/BasicExample/BasicExample/Assets.xcassets/Contents.json diff --git a/SegmentExample/Base.lproj/LaunchScreen.storyboard b/Examples/apps/BasicExample/BasicExample/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from SegmentExample/Base.lproj/LaunchScreen.storyboard rename to Examples/apps/BasicExample/BasicExample/Base.lproj/LaunchScreen.storyboard diff --git a/Examples/apps/BasicExample/BasicExample/Base.lproj/Main.storyboard b/Examples/apps/BasicExample/BasicExample/Base.lproj/Main.storyboard new file mode 100644 index 00000000..8cf4874c --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample/Base.lproj/Main.storyboard @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. + + + + + + + + + + + + + + + + + + + diff --git a/Examples/apps/BasicExample/BasicExample/EventData.swift b/Examples/apps/BasicExample/BasicExample/EventData.swift new file mode 100644 index 00000000..53266fc7 --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample/EventData.swift @@ -0,0 +1,57 @@ +// +// EventData.swift +// BasicExample +// +// Created by Brandon Sneed on 5/24/21. +// + +import Foundation +import Segment +import UIKit + +struct UserTraits: Codable { + let email: String + let birthday: String + let likesPho: Bool +} + +struct TrackProperties: Codable { + let dayOfWeek: String +} + +struct ScreenProperties: Codable { + let appUsage: TimeInterval +} + + +extension Date { + func dayOfWeek() -> String? { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "EEEE" + return dateFormatter.string(from: self).capitalized + } +} + + +class OutputPlugin: Plugin { + let type: PluginType = .after + let name: String + + var analytics: Analytics? + var textView: UITextView! + + required init(name: String) { + self.name = name + } + + init(textView: UITextView!) { + self.textView = textView + self.name = "output_capture" + } + + func execute(event: T?) -> T? where T : RawEvent { + let string = event?.prettyPrint() + textView.text = string + return event + } +} diff --git a/SegmentExample/Info.plist b/Examples/apps/BasicExample/BasicExample/Info.plist similarity index 100% rename from SegmentExample/Info.plist rename to Examples/apps/BasicExample/BasicExample/Info.plist diff --git a/SegmentExample/SceneDelegate.swift b/Examples/apps/BasicExample/BasicExample/SceneDelegate.swift similarity index 97% rename from SegmentExample/SceneDelegate.swift rename to Examples/apps/BasicExample/BasicExample/SceneDelegate.swift index ffec6f5d..a4a6404d 100644 --- a/SegmentExample/SceneDelegate.swift +++ b/Examples/apps/BasicExample/BasicExample/SceneDelegate.swift @@ -1,8 +1,8 @@ // // SceneDelegate.swift -// SegmentExample +// BasicExample // -// Created by Cody Garvin on 12/30/20. +// Created by Brandon Sneed on 5/21/21. // import UIKit diff --git a/Examples/apps/BasicExample/BasicExample/ViewController.swift b/Examples/apps/BasicExample/BasicExample/ViewController.swift new file mode 100644 index 00000000..87149003 --- /dev/null +++ b/Examples/apps/BasicExample/BasicExample/ViewController.swift @@ -0,0 +1,57 @@ +// +// ViewController.swift +// BasicExample +// +// Created by Brandon Sneed on 5/21/21. +// + +import UIKit + +class ViewController: UIViewController { + var analytics = UIApplication.shared.delegate?.analytics + + var usage: TimeInterval = 0 + var timer: Timer? = nil + + @IBOutlet weak var eventView: UITextView! + + override func viewDidLoad() { + super.viewDidLoad() + + timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in + self.usage += 1 + } + + let outputCapture = OutputPlugin(textView: eventView) + analytics?.add(plugin: outputCapture) + } + + @IBAction func trackTapped(_ sender: Any) { + guard let day = Date().dayOfWeek() else { + print("we couldn't get the day of the week. the world has ended. :(") + return + } + + let props = TrackProperties(dayOfWeek: day) + analytics?.track(name: "Track Tapped", properties: props) + } + + @IBAction func screenTapped(_ sender: Any) { + let props = ScreenProperties(appUsage: usage) + analytics?.screen(screenTitle: "Main Screen", category: "Best", properties: props) + } + + @IBAction func identifyTapped(_ sender: Any) { + let traits = UserTraits(email: "sloth@segment.com", birthday: "09/01/2011", likesPho: true) + analytics?.identify(userId: "sloth", traits: traits) + } + + @IBAction func groupTapped(_ sender: Any) { + analytics?.group(groupId: "1234") + } + + @IBAction func flushTapped(_ sender: Any) { + analytics?.flush() + } +} + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.pbxproj b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.pbxproj new file mode 100644 index 00000000..63d109fa --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.pbxproj @@ -0,0 +1,463 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 52; + objects = { + +/* Begin PBXBuildFile section */ + 46022785261F860100A9E913 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46022784261F860100A9E913 /* AppDelegate.swift */; }; + 46022787261F860100A9E913 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46022786261F860100A9E913 /* SceneDelegate.swift */; }; + 46022789261F860100A9E913 /* Tab1ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46022788261F860100A9E913 /* Tab1ViewController.swift */; }; + 4602278C261F860100A9E913 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4602278A261F860100A9E913 /* Main.storyboard */; }; + 4602278E261F860300A9E913 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4602278D261F860300A9E913 /* Assets.xcassets */; }; + 46022791261F860300A9E913 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4602278F261F860300A9E913 /* LaunchScreen.storyboard */; }; + 46E3834626582D9600BA2502 /* FlurryDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3834526582D9600BA2502 /* FlurryDestination.swift */; }; + 46E3834C26582D9E00BA2502 /* UIKitScreenTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3834826582D9E00BA2502 /* UIKitScreenTracking.swift */; }; + 46E3834D26582D9E00BA2502 /* ConsentTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3834926582D9E00BA2502 /* ConsentTracking.swift */; }; + 46E3834E26582D9E00BA2502 /* IDFACollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3834A26582D9E00BA2502 /* IDFACollection.swift */; }; + 46E3834F26582D9E00BA2502 /* ConsoleLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3834B26582D9E00BA2502 /* ConsoleLogger.swift */; }; + 46E3835326582DA400BA2502 /* CustomScreenTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3835126582DA400BA2502 /* CustomScreenTracking.swift */; }; + 46E3835426582DA400BA2502 /* MultiInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E3835226582DA400BA2502 /* MultiInstance.swift */; }; + 46E383572658307800BA2502 /* Segment in Frameworks */ = {isa = PBXBuildFile; productRef = 46E383562658307800BA2502 /* Segment */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 46022781261F860100A9E913 /* SegmentUIKitExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SegmentUIKitExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 46022784261F860100A9E913 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 46022786261F860100A9E913 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 46022788261F860100A9E913 /* Tab1ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tab1ViewController.swift; sourceTree = ""; }; + 4602278B261F860100A9E913 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 4602278D261F860300A9E913 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 46022790261F860300A9E913 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 46022792261F860300A9E913 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 460227BC2620C02B00A9E913 /* SegmentUIKitExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SegmentUIKitExample-Bridging-Header.h"; sourceTree = ""; }; + 469F7AFA265D8D890038E773 /* SegmentUIKitExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SegmentUIKitExample.entitlements; sourceTree = ""; }; + 46E3834526582D9600BA2502 /* FlurryDestination.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlurryDestination.swift; sourceTree = ""; }; + 46E3834826582D9E00BA2502 /* UIKitScreenTracking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKitScreenTracking.swift; sourceTree = ""; }; + 46E3834926582D9E00BA2502 /* ConsentTracking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsentTracking.swift; sourceTree = ""; }; + 46E3834A26582D9E00BA2502 /* IDFACollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IDFACollection.swift; sourceTree = ""; }; + 46E3834B26582D9E00BA2502 /* ConsoleLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsoleLogger.swift; sourceTree = ""; }; + 46E3835126582DA400BA2502 /* CustomScreenTracking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomScreenTracking.swift; sourceTree = ""; }; + 46E3835226582DA400BA2502 /* MultiInstance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiInstance.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4602277E261F860100A9E913 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 46E383572658307800BA2502 /* Segment in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 46022778261F860100A9E913 = { + isa = PBXGroup; + children = ( + 46E3835026582DA400BA2502 /* tasks */, + 46E3834726582D9E00BA2502 /* other_plugins */, + 46E3834426582D9600BA2502 /* destination_plugins */, + 46022783261F860100A9E913 /* SegmentUIKitExample */, + 46022782261F860100A9E913 /* Products */, + 46E383552658307800BA2502 /* Frameworks */, + ); + sourceTree = ""; + }; + 46022782261F860100A9E913 /* Products */ = { + isa = PBXGroup; + children = ( + 46022781261F860100A9E913 /* SegmentUIKitExample.app */, + ); + name = Products; + sourceTree = ""; + }; + 46022783261F860100A9E913 /* SegmentUIKitExample */ = { + isa = PBXGroup; + children = ( + 469F7AFA265D8D890038E773 /* SegmentUIKitExample.entitlements */, + 46022784261F860100A9E913 /* AppDelegate.swift */, + 46022786261F860100A9E913 /* SceneDelegate.swift */, + 46022788261F860100A9E913 /* Tab1ViewController.swift */, + 4602278A261F860100A9E913 /* Main.storyboard */, + 4602278D261F860300A9E913 /* Assets.xcassets */, + 4602278F261F860300A9E913 /* LaunchScreen.storyboard */, + 46022792261F860300A9E913 /* Info.plist */, + 460227BC2620C02B00A9E913 /* SegmentUIKitExample-Bridging-Header.h */, + ); + path = SegmentUIKitExample; + sourceTree = ""; + }; + 46E3834426582D9600BA2502 /* destination_plugins */ = { + isa = PBXGroup; + children = ( + 46E3834526582D9600BA2502 /* FlurryDestination.swift */, + ); + name = destination_plugins; + path = ../../destination_plugins; + sourceTree = ""; + }; + 46E3834726582D9E00BA2502 /* other_plugins */ = { + isa = PBXGroup; + children = ( + 46E3834826582D9E00BA2502 /* UIKitScreenTracking.swift */, + 46E3834926582D9E00BA2502 /* ConsentTracking.swift */, + 46E3834A26582D9E00BA2502 /* IDFACollection.swift */, + 46E3834B26582D9E00BA2502 /* ConsoleLogger.swift */, + ); + name = other_plugins; + path = ../../other_plugins; + sourceTree = ""; + }; + 46E3835026582DA400BA2502 /* tasks */ = { + isa = PBXGroup; + children = ( + 46E3835126582DA400BA2502 /* CustomScreenTracking.swift */, + 46E3835226582DA400BA2502 /* MultiInstance.swift */, + ); + name = tasks; + path = ../../tasks; + sourceTree = ""; + }; + 46E383552658307800BA2502 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 46022780261F860100A9E913 /* SegmentUIKitExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 46022795261F860300A9E913 /* Build configuration list for PBXNativeTarget "SegmentUIKitExample" */; + buildPhases = ( + 4602277D261F860100A9E913 /* Sources */, + 4602277E261F860100A9E913 /* Frameworks */, + 4602277F261F860100A9E913 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 460227A1261F887C00A9E913 /* PBXTargetDependency */, + ); + name = SegmentUIKitExample; + packageProductDependencies = ( + 46E383562658307800BA2502 /* Segment */, + ); + productName = SegmentUIKitExample; + productReference = 46022781261F860100A9E913 /* SegmentUIKitExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 46022779261F860100A9E913 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1240; + LastUpgradeCheck = 1240; + TargetAttributes = { + 46022780261F860100A9E913 = { + CreatedOnToolsVersion = 12.4; + }; + }; + }; + buildConfigurationList = 4602277C261F860100A9E913 /* Build configuration list for PBXProject "SegmentUIKitExample" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 46022778261F860100A9E913; + packageReferences = ( + ); + productRefGroup = 46022782261F860100A9E913 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 46022780261F860100A9E913 /* SegmentUIKitExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4602277F261F860100A9E913 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 46022791261F860300A9E913 /* LaunchScreen.storyboard in Resources */, + 4602278E261F860300A9E913 /* Assets.xcassets in Resources */, + 4602278C261F860100A9E913 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4602277D261F860100A9E913 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 46E3835326582DA400BA2502 /* CustomScreenTracking.swift in Sources */, + 46E3834626582D9600BA2502 /* FlurryDestination.swift in Sources */, + 46E3834F26582D9E00BA2502 /* ConsoleLogger.swift in Sources */, + 46022789261F860100A9E913 /* Tab1ViewController.swift in Sources */, + 46022785261F860100A9E913 /* AppDelegate.swift in Sources */, + 46E3834C26582D9E00BA2502 /* UIKitScreenTracking.swift in Sources */, + 46E3835426582DA400BA2502 /* MultiInstance.swift in Sources */, + 46E3834E26582D9E00BA2502 /* IDFACollection.swift in Sources */, + 46022787261F860100A9E913 /* SceneDelegate.swift in Sources */, + 46E3834D26582D9E00BA2502 /* ConsentTracking.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 460227A1261F887C00A9E913 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + productRef = 460227A0261F887C00A9E913 /* Segment */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 4602278A261F860100A9E913 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 4602278B261F860100A9E913 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 4602278F261F860300A9E913 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 46022790261F860300A9E913 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 46022793261F860300A9E913 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OBJC_BRIDGING_HEADER = "SegmentUIKitExample/SegmentUIKitExample-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 46022794261F860300A9E913 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OBJC_BRIDGING_HEADER = "SegmentUIKitExample/SegmentUIKitExample-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 46022796261F860300A9E913 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = SegmentUIKitExample/SegmentUIKitExample.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = SegmentUIKitExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.segment.SegmentUIKitExample; + 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; + }; + 46022797261F860300A9E913 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = SegmentUIKitExample/SegmentUIKitExample.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = SegmentUIKitExample/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.segment.SegmentUIKitExample; + 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 */ + 4602277C261F860100A9E913 /* Build configuration list for PBXProject "SegmentUIKitExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 46022793261F860300A9E913 /* Debug */, + 46022794261F860300A9E913 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 46022795261F860300A9E913 /* Build configuration list for PBXNativeTarget "SegmentUIKitExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 46022796261F860300A9E913 /* Debug */, + 46022797261F860300A9E913 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 4602279B261F884600A9E913 /* XCRemoteSwiftPackageReference "analytics-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "git@github.com:segmentio/analytics-swift.git"; + requirement = { + branch = main; + kind = branch; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 460227A0261F887C00A9E913 /* Segment */ = { + isa = XCSwiftPackageProductDependency; + package = 4602279B261F884600A9E913 /* XCRemoteSwiftPackageReference "analytics-swift" */; + productName = Segment; + }; + 46E383562658307800BA2502 /* Segment */ = { + isa = XCSwiftPackageProductDependency; + productName = Segment; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 46022779261F860100A9E913 /* Project object */; +} diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..73d8839a --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "Flurry", + "repositoryURL": "git@github.com:flurrydev/FlurrySwiftPackage.git", + "state": { + "branch": "master", + "revision": "da8b316b36760dda92272adf53991a0f9db9b8be", + "version": null + } + } + ] + }, + "version": 1 +} diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcworkspace/contents.xcworkspacedata b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..cffbb7e6 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/AppDelegate.swift b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/AppDelegate.swift new file mode 100644 index 00000000..f63ce38a --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/AppDelegate.swift @@ -0,0 +1,54 @@ +// +// AppDelegate.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/8/21. +// + +import UIKit +import Segment + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // add console logging plugins to our multiple instances + Analytics.main.add(plugin: ConsoleLogger(name: "main")) + Analytics.main.add(plugin: ConsentTracking(name: "consent")) + Analytics.main.add(plugin: IDFACollection(name: "idfa")) + Analytics.main.add(plugin: UIKitScreenTracking(name: "autoScreenTracking")) + + Analytics.support.add(plugin: ConsoleLogger(name: "support")) + Analytics.support.add(plugin: ConsentTracking(name: "consent")) + + // setup flurry on the main instance + // NOTE: This is currently commented out due to lack of arm64 support in the flurry SDK via swift package manager. + //let flurry = FlurryDestination(name: "Flurry", analytics: Analytics.main) + //Analytics.main.add(plugin: flurry) + + Analytics.support.track(name: "test event") + + + 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/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..9221b9bb --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/Contents.json b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SegmentExample/Base.lproj/Main.storyboard b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Base.lproj/LaunchScreen.storyboard similarity index 69% rename from SegmentExample/Base.lproj/Main.storyboard rename to Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Base.lproj/LaunchScreen.storyboard index 25a76385..865e9329 100644 --- a/SegmentExample/Base.lproj/Main.storyboard +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Base.lproj/LaunchScreen.storyboard @@ -1,5 +1,5 @@ - - + + @@ -7,18 +7,19 @@ - + - - + + - + + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Base.lproj/Main.storyboard b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Base.lproj/Main.storyboard new file mode 100644 index 00000000..b479780b --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Base.lproj/Main.storyboard @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Info.plist b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Info.plist new file mode 100644 index 00000000..68888fa8 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Info.plist @@ -0,0 +1,68 @@ + + + + + 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 + + NSUserTrackingUsageDescription + Can we use your IDFA to track you? + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SceneDelegate.swift b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SceneDelegate.swift new file mode 100644 index 00000000..560da4ea --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SceneDelegate.swift @@ -0,0 +1,52 @@ +// +// SceneDelegate.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/8/21. +// + +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 necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SegmentUIKitExample-Bridging-Header.h b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SegmentUIKitExample-Bridging-Header.h new file mode 100644 index 00000000..f5d7ece1 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SegmentUIKitExample-Bridging-Header.h @@ -0,0 +1,14 @@ +// +// SegmentUIKitExample-Bridging-Header.h +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/9/21. +// + +#ifndef SegmentUIKitExample_Bridging_Header_h +#define SegmentUIKitExample_Bridging_Header_h + +//Needed for all Flurry Integration +//#import "Flurry.h" + +#endif /* SegmentUIKitExample_Bridging_Header_h */ diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SegmentUIKitExample.entitlements b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SegmentUIKitExample.entitlements new file mode 100644 index 00000000..ee95ab7e --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/SegmentUIKitExample.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + + diff --git a/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Tab1ViewController.swift b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Tab1ViewController.swift new file mode 100644 index 00000000..81b9a7c7 --- /dev/null +++ b/Examples/apps/SegmentUIKitExample/SegmentUIKitExample/Tab1ViewController.swift @@ -0,0 +1,25 @@ +// +// ViewController.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/8/21. +// + +import UIKit + +class Tab1ViewController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + + @IBAction func queryAction(_ sender: Any) { + // tap the "?" in the navbar and see an example of customized screen tracking. + let alertController = QueryAlertController(title: "I know you like pie", message: "Everyone likes pie", preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "Yeah, I do", style: .default, handler: nil)) + present(alertController, animated: true, completion: nil) + } + +} + diff --git a/Examples/destination_plugins/FlurryDestination.swift b/Examples/destination_plugins/FlurryDestination.swift new file mode 100644 index 00000000..09be0a20 --- /dev/null +++ b/Examples/destination_plugins/FlurryDestination.swift @@ -0,0 +1,137 @@ +// +// FlurryDestination.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/9/21. +// + +// NOTE: You can see this plugin in use in the SwiftUIKitExample application. +// +// This plugin is NOT SUPPORTED by Segment. It is here merely as an example, +// and for your convenience should you find it useful. Please contact Flurry +// about providing full support and publishing if desired. +// +// Flurry SPM package can be found here: https://github.com/flurry/FlurrySwiftPackage + +// MIT License +// +// Copyright (c) 2021 Segment +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import Segment +/** + An implmentation of the Flurry Analytics device mode destination as a plugin. + + NOTE: This is currently commented out due to lack of arm64 support in the flurry SDK via swift package manager. + See here: https://github.com/flurry/FlurrySwiftPackage/issues/3 + */ + +/* +import FlurryAnalytics + +class FlurryDestination: DestinationPlugin { + let timeline: Timeline = Timeline() + let type: PluginType = .destination + let name: String + var analytics: Analytics? = nil + + var started = false + var screenTracksEvents = false + + required init(name: String) { + self.name = name + } + + func update(settings: Settings) { + guard let jsonSettings = settings.integrationSettings(for: "Flurry") else { return } + guard let flurryApiKey = jsonSettings["apiKey"] as? String else { return } + + let builder = FlurrySessionBuilder() + + if let sessionContinueSeconds = jsonSettings["sessionContinueSeconds"] as? Int { + builder.withSessionContinueSeconds(sessionContinueSeconds) + } + + if let screenTracksEvents = jsonSettings["screenTracksEvents"] as? Bool { + self.screenTracksEvents = screenTracksEvents + } + + Flurry.startSession(flurryApiKey, with: builder) + started = true + } + + func identify(event: IdentifyEvent) -> IdentifyEvent? { + guard started == true else { return event } + + Flurry.setUserID(event.userId) + + if let traits = event.traits?.dictionaryValue { + if let gender = traits["gender"] as? String { + Flurry.setGender(String(gender.prefix(1))) + } + + if let value = traits["age"] as? String, let age = Int32(value) { + Flurry.setAge(age) + } + } + + return event + } + + func track(event: TrackEvent) -> TrackEvent? { + guard started == true else { return event } + + let props = truncate(properties: event.properties?.dictionaryValue) + Flurry.logEvent(event.event, withParameters: props) + return event + } + + func screen(event: ScreenEvent) -> ScreenEvent? { + guard started == true else { return event } + + if screenTracksEvents { + let props = truncate(properties: event.properties?.dictionaryValue) + Flurry.logEvent("Viewed \(event.name ?? "") Screen", withParameters: props) + } + return event + } +} + +// MARK: - Support methods + +extension FlurryDestination { + /** + Flurry can only have a maximum of 10 properties, so we need to truncate any properties we were given. + */ + func truncate(properties: [String: Any]?) -> [String: Any]? { + guard let properties = properties else { return nil } + var truncated = [String: Any]() + for (key, value) in properties { + truncated[key] = value + if truncated.count == 10 { + break + } + } + return properties + } +} + +*/ diff --git a/Examples/other_plugins/ConsentTracking.swift b/Examples/other_plugins/ConsentTracking.swift new file mode 100644 index 00000000..26cc66f1 --- /dev/null +++ b/Examples/other_plugins/ConsentTracking.swift @@ -0,0 +1,128 @@ +// +// ConsentTracking.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/9/21. +// + +// NOTE: You can see this plugin in use in the SwiftUIKitExample application. +// +// This plugin is NOT SUPPORTED by Segment. It is here merely as an example, +// and for your convenience should you find it useful. + +// MIT License +// +// Copyright (c) 2021 Segment +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import Segment +import UIKit + +/** + An example of implementing a consent management plugin. + + This plugin will display a dialog at startup requesting tracking consent. Until consent is given, + any events that would flow through the system are queued so they can be replayed post-consent. + + If consent is declined, all events are dropped immediately after entering the event timeline. + */ +class ConsentTracking: Plugin { + let type: PluginType = .before + let name: String + var analytics: Analytics? = nil + + var queuedEvents = [RawEvent]() + + static var consentGiven = false + static var consentAsked = false + static var lock = NSLock() + static var instances = [ConsentTracking]() + + required init(name: String) { + self.name = name + + Self.instances.append(self) + + // In our example, we'll be adding this plugin to multiple instances of Analytics. + // Because of this, we need a centralized point to determine whether we're allowed to + // track or process events. + if Self.lock.try() { + DispatchQueue.main.async { + let alertController = UIAlertController(title: "Privacy Notice", message: "This app tracks you for X, Y and Z. Do you consent?", preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "Yes", style: .default, handler: { _ in + Self.consentGiven = true + Self.consentAsked = true + Self.lock.unlock() + + self.analytics?.track(name: "Consent to track given") + + // replay any queued events if they gave consent. + Self.replayEvents() + })) + + alertController.addAction(UIAlertAction(title: "No", style: .destructive, handler: { _ in + Self.consentGiven = false + Self.consentAsked = true + Self.lock.unlock() + + // clear any queued events if it was denied. + Self.clearQueuedEvents() + })) + + UIApplication.shared.windows.first?.rootViewController?.present(alertController, animated: true, completion: nil) + } + } + } + + func execute(event: T?) -> T? { + // if we've been given consent, let the event pass through. + if Self.consentGiven { + return event + } + + // queue the event in case they given consent later + if let e = event, Self.consentAsked == false { + queuedEvents.append(e) + } + + // returning nil will stop processing the event in the timeline. + return nil + } + + static func clearQueuedEvents() { + for instance in Self.instances { + instance.queuedEvents.removeAll() + } + } + + static func replayEvents() { + for instance in Self.instances { + instance.replayEvents() + } + } + + func replayEvents() { + // replay the queued events to the instance of Analytics we're working with. + for event in queuedEvents { + analytics?.process(event: event) + } + } +} diff --git a/Examples/other_plugins/ConsoleLogger.swift b/Examples/other_plugins/ConsoleLogger.swift new file mode 100644 index 00000000..18ebe759 --- /dev/null +++ b/Examples/other_plugins/ConsoleLogger.swift @@ -0,0 +1,69 @@ +// +// ConsoleLogger.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/9/21. +// + +// NOTE: You can see this plugin in use in the SwiftUIKitExample application. +// +// This plugin is NOT SUPPORTED by Segment. It is here merely as an example, +// and for your convenience should you find it useful. + +// MIT License +// +// Copyright (c) 2021 Segment +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import Segment + +/** + A generic console logging plugin. The type `.after` signifies that this plugin will + run at the end of the event timeline, at which point it will print event data to the Xcode console window. + */ +class ConsoleLogger: Plugin { + let type: PluginType = .after + let name: String + var analytics: Analytics? = nil + + var identifier: String? = nil + + required init(name: String) { + self.name = name + } + + // we want to log every event, so lets override `execute`. + func execute(event: T?) -> T? { + if let json = event?.prettyPrint() { + print("event received on instance: \(name)") + print("\(json)\n") + } + return event + } + + // we also want to know when settings are retrieved or changed. + func update(settings: Settings) { + let json = settings.prettyPrint() + print("settings updated on instance: \(name)") + print("\(json)\n") + } + +} diff --git a/Examples/other_plugins/IDFACollection.swift b/Examples/other_plugins/IDFACollection.swift new file mode 100644 index 00000000..4aa8deee --- /dev/null +++ b/Examples/other_plugins/IDFACollection.swift @@ -0,0 +1,118 @@ +// +// IDFACollection.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/12/21. +// + +// NOTE: You can see this plugin in use in the SwiftUIKitExample application. +// +// This plugin is NOT SUPPORTED by Segment. It is here merely as an example, +// and for your convenience should you find it useful. + +// MIT License +// +// Copyright (c) 2021 Segment +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import UIKit +import Segment +import AdSupport +import AppTrackingTransparency + +/** + Plugin to collect IDFA values. Users will be prompted if authorization status is undetermined. + Upon completion of user entry a track event is issued showing the choice user made. + + Don't forget to add "NSUserTrackingUsageDescription" with a description to your Info.plist. + */ +class IDFACollection: Plugin { + let type: PluginType = .enrichment + let name: String + var analytics: Analytics? = nil + + required init(name: String) { + self.name = name + } + + func execute(event: T?) -> T? { + let status = ATTrackingManager.trackingAuthorizationStatus + if status == .notDetermined { + // we don't know, so should ask the user. + askForPermission() + } + + let trackingStatus = statusToString(status) + var idfa = fallbackValue + var adTrackingEnabled = false + + if status == .authorized { + adTrackingEnabled = true + idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString + } + + var workingEvent = event + if var context = event?.context?.dictionaryValue { + context[keyPath: "device.adTrackingEnabled"] = adTrackingEnabled + context[keyPath: "device.advertisingId"] = idfa + context[keyPath: "device.trackingStatus"] = trackingStatus + + workingEvent?.context = try? JSON(context) + } + + return workingEvent + } +} + +extension IDFACollection { + var fallbackValue: String? { + get { + // fallback to the IDFV value. + // this is also sent in event.context.device.id, + // feel free to use a value that is more useful to you. + return UIDevice.current.identifierForVendor?.uuidString + } + } + + func statusToString(_ status: ATTrackingManager.AuthorizationStatus) -> String { + var result = "unknown" + switch status { + case .notDetermined: + result = "notDetermined" + case .restricted: + result = "restricted" + case .denied: + result = "denied" + case .authorized: + result = "authorized" + @unknown default: + break + } + return result + } + + func askForPermission() { + ATTrackingManager.requestTrackingAuthorization { status in + // send a track event that shows the results of asking the user for permission. + self.analytics?.track(name: "IDFAQuery", properties: ["result": self.statusToString(status)]) + } + } +} diff --git a/Examples/other_plugins/UIKitScreenTracking.swift b/Examples/other_plugins/UIKitScreenTracking.swift new file mode 100644 index 00000000..61ce54f3 --- /dev/null +++ b/Examples/other_plugins/UIKitScreenTracking.swift @@ -0,0 +1,171 @@ +// +// UIKitScreenTracking.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/13/21. +// + +// NOTE: You can see this plugin in use in the SwiftUIKitExample application. +// +// This plugin is NOT SUPPORTED by Segment. It is here merely as an example, +// and for your convenience should you find it useful. + +// MIT License +// +// Copyright (c) 2021 Segment +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import Segment +import UIKit + +/** + Example plugin to replicate automatic screen tracking in iOS. + */ + +// Conform to this protocol if self-tracking screens are desired +@objc protocol UIKitScreenTrackable: NSObjectProtocol { + @objc func seg__trackScreen(name: String?) +} + +class UIKitScreenTracking: UtilityPlugin { + static let notificationName = Notification.Name(rawValue: "UIKitScreenTrackNotification") + static let screenNameKey = "name" + static let controllerKey = "controller" + + let type: PluginType = .utility + let name: String + var analytics: Analytics? = nil + + required init(name: String) { + self.name = name + setupUIKitHooks() + } + + internal func setupUIKitHooks() { + swizzle(forClass: UIViewController.self, + original: #selector(UIViewController.viewDidAppear(_:)), + new: #selector(UIViewController.seg__viewDidAppear) + ) + + swizzle(forClass: UIViewController.self, + original: #selector(UIViewController.viewDidDisappear(_:)), + new: #selector(UIViewController.seg__viewDidDisappear) + ) + + NotificationCenter.default.addObserver(forName: Self.notificationName, object: nil, queue: OperationQueue.main) { notification in + let name = notification.userInfo?[Self.screenNameKey] as? String + if let controller = notification.userInfo?[Self.controllerKey] as? UIKitScreenTrackable { + // if the controller conforms to UIKitScreenTrackable, + // call the trackScreen method with the name we have (possibly even nil) + // and the implementor will decide what to do. + controller.seg__trackScreen(name: name) + } else if let name = name { + // if we have a name, call screen + self.analytics?.screen(screenTitle: name) + } + } + } +} + +extension UIKitScreenTracking { + private func swizzle(forClass: AnyClass, original: Selector, new: Selector) { + guard let originalMethod = class_getInstanceMethod(forClass, original) else { return } + guard let swizzledMethod = class_getInstanceMethod(forClass, new) else { return } + method_exchangeImplementations(originalMethod, swizzledMethod) + } +} + +extension UIViewController { + internal func activeController() -> UIViewController? { + // if a view is being dismissed, this will return nil + if let root = viewIfLoaded?.window?.rootViewController { + return root + } else if #available(iOS 13.0, *) { + // preferred way to get active controller in ios 13+ + for scene in UIApplication.shared.connectedScenes { + if scene.activationState == .foregroundActive { + let windowScene = scene as? UIWindowScene + let sceneDelegate = windowScene?.delegate as? UIWindowSceneDelegate + if let target = sceneDelegate, let window = target.window { + return window?.rootViewController + } + } + } + } else { + // this was deprecated in ios 13.0 + return UIApplication.shared.keyWindow?.rootViewController + } + return nil + } + + internal func captureScreen() { + var rootController = viewIfLoaded?.window?.rootViewController + if rootController == nil { + rootController = activeController() + } + guard let top = Self.seg__visibleViewController(activeController()) else { return } + + var name = String(describing: top.self.classForCoder).replacingOccurrences(of: "ViewController", with: "") + print(name) + // name could've been just "ViewController"... + if name.count == 0 { + name = top.title ?? "Unknown" + } + + // post a notification that our plugin can capture. + // if you were to do a custom implementation of how the name should + // appear, you probably want to inspect the viewcontroller itself, `top` in this + // case to generate your string for name and/or category. + NotificationCenter.default.post(name: UIKitScreenTracking.notificationName, + object: self, + userInfo: [UIKitScreenTracking.screenNameKey: name, + UIKitScreenTracking.controllerKey: top]) + } + + @objc internal func seg__viewDidAppear(animated: Bool) { + captureScreen() + // it looks like we're calling ourselves, but we're actually + // calling the original implementation of viewDidAppear since it's been swizzled. + seg__viewDidAppear(animated: animated) + } + + @objc internal func seg__viewDidDisappear(animated: Bool) { + // call the original method first + seg__viewDidDisappear(animated: animated) + // the VC should be gone from the stack now, so capture where we're at now. + captureScreen() + } + + static func seg__visibleViewController(_ controller: UIViewController?) -> UIViewController? { + if let navigationController = controller as? UINavigationController { + return seg__visibleViewController(navigationController.visibleViewController) + } + if let tabController = controller as? UITabBarController { + if let selected = tabController.selectedViewController { + return seg__visibleViewController(selected) + } + } + if let presented = controller?.presentedViewController { + return seg__visibleViewController(presented) + } + return controller + } +} diff --git a/Examples/tasks/CustomScreenTracking.swift b/Examples/tasks/CustomScreenTracking.swift new file mode 100644 index 00000000..6eea9189 --- /dev/null +++ b/Examples/tasks/CustomScreenTracking.swift @@ -0,0 +1,47 @@ +// +// CustomScreenTracking.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/14/21. +// + +// NOTE: You can see this task in use in the SwiftUIKitExample application. + +// MIT License +// +// Copyright (c) 2021 Segment +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import UIKit +import Segment + +class QueryAlertController: UIAlertController { + // we already conform to UIKitScreenTrackable so override + override func seg__trackScreen(name: String?) { + Analytics.main.screen(screenTitle: "Query", category: "Action Sheet") + } +} + +extension UIAlertController: UIKitScreenTrackable { + func seg__trackScreen(name: String?) { + Analytics.main.screen(screenTitle: "Basic Alert", category: "Alert") + } +} diff --git a/Examples/tasks/MultiInstance.swift b/Examples/tasks/MultiInstance.swift new file mode 100644 index 00000000..e762ccb7 --- /dev/null +++ b/Examples/tasks/MultiInstance.swift @@ -0,0 +1,46 @@ +// +// MultiInstance.swift +// SegmentUIKitExample +// +// Created by Brandon Sneed on 4/8/21. +// + +// NOTE: You can see this task in use in the SwiftUIKitExample application. + +// MIT License +// +// Copyright (c) 2021 Segment +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import Segment + +/** + An example of implementing multiple Analytics instances in a single application. + */ +extension Analytics { + static var main = Analytics(configuration: Configuration(writeKey: "1234") + .flushAt(3) + .trackApplicationLifecycleEvents(true)) + + static var support = Analytics(configuration: Configuration(writeKey: "5678") + .flushAt(10) + .trackApplicationLifecycleEvents(false)) +} diff --git a/Segment.xcodeproj/project.pbxproj b/Segment.xcodeproj/project.pbxproj index e003037a..00f22fa1 100644 --- a/Segment.xcodeproj/project.pbxproj +++ b/Segment.xcodeproj/project.pbxproj @@ -37,21 +37,12 @@ 46E382E72654429A00BA2502 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E382E62654429A00BA2502 /* Utils.swift */; }; 46FE4C9725A3F35E003A7362 /* macOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46FE4C9625A3F35E003A7362 /* macOSLifecycleMonitor.swift */; }; 46FE4C9C25A3F41C003A7362 /* LinuxLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46FE4C9B25A3F41C003A7362 /* LinuxLifecycleMonitor.swift */; }; - 46FE4CA725A3F836003A7362 /* TestPlugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46FE4CA625A3F836003A7362 /* TestPlugins.swift */; }; 46FE4CE025A53FAD003A7362 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46FE4CDF25A53FAD003A7362 /* Storage.swift */; }; 46FE4CFB25A6C671003A7362 /* TestUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46FE4CFA25A6C671003A7362 /* TestUtilities.swift */; }; 46FE4D1D25A7A850003A7362 /* Storage_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46FE4D1C25A7A850003A7362 /* Storage_Tests.swift */; }; 9620862C2575C0C800314F8D /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9620862B2575C0C800314F8D /* Events.swift */; }; 96208650257AA83E00314F8D /* iOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9620864F257AA83E00314F8D /* iOSLifecycleMonitor.swift */; }; 966945D7259BDCDD00271339 /* HTTPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967C40ED259A7311008EB0B6 /* HTTPClient.swift */; }; - 966945E5259D717E00271339 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966945E4259D717E00271339 /* AppDelegate.swift */; }; - 966945E7259D717E00271339 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966945E6259D717E00271339 /* SceneDelegate.swift */; }; - 966945E9259D717E00271339 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966945E8259D717E00271339 /* ViewController.swift */; }; - 966945EC259D717E00271339 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 966945EA259D717E00271339 /* Main.storyboard */; }; - 966945EE259D717F00271339 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 966945ED259D717F00271339 /* Assets.xcassets */; }; - 966945F1259D717F00271339 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 966945EF259D717F00271339 /* LaunchScreen.storyboard */; }; - 966945FA259D71F800271339 /* Segment.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Segment::Segment::Product" /* Segment.framework */; }; - 966945FB259D71F800271339 /* Segment.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = "Segment::Segment::Product" /* Segment.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 967C40DA258D472C008EB0B6 /* Logger_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967C40D9258D472C008EB0B6 /* Logger_Tests.swift */; }; 967C40E3258D4DAF008EB0B6 /* Metrics_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967C40E2258D4DAF008EB0B6 /* Metrics_Tests.swift */; }; 9692724E25A4E5B7009B5298 /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9692724D25A4E5B7009B5298 /* Startup.swift */; }; @@ -78,13 +69,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 966945FC259D71F800271339 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = "Segment::Segment"; - remoteInfo = Segment; - }; A3471FB7256487B500965480 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = OBJ_1 /* Project object */; @@ -112,17 +96,6 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; - 966945FE259D71F800271339 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 966945FB259D71F800271339 /* Segment.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -141,21 +114,12 @@ 46E382E62654429A00BA2502 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; 46FE4C9625A3F35E003A7362 /* macOSLifecycleMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = macOSLifecycleMonitor.swift; sourceTree = ""; }; 46FE4C9B25A3F41C003A7362 /* LinuxLifecycleMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinuxLifecycleMonitor.swift; sourceTree = ""; }; - 46FE4CA625A3F836003A7362 /* TestPlugins.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestPlugins.swift; sourceTree = ""; }; 46FE4CDF25A53FAD003A7362 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; 46FE4CFA25A6C671003A7362 /* TestUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUtilities.swift; sourceTree = ""; }; 46FE4D1C25A7A850003A7362 /* Storage_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage_Tests.swift; sourceTree = ""; }; 9620862B2575C0C800314F8D /* Events.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Events.swift; sourceTree = ""; }; 962086482579CCC200314F8D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 9620864F257AA83E00314F8D /* iOSLifecycleMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSLifecycleMonitor.swift; sourceTree = ""; }; - 966945E2259D717E00271339 /* SegmentExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SegmentExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 966945E4259D717E00271339 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 966945E6259D717E00271339 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 966945E8259D717E00271339 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 966945EB259D717E00271339 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 966945ED259D717F00271339 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 966945F0259D717F00271339 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 966945F2259D718000271339 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 967C40D9258D472C008EB0B6 /* Logger_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger_Tests.swift; sourceTree = ""; }; 967C40E2258D4DAF008EB0B6 /* Metrics_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Metrics_Tests.swift; sourceTree = ""; }; 967C40ED259A7311008EB0B6 /* HTTPClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPClient.swift; sourceTree = ""; }; @@ -185,14 +149,6 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 966945DF259D717E00271339 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 966945FA259D71F800271339 /* Segment.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; OBJ_24 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 0; @@ -259,21 +215,6 @@ path = Plugins; sourceTree = ""; }; - 966945E3259D717E00271339 /* SegmentExample */ = { - isa = PBXGroup; - children = ( - 966945E4259D717E00271339 /* AppDelegate.swift */, - 46FE4CA625A3F836003A7362 /* TestPlugins.swift */, - 966945E6259D717E00271339 /* SceneDelegate.swift */, - 966945E8259D717E00271339 /* ViewController.swift */, - 966945EA259D717E00271339 /* Main.storyboard */, - 966945ED259D717F00271339 /* Assets.xcassets */, - 966945EF259D717F00271339 /* LaunchScreen.storyboard */, - 966945F2259D718000271339 /* Info.plist */, - ); - path = SegmentExample; - sourceTree = ""; - }; 969A533D25B0D510009227D9 /* Platforms */ = { isa = PBXGroup; children = ( @@ -338,8 +279,8 @@ OBJ_11 /* Segment-Tests */ = { isa = PBXGroup; children = ( - OBJ_13 /* XCTestManifests.swift */, 4621082D2609206D00EBC4A8 /* Support */, + OBJ_13 /* XCTestManifests.swift */, A31A16502576C47400C9CDDF /* JSON_Tests.swift */, 967C40D9258D472C008EB0B6 /* Logger_Tests.swift */, 46FE4D1C25A7A850003A7362 /* Storage_Tests.swift */, @@ -357,7 +298,6 @@ children = ( "Segment::Segment::Product" /* Segment.framework */, "Segment::Segment-Tests::Product" /* Segment-Tests.xctest */, - 966945E2259D717E00271339 /* SegmentExample.app */, ); name = Products; sourceTree = BUILT_PRODUCTS_DIR; @@ -369,7 +309,6 @@ OBJ_10 /* Tests */, OBJ_6 /* Package.swift */, OBJ_17 /* README.md */, - 966945E3259D717E00271339 /* SegmentExample */, OBJ_14 /* Products */, 96208624256DC23F00314F8D /* Frameworks */, ); @@ -407,25 +346,6 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 966945E1259D717E00271339 /* SegmentExample */ = { - isa = PBXNativeTarget; - buildConfigurationList = 966945F3259D718000271339 /* Build configuration list for PBXNativeTarget "SegmentExample" */; - buildPhases = ( - 966945DE259D717E00271339 /* Sources */, - 966945DF259D717E00271339 /* Frameworks */, - 966945E0259D717E00271339 /* Resources */, - 966945FE259D71F800271339 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 966945FD259D71F800271339 /* PBXTargetDependency */, - ); - name = SegmentExample; - productName = SegmentExample; - productReference = 966945E2259D717E00271339 /* SegmentExample.app */; - productType = "com.apple.product-type.application"; - }; "Segment::Segment" /* Segment */ = { isa = PBXNativeTarget; buildConfigurationList = OBJ_19 /* Build configuration list for PBXNativeTarget "Segment" */; @@ -486,12 +406,6 @@ LastSwiftMigration = 9999; LastSwiftUpdateCheck = 1220; LastUpgradeCheck = 1240; - TargetAttributes = { - 966945E1259D717E00271339 = { - CreatedOnToolsVersion = 12.2; - ProvisioningStyle = Automatic; - }; - }; }; buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "Segment" */; compatibilityVersion = "Xcode 3.2"; @@ -513,36 +427,11 @@ "Segment::Segment-Tests" /* Segment-Tests */, "Segment::SwiftPMPackageDescription" /* SegmentPackageDescription */, "Segment::SegmentPackageTests::ProductTarget" /* SegmentPackageTests */, - 966945E1259D717E00271339 /* SegmentExample */, ); }; /* End PBXProject section */ -/* Begin PBXResourcesBuildPhase section */ - 966945E0259D717E00271339 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 966945F1259D717F00271339 /* LaunchScreen.storyboard in Resources */, - 966945EE259D717F00271339 /* Assets.xcassets in Resources */, - 966945EC259D717E00271339 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ - 966945DE259D717E00271339 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 966945E9259D717E00271339 /* ViewController.swift in Sources */, - 966945E5259D717E00271339 /* AppDelegate.swift in Sources */, - 966945E7259D717E00271339 /* SceneDelegate.swift in Sources */, - 46FE4CA725A3F836003A7362 /* TestPlugins.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; OBJ_22 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 0; @@ -610,11 +499,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 966945FD259D71F800271339 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = "Segment::Segment" /* Segment */; - targetProxy = 966945FC259D71F800271339 /* PBXContainerItemProxy */; - }; OBJ_34 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = "Segment::Segment" /* Segment */; @@ -627,160 +511,7 @@ }; /* End PBXTargetDependency section */ -/* Begin PBXVariantGroup section */ - 966945EA259D717E00271339 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 966945EB259D717E00271339 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 966945EF259D717F00271339 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 966945F0259D717F00271339 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ - 966945F4259D718000271339 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - 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_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - 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; - INFOPLIST_FILE = SegmentExample/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.2; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.Segment.SegmentExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 966945F5259D718000271339 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - 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_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = ""; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - 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; - INFOPLIST_FILE = SegmentExample/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.2; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.Segment.SegmentExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; OBJ_20 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1043,15 +774,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 966945F3259D718000271339 /* Build configuration list for PBXNativeTarget "SegmentExample" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 966945F4259D718000271339 /* Debug */, - 966945F5259D718000271339 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; OBJ_19 /* Build configuration list for PBXNativeTarget "Segment" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/SegmentExample/TestPlugins.swift b/SegmentExample/TestPlugins.swift deleted file mode 100644 index 4e01a7db..00000000 --- a/SegmentExample/TestPlugins.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// TestPlugins.swift -// SegmentExample -// -// Created by Brandon Sneed on 1/4/21. -// - -import Foundation -import Segment - -class GooberPlugin: EventPlugin { - var analytics: Analytics? - let type: PluginType - let name: String - - required init(name: String) { - self.name = name - self.type = .enrichment - } - - func identify(event: IdentifyEvent) -> IdentifyEvent? { - var newEvent = IdentifyEvent(existing: event) - newEvent.userId = "goober" - return newEvent - //return nil - } -} - -class ZiggyPlugin: EventPlugin { - var analytics: Analytics? - let type: PluginType - let name: String - - var completion: (() -> Void)? - - required init(name: String) { - self.name = name - self.type = .enrichment - } - - func identify(event: IdentifyEvent) -> IdentifyEvent? { - var newEvent = IdentifyEvent(existing: event) - newEvent.userId = "ziggy" - return newEvent - //return nil - } - - func shutdown() { - completion?() - } -} - -class MyDestination: DestinationPlugin { - var analytics: Analytics? - - var timeline: Timeline - let type: PluginType - let name: String - - required init(name: String) { - self.name = name - self.type = .destination - self.timeline = Timeline() - } - - func reloadWithSettings(_ settings: Settings) { - // TODO: Update the proper types - } - - func identify(event: IdentifyEvent) -> IdentifyEvent? { - return event - } -} - -class AfterPlugin: Plugin { - var analytics: Analytics? - - var timeline: Timeline - let type: PluginType - let name: String - - required init(name: String) { - self.name = name - self.type = .after - self.timeline = Timeline() - } - - public func execute(event: T?, settings: Settings?) -> T? { - print(event.prettyPrint()) - return event - } -} diff --git a/SegmentExample/ViewController.swift b/SegmentExample/ViewController.swift deleted file mode 100644 index e1bb963c..00000000 --- a/SegmentExample/ViewController.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// ViewController.swift -// SegmentExample -// -// Created by Cody Garvin on 12/30/20. -// - -import UIKit -import Segment - -class ViewController: UIViewController { - - var analytics: Analytics? = nil - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - - - } - -} -