diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index ec64922a..3e2b76ad 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -57,7 +57,7 @@ jobs: - uses: webfactory/ssh-agent@v0.5.3 with: ssh-private-key: ${{ secrets.SOVRAN_SSH_KEY }} - - run: xcodebuild -scheme Segment-Package test -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 11' + - run: xcodebuild -scheme Segment-Package test -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13' build_and_test_tvos: diff --git a/Examples/apps/ObjCExample/ObjCExample.xcodeproj/project.pbxproj b/Examples/apps/ObjCExample/ObjCExample.xcodeproj/project.pbxproj index d5952004..91904b3d 100644 --- a/Examples/apps/ObjCExample/ObjCExample.xcodeproj/project.pbxproj +++ b/Examples/apps/ObjCExample/ObjCExample.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 460FF309299AAEEC00635FF9 /* Segment in Frameworks */ = {isa = PBXBuildFile; productRef = 460FF308299AAEEC00635FF9 /* Segment */; }; 46262AB229CB731B005C68FF /* SegmentMixpanel in Frameworks */ = {isa = PBXBuildFile; productRef = 46262AB129CB731B005C68FF /* SegmentMixpanel */; }; + 463F61EA29E9C33400BBB4ED /* TestDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 463F61E929E9C33400BBB4ED /* TestDestination.swift */; }; 464247BC26C6D7A700CAD301 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 464247BB26C6D7A700CAD301 /* AppDelegate.m */; }; 464247BF26C6D7A700CAD301 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 464247BE26C6D7A700CAD301 /* SceneDelegate.m */; }; 464247C226C6D7A700CAD301 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 464247C126C6D7A700CAD301 /* ViewController.m */; }; @@ -19,6 +20,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 463F61E829E9C33400BBB4ED /* ObjCExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ObjCExample-Bridging-Header.h"; sourceTree = ""; }; + 463F61E929E9C33400BBB4ED /* TestDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestDestination.swift; sourceTree = ""; }; 464247B726C6D7A700CAD301 /* ObjCExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ObjCExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 464247BA26C6D7A700CAD301 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 464247BB26C6D7A700CAD301 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -66,6 +69,7 @@ 464247B926C6D7A700CAD301 /* ObjCExample */ = { isa = PBXGroup; children = ( + 463F61E929E9C33400BBB4ED /* TestDestination.swift */, 464247BA26C6D7A700CAD301 /* AppDelegate.h */, 464247BB26C6D7A700CAD301 /* AppDelegate.m */, 464247BD26C6D7A700CAD301 /* SceneDelegate.h */, @@ -77,6 +81,7 @@ 464247C826C6D7A800CAD301 /* LaunchScreen.storyboard */, 464247CB26C6D7A800CAD301 /* Info.plist */, 464247CC26C6D7A800CAD301 /* main.m */, + 463F61E829E9C33400BBB4ED /* ObjCExample-Bridging-Header.h */, ); path = ObjCExample; sourceTree = ""; @@ -122,6 +127,7 @@ TargetAttributes = { 464247B626C6D7A700CAD301 = { CreatedOnToolsVersion = 12.5.1; + LastSwiftMigration = 1430; }; }; }; @@ -164,6 +170,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 463F61EA29E9C33400BBB4ED /* TestDestination.swift in Sources */, 464247C226C6D7A700CAD301 /* ViewController.m in Sources */, 464247BC26C6D7A700CAD301 /* AppDelegate.m in Sources */, 464247CD26C6D7A800CAD301 /* main.m in Sources */, @@ -310,6 +317,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = ObjCExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -318,6 +326,9 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.segment.ObjCExample; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "ObjCExample/ObjCExample-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -327,6 +338,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = ObjCExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -335,6 +347,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.segment.ObjCExample; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "ObjCExample/ObjCExample-Bridging-Header.h"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/Examples/apps/ObjCExample/ObjCExample/AppDelegate.m b/Examples/apps/ObjCExample/ObjCExample/AppDelegate.m index bd5b60a6..5cc6b75d 100644 --- a/Examples/apps/ObjCExample/ObjCExample/AppDelegate.m +++ b/Examples/apps/ObjCExample/ObjCExample/AppDelegate.m @@ -6,6 +6,7 @@ // #import "AppDelegate.h" +#import "ObjCExample-Swift.h" @import Segment; @import SegmentMixpanel; @@ -29,6 +30,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [self.analytics flush]; + SEGTestDestination *testDestination = [[SEGTestDestination alloc] init]; + [self.analytics addPlugin:testDestination]; + [self.analytics addSourceMiddleware:^NSDictionary * _Nullable(NSDictionary * _Nullable event) { // drop all events named booya NSString *eventType = event[@"type"]; diff --git a/Examples/apps/ObjCExample/ObjCExample/Info.plist b/Examples/apps/ObjCExample/ObjCExample/Info.plist index 72bf2c4f..f6701f24 100644 --- a/Examples/apps/ObjCExample/ObjCExample/Info.plist +++ b/Examples/apps/ObjCExample/ObjCExample/Info.plist @@ -16,6 +16,15 @@ $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString 1.0 + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + + CFBundleVersion 1 LSRequiresIPhoneOS diff --git a/Examples/apps/ObjCExample/ObjCExample/ObjCExample-Bridging-Header.h b/Examples/apps/ObjCExample/ObjCExample/ObjCExample-Bridging-Header.h new file mode 100644 index 00000000..f84fb540 --- /dev/null +++ b/Examples/apps/ObjCExample/ObjCExample/ObjCExample-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + + diff --git a/Examples/apps/ObjCExample/ObjCExample/TestDestination.swift b/Examples/apps/ObjCExample/ObjCExample/TestDestination.swift new file mode 100644 index 00000000..b03d7a7c --- /dev/null +++ b/Examples/apps/ObjCExample/ObjCExample/TestDestination.swift @@ -0,0 +1,26 @@ +// +// TestDestination.swift +// ObjCExample +// +// Created by Brandon Sneed on 4/14/23. +// + +import Foundation +import Segment + +@objc(SEGTestDestination) +public class ObjCTestDestination: NSObject, ObjCPlugin, ObjCPluginShim { + public func instance() -> EventPlugin { return TestDestination() } +} + +public class TestDestination: DestinationPlugin { + public let key = "Booya" + public let timeline = Timeline() + public let type = PluginType.destination + public var analytics: Analytics? = nil + + public func execute(event: T?) -> T? { + print("some event came to visit us for xmas din din.") + return event + } +} diff --git a/Sources/Segment/Events.swift b/Sources/Segment/Events.swift index 520ceb8a..ecff0e85 100644 --- a/Sources/Segment/Events.swift +++ b/Sources/Segment/Events.swift @@ -142,7 +142,7 @@ extension Analytics { /// generate the UUID and Apple's policies on IDs, see /// https://segment.io/libraries/ios#ids /// - properties: A dictionary of traits you know about the user. Things like: email, name, plan, etc. - public func track(name: String, properties: [String: Codable]? = nil) { + public func track(name: String, properties: [String: Any]? = nil) { var props: JSON? = nil if let properties = properties { do { @@ -165,7 +165,7 @@ extension Analytics { /// https://segment.io/libraries/ios#ids /// - traits: A dictionary of traits you know about the user. Things like: email, name, plan, etc. /// In the case when user logs out, make sure to call ``reset()`` to clear user's identity info. - public func identify(userId: String, traits: [String: Codable]? = nil) { + public func identify(userId: String, traits: [String: Any]? = nil) { do { if let traits = traits { let traits = try JSON(traits as Any) @@ -187,7 +187,7 @@ extension Analytics { /// - screenTitle: The title of the screen being tracked. /// - category: A category to the type of screen if it applies. /// - properties: Any extra metadata associated with the screen. e.g. method of access, size, etc. - public func screen(title: String, category: String? = nil, properties: [String: Codable]? = nil) { + public func screen(title: String, category: String? = nil, properties: [String: Any]? = nil) { var event = ScreenEvent(title: title, category: category, properties: nil) if let properties = properties { do { @@ -204,7 +204,7 @@ extension Analytics { /// - Parameters: /// - groupId: A unique identifier for the group identification in your system. /// - traits: Traits of the group you may be interested in such as email, phone or name. - public func group(groupId: String, traits: [String: Codable]?) { + public func group(groupId: String, traits: [String: Any]?) { var event = GroupEvent(groupId: groupId) if let traits = traits { do { diff --git a/Sources/Segment/ObjC/ObjCDestinationSupport.swift b/Sources/Segment/ObjC/ObjCDestinationSupport.swift index f87c3637..ba7c5020 100644 --- a/Sources/Segment/ObjC/ObjCDestinationSupport.swift +++ b/Sources/Segment/ObjC/ObjCDestinationSupport.swift @@ -9,11 +9,11 @@ import Foundation -@objc(SEGDestination) -public protocol ObjCDestination {} +@objc(SEGPlugin) +public protocol ObjCPlugin {} -public protocol ObjCDestinationShim { - func instance() -> DestinationPlugin +public protocol ObjCPluginShim { + func instance() -> EventPlugin } // NOTE: Destination plugins need something similar to the following to work @@ -22,8 +22,8 @@ public protocol ObjCDestinationShim { /* @objc(SEGMixpanelDestination) -public class ObjCSegmentMixpanel: NSObject, ObjCDestination, ObjCDestinationShim { - public func instance() -> DestinationPlugin { return MixpanelDestination() } +public class ObjCSegmentMixpanel: NSObject, ObjCPlugin, ObjCPluginShim { + public func instance() -> EventPlugin { return MixpanelDestination() } } */ diff --git a/Sources/Segment/ObjC/ObjCPluginSupport.swift b/Sources/Segment/ObjC/ObjCPluginSupport.swift index accc1452..9fc9347f 100644 --- a/Sources/Segment/ObjC/ObjCPluginSupport.swift +++ b/Sources/Segment/ObjC/ObjCPluginSupport.swift @@ -113,11 +113,11 @@ extension ObjCAnalytics { _ = dest.add(plugin: ObjCShimPlugin(middleware: middleware)) } - @objc(addDestination:) - public func addDestination(_ destination: ObjCDestination) { - guard let bouncer = destination as? ObjCDestinationShim else { return } - let dest = bouncer.instance() - analytics.add(plugin: dest) + @objc(addPlugin:) + public func add(plugin: ObjCPlugin) { + guard let bouncer = plugin as? ObjCPluginShim else { return } + let p = bouncer.instance() + analytics.add(plugin: p) } } diff --git a/Tests/Segment-Tests/Support/TestUtilities.swift b/Tests/Segment-Tests/Support/TestUtilities.swift index a34dd31e..c9a08444 100644 --- a/Tests/Segment-Tests/Support/TestUtilities.swift +++ b/Tests/Segment-Tests/Support/TestUtilities.swift @@ -61,6 +61,15 @@ class ZiggyPlugin: EventPlugin { } } +#if !os(Linux) + +@objc(SEGMyDestination) +public class ObjCMyDestination: NSObject, ObjCPlugin, ObjCPluginShim { + public func instance() -> EventPlugin { return MyDestination() } +} + +#endif + class MyDestination: DestinationPlugin { var timeline: Timeline let type: PluginType