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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Swift Package Manager / Xcode build output
.build/
DerivedData/
*.xcuserstate
xcuserdata/

# Credentials — never commit real keys (see Secrets.example.swift)
examples/swiftui/SwiftUIUploadExample/Secrets.swift
11 changes: 11 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# FastPix iOS Uploads — Examples

Standalone example apps for the [FastPix iOS Uploads SDK](../). Each folder is a
self-contained Xcode project — copy one and run it.

| Example | UI | Picks from | Notes |
|---------|-----|-----------|-------|
| [`uikit/`](uikit) | UIKit | Files (paste a signed URL) | Original example. |
| [`swiftui/`](swiftui) | SwiftUI | Photos | Mints the upload URL in-app; best-effort background upload. |

Both do chunked upload with live progress and pause / resume / cancel.
55 changes: 55 additions & 0 deletions examples/swiftui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# FastPix iOS Uploads — SwiftUI Example

A minimal **SwiftUI** app that mints a signed upload URL from FastPix, picks a
video, and chunk-uploads it with live progress and **pause / resume / cancel**.
Upload state is driven by an `ObservableObject` (`UploadManager`).

This is separate from the UIKit example in [`../uikit`](../uikit).

## Run it

1. **Add your credentials.** Copy the template and paste a token + secret key
(Dashboard → Settings → Access Tokens):

```bash
cd examples/swiftui/SwiftUIUploadExample
cp Secrets.example.swift Secrets.swift # Secrets.swift is gitignored
```

2. **Open and run:**

```bash
open examples/swiftui/SwiftUIUploadExample.xcodeproj
```

Pick the `SwiftUIUploadExample` scheme + a simulator (or your device, with a
signing team set), then ⌘R. The project references the SDK locally (`../..`),
so it builds against the code in this repo.

3. Tap **Choose Video…**, pick a clip. The app calls create-upload, then uploads.
Watch the progress bar and event log; use **Pause / Resume / Cancel**.

## What "background upload" means here

Tap upload, then background the app — it keeps uploading for the short window
iOS grants (`beginBackgroundTask`), typically tens of seconds to a couple of
minutes, then iOS suspends it.

**Why not longer, like the Android example?** Android has a *foreground service*
that keeps your process running while backgrounded. iOS has no equivalent — it
suspends your process within seconds. The only way a large transfer truly
survives suspension is a **background `URLSession`** (`URLSessionConfiguration.background`),
where a system daemon does the transfer. That has to be configured *inside* the
SDK (it currently uses `URLSessionConfiguration.default`), and a background
session can't upload in-memory `Data` chunks the way this SDK does — so it's an
SDK change, out of scope for an example. This app does the honest best-effort:
`beginBackgroundTask` around the active upload.

## Files

- `UploadExampleApp.swift` — `@main` app, owns the `UploadManager`.
- `ContentView.swift` — the screen: pick, progress, pause/resume/cancel, log.
- `UploadManager.swift` — `ObservableObject` bridging SDK delegates → `@Published`
state; holds the `beginBackgroundTask` assertion.
- `FastPixAPI.swift` — the create-upload POST call.
- `Secrets.swift` — your credentials (gitignored).
304 changes: 304 additions & 0 deletions examples/swiftui/SwiftUIUploadExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objects = {

/* Begin PBXBuildFile section */
1B0000000000000000000001 /* UploadExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0000000000000000000001 /* UploadExampleApp.swift */; };
1B0000000000000000000002 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0000000000000000000002 /* ContentView.swift */; };
1B0000000000000000000003 /* UploadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0000000000000000000003 /* UploadManager.swift */; };
1B0000000000000000000004 /* FastPixAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0000000000000000000004 /* FastPixAPI.swift */; };
1B0000000000000000000005 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0000000000000000000005 /* Secrets.swift */; };
1B0000000000000000000006 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A0000000000000000000006 /* Assets.xcassets */; };
1B0000000000000000000010 /* fp-swift-upload-sdk in Frameworks */ = {isa = PBXBuildFile; productRef = 7A0000000000000000000002 /* fp-swift-upload-sdk */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
1A0000000000000000000001 /* UploadExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadExampleApp.swift; sourceTree = "<group>"; };
1A0000000000000000000002 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
1A0000000000000000000003 /* UploadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadManager.swift; sourceTree = "<group>"; };
1A0000000000000000000004 /* FastPixAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FastPixAPI.swift; sourceTree = "<group>"; };
1A0000000000000000000005 /* Secrets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = "<group>"; };
1A0000000000000000000006 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
1A0000000000000000000007 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1A0000000000000000000008 /* Secrets.example.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Secrets.example.swift; sourceTree = "<group>"; };
1A0000000000000000000009 /* SwiftUIUploadExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUIUploadExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
3A0000000000000000000002 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1B0000000000000000000010 /* fp-swift-upload-sdk in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
2A0000000000000000000001 = {
isa = PBXGroup;
children = (
2A0000000000000000000002 /* SwiftUIUploadExample */,
2A0000000000000000000003 /* Products */,
2A0000000000000000000004 /* Frameworks */,
);
sourceTree = "<group>";
};
2A0000000000000000000002 /* SwiftUIUploadExample */ = {
isa = PBXGroup;
children = (
1A0000000000000000000001 /* UploadExampleApp.swift */,
1A0000000000000000000002 /* ContentView.swift */,
1A0000000000000000000003 /* UploadManager.swift */,
1A0000000000000000000004 /* FastPixAPI.swift */,
1A0000000000000000000005 /* Secrets.swift */,
1A0000000000000000000008 /* Secrets.example.swift */,
1A0000000000000000000006 /* Assets.xcassets */,
1A0000000000000000000007 /* Info.plist */,
);
path = SwiftUIUploadExample;
sourceTree = "<group>";
};
2A0000000000000000000003 /* Products */ = {
isa = PBXGroup;
children = (
1A0000000000000000000009 /* SwiftUIUploadExample.app */,
);
name = Products;
sourceTree = "<group>";
};
2A0000000000000000000004 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
4A0000000000000000000001 /* SwiftUIUploadExample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5A0000000000000000000002 /* Build configuration list for PBXNativeTarget "SwiftUIUploadExample" */;
buildPhases = (
3A0000000000000000000001 /* Sources */,
3A0000000000000000000002 /* Frameworks */,
3A0000000000000000000003 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = SwiftUIUploadExample;
packageProductDependencies = (
7A0000000000000000000002 /* fp-swift-upload-sdk */,
);
productName = SwiftUIUploadExample;
productReference = 1A0000000000000000000009 /* SwiftUIUploadExample.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
4A0000000000000000000002 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1620;
LastUpgradeCheck = 1620;
TargetAttributes = {
4A0000000000000000000001 = {
CreatedOnToolsVersion = 16.2;
};
};
};
buildConfigurationList = 5A0000000000000000000001 /* Build configuration list for PBXProject "SwiftUIUploadExample" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 2A0000000000000000000001;
packageReferences = (
7A0000000000000000000001 /* XCLocalSwiftPackageReference "iOS-Uploads" */,
);
productRefGroup = 2A0000000000000000000003 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
4A0000000000000000000001 /* SwiftUIUploadExample */,
);
};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
3A0000000000000000000003 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1B0000000000000000000006 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
3A0000000000000000000001 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1B0000000000000000000001 /* UploadExampleApp.swift in Sources */,
1B0000000000000000000002 /* ContentView.swift in Sources */,
1B0000000000000000000003 /* UploadManager.swift in Sources */,
1B0000000000000000000004 /* FastPixAPI.swift in Sources */,
1B0000000000000000000005 /* Secrets.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */

/* Begin XCBuildConfiguration section */
6A0000000000000000000001 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
6A0000000000000000000002 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
6A0000000000000000000003 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = TRG6Q7877U;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = SwiftUIUploadExample/Info.plist;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.fastpix.SwiftUIUploadExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6A0000000000000000000004 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = TRG6Q7877U;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = SwiftUIUploadExample/Info.plist;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.fastpix.SwiftUIUploadExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
5A0000000000000000000001 /* Build configuration list for PBXProject "SwiftUIUploadExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6A0000000000000000000001 /* Debug */,
6A0000000000000000000002 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5A0000000000000000000002 /* Build configuration list for PBXNativeTarget "SwiftUIUploadExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6A0000000000000000000003 /* Debug */,
6A0000000000000000000004 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */

/* Begin XCLocalSwiftPackageReference section */
7A0000000000000000000001 /* XCLocalSwiftPackageReference "iOS-Uploads" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = ../..;
};
/* End XCLocalSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
7A0000000000000000000002 /* fp-swift-upload-sdk */ = {
isa = XCSwiftPackageProductDependency;
productName = "fp-swift-upload-sdk";
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 4A0000000000000000000002 /* Project object */;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"colors" : [ { "idiom" : "universal" } ],
"info" : { "author" : "xcode", "version" : 1 }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"images" : [ { "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" } ],
"info" : { "author" : "xcode", "version" : 1 }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"info" : { "author" : "xcode", "version" : 1 }
}
Loading