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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/ios-sdk-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
jobs:
sdk-tests:
name: "SDK Tests"
runs-on: macos-15
runs-on: xcode-27
steps:
- name: Checkout Code
uses: actions/checkout@v5
Expand All @@ -30,7 +30,7 @@ jobs:

build-demo-swift:
name: "Build Demo Swift"
runs-on: macos-15
runs-on: xcode-27
needs: [sdk-tests]
steps:
- name: Checkout Code
Expand Down Expand Up @@ -58,13 +58,13 @@ jobs:

build-demo-objc:
name: "Build Demo Objective-C"
runs-on: macos-15
runs-on: xcode-27
env:
FL_OUTPUT_DIR: output
needs: [sdk-tests]
steps:
- name: Checkout Code
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Bundle install
uses: ruby/setup-ruby@v1
with:
Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:
steps:
- name: Successful Release Post to Slack
uses: slackapi/slack-github-action@v2.1.1
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && needs.build-demo-swift.result == 'success' && needs.build-demo-swift.result == 'success' }}
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && needs.build-demo-swift.result == 'success' && needs.build-demo-objc.result == 'success' }}
with:
method: chat.postMessage
token: "${{ secrets.SLACK_MESSENGER_APP_TOKEN }}"
Expand All @@ -117,7 +117,7 @@ jobs:
text: ":white_check_mark: *iOS SDK release:*\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
- name: Build failure Post to Slack
uses: slackapi/slack-github-action@v2.1.1
if: ${{ github.event_name == 'pull_request' && (needs.build-demo-swift.result != 'success' || needs.build-demo-swift.result != 'success')}}
if: ${{ github.event_name == 'pull_request' && (needs.build-demo-swift.result != 'success' || needs.build-demo-objc.result != 'success')}}
with:
method: chat.postMessage
token: "${{ secrets.SLACK_MESSENGER_APP_TOKEN }}"
Expand Down
2 changes: 1 addition & 1 deletion OptableSDK.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Pod::Spec.new do |spec|
spec.author = { "Optable Technologies Inc" => "support@optable.co" }

spec.platform = :ios
spec.ios.deployment_target = "12.0"
spec.ios.deployment_target = "15.0"
spec.swift_version = "5.0"

spec.source = { :git => "https://github.com/Optable/optable-ios-sdk.git", :tag => "#{spec.version}" }
Expand Down
12 changes: 6 additions & 6 deletions OptableSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
Expand Down Expand Up @@ -347,7 +347,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
Expand All @@ -374,7 +374,7 @@
ENABLE_MODULE_VERIFIER = YES;
INFOPLIST_FILE = Source/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -407,7 +407,7 @@
ENABLE_MODULE_VERIFIER = YES;
INFOPLIST_FILE = Source/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -431,7 +431,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -452,7 +452,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// swift-tools-version:5.3
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "OptableSDK",
platforms: [.iOS(.v12)],
platforms: [.iOS(.v15)],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
Expand Down
25 changes: 5 additions & 20 deletions Source/Core/EdgeAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,25 +118,8 @@ extension EdgeAPI {
completionHandler(data, response, error)
return
}
if #available(iOS 13.0, *) {
if let passport = res.value(forHTTPHeaderField: self.kPassportHeader) {
self.storage.setPassport(passport)
}
} else {
// In older versions of iOS, we have to resort searching through headers via res.allHeaderFields
// Unlike res.value(forHTTPHeaderField:...) which was introduced in iOS 13.0, allHeaderFields is
// case-sensitive, so we need to take special care to perform a case-INsensitive search:
for (key, value) in res.allHeaderFields {
if let header = key as? String {
let result: ComparisonResult = header.compare(self.kPassportHeader, options: NSString.CompareOptions.caseInsensitive)
if result == .orderedSame {
if let pp = value as? String {
self.storage.setPassport(pp)
break
}
}
}
}
if let passport = res.value(forHTTPHeaderField: self.kPassportHeader) {
self.storage.setPassport(passport)
}
completionHandler(data, response, error)
}
Expand All @@ -148,7 +131,9 @@ extension EdgeAPI {
private func resolveUserAgent(callback: @escaping (_ useragent: String) -> Void) {
var wkUserAgent = ""
let myGroup = DispatchGroup()
let window = UIApplication.shared.keyWindow
let window = UIApplication.shared.connectedScenes
.compactMap { ($0 as? UIWindowScene)?.keyWindow }
.first
let webView = WKWebView(frame: UIScreen.main.bounds)

webView.isHidden = true
Expand Down
29 changes: 5 additions & 24 deletions Source/Core/OptableIdentifierEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
// Copyright © 2026 Optable Technologies, Inc. All rights reserved.
//

import CommonCrypto
import CryptoKit
import Foundation
#if canImport(CryptoKit)
import CryptoKit
#endif

// MARK: - OptableIdentifierEncoder
enum OptableIdentifierEncoder {
Expand Down Expand Up @@ -196,25 +193,9 @@ enum OptableIdentifierEncoder {
}

private static func sha256(data: Data) -> String {
#if canImport(CryptoKit)
if #available(iOS 13.0, *) {
return SHA256
.hash(data: data)
.compactMap({ String(format: "%02x", $0) })
.joined()
}
#endif

return cchash(data)
}

private static func cchash(_ input: Data) -> String {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
input.withUnsafeBytes { bytes in
_ = CC_SHA256(bytes.baseAddress, CC_LONG(input.count), &digest)
}
return digest.makeIterator().compactMap {
String(format: "%02x", $0)
}.joined()
SHA256
.hash(data: data)
.compactMap({ String(format: "%02x", $0) })
.joined()
}
}
123 changes: 8 additions & 115 deletions Source/Misc/AppTrackingTransparency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
#if canImport(AdSupport)

import AdSupport

#if canImport(AppTrackingTransparency)
import AppTrackingTransparency
#endif

import AppTrackingTransparency
import Foundation

enum ATT {
Expand All @@ -29,21 +25,6 @@
}
#endif

// MARK: isAdvertisingTrackingEnabled

#if DEBUG
@available(iOS, introduced: 6, deprecated: 14,
message: "Replaced by ATTrackingManager in AppTrackingTransparency.")
static var isAdvertisingTrackingEnabled_DebugOverride: Bool?
static var isAdvertisingTrackingEnabled: Bool {
isAdvertisingTrackingEnabled_DebugOverride ?? ASIdentifierManager.shared().isAdvertisingTrackingEnabled
}
#else
static var isAdvertisingTrackingEnabled: Bool {
ASIdentifierManager.shared().isAdvertisingTrackingEnabled
}
#endif

// MARK: advertisingIdentifierAvailable

#if DEBUG
Expand All @@ -57,110 +38,22 @@
}
#endif

#if canImport(AppTrackingTransparency)
if #available(iOS 14, *) {
return trackingStatus == .authorized
} else {
return isAdvertisingTrackingEnabled
}
#else
return isAdvertisingTrackingEnabled
#endif
return trackingStatus == .authorized
}

// MARK: attAvailable
// MARK: trackingStatus

#if DEBUG
static var attAvailable_DebugOverride: Bool?
static var trackingStatus_DebugOverride: ATTrackingManager.AuthorizationStatus?
#endif

static var attAvailable: Bool {
static var trackingStatus: ATTrackingManager.AuthorizationStatus {
#if DEBUG
if let override = attAvailable_DebugOverride {
return override
}
return trackingStatus_DebugOverride ?? ATTrackingManager.trackingAuthorizationStatus
#else
return ATTrackingManager.trackingAuthorizationStatus
#endif

if #available(iOS 14, *) {
return true
} else {
return false
}
}

#if canImport(AppTrackingTransparency)

// MARK: canAuthorize

#if DEBUG
@available(iOS 14, *)
static var canAuthorize_DebugOverride: Bool?
#endif

static var canAuthorize: Bool {
if #available(iOS 14, *) {
#if DEBUG
if let override = canAuthorize_DebugOverride {
return override
}
#endif

return ATTrackingManager.trackingAuthorizationStatus == .notDetermined
} else {
return false
}
}

// MARK: trackingStatus

#if DEBUG
@available(iOS 14, *)
static var trackingStatus_DebugOverride: ATTrackingManager.AuthorizationStatus?
#endif

@available(iOS 14, *)
static var trackingStatus: ATTrackingManager.AuthorizationStatus {
#if DEBUG
return trackingStatus_DebugOverride ?? ATTrackingManager.trackingAuthorizationStatus
#else
return ATTrackingManager.trackingAuthorizationStatus
#endif
}

// MARK: RequestAuthorization

@available(iOS 14, *)
static func requestATTAuthorization(completion: ((Bool) -> Void)? = nil) {
#if DEBUG
if let override = trackingStatus_DebugOverride {
completion?(override == .authorized)
return
}
#endif

ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .authorized:
completion?(true)
case .denied, .notDetermined, .restricted:
completion?(false)
@unknown default:
completion?(true)
}
}
}

@available(iOS 14, *)
@discardableResult
static func requestATTAuthorization() async -> Bool {
await withCheckedContinuation { continuation in
requestATTAuthorization { isAuthorized in
continuation.resume(returning: isAuthorized)
}
}
}

#endif
}

#endif
22 changes: 0 additions & 22 deletions Source/Misc/RangeReplaceableCollection+Compat.swift

This file was deleted.

Loading
Loading