├── checksum
├── BranchTestHost
├── Assets.xcassets
│ ├── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── ViewController.h
├── AppDelegate.h
├── BranchTestHost.entitlements
├── main.m
├── AppDelegate.m
├── ViewController.m
└── Info.plist
├── Examples
├── TestBed-macOS
│ ├── TestBed-macOS
│ │ ├── Assets.xcassets
│ │ │ ├── Contents.json
│ │ │ ├── Branch.imageset
│ │ │ │ ├── Branch-16.png
│ │ │ │ ├── Branch-32.png
│ │ │ │ ├── Branch-48.png
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── AppIcon-128.png
│ │ │ │ ├── AppIcon-16.png
│ │ │ │ ├── AppIcon-256.png
│ │ │ │ ├── AppIcon-32.png
│ │ │ │ ├── AppIcon-512.png
│ │ │ │ ├── AppIcon-128@2x.png
│ │ │ │ ├── AppIcon-16@2x.png
│ │ │ │ ├── AppIcon-256@2x.png
│ │ │ │ ├── AppIcon-32@2x.png
│ │ │ │ ├── AppIcon-512@2x.png
│ │ │ │ └── Contents.json
│ │ ├── main.m
│ │ ├── APPAppDelegate.h
│ │ ├── APPActionItemView.h
│ │ ├── TestBed-macOS.entitlements
│ │ ├── APPViewController.h
│ │ ├── APPActionItemView.m
│ │ ├── Info.plist
│ │ └── APPV2EventSelectionWindow.xib
│ ├── TestBed-macOSUITests
│ │ ├── TestDeepLinking.zip
│ │ ├── TestBed-macOS-UITest.entitlements
│ │ ├── TestWebPage.html
│ │ ├── TestDeferredLinking.html
│ │ ├── TestNonBranchLink.html
│ │ ├── TestRaceConditionWebPage.html
│ │ ├── TestRedirectionWebPage.html
│ │ ├── TestBedUIUtils.h
│ │ ├── Info.plist
│ │ ├── TestBedUITest.h
│ │ ├── TestBedUIV2EventTest.m
│ │ ├── TestBedUISetIdentityTest.m
│ │ ├── TestBedUINonBranchLinkTest.m
│ │ └── TestBedUIInstallOpenTest.m
│ ├── TestBed-macOS.xcodeproj
│ │ └── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── README.md
│ ├── TestBed-macOSTests
│ │ ├── Info.plist
│ │ └── TestBed-MacTests.m
│ └── TestPlan.xctestplan
└── TestDeepLinking
│ ├── TestDeepLinking
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── main.m
│ ├── TestDeepLinking.entitlements
│ ├── AppDelegate.h
│ ├── Info.plist
│ └── AppDelegate.m
│ ├── TestDeepLinking.xcodeproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ ├── TestDeepLinkingTests
│ ├── Info.plist
│ └── TestDeepLinkingTests.m
│ └── TestDeepLinkingUITests
│ ├── Info.plist
│ └── TestDeepLinkingUITests.m
├── README.md
├── Branch.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ ├── IDETemplateMacros.plist
│ └── xcschemes
│ ├── Branch-macOS.xcscheme
│ ├── Branch-framework.xcscheme
│ └── BranchTestHost.xcscheme
├── Branch
├── Branch.m
├── BNCThreads.m
├── BranchHeader.m
├── Branch.modulemap
├── BNCUserAgentCollector.h
├── NSData+Branch.h
├── BNCQRCodeCache.h
├── BranchHeader.h
├── BranchDelegate.m
├── BranchMutableDictionary.h
├── BranchMainClass+Private.h
├── BNCEncoder.h
├── Branch.h
├── Info.plist
├── BNCNetworkInformation.h
├── NSString+Branch.h
├── BNCNetworkService.h
├── BNCLocalization.h
├── BranchLinkProperties.h
├── BNCPersistence.h
├── NSString+Branch.m
├── BNCURLBlackList.h
├── BNCQRCodeCache.m
├── BranchSession.h
├── BNCNetworkAPIService.h
├── BNCSettings.h
├── NSData+Branch.m
├── BranchError.h
├── BNCDevice.h
├── BNCThreads.h
├── BranchQRCode.h
├── BranchMutableDictionary.m
├── BranchLinkProperties.m
├── BranchSession.m
├── BNCKeyChain.h
├── BranchNetworkServiceProtocol.h
├── BNCApplication.h
├── BranchDelegate.h
├── BNCUserAgentCollector.m
└── BranchError.m
├── SECURITY.md
├── Scripts
├── deploy-build-framework
├── deploy-checksum
├── deploy-git-tag
├── deploy-preflight
├── deploy-release
└── whichapp
├── BranchTests
├── BranchTests-Bridging-Header.h
├── BranchCommerce.Test.m
├── Branch.Test.m
├── Info.plist
├── BNCTestCase.Test.m
├── BNCPersistence.Test.m
├── BNCNetworkInformation.Test.m
├── BNCTestCase.h
├── BNCTestNetworkService.Test.m
├── BranchUserTrackingDisabled.m
├── BNCTestNetworkService.h
├── NSData+Branch.Test.m
├── BranchMutableDictionary.Test.m
├── BNCDevice.Test.m
├── BranchLinkProperties.Test.m
├── BranchError.Test.m
├── BNCLocalization.Test.m
├── NSString+Branch.Test.m
├── BNCThreads.Test.m
├── BNCTestNetworkService.m
├── BNCApplication.Test.m
├── BNCKeyChain.Test.m
└── BNCUserAgentCollectorTests.m
├── .github
├── ISSUE_TEMPLATE
│ ├── feature-request.yml
│ ├── config.yml
│ └── bug-report.yml
├── workflows
│ ├── stale.yml
│ └── sync-readme-changelog.yml
└── PULL_REQUEST_TEMPLATE.md
├── Package.swift
├── LICENSE
├── BranchMacOS.podspec
├── .gitignore
└── CHANGELOG.md
/checksum:
--------------------------------------------------------------------------------
1 | #checksum for Branch.zip on Github
2 | 7dabc397fcb4eab8dda7a858837a8832024170b0 Branch.zip
3 |
--------------------------------------------------------------------------------
/BranchTestHost/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Branch SDK Documentation for Mac OS
2 |
3 | View [Branch's SDK documentation for Mac OS](https://help.branch.io/developers-hub/docs/mac-os-sdk-overview)
4 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestDeepLinking.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOSUITests/TestDeepLinking.zip
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/Branch.imageset/Branch-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/Branch.imageset/Branch-16.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/Branch.imageset/Branch-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/Branch.imageset/Branch-32.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/Branch.imageset/Branch-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/Branch.imageset/Branch-48.png
--------------------------------------------------------------------------------
/Branch.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-16@2x.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BranchMetrics/mac-branch-deep-linking/HEAD/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Branch/Branch.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file Branch.h
3 | @package Branch
4 | @brief The Branch framework header.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "Branch.h"
12 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/README.md:
--------------------------------------------------------------------------------
1 | # TestBed-Mac
2 |
3 | This is a quick example of using the Branch SDK in Mac apps.
4 |
5 | It's also is a testbed for the Branch Mac SDK unit and UI tests.
6 |
7 | ## Building & Running
8 |
9 | Open the TestBed-Mac.xcodeproj file in Xcode and select Project > Run from the menu.
10 |
--------------------------------------------------------------------------------
/Branch.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Branch/BNCThreads.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCThreads.m
3 | @package Branch
4 | @brief Utilities for working with threads, queues, and blocks.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCThreads.h"
12 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TestBed-Mac
4 | //
5 | // Created by Edward Smith on 5/15/18.
6 | // Copyright © 2018 Edward Smith. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | int main(int argc, const char * argv[]) {
12 | return NSApplicationMain(argc, argv);
13 | }
14 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestBed-macOS-UITest.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Branch/BranchHeader.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchHeader.h
3 | @package Branch
4 | @brief Imports the system header dependencies for the Branch SDK.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Reporting a Vulnerability
4 | If you discover a potential security issue in this project we ask that you notify Branch Security directly via email to security@branch.io
5 | Please do not open GitHub issues or pull requests - this makes the problem immediately visible to everyone, including malicious actors.
6 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Scripts/deploy-build-framework:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -euo pipefail
3 |
4 | # deploy-build-framework
5 | #
6 | # Edward Smith, August 2017
7 |
8 | scriptname=$(basename "${BASH_SOURCE[0]}")
9 | scriptpath="${BASH_SOURCE[0]}"
10 | scriptpath=$(cd "$(dirname "${scriptpath}")" && pwd)
11 | cd ${scriptpath}/../
12 |
13 | # Build
14 | xcodebuild -scheme 'Branch-framework'
15 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/APPAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // APPAppDelegate.h
3 | // TestBed-Mac
4 | //
5 | // Created by Edward Smith on 5/15/18.
6 | // Copyright © 2018 Edward Smith. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface APPAppDelegate : NSObject
12 | - (void) processLogMessage:(NSString*)message;
13 | @end
14 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TestDeepLinking
4 | //
5 | // Created by Nidhi on 2/3/21.
6 | //
7 |
8 | #import
9 |
10 | int main(int argc, const char * argv[]) {
11 | @autoreleasepool {
12 | // Setup code that might create autoreleased objects goes here.
13 | }
14 | return NSApplicationMain(argc, argv);
15 | }
16 |
--------------------------------------------------------------------------------
/Branch/Branch.modulemap:
--------------------------------------------------------------------------------
1 | /**
2 | @file Branch.modulemap
3 | @package Branch
4 | @brief The Branch SDK module map file.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | framework module Branch {
12 | umbrella header "Branch.h"
13 | export *
14 | module * { export * }
15 | }
16 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/APPActionItemView.h:
--------------------------------------------------------------------------------
1 | //
2 | // APPActionItemView.h
3 | // TestBed-Mac
4 | //
5 | // Created by Edward on 5/30/18.
6 | // Copyright © 2018 Branch. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface APPActionItemView : NSCollectionViewItem
13 | @property (weak) IBOutlet NSTextField *detailTextField;
14 | @end
15 |
--------------------------------------------------------------------------------
/BranchTests/BranchTests-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchTests-Bridging-Header.h
3 | @package BranchTests
4 | @brief The bridging header for the BranchTests target.
5 |
6 | @author Edward Smith
7 | @date June 10, 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "Branch.h"
12 | #import "BNCTestCase.h"
13 | #import "BNCThreads.h"
14 |
--------------------------------------------------------------------------------
/BranchTestHost/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | /**
3 | @file ViewController.h
4 | @package BranchTestHost
5 | @brief < A brief description of the file function. >
6 |
7 | @author Ernest Cho
8 | @date 2020
9 | @copyright Copyright © 2020 Branch. All rights reserved.
10 | */
11 |
12 | #import
13 |
14 | @interface ViewController : NSViewController
15 |
16 |
17 | @end
18 |
19 |
--------------------------------------------------------------------------------
/BranchTestHost/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | /**
3 | @file AppDelegate.h
4 | @package BranchTestHost
5 | @brief < A brief description of the file function. >
6 |
7 | @author Ernest Cho
8 | @date 2020
9 | @copyright Copyright © 2020 Branch. All rights reserved.
10 | */
11 |
12 | #import
13 |
14 | @interface AppDelegate : NSObject
15 |
16 |
17 | @end
18 |
19 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking/TestDeepLinking.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.associated-domains
6 |
7 | wfnz6.app.link
8 | wfnz6-alternate.app.link
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/BranchTestHost/BranchTestHost.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 | com.apple.security.network.client
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestWebPage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Branch SDK : macOS
7 |
8 |
9 |
10 | Branch SDK for macOS
11 | Open in the app!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestDeferredLinking.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Branch SDK : macOS
7 |
8 |
9 |
10 | Branch SDK for macOS
11 | Open in the app!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestNonBranchLink.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Branch SDK : macOS
7 |
8 |
9 |
10 | Branch SDK for macOS - Test Non-Branch link
11 | Open in the app!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🚀 Feature Request
3 | description: Suggest an idea for this project
4 | title: "(short issue description)"
5 | labels: [feature-request, needs-triage]
6 | assignees: []
7 | body:
8 | - type: textarea
9 | id: description
10 | attributes:
11 | label: Describe the feature
12 | description: A clear and concise description of the feature you are proposing.
13 | validations:
14 | required: true
15 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestRaceConditionWebPage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Branch SDK : macOS
7 |
8 |
9 |
10 | Branch SDK for macOS
11 | Open in the app ( Select cancel to open in Web SDK)!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestRedirectionWebPage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Branch SDK : macOS
7 |
8 |
9 |
10 | Branch SDK for macOS
11 | Open in the app! ($afterclick_desktop_url param added.)
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // TestDeepLinking
4 | //
5 | // Created by Nidhi on 2/3/21.
6 | //
7 |
8 | #import
9 |
10 | @interface AppDelegate : NSObject
11 |
12 | @property (weak) IBOutlet NSTextField *notification;
13 | @property (weak) IBOutlet NSScrollView *logs;
14 | @property (unsafe_unretained) IBOutlet NSTextView *sessionData;
15 |
16 | - (void) processLogMessage:(NSString*)message;
17 |
18 | @end
19 |
20 |
--------------------------------------------------------------------------------
/BranchTestHost/main.m:
--------------------------------------------------------------------------------
1 | //
2 | /**
3 | @file main.m
4 | @package BranchTestHost
5 | @brief < A brief description of the file function. >
6 |
7 | @author Ernest Cho
8 | @date 2020
9 | @copyright Copyright © 2020 Branch. All rights reserved.
10 | */
11 |
12 | #import
13 |
14 | int main(int argc, const char * argv[]) {
15 | @autoreleasepool {
16 | // Setup code that might create autoreleased objects goes here.
17 | }
18 | return NSApplicationMain(argc, argv);
19 | }
20 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/Branch.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Branch-16.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Branch-32.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Branch-48.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | ---
2 | blank_issues_enabled: false
3 | contact_links:
4 | - name: "📕 Documentation Issue"
5 | url: https://help.branch.io/developers-hub/docs/mac-os-sdk-overview
6 | about: Report an issue in the Branch macOS SDK Reference documentation by clicking "Suggest edits" button on the documentation page.
7 | - name: "Branch Support"
8 | url: https://help.branch.io/using-branch/page/submit-a-ticket
9 | about: If you are having general trouble with Branch macOS SDK integration, please submit a ticket to Branch Support.
10 |
--------------------------------------------------------------------------------
/Branch/BNCUserAgentCollector.h:
--------------------------------------------------------------------------------
1 | //
2 | // BNCUserAgentCollector.h
3 | // Branch
4 | //
5 | // Created by Ernest Cho on 8/29/19.
6 | // Copyright © 2019 Branch, Inc. All rights reserved.
7 | //
8 |
9 | @import Foundation;
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface BNCUserAgentCollector : NSObject
14 |
15 | + (BNCUserAgentCollector *)instance;
16 |
17 | @property (nonatomic, copy, readwrite) NSString *userAgent;
18 |
19 | - (void)loadUserAgentWithCompletion:(void (^)(NSString * _Nullable userAgent))completion;
20 |
21 | @end
22 |
23 | NS_ASSUME_NONNULL_END
24 |
--------------------------------------------------------------------------------
/Branch.xcodeproj/xcshareddata/IDETemplateMacros.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FILEHEADER
6 |
7 | /**
8 | @file ___FILENAME___
9 | @package ___PACKAGENAME___
10 | @brief < A brief description of the file function. >
11 |
12 | @author ___FULLUSERNAME___
13 | @date ___YEAR___
14 | @copyright ___COPYRIGHT___
15 | */
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Branch/NSData+Branch.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file NSData+Branch.h
3 | @package Branch
4 | @brief NSData additions.
5 |
6 | @author Edward Smith
7 | @date June 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | @interface NSData (Branch)
16 | + (NSData*) bnc_dataWithHexString:(NSString*)string;
17 | @end
18 |
19 | FOUNDATION_EXPORT void BNCForceNSDataCategoryToLoad(void)
20 | __attribute__((constructor));
21 |
22 | NS_ASSUME_NONNULL_END
23 |
--------------------------------------------------------------------------------
/Branch/BNCQRCodeCache.h:
--------------------------------------------------------------------------------
1 | //
2 | // BNCQRCodeCache.h
3 | // BranchMacOS
4 | //
5 | // Created by Nipun Singh on 5/24/22.
6 | // Copyright © 2022 Branch, Inc. All rights reserved.
7 | //
8 |
9 | #import "BranchHeader.h"
10 |
11 | #ifndef BNCQRCodeCache_h
12 | #define BNCQRCodeCache_h
13 |
14 | @interface BNCQRCodeCache : NSObject
15 |
16 | + (BNCQRCodeCache *) sharedInstance;
17 | - (void)addQRCodeToCache:(NSData *)qrCodeData withParams:(NSMutableDictionary *)parameters;
18 | - (NSData *)checkQRCodeCache:(NSMutableDictionary *)parameters;
19 |
20 | @end
21 |
22 | #endif /* BNCQRCodeCache_h */
23 |
--------------------------------------------------------------------------------
/Branch/BranchHeader.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchHeader.h
3 | @package Branch
4 | @brief Imports the system header dependencies for the Branch SDK.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #ifndef BranchHeader_h
12 | #define BranchHeader_h
13 |
14 | #if __has_feature(modules)
15 | @import Foundation;
16 | #else
17 | #import
18 | #endif
19 |
20 | #if __has_feature(modules)
21 | @import AppKit;
22 | #else
23 | #import
24 | #endif
25 |
26 | #endif // BranchHeader_h
27 |
--------------------------------------------------------------------------------
/BranchTests/BranchCommerce.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchCommerce.Test.m
3 | @package BranchTests
4 | @brief BranchCommerce Tests
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BranchCommerce.h"
13 |
14 | @interface BranchCommerceTest : BNCTestCase
15 | @end
16 |
17 | @implementation BranchCommerceTest
18 |
19 | - (void)testBranchCommerce {
20 | XCTAssertTrue(BNCProductCategoryAllCategories().count == 21);
21 | XCTAssertTrue(BNCCurrencyAllCurrencies().count == 178);
22 | }
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "Branch",
8 | platforms: [
9 | .macOS(.v10_14)
10 | ],
11 | products: [
12 | .library(
13 | name: "Branch",
14 | targets: ["Branch"]),
15 | ],
16 | targets: [
17 | .target(
18 | name: "Branch",
19 | path: "Branch",
20 | publicHeadersPath: ".",
21 | cSettings: [
22 | .headerSearchPath("../"),
23 | ]
24 | ),
25 | ]
26 | )
27 |
28 |
--------------------------------------------------------------------------------
/BranchTestHost/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | /**
3 | @file AppDelegate.m
4 | @package BranchTestHost
5 | @brief < A brief description of the file function. >
6 |
7 | @author Ernest Cho
8 | @date 2020
9 | @copyright Copyright © 2020 Branch. All rights reserved.
10 | */
11 |
12 | #import "AppDelegate.h"
13 |
14 | @interface AppDelegate ()
15 |
16 | @end
17 |
18 | @implementation AppDelegate
19 |
20 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
21 | // Insert code here to initialize your application
22 | }
23 |
24 |
25 | - (void)applicationWillTerminate:(NSNotification *)aNotification {
26 | // Insert code here to tear down your application
27 | }
28 |
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/TestBed-macOS.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.associated-domains
6 |
7 | applinks:testbed-mac.app.link
8 |
9 | com.apple.security.app-sandbox
10 |
11 | com.apple.security.files.user-selected.read-only
12 |
13 | com.apple.security.network.client
14 |
15 | keychain-access-groups
16 |
17 | $(AppIdentifierPrefix)io.branch.sdk.TestBed-Mac
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/BranchTestHost/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | /**
3 | @file ViewController.m
4 | @package BranchTestHost
5 | @brief < A brief description of the file function. >
6 |
7 | @author Ernest Cho
8 | @date 2020
9 | @copyright Copyright © 2020 Branch. All rights reserved.
10 | */
11 |
12 | #import "ViewController.h"
13 |
14 | @implementation ViewController
15 |
16 | // Comment for test commit
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 |
20 | // Do any additional setup after loading the view.
21 | }
22 |
23 |
24 | - (void)setRepresentedObject:(id)representedObject {
25 | [super setRepresentedObject:representedObject];
26 |
27 | // Update the view, if already loaded.
28 | }
29 |
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestBedUIUtils.h:
--------------------------------------------------------------------------------
1 | //
2 | // TestBedUIUtils.h
3 | // TestBed-macOSUITests
4 | //
5 | // Created by Nidhi on 11/3/20.
6 | // Copyright © 2020 Branch. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | #define TESTBED_CLICK_LINK "https://testbed-mac.app.link/ODYeswaVWM"
14 | #define TESTBED_CLICK_LINK_WITH_REDIRECTION "https://testbed-mac.app.link/y94TsHlrAdb"
15 | #define TESTBED_CLICK_LINK_RACE_CONDN "https://testbed-mac.app.link/KnH4lWDO6bb"
16 |
17 | @interface TestBedUIUtils : NSObject
18 |
19 | + (NSDictionary *) dictionaryFromString:(NSString *)APIDataString;
20 | + (void) deleteSettingsFiles;
21 |
22 | @end
23 |
24 | NS_ASSUME_NONNULL_END
25 |
--------------------------------------------------------------------------------
/Scripts/deploy-checksum:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -euo pipefail
3 |
4 | # deploy-checksum - The zip & checksum the framework.
5 | #
6 | # Edward Smith, December 2016
7 |
8 | scriptname=$(basename "${BASH_SOURCE[0]}")
9 | scriptpath="${BASH_SOURCE[0]}"
10 | scriptpath=$(cd "$(dirname "${scriptpath}")" && pwd)
11 | cd ${scriptpath}/../build
12 |
13 | # Zip the SDK files
14 | echo "Zipping frameworks"
15 | zip -rqy Branch.zip Branch.framework/
16 |
17 | # Checksum the zip files
18 | echo "Creating checksums"
19 | checksum_file=checksum
20 |
21 | echo '#checksum for Branch.zip on Github' > "$checksum_file"
22 | shasum Branch.zip >> $checksum_file
23 |
24 | # remove source frameworks
25 | mv Branch.zip ..
26 | mv checksum ..
27 | echo "Cleaning up"
28 | rm -rf Branch.framework
29 |
30 |
--------------------------------------------------------------------------------
/BranchTests/Branch.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file Branch.Test.m
3 | @package BranchTests
4 | @brief Branch frame work tests.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "Branch.h"
13 |
14 | @interface BranchTest : BNCTestCase
15 | @end
16 |
17 | @implementation BranchTest
18 |
19 | - (void)testVersion {
20 | double vn = BranchVersionNumber;
21 | const unsigned char *vs = BranchVersionString;
22 | XCTAssertTrue(vn > 0 && vs);
23 | NSString*testString = [[NSString alloc] initWithUTF8String:(const char*)vs];
24 | XCTAssertTrue([testString hasPrefix:@"@(#)PROGRAM:Branch PROJECT:Branch-"]);
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Branch/BranchDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchDelegate.m
3 | @package Branch
4 | @brief Branch delegate protocol and notifications.
5 |
6 | @author Edward Smith
7 | @date June 30, 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchDelegate.h"
12 |
13 | NSString* const BranchWillStartSessionNotification = @"BranchWillStartSessionNotification";
14 | NSString* const BranchDidStartSessionNotification = @"BranchDidStartSessionNotification";
15 | NSString* const BranchDidOpenURLWithSessionNotification = @"BranchDidOpenURLWithSessionNotification";
16 |
17 | NSString* const BranchErrorKey = @"BranchErrorKey";
18 | NSString* const BranchURLKey = @"BranchURLKey";
19 | NSString* const BranchSessionKey = @"BranchSessionKey";
20 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Branch/BranchMutableDictionary.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchMutableDictionary.h
3 | @package Branch
4 | @brief A thread-safe mutable dictionary.
5 |
6 | @author Edward Smith
7 | @date July 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import
12 |
13 |
14 | #ifndef BranchMutableDictionary_h
15 | #define BranchMutableDictionary_h
16 |
17 | /**
18 | This is a thread-safe version of an NSMutableDictionary.
19 | */
20 | @interface BranchMutableDictionary : NSMutableDictionary
21 | - (instancetype) init NS_DESIGNATED_INITIALIZER;
22 | - (instancetype) initWithCapacity:(NSUInteger)numItems NS_DESIGNATED_INITIALIZER;
23 | - (instancetype) initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
24 | @end
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinkingTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinkingUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/BranchTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | AppIdentifierPrefix
22 | $(AppIdentifierPrefix)
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Branch/BranchMainClass+Private.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchMainClass+Private.h
3 | @package Branch
4 | @brief Private definitions for the Branch class.
5 |
6 | @author Edward Smith
7 | @date June 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchMainClass.h"
12 | @class BNCNetworkAPIService, BNCSettings;
13 |
14 | NS_ASSUME_NONNULL_BEGIN
15 |
16 | @interface Branch (Private)
17 | @property (atomic, strong, readonly) BNCNetworkAPIService*_Nullable networkAPIService;
18 | @property (atomic, strong, readonly) BranchConfiguration*_Nullable configuration;
19 | - (void) clearAllSettings;
20 | - (void) startNewSession;
21 | - (void) endSession;
22 | @end
23 |
24 | @interface BranchConfiguration (Private)
25 | @property (atomic, strong, readonly) BNCSettings* settings;
26 | @end
27 |
28 | NS_ASSUME_NONNULL_END
29 |
--------------------------------------------------------------------------------
/Branch/BNCEncoder.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCEncoder.h
3 | @package Branch
4 | @brief A light weight, general purpose object encoder.
5 |
6 | @author Edward Smith
7 | @date June 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | @interface BNCEncoder : NSObject
16 |
17 | + (NSError*_Nullable) decodeInstance:(id)instance
18 | withCoder:(NSCoder*)coder
19 | ignoring:(NSArray*_Nullable)ignoreIvars;
20 |
21 | + (NSError*_Nullable) encodeInstance:(id)instance
22 | withCoder:(NSCoder*)coder
23 | ignoring:(NSArray*_Nullable)ignoreIvars;
24 |
25 | + (NSError*) copyInstance:(id)toInstance
26 | fromInstance:(id)fromInstance
27 | ignoring:(NSArray*_Nullable)ignoreIvarsArray;
28 |
29 | @end
30 |
31 | NS_ASSUME_NONNULL_END
32 |
--------------------------------------------------------------------------------
/Scripts/deploy-git-tag:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -euo pipefail
3 |
4 | # deploy-git-tag - Commit and push the current git changes. Create a version tag and push to master.
5 | #
6 | # Edward Smith, January 2017
7 |
8 | scriptfile="$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9 | scriptfile="${scriptfile}"/$(basename "$0")
10 | cd $(dirname "$scriptfile")/..
11 |
12 | git_branch=$(git symbolic-ref --short HEAD)
13 | version=$(./scripts/version)
14 |
15 | echo ">>> Merging and pushing '$git_branch' to master..." 1>&2
16 |
17 | # Tag and merge the release to master:
18 | git add --all
19 | git commit -m "Release ${version}."
20 | git push
21 | git checkout master
22 | git pull
23 | git merge -m "Merge ${git_branch}." origin "${git_branch}"
24 | (git commit || true)
25 | git tag "${version}"
26 | git push
27 | git push --tags origin master
28 |
29 | # Update staging from master:
30 | git checkout staging
31 | git pull
32 | git pull origin master
33 | git push
34 |
--------------------------------------------------------------------------------
/Branch/Branch.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file Branch.h
3 | @package Branch
4 | @brief The Branch framework header.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | /// The Branch SDK version number as a double.
14 | FOUNDATION_EXPORT double BranchVersionNumber;
15 |
16 | /// The Branch SDK version framework string.
17 | FOUNDATION_EXPORT const unsigned char BranchVersionString[];
18 |
19 | #import "BranchCommerce.h"
20 | #import "BranchDelegate.h"
21 | #import "BranchError.h"
22 | #import "BranchEvent.h"
23 | #import "BranchLinkProperties.h"
24 | #import "BranchNetworkServiceProtocol.h"
25 | #import "BranchMainClass.h"
26 | #import "BranchMutableDictionary.h"
27 | #import "BranchSession.h"
28 | #import "BranchUniversalObject.h"
29 | #import "BranchQRCode.h"
30 |
31 | // Exposed private headers:
32 | #import "BNCLog.h"
33 |
--------------------------------------------------------------------------------
/BranchTests/BNCTestCase.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCTestCase.Test.m
3 | @package BranchTests
4 | @brief Test cases for the BNCTestCase super class.
5 |
6 | @author Edward Smith
7 | @date April 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 |
13 | @interface BNCTestCaseTest : BNCTestCase
14 | @end
15 |
16 | @implementation BNCTestCaseTest
17 |
18 | - (void) testFailure {
19 | // Un-comment the next line to test a failure case:
20 | // XCTAssert(NO, @"Testing a test failure!");
21 | XCTAssertTrue(YES, @"Test passes!");
22 | NSString * bundleID = [NSBundle mainBundle].bundleIdentifier;
23 | NSLog(@"The test bundleID is '%@'.", bundleID);
24 | }
25 |
26 | - (void) testLoadString {
27 | NSString *string = [self stringFromBundleWithKey:@"BNCTestCaseString"];
28 | XCTAssertEqualObjects(string, @"Test success!");
29 | }
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/APPViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // APPViewController.h
3 | // TestBed-Mac
4 | //
5 | // Created by Edward Smith on 5/15/18.
6 | // Copyright © 2018 Edward Smith. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface APPViewController : NSViewController
12 | + (APPViewController*) loadController;
13 | @property (weak) IBOutlet NSButton *trackingDisabled;
14 | @property (weak) IBOutlet NSButton *limitFacebookTracking;
15 | @property (weak) IBOutlet NSTextField *stateField;
16 | @property (weak) IBOutlet NSTextField *urlField;
17 | @property (weak) IBOutlet NSTextField *errorField;
18 | @property (strong) IBOutlet NSTextView *dataTextView;
19 | @property (strong) IBOutlet NSTextView *requestTextView;
20 | @property (strong) IBOutlet NSTextView *responseTextView;
21 | @property (nonatomic, strong) IBOutlet NSWindow* window;
22 |
23 | - (void) clearUIFields;
24 | - (NSArray *) v2Events;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Branch/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | 1
21 | NSHumanReadableCopyright
22 | Copyright © 2018 Branch. All rights reserved.
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinkingTests/TestDeepLinkingTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestDeepLinkingTests.m
3 | // TestDeepLinkingTests
4 | //
5 | // Created by Nidhi on 2/3/21.
6 | //
7 |
8 | #import
9 |
10 | @interface TestDeepLinkingTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation TestDeepLinkingTests
15 |
16 | - (void)setUp {
17 | // Put setup code here. This method is called before the invocation of each test method in the class.
18 | }
19 |
20 | - (void)tearDown {
21 | // Put teardown code here. This method is called after the invocation of each test method in the class.
22 | }
23 |
24 | - (void)testExample {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | - (void)testPerformanceExample {
30 | // This is an example of a performance test case.
31 | [self measureBlock:^{
32 | // Put the code you want to measure the time of here.
33 | }];
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Branch
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSTests/TestBed-MacTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestBed-macOSTests.m
3 | // TestBed-macOSTests
4 | //
5 | // Created by Edward Smith on 5/21/18.
6 | // Copyright © 2018 Branch. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TestBedmacOSTests : XCTestCase
12 | @end
13 |
14 | @implementation TestBedmacOSTests
15 |
16 | - (void)setUp {
17 | [super setUp];
18 | // Put setup code here. This method is called before the invocation of each test method in the class.
19 | }
20 |
21 | - (void)tearDown {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | [super tearDown];
24 | }
25 |
26 | - (void)testExample {
27 | NSLog(@"Yo. Bundle: '%@'.", [NSBundle mainBundle].bundleIdentifier);
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/BranchTestHost/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "scale" : "1x",
6 | "size" : "16x16"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "2x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "1x",
16 | "size" : "32x32"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "2x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "1x",
26 | "size" : "128x128"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "2x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "1x",
36 | "size" : "256x256"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "2x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x",
46 | "size" : "512x512"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "2x",
51 | "size" : "512x512"
52 | }
53 | ],
54 | "info" : {
55 | "author" : "xcode",
56 | "version" : 1
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | # This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
2 | #
3 | # You can adjust the behavior by modifying this file.
4 | # For more information, see:
5 | # https://github.com/actions/stale
6 | name: Mark stale issues
7 |
8 | on:
9 | schedule:
10 | - cron: '0 0 * * *'
11 |
12 | jobs:
13 | stale:
14 |
15 | runs-on: ubuntu-latest
16 | permissions:
17 | issues: write
18 |
19 | steps:
20 | - uses: actions/stale@v5
21 | with:
22 | repo-token: ${{ github.token }}
23 | days-before-issue-stale: 60
24 | days-before-close: 7
25 | stale-issue-message: 'This issue has been automatically marked as stale due to inactivity for 60 days. If this issue is still relevant, please respond with any updates or this issue will be closed in 7 days. If you believe this is a mistake, please comment to let us know. Thank you for your contributions.'
26 | stale-issue-label: 'no-issue-activity'
27 | close-issue-message: 'This issue has been closed due to inactivity. If this issue is still relevant, please reopen it or create a new one. Thank you for your contributions.'
28 | start-date: '2023-05-22'
29 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "scale" : "1x",
6 | "size" : "16x16"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "2x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "1x",
16 | "size" : "32x32"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "2x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "1x",
26 | "size" : "128x128"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "2x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "1x",
36 | "size" : "256x256"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "2x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x",
46 | "size" : "512x512"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "2x",
51 | "size" : "512x512"
52 | }
53 | ],
54 | "info" : {
55 | "author" : "xcode",
56 | "version" : 1
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Branch/BNCNetworkInformation.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCNetworkInformation.h
3 | @package Branch
4 | @brief This class retreives information about the local network.
5 |
6 | @author Edward Smith
7 | @date August 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | typedef NS_ENUM(NSInteger, BNCInetAddressType) {
16 | BNCInetAddressTypeUnknown = 0,
17 | BNCInetAddressTypeIPv4,
18 | BNCInetAddressTypeIPv6
19 | };
20 |
21 | @interface BNCNetworkInformation : NSObject
22 | + (BNCNetworkInformation*_Nullable) local;
23 | + (NSArray*) areaEntries;
24 | + (NSArray*) currentInterfaces;
25 | @property (nonatomic, readonly, strong) NSString*interface;
26 | @property (nonatomic, readonly, strong) NSData*_Nullable address;
27 | @property (nonatomic, readonly, strong) NSString*displayAddress;
28 | @property (nonatomic, readonly, strong) NSData*_Nullable inetAddress;
29 | @property (nonatomic, readonly, strong) NSString*displayInetAddress;
30 | @property (nonatomic, readonly, assign) BNCInetAddressType inetAddressType;
31 | @end
32 |
33 | NS_ASSUME_NONNULL_END
34 |
35 |
--------------------------------------------------------------------------------
/Branch/NSString+Branch.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file NSString+Branch.h
3 | @package Branch
4 | @brief NSString Additions
5 |
6 | @author Edward Smith
7 | @date February 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | @interface NSString (Branch)
16 |
17 | /**
18 | Compares the receiver to a masked string. Masked characters (the '*' character) are
19 | ignored for purposes of the compare.
20 |
21 | @return YES if string (ignoring any masked characters) is equal to the receiver.
22 | */
23 | - (BOOL) bnc_isEqualToMaskedString:(NSString*_Nullable)string;
24 |
25 | /** @return Returns a string that is truncated at the first null character. */
26 | - (NSString*) bnc_stringTruncatedAtNull;
27 |
28 | /**
29 | The `containsString:` method isn't supported pre-iOS 8. Here we roll our own.
30 |
31 | @param string The string to for comparison.
32 |
33 | @return Reurns true if the instance contains the string.
34 | */
35 | - (BOOL) bnc_containsString:(NSString*_Nullable)string;
36 | @end
37 |
38 | FOUNDATION_EXPORT void BNCForceNSStringCategoryToLoad(void)
39 | __attribute__((constructor));
40 |
41 | NS_ASSUME_NONNULL_END
42 |
--------------------------------------------------------------------------------
/Branch/BNCNetworkService.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCNetworkService.h
3 | @package Branch
4 | @brief Basic Networking Services
5 |
6 | @author Edward Smith
7 | @date April 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 | #import "BranchNetworkServiceProtocol.h"
13 |
14 | NS_ASSUME_NONNULL_BEGIN
15 |
16 | #pragma mark BNCNetworkOperation
17 |
18 | @interface BNCNetworkOperation : NSObject
19 |
20 | @property (readonly) NSMutableURLRequest* request;
21 | @property (readonly) NSError*_Nullable error;
22 | @property (readonly) NSInteger HTTPStatusCode;
23 | @property (readonly) NSData*_Nullable responseData;
24 |
25 | - (void) start;
26 | - (void) cancel;
27 | @end
28 |
29 | #pragma mark - BNCNetworkService
30 |
31 | @interface BNCNetworkService : NSObject
32 |
33 | - (id) networkOperationWithURLRequest:(NSMutableURLRequest*)request
34 | completion:(void (^)(idoperation))completion;
35 |
36 | @property (atomic, assign) NSInteger maxConcurrentOperationCount;
37 |
38 | - (void) cancelAllOperations;
39 |
40 | @end
41 |
42 | NS_ASSUME_NONNULL_END
43 |
44 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Reference
2 | SDK-XXXX -- .
3 |
4 | ## Summary
5 |
6 |
7 | ## Motivation
8 |
9 |
10 | ## Type Of Change
11 |
12 | - [ ] Bug fix (non-breaking change which fixes an issue)
13 | - [ ] New feature (non-breaking change which adds functionality)
14 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
15 | - [ ] This change requires a documentation update
16 |
17 | ## Testing Instructions
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | cc @BranchMetrics/saas-sdk-devs for visibility.
30 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/APPActionItemView.m:
--------------------------------------------------------------------------------
1 | //
2 | // APPActionItemView.m
3 | // TestBed-Mac
4 | //
5 | // Created by Edward on 5/30/18.
6 | // Copyright © 2018 Branch. All rights reserved.
7 | //
8 |
9 | #import "APPActionItemView.h"
10 |
11 | @interface APPActionItemSubview : NSView
12 | @property (assign) BOOL selected;
13 | @end
14 |
15 | @implementation APPActionItemSubview
16 |
17 | - (void)drawRect:(NSRect)dirtyRect {
18 | if (self.selected) {
19 | [[NSColor selectedTextBackgroundColor] set];
20 | NSRectFill([self bounds]);
21 | }
22 | [super drawRect:dirtyRect];
23 | }
24 |
25 | @end
26 |
27 | #pragma mark - APPActionItemView
28 |
29 | @implementation APPActionItemView
30 |
31 | - (void)setHighlightState:(NSCollectionViewItemHighlightState)highlightState_ {
32 | [super setHighlightState:highlightState_];
33 | BOOL selected_ =
34 | (highlightState_ == NSCollectionViewItemHighlightAsDropTarget ||
35 | highlightState_ == NSCollectionViewItemHighlightForSelection);
36 | [(APPActionItemSubview*)[self view] setSelected:selected_];
37 | [(APPActionItemSubview*)[self view] setNeedsDisplay:YES];
38 | }
39 |
40 | - (NSCollectionViewItemHighlightState) highlightState {
41 | return [super highlightState];
42 | }
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/BranchTestHost/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | Copyright © 2020 Branch. All rights reserved.
27 | NSMainStoryboardFile
28 | Main
29 | NSPrincipalClass
30 | NSApplication
31 | NSSupportsAutomaticTermination
32 |
33 | NSSupportsSuddenTermination
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestBedUITest.h:
--------------------------------------------------------------------------------
1 | //
2 | // TestBedUITest.h
3 | // TestBed-macOS
4 | //
5 | // Created by Nidhi on 11/3/20.
6 | // Copyright © 2020 Branch. All rights reserved.
7 | //
8 |
9 | #ifndef TestBedUITest_h
10 | #define TestBedUITest_h
11 |
12 | #import
13 |
14 | #define TRACKING_STATE_UNKNOWN -1
15 | #define TRACKING_ENABLED 0
16 | #define TRACKING_DISABLED 1
17 |
18 | @interface TestBedUITest : XCTestCase
19 |
20 | @property BOOL appLaunched;
21 | @property NSInteger trackingState;
22 |
23 | - (XCTWaiterResult) launchAppAndWaitForSessionStart;
24 | - (NSString *) serverRequestString;
25 | - (NSString *) serverResponseString;
26 | - (void) setIdentity;
27 | - (void) logOut;
28 | - (NSString *) createShortLink;
29 | - (void) openLastLink;
30 | - (NSString *) getErrorString;
31 | - (void) logEvent:(NSString *)eventName;
32 | - (void) logAllEvents;
33 | - (NSString *) dataTextViewString;
34 | -(void) enableTracking;
35 | -(void) disableTracking;
36 | -(void) terminateTestBed;
37 | -(NSString *) webPageURLWithRedirection:(BOOL)enabled;
38 | - (void) validateDeepLinkDataForRedirectionEnabled:(bool)enabled;
39 | - (void) takeScreenShot;
40 | @end
41 |
42 | #endif /* TestBedUITest_h */
43 |
44 | // Adding this message for testing integration on commit from remote machine.
45 |
--------------------------------------------------------------------------------
/BranchTests/BNCPersistence.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCPersistenceTest.m
3 | @package BranchTests
4 | @brief Tests for BNCPersistence.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BNCPersistence.h"
13 |
14 | @interface BNCPersistenceTest : BNCTestCase
15 | @end
16 |
17 | @implementation BNCPersistenceTest
18 |
19 | - (void) testBranchDirectory {
20 | NSURL* url = BNCURLForBranchDataDirectory();
21 | XCTAssertNotNil(url);
22 | }
23 |
24 | - (void) testSaveLoadRemove {
25 | BNCPersistence*persistence = [[BNCPersistence alloc] initWithAppGroup:@"io.branch.sdk.unit.tests"];
26 | [persistence removeDataNamed:@"io.branch.sdk.test"];
27 |
28 | NSString*s = @"Howdy!";
29 | NSData*sd = [s dataUsingEncoding:NSUTF8StringEncoding];
30 | NSError*error = [persistence saveDataNamed:@"io.branch.sdk.test" data:sd];
31 | XCTAssertNil(error);
32 |
33 | NSData*td = [persistence loadDataNamed:@"io.branch.sdk.test"];
34 | XCTAssertEqualObjects(sd, td);
35 |
36 | error = [persistence removeDataNamed:@"io.branch.sdk.test"];
37 | XCTAssertNil(error);
38 |
39 | td = [persistence loadDataNamed:@"io.branch.sdk.test"];
40 | XCTAssertNil(td);
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Branch/BNCLocalization.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCLocalization.h
3 | @package Branch
4 | @brief Branch string localizations.
5 |
6 | @author Parth Kalavadia
7 | @date July 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | /**
16 | Since the Branch SDK can be shipped as a static library, it can't use the standard Apple string
17 | localization mechanism.
18 |
19 | Use this class to localize the few user-facing string resources the Branch SDK has.
20 | */
21 | @interface BNCLocalization : NSObject
22 |
23 | + (instancetype) shared;
24 | + (NSString*) applicationLanguage;
25 | + (NSDictionary*) languageDictionaries;
26 | - (NSString*) localizeString:(NSString*)string;
27 |
28 | /// Set to an empty string or nil to reset the current language.
29 | @property (copy, atomic) NSString* currentLanguage;
30 | @property (strong, atomic, readonly) NSDictionary *currentLanguageDictionary;
31 | @end
32 |
33 | #pragma mark Convenience Functions
34 |
35 | static inline NSString* BNCLocalizedString(NSString*const string) {
36 | return [[BNCLocalization shared] localizeString:string];
37 | }
38 |
39 | extern NSString* BNCLocalizedFormattedString(NSString*const format, ...) NS_FORMAT_FUNCTION(1,2);
40 |
41 | NS_ASSUME_NONNULL_END
42 |
--------------------------------------------------------------------------------
/BranchTests/BNCNetworkInformation.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCNetworkInformation.Test.m
3 | @package BranchTests
4 | @brief Tests for BNCNetworkInformation.
5 |
6 | @author Edward Smith
7 | @date August 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BNCNetworkInformation.h"
13 |
14 | @interface BNCNetworkInformationTest : BNCTestCase
15 | @end
16 |
17 | @implementation BNCNetworkInformationTest
18 |
19 | - (void)testAreaEntries {
20 | NSArray*entries = [BNCNetworkInformation areaEntries];
21 | XCTAssertGreaterThan(entries.count, 0);
22 | NSLog(@"%@", entries);
23 | }
24 |
25 | - (void)testCurrentInterfaces {
26 | NSArray*entries = [BNCNetworkInformation currentInterfaces];
27 | XCTAssertGreaterThan(entries.count, 0);
28 | NSLog(@"%@", entries);
29 | }
30 |
31 | - (void)testLocal {
32 | BNCNetworkInformation*entry = [BNCNetworkInformation local];
33 | XCTAssertGreaterThan(entry.interface.length, 0);
34 | XCTAssertGreaterThan(entry.address.length, 0);
35 | XCTAssertGreaterThan(entry.displayAddress.length, 0);
36 | XCTAssertGreaterThan(entry.inetAddress.length, 0);
37 | XCTAssertGreaterThan(entry.displayInetAddress.length, 0);
38 | XCTAssertGreaterThan(entry.inetAddressType, 0);
39 | NSLog(@"%@", entry);
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestPlan.xctestplan:
--------------------------------------------------------------------------------
1 | {
2 | "configurations" : [
3 | {
4 | "id" : "733BCF4B-C794-434C-9A91-D0889364C340",
5 | "name" : "Configuration 1",
6 | "options" : {
7 |
8 | }
9 | }
10 | ],
11 | "defaultOptions" : {
12 |
13 | },
14 | "testTargets" : [
15 | {
16 | "enabled" : false,
17 | "target" : {
18 | "containerPath" : "container:..\/..\/Branch.xcodeproj",
19 | "identifier" : "5F78ED8E249C317400E313B9",
20 | "name" : "BranchTests"
21 | }
22 | },
23 | {
24 | "skippedTests" : [
25 | "BranchSDKUITestCase",
26 | "OpenURL_macOSUITests",
27 | "SafariOpenLink",
28 | "SafariOpenLinkUITests",
29 | "TestBedUIChromeTest",
30 | "TestBedUIDeepLinkDataTest\/testDeepLink",
31 | "TestBedUIRaceCondTest\/testChromeAllowAppLaunch",
32 | "TestBedUIRaceCondTest\/testChromeCancelAppLaunch",
33 | "TestBedUISafariTest\/test1OpenURLInSafariInNewTab",
34 | "TestBedUISafariTest\/testOpenURLInSafariInNewWindow",
35 | "TestBedUISafariTest\/testOpenURLInSafariInPrivateWindow"
36 | ],
37 | "target" : {
38 | "containerPath" : "container:TestBed-macOS.xcodeproj",
39 | "identifier" : "0310053A253A4BE500E135E0",
40 | "name" : "TestBed-macOSUITests"
41 | }
42 | }
43 | ],
44 | "version" : 1
45 | }
46 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleURLTypes
22 |
23 |
24 | CFBundleTypeRole
25 | Editor
26 | CFBundleURLSchemes
27 |
28 | testDeepLinking-Mac
29 |
30 |
31 |
32 | CFBundleVersion
33 | 1
34 | LSMinimumSystemVersion
35 | $(MACOSX_DEPLOYMENT_TARGET)
36 | NSMainNibFile
37 | MainMenu
38 | NSPrincipalClass
39 | NSApplication
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Branch/BranchLinkProperties.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchLinkProperties.h
3 | @package Branch
4 | @brief Branch link properties: non-content properties that are associated with a link.
5 |
6 | @author Derrick Staten
7 | @date October 2015
8 | @copyright Copyright © 2015 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | #ifndef BranchLinkProperties_h
16 | #define BranchLinkProperties_h
17 |
18 | typedef NS_ENUM(NSInteger, BranchLinkType) {
19 | BranchLinkTypeUnlimitedUse = 0,
20 | BranchLinkTypeOneTimeUse = 1
21 | };
22 |
23 | @interface BranchLinkProperties : NSObject
24 |
25 | + (instancetype)linkPropertiesWithDictionary:(NSDictionary*)dictionary;
26 | - (NSDictionary*) dictionary;
27 |
28 | @property (nonatomic, strong) NSArray*_Nullable tags;
29 | @property (nonatomic, strong) NSString*_Nullable feature;
30 | @property (nonatomic, strong) NSString*_Nullable alias;
31 | @property (nonatomic, strong) NSString*_Nullable channel;
32 | @property (nonatomic, strong) NSString*_Nullable stage;
33 | @property (nonatomic, strong) NSString*_Nullable campaign;
34 | @property (nonatomic, assign) NSInteger matchDuration;
35 | @property (nonatomic, assign) BranchLinkType linkType;
36 | @property (nonatomic, strong, null_resettable) NSMutableDictionary* controlParams;
37 | @end
38 |
39 | #endif
40 |
41 | NS_ASSUME_NONNULL_END
42 |
--------------------------------------------------------------------------------
/Branch/BNCPersistence.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCPersistence.h
3 | @package Branch
4 | @brief Persists a smallish (< 1mb?) set of data between app runs.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | /**
16 | Returns a URL appropriate for storing persistent settings that aren't normally user visible.
17 |
18 | @discussion This URL is defined as a function so it can be called before the class system are loaded and
19 | initialized.
20 |
21 | @return Returns a file system URL.
22 | */
23 | NSURL* BNCURLForBranchDataDirectory(void);
24 |
25 | #pragma mark - BNCPersistence
26 |
27 | /**
28 | A generalized but very basic low-volume persistent data store.
29 | */
30 | @interface BNCPersistence : NSObject
31 |
32 | + (instancetype) new NS_UNAVAILABLE;
33 | - (instancetype) init NS_UNAVAILABLE;
34 |
35 | - (instancetype) initWithAppGroup:(NSString*)appGroup NS_DESIGNATED_INITIALIZER;
36 |
37 | - (NSData*_Nullable) loadDataNamed:(NSString*)name;
38 | - (NSError*_Nullable) saveDataNamed:(NSString*)name data:(NSData*)data;
39 | - (NSError*_Nullable) removeDataNamed:(NSString*)name;
40 |
41 | - (id _Nullable) unarchiveObjectNamed:(NSString*)name;
42 | - (NSError*_Nullable) archiveObject:(id)object named:(NSString*)name;
43 | @end
44 |
45 | NS_ASSUME_NONNULL_END
46 |
--------------------------------------------------------------------------------
/Branch/NSString+Branch.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file NSString+Branch.m
3 | @package Branch
4 | @brief NSString Additions
5 |
6 | @author Edward Smith
7 | @date February 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "NSString+Branch.h"
12 |
13 | __attribute__((constructor)) void BNCForceNSStringCategoryToLoad() {
14 | // Nothing here, but forces linker to load the category.
15 | }
16 |
17 | @implementation NSString (Branch)
18 |
19 | - (BOOL) bnc_isEqualToMaskedString:(NSString*_Nullable)string {
20 | // Un-comment for debugging:
21 | // NSLog(@"bnc_isEqualToMaskedString self/string:\n%@\n%@.", self, string);
22 | if (!string) return NO;
23 | if (self.length != string.length) return NO;
24 | for (NSUInteger idx = 0; idx < self.length; idx++) {
25 | unichar p = [self characterAtIndex:idx];
26 | unichar q = [string characterAtIndex:idx];
27 | if (q != '*' && p != q) return NO;
28 | }
29 | return YES;
30 | }
31 |
32 | - (NSString*_Nonnull) bnc_stringTruncatedAtNull {
33 | NSRange range = [self rangeOfString:@"\0"];
34 | if (range.location == NSNotFound)
35 | return self;
36 | range.length = range.location;
37 | range.location = 0;
38 | return [self substringWithRange:range];
39 | }
40 |
41 | - (BOOL) bnc_containsString:(NSString*_Nullable)string {
42 | return (string && [self rangeOfString:(NSString*_Nonnull)string].location != NSNotFound);
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/Scripts/deploy-preflight:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -euo pipefail
3 |
4 | # deploy-preflight - Check that the development environment is set up for deployment.
5 | #
6 | # Edward Smith, January 2017
7 |
8 |
9 | wasError=0
10 |
11 |
12 | function checkApp() {
13 | local appname="$1"
14 | local apppath=$(./scripts/whichapp "$appname" 2>&1)
15 | if (( ${#apppath} == 0 )); then
16 | echo ">>> Error: The application $appname not installed." 1>&2
17 | wasError=1
18 | fi
19 | }
20 |
21 |
22 | function checkTool() {
23 | local appname="$1"
24 | local apppath=$(which "$appname")
25 | if (( ${#apppath} == 0 )); then
26 | echo ">>> Error: The tool '$appname' is not installed." 1>&2
27 | wasError=1
28 | fi
29 | }
30 |
31 |
32 | function checkVariable() {
33 | local v=$1
34 | if [ -z ${!v+x} ]; then
35 | echo ">>> Error: Bash variable '$v' is unset." 1>&2
36 | wasError=1
37 | fi
38 | local vval=${!v}
39 | if (( ${#vval} == 0 )); then
40 | echo ">>> Error: Bash variable '$v' is empty." 1>&2
41 | wasError=1
42 | fi
43 | }
44 |
45 | # Check Xcode
46 | checkApp Xcode
47 |
48 | # Check CocoaPods
49 | checkTool pod
50 |
51 | # Check Carthage
52 | checkTool carthage
53 |
54 | # Check Github
55 | if ! git push --dry-run &> /dev/null; then
56 | echo ">>> Error: Not able to push to github." 1>&2
57 | wasError=1
58 | fi
59 |
60 | if [[ $wasError != 0 ]]; then
61 | echo ">>> Error: deploy-preflight failed." 1>&2
62 | exit 1
63 | fi
64 |
65 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestBedUIV2EventTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestBedUIV2EventTest.m
3 | // TestBed-macOSUITests
4 | //
5 | // Created by Nidhi on 11/6/20.
6 | // Copyright © 2020 Branch. All rights reserved.
7 | //
8 |
9 |
10 | #import "TestBedUITest.h"
11 | #import "TestBedUIUtils.h"
12 | #import
13 |
14 | @interface TestBedUIV2EventTest : TestBedUITest
15 |
16 | @end
17 |
18 | @implementation TestBedUIV2EventTest
19 |
20 | - (void)setUp {
21 | [super setUp];
22 | }
23 |
24 | - (void)tearDown {
25 | [super tearDown];
26 | }
27 |
28 | - (void)testSendV2Events {
29 |
30 | XCTWaiterResult result = [self launchAppAndWaitForSessionStart];
31 |
32 | if (result == XCTWaiterResultCompleted) {
33 |
34 | if (self.trackingState == TRACKING_DISABLED) {
35 | [self enableTracking];
36 | }
37 |
38 | NSArray *events = [BranchEvent standardEvents];
39 |
40 | for (NSString *eventName in events) {
41 |
42 | [self logEvent:eventName];
43 | XCTAssertTrue([[self serverRequestString] containsString:@"/v2/event/standard"]);
44 | XCTAssertTrue([[self getErrorString] isEqualToString:@"< None >"]);
45 | }
46 |
47 | [self logEvent:@"Custom Event"];
48 | XCTAssertTrue([[self serverRequestString] containsString:@"/v2/event/custom"]);
49 | XCTAssertTrue([[self getErrorString] isEqualToString:@"< None >"]);
50 |
51 | } else {
52 | XCTFail("App Launch / Session Start Failed.");
53 | }
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/Branch/BNCURLBlackList.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCURLBlackList.h
3 | @package Branch
4 | @brief Manages a list of sensitive URLs such as login data that should not be handled by Branch.
5 |
6 | @author Edward Smith
7 | @date February 14, 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 | @class Branch;
13 |
14 | NS_ASSUME_NONNULL_BEGIN
15 |
16 | // TODO: rename this class
17 | @interface BNCURLBlackList : NSObject
18 |
19 | - (instancetype) initWithBlackList:(NSArray*)blacklist_ version:(NSInteger)version_
20 | NS_DESIGNATED_INITIALIZER;
21 |
22 | /**
23 | @brief Checks if a given URL should be ignored (blacklisted).
24 |
25 | @param url The URL to be checked.
26 | @return Returns true if the provided URL should be ignored.
27 | */
28 | - (BOOL) isBlackListedURL:(NSURL*_Nullable)url;
29 |
30 | /**
31 | @brief Returns the pattern that matches a URL, if any.
32 |
33 | @param url The URL to be checked.
34 | @return Returns the pattern matching the URL or `nil` if no patterns match.
35 | */
36 | - (NSString*_Nullable) blackListPatternMatchingURL:(NSURL*_Nullable)url;
37 |
38 | /// Refreshes the list of ignored URLs from the server.
39 | - (void) refreshBlackListFromServerWithBranch:(Branch*)branch
40 | completion:(void (^_Nullable) (BNCURLBlackList*blackList, NSError*_Nullable error))completion;
41 |
42 | @property (assign) NSInteger blackListVersion;
43 | @property (strong) NSArray*_Nullable blackList;
44 | @end
45 |
46 | NS_ASSUME_NONNULL_END
47 |
48 |
--------------------------------------------------------------------------------
/BranchMacOS.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = "BranchMacOS"
3 | spec.version = "1.5.0"
4 | spec.summary = "Create an HTTP URL for any piece of content in your MacOS app"
5 | spec.description = <<-DESC
6 | - Want the highest possible conversions on your sharing feature?
7 | - Want to measure the k-factor of your invite feature?
8 | - Want a whole referral program in 10 lines of code, with automatic user-user attribution and rewarding?
9 | - Want to pass data (deep link) from a URL across install and open?
10 | - Want custom onboarding post install?
11 |
12 | Use the Branch SDK (branch.io) to create and power the links that point back to your apps for all of these things and more. Branch makes it incredibly simple to create powerful deep links that can pass data across app install and open while handling all edge cases (using on desktop vs. mobile vs. already having the app installed, etc). Best of all, it's really simple to start using the links for your own app: only 2 lines of code to register the deep link router and one more line of code to create the links with custom data.
13 | DESC
14 | spec.homepage = "https://help.branch.io/developers-hub/docs/mac-os-sdk-overview"
15 | spec.license = "MIT"
16 | spec.author = { "Branch" => "support@branch.io" }
17 | spec.source = { git: "https://github.com/BranchMetrics/mac-branch-deep-linking.git", tag: spec.version.to_s }
18 | spec.osx.deployment_target = "10.15"
19 | spec.source_files = "Branch/*.{h,m}"
20 | spec.frameworks = "WebKit" , "AdSupport"
21 | spec.header_dir = 'Branch'
22 | end
23 |
--------------------------------------------------------------------------------
/Branch/BNCQRCodeCache.m:
--------------------------------------------------------------------------------
1 | //
2 | // BNCQRCodeCache.m
3 | // BranchMacOS
4 | //
5 | // Created by Nipun Singh on 5/24/22.
6 | // Copyright © 2022 Branch, Inc. All rights reserved.
7 | //
8 |
9 | #import "BNCQRCodeCache.h"
10 |
11 | @interface BNCQRCodeCache()
12 | @property (nonatomic, strong) NSMutableDictionary *cache;
13 | @end
14 |
15 | @implementation BNCQRCodeCache
16 |
17 | //Can only hold one QR code in cache. Just used to debounce.
18 | + (BNCQRCodeCache *) sharedInstance {
19 | static BNCQRCodeCache *singleton;
20 | static dispatch_once_t onceToken;
21 | dispatch_once(&onceToken, ^{
22 | singleton = [BNCQRCodeCache new];
23 | });
24 | return singleton;
25 | }
26 |
27 | - (instancetype)init {
28 | if ((self = [super init])) {
29 | self.cache = [[NSMutableDictionary alloc] init];
30 | }
31 | return self;
32 | }
33 |
34 | - (void)addQRCodeToCache:(NSData *)qrCodeData withParams:(NSMutableDictionary *)parameters {
35 | @synchronized (self) {
36 | [self.cache removeAllObjects];
37 | NSMutableDictionary *tempParams = [parameters mutableCopy];
38 | [tempParams[@"data"] removeObjectForKey:@"$creation_timestamp"];
39 | self.cache[tempParams] = qrCodeData;
40 | }
41 | }
42 |
43 | - (NSData *)checkQRCodeCache:(NSMutableDictionary *)parameters {
44 | NSData *qrCode;
45 | @synchronized (self) {
46 | NSMutableDictionary *tempParams = [parameters mutableCopy];
47 | [tempParams[@"data"] removeObjectForKey:@"$creation_timestamp"];
48 | qrCode = self.cache[tempParams];
49 | }
50 | return qrCode;
51 | }
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "AppIcon-16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "AppIcon-16@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "AppIcon-32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "AppIcon-32@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "AppIcon-128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "AppIcon-128@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "AppIcon-256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "AppIcon-256@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "AppIcon-512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "AppIcon-512@2x.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinkingUITests/TestDeepLinkingUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestDeepLinkingUITests.m
3 | // TestDeepLinkingUITests
4 | //
5 | // Created by Nidhi on 2/3/21.
6 | //
7 |
8 | #import
9 |
10 | @interface TestDeepLinkingUITests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation TestDeepLinkingUITests
15 |
16 | - (void)setUp {
17 | // Put setup code here. This method is called before the invocation of each test method in the class.
18 |
19 | // In UI tests it is usually best to stop immediately when a failure occurs.
20 | self.continueAfterFailure = NO;
21 |
22 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
23 | }
24 |
25 | - (void)tearDown {
26 | // Put teardown code here. This method is called after the invocation of each test method in the class.
27 | }
28 |
29 | - (void)testExample {
30 | // UI tests must launch the application that they test.
31 | XCUIApplication *app = [[XCUIApplication alloc] init];
32 | [app launch];
33 |
34 | // Use recording to get started writing UI tests.
35 | // Use XCTAssert and related functions to verify your tests produce the correct results.
36 | }
37 |
38 | - (void)testLaunchPerformance {
39 | if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
40 | // This measures how long it takes to launch your application.
41 | [self measureWithMetrics:@[[[XCTApplicationLaunchMetric alloc] init]] block:^{
42 | [[[XCUIApplication alloc] init] launch];
43 | }];
44 | }
45 | }
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/BranchTests/BNCTestCase.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCTestCase.h
3 | @package BranchTests
4 | @brief The Branch testing framework super class.
5 |
6 | @author Edward Smith
7 | @date April 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import
12 | #import "NSString+Branch.h"
13 | #import "BNCThreads.h"
14 | #import "BranchMainClass+Private.h"
15 | #import "BNCTestNetworkService.h"
16 | #import "BNCDevice.h"
17 | #import "BranchMainClass.h"
18 |
19 | FOUNDATION_EXPORT NSString*_Nonnull const BNCTestBranchKey;
20 |
21 | #define BNCTAssertEqualMaskedString(string, mask) { \
22 | if ((id)string != nil && (id)mask != nil && [string bnc_isEqualToMaskedString:mask]) { \
23 | } else { \
24 | XCTAssertEqualObjects(string, mask); \
25 | } \
26 | }
27 |
28 | NS_ASSUME_NONNULL_BEGIN
29 |
30 | extern BOOL BNCTestStringMatchesRegex(NSString *string, NSString *regex);
31 |
32 | #define XCTAssertStringMatchesRegex(string, regex) \
33 | XCTAssertTrue(BNCTestStringMatchesRegex(string, regex))
34 |
35 | @interface BNCTestCase : XCTestCase
36 |
37 | - (void)safelyFulfillExpectation:(XCTestExpectation *)expectation;
38 | - (void)awaitExpectations;
39 | - (void)resetExpectations;
40 | //- (id)stringMatchingPattern:(NSString *)pattern;
41 |
42 | // Load Resources from the test bundle:
43 |
44 | - (NSString*_Nullable)stringFromBundleWithKey:(NSString*)key;
45 | - (NSString*_Nullable)stringFromBundleJSONWithKey:(NSString *)key;
46 | - (NSMutableDictionary*_Nullable)mutableDictionaryFromBundleJSONWithKey:(NSString*)key;
47 |
48 | - (BOOL) testDeviceSupportsIDFA;
49 | + (BOOL) breakpointsAreEnabledInTests;
50 | @end
51 |
52 | NS_ASSUME_NONNULL_END
53 |
--------------------------------------------------------------------------------
/Branch/BranchSession.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchSession.h
3 | @package Branch
4 | @brief Attributes of the current Branch session.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 | #import "BranchLinkProperties.h"
13 | #import "BranchUniversalObject.h"
14 |
15 | NS_ASSUME_NONNULL_BEGIN
16 |
17 |
18 | #ifndef BranchSession_h
19 | #define BranchSession_h
20 | /**
21 | Branch session parameters.
22 | */
23 | @interface BranchSession : NSObject
24 |
25 | + (instancetype) sessionWithDictionary:(NSDictionary*)dictionary;
26 |
27 | @property (nonatomic, strong) NSString*_Nullable sessionID;
28 | @property (nonatomic, assign) BOOL isFirstSession;
29 | @property (nonatomic, assign) BOOL isBranchURL;
30 | @property (nonatomic, assign, readonly) BOOL matchGuaranteed;
31 | @property (nonatomic, strong, readonly) NSDate* clickTimestamp;
32 | @property (nonatomic, strong) NSURL*_Nullable referringURL;
33 | @property (nonatomic, strong) NSString*_Nullable deviceFingerprintID;
34 | @property (nonatomic, strong) NSString*_Nullable randomizedDeviceToken;
35 | @property (nonatomic, strong) NSString*_Nullable identityID;
36 | @property (nonatomic, strong) NSString*_Nullable randomizedBundleToken;
37 | @property (nonatomic, strong) NSString*_Nullable userIdentityForDeveloper;
38 | @property (nonatomic, strong) NSString*_Nullable linkCreationURL;
39 | @property (nonatomic, strong) BranchUniversalObject*_Nullable linkContent;
40 | @property (nonatomic, strong) BranchLinkProperties*_Nullable linkProperties;
41 | @property (nonatomic, strong) NSDictionary*_Nullable data;
42 | @end
43 |
44 | #endif
45 |
46 | NS_ASSUME_NONNULL_END
47 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0.1
21 | CFBundleURLTypes
22 |
23 |
24 | CFBundleTypeRole
25 | Editor
26 | CFBundleURLSchemes
27 |
28 | testbed-mac
29 |
30 |
31 |
32 | CFBundleVersion
33 | 5
34 | LSApplicationCategoryType
35 | public.app-category.developer-tools
36 | LSMinimumSystemVersion
37 | $(MACOSX_DEPLOYMENT_TARGET)
38 | LSMultipleInstancesProhibited
39 |
40 | NSAppTransportSecurity
41 |
42 | NSAllowsArbitraryLoads
43 |
44 |
45 | NSHumanReadableCopyright
46 | Copyright © 2018 Branch. All rights reserved.
47 | NSMainNibFile
48 | MainMenu
49 | NSPrincipalClass
50 | NSApplication
51 | NSRequiresAquaSystemAppearance
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/BranchTests/BNCTestNetworkService.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCTestNetworkService.Test.m
3 | @package BranchTests
4 | @brief Test the BNCTestNetworkService.
5 |
6 | @author Edward Smith
7 | @date June 6, 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestNetworkService.h"
12 | #import "BNCTestCase.h"
13 | #import "Branch.h"
14 |
15 | @interface BNCTestNetworkServiceTest : BNCTestCase
16 | @end
17 |
18 | @implementation BNCTestNetworkServiceTest
19 |
20 | - (void) testTheTestService {
21 | BranchConfiguration*config = [[BranchConfiguration alloc] initWithKey:@"key_live_12345"];
22 | config.networkServiceClass = [BNCTestNetworkService class];
23 | Branch*branch = [[Branch alloc] init];
24 | [branch startWithConfiguration:config];
25 |
26 | XCTestExpectation*requestExpectation = [self expectationWithDescription:@"testTheTestService-1"];
27 | BNCTestNetworkService.requestHandler = ^ id (NSMutableURLRequest*request) {
28 | XCTAssertEqualObjects(request.HTTPMethod, @"POST");
29 | XCTAssertEqualObjects(request.URL.path, @"/v1/install");
30 | NSMutableDictionary*truthDictionary = [self mutableDictionaryFromBundleJSONWithKey:@"BranchInstallRequestMac"];
31 | NSMutableDictionary*requestDictionary = [BNCTestNetworkService mutableDictionaryFromRequest:request];
32 | XCTAssertNotNil(truthDictionary);
33 | XCTAssertNotNil(requestDictionary);
34 |
35 | [requestExpectation fulfill];
36 | NSString*responseString = [self stringFromBundleJSONWithKey:@"BranchOpenResponseMac"];
37 | return [BNCTestNetworkService operationWithRequest:request response:responseString];
38 | };
39 |
40 | [self waitForExpectationsWithTimeout:5.0 handler:nil];
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | # Mac
6 | .DS_Store
7 | .LSOverride
8 |
9 | # merge-repo commit/discard file
10 | merge-repo-commit
11 |
12 | ## Build generated
13 | [Bb]uild/
14 | DerivedData/
15 |
16 | ## Various settings
17 | *.pbxuser
18 | !default.pbxuser
19 | *.mode1v3
20 | !default.mode1v3
21 | *.mode2v3
22 | !default.mode2v3
23 | *.perspectivev3
24 | !default.perspectivev3
25 | xcuserdata/
26 |
27 | ## Other
28 | *.moved-aside
29 | *.xccheckout
30 | *.xcscmblueprint
31 |
32 | ## Obj-C/Swift specific
33 | *.hmap
34 | *.ipa
35 | *.dSYM.zip
36 | *.dSYM
37 |
38 | # CocoaPods
39 | #
40 | # We recommend against adding the Pods directory to your .gitignore. However
41 | # you should judge for yourself, the pros and cons are mentioned at:
42 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
43 | #
44 | Pods/
45 |
46 | # Carthage
47 | #
48 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
49 | # Carthage/Checkouts
50 |
51 | Carthage/Build
52 |
53 | # fastlane
54 | #
55 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
56 | # screenshots whenever they are needed.
57 | # For more information about the recommended setup visit:
58 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
59 |
60 | fastlane/report.xml
61 | fastlane/Preview.html
62 | fastlane/screenshots
63 | fastlane/test_output
64 |
65 | # Code Injection
66 | #
67 | # After new code Injection tools there's a generated folder /iOSInjectionProject
68 | # https://github.com/johnno1962/injectionforxcode
69 |
70 | iOSInjectionProject/
71 |
72 | # ignore release build product. this is attached to the github release page
73 | Branch.zip
74 |
--------------------------------------------------------------------------------
/Branch/BNCNetworkAPIService.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCNetworkAPIService.h
3 | @package Branch
4 | @brief Branch API network service interface.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 | #import "BranchSession.h"
13 | #import "BranchNetworkServiceProtocol.h"
14 | @class BranchConfiguration;
15 |
16 | NS_ASSUME_NONNULL_BEGIN
17 |
18 | #pragma mark BNCNetworkAPIOperation
19 |
20 | @interface BNCNetworkAPIOperation : NSOperation
21 | @property (atomic, strong) id operation;
22 | @property (atomic, strong) NSDate*_Nullable startDate;
23 | @property (atomic, strong) NSDate*_Nullable timeoutDate;
24 | @property (atomic, strong) NSError*_Nullable error;
25 | @property (atomic, strong) BranchSession*_Nullable session;
26 | @end
27 |
28 | #pragma mark - BNCNetworkAPIService
29 |
30 | @interface BNCNetworkAPIService : NSObject
31 | - (instancetype) initWithConfiguration:(BranchConfiguration*)configuration;
32 |
33 | - (void) appendV1APIParametersWithDictionary:(NSMutableDictionary*)dictionary;
34 | - (void) appendV2APIParametersWithDictionary:(NSMutableDictionary*)dictionary;
35 |
36 | /**
37 | @param serviceName The Branch end point name, like "v2/event" or "v1/open".
38 | @param dictionary The dictionary for the JSON post content.
39 | @param completion The completion block that receives the response data.
40 | */
41 | - (void) postOperationForAPIServiceName:(NSString*)serviceName
42 | dictionary:(NSMutableDictionary*)dictionary
43 | completion:(void (^_Nullable)(BNCNetworkAPIOperation*operation))completion;
44 |
45 | - (void) clearNetworkQueue;
46 | @property (atomic, assign, getter=queueIsPaused) BOOL queuePaused;
47 | @property (atomic, assign, readonly) NSInteger queueDepth;
48 | @end
49 |
50 | NS_ASSUME_NONNULL_END
51 |
--------------------------------------------------------------------------------
/BranchTests/BranchUserTrackingDisabled.m:
--------------------------------------------------------------------------------
1 | //
2 | /**
3 | @file BranchUserTrackingDisabled.m
4 | @package BranchTests
5 | @brief Tests creation of short link when tracking is disabled.
6 |
7 | @author Nidhi Dixit
8 | @date 2020
9 | @copyright Copyright © 2020 Branch. All rights reserved.
10 | */
11 |
12 | #import
13 | #import "BNCTestCase.h"
14 | #import "BranchError.h"
15 | #import "BNCLog.h"
16 |
17 | @interface BranchUserTrackingDisabled : XCTestCase
18 | @property (strong) Branch *branch;
19 | @end
20 |
21 | @implementation BranchUserTrackingDisabled
22 |
23 | - (void)setUp {
24 | if (!self.branch) {
25 | self.branch = [[Branch alloc] init];
26 | [self.branch startWithConfiguration:[[BranchConfiguration alloc] initWithKey:BNCTestBranchKey]];
27 | self.branch.userTrackingDisabled = YES;
28 | }
29 | }
30 |
31 | - (void)tearDown {
32 | if (self.branch)
33 | self.branch.userTrackingDisabled = NO;
34 | }
35 |
36 | - (void)testShortLink {
37 |
38 | BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:@"id-123"];
39 | buo.title = @"Test link";
40 | buo.canonicalUrl = @"https://branch.io/docs/unit-tests";
41 | BranchLinkProperties *lp = [[BranchLinkProperties alloc] init];
42 | lp.channel = @"UnitTests";
43 | XCTestExpectation *expectation = [self expectationWithDescription:@"testShortLinks"];
44 | [self.branch branchShortLinkWithContent:buo linkProperties:lp completion:
45 | ^ (NSURL * _Nullable shortURL, NSError * _Nullable error) {
46 | XCTAssertNil(error);
47 | XCTAssertNotNil(shortURL);
48 | XCTAssertTrue([shortURL.absoluteString hasPrefix:@"https://testbed-mac.app.link/"]);
49 | [expectation fulfill];
50 | }];
51 | [self waitForExpectationsWithTimeout:5.0 handler:nil];
52 |
53 |
54 | }
55 |
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/BranchTests/BNCTestNetworkService.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCTestNetworkService.h
3 | @package BranchTests
4 | @brief A class for mocking network service calls.
5 |
6 | @author Edward Smith
7 | @date June 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import
12 | #import "BranchNetworkServiceProtocol.h"
13 | #import "BNCNetworkAPIService.h"
14 |
15 | NS_ASSUME_NONNULL_BEGIN
16 |
17 | #pragma mark BNCTestNetworkOperation
18 |
19 | @interface BNCTestNetworkOperation : NSObject
20 | @property (strong) NSMutableURLRequest* request;
21 | @property (assign) NSInteger HTTPStatusCode;
22 | @property (strong) NSError*_Nullable error;
23 | //@property (strong) NSDate*_Nullable startDate;
24 | //@property (strong) NSDate*_Nullable timeoutDate;
25 | @property (strong) NSData*_Nullable responseData;
26 | //@property (strong) NSDictionary*userInfo;
27 | - (void) start;
28 | - (void) cancel;
29 | @end
30 |
31 | #pragma mark - BNCTestNetworkService
32 |
33 | @interface BNCTestNetworkService : NSObject
34 |
35 | - (id) networkOperationWithURLRequest:(NSMutableURLRequest*)request
36 | completion:(void (^)(idoperation))completion;
37 |
38 | //@property (atomic, strong) NSDictionary*_Nullable userInfo;
39 |
40 | // Properties and methods for mocking tests:
41 |
42 | @property (atomic, class, copy) id(^_Nullable requestHandler)(NSMutableURLRequest*request);
43 |
44 | + (NSMutableDictionary*_Nullable) mutableDictionaryFromRequest:(NSURLRequest*)request;
45 |
46 | + (id) operationWithRequest:(NSMutableURLRequest*)request
47 | response:(NSString*_Nullable)responseString;
48 | @end
49 |
50 | NS_ASSUME_NONNULL_END
51 |
52 |
--------------------------------------------------------------------------------
/BranchTests/NSData+Branch.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file NSData+Branch.Test.m
3 | @package BranchTests
4 | @brief Tests for the NSData+Branch category.
5 |
6 | @author Edward Smith
7 | @date June 10, 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "NSData+Branch.h"
13 |
14 | @interface NSDataBranchTest : BNCTestCase
15 | @end
16 |
17 | @implementation NSDataBranchTest
18 |
19 | - (void) testHexDecode {
20 | char bytes[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
21 | NSData*truthData = [NSData dataWithBytes:bytes length:8];
22 | NSData*data = [NSData bnc_dataWithHexString:@"0123456789abcdef"];
23 | XCTAssertEqualObjects(truthData, data);
24 |
25 | data = [NSData bnc_dataWithHexString:@"0123456789ABCDEF"];
26 | XCTAssertEqualObjects(truthData, data);
27 | }
28 |
29 | - (void) testHexDecodeOddBytes {
30 | char bytes[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe0 };
31 | NSData*truthData = [NSData dataWithBytes:bytes length:8];
32 | NSData*data = [NSData bnc_dataWithHexString:@"0123456789abcde"];
33 | XCTAssertEqualObjects(truthData, data);
34 | }
35 |
36 | - (void) testHexDecodeTricky {
37 | char bytes[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
38 | NSData*truthData = [NSData dataWithBytes:bytes length:8];
39 |
40 | NSData*data = [NSData bnc_dataWithHexString:@""];
41 | XCTAssertTrue(data != nil && data.length == 0);
42 |
43 | data = [NSData bnc_dataWithHexString:@" XXX 012345678 9ab cde\nf"];
44 | XCTAssertEqualObjects(truthData, data);
45 | }
46 |
47 | - (void) testHighLowBytes {
48 | char bytes[] = { 0x00, 0x01, 0x7f, 0x80, 0xff };
49 | NSData*truthData = [NSData dataWithBytes:bytes length:5];
50 | NSData*data = [NSData bnc_dataWithHexString:@"0001 7f80 ff"];
51 | XCTAssertEqualObjects(truthData, data);
52 | }
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/BranchTests/BranchMutableDictionary.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchMutableDictionary.Test.m
3 | @package BranchTests
4 | @brief BranchMutableDictionary tests.
5 |
6 | @author Edward Smith
7 | @date July 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BranchMutableDictionary.h"
13 |
14 | @interface BranchMutableDictionaryTest : BNCTestCase
15 | @end
16 |
17 | @implementation BranchMutableDictionaryTest
18 |
19 | - (void)testDictionary {
20 | NSDictionary*truth = @{
21 | @"key1": @"value1",
22 | @"key2": @"value2",
23 | @"key3": @"value3"
24 | };
25 |
26 | BranchMutableDictionary *d = [[BranchMutableDictionary alloc] init];
27 | d[@"key1"] = @"value1";
28 | d[@"key2"] = @"value2";
29 | XCTAssertEqual(d.count, 2);
30 | [d setObject:@"value3" forKey:@"key3"];
31 | XCTAssertEqualObjects(d[@"key2"], @"value2");
32 | XCTAssertEqualObjects(d, truth);
33 |
34 | BranchMutableDictionary *c = [BranchMutableDictionary dictionaryWithDictionary:truth];
35 | XCTAssertTrue([c isKindOfClass:BranchMutableDictionary.class]);
36 | XCTAssertEqualObjects(c, truth);
37 |
38 | BranchMutableDictionary *e = [c copy];
39 | XCTAssertTrue([e isKindOfClass:BranchMutableDictionary.class]);
40 | XCTAssertEqualObjects(e, truth);
41 | }
42 |
43 | - (void) testCoding {
44 | NSDictionary*truth = @{
45 | @"key1": @"value1",
46 | @"key2": @"value2",
47 | @"key3": @"value3"
48 | };
49 | BranchMutableDictionary*d = [BranchMutableDictionary dictionaryWithDictionary:truth];
50 | NSData*data = [NSKeyedArchiver archivedDataWithRootObject:d];
51 | BranchMutableDictionary*e = [NSKeyedUnarchiver unarchiveObjectWithData:data];
52 | XCTAssertTrue([e isKindOfClass:BranchMutableDictionary.class]);
53 | XCTAssertEqualObjects(e, truth);
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/Branch/BNCSettings.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCSettings.h
3 | @package Branch
4 | @brief Branch SDK persistent settings.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 | #import "BranchMutableDictionary.h"
13 |
14 | NS_ASSUME_NONNULL_BEGIN
15 |
16 | @interface BNCSettings : NSObject
17 | + (instancetype) loadSettings;
18 | - (instancetype) init NS_DESIGNATED_INITIALIZER;
19 | - (void) clearAllSettings;
20 | - (void) clearUserIdentifyingInformation;
21 | - (void) setNeedsSave;
22 | - (void) save;
23 | @property (atomic, copy) void (^_Nullable settingsSavedBlock)(BNCSettings*settings, NSError*_Nullable error);
24 | @property (atomic, copy) NSString*_Nullable randomizedDeviceToken;
25 | @property (atomic, copy) NSString*_Nullable randomizedBundleToken;
26 | @property (atomic, copy) NSString*_Nullable deviceFingerprintID;
27 | @property (atomic, copy) NSString*_Nullable identityID;
28 | @property (atomic, copy) NSString*_Nullable userIdentityForDeveloper;
29 | @property (atomic, copy) NSString*_Nullable sessionID;
30 | @property (atomic, copy) NSString*_Nullable linkCreationURL;
31 | @property (atomic, assign) BOOL limitFacebookTracking;
32 | @property (atomic, assign) BOOL userTrackingDisabled;
33 |
34 | // URL Black list settings:
35 |
36 | @property (atomic, assign) NSInteger URLBlackListVersion;
37 | @property (atomic, copy) NSDate*_Nullable URLBlackListLastRefreshDate;
38 | @property (atomic, copy) NSArray*_Nullable URLBlackList;
39 |
40 | @property (atomic, strong, null_resettable)
41 | BranchMutableDictionary *requestMetadataDictionary;
42 | @property (atomic, strong, null_resettable)
43 | BranchMutableDictionary *instrumentationDictionary;
44 |
45 | @end
46 |
47 | NS_ASSUME_NONNULL_END
48 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestBedUISetIdentityTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestBedUISetIdentityTest.m
3 | // TestBed-macOSUITests
4 | //
5 | // Created by Nidhi on 11/6/20.
6 | // Copyright © 2020 Branch. All rights reserved.
7 | //
8 |
9 |
10 | #import "TestBedUITest.h"
11 | #import "TestBedUIUtils.h"
12 |
13 | @interface TestBedUISetIdentityTest : TestBedUITest
14 |
15 | @end
16 |
17 | @implementation TestBedUISetIdentityTest
18 |
19 | - (void)setUp {
20 | [super setUp];
21 | }
22 |
23 | - (void)tearDown {
24 | [super tearDown];
25 | }
26 |
27 | - (void)testSetIdentityNLogout {
28 |
29 | XCTWaiterResult result = [self launchAppAndWaitForSessionStart];
30 |
31 | if (result == XCTWaiterResultCompleted) {
32 |
33 | if (self.trackingState == TRACKING_DISABLED) {
34 | [self enableTracking];
35 | }
36 |
37 | [self logOut];
38 |
39 | [self setIdentity];
40 |
41 | XCTAssertTrue([[self serverRequestString] containsString:@"/v1/profile"]);
42 |
43 | NSDictionary *serverRequest = [TestBedUIUtils dictionaryFromString:[self serverRequestString]];
44 | XCTAssertNotNil([serverRequest valueForKey:@"randomized_bundle_token"]);
45 | XCTAssertNotNil([serverRequest valueForKey:@"identity"]);
46 |
47 | XCTAssertTrue([[self getErrorString] isEqualToString:@"< None >"]);
48 |
49 | // TODO : Check for subsequent calls to log events should include the identity specific, sent up as user_data.developer_identity
50 |
51 | // Logout
52 | [self logOut];
53 | XCTAssertTrue([[self serverRequestString] containsString:@"/v1/logout"]);
54 | XCTAssertTrue([[self getErrorString] isEqualToString:@"< None >"]);
55 |
56 | // TODO : no subsequent requests should include the developer identity value (“a_user_name”)
57 | }
58 | else {
59 | XCTFail("App Launch / Session Start Failed.");
60 | }
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/Branch/NSData+Branch.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file NSData+Branch.m
3 | @package Branch
4 | @brief NSData additions.
5 |
6 | @author Edward Smith
7 | @date June 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "NSData+Branch.h"
12 |
13 | __attribute__((constructor)) void BNCForceNSDataCategoryToLoad() {
14 | // Nothing here, but forces linker to load the category.
15 | }
16 |
17 | @implementation NSData (Branch)
18 |
19 | static inline int16_t nibble(UniChar c) {
20 | if (c >= '0' && c <= '9')
21 | return c - '0';
22 | else
23 | if (c >= 'a' && c <= 'f')
24 | return c - 'a' + 10;
25 | else
26 | if (c >= 'A' && c <= 'F')
27 | return c - 'A' + 10;
28 | else
29 | return -1;
30 | }
31 |
32 | + (NSData*) bnc_dataWithHexString:(NSString*)string {
33 | uint8_t*bytes = NULL;
34 | NSData*data = nil;
35 | {
36 | NSUInteger stringLength = string.length;
37 | CFStringInlineBuffer stringBuffer;
38 | CFStringInitInlineBuffer((CFStringRef)string, &stringBuffer, CFRangeMake(0, stringLength));
39 |
40 | UniChar c;
41 | int16_t n, lastNibble = -1;
42 | NSUInteger idx = 0;
43 | uint8_t*p = bytes = malloc(stringLength/2+1);
44 | while (idx < stringLength) {
45 | c = CFStringGetCharacterFromInlineBuffer(&stringBuffer, idx++);
46 | n = nibble(c);
47 | if (n < 0) continue;
48 | if (lastNibble < 0)
49 | lastNibble = n;
50 | else {
51 | *p++ = (uint8_t) (uint16_t) (lastNibble << 4 | n);
52 | lastNibble = -1;
53 | }
54 | }
55 | if (lastNibble >= 0)
56 | *p++ = (uint8_t) (uint16_t) (lastNibble << 4 | 0);
57 | data = [NSData dataWithBytesNoCopy:bytes length:p-bytes freeWhenDone:YES];
58 | bytes = NULL;
59 | }
60 | exit:
61 | if (bytes) free(bytes);
62 | return data;
63 | }
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/Branch/BranchError.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchError.h
3 | @package Branch
4 | @brief Branch errors.
5 |
6 | @author Qinwei Gong
7 | @date November 2014
8 | @copyright Copyright © 2014 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 |
16 | #ifndef BranchError_h
17 | #define BranchError_h
18 |
19 | /// The Branch error domain.
20 | FOUNDATION_EXPORT NSString*const BNCErrorDomain;
21 |
22 | /// Branch specific error codes.
23 | typedef NS_ENUM(NSInteger, BNCErrorCode) {
24 | BNCInitError = 1000, //!< The main Branch instance wasn't initialized correctly.
25 | BNCDuplicateResourceError = 1001, //!< A requested resource, such as a short link, already exists.
26 | BNCRedeemCreditsError = 1002, //!< The credits could not be redeemed.
27 | BNCBadRequestError = 1003,
28 | BNCServerProblemError = 1004,
29 | BNCNilLogError = 1005, //!< Not used at the moment.
30 | BNCVersionError = 1006, //!< Not used at the moment.
31 | BNCNetworkServiceInterfaceError = 1007,
32 | BNCContentIdentifierError = 1008,
33 | BNCSpotlightNotAvailableError = 1009,
34 | BNCSpotlightTitleError = 1010,
35 | BNCRedeemZeroCreditsError = 1011,
36 | BNCSpotlightIdentifierError = 1012,
37 | BNCSpotlightPublicIndexError = 1013,
38 | BNCTrackingDisabledError = 1014,
39 | BNCHighestError,
40 | };
41 |
42 | /**
43 | A convenience category for creating Branch errors.
44 | */
45 | @interface NSError (Branch)
46 | + (NSError*) branchErrorWithCode:(BNCErrorCode)errorCode;
47 | + (NSError*) branchErrorWithCode:(BNCErrorCode)errorCode error:(NSError*_Nullable)error;
48 | + (NSError*) branchErrorWithCode:(BNCErrorCode)errorCode localizedMessage:(NSString*_Nullable)message;
49 | @end
50 |
51 | ///
52 | FOUNDATION_EXPORT void BNCForceNSErrorCategoryToLoad(void)
53 | __attribute__((constructor));
54 |
55 | #endif
56 |
57 | NS_ASSUME_NONNULL_END
58 |
--------------------------------------------------------------------------------
/Branch/BNCDevice.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCDevice.h
3 | @package Branch
4 | @brief Device information.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | @interface BNCDevice : NSObject
16 |
17 | + (instancetype) currentDevice;
18 | - (NSMutableDictionary*) v1dictionary;
19 | - (NSMutableDictionary*) v2dictionary;
20 |
21 | @property (atomic, copy, readonly) NSString *hardwareID;
22 | @property (atomic, copy, readonly) NSString *hardwareIDType; //!< vendor_id, idfa, or random
23 | @property (atomic, assign, readonly) BOOL deviceIsUnidentified;
24 | @property (atomic, copy, readonly) NSString *brandName;
25 | @property (atomic, copy, readonly) NSString *modelName;
26 | @property (atomic, copy, readonly) NSString *systemName;
27 | @property (atomic, copy, readonly) NSString *systemVersion;
28 | @property (atomic, copy, readonly) NSString *systemBuildVersion;
29 | @property (atomic, assign, readonly) BOOL isSimulator;
30 | @property (atomic, assign, readonly) CGSize screenSize;
31 | @property (atomic, assign, readonly) CGFloat screenDPI;
32 | @property (atomic, assign, readonly) BOOL adTrackingIsEnabled; //!< True if advertisingID is available.
33 | @property (atomic, copy, readonly) NSString*_Nullable advertisingID; //!< iOS identifierForAdvertisor.
34 | @property (atomic, copy, readonly) NSString*_Nullable vendorID; //!< iOS identifierForVendor.
35 | @property (atomic, copy, readonly) NSString*_Nullable netAddress; //!< Network card address.
36 | @property (atomic, copy, readonly) NSString *country; //!< The iso2 Country name (us, in,etc).
37 | @property (atomic, copy, readonly) NSString *language; //!< The iso2 language code (en, ml).
38 | @property (atomic, copy, readonly) NSString *localIPAddress; //!< The current local IPv4 address.
39 | @property (atomic, copy, readonly) NSArray *allLocalIPAddresses; //!< All local IP addresses.
40 |
41 | @property (atomic, copy, readonly) NSString *userAgent;
42 |
43 | @end
44 |
45 | NS_ASSUME_NONNULL_END
46 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.yml:
--------------------------------------------------------------------------------
1 | ---
2 | assignees: []
3 | body:
4 | -
5 | attributes:
6 | description: "What is the problem? A clear and concise description of what the bug is."
7 | label: "Describe the bug"
8 | placeholder: "Tell us what you see!"
9 | id: description
10 | type: textarea
11 | validations:
12 | required: true
13 | -
14 | attributes:
15 | description: "Please provide as much step-by-step detail as possible including logs, stack traces, and uncaught exceptions."
16 | label: "Steps to reproduce"
17 | value: |
18 | 1.
19 | 2.
20 | 3.
21 | id: steps
22 | type: textarea
23 | validations:
24 | required: true
25 | -
26 | attributes:
27 | description: "What did you expect to happen?"
28 | label: "Expected behavior"
29 | id: expected
30 | type: textarea
31 | validations:
32 | required: true
33 | -
34 | attributes:
35 | description: "What version of sdk are you seeing this issue on?"
36 | label: "SDK Version"
37 | placeholder: "1.4.0"
38 | id: sdk-version
39 | type: input
40 | validations:
41 | required: true
42 | -
43 | attributes:
44 | description: "What version of Xcode are you using?"
45 | label: "XCode Version"
46 | placeholder: "13.4.1"
47 | id: xcode-version
48 | type: input
49 | validations:
50 | required: true
51 | -
52 | attributes:
53 | description: "What is the version of macOS?"
54 | label: OS
55 | placeholder: "12.5.1"
56 | id: os
57 | type: input
58 | validations:
59 | required: true
60 | -
61 | attributes:
62 | description: "Anything else that might be relevant for troubleshooting this bug. Any screenshots or videos that show the issue are very helpful."
63 | label: "Additional Information/Context"
64 | id: context
65 | type: textarea
66 | validations:
67 | required: false
68 |
69 | description: "Found a bug in the Branch macOS SDK? File it here."
70 | labels:
71 | - bug
72 | - needs-triage
73 | name: "🐞 Bug report"
74 | title: "(short issue description)"
75 |
--------------------------------------------------------------------------------
/Branch/BNCThreads.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCThreads.h
3 | @package Branch
4 | @brief Utilities for working with threads, queues, and blocks.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | ///@name Blocks and Threads
16 | #pragma mark - Blocks and Threads
17 |
18 | static inline uint64_t BNCNanoSecondsFromTimeInterval(NSTimeInterval interval) {
19 | return interval * ((NSTimeInterval) NSEC_PER_SEC);
20 | }
21 |
22 | static inline dispatch_time_t BNCDispatchTimeFromSeconds(NSTimeInterval seconds) {
23 | return dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC);
24 | }
25 |
26 | static inline void BNCAfterSecondsPerformBlockOnMainThread(NSTimeInterval seconds, dispatch_block_t block) {
27 | dispatch_after(BNCDispatchTimeFromSeconds(seconds), dispatch_get_main_queue(), block);
28 | }
29 |
30 | static inline void BNCAfterSecondsPerformBlock(NSTimeInterval seconds, dispatch_block_t block) {
31 | dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0);
32 | dispatch_after(BNCDispatchTimeFromSeconds(seconds), queue, block);
33 | }
34 |
35 | static inline void BNCPerformBlockOnMainThreadAsync(dispatch_block_t block) {
36 | dispatch_async(dispatch_get_main_queue(), block);
37 | }
38 |
39 | static inline void BNCPerformBlockAsync(dispatch_block_t block) {
40 | dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0);
41 | dispatch_async(queue, block);
42 | }
43 |
44 | static inline void BNCPerformBlockOnMainThreadSync(dispatch_block_t block) {
45 | if ([NSThread isMainThread])
46 | block();
47 | else
48 | dispatch_sync(dispatch_get_main_queue(), block);
49 | }
50 |
51 | static inline void BNCSleepForTimeInterval(NSTimeInterval seconds) {
52 | double secPart = trunc(seconds);
53 | double nanoPart = trunc((seconds - secPart) * ((double)NSEC_PER_SEC));
54 | struct timespec sleepTime;
55 | sleepTime.tv_sec = (__typeof(sleepTime.tv_sec)) secPart;
56 | sleepTime.tv_nsec = (__typeof(sleepTime.tv_nsec)) nanoPart;
57 | nanosleep(&sleepTime, NULL);
58 | }
59 |
60 | NS_ASSUME_NONNULL_END
61 |
--------------------------------------------------------------------------------
/BranchTests/BNCDevice.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCDevice.Test.m
3 | @package BranchTests
4 | @brief Tests for BNCDevice.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BNCDevice.h"
13 |
14 | @interface BNCDeviceTest : BNCTestCase
15 | @end
16 |
17 | @implementation BNCDeviceTest
18 |
19 | - (void)testDevice {
20 | BNCDevice *device = [BNCDevice currentDevice];
21 | XCTAssertTrue(device.hardwareID.length > 0);
22 | XCTAssertTrue(
23 | [device.hardwareIDType isEqualToString:@"idfa"] ||
24 | [device.hardwareIDType isEqualToString:@"random"] ||
25 | [device.hardwareIDType isEqualToString:@"mac_address"]
26 | );
27 | XCTAssertFalse(device.deviceIsUnidentified);
28 | XCTAssertTrue([device.brandName isEqualToString:@"Apple"]);
29 |
30 | XCTAssertTrue([device.modelName hasPrefix:@"Mac"]);
31 | XCTAssertTrue([device.systemName isEqualToString:@"mac_OS"]);
32 | XCTAssertTrue(device.hardwareID.length > 0);
33 |
34 | XCTAssertTrue(
35 | device.systemVersion.doubleValue > 10.15 &&
36 | device.systemVersion.doubleValue <= 14
37 | );
38 | XCTAssertTrue(BNCTestStringMatchesRegex(device.systemBuildVersion, @"^[0-9A-Za-z]+$"));
39 | XCTAssertTrue(
40 | device.screenSize.height > 0 &&
41 | device.screenSize.width > 0
42 | );
43 |
44 | XCTAssertTrue(device.screenDPI >= 72.0 && device.screenDPI <= 216.0);
45 |
46 | // idfa is broken on 10.15+
47 | if ([self testDeviceSupportsIDFA]) {
48 | XCTAssertTrue(device.adTrackingIsEnabled);
49 | XCTAssertNotNil(device.advertisingID);
50 | } else {
51 | XCTAssertFalse(device.adTrackingIsEnabled);
52 | XCTAssertNil(device.advertisingID);
53 | }
54 | XCTAssertTrue([device.country isEqualToString:@"US"]);
55 | XCTAssertTrue([device.language isEqualToString:@"en"]);
56 | XCTAssertTrue(BNCTestStringMatchesRegex(device.localIPAddress, @"^\\d*\\.\\d*\\.\\d*\\.\\d*$"));
57 | }
58 |
59 | - (void)testIPAddresses {
60 | NSArray *d = [[BNCDevice currentDevice] allLocalIPAddresses];
61 | XCTAssertGreaterThan(d.count, 1);
62 | NSLog(@"IP Addresses: %@.", d);
63 | }
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/Scripts/deploy-release:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -euo pipefail
3 |
4 | # deploy-release - The release deployment master script.
5 | #
6 | # This script is written to be excessively modular so it can be debugged or restarted easily.
7 | #
8 | # Edward Smith, December 2016
9 |
10 | scriptfile="$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11 | scriptfile="${scriptfile}"/$(basename "$0")
12 | cd $(dirname "$scriptfile")/..
13 |
14 | scriptFailed=1
15 | function finish {
16 | if [ $scriptFailed -ne 0 ]; then
17 | echo ">>> Error: `basename "$scriptfile"` failed!" 1>&2
18 | exit 1
19 | fi
20 | }
21 | trap finish EXIT
22 |
23 |
24 | version=$(./scripts/version)
25 |
26 | echo ""
27 | echo "Before continuing:"
28 | echo "- Make sure that the release version number is already updated."
29 | echo "- Make sure that the ChangeLog.md has been updated, spell checked, and is coherent."
30 | echo "- Make sure that you are logged in to your Branch Google account and have write access to Google Groups."
31 | echo ""
32 | if ! ./scripts/askYN "Deploy Branch release version ${version}?"; then
33 | echo ">>> Nothing deployed." 1>&2
34 | exit 1
35 | fi
36 |
37 | # Check that deployment software is installed
38 | ./scripts/deploy-preflight
39 |
40 | # Prompt for editor input for ChangeLog.
41 | #vim +4 +star ChangeLog.md
42 | nano ChangeLog.md
43 |
44 | # Pre-release CocoaPod lint
45 | echo ">>> Linting build for release..." 1>&2
46 |
47 | # Validate the podspec
48 | pod lib lint BranchMacOS.podspec --verbose
49 |
50 | # Build the framework
51 | echo ">>> Building the framework..." 1>&2
52 | ./scripts/deploy-build-framework
53 |
54 | # Make the zip files and get the checksums
55 | echo ">>> Zipping and checksumming framework files..." 1>&2
56 | ./scripts/deploy-checksum
57 |
58 | echo '>>> The Branch SDK build is successful so far.' 1>&2
59 | if ! ./scripts/askYN "Commit and deploy Branch release version ${version}?"; then
60 | echo ">>> Nothing deployed." 1>&2
61 | exit 1
62 | fi
63 |
64 | # currently we have to manually commit and tag
65 | #echo '>>> Commit and tag...' 1>&2
66 | #./scripts/deploy-git-tag
67 |
68 | echo '>>> Pushing Branch CocoaPod...' 1>&2
69 | pod trunk push Branch.podspec
70 |
71 | # Prompts for SDK Release announcements
72 | ./scripts/deploy-announce
73 |
74 | echo ""
75 | echo "The Branch SDK has been released. Rejoice and pay tribute to Steve Jobs!"
76 | # Completed OK:
77 | scriptFailed=0
78 |
--------------------------------------------------------------------------------
/Branch/BranchQRCode.h:
--------------------------------------------------------------------------------
1 | //
2 | // BranchQRCode.h
3 | // BranchMacOS
4 | //
5 | // Created by Nipun Singh on 5/23/22.
6 | // Copyright © 2022 Branch, Inc. All rights reserved.
7 | //
8 |
9 | #import "BranchUniversalObject.h"
10 | #import "BranchLinkProperties.h"
11 | #import "BranchHeader.h"
12 |
13 | #ifndef BranchQRCode_h
14 | #define BranchQRCode_h
15 |
16 | typedef NS_ENUM(NSInteger, BranchQRCodeImageFormat){
17 | BranchQRCodeImageFormatPNG,
18 | BranchQRCodeImageFormatJPEG
19 | };
20 |
21 | @interface BranchQRCode : NSObject
22 |
23 | /// Primary color of the generated QR code itself.
24 | @property (nonatomic, copy, readwrite) NSColor * _Nullable codeColor;
25 | /// Secondary color used as the QR Code background.
26 | @property (nonatomic, copy, readwrite) NSColor * _Nullable backgroundColor;
27 | /// A URL of an image that will be added to the center of the QR code. Must be a PNG or JPEG.
28 | @property (nonatomic, copy, readwrite) NSString * _Nullable centerLogo;
29 | /// Output size of QR Code image. Min 500px. Max 2000px.
30 | @property (nonatomic, readwrite) NSNumber * _Nullable width;
31 | /// The number of pixels for the QR code's border. Min 0px. Max 20px.
32 | @property (nonatomic, readwrite) NSNumber * _Nullable margin;
33 | /// Format of the returned QR code. Can be a JPEG or PNG.
34 | @property (nonatomic, assign, readwrite) BranchQRCodeImageFormat imageFormat;
35 |
36 | /**
37 | Creates a Branch QR Code image. Returns the QR code as a CIImage.
38 |
39 | @param buo The Branch Universal Object the will be shared.
40 | @param lp The link properties that the link will have.
41 | @param completion Completion handler containing the QR code image and error.
42 |
43 | */
44 | - (void) getQRCodeAsImage:(BranchUniversalObject*_Nullable)buo
45 | linkProperties:(BranchLinkProperties*_Nullable)lp
46 | completion:(void(^_Nonnull)(CIImage * _Nullable qrCode, NSError * _Nullable error))completion;
47 |
48 | /**
49 | Creates a Branch QR Code image. Returns the QR code as NSData.
50 |
51 | @param buo The Branch Universal Object the will be shared.
52 | @param lp The link properties that the link will have.
53 | @param completion Completion handler containing the QR code image and error.
54 |
55 | */
56 | - (void) getQRCodeAsData:(BranchUniversalObject*_Nullable)buo
57 | linkProperties:(BranchLinkProperties*_Nullable)lp
58 | completion:(void(^_Nonnull)(NSData * _Nullable qrCode, NSError * _Nullable error))completion;
59 |
60 |
61 | @end
62 |
63 |
64 | #endif /* BranchQRCode_h */
65 |
--------------------------------------------------------------------------------
/BranchTests/BranchLinkProperties.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchLinkProperties.Test.m
3 | @package BranchTests
4 | @brief BranchLinkProperties tests.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BranchLinkProperties.h"
13 | #import "BNCWireFormat.h"
14 |
15 | @interface BranchLinkPropertiesTest : BNCTestCase
16 | @end
17 |
18 | @implementation BranchLinkPropertiesTest
19 |
20 | - (void) testSerializeDeserialize {
21 | NSDictionary* open = [self mutableDictionaryFromBundleJSONWithKey:@"BranchOpenResponse"];
22 | XCTAssertNotNil(open);
23 | NSDictionary*d1 = BNCDictionaryFromWireFormat(open[@"data"]);
24 | BranchLinkProperties *lp = [BranchLinkProperties linkPropertiesWithDictionary:d1];
25 | NSArray*tags = @[ @"tag1", @"tag2" ];
26 | XCTAssertEqualObjects(lp.tags, tags);
27 | XCTAssertEqualObjects(lp.feature, @"Sharing Feature");
28 | XCTAssertEqualObjects(lp.alias, nil);
29 | XCTAssertEqualObjects(lp.channel, @"Distribution Channel");
30 | XCTAssertEqualObjects(lp.stage, @"stage four");
31 | XCTAssertEqualObjects(lp.campaign, @"some campaign");
32 | XCTAssertEqual(lp.matchDuration, 0);
33 | NSDictionary*cp = @{
34 | @"$canonical_identifier": @"item/12345",
35 | @"$canonical_url": @"https://dev.branch.io/getting-started/deep-link-routing/guide/ios/",
36 | @"$content_schema": @"some type",
37 | @"$creation_timestamp": @1527379945531,
38 | @"$currency": @"$",
39 | @"$desktop_url": @"http://branch.io",
40 | @"$randomized_bundle_token": @529056271991951584,
41 | @"$ios_url":@"https://dev.branch.io/getting-started/sdk-integration-guide/guide/ios/",
42 | @"$match_duration": @12,
43 | @"$og_description": @"My Content Description",
44 | @"$og_image_url": @"http://a57.foxnews.com/images.foxnews.com/content/fox-news/science/2018/03/20/first-day-spring-arrives-5-things-to-know-about-vernal-equinox/_jcr_content/par/featured_image/media-0.img.jpg/1862/1048/1521552912093.jpg?ve=1&tl=1",
45 | @"$og_title": @"Content Title",
46 | @"$og_type": @"website",
47 | @"$one_time_use": @0,
48 | @"$price": @1000,
49 | };
50 | XCTAssertEqualObjects(lp.controlParams, cp);
51 |
52 | NSDictionary*d2 = [lp dictionary];
53 | for (NSString*key in d2.keyEnumerator) {
54 | id v1 = d1[key];
55 | id v2 = d2[key];
56 | XCTAssertEqualObjects(v1, v2);
57 | }
58 | }
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/BranchTests/BranchError.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchError.Test.m
3 | @package BranchTests
4 | @brief Branch error tests.
5 |
6 | @author Edward Smith
7 | @date August 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BranchError.h"
13 | #import "BNCLocalization.h"
14 | #import "BNCDevice.h"
15 |
16 | @interface BranchErrorTest : BNCTestCase
17 | @end
18 |
19 | @implementation BranchErrorTest
20 |
21 | - (void) testErrorBasic {
22 |
23 | NSError *error = nil;
24 | error = [NSError branchErrorWithCode:BNCInitError];
25 | XCTAssert(error.domain == BNCErrorDomain);
26 | XCTAssert(error.code == BNCInitError);
27 | XCTAssert([error.localizedDescription isEqualToString:
28 | @"The Branch user session has not been initialized."]
29 | );
30 |
31 | NSError *underlyingError =
32 | [NSError errorWithDomain:NSCocoaErrorDomain
33 | code:NSFileNoSuchFileError userInfo:nil];
34 | error = [NSError branchErrorWithCode:BNCServerProblemError error:underlyingError];
35 | XCTAssert(error.domain == BNCErrorDomain);
36 | XCTAssert(error.code == BNCServerProblemError);
37 | XCTAssert(
38 | [error.localizedDescription isEqualToString:
39 | @"Trouble reaching the Branch servers, please try again shortly."]
40 | );
41 | XCTAssert(error.userInfo[NSUnderlyingErrorKey] == underlyingError);
42 | if ([BNCDevice currentDevice].systemVersion.floatValue < 9.0) {
43 | XCTAssert([error.localizedFailureReason isEqualToString:
44 | @"The operation couldn’t be completed. (Cocoa error 4.)"]);
45 | } else {
46 | XCTAssert([error.localizedFailureReason isEqualToString:@"The file doesn’t exist."]);
47 | }
48 |
49 | NSString *message =
50 | BNCLocalizedFormattedString(
51 | @"Network operation of class '%@' does not conform to the BNCNetworkOperationProtocol.",
52 | NSStringFromClass([self class]));
53 | error = [NSError branchErrorWithCode:BNCNetworkServiceInterfaceError localizedMessage:message];
54 | XCTAssert(error.domain == BNCErrorDomain);
55 | XCTAssert(error.code == BNCNetworkServiceInterfaceError);
56 | XCTAssert([error.localizedDescription isEqualToString:
57 | @"The underlying network service does not conform to the BNCNetworkOperationProtocol."]);
58 | XCTAssert([error.localizedFailureReason isEqualToString:
59 | @"Network operation of class 'BranchErrorTest' does not conform to the BNCNetworkOperationProtocol."]);
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Branch Mac SDK Change Log
2 |
3 | ## 1.5.0 - April 30, 2024
4 | - Removed v1/profile and v1/logout requests.
5 | - Create new versions of logout() and setUserIdentity() without callbacks.
6 |
7 | ## 1.4.1 - May 9, 2023
8 |
9 | SDK-1905
10 | Fix for build issue with Xcode 14.3 and Swift 5.8
11 |
12 | INTENG-17551
13 | Added developer_identity to v2/event requests
14 |
15 | ## 1.4.0 - Aug 16, 2022
16 |
17 | SDK-1405
18 | Branch QR codes functionality added.
19 |
20 | SDK-1205
21 | Fixed Set Identity Issue.
22 |
23 | SDK-1373, SDK-1374
24 | Renamed device_fingerprint_id and identity_id to better reflect functionality. Fingerprinting was removed long ago.
25 |
26 | SDK-1346
27 | Exposed setRequestMetadata API.
28 |
29 | SDK-1530
30 | Developer id added in v1/open requests.
31 |
32 | ## v1.3.1 - Jun 2, 2021
33 |
34 | CORE-1989
35 | Add getUserIdentity to the public API
36 |
37 | CORE-1659
38 | Add INITIATE_STREAM and COMPLETE_STREAM to standard events
39 |
40 | Test coverage improvements
41 |
42 | ## v1.3.0 - Jan 28, 2021
43 |
44 | CORE-1303
45 | Improve integration options for the macOS SDK by adding support for Swift Package Manager, Carthage and Cocoapods. See the Branch docs site for more details.
46 |
47 | Improve test coverage and test automation. This may impact you if you are importing the Branch macOS SDK as source.
48 |
49 | ## v1.2.5 - Oct 8, 2020
50 | * Allow short link generation when tracking is disabled
51 |
52 | ## v1.2.4 - June 17, 2020
53 | * Remove certificate pinning
54 |
55 | ## v1.2.3 - May 13, 2020
56 | * Fix control param location in request payload
57 |
58 | ## v1.2.2 - May 7, 2020
59 | * Fix fallback when idfa is not available
60 |
61 | ## v1.2.1 - December 13, 2019
62 | * Fix crash when idfa is not available
63 |
64 | ## v1.2.0 - October 7, 2019
65 | * Add user agent
66 | * Attribution fixes
67 |
68 | ## v1.1.0 - December 6th, 2018
69 | * Added tvOS support
70 | * Added CocoaPod support
71 |
72 | ## v0.1.0-beta - *First Release - July 13, 2018*
73 |
74 | Branch is proud to release the beta version of the Branch SDK for Mac!
75 |
76 | Thank you @Sarkar, @ahmednawar, @clayjones94, @aaaronlopez and @GeneShay!
77 |
78 | We welcome your feedback, suggestions and bugs reports. You can add them in [here, in issues area here on GitHub.](https://github.com/BranchMetrics/mac-branch-deep-linking/issues)
79 |
80 | For installation and usage instructions check out the [Readme](https://github.com/BranchMetrics/mac-branch-deep-linking/blob/master/README.md) and the [documentation](https://branchmetrics.github.io/mac-branch-deep-linking/index.html).
81 |
82 | Happy linking!
83 | @E-B-Smith
84 |
--------------------------------------------------------------------------------
/Branch/BranchMutableDictionary.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchMutableDictionary.m
3 | @package Branch
4 | @brief A thread-safe mutable dictionary.
5 |
6 | @author Edward Smith
7 | @date July 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchMutableDictionary.h"
12 |
13 | @interface BranchMutableDictionary () {
14 | NSMutableDictionary *_dictionary;
15 | }
16 | @end
17 |
18 | @implementation BranchMutableDictionary
19 |
20 | - (instancetype) init {
21 | self = [super init];
22 | if (!self) return self;
23 | _dictionary = [[NSMutableDictionary alloc] init];
24 | return self;
25 | }
26 |
27 | - (instancetype) initWithCapacity:(NSUInteger)numItems {
28 | self = [super init];
29 | if (!self) return self;
30 | _dictionary = [[NSMutableDictionary alloc] initWithCapacity:numItems];
31 | return self;
32 | }
33 |
34 | - (instancetype) initWithCoder:(NSCoder *)aDecoder {
35 | self = [super init];
36 | if (!self) return self;
37 | _dictionary = [[NSMutableDictionary alloc] initWithCoder:aDecoder];
38 | return self;
39 | }
40 |
41 | - (instancetype) copyWithZone:(NSZone *)zone {
42 | return [self mutableCopyWithZone:zone];
43 | }
44 |
45 | - (instancetype) mutableCopyWithZone:(NSZone *)zone {
46 | @synchronized(self) {
47 | BranchMutableDictionary*copy = [[BranchMutableDictionary allocWithZone:zone] init];
48 | [copy setDictionary:self];
49 | return copy;
50 | }
51 | }
52 |
53 | - (NSUInteger) count {
54 | @synchronized(self) {
55 | return [_dictionary count];
56 | }
57 | }
58 |
59 | - (id)objectForKey:(id)aKey {
60 | @synchronized(self) {
61 | return (aKey) ? [_dictionary objectForKey:aKey] : nil;
62 | }
63 | }
64 |
65 | - (NSEnumerator *)keyEnumerator {
66 | @synchronized(self) {
67 | return [_dictionary keyEnumerator];
68 | }
69 | }
70 |
71 | - (void) setObject:(id)anObject forKey:(id)aKey {
72 | @synchronized(self) {
73 | if (aKey == nil) {
74 | } else
75 | if (anObject == nil)
76 | [_dictionary removeObjectForKey:aKey];
77 | else
78 | [_dictionary setObject:anObject forKey:aKey];
79 | }
80 | }
81 |
82 | - (void) removeObjectForKey:(id)aKey {
83 | @synchronized(self) {
84 | if (aKey != nil) [_dictionary removeObjectForKey:aKey];
85 | }
86 | }
87 |
88 | - (void)encodeWithCoder:(NSCoder *)aCoder {
89 | @synchronized(self) {
90 | [_dictionary encodeWithCoder:aCoder];
91 | }
92 | }
93 |
94 | - (Class) classForCoder {
95 | return self.class;
96 | }
97 |
98 | @end
99 |
--------------------------------------------------------------------------------
/Branch/BranchLinkProperties.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchLinkProperties.m
3 | @package Branch
4 | @brief Branch link properties: non-content properties that are associated with a link.
5 |
6 | @author Derrick Staten
7 | @date October 2015
8 | @copyright Copyright © 2015 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchLinkProperties.h"
12 |
13 | @implementation BranchLinkProperties
14 |
15 | - (NSMutableDictionary*)controlParams {
16 | @synchronized(self) {
17 | if (!_controlParams) _controlParams = [[NSMutableDictionary alloc] init];
18 | return _controlParams;
19 | }
20 | }
21 |
22 | + (instancetype)linkPropertiesWithDictionary:(NSDictionary *)dictionary {
23 | BranchLinkProperties *object = [[BranchLinkProperties alloc] init];
24 |
25 | #define BNCWireFormatObjectFromDictionary
26 | #include "BNCWireFormat.h"
27 |
28 | addStringArray(tags, ~tags);
29 | addString(feature, ~feature);
30 | addString(alias, ~alias);
31 | addString(channel, ~channel);
32 | addString(stage, ~stage);
33 | addString(campaign, ~campaign);
34 | addInteger(matchDuration, ~duration); // TODO: encodes as $match_duration in iOS
35 | addInteger(linkType, ~type); // Is this right?
36 |
37 | NSMutableDictionary *controlParams = [[NSMutableDictionary alloc] init];
38 | for (NSString*key in dictionary.allKeys) {
39 | if ([key hasPrefix:@"$"]) {
40 | controlParams[key] = dictionary[key];
41 | }
42 | }
43 | object.controlParams = controlParams;
44 |
45 | return object;
46 | }
47 |
48 | - (NSDictionary*) dictionary {
49 | NSMutableDictionary*dictionary = [[NSMutableDictionary alloc] init];
50 |
51 | #define BNCWireFormatDictionaryFromSelf
52 | #include "BNCWireFormat.h"
53 |
54 | addStringArray(tags, ~tags);
55 | addString(feature, ~feature);
56 | addString(alias, ~alias);
57 | addString(channel, ~channel);
58 | addString(stage, ~stage);
59 | addString(campaign, ~campaign);
60 | addInteger(matchDuration, ~duration);
61 | addInteger(linkType, ~type);
62 |
63 | //[dictionary addEntriesFromDictionary:self.controlParams];
64 |
65 | return dictionary;
66 | }
67 |
68 | - (NSString *)description {
69 | return [NSString stringWithFormat:
70 | @"BranchLinkProperties | tags: %@ \n feature: %@ \n alias: %@ \n channel: %@ \n stage: %@ \n"
71 | " campaign: %@ \n matchDuration: %lu \n controlParams: %@",
72 | self.tags, self.feature, self.alias, self.channel, self.stage, self.campaign,
73 | (long)self.matchDuration, self.controlParams];
74 | }
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/Branch.xcodeproj/xcshareddata/xcschemes/Branch-macOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
57 |
58 |
59 |
60 |
62 |
63 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/Branch.xcodeproj/xcshareddata/xcschemes/Branch-framework.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
57 |
58 |
59 |
60 |
62 |
63 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/Branch/BranchSession.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchSession.m
3 | @package Branch
4 | @brief Attributes of the current Branch session.
5 |
6 | @author Edward
7 | @date 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchSession.h"
12 | #import "BNCLog.h"
13 |
14 | @interface BranchSession ()
15 | @property (nonatomic, assign) BOOL matchGuaranteed;
16 | @property (nonatomic, strong) NSDate* clickTimestamp;
17 | @end
18 |
19 | @implementation BranchSession
20 |
21 | + (instancetype) sessionWithDictionary:(NSDictionary *)dictionary {
22 | BranchSession*object = [[BranchSession alloc] init];
23 |
24 | #define BNCWireFormatObjectFromDictionary
25 | #include "BNCWireFormat.h"
26 |
27 | addString(sessionID, session_id);
28 | addString(userIdentityForDeveloper, identity);
29 | addString(randomizedDeviceToken, randomized_device_token);
30 | addString(randomizedBundleToken, randomized_bundle_token);
31 | addString(linkCreationURL, link);
32 |
33 | NSString*dataString = dictionary[@"data"];
34 | if (!dataString) dataString = dictionary[@"referring_data"];
35 |
36 | if (dataString) {
37 | NSData*dataData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
38 | if (dataData) {
39 | NSError*error = nil;
40 | object.data = [NSJSONSerialization JSONObjectWithData:dataData options:0 error:&error];
41 | if (error) BNCLogError(@"Can't decode data: %@", error);
42 | NSDictionary*dictionary = object.data;
43 | addBoolean(isFirstSession, +is_first_session);
44 | addBoolean(isBranchURL, +clicked_branch_link);
45 | addBoolean(matchGuaranteed, +match_guaranteed);
46 | addURL(referringURL, ~referring_link);
47 | object.clickTimestamp = BNCDateFromWireFormatSeconds(dictionary[@"+click_timestamp"]);
48 | }
49 | } else {
50 | object.data = dictionary;
51 | }
52 | return object;
53 | }
54 |
55 | #include "BNCWireFormat.h"
56 |
57 | - (NSString*) description {
58 | return [NSString stringWithFormat:
59 | @"<%@ 0x%p isFirst: %@ isBranchURL: %@ sessionID: %@ referring: %@ identity: %@"
60 | " buo: %@ link: %@ items data: %@>",
61 | NSStringFromClass(self.class),
62 | (void*) self,
63 | BNCStringFromBool(self.isFirstSession),
64 | BNCStringFromBool(self.isBranchURL),
65 | self.sessionID,
66 | self.referringURL,
67 | self.randomizedBundleToken,
68 | self.linkContent,
69 | self.linkProperties,
70 | self.data];
71 | }
72 |
73 | @end
74 |
--------------------------------------------------------------------------------
/BranchTests/BNCLocalization.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCLocalization.Test.m
3 | @package BranchTests
4 | @brief Branch string localization tests.
5 |
6 | @author Edward Smith
7 | @date July 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BNCLocalization.h"
13 |
14 | @interface BNCLocalizationTest : BNCTestCase
15 | @end
16 |
17 | @implementation BNCLocalizationTest
18 |
19 | - (void) testLocalizationBasic {
20 |
21 | NSString *truth = nil;
22 | NSString *string = nil;
23 | [BNCLocalization shared].currentLanguage = @"en";
24 |
25 | truth = @"Could not generate a URL.";
26 | string = BNCLocalizedString(truth);
27 | XCTAssertEqualObjects(string, truth);
28 |
29 | truth = @"This string is not in table: Should print a warning and return same string.";
30 | string = BNCLocalizedString(truth);
31 | XCTAssertEqualObjects(string, truth);
32 |
33 | #pragma clang diagnostic push
34 | #pragma clang diagnostic ignored "-Wall"
35 | // Nil input should return empty string output.
36 | truth = @"";
37 | string = BNCLocalizedString(nil);
38 | XCTAssertEqualObjects(string, truth);
39 | #pragma clang diagnostic pop
40 |
41 | // Test formatted language strings.
42 | truth = @"Test formatted language strings.";
43 | string = BNCLocalizedFormattedString(@"Test formatted %@ strings.", @"language");
44 | XCTAssertEqualObjects(string, truth);
45 |
46 | // Test formatted language strings with format checking:
47 | truth = @"Test formatted language strings float 1.00.";
48 | string = BNCLocalizedFormattedString(@"Test formatted %@ strings float %1.2f.", @"language", 1.0);
49 | XCTAssertEqualObjects(string, truth);
50 |
51 | #pragma clang diagnostic push
52 | #pragma clang diagnostic ignored "-Wall"
53 | truth = @"";
54 | string = BNCLocalizedFormattedString(nil, 1.0);
55 | XCTAssertEqualObjects(string, truth);
56 | #pragma clang diagnostic pop
57 | }
58 |
59 | - (void) testLocalizationRussian {
60 |
61 | NSString *truth = nil;
62 | NSString *string = nil;
63 | [BNCLocalization shared].currentLanguage = @"ru";
64 |
65 | string = @"Could not generate a URL.";
66 | truth = @"Не получилось сгенерировать URL.";
67 | string = BNCLocalizedString(string);
68 | XCTAssertEqualObjects(string, truth);
69 | }
70 |
71 | - (void) testApplicationLanguage {
72 | XCTAssertEqualObjects([BNCLocalization applicationLanguage], @"en");
73 | }
74 |
75 | - (void) testSetWeirdLanguage {
76 | // App doesn't speak that. Default to english.
77 | [BNCLocalization shared].currentLanguage = @"UFOAlienSpeak";
78 | XCTAssertEqualObjects([BNCLocalization shared].currentLanguage, @"en");
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/Branch/BNCKeyChain.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCKeyChain.h
3 | @package Branch
4 | @brief Simple access routines for secure keychain storage.
5 |
6 | @author Edward Smith
7 | @date January 8, 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | @interface BNCKeyChain : NSObject
16 |
17 | - (instancetype) init __attribute__((unavailable("init is not available.")));
18 |
19 | - (instancetype) initWithSecurityAccessGroup:(NSString*)securityGroup NS_DESIGNATED_INITIALIZER;
20 |
21 | /**
22 | @brief Remove a value for a service and key. Optionally removes all keys and values for a service.
23 |
24 | @param service The name of the service under which to store the key.
25 | @param key The key to remove the value from. If `nil` is passed, all keys and values are removed for that service.
26 | @return Returns an `NSError` if an error occurs.
27 | */
28 | - (NSError*_Nullable) removeValuesForService:(NSString*)service
29 | key:(NSString*_Nullable)key;
30 |
31 | /**
32 | @brief Returns a value for the passed service and key.
33 |
34 | @param service The name of the service that the value is stored under.
35 | @param key The key that the value is stored under.
36 | @param error If an error occurs, and `error` is a pointer to an error pointer, the error is returned here.
37 | @return Returns the value stored under `service` and `key`, or `nil` if none found.
38 | */
39 | - (id _Nullable) retrieveValueForService:(NSString*)service
40 | key:(NSString*)key
41 | error:(NSError*_Nullable __autoreleasing *_Nullable)error;
42 |
43 | /**
44 | @brief Returns an array of all keys found for a service in the keychain.
45 |
46 | @param service The service name.
47 | @param error If an error occurs, the error is returned in `error` if it is not `NULL`.
48 | @return Returns an array of the items stored in the keychain or `nil`.
49 | */
50 | - (NSArray*_Nullable) retrieveKeysWithService:(NSString*)service
51 | error:(NSError*_Nullable __autoreleasing *_Nullable)error;
52 |
53 | /**
54 | @brief Stores an item in the keychain.
55 |
56 | @param value The value to store.
57 | @param service The service name to store the item under.
58 | @param key The key to store the item under.
59 | @return Returns an error if an error occurs.
60 | */
61 | - (NSError*_Nullable) storeValue:(id)value
62 | forService:(NSString*)service
63 | key:(NSString*)key;
64 |
65 | @property (atomic, copy, readonly) NSString* securityAccessGroup;
66 | @end
67 |
68 | NS_ASSUME_NONNULL_END
69 |
--------------------------------------------------------------------------------
/Scripts/whichapp:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # whichapp - Prints details about a Mac app such as it's installed location,
4 | # bundleID, filename, and display name.
5 | #
6 | # Usage: whichapp [-bdfhps] [--]
7 | #
8 | # Exits code 0 if app is found, 1 otherwise.
9 | #
10 | # E.B. Smith - January 2014
11 |
12 | scriptname=whichapp
13 |
14 | usage () {
15 | cat <
20 |
21 | Converts a common app name like 'textedit' to:
22 |
23 | * A canonical display name like 'TextEdit'.
24 | * A filename, like 'TextEdit.app'.
25 | * A path name, like '/Hard Drive/Applications/TextEdit.app'
26 | * A bundle ID, like 'com.apple.TextEdit'
27 |
28 | Options:
29 |
30 | -a Prints all application information.
31 | -b Prints the application's bundleID.
32 | -d Prints the application's display name.
33 | -f Prints the application's filename.
34 | -h Print this help.
35 | -p Prints the applcaition's full path (default).
36 | -s Silent mode.
37 |
38 | Exits with code 1 if is not found, 0 otherwise.
39 |
40 | USAGE
41 | exit 1
42 | }
43 |
44 | set -eu
45 | set -o pipefail
46 |
47 | appname=""
48 | bDisplayname=false
49 | bFilename=false
50 | bBundleID=false
51 | bPathname=false
52 | bSilent=false
53 |
54 | while getopts ":abdfhps" option; do
55 | case "$option" in
56 | a) bDisplayname=true
57 | bFilename=true
58 | bBundleID=true
59 | bPathname=true
60 | bSilent=false
61 | ;;
62 | b) bBundleID=true ;;
63 | d) bDisplayname=true ;;
64 | f) bFilename=true ;;
65 | h) usage ;;
66 | p) bPathname=true ;;
67 | s) bSilent=true ;;
68 | ?) echo "Unknown option '-$OPTARG'."; exit 1;;
69 | esac
70 | done
71 |
72 | appname="${@:$OPTIND:1}"
73 | if [[ ${#appname} == 0 ]]; then
74 | echo "An is required."
75 | usage
76 | fi
77 |
78 | if ! ($bBundleID || $bDisplayname || $bFilename || $bPathname) ; then
79 | bPathname=true
80 | fi
81 |
82 | if $bSilent ; then
83 | bBundleID=false
84 | bDisplayname=false
85 | bFilename=false
86 | bPathname=false
87 | fi
88 |
89 | query="(kMDItemFSName = \"*${appname}*\"cdw && kMDItemKind == \"Application\")"
90 | pathname=$(mdfind "${query}")
91 | count=$(wc -l <<<"${pathname}")
92 | if (( ${#pathname} == 0 )); then
93 | exit 1
94 | elif (( $count > 1 )); then
95 | echo "Too many results." 1>&2
96 | echo "${pathname}" 1>&2
97 | exit 1
98 | fi
99 |
100 | if $bDisplayname ; then
101 | echo `mdls -raw -name kMDItemDisplayName "${pathname}"`
102 | fi
103 |
104 | if $bFilename ; then
105 | echo `mdls -raw -name kMDItemFSName "${pathname}"`
106 | fi
107 |
108 | if $bBundleID ; then
109 | echo `mdls -raw -name kMDItemCFBundleIdentifier "${pathname}"`
110 | fi
111 |
112 | if $bPathname ; then
113 | echo "${pathname}"
114 | fi
115 |
116 | #DS al fine
117 |
--------------------------------------------------------------------------------
/BranchTests/NSString+Branch.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file NSString+Branch.Test.m
3 | @package BranchTests
4 | @brief Tests for the NSString+Branch category.
5 |
6 | @author Edward Smith
7 | @date February 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "NSString+Branch.h"
13 |
14 | #define _countof(array) (sizeof(array)/sizeof(array[0]))
15 |
16 | @interface NSStringBranchTest : BNCTestCase
17 | @end
18 |
19 | @implementation NSStringBranchTest
20 |
21 | - (void) testMaskEqual {
22 | XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"0123"]);
23 | XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"012"]);
24 | XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"01234"]);
25 | XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"01*3"]);
26 | XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"01*4"]);
27 | XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"*123"]);
28 | XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"012*"]);
29 | XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語123日本語"]);
30 | XCTAssertFalse([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語1234本語"]);
31 | XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語***日本語"]);
32 | XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"***123日本語"]);
33 | }
34 |
35 | - (void) testStringTruncatedAtNull {
36 | char bytes[] = "\x30\x31\x00\x32\x33\x34\x35\x36";
37 | XCTAssert(sizeof(bytes) == 9);
38 | NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)-1];
39 | XCTAssert(data.length == 8);
40 | NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
41 | XCTAssert(string.length == 8);
42 | string = [string bnc_stringTruncatedAtNull];
43 | XCTAssert(string.length == 2);
44 | XCTAssertEqualObjects(string, @"01");
45 |
46 | string = @"";
47 | NSString *test = @"";
48 | string = [string bnc_stringTruncatedAtNull];
49 | XCTAssertEqualObjects(string, test);
50 |
51 | char byte2[] = "\x00\x31\x00\x32\x33\x34\x35\x36";
52 | data = [NSData dataWithBytes:byte2 length:sizeof(byte2)];
53 | string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
54 | XCTAssert(string && string.length == 9);
55 | string = [string bnc_stringTruncatedAtNull];
56 | XCTAssert(string && string.length == 0);
57 |
58 | string = @"No truncate";
59 | test = @"No truncate";
60 | string = [string bnc_stringTruncatedAtNull];
61 | XCTAssertEqualObjects(string, test);
62 | }
63 |
64 | - (void) testContainsString {
65 | NSString *testString = @"I'm a good girl I am.";
66 | XCTAssertTrue([testString bnc_containsString:@"good girl"]);
67 | XCTAssertFalse([testString bnc_containsString:@"I'm a bad girl."]);
68 | XCTAssertFalse([testString bnc_containsString:nil]);
69 | XCTAssertTrue([testString bnc_containsString:testString]);
70 | XCTAssertFalse([testString bnc_containsString:@"I'm a good girl I am..."]);
71 | XCTAssertFalse([testString bnc_containsString:@""]);
72 | }
73 |
74 | @end
75 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestBedUINonBranchLinkTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestBedUINonBranchLinkTest.m
3 | // TestBed-macOSUITests
4 | //
5 | // Created by Nidhi on 2/6/21.
6 | // Copyright © 2021 Branch. All rights reserved.
7 | //
8 |
9 |
10 | #import "TestBedUITest.h"
11 | #import "TestBedUIUtils.h"
12 |
13 | #define SLEEP_TIME_CLICK_BIG 3
14 | #define SLEEP_TIME_CLICK_SMALL 1
15 |
16 | @interface TestBedUINonBranchLinkTest : TestBedUITest
17 |
18 | @end
19 |
20 | @implementation TestBedUINonBranchLinkTest
21 |
22 | - (void)setUp {
23 | [super setUp];
24 | }
25 |
26 | - (void)tearDown {
27 | [super tearDown];
28 | }
29 |
30 | - (void)validateForNonBranchLink {
31 |
32 | NSMutableString *deepLinkDataString ;
33 |
34 | XCUIElement *testbedMacWindow = [[XCUIApplication alloc] init].windows[@"TestBed-Mac"];
35 | XCUIElement *stateElementNext = testbedMacWindow.staticTexts[@"BranchDidStartSessionNotification"];
36 | if ([stateElementNext waitForExistenceWithTimeout:15] != NO) {
37 | XCUIElement *dataTextView = [[[testbedMacWindow childrenMatchingType:XCUIElementTypeScrollView] elementBoundByIndex:0] childrenMatchingType:XCUIElementTypeTextView].element;
38 | deepLinkDataString = dataTextView.value;
39 |
40 | } else {
41 | XCTFail("BranchDidStartSessionNotification not received in 15 seconds");
42 | }
43 |
44 | XCTAssertTrue([deepLinkDataString isNotEqualTo:@""]);
45 | XCTAssertTrue([deepLinkDataString containsString:@"\"+non_branch_link\" = \"testbed-mac://\""] );
46 | }
47 |
48 | - (void)testNonBranchLink {
49 |
50 | XCUIApplication *testBedApp = [[XCUIApplication alloc] init];
51 | if (testBedApp.state != XCUIApplicationStateNotRunning)
52 | [self terminateTestBed];
53 |
54 | XCUIApplication *safariApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.Safari"];
55 | [safariApp setLaunchArguments: @[[NSString stringWithFormat:@"%@%@", [[NSBundle mainBundle] bundlePath], @"/Contents/PlugIns/TestBed-macOSUITests.xctest/Contents/Resources/TestNonBranchLink.html"]]];
56 | [safariApp launch];
57 | sleep(SLEEP_TIME_CLICK_BIG);
58 | XCUIElement *testBedLink = [[safariApp.webViews descendantsMatchingType:XCUIElementTypeLink] elementBoundByIndex:0];
59 |
60 | [testBedLink click];
61 | sleep(SLEEP_TIME_CLICK_BIG);
62 |
63 | XCUIElement *toggleElement = [[safariApp descendantsMatchingType:XCUIElementTypeToggle] elementBoundByIndex:1 ];
64 | if ([toggleElement waitForExistenceWithTimeout:12] != NO) {
65 | [toggleElement click];
66 | }
67 | else {
68 | NSLog(@"Toggle Element(TestBed Launch Confirmation Dialog) Not Found");
69 | }
70 |
71 | if ([[[XCUIApplication alloc] init] waitForExistenceWithTimeout:15] != NO) {
72 | self.appLaunched = TRUE;
73 | [self validateForNonBranchLink];
74 | [safariApp activate];
75 | [safariApp typeKey:@"W" modifierFlags:XCUIKeyModifierShift|XCUIKeyModifierCommand|XCUIKeyModifierOption];
76 |
77 | } else {
78 | XCTFail("Application not launched");
79 | }
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/BranchTests/BNCThreads.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCThreads.Test.m
3 | @package BranchTests
4 | @brief Tests for BNCThreads.
5 |
6 | @author Edward Smith
7 | @date May 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BNCThreads.h"
13 |
14 | @interface BNCThreadsTest : BNCTestCase
15 | @end
16 |
17 | @implementation BNCThreadsTest
18 |
19 | - (void) testTimeConversion {
20 | uint64_t nsec = BNCNanoSecondsFromTimeInterval(1.25);
21 | XCTAssert(nsec == 1250000000ull);
22 |
23 | XCTestExpectation*expectation =
24 | [self expectationWithDescription:@"BNCAfterSecondsPerformBlockOnMainThread"];
25 | NSDate*date = [NSDate date];
26 | BNCAfterSecondsPerformBlockOnMainThread(1.25, ^{
27 | NSTimeInterval te = [date timeIntervalSinceNow];
28 | XCTAssertTrue(te + 1.25 < 0.2000);
29 | [expectation fulfill];
30 | });
31 | [self awaitExpectations];
32 | }
33 |
34 | - (void) testAsyncQueue {
35 | XCTestExpectation*expectation =
36 | [self expectationWithDescription:@"BNCPerformBlockOnMainThreadAsync"];
37 | BNCPerformBlockOnMainThreadAsync(^{
38 | XCTAssertTrue([NSThread isMainThread]);
39 | [expectation fulfill];
40 | });
41 | [self awaitExpectations];
42 | }
43 |
44 | - (void) testSyncQueue {
45 | XCTestExpectation*expectation =
46 | [self expectationWithDescription:@"BNCPerformBlockOnMainThreadSync"];
47 | XCTAssertTrue([NSThread isMainThread]);
48 | BNCPerformBlockOnMainThreadSync(^{
49 | XCTAssertTrue([NSThread isMainThread]);
50 | [expectation fulfill];
51 | });
52 | [self awaitExpectations];
53 | }
54 |
55 | - (void) testSleep {
56 | NSDate*date = [NSDate date];
57 | BNCSleepForTimeInterval(0.125);
58 | NSTimeInterval delta = [date timeIntervalSinceNow];
59 | XCTAssertTrue(delta < -0.125 && delta > -0.200);
60 | }
61 |
62 | - (void) testPerforms {
63 | NSDate*date = [NSDate date];
64 | XCTestExpectation*expectation =
65 | [self expectationWithDescription:@"BNCPerformBlockOnMainThreadSync"];
66 | BNCAfterSecondsPerformBlockOnMainThread(1.0, ^ {
67 | XCTAssertTrue([NSThread isMainThread]);
68 | [expectation fulfill];
69 | });
70 | [self awaitExpectations];
71 | NSTimeInterval t = [date timeIntervalSinceNow];
72 | XCTAssert(t >= -1.5 && t < -1.0);
73 | }
74 |
75 | - (void) testBNCPerformBlockAsync {
76 | XCTestExpectation*expectation = [self expectationWithDescription:@"BNCPerformBlockAsync"];
77 | BNCPerformBlockAsync( ^ {
78 | [expectation fulfill];
79 | });
80 | [self awaitExpectations];
81 | }
82 |
83 | - (void) testBNCAfterSecondsPerformBlock {
84 | NSDate*date = [NSDate date];
85 | XCTestExpectation*expectation =
86 | [self expectationWithDescription:@"BNCAfterSecondsPerformBlock"];
87 | BNCAfterSecondsPerformBlock(1.0, ^ {
88 | [expectation fulfill];
89 | });
90 | [self awaitExpectations];
91 | NSTimeInterval t = [date timeIntervalSinceNow];
92 | XCTAssert(t >= -1.25 && t < -1.0);
93 | }
94 |
95 | @end
96 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOSUITests/TestBedUIInstallOpenTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestBedUIInstallOpenTest.m
3 | // TestBed-macOSUITests
4 | //
5 | // Created by Nidhi on 11/3/20.
6 | // Copyright © 2020 Branch. All rights reserved.
7 | //
8 |
9 | #import "TestBedUITest.h"
10 | #import "TestBedUIUtils.h"
11 |
12 | @interface TestBedUIInstallOpenTest : TestBedUITest
13 |
14 | @end
15 |
16 | @implementation TestBedUIInstallOpenTest
17 |
18 | - (void)setUp {
19 | [super setUp];
20 | }
21 |
22 | - (void)tearDown {
23 | [super tearDown];
24 | }
25 |
26 | - (void)testInstallAndOpen {
27 |
28 | __block NSString *randomizedBundleToken;
29 | __block NSString *randomizedDeviceToken;
30 |
31 | [TestBedUIUtils deleteSettingsFiles];
32 |
33 | if (self.trackingState == TRACKING_DISABLED) {
34 | [self enableTracking];
35 | }
36 |
37 | XCTWaiterResult result = [self launchAppAndWaitForSessionStart];
38 |
39 | [XCTContext runActivityNamed:@"InstallAPI" block:^(id activity){
40 |
41 | if (result == XCTWaiterResultCompleted) {
42 |
43 | XCTAssertTrue([[self serverRequestString] containsString:@"/v1/install"]);
44 |
45 | NSDictionary *serverResponseDictionary = [ TestBedUIUtils dictionaryFromString:[self serverResponseString]];
46 | XCTAssertNotNil([serverResponseDictionary valueForKey:@"randomized_bundle_token"]);
47 | XCTAssertNotNil([serverResponseDictionary valueForKey:@"randomized_device_token"]);
48 |
49 | randomizedBundleToken = [serverResponseDictionary objectForKey:@"randomized_bundle_token"];
50 | randomizedDeviceToken = [serverResponseDictionary objectForKey:@"randomized_device_token"];
51 |
52 | [activity addAttachment:[XCTAttachment attachmentWithScreenshot:[[XCUIScreen mainScreen] screenshot]]];
53 | [self terminateTestBed];
54 | self.appLaunched = FALSE;
55 | }
56 | else {
57 | XCTFail("App Launch / Session Start Failed.");
58 | }
59 | }];
60 |
61 | result = [self launchAppAndWaitForSessionStart];
62 |
63 | [XCTContext runActivityNamed:@"OpenAPI" block:^(id activity){
64 | if (result == XCTWaiterResultCompleted) {
65 |
66 | XCTAssertTrue([[self serverRequestString] containsString:@"/v1/open"]);
67 |
68 | NSDictionary *serverRequestDictionary = [TestBedUIUtils dictionaryFromString:[self serverRequestString]];
69 | XCTAssertNotNil([serverRequestDictionary valueForKey:@"randomized_bundle_token"]);
70 | XCTAssertEqualObjects([serverRequestDictionary valueForKey:@"randomized_bundle_token"], randomizedBundleToken);
71 |
72 | XCTAssertNotNil([serverRequestDictionary valueForKey:@"randomized_device_token"]);
73 | XCTAssertEqualObjects([serverRequestDictionary valueForKey:@"randomized_device_token"], randomizedDeviceToken);
74 |
75 | XCTAssertTrue([[self serverResponseString] containsString:@"Status 200"]);
76 | }
77 | else {
78 | XCTFail("App Launch / Session Start Failed.");
79 | }
80 | }];
81 |
82 | }
83 |
84 | @end
85 |
--------------------------------------------------------------------------------
/Branch/BranchNetworkServiceProtocol.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchNetworkServiceProtocol.h
3 | @package Branch
4 | @brief A networking protocol contract to an abstract underlying network class.
5 |
6 | @author Edward Smith
7 | @date May 30, 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 |
16 | #ifndef BNCNetworkOperationProtocol_h
17 | #define BNCNetworkOperationProtocol_h
18 |
19 | #pragma mark BNCNetworkOperationProtocol
20 |
21 | /**
22 | @name The `BNCNetworkServiceProtocol` and `BNCNetworkOperationProtocol` protocols.
23 |
24 | @discussion
25 | The protocols `BNCNetworkServiceProtocol` and `BNCNetworkOperationProtocol` describe the methods
26 | needed to create a drop in replacement for the standard Branch SDK networking.
27 |
28 | See `Branch-SDK/Network/BNCNetworkService.h` and `Branch-SDK/Network/BNCNetworkService.m` for a
29 | concrete example of how to implement the BNCNetworkServiceProtocol and BNCNetworkOperationProtocol
30 | protocols.
31 |
32 | Usage
33 | -----
34 |
35 | 1. Create your own network service class that follows the `BNCNetworkServiceProtocol`.
36 | The `new` and `networkOperationWithURLRequest:completion:` methods are required. The
37 | others are optional.
38 |
39 | 2. Create your own network operation class that follows the `BNCNetworkOperationProtocol`.
40 | The `start` method is required, as are all the getters for request, response, error, and date
41 | data items.
42 |
43 | 3. In your app delegate, set your network class by calling `[Branch setNetworkServiceClass:]` with
44 | your network class as a parameter. This method must be called before initializing the Branch
45 | shared object.
46 |
47 | */
48 | @protocol BNCNetworkOperationProtocol
49 |
50 | /// The initial NSMutableURLRequest.
51 | @required
52 | @property (readonly) NSURLRequest *request;
53 |
54 | /// The response code from the server.
55 | @required
56 | @property (readonly) NSInteger HTTPStatusCode;
57 |
58 | /// The data from the server.
59 | @required
60 | @property (readonly) NSData*_Nullable responseData;
61 |
62 | /// Any errors that occurred during the request.
63 | @required
64 | @property (readonly) NSError*_Nullable error;
65 |
66 | /// Starts the network operation.
67 | @required
68 | - (void) start;
69 |
70 | /// Cancels a queued or in progress network operation.
71 | @optional
72 | - (void) cancel;
73 |
74 | @end
75 |
76 | #pragma mark - BNCNetworkServiceProtocol
77 |
78 | /**
79 | The `BNCNetworkServiceProtocol` defines a network service that handles a queue of network
80 | operations.
81 | */
82 | @protocol BNCNetworkServiceProtocol
83 |
84 | /// Creates and returns a new network service.
85 | @required
86 | - (id) init;
87 |
88 | /// Cancel all current and queued network operations.
89 | @optional
90 | - (void) cancelAllOperations;
91 |
92 | /// Create and return a new network operation object. The network operation is not started until
93 | /// `[operation start]` is called.
94 | @required
95 | - (id) networkOperationWithURLRequest:(NSMutableURLRequest*)request
96 | completion:(void (^)(idoperation))completion;
97 |
98 | @end
99 |
100 | #endif
101 |
102 | NS_ASSUME_NONNULL_END
103 |
--------------------------------------------------------------------------------
/BranchTests/BNCTestNetworkService.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCTestNetworkService.m
3 | @package BranchTests
4 | @brief A class for mocking network service calls.
5 |
6 | @author Edward
7 | @date 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestNetworkService.h"
12 | #import "BNCThreads.h"
13 |
14 | @interface BNCTestNetworkService ()
15 | - (void) startOperation:(BNCTestNetworkOperation*)operation;
16 | @end
17 |
18 | #pragma mark BNCTestNetworkOperation
19 |
20 | @interface BNCTestNetworkOperation ()
21 | @property (strong) BNCTestNetworkService*networkService;
22 | @property (copy, nullable) void (^completionBlock)(BNCTestNetworkOperation*);
23 | @end
24 |
25 | @implementation BNCTestNetworkOperation
26 |
27 | - (void) start {
28 | [self.networkService startOperation:self];
29 | }
30 |
31 | - (void) cancel {
32 | }
33 |
34 | @end
35 |
36 | #pragma mark - BNCTestNetworkService
37 |
38 | @implementation BNCTestNetworkService
39 |
40 | static id(^_requestHandler)(NSMutableURLRequest*request);
41 |
42 | + (void) setRequestHandler:(id_Nonnull(^)(NSMutableURLRequest*_Nonnull))requestHandler {
43 | @synchronized(self) {
44 | _requestHandler = [requestHandler copy];
45 | }
46 | }
47 |
48 | + (id _Nonnull (^)(NSMutableURLRequest * _Nonnull))requestHandler {
49 | @synchronized(self) {
50 | return [_requestHandler copy];
51 | }
52 | }
53 |
54 | + (NSMutableDictionary*) mutableDictionaryFromRequest:(NSURLRequest*)request {
55 | NSData*data = request.HTTPBody;
56 | if (!data) return nil;
57 | NSMutableDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data
58 | options:NSJSONReadingMutableContainers error:nil];
59 | return dictionary;
60 | }
61 |
62 | + (id) operationWithRequest:(NSMutableURLRequest*)request
63 | response:(NSString*)responseString {
64 | BNCTestNetworkOperation*operation = [[BNCTestNetworkOperation alloc] init];
65 | operation.request = request;
66 | operation.HTTPStatusCode = 200;
67 | operation.responseData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
68 | return operation;
69 | }
70 |
71 | #pragma mark - Protocol Methods
72 |
73 | - (id) networkOperationWithURLRequest:(NSMutableURLRequest*)request
74 | completion:(void (^)(idoperation))completion {
75 | idoperation = nil;
76 | if (self.class.requestHandler == nil) {
77 | // [NSException raise:NSInternalInconsistencyException
78 | // format:@"%@ requestHandler not set!", NSStringFromClass(self.class)];
79 | operation = [self.class operationWithRequest:request response:@"{}"];
80 | } else {
81 | operation = self.class.requestHandler(request);
82 | }
83 | ((BNCTestNetworkOperation*)operation).networkService = self;
84 | ((BNCTestNetworkOperation*)operation).completionBlock = completion;
85 | return operation;
86 | }
87 |
88 | - (void) startOperation:(BNCTestNetworkOperation*)operation {
89 | operation.networkService = self;
90 | // operation.startDate = [NSDate date];
91 | // operation.timeoutDate = [operation.startDate dateByAddingTimeInterval:operation.request.timeoutInterval];
92 | BNCAfterSecondsPerformBlockOnMainThread(0.010, ^{
93 | if (operation.completionBlock)
94 | operation.completionBlock(operation);
95 | });
96 | }
97 |
98 | @end
99 |
--------------------------------------------------------------------------------
/Branch.xcodeproj/xcshareddata/xcschemes/BranchTestHost.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/Branch/BNCApplication.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCApplication.h
3 | @package Branch
4 | @brief Current application and extension info.
5 |
6 | @author Edward Smith
7 | @date January 8, 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | typedef NS_ENUM(NSInteger, BNCApplicationUpdateState) {
16 | BNCApplicationUpdateStateInstall = 0, //!< Application was recently installed.
17 | BNCApplicationUpdateStateNonUpdate = 1, //!< Application was neither newly installed nor updated.
18 | BNCApplicationUpdateStateUpdate = 2, //!< Application was recently updated.
19 |
20 | BNCApplicationUpdateStateError = 3, //!< Error determining update state.
21 | BNCApplicationUpdateStateReinstall = 4, //!< App was re-installed.
22 | };
23 |
24 | @interface BNCApplication : NSObject
25 |
26 | /// A reference to the current running application.
27 | + (BNCApplication*_Nonnull) currentApplication;
28 |
29 | /// The bundle identifier of the current
30 | @property (atomic, readonly) NSString*_Nullable bundleID;
31 |
32 | /// The team that was for code signing.
33 | @property (atomic, readonly) NSString*_Nullable teamID;
34 |
35 | /// The bundle display name from the info plist.
36 | @property (atomic, readonly) NSString*_Nullable displayName;
37 |
38 | /// The bundle short display name from the info plist.
39 | @property (atomic, readonly) NSString*_Nullable shortDisplayName;
40 |
41 | /// The short version ID as is typically shown to the user, like in iTunes (CFBundleShortVersionString).
42 | @property (atomic, readonly) NSString*_Nullable displayVersionString;
43 |
44 | /// The version ID that developers use (CFBundleVersion).
45 | @property (atomic, readonly) NSString*_Nullable versionString;
46 |
47 | /// The creation date of the current executable.
48 | @property (atomic, readonly) NSDate*_Nullable currentBuildDate;
49 |
50 | /// Previous value of the creation date of the current executable, if available.
51 | @property (atomic, readonly) NSDate*_Nullable previousAppBuildDate;
52 |
53 | /// The creating date of the exectuble the first time it was recorded by Branch.
54 | @property (atomic, readonly) NSDate*_Nullable firstInstallBuildDate;
55 |
56 | /// The date this app was installed on this device.
57 | @property (atomic, readonly) NSDate*_Nullable currentInstallDate;
58 |
59 | /// The date this app was first installed on this device.
60 | @property (atomic, readonly) NSDate*_Nullable firstInstallDate;
61 |
62 | /// The update state off the application.
63 | @property (atomic, readonly) BNCApplicationUpdateState updateState;
64 |
65 | /// YES if running as an application.
66 | @property (atomic, readonly) BOOL isApplication;
67 |
68 | /// YES if running as an application extension.
69 | @property (atomic, readonly) BOOL isApplicationExtension;
70 |
71 | /// The app extension type or `nil` for a full application.
72 | @property (atomic, readonly) NSString*_Nullable extensionType;
73 |
74 | /// The Branch extension type.
75 | @property (atomic, readonly) NSString* branchExtensionType;
76 |
77 | /// The default URL scheme for the app as found in the app's Info.plist.
78 | @property (atomic, readonly) NSString*_Nullable defaultURLScheme;
79 |
80 | /// The unique application identifier. Typically this is `teamID.bundleID`: XYZ123.com.company.app.
81 | @property (atomic, readonly) NSString*_Nullable applicationID;
82 |
83 | /// The push notification environment. Usually `development` or `production` or `nil`.
84 | @property (atomic, readonly) NSString*_Nullable pushNotificationEnvironment;
85 |
86 | /// The keychain access groups from the entitlements.
87 | @property (atomic, readonly) NSArray*_Nullable keychainAccessGroups;
88 |
89 | /// The associated domains from the entitlements.
90 | @property (atomic, readonly) NSArray*_Nullable associatedDomains;
91 | @end
92 |
93 | NS_ASSUME_NONNULL_END
94 |
--------------------------------------------------------------------------------
/BranchTests/BNCApplication.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCApplication.Test.m
3 | @package BranchTests
4 | @brief Tests for BNCApplication.
5 |
6 | @author Edward Smith
7 | @date January 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BNCApplication.h"
13 | #import "BNCKeyChain.h"
14 | #import "BranchMainClass.h"
15 | #import "BranchMainClass+Private.h"
16 |
17 | @interface BNCApplication (BNCTestCase)
18 | + (BNCApplication *) createCurrentApplication;
19 | @end
20 |
21 | #pragma mark - BNCApplicationTest
22 |
23 | @interface BNCApplicationTest : BNCTestCase
24 | @end
25 |
26 | @implementation BNCApplicationTest
27 |
28 | - (void)testIsApplication {
29 | XCTAssertTrue([BNCApplication currentApplication].isApplication);
30 | }
31 |
32 | - (void)testApplication {
33 | BNCApplication *application = [BNCApplication currentApplication];
34 | if (!application.isApplication) {
35 | return;
36 | }
37 | NSDictionary *info = [NSBundle mainBundle].infoDictionary;
38 | XCTAssertEqualObjects(application.bundleID, info[@"CFBundleIdentifier"]);
39 | XCTAssertEqualObjects(application.displayName, info[@"CFBundleName"]);
40 | XCTAssertEqualObjects(application.shortDisplayName, info[@"CFBundleName"]);
41 | XCTAssertEqualObjects(application.displayVersionString, info[@"CFBundleShortVersionString"]);
42 | XCTAssertEqualObjects(application.versionString, info[@"CFBundleVersion"]);
43 |
44 | XCTAssert(application.extensionType == nil);
45 | XCTAssert([application.branchExtensionType isEqualToString:@"FULL_APP"]);
46 |
47 | XCTAssert(application.pushNotificationEnvironment == nil);
48 |
49 | // TODO: These only exist when integrated into a full app, make them part of an integration test
50 | //XCTAssert(application.defaultURLScheme.length > 0);
51 | //XCTAssert(application.applicationID.length > 0);
52 | //XCTAssert(application.teamID.length > 0);
53 | //XCTAssert(application.keychainAccessGroups.count > 0);
54 |
55 | XCTAssert(application.associatedDomains.count == 0);
56 | }
57 |
58 | // TODO: unit tests should not be order dependent, refactor this test
59 | // These are methods are numbered so they run in order:
60 | //- (void) testAppUpdate1Basic {
61 | // BNCApplication *application = [BNCApplication currentApplication];
62 | // if (!application.isApplication) {
63 | // return;
64 | // }
65 | //
66 | // //
67 | // // App dates. Not a great test but tests basic function:
68 | // //
69 | // NSTimeInterval const kOneYearAgo = -365.0 * 24.0 * 60.0 * 60.0;
70 | //
71 | // XCTAssertTrue(application.firstInstallDate && [application.firstInstallDate timeIntervalSinceNow] > kOneYearAgo);
72 | // XCTAssertTrue(application.firstInstallBuildDate && [application.firstInstallBuildDate timeIntervalSinceNow] > kOneYearAgo);
73 | // XCTAssertTrue(application.currentInstallDate && [application.currentInstallDate timeIntervalSinceNow] > kOneYearAgo);
74 | // XCTAssertTrue(application.currentBuildDate && [application.currentBuildDate timeIntervalSinceNow] > kOneYearAgo);
75 | //
76 | // NSString*const kBranchKeychainService = @"BranchKeychainService";
77 | // NSString*const kBranchKeychainFirstBuildKey = @"BranchKeychainFirstBuild";
78 | // NSString*const kBranchKeychainFirstInstalldKey = @"BranchKeychainFirstInstall";
79 | //
80 | // NSString*securityGroup = application.applicationID;
81 | // BNCKeyChain*keychain = [[BNCKeyChain alloc] initWithSecurityAccessGroup:securityGroup];
82 | //
83 | // NSDate *firstBuildDate = [keychain retrieveValueForService:kBranchKeychainService key:kBranchKeychainFirstBuildKey error:nil];
84 | // XCTAssertEqualObjects(application.firstInstallBuildDate, firstBuildDate);
85 | //
86 | // NSDate *firstInstallDate = [keychain retrieveValueForService:kBranchKeychainService key:kBranchKeychainFirstInstalldKey error:nil];
87 | // XCTAssertEqualObjects(application.firstInstallDate, firstInstallDate);
88 | //}
89 |
90 | @end
91 |
--------------------------------------------------------------------------------
/Examples/TestBed-macOS/TestBed-macOS/APPV2EventSelectionWindow.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/.github/workflows/sync-readme-changelog.yml:
--------------------------------------------------------------------------------
1 | name: Update Version History on Readme
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | update-changelog:
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - name: Format and publish release notes to version history doc
13 | id: update
14 | run: |
15 | # Get release name, body, and date from the release event
16 | release_name="${{ github.event.release.tag_name }}"
17 | release_body="${{ github.event.release.body }}"
18 | release_date=$(date -d "${{ github.event.release.published_at }}" +"%Y-%B-%d")
19 | # Format release notes
20 | formatted_notes="## v$release_name\n\n**($release_date)**\n\n$release_body"
21 |
22 | # Get existing version history page
23 | existing_content=$(curl --request GET \
24 | --url https://dash.readme.com/api/v1/docs/mac-os-version-history \
25 | --header 'accept: application/json' \
26 | --header "authorization: Basic ${{ secrets.readme_api_key_base64 }}" \
27 | | jq -r '.body')
28 |
29 | # Prepend new release notes to existing content
30 | new_content=$(echo -e "$formatted_notes\n\n$existing_content")
31 | payload=$(jq -n --arg nc "$new_content" '{"body": $nc}')
32 |
33 | # Update version history page with new release notes
34 | curl --request PUT \
35 | --url https://dash.readme.com/api/v1/docs/mac-os-version-history \
36 | --header 'accept: application/json' \
37 | --header "authorization: Basic ${{ secrets.readme_api_key_base64 }}" \
38 | --header 'content-type: application/json' \
39 | --data "$payload"
40 |
41 | - name: Announce New Release in Slack
42 | uses: slackapi/slack-github-action@v1.24.0
43 | with:
44 | channel-id: "C063MQJMKJN" #sdk-releases
45 | payload: |
46 | {
47 | "text": "New Release: Branch MacOS SDK v${{ github.event.release.tag_name }}",
48 | "blocks": [
49 | {
50 | "type": "header",
51 | "text": {
52 | "type": "plain_text",
53 | "text": ":rocket: New Release: Branch MacOS SDK v${{ github.event.release.tag_name }}",
54 | "emoji": true
55 | }
56 | },
57 | {
58 | "type": "divider"
59 | },
60 | {
61 | "type": "section",
62 | "text": {
63 | "type": "mrkdwn",
64 | "text": ":star: *What's New*"
65 | }
66 | },
67 | {
68 | "type": "section",
69 | "text": {
70 | "type": "mrkdwn",
71 | "text": ${{ toJSON(github.event.release.body) }}
72 | }
73 | },
74 | {
75 | "type": "divider"
76 | },
77 | {
78 | "type": "actions",
79 | "elements": [
80 | {
81 | "type": "button",
82 | "text": {
83 | "type": "plain_text",
84 | "text": ":git: GitHub Release",
85 | "emoji": true
86 | },
87 | "value": "github",
88 | "action_id": "github",
89 | "url": "${{ github.event.release.html_url }}"
90 | }
91 | ]
92 | }
93 | ]
94 | }
95 | env:
96 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_SDK_BOT_TOKEN }}
97 |
--------------------------------------------------------------------------------
/Branch/BranchDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchDelegate.h
3 | @package Branch
4 | @brief Branch delegate protocol and notifications.
5 |
6 | @author Edward Smith
7 | @date June 30, 2017
8 | @copyright Copyright © 2017 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchHeader.h"
12 | @class Branch, BranchSession;
13 |
14 | NS_ASSUME_NONNULL_BEGIN
15 |
16 |
17 | #ifndef BranchDelegate_h
18 | #define BranchDelegate_h
19 |
20 | /**
21 | @name Branch Notifications and delegate methods.
22 |
23 | The Branch SDK can signal your app in three different ways when an deep link is available for your app to
24 | handle: You can set a callback block, you can set a delegate, or you can add an observer for NSNotifications.
25 | You can choose the that best suits your app archetcture.
26 | */
27 |
28 | #pragma mark BranchDelegate Protocol
29 |
30 | /**
31 | These delegate methods are called when while Branch is starting a new URL session and possibly opening a
32 | deep link. All the methods are optional.
33 |
34 | ```objc
35 | [Branch sharedInstance].delegate = delegateInstance;
36 | ```
37 | */
38 | @protocol BranchDelegate
39 |
40 | @optional
41 | - (void) branch:(Branch*)branch willStartSessionWithURL:(NSURL*_Nullable)url;
42 | - (void) branch:(Branch*)branch didStartSession:(BranchSession*)session;
43 | - (void) branch:(Branch*)branch failedToStartSessionWithURL:(NSURL*_Nullable)url
44 | error:(NSError*_Nullable)error;
45 | - (void) branch:(Branch*)branch didOpenURLWithSession:(BranchSession*)session;
46 | @end
47 |
48 | #pragma mark - Branch Notifications and Keys
49 |
50 | /**
51 | @name Branch Notifications
52 |
53 | The advantage of observing Branch NSNotifications is that it allows for more modularized code with greater
54 | separation of responsibility. Only those classes that care about Branch notifications need to know about
55 | them. This is particularly useful as your project grows larger and dependency management becomes an issue.
56 |
57 | #### **`BranchWillStartSessionNotification`**
58 |
59 | This notification is sent just before the Branch SDK is about to determine if there is a deep link for your
60 | app to handle. This usually involves a server call so it may take some time for the SDK to make the
61 | determination.
62 |
63 | ##### Notification Keys
64 |
65 | The notification `userInfo` dictionary may have these keys:
66 |
67 | Key | Value Type | Content
68 | :---:|:----------:|:-------
69 | `BranchURLKey`
(Optional) | NSURL | This is the URL if the Branch session was started with a URL.
70 |
71 | #### **`BranchDidStartSessionNotification`**
72 |
73 | This notification is sent when the Branch SDK has started a new URL session. There may or may not be a deep
74 | link for your app to handle. If there is, the `BranchSessionKey` value will have a BranchSession that
75 | contains the deep link content.
76 |
77 | If an error has occurred the `BranchErrorKey` value will contain an `NSError` that describes the error.
78 |
79 | ##### Notification Keys
80 |
81 | The notification `userInfo` dictionary may have these keys:
82 |
83 | Key | Value Type | Content
84 | :---:|:----------:|:-------
85 | `BranchURLKey`
(Optional) | NSURL | This is the URL that started the Branch session.
86 | `BranchSessionKey`
(Optional) | BranchSession | If the Branch session has a Branch deep link for your app to handle, this is the deep link content decoded into a BranchSession.
87 | `BranchErrorKey`
(Optional) | NSError | If an error occurred while starting the Branch session, this the NSError that describes the error.
88 | */
89 |
90 | FOUNDATION_EXPORT NSString*const BranchWillStartSessionNotification;
91 | FOUNDATION_EXPORT NSString*const BranchDidStartSessionNotification;
92 | FOUNDATION_EXPORT NSString*const BranchDidOpenURLWithSessionNotification;
93 |
94 | FOUNDATION_EXPORT NSString*const BranchURLKey;
95 | FOUNDATION_EXPORT NSString*const BranchSessionKey;
96 | FOUNDATION_EXPORT NSString*const BranchErrorKey;
97 |
98 | #endif
99 |
100 | NS_ASSUME_NONNULL_END
101 |
--------------------------------------------------------------------------------
/Branch/BNCUserAgentCollector.m:
--------------------------------------------------------------------------------
1 | //
2 | // BNCUserAgentCollector.m
3 | // Branch
4 | //
5 | // Created by Ernest Cho on 8/29/19.
6 | // Copyright © 2019 Branch, Inc. All rights reserved.
7 | //
8 |
9 | #import "BNCUserAgentCollector.h"
10 | #import "BNCDevice.h"
11 | @import WebKit;
12 |
13 | // expose a private method on BNCDevice
14 | @interface BNCDevice()
15 | + (NSString *)systemBuildVersion;
16 | @end
17 |
18 | @interface BNCUserAgentCollector()
19 | // need to hold onto the webview until the async user agent fetch is done
20 | @property (nonatomic, strong, readwrite) WKWebView *webview;
21 | @end
22 |
23 | @implementation BNCUserAgentCollector
24 |
25 | + (BNCUserAgentCollector *)instance {
26 | static BNCUserAgentCollector *collector;
27 | static dispatch_once_t onceToken;
28 | dispatch_once(&onceToken, ^{
29 | collector = [BNCUserAgentCollector new];
30 | });
31 | return collector;
32 | }
33 |
34 | + (NSString *)userAgentKey {
35 | return @"BNC_USER_AGENT";
36 | }
37 |
38 | + (NSString *)systemBuildVersionKey {
39 | return @"BNC_SYSTEM_BUILD_VERSION";
40 | }
41 |
42 | - (void)loadUserAgentWithCompletion:(void (^)(NSString *userAgent))completion {
43 | [self loadUserAgentForSystemBuildVersion:[BNCDevice systemBuildVersion] withCompletion:completion];
44 | }
45 |
46 | - (void)loadUserAgentForSystemBuildVersion:(NSString *)systemBuildVersion withCompletion:(void (^)(NSString *userAgent))completion {
47 |
48 | NSString *savedUserAgent = [self loadUserAgentForSystemBuildVersion:systemBuildVersion];
49 | if (savedUserAgent) {
50 | self.userAgent = savedUserAgent;
51 | if (completion) {
52 | completion(savedUserAgent);
53 | }
54 | } else {
55 | [self collectUserAgentWithCompletion:^(NSString * _Nullable userAgent) {
56 | self.userAgent = userAgent;
57 | [self saveUserAgent:userAgent forSystemBuildVersion:systemBuildVersion];
58 | if (completion) {
59 | completion(userAgent);
60 | }
61 | }];
62 | }
63 | }
64 |
65 | // load user agent from preferences
66 | - (NSString *)loadUserAgentForSystemBuildVersion:(NSString *)systemBuildVersion {
67 | NSString *userAgent = nil;
68 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
69 | NSString *savedUserAgent = (NSString *)[defaults valueForKey:[BNCUserAgentCollector userAgentKey]];
70 | NSString *savedSystemBuildVersion = (NSString *)[defaults valueForKey:[BNCUserAgentCollector systemBuildVersionKey]];
71 |
72 | if (savedUserAgent && [systemBuildVersion isEqualToString:savedSystemBuildVersion]) {
73 | userAgent = savedUserAgent;
74 | }
75 | return userAgent;
76 | }
77 |
78 | // save user agent to preferences
79 | - (void)saveUserAgent:(NSString *)userAgent forSystemBuildVersion:(NSString *)systemBuildVersion {
80 | if (userAgent && systemBuildVersion) {
81 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
82 | [defaults setObject:userAgent forKey:[BNCUserAgentCollector userAgentKey]];
83 | [defaults setObject:systemBuildVersion forKey:[BNCUserAgentCollector systemBuildVersionKey]];
84 | }
85 | }
86 |
87 | // collect user agent from webkit. this is expensive.
88 | - (void)collectUserAgentWithCompletion:(void (^)(NSString *userAgent))completion {
89 | dispatch_async(dispatch_get_main_queue(), ^{
90 | if (!self.webview) {
91 | self.webview = [[WKWebView alloc] initWithFrame:CGRectZero];
92 | }
93 |
94 | [self.webview evaluateJavaScript:@"navigator.userAgent;" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
95 | if (completion) {
96 | if (response) {
97 | completion(response);
98 |
99 | // release the webview
100 | self.webview = nil;
101 | } else {
102 | // retry if we failed to obtain user agent. This occurs on iOS simulators.
103 | [self collectUserAgentWithCompletion:completion];
104 | }
105 | }
106 | }];
107 | });
108 | }
109 |
110 | @end
111 |
--------------------------------------------------------------------------------
/Examples/TestDeepLinking/TestDeepLinking/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // TestDeepLinking
4 | //
5 | // Created by Nidhi on 2/3/21.
6 | //
7 |
8 | #import "AppDelegate.h"
9 | #import
10 | #import
11 | #import
12 |
13 | static AppDelegate* appDelegate = nil;
14 | static BNCLogOutputFunctionPtr originalLogHook = NULL;
15 |
16 | void APPLogHookFunction(NSDate*_Nonnull timestamp, BNCLogLevel level, NSString*_Nullable message);
17 | void APPLogHookFunction(NSDate*_Nonnull timestamp, BNCLogLevel level, NSString*_Nullable message) {
18 | [appDelegate processLogMessage:message];
19 | if (originalLogHook) {
20 | originalLogHook(timestamp, level, message);
21 | }
22 | }
23 |
24 | @interface AppDelegate ()
25 |
26 | @property (strong) IBOutlet NSWindow *window;
27 | @end
28 |
29 | @implementation AppDelegate
30 |
31 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
32 |
33 | appDelegate = self;
34 | originalLogHook = BNCLogOutputFunction();
35 | BNCLogSetOutputFunction(APPLogHookFunction);
36 | BNCLogSetDisplayLevel(BNCLogLevelAll);
37 |
38 | [[NSNotificationCenter defaultCenter]
39 | addObserver:self
40 | selector:@selector(branchWillStartSession:)
41 | name:BranchWillStartSessionNotification
42 | object:nil];
43 |
44 | [[NSNotificationCenter defaultCenter]
45 | addObserver:self
46 | selector:@selector(branchDidStartSession:)
47 | name:BranchDidStartSessionNotification
48 | object:nil];
49 |
50 | [[NSNotificationCenter defaultCenter]
51 | addObserver:self
52 | selector:@selector(branchOpenedURLNotification:)
53 | name:BranchDidOpenURLWithSessionNotification
54 | object:nil];
55 |
56 | BranchConfiguration *configuration = [[BranchConfiguration alloc] initWithKey:@"key_live_jcZkwmLUm17zGqCXKyh6QjdiAyjDodHI"];
57 |
58 | configuration.branchAPIServiceURL = @"https://api.branch.io";
59 | configuration.key = @"key_live_jcZkwmLUm17zGqCXKyh6QjdiAyjDodHI";
60 |
61 | [[Branch sharedInstance] startWithConfiguration:configuration];
62 | }
63 |
64 | - (BOOL) string:(NSString*)string matchesRegex:(NSString*)regex {
65 | NSError *error = NULL;
66 | NSRegularExpression *ns_regex =
67 | [NSRegularExpression regularExpressionWithPattern:regex options:0 error:&error];
68 | NSRange range = [ns_regex rangeOfFirstMatchInString:string options:0 range:NSMakeRange(0, string.length)];
69 | return (range.location == NSNotFound) ? NO : YES;
70 | }
71 |
72 |
73 | - (void) processLogMessage:(NSString *)message {
74 | if (([self string:message matchesRegex:
75 | @"^\\[branch\\.io\\] BNCNetworkService\\.m\\([0-9]+\\) Debug: Network start"])&&
76 | ([message containsString:@"https://cdn.branch.io/sdk/uriskiplist_v0.json"] == NO)) {
77 | BNCPerformBlockOnMainThreadAsync(^{
78 |
79 | NSLog(@"---------------\n%@\n--------------", message);
80 | // self.viewController.requestTextView.string = message;
81 | });
82 | } else
83 | if (([self string:message matchesRegex:
84 | @"^\\[branch\\.io\\] BNCNetworkService\\.m\\([0-9]+\\) Debug: Network finish"])&&
85 | ([message containsString:@"https://cdn.branch.io/sdk/uriskiplist_v0.json"] == NO)) {
86 | BNCPerformBlockOnMainThreadAsync(^{
87 | //self.viewController.responseTextView.string = message;
88 | });
89 | }
90 | }
91 |
92 |
93 | #pragma mark - Branch Notifications
94 |
95 | - (void) branchWillStartSession:(NSNotification*)notification {
96 | self.notification.stringValue = notification.name;
97 | }
98 |
99 | - (void) branchDidStartSession:(NSNotification*)notification {
100 |
101 | BranchSession *session = notification.userInfo[BranchSessionKey];
102 |
103 | NSString *data = (session && session.data) ? session.data.description : @"";
104 | self.sessionData.string = data ;
105 |
106 | }
107 |
108 | - (void) branchOpenedURLNotification:(NSNotification*)notification {
109 | self.notification.stringValue = notification.name;
110 | }
111 |
112 |
113 | - (void)applicationWillTerminate:(NSNotification *)aNotification {
114 | // Insert code here to tear down your application
115 | }
116 |
117 |
118 | @end
119 |
--------------------------------------------------------------------------------
/BranchTests/BNCKeyChain.Test.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BNCKeyChain.Test.m
3 | @package BranchTests
4 | @brief BNCKeyChain tests.
5 |
6 | @author Edward Smith
7 | @date January 8, 2018
8 | @copyright Copyright © 2018 Branch. All rights reserved.
9 | */
10 |
11 | #import "BNCTestCase.h"
12 | #import "BNCKeyChain.h"
13 | #import "BNCDevice.h"
14 | #import "BNCApplication.h"
15 |
16 | @interface BNCKeyChainTest : BNCTestCase
17 | @end
18 |
19 | @implementation BNCKeyChainTest
20 |
21 | - (void)testKeyChain {
22 | NSError *error = nil;
23 | NSString*value = nil;
24 | NSArray *array, *array1;
25 | NSString*const kServiceName = @"Service";
26 | NSString*const kServiceName2 = @"Service2";
27 | double systemVersion = [BNCDevice currentDevice].systemVersion.doubleValue;
28 | NSString*systemName = [BNCDevice currentDevice].systemName;
29 |
30 | // Find a signed bundle:
31 |
32 | NSString*teamID = [BNCApplication currentApplication].teamID;
33 | NSString*bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
34 |
35 | if (teamID.length == 0 || bundleID.length == 0) {
36 | // The app bundle needs to be signed probably.
37 | //XCTAssertTrue(bundleID.length > 0 && teamID.length > 0);
38 | return;
39 | }
40 | NSString*securityGroup = [NSString stringWithFormat:@"%@.%@", teamID, bundleID];
41 | BNCKeyChain*keychain = [[BNCKeyChain alloc] initWithSecurityAccessGroup:securityGroup];
42 |
43 | // Remove and validate gone:
44 |
45 | error = [keychain removeValuesForService:kServiceName key:nil];
46 | if (![systemName isEqualToString:@"mac_OS"] && systemVersion >= 10.0 && systemVersion < 11.0)
47 | { XCTAssertTrue(error == nil || error.code == -34018); }
48 | else
49 | { XCTAssertTrue(error == nil); }
50 |
51 | array = [keychain retrieveKeysWithService:kServiceName error:&error];
52 | XCTAssertTrue(array.count == 0 && error == errSecSuccess);
53 |
54 | // Check some keys:
55 |
56 | value = [keychain retrieveValueForService:kServiceName key:@"key1" error:&error];
57 | XCTAssertTrue(value == nil && error.code == errSecItemNotFound);
58 |
59 | value = [keychain retrieveValueForService:kServiceName key:@"key2" error:&error];
60 | XCTAssertTrue(value == nil && error.code == errSecItemNotFound);
61 |
62 | // Test that local storage works:
63 |
64 | error = [keychain storeValue:@"1xyz123" forService:kServiceName key:@"key1"];
65 | XCTAssertTrue(error == nil);
66 | value = [keychain retrieveValueForService:kServiceName key:@"key1" error:&error];
67 | XCTAssertTrue(error == nil && [value isEqualToString:@"1xyz123"]);
68 |
69 | error = [keychain storeValue:@"2xyz123" forService:kServiceName key:@"key2"];
70 | XCTAssertTrue(error == nil);
71 | value = [keychain retrieveValueForService:kServiceName key:@"key2" error:&error];
72 | XCTAssertTrue(error == nil && [value isEqualToString:@"2xyz123"]);
73 |
74 | error = [keychain storeValue:@"3xyz123" forService:kServiceName2 key:@"key3"];
75 | XCTAssertTrue(error == nil);
76 | value = [keychain retrieveValueForService:kServiceName2 key:@"key3" error:&error];
77 | XCTAssertTrue(error == nil && [value isEqualToString:@"3xyz123"]);
78 |
79 | // Remove by service:
80 |
81 | error = [keychain removeValuesForService:kServiceName key:nil];
82 | value = [keychain retrieveValueForService:kServiceName key:@"key1" error:&error];
83 | XCTAssertTrue(value == nil && error.code == errSecItemNotFound);
84 |
85 | value = [keychain retrieveValueForService:kServiceName key:@"key2" error:&error];
86 | XCTAssertTrue(value == nil && error.code == errSecItemNotFound);
87 |
88 | value = [keychain retrieveValueForService:kServiceName2 key:@"key3" error:&error];
89 | XCTAssertTrue(error == nil && [value isEqualToString:@"3xyz123"]);
90 |
91 | // Check service2 values:
92 |
93 | error = [keychain storeValue:@"4xyz123" forService:kServiceName2 key:@"key4"];
94 | XCTAssertTrue(error == nil);
95 | array1 = [keychain retrieveKeysWithService:kServiceName2 error:&error];
96 | XCTAssertNil(error);
97 | NSSet*s1 = [NSSet setWithArray:array1];
98 | NSSet*s2 = [NSSet setWithArray:@[ @"key3", @"key4" ]];
99 | XCTAssertEqualObjects(s1, s2);
100 | }
101 |
102 | @end
103 |
--------------------------------------------------------------------------------
/BranchTests/BNCUserAgentCollectorTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // BNCUserAgentCollectorTests.m
3 | // Branch-SDK-Tests
4 | //
5 | // Created by Ernest Cho on 8/29/19.
6 | // Copyright © 2019 Branch, Inc. All rights reserved.
7 | //
8 | #import
9 | #import "BNCUserAgentCollector.h"
10 |
11 | // expose private methods for unit testing
12 | @interface BNCUserAgentCollector()
13 |
14 | + (NSString *)userAgentKey;
15 | + (NSString *)systemBuildVersionKey;
16 |
17 | - (NSString *)loadUserAgentForSystemBuildVersion:(NSString *)systemBuildVersion;
18 | - (void)saveUserAgent:(NSString *)userAgent forSystemBuildVersion:(NSString *)systemBuildVersion;
19 |
20 | - (void)loadUserAgentForSystemBuildVersion:(NSString *)systemBuildVersion withCompletion:(void (^)(NSString *userAgent))completion;
21 |
22 | - (void)collectUserAgentWithCompletion:(void (^)(NSString *userAgent))completion;
23 |
24 | @end
25 |
26 | @interface BNCUserAgentCollectorTests : XCTestCase
27 |
28 | @end
29 |
30 | @implementation BNCUserAgentCollectorTests
31 |
32 | + (void)setUp {
33 | [BNCUserAgentCollectorTests resetPersistentData];
34 | }
35 |
36 | - (void)setUp {
37 |
38 | }
39 |
40 | - (void)tearDown {
41 | [BNCUserAgentCollectorTests resetPersistentData];
42 | }
43 |
44 | + (void)resetPersistentData {
45 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
46 | [defaults setObject:nil forKey:[BNCUserAgentCollector userAgentKey]];
47 | [defaults setObject:nil forKey:[BNCUserAgentCollector systemBuildVersionKey]];
48 | }
49 |
50 | - (void)testResetPersistentData {
51 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
52 | NSString *savedUserAgent = (NSString *)[defaults valueForKey:[BNCUserAgentCollector userAgentKey]];
53 | NSString *savedSystemBuildVersion = (NSString *)[defaults valueForKey:[BNCUserAgentCollector systemBuildVersionKey]];
54 |
55 | XCTAssertNil(savedUserAgent);
56 | XCTAssertNil(savedSystemBuildVersion);
57 | }
58 |
59 | - (void)testSaveAndLoadUserAgent {
60 | NSString *systemBuildVersion = @"test";
61 | NSString *userAgent = @"UserAgent";
62 |
63 | BNCUserAgentCollector *collector = [BNCUserAgentCollector new];
64 | [collector saveUserAgent:userAgent forSystemBuildVersion:systemBuildVersion];
65 | NSString *expected = [collector loadUserAgentForSystemBuildVersion:systemBuildVersion];
66 | XCTAssertTrue([userAgent isEqualToString:expected]);
67 | }
68 |
69 | - (void)testCollectUserAgent {
70 | XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"];
71 |
72 | BNCUserAgentCollector *collector = [BNCUserAgentCollector new];
73 | [collector collectUserAgentWithCompletion:^(NSString * _Nullable userAgent) {
74 | XCTAssertNotNil(userAgent);
75 | XCTAssertTrue([userAgent containsString:@"AppleWebKit"]);
76 | [expectation fulfill];
77 | }];
78 |
79 | [self waitForExpectationsWithTimeout:2.0 handler:^(NSError * _Nullable error) {
80 |
81 | }];
82 | }
83 |
84 | - (void)testLoadUserAgent_EmptyDataStore {
85 | XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"];
86 | NSString *systemBuildVersion = @"test";
87 |
88 | BNCUserAgentCollector *collector = [BNCUserAgentCollector new];
89 | [collector loadUserAgentForSystemBuildVersion:systemBuildVersion withCompletion:^(NSString * _Nullable userAgent) {
90 | XCTAssertNotNil(userAgent);
91 | XCTAssertTrue([userAgent containsString:@"AppleWebKit"]);
92 | [expectation fulfill];
93 | }];
94 |
95 | [self waitForExpectationsWithTimeout:2.0 handler:^(NSError * _Nullable error) {
96 |
97 | }];
98 | }
99 |
100 | - (void)testLoadUserAgent_FilledDataStore {
101 | XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"];
102 | NSString *systemBuildVersion = @"test";
103 | NSString *savedUserAgent = @"UserAgent";
104 |
105 | BNCUserAgentCollector *collector = [BNCUserAgentCollector new];
106 | [collector saveUserAgent:savedUserAgent forSystemBuildVersion:systemBuildVersion];
107 | [collector loadUserAgentForSystemBuildVersion:systemBuildVersion withCompletion:^(NSString * _Nullable userAgent) {
108 | XCTAssertNotNil(userAgent);
109 | XCTAssertTrue([userAgent isEqualToString:savedUserAgent]);
110 | XCTAssertFalse([userAgent containsString:@"AppleWebKit"]);
111 | [expectation fulfill];
112 | }];
113 |
114 | [self waitForExpectationsWithTimeout:2.0 handler:^(NSError * _Nullable error) {
115 |
116 | }];
117 | }
118 |
119 | @end
120 |
--------------------------------------------------------------------------------
/Branch/BranchError.m:
--------------------------------------------------------------------------------
1 | /**
2 | @file BranchError.m
3 | @package Branch
4 | @brief Branch errors.
5 |
6 | @author Qinwei Gong
7 | @date November 2014
8 | @copyright Copyright © 2014 Branch. All rights reserved.
9 | */
10 |
11 | #import "BranchError.h"
12 | #import "BNCLocalization.h"
13 |
14 | NSString * const BNCErrorDomain = @"io.branch.sdk.error";
15 |
16 | __attribute__((constructor)) void BNCForceNSErrorCategoryToLoad() {
17 | // Nothing here, but forces linker to load the category.
18 | }
19 |
20 | @implementation NSError (Branch)
21 |
22 | + (NSString*) messageForCode:(BNCErrorCode)code {
23 |
24 | // The order is important!
25 |
26 | static NSString* const messages[] = {
27 |
28 | // BNCInitError
29 | @"The Branch user session has not been initialized.",
30 |
31 | // BNCDuplicateResourceError
32 | @"A resource with this identifier already exists.",
33 |
34 | // BNCRedeemCreditsError
35 | @"You're trying to redeem more credits than are available. Have you loaded rewards?",
36 |
37 | // BNCBadRequestError
38 | @"The network request was invalid.",
39 |
40 | // BNCServerProblemError
41 | @"Trouble reaching the Branch servers, please try again shortly.",
42 |
43 | // BNCNilLogError
44 | @"Can't log error messages because the logger is set to nil.",
45 |
46 | // BNCVersionError
47 | @"Incompatible version.",
48 |
49 | // BNCNetworkServiceInterfaceError
50 | @"The underlying network service does not conform to the BNCNetworkOperationProtocol.",
51 |
52 | // BNCContentIdentifierError
53 | @"A canonical identifier or title are required to uniquely identify content.",
54 |
55 | // BNCSpotlightNotAvailableError
56 | @"The Core Spotlight indexing service is not available on this device.",
57 |
58 | // BNCSpotlightTitleError
59 | @"Spotlight indexing requires a title.",
60 |
61 | // BNCRedeemZeroCreditsError
62 | @"Can't redeem zero credits.",
63 |
64 | // BNCSpotlightIdentifierError
65 | @"The Spotlight identifier is required to remove indexing from spotlight.",
66 |
67 | //BNCSpotlightPublicIndexError
68 | @"Spotlight cannot remove publicly indexed content.",
69 |
70 | //BNCTrackingDisabledError
71 | @"User tracking is disabled."
72 | };
73 |
74 | #define _countof(array) (sizeof(array)/sizeof(array[0]))
75 |
76 | // Sanity check
77 | #pragma clang diagnostic push
78 | #pragma clang diagnostic ignored "-Wunreachable-code"
79 | if (_countof(messages) != (BNCHighestError - BNCInitError)) {
80 | [NSException raise:NSInternalInconsistencyException format:@"Branch error message count is wrong."];
81 | return @"Branch encountered an error.";
82 | }
83 | #pragma clang diagnostic pop
84 |
85 | if (code < BNCInitError || code >= BNCHighestError)
86 | return @"Branch encountered an error.";
87 |
88 | return messages[code - BNCInitError];
89 | }
90 |
91 | + (NSError*_Nonnull) branchErrorWithCode:(BNCErrorCode)errorCode
92 | error:(NSError*)error
93 | localizedMessage:(NSString*_Nullable)message {
94 |
95 | NSMutableDictionary *userInfo = [NSMutableDictionary new];
96 |
97 | NSString *localizedString = BNCLocalizedString([self messageForCode:errorCode]);
98 | if (localizedString) userInfo[NSLocalizedDescriptionKey] = localizedString;
99 | if (message) {
100 | userInfo[NSLocalizedFailureReasonErrorKey] = message;
101 | }
102 | if (error) {
103 | userInfo[NSUnderlyingErrorKey] = error;
104 | if (!userInfo[NSLocalizedFailureReasonErrorKey] && error.localizedDescription)
105 | userInfo[NSLocalizedFailureReasonErrorKey] = error.localizedDescription;
106 | }
107 |
108 | return [NSError errorWithDomain:BNCErrorDomain code:errorCode userInfo:userInfo];
109 | }
110 |
111 | + (NSError*_Nonnull) branchErrorWithCode:(BNCErrorCode)errorCode {
112 | return [NSError branchErrorWithCode:errorCode error:nil localizedMessage:nil];
113 | }
114 |
115 | + (NSError*_Nonnull) branchErrorWithCode:(BNCErrorCode)errorCode error:(NSError*_Nullable)error {
116 | return [NSError branchErrorWithCode:errorCode error:error localizedMessage:nil];
117 | }
118 |
119 | + (NSError*_Nonnull) branchErrorWithCode:(BNCErrorCode)errorCode localizedMessage:(NSString*_Nullable)message {
120 | return [NSError branchErrorWithCode:errorCode error:nil localizedMessage:message];
121 | }
122 |
123 | @end
124 |
--------------------------------------------------------------------------------