{"id":21214791,"url":"https://github.com/filestack/filestack-ios","last_synced_at":"2025-07-10T10:30:43.504Z","repository":{"id":56911233,"uuid":"49502174","full_name":"filestack/filestack-ios","owner":"filestack","description":"Official iOS SDK for Filestack - API and content management system that makes it easy to add powerful file uploading and transformation capabilities to any web or mobile application.","archived":false,"fork":false,"pushed_at":"2024-04-24T06:08:45.000Z","size":13751,"stargazers_count":53,"open_issues_count":9,"forks_count":35,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-04-25T04:46:21.764Z","etag":null,"topics":["carthage","cloud-providers","files","filestack","filestack-ios-sdk","picker","upload","uploader","xcode"],"latest_commit_sha":null,"homepage":"https://www.filestack.com","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/filestack.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-12T13:36:58.000Z","updated_at":"2024-06-11T06:44:38.876Z","dependencies_parsed_at":"2024-06-11T06:44:31.330Z","dependency_job_id":"10fbb23b-5c78-40b5-9b02-c22d17d72b9c","html_url":"https://github.com/filestack/filestack-ios","commit_stats":{"total_commits":340,"total_committers":6,"mean_commits":"56.666666666666664","dds":0.2147058823529412,"last_synced_commit":"6a62b5193567e3b0c7847aa335c53d3e4e304c84"},"previous_names":[],"tags_count":68,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filestack%2Ffilestack-ios","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filestack%2Ffilestack-ios/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filestack%2Ffilestack-ios/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filestack%2Ffilestack-ios/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/filestack","download_url":"https://codeload.github.com/filestack/filestack-ios/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225632846,"owners_count":17499874,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["carthage","cloud-providers","files","filestack","filestack-ios-sdk","picker","upload","uploader","xcode"],"created_at":"2024-11-20T21:31:01.243Z","updated_at":"2025-07-10T10:30:43.489Z","avatar_url":"https://github.com/filestack.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Filestack iOS SDK\n\n\u003ca href=\"https://www.filestack.com\"\u003e\u003cimg src=\"https://www.filestack.com/docs/images/fs-logo-dark.svg\" align=\"left\" hspace=\"10\" vspace=\"6\"\u003e\u003c/a\u003e\nThis is the official Swift iOS for Filestack — API and content management system that makes it easy to add powerful file uploading and transformation capabilities to any web or mobile application.\n\n## Resources\n\n* [Filestack](https://www.filestack.com)\n* [Documentation](https://www.filestack.com/docs)\n* [API Reference](https://filestack.github.io/filestack-ios/)\n\n## Requirements\n\n* Xcode 11+ (*Xcode 12+ required for SPM support*)\n* Swift 4.2+ / Objective-C\n* iOS 14.0+\n\n## Installing\n\n### CocoaPods\n\n[CocoaPods](http://cocoapods.org/) is a dependency manager for Cocoa projects. You can install it with the following command:\n\n`$ gem install cocoapods`\n\nTo integrate Filestack into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n```\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '14.0'\nuse_frameworks!\n\ntarget '\u003cYour Target Name\u003e' do\n    pod 'Filestack', '~\u003e 3.0.1'\nend\n```\n\nThen, run the following command:\n\n`$ pod install`\n\n### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.\n\nYou can install Carthage with [Homebrew](http://brew.sh/) using the following command:\n\n```\n$ brew update\n$ brew install carthage\n```\n\nTo integrate Filestack into your Xcode project using Carthage, specify it in your `Cartfile`:\n\n`github \"filestack/filestack-ios\" ~\u003e 3.0.1`\n\nRun `carthage update` to build the framework and drag the built `Filestack.framework` into your Xcode project. Additionally, add `Filestack.framework`, `FilestackSDK.framework`, and `ZIPFoundation.framework` to the embedded frameworks build phase of your app's target.\n\n### Swift Package Manager\n\nAdd `https://github.com/filestack/filestack-ios.git` as a [Swift Package Manager](https://swift.org/package-manager/) dependency to your Xcode project.\n\nAlternatively, if you are adding `Filestack` to your own Swift Package, declare the dependency in your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(name: \"Filestack\", url: \"https://github.com/filestack/filestack-ios.git\", .upToNextMajor(from: \"3.0.1\"))\n]\n```\n\n### Manually\n\n#### Embedded Framework\n\nOpen up Terminal, cd into your top-level project directory, and run the following command \"if\" your project is not initialized as a git repository:\n\n`$ git init`\n\nAdd Filestack and its dependencies as git submodules by running the following commands:\n\n```shell\n$ git submodule add https://github.com/filestack/filestack-ios.git\n$ git submodule add https://github.com/filestack/filestack-swift.git\n$ git submodule add https://github.com/weichsel/ZIPFoundation.git\n```\n\nOpen the new `filestack-ios` folder, and drag the `Filestack.xcodeproj` into the Project Navigator of your application's Xcode project.\n\nIt should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.\nSelect the `Filestack.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.\n\nNext, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the \"Targets\" heading in the sidebar.\n\nIn the tab bar at the top of that window, open the \"General\" panel.\n\nClick on the + button under the \"Embedded Binaries\" section and choose the `Filestack.framework` for iOS.\n\nRepeat the same process for adding `FilestackSDK`, and `ZIPFoundation` dependent frameworks.\n\n## Usage\n\n### Importing required frameworks\n\nAny source files that need to use the Filestack iOS SDK should import the `Filestack` and `FilestackSDK` frameworks:\n\n```swift\nimport Filestack\nimport FilestackSDK\n```\n\n### Instantiating a Filestack object\n\n```swift\n// Initialize a `Policy` with the expiry time and permissions you need.\nlet oneDayInSeconds: TimeInterval = 60 * 60 * 24 // expires tomorrow\nlet policy = Policy(// Set your expiry time (24 hours in our case)\n                    expiry: Date(timeIntervalSinceNow: oneDayInSeconds),\n                    // Set the permissions you want your policy to have\n                    call: [.pick, .read, .store])\n\n// Initialize a `Security` object by providing a `Policy` object and your app secret.\n// You can find and/or enable your app secret in the Developer Portal.\nguard let security = try? Security(policy: policy, appSecret: \"YOUR-APP-SECRET\") else {\n    return\n}\n\n// Create `Config` object.\nlet config = Filestack.Config()\n\n// Make sure to assign a callback URL scheme that is handled by your app.\nconfig.callbackURLScheme = \"filestackdemo\"\n\nlet client = Filestack.Client(apiKey: \"YOUR-API-KEY\", security: security, config: config)\n```\n\n### Uploading files programmatically\n\n```swift\nlet localURL = URL(string: \"file:///an-app-sandbox-friendly-local-url\")!\n\nlet uploader = client.upload(using: localURL, uploadProgress: { (progress) in\n    // Here you may update the UI to reflect the upload progress.\n    print(\"progress = \\(String(describing: progress))\")\n}) { (response) in\n    // Try to obtain Filestack handle\n    if let json = response?.json, let handle = json[\"handle\"] as? String {\n        // Use Filestack handle\n    } else if let error = response?.error {\n        // Handle error\n    }\n}\n```\n\n### Uploading files interactively from the Camera, Photo Library, or Documents\n\n```swift\n// The view controller that will be presenting the image picker.\nlet presentingViewController = self\n\n// The source type (e.g. `.camera`, `.photoLibrary`, or `.documents`)\nlet sourceType: LocalSource = .camera\n\n// Upload options for any uploaded files.\nlet uploadOptions: UploadOptions = .defaults\n\n// Store options for any uploaded files. Public access only available for the custom s3 storage.\nuploadOptions.storeOptions = StorageOptions(location: .s3, access: .private)\n\nlet behavior = .uploadAndStore(uploadOptions: uploadOptions)\n\nlet uploader = client.pickFiles(using: presentingViewController,\n                                source: sourceType,\n                                behavior: behavior,\n                                pickCompletionHandler: { (urls) in\n    // Copy, move, or access the contents of the returned files at this point while they are still available.\n    // Once this closure call returns, all the files will be automatically removed.\n}) { (responses) in\n    for response in responses {\n        // Try to obtain Filestack handle\n        if let json = response?.json, let handle = json[\"handle\"] as? String {\n            // Use Filestack handle\n        } else if let error = response?.error {\n            // Handle error\n        }\n    }\n}\n\n// OPTIONAL: Monitor upload progress.\nlet uploadObserver = uploader.progress.observe(\\.fractionCompleted, options: [.new]) { (progress, change) in\n    // TODO: Use `progress` or `change` objects.\n})\n```\n\nIn all the previous uploading examples, an upload may be cancelled at anytime by calling `cancel()` on the `Uploader`:\n\n```swift\nuploader.cancel()\n```\n\n### Listing contents from a cloud provider\n\n```swift\nclient.folderList(provider: .googleDrive, path: \"/\", pageToken: nil) { response in\n    if let error = response.error {\n        // Handle error\n        return\n    }\n\n    if let contents = response.contents {\n        // Contents received — do something with them.\n        print(\"Received \\(contents.count) entries.\")\n    }\n\n    if let nextToken = response.nextToken {\n    \t // More contents are available — to retrieve next page, pass this `nextToken` as a parameter in the `folderList` function.\n    } else {\n    \t // No more contents available — we are done.\n    }\n}\n```\n\n### Storing contents from a cloud provider into a store location\n\n```swift\n// Store options for your uploaded files.\n// Here we are saying our storage location is S3. Public access only available for the custom s3 storage.\nlet storeOptions = StorageOptions(location: .s3, access: .private)\n\nclient.store(provider: .googleDrive, path: \"/some-large-image.jpg\", storeOptions: storeOptions) { (response) in\n    if let error = response.error {\n        // Handle error\n        return\n    }\n\n    if let contents = response.contents {\n        // Contents received describing the request's result.\n    }\n}\n```\n\nPlease make sure to authenticate against the cloud provider first by using the `folderList` function before calling `store`.\n\n\n### Launching picker UI\n\nThis is a code fragment broken into pieces taken from the demo app (included in this repository) describing the process of launching the picker UI using some of the most relevant config options:\n\n#### 1. Setting up Policy and Security objects\n\n```swift\n// In case your Filestack account has security enabled, you will need to instantiate a `Security` object.\n// We can do this by either configuring a `Policy` and instantiating a `Security` object by passing\n// the `Policy` and an `appSecret`, or by instantiating a `Security` object directly by passing an already\n// encoded policy together with its corresponding signature — in this example, we will use the 1st method.\n\n// Create `Policy` object with an expiry time and call permissions.\nlet policy = Policy(expiry: .distantFuture,\n                    call: [.pick, .read, .stat, .write, .writeURL, .store, .convert, .remove, .exif])\n\n// Create `Security` object based on our previously created `Policy` object and app secret obtained from\n// https://dev.filestack.com/.\nguard let security = try? Security(policy: policy, appSecret: \"YOUR-APP-SECRET-HERE\") else {\n    fatalError(\"Unable to instantiate Security object.\")\n}\n```\n\n#### 2. Setting up Config object\n\n```swift\n// Create `Config` object.\n// IMPORTANT: - Make sure to assign an app scheme URL that matches the one(s) configured in your info.plist\nlet config = Filestack.Config.builder\n  .with(callbackURLScheme: \"YOUR-APP-URL-SCHEME\")\n  .with(videoQuality: .typeHigh)\n  .with(imageURLExportPreset: .current)\n  .with(maximumSelectionLimit: 10)\n  .withEditorEnabled()\n  .with(availableCloudSources: [.dropbox, .googledrive, .googlephotos, .customSource])\n  .with(availableLocalSources: [.camera])\n  .build()\n```\n\n#### 3. Setting up Client object\n\n```swift\n// Instantiate the Filestack `Client` by passing an API key obtained from https://dev.filestack.com/,\n// together with a `Security` and `Config` object.\n// If your account does not have security enabled, then you can omit this parameter or set it to `nil`.\nlet client = Filestack.Client(apiKey: \"YOUR-API-KEY-HERE\", security: security, config: config)\n```\n\n#### 4. Instantiating the picker with custom storage options\n\n```swift\n// Store options for your uploaded files.\n// Here we are saying our storage location is S3. Public access only available for the custom s3 storage.\nlet storeOptions = StorageOptions(location: .s3, access: .private)\n\n// Instantiate picker by passing the `StorageOptions` object we just set up.\nlet picker = client.picker(storeOptions: storeOptions)\n```\n\n#### 5. *(Optional)* Setting picking behavior\n\n##### Upload and Store Behavior\n\n```swift\n/// After finishing picking, local files are uploaded and cloud files are stored at the store destination.\npicker.behavior = .uploadAndStore(uploadOptions: .defaults)\n```\n##### Store Only Behavior\n\n```swift\n/// After finishing picking, only cloud files are stored at the store destination.\npicker.behavior = .storeOnly\n```\n\n#### 6. Setting the picker's delegate\n\n```swift\n// Optional. Set the picker's delegate.\npicker.pickerDelegate = self\n```\n\nAnd implement the `PickerNavigationControllerDelegate` protocol in your view controller, i.e.:\n\n```swift\nextension ViewController: PickerNavigationControllerDelegate {\n    /// Called when the picker finishes picking files originating from the local device.\n    func pickerPickedFiles(picker: PickerNavigationController, fileURLs: [URL]) {\n        switch picker.behavior {\n        case .storeOnly:\n            // IMPORTANT: Copy, move, or access the contents of the returned files at this point while they are still available.\n            // Once this delegate function call returns, all the files will be automatically removed.\n\n            // Dismiss the picker since we have finished picking files from the local device, and, in `storeOnly` mode,\n            // there's no upload phase.\n            DispatchQueue.main.async {\n                picker.dismiss(animated: true) {\n                    self.presentAlert(titled: \"Success\", message: \"Finished picking files: \\(fileURLs)\")\n                }\n            }\n        case let .uploadAndStore(uploadOptions):\n            // TODO: Handle this case.\n            break\n        default:\n            break\n        }\n    }\n\n    /// Called when the picker finishes storing a file originating from a cloud source into the destination storage location.\n    func pickerStoredFile(picker: PickerNavigationController, response: StoreResponse) {\n        if let contents = response.contents {\n            // Our cloud file was stored into the destination location.\n            print(\"Stored file response: \\(contents)\")\n        } else if let error = response.error {\n            // The store operation failed.\n            print(\"Error storing file: \\(error)\")\n        }\n    }\n\n    /// Called when the picker finishes uploading a file originating from the local device into the destination storage location.\n    func pickerUploadedFile(picker: PickerNavigationController, response: JSONResponse?) {\n        if let contents = response?.json {\n            // Our local file was stored into the destination location.\n            print(\"Uploaded file response: \\(contents)\")\n        } else if let error = response?.error {\n            // The upload operation failed.\n            print(\"Error uploading file: \\(error)\")\n        }\n    }\n\n    /// Called when the picker reports progress during a file or set of files being uploaded.\n    func pickerReportedUploadProgress(picker: PickerNavigationController, progress: Float) {\n        print(\"Picker \\(picker) reported upload progress: \\(progress)\")\n    }\n}\n```\n\n#### 7. Presenting the picker on the screen\n\n```swift\nyourViewController.present(picker, animated: true)\n```\n\n#### 8. (*Optional*) Enabling background upload support\n\nStarting in Filestack SDK `2.3`, background upload support is available. In order to use it in `Filestack` for file uploads, simply add the following to your code:\n\n```swift\n// Set `UploadService.shared.useBackgroundSession` to true to allow uploads in the background.\nFilestackSDK.UploadService.shared.useBackgroundSession = true\n```\n\n#### 9. (*Optional*) Implementing custom picker sources\n\nStarting in Filestack iOS SDK `2.8.0`, SDK users can add their own custom source implementations by following these steps:\n\n1. Create a new view controller that inherits from `UIViewController` and implements `SourceProvider`: \n\n    ```swift\n    class MyCustomSourceProvider: UIViewController, SourceProvider {\n        // 1. Add `sourceProviderDelegate`\n        weak var sourceProviderDelegate: SourceProviderDelegate?\n        \n        // 2. Add initializer.\n        init() {\n            // TODO: Implement initializer.\n        }\n        \n        // 3. Call this function whenever you want to start uploading files. \n        // These should be passed to the source provider delegate as an array of locally stored URLs.\n        @objc func upload() {\n            let urls = Array(urls)\n\n            dismiss(animated: true) {\n                self.sourceProviderDelegate?.sourceProviderPicked(urls: urls)\n            }\n        }\n\n        // 4. Call this function whenever you want to dismiss your source provider without uploading. \n        @objc func cancel() {\n            dismiss(animated: true) {\n                self.sourceProviderDelegate?.sourceProviderCancelled()\n            }\n        }\n        \n        // TODO: Continue implementing your view controller.\n    }        \n    ```\n    \n2. Set up your custom source:\n\n    ```swift\n    /// Returns a custom `LocalSource` configured to use an user-provided `SourceProvider`.\n    func customLocalSource() -\u003e LocalSource {\n        // Instantiate your source provider\n        let customProvider = MyCustomSourceProvider()\n        \n        // Optional. Configure your `customProvider` object\n        customProvider.urls = [url1, url2, url3]\n\n        // Define your custom source\n        let customSource = LocalSource.custom(\n            description: \"Custom Source\",\n            image: UIImage(named: \"icon-custom-source\")!,\n            provider: customProvider\n        )\n\n        // Return your custom source\n        return customSource\n    }\n    ```\n    \n3. Pass your custom source to your `Config` object:\n\n    - Using `Filestack.Config.builder`:\n        ```swift\n        .with(availableLocalSources: [.camera, .photoLibrary, .documents, customLocalSource()])\n        ``` \n    - Using `Filestack.Config` directly:\n        ```swift\n        config.availableLocalSources = [.camera, .photoLibrary, .documents, customLocalSource()]\n        ```\n\n## Demo\n\nCheck the demo app included in this repository showcasing all the topics discussed above.\n\n## Versioning\n\nFilestack iOS SDK follows the [Semantic Versioning](http://semver.org/).\n\n## Issues\n\nIf you have problems, please create a [Github Issue](https://github.com/filestack/filestack-ios/issues).\n\n## Contributing\n\nPlease see [CONTRIBUTING.md](https://github.com/filestack/filestack-ios/blob/master/CONTRIBUTING.md) for details.\n\n## Credits\n\nThank you to all the [contributors](https://github.com/filestack/filestack-ios/graphs/contributors).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilestack%2Ffilestack-ios","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffilestack%2Ffilestack-ios","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilestack%2Ffilestack-ios/lists"}