Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,6 @@ playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
<<<<<<< HEAD
Packages/
Package.pins
Package.resolved
*.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
.swiftpm
=======
# Packages/
# Package.pins
# Package.resolved
Expand All @@ -41,7 +31,6 @@ Package.resolved
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
>>>>>>> cd22661 (Update)

.build/

Expand Down
24 changes: 18 additions & 6 deletions BranchLinkSimulator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
C16B97A02B75A0FA00FB0631 /* DeeplinkDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C16B979F2B75A0FA00FB0631 /* DeeplinkDetailView.swift */; };
C16B97A22B75A18A00FB0631 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C16B97A12B75A18A00FB0631 /* AppDelegate.swift */; };
C16B97B22B87BD8300FB0631 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C16B97B02B87BD8000FB0631 /* AdSupport.framework */; };
E78DBA1F2E9786B1009FE663 /* BranchSDK.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = E78DBA1E2E9786B1009FE663 /* BranchSDK.xcframework */; };
E78DBA202E9786B1009FE663 /* BranchSDK.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E78DBA1E2E9786B1009FE663 /* BranchSDK.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
E7EA36B22DD63A350094FCC9 /* SafariServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7EA36B12DD63A350094FCC9 /* SafariServices.framework */; };
F1A2B3C4D5E6F7891ABCDEF1 /* BranchSDK in Frameworks */ = {isa = PBXBuildFile; productRef = F1A2B3C4D5E6F7890ABCDEF0 /* BranchSDK */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand All @@ -31,7 +30,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
E78DBA202E9786B1009FE663 /* BranchSDK.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -54,7 +52,6 @@
C16B97A52B75A4F800FB0631 /* BranchLinkSimulator.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = BranchLinkSimulator.entitlements; sourceTree = "<group>"; };
C16B97A62B75A5F700FB0631 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
C16B97B02B87BD8000FB0631 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; };
E78DBA1E2E9786B1009FE663 /* BranchSDK.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = BranchSDK.xcframework; path = Frameworks/BranchSDK.xcframework; sourceTree = "<group>"; };
E7EA36B12DD63A350094FCC9 /* SafariServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafariServices.framework; path = System/Library/Frameworks/SafariServices.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */

Expand All @@ -64,7 +61,7 @@
buildActionMask = 2147483647;
files = (
E7EA36B22DD63A350094FCC9 /* SafariServices.framework in Frameworks */,
E78DBA1F2E9786B1009FE663 /* BranchSDK.xcframework in Frameworks */,
F1A2B3C4D5E6F7891ABCDEF1 /* BranchSDK in Frameworks */,
C16B97B22B87BD8300FB0631 /* AdSupport.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -120,7 +117,6 @@
C16B97AF2B87BD8000FB0631 /* Frameworks */ = {
isa = PBXGroup;
children = (
E78DBA1E2E9786B1009FE663 /* BranchSDK.xcframework */,
E7EA36B12DD63A350094FCC9 /* SafariServices.framework */,
C16B97B02B87BD8000FB0631 /* AdSupport.framework */,
);
Expand All @@ -145,6 +141,7 @@
);
name = BranchLinkSimulator;
packageProductDependencies = (
F1A2B3C4D5E6F7890ABCDEF0 /* BranchSDK */,
);
productName = BranchLinkSimulator;
productReference = C16B978B2B759F9D00FB0631 /* BranchLinkSimulator.app */;
Expand Down Expand Up @@ -175,6 +172,7 @@
);
mainGroup = C16B97822B759F9D00FB0631;
packageReferences = (
F1A2B3C4D5E6F7890ABCDEF2 /* XCLocalSwiftPackageReference "ios-branch-deep-linking-attribution" */,
);
productRefGroup = C16B978C2B759F9D00FB0631 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -442,6 +440,20 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */

/* Begin XCLocalSwiftPackageReference section */
F1A2B3C4D5E6F7890ABCDEF2 /* XCLocalSwiftPackageReference "ios-branch-deep-linking-attribution" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = "../ios-branch-deep-linking-attribution";
};
/* End XCLocalSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
F1A2B3C4D5E6F7890ABCDEF0 /* BranchSDK */ = {
isa = XCSwiftPackageProductDependency;
productName = BranchSDK;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = C16B97832B759F9D00FB0631 /* Project object */;
}
136 changes: 112 additions & 24 deletions BranchLinkSimulator/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// Created by Nipun Singh on 2/8/24.
//

import SwiftUI
import BranchSDK
import SwiftUI

struct AlertItem: Identifiable {
var id: String { message }
Expand All @@ -22,53 +22,141 @@ class DeepLinkViewModel: ObservableObject {
class AppDelegate: UIResponder, UIApplicationDelegate {
var deepLinkViewModel = DeepLinkViewModel()
var store = RoundTripStore()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {


/// Convenience logger (Objective-C singleton)
private var logger: BranchLogger {
BranchLogger.shared()
}

func application(_: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
let config = loadConfigOrDefault()

// Configure the SDK for API URL and Branch Key
Branch.setAPIUrl(config.apiUrl)
Branch.setBranchKey(config.branchKey)

Branch.enableLogging(at: .verbose) { msg, logLevel, err, request, response in
self.store.processLog(request, response)
}

// Enable verbose logging with advanced callback for console output and RoundTripStore
Branch.enableLogging(at: .verbose, withAdvancedCallback: { [weak self] message, logLevel, error, request, response in
// Log to console (os_log doesn't show verbose/debug in Xcode console)
let levelStr: String
switch logLevel {
case .verbose: levelStr = "VERBOSE"
case .debug: levelStr = "DEBUG"
case .warning: levelStr = "WARNING"
case .error: levelStr = "ERROR"
@unknown default: levelStr = "UNKNOWN"
}
var fullMessage = "[BranchSDK][\(levelStr)] \(message)"
if let error = error {
fullMessage += " Error: \(error.localizedDescription)"
}
NSLog("%@", fullMessage)

// Process for RoundTripStore
self?.store.processLog(request, response)
})

// Retrieve or create the bls_session_id
let blsSessionId: String
if let savedId = UserDefaults.standard.string(forKey: "blsSessionId") {
blsSessionId = savedId
} else {
// Generate a new UUID if one does not exist
blsSessionId = UUID().uuidString
UserDefaults.standard.set(blsSessionId, forKey: "blsSessionId")
}

// Set the bls_session_id in Branch request metadata
Branch.getInstance().setRequestMetadataKey("bls_session_id", value: blsSessionId)

Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
print(params as? [String: AnyObject] ?? {})
// MARK: - Initialize with Branch SDK (Objective-C API)

logger.logVerbose("Initializing Branch SDK...", error: nil)

Branch.getInstance().initSession(launchOptions: launchOptions, andRegisterDeepLinkHandler: { [weak self] params, error in
guard let self = self else { return }

if let error = error {
self.logger.logError("Branch init error: \(error.localizedDescription)", error: error)
var message = "Failed to initialize Branch SDK: \(error.localizedDescription)."
if config.staging {
message += " Are you connected to VPN?"
message += " Are you connected to VPN?"
}
DispatchQueue.main.async {
self.deepLinkViewModel.errorItem = AlertItem(message: message)
}
self.deepLinkViewModel.errorItem = AlertItem(message: message)
} else if let params = params {
self.logger.logVerbose("Branch SDK initialized successfully!", error: nil)
self.logger.logDebug("Params: \(params)", error: nil)

// Handle deep link data if present
self.handleSessionParams(params)
}
if let params = params as? [String: AnyObject] {
if let clickedBranchLink = params["+clicked_branch_link"] as? NSNumber, clickedBranchLink.boolValue == true {
DispatchQueue.main.async {
self.deepLinkViewModel.deepLinkData = params
self.deepLinkViewModel.deepLinkHandled = true
}
} else {
print("Didn't click Branch link")
})

return true
}

// MARK: - Session Handling

/// Handle successful session initialization
private func handleSessionParams(_ params: [AnyHashable: Any]) {
// Check if there's deep link data
let clickedBranchLink = params["+clicked_branch_link"] as? Bool ?? false

if clickedBranchLink {
logger.logVerbose("Deep link detected!", error: nil)
logger.logDebug("Deep link params: \(params)", error: nil)

// Convert params to the format expected by the UI
var displayParams: [String: AnyObject] = [:]
for (key, value) in params {
if let stringKey = key as? String {
displayParams[stringKey] = value as AnyObject
}
}

DispatchQueue.main.async {
self.deepLinkViewModel.deepLinkData = displayParams
self.deepLinkViewModel.deepLinkHandled = true
}
} else {
logger.logVerbose("No deep link data - organic session", error: nil)
}
}

// MARK: - Universal Links

func application(
_: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler _: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL
else {
return false
}


logger.logVerbose("Received Universal Link: \(url)", error: nil)

// Handle via Branch SDK
Branch.getInstance().handleDeepLink(url)

return true
}

// MARK: - URL Scheme Deep Links

func application(
_: UIApplication,
open url: URL,
options _: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
logger.logVerbose("Received URL Scheme: \(url)", error: nil)

// Handle via Branch SDK
Branch.getInstance().handleDeepLink(url)

return true
}

}
10 changes: 7 additions & 3 deletions BranchLinkSimulator/BranchLinkSimulatorApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// Created by Nipun Singh on 2/8/24.
//

import SwiftUI
import BranchSDK
import SwiftUI

@main
struct BranchLinkSimulatorApp: App {
Expand All @@ -17,9 +17,13 @@ struct BranchLinkSimulatorApp: App {
HomeView()
.environmentObject(appDelegate.deepLinkViewModel)
.environmentObject(appDelegate.store)
.onOpenURL(perform: { url in
.onOpenURL { url in
// Use Branch SDK for URL handling
BranchLogger.shared().logVerbose("onOpenURL: \(url)", error: nil)

// Handle the deep link - Branch SDK will call the init callback
Branch.getInstance().handleDeepLink(url)
})
}
}
}
}
Loading