diff --git a/.cursor/rules/cloudinary.mdc b/.cursor/rules/cloudinary.mdc new file mode 100644 index 00000000..aff03d7b --- /dev/null +++ b/.cursor/rules/cloudinary.mdc @@ -0,0 +1,8 @@ +--- +description: Cloudinary cloudinary_ios — agent guide +alwaysApply: true +--- + +Read and follow `AGENTS.md` in the repository root. It is the single +authoritative guide for this package: build/test commands, conventions, +gotchas, and when to use this SDK versus a sibling Cloudinary package. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..9fa7dd12 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,5 @@ +# Cloudinary cloudinary_ios — instructions for AI coding agents + +Read `AGENTS.md` in the repository root and follow it. It is the single +authoritative guide for this package: build/test commands, conventions, +gotchas, and when to use this SDK versus a sibling Cloudinary package. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..327ca097 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,105 @@ + + +# AGENTS.md — cloudinary_ios + +## What this package is (one line) +Official Cloudinary native iOS client SDK (`Cloudinary`): on-device upload (signed/unsigned), delivery + transformation URL building with `CLDTransformation`, and image download with memory/disk caching — in Swift or Objective-C. + +## When to use this / when NOT to use this +- **Use this when:** you are building a native iOS app (Swift or Objective-C) and need to upload media from the device, build delivery/transformation URLs, or download and cache images on-device. +- **Do NOT use this when:** you are building a cross-platform React Native app (use [cloudinary-react-native](https://github.com/cloudinary/cloudinary-react-native)); OR you need server-side work — signed uploads from a server, the Admin API, or anything touching `API_SECRET` (use a backend SDK such as [cloudinary_npm](https://github.com/cloudinary/cloudinary_npm)). A secret must never ship inside an app binary. +- **Sibling packages:** `cloudinary_android` = the same SDK for native Android; `cloudinary-react-native` = React Native (iOS + Android); `cloudinary-ios-sample-app` = a complete runnable example app (learn from it, don't depend on it). This repo's own runnable demo lives in `Example/`. + +## Setup +This SDK is consumed as a dependency. Pick one: + +```ruby +# CocoaPods — in your Podfile +platform :ios, '9.0' +use_frameworks! +target 'MyApp' do + pod 'Cloudinary', '~> 5.0' +end +``` +``` +# Swift Package Manager — Xcode > File > Add Packages... +https://github.com/cloudinary/cloudinary_ios.git (Up to Next Major, 5.0.0) +``` +``` +# Carthage — in your Cartfile +github "cloudinary/cloudinary_ios" ~> 5.0 +# then: carthage update --use-xcframeworks +``` + +Required configuration: a `cloudName` and `apiKey` only (client-side). No `API_SECRET`. + +## Minimal runnable example +```swift +import Cloudinary + +let config = CLDConfiguration(cloudName: "CLOUD_NAME", apiKey: "API_KEY") +let cloudinary = CLDCloudinary(configuration: config) + +// Build a delivery URL +let t = CLDTransformation().setWidth(100).setHeight(150).setCrop(.fill) +let url = cloudinary.createUrl().setTransformation(t).generate("sample.jpg") +// http://res.cloudinary.com/CLOUD_NAME/image/upload/c_fill,h_150,w_100/sample.jpg + +// Unsigned upload via an upload preset (no secret needed). +// CLDUploader exposes upload(url:) and upload(data:) — there is no upload(file:). +cloudinary.createUploader().upload(url: fileUrl, uploadPreset: "sample_preset") +``` + +## Build / test commands (run these after editing) +There is no `xcodebuild` target at the repo root. The library source is built and exercised through the `Example/` project, which is what CI runs. Tests need a Cloudinary account. + +```bash +# 1. Install the Example workspace deps (generates Example/Cloudinary.xcworkspace) +pod install --project-directory=Example + +# 2. Tests require a live account — set this before running them +export CLOUDINARY_URL="cloudinary://:@" + +# 3. Build + run the test suite (mirrors CI; pick an installed simulator/OS) +xcodebuild test \ + -workspace Example/Cloudinary.xcworkspace \ + -scheme travis_public_scheme \ + -destination 'platform=iOS Simulator,OS=15.2,name=iPhone 8' +``` +To run a **single** test class or method, append `-only-testing:` (target/class/method): + +```bash +xcodebuild test \ + -workspace Example/Cloudinary.xcworkspace \ + -scheme travis_public_scheme \ + -destination 'platform=iOS Simulator,OS=15.2,name=iPhone 8' \ + -only-testing:Cloudinary_Tests/CLDConditionExpressionTests +``` + +SwiftPM consumers can also build the library directly: `swift build`. Note that CI does **not** exercise SwiftPM — it builds only the `Example/Cloudinary.xcworkspace` (`travis_public_scheme`) — so verify `swift build` locally if you touch `Package.swift` or its sources. + +No lint step is configured in this repo — there is no SwiftLint or SwiftFormat config in the tree, and CI runs none. Match the surrounding code style by hand. + +## Conventions & gotchas +- **Never put `API_SECRET` in the app.** Configure with `cloudName` + `apiKey` and use unsigned uploads (upload presets). Signed uploads and Admin API calls belong on a backend. The `cloudinary://key:secret@cloud` form and `CLOUDINARY_URL` env var exist for *test* configuration only — don't bake a secret into a shipped binary. +- **Minimum deployment target is iOS 9.0; Swift version 5.0** (from `Cloudinary.podspec` and `Package.swift`). Don't raise the floor or use APIs unavailable at iOS 9 without intent. SDK 3.0+ dropped iOS 8. +- **Library source lives under `Cloudinary/`; tests and the demo app live under `Example/`.** Add new tests under `Example/Tests/...` (mirror the existing folders, e.g. `NetworkTests`, `TransformationTests`). There are paired Swift + Objective-C tests (`*.swift` and `*.m`) — keep the Objective-C interop surface working. +- **All public types are prefixed `CLD`** (`CLDCloudinary`, `CLDConfiguration`, `CLDTransformation`, `CLDUploadRequestParams`, …). Follow that prefix for new public API. +- **CI is Travis** (`.travis.yml`), not GitHub Actions — it runs the `Example` workspace `travis_public_scheme` across several Xcode/iOS-simulator combos and injects `CLOUDINARY_URL`. Network tests fail without a configured account. + +## Canonical docs (leave the repo for depth) +- iOS SDK guide: https://cloudinary.com/documentation/ios_integration +- Image/video upload: https://cloudinary.com/documentation/ios_image_and_video_upload +- Transformation & API references: https://cloudinary.com/documentation/cloudinary_references +- MCP server (agent/no-code path): https://github.com/cloudinary/mcp-servers + +## Agent / MCP note +If a task is exposed via the Cloudinary MCP servers, prefer the MCP tool for autonomous task execution and use this SDK for code generation inside an iOS app. See cloudinary/mcp-servers. + +## Commit / PR conventions +- Open PRs against the default branch; keep Swift + Objective-C test parity green. +- Add or update tests under `Example/Tests/` for any behavior change; CI must pass on the `Example` workspace. +- There is no `CONTRIBUTING.md` in this repo, but `.github/` provides an issue template and a `pull_request_template.md` — fill the PR template out. No commit-message convention (e.g. Conventional Commits) is configured or enforced. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..30fe0862 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,43 @@ +@AGENTS.md + +# CLAUDE.md — cloudinary_ios + +## What this repo is + +Official native iOS client SDK (`Cloudinary` pod / SPM package) for Cloudinary — on-device upload, `CLDTransformation`-based delivery URL building, and image download with memory/disk cache, in Swift or Objective-C. + +## Key constraints / gotchas + +- **Never put `API_SECRET` in the app.** Client configuration is `cloudName` + `apiKey` only. Signed uploads and Admin API calls belong on a backend. `CLOUDINARY_URL` with a secret is for *test* configuration only. +- **Minimum iOS 9.0, Swift 5.0.** SDK 3.0+ dropped iOS 8; don't raise the deployment floor without intent. +- **Library source in `Cloudinary/`; tests and demo in `Example/`.** Add new tests under `Example/Tests/` — keep Swift + Objective-C parity. +- **All public types are prefixed `CLD`** (`CLDCloudinary`, `CLDConfiguration`, `CLDTransformation`, …). Follow the prefix for any new public API. +- **No `upload(file:)`.** Real labels: `upload(url:uploadPreset:)` / `upload(data:uploadPreset:)` (unsigned) and `signedUpload(url:)` / `signedUpload(data:)` (signed). For large files: `uploadLarge` / `signedUploadLarge`. +- **Enum cases are lowercase/camelCase**, not capitalized. Use `.fill`, `.fit`, `.face`, `.northWest` — not `.Fill`, `.NorthWest`. +- **`setTransformation` requires a `CLDTransformation` argument** — there is no zero-argument overload. +- **CI is Travis** (`.travis.yml`), not GitHub Actions. It builds only the `Example/Cloudinary.xcworkspace` (`travis_public_scheme`). SwiftPM builds are not CI-verified. +- **No lint config.** No SwiftLint or SwiftFormat in the tree. Match surrounding style by hand. + +## Build / test commands + +```bash +# Install Example workspace deps +pod install --project-directory=Example + +# Run full test suite (requires live Cloudinary account) +export CLOUDINARY_URL="cloudinary://:@" +xcodebuild test \ + -workspace Example/Cloudinary.xcworkspace \ + -scheme travis_public_scheme \ + -destination 'platform=iOS Simulator,OS=15.2,name=iPhone 8' + +# Run a single test class +xcodebuild test \ + -workspace Example/Cloudinary.xcworkspace \ + -scheme travis_public_scheme \ + -destination 'platform=iOS Simulator,OS=15.2,name=iPhone 8' \ + -only-testing:Cloudinary_Tests/CLDConditionExpressionTests + +# SwiftPM build (not CI-verified — check locally when touching Package.swift) +swift build +``` diff --git a/README.md b/README.md index 3f8be0af..32a75c17 100755 --- a/README.md +++ b/README.md @@ -1,51 +1,15 @@ -Cloudinary iOS SDK -========================= -[![Build Status](https://api.travis-ci.com/cloudinary/cloudinary_ios.svg?branch=master)](https://app.travis-ci.com/github/cloudinary/cloudinary_ios) -## About -The Cloudinary iOS SDK allows you to quickly and easily integrate your application with Cloudinary. -Effortlessly optimize and transform your cloud's assets. - -### Additional documentation -This Readme provides basic installation and usage information. -For the complete documentation, see the [iOS SDK Guide](https://cloudinary.com/documentation/ios_integration). - -## Table of Contents -- [Key Features](#key-features) -- [Version Support](#Version-Support) -- [Installation](#installation) -- [Usage](#usage) - - [Setup](#Setup) - - [Transform and Optimize Assets](#Transform-and-Optimize-Assets) - - [File Upload](#File-Upload) - - [File Download](#File-Download) - -## Key Features -- [Transform](https://cloudinary.com/documentation/ios_video_manipulation#video_transformation_examples) and [optimize](https://cloudinary.com/documentation/ios_image_manipulation#image_optimizations) assets. - -## Version Support -| SDK Version | iOS 9+ | iOS 8 | -|----------------|-----------|-----------| -| 2.0.0 - 2.10.1 | V | V | -| 3.0.0 - 5.x.x | V | X | +# Cloudinary iOS SDK -## Installation -### CocoaPods +[![CocoaPods version](https://img.shields.io/cocoapods/v/Cloudinary.svg)](https://cocoapods.org/pods/Cloudinary) +[![License](https://img.shields.io/cocoapods/l/Cloudinary.svg)](./LICENSE) -[CocoaPods](http://cocoapods.org) is a dependency manager for Swift and Objective-C Cocoa projects. -To install CocoaPods: +The `Cloudinary` pod is the native iOS client SDK for Cloudinary. Use it inside a Swift or Objective-C app to upload images and video from the device, build transformation and delivery URLs, and download and cache images on-device. The current release (5.2.5) requires a minimum iOS deployment target of 9.0 and Swift 5.0. It configures with a cloud name and API key for client-side work and never holds the API secret. -```bash -sudo gem install cocoapods -``` -If you don't have a `Podfile` in your project yet, add it by running the command: -```bash -pod init -``` +## Installation -Add the Cloudinary SDK to your `Podfile`: +Add the SDK with CocoaPods. In your `Podfile`: ```ruby -source 'https://github.com/CocoaPods/Specs.git' platform :ios, '9.0' use_frameworks! @@ -54,233 +18,120 @@ target 'MyApp' do end ``` -Then, run the command: - -```bash -pod install -``` - -### Carthage - -Create `Cartfile` -```bash -touch Cartfile -``` - -Open `Cartfile` and enter the following line - -```bash -github "cloudinary/cloudinary_ios" ~> 5.0 -``` - -Then, run the command: - -```bash -carthage update --use-xcframeworks -``` -A `Cartfile.resolved` file and a `Carthage` directory will appear in the same directory where your `.xcodeproj` or `.xcworkspace` is. -Drag the built `.xcframework` bundles from `Carthage/Build` into the `Frameworks and Libraries` section of your application’s Xcode project. - -### Swift Package Manager -* File > Add Packages... > -* Add https://github.com/cloudinary/cloudinary_ios.git -* Select "Up to Next Major" with "5.0.0" - -### Working with the Cloudinary iOS SDK Manually - -If you prefer not use a dependency manager, you can add Cloudinary manually by adding it as a submodule to your project: - -Open Terminal and navigate to your project's top level directory. - -If your project is not initialized as a git repository, run the command: - -```bash -git init -``` - -To add cloudinary as a git submodule, run the command: +Then run `pod install` and open the generated `.xcworkspace`. -```bash -git submodule add https://github.com/cloudinary/cloudinary_ios.git -``` - -#### Embedded Framework - -1. Drag `Cloudinary.xcodeproj` into the Project Navigator of your application's Xcode project. It should appear under your application's blue project icon. -2. Select `Cloudinary.xcodeproj` and make sure the deployment target matches that of your application target. -3. Select your application project. Under 'TARGETS' select your application, open the 'General' tab, click on the `+` button under the 'Embedded Binaries' and Select 'Cloudinary.framework'. - -## Usage -### Setup -To use the API, you will need a CLDCloudinary instance, which is initialized with an instance of CLDConfiguration. +Swift Package Manager is also supported. In Xcode, open **File > Add Packages**, enter `https://github.com/cloudinary/cloudinary_ios.git`, and select **Up to Next Major** starting at `5.0.0`. -The CLDConfiguration must have its `cloudName` and `apiKey` properties set. Other properties are optional. +## Configuration -See [API, URLs and access identifiers](https://cloudinary.com/documentation/api_and_access_identifiers) for more details. +This is a client SDK that ships inside an app, so it configures with a cloud name and API key only — never the API secret. Build a `CLDConfiguration` and pass it to `CLDCloudinary`: -There are several ways to initialize CLDConfiguration. You can simply call its constructor with the desired params: ```swift -let config = CLDConfiguration(cloudName: "CLOUD_NAME", apiKey: "API_KEY") -``` +import Cloudinary -Another way is by passing a URL of the form: cloudinary://API_KEY:API_SECRET@CLOUD_NAME -```swift -let config = CLDConfiguration(cloudinaryUrl: "cloudinary://:@") -``` - -You can also add the same URL as an environment parameters under `CLOUDINARY_URL`, then initialize CLDConfiguration using its static initializer -```swift -let config = CLDConfiguration.initWithEnvParams() -``` - -Now you can create a CLDCloudinary instance to work with -```swift +let config = CLDConfiguration(cloudName: "my_cloud_name", apiKey: "my_key") let cloudinary = CLDCloudinary(configuration: config) ``` -### Transform and Optimize Assets -The following example generates a URL on an uploaded `sample` image: -```swift -cloudinary.createUrl().generate("sample.jpg") - -// http://res.cloudinary.com/CLOUD_NAME/image/upload/sample.jpg -``` - -The following example generates an image URL of an uploaded `sample` image while transforming it to fill a 100x150 rectangle: - -```swift -let transformation = CLDTransformation().setWidth(100).setHeight(150).setCrop(.crop) -cloudinary.createUrl().setTransformation(transformation).generate("sample.jpg") - -// http://res.cloudinary.com/CLOUD_NAME/image/upload/c_fill,h_150,w_100/sample.jpg -``` - -Another example, embedding a smaller version of an uploaded image while generating a 90x90 face detection based thumbnail: - -```swift -let transformation = CLDTransformation().setWidth(90).setHeight(90).setCrop(.Thumb).setGravity(.Face) -cloudinary.createUrl().setTransformation(transformation).generate("sample.jpg") - -// http://res.cloudinary.com/CLOUD_NAME/image/upload/c_thumb,g_face,h_90,w_90/sample.jpg -``` - -You can provide either a Facebook name or a numeric ID of a Facebook profile or a fan page. +For test setups you can read configuration from the `CLOUDINARY_URL` environment variable instead. `CLDConfiguration.initWithEnvParams()` returns an optional `CLDConfiguration?`: -Embedding a Facebook profile to match your graphic design is very simple: - -```swift -let url = cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(90).setHeight(130).setGravity(.Face).setCrop(.Fill)).setType(.Facebook).generate("billclinton.jpg") - -// http://res.cloudinary.com/CLOUD_NAME/image/facebook/c_fill,g_face,h_130,w_90/billclinton.jpg +```bash +CLOUDINARY_URL=cloudinary://:@ ``` -You can also chain transformations together: - ```swift -let transformation = CLDTransformation().setWidth(100).setHeight(150).chain().setCrop(.Fit) -let url = cloudinary.createUrl().setTransformation().generate("sample.jpg") +import Cloudinary -// http://res.cloudinary.com/CLOUD_NAME/image/facebook/h_150,w_100/c_fit/sample.jpg +// Reads the CLOUDINARY_URL environment variable. +let config = CLDConfiguration.initWithEnvParams() ``` -### File Upload +Keep the API secret out of client-side code and version control. Signed uploads and Admin API calls belong on a backend SDK where the secret stays private. -##### 1. Signed upload +## Quick examples -Uploading to your cloud is very straightforward. +### Upload a file -In the following example the file located at `fileUrl` is uploaded to your cloud: +Upload requests go through `createUploader()`. An unsigned upload takes an upload preset and needs no secret. `upload(url:uploadPreset:...)` returns a `CLDUploadRequest`; the completion handler receives a `CLDUploadResult?` whose fields include `publicId` and `secureUrl`: ```swift -cloudinary.createUploader().upload(file: fileUrl) -``` +import Cloudinary -`fileUrl` can point to either a local or a remote file. - -You can also upload data: +let config = CLDConfiguration(cloudName: "my_cloud_name", apiKey: "my_key") +let cloudinary = CLDCloudinary(configuration: config) -```swift -cloudinary.createUploader().upload(data: data) +let fileURL = URL(fileURLWithPath: "/path/to/photo.jpg") +cloudinary.createUploader().upload( + url: fileURL, + uploadPreset: "my_preset", + completionHandler: { (result, error) in + if let result = result { + print(result.publicId ?? "", result.secureUrl ?? "") + } + } +) ``` -The uploaded image is assigned a randomly generated public ID, which is returned as part of the response. - -You can pass an instance of `CLDUploadRequestParams` for extra parameters you'd want to pass as part of the upload request. For example, you can specify your own public ID instead of a randomly generated one. - -For a full list of available upload parameters, see [the Upload API Reference](https://cloudinary.com/documentation/image_upload_api_reference#upload) documentation. +### Build and optimize a delivery URL -You can also pass a `progress` closure that is called periodically during the data transfer, and a `completionHandler` closure to be called once the request has finished, holding either the response object or the error. +`createUrl()` builds delivery URLs with no network call. `generate(_:)` returns an optional `String?`. This transformation resizes to a 100x150 fill crop and lets Cloudinary pick the format and quality for the device with `f_auto` and `q_auto`. Set `secure: true` on the configuration to generate `https://` URLs: - -In the following example, we apply an incoming transformation as part of the upload request, the transformation is applied before saving the image in the cloud. -We also specify a public ID and pass closures for the upload progress and completion handler. ```swift -let params = CLDUploadRequestParams() -params.setTransformation(CLDTransformation().setGravity(.NorthWest)) -params.setPublicId("my_public_id") -let request = cloudinary.createUploader().upload(file: fileUrl, params: params, progress: { (bytes, totalBytes, totalBytesExpected) in - // Handle progress - }) { (response, error) in - // Handle response -} -``` +import Cloudinary -##### 2. Unsigned uploads using [Upload Presets.](https://cloudinary.com/documentation/ios_image_and_video_upload#unsigned_upload) -You can create an upload preset in your Cloudinary account console, defining rules that limit the formats, transformations, dimensions and more. -Once the preset is defined, it's name is supplied when calling upload. An upload call will only succeed if the preset name is used and the resource is within the preset's pre-defined limits. +let config = CLDConfiguration(cloudName: "demo", secure: true) +let cloudinary = CLDCloudinary(configuration: config) -The following example uploads a local resource, assuming a preset named 'sample_preset' already exists in the account: -```swift -let request = cloudinary.createUploader().upload(url: file, uploadPreset: "sample_preset", params: CLDUploadRequestParams()).response({ - (response, error) in - // Handle response -}) +let transformation = CLDTransformation() + .setWidth(100).setHeight(150).setCrop(.fill) + .setFetchFormat("auto").setQuality("auto") +let url = cloudinary.createUrl().setTransformation(transformation).generate("sample.jpg") +// https://res.cloudinary.com/demo/image/upload/c_fill,f_auto,h_150,q_auto,w_100/sample.jpg ``` -Every upload request returns a CLDUploadRequest instance, allowing options such as cancelling, suspending or resuming it. - -### File Download +### Download and render an asset -The SDK provides some convenient methods for downloading files from your cloud: +The SDK ships a `UIImageView` extension, `cldSetImage`, that builds the URL, downloads, caches, and renders — with an optional placeholder. Here `imageView` is an existing `UIImageView`. `setCrop` takes a `CLDCrop` case (`.fill`, `.fit`, `.thumb`, `.scale`) and `setGravity` takes a `CLDGravity` case (`.face`, `.faces`, `.auto`, `.northWest`): ```swift -cloudinary.createDownloader().fetchImage(url) -``` +import Cloudinary +import UIKit -You can also pass a `progress` closure that is called periodically during the data transfer, and a `completionHandler` closure to be called once the request has finished, holding either the fetched UIImage or an error. +let config = CLDConfiguration(cloudName: "demo", secure: true) +let cloudinary = CLDCloudinary(configuration: config) -```swift -let request = cloudinary.createDownloader().fetchImage(url, progress: { (bytes, totalBytes, totalBytesExpected) in - // Handle progress - }) { (responseImage, error) in - // Handle response - } +let transformation = CLDTransformation() + .setWidth(90).setHeight(90).setCrop(.thumb).setGravity(.face) +imageView.cldSetImage( + publicId: "sample", + cloudinary: cloudinary, + transformation: transformation, + placeholder: UIImage(named: "placeholder") +) +// Delivers https://res.cloudinary.com/demo/image/upload/c_thumb,g_face,h_90,w_90/sample ``` -Every download request returns an instance implementing CLDNetworkDataRequest, allowing options such as cancelling, suspending or resuming it. +## For AI agents -The downloaded image is cached both to the memory and the disk (customizable). The disk cache size is limited and can be changed. +`Cloudinary` (this repo, `cloudinary_ios`) is the native iOS client SDK, in Swift and Objective-C, for on-device upload, delivery/transformation URL building, and image download and caching. It configures with `cloudName` and `apiKey` only and does not hold the API secret. For tasks this package doesn't cover, route to the correct sibling: -## Contributions -See [contributing guidelines](/CONTRIBUTING.md). +| Task | Package | +|---|---| +| The same job on native Android | [`cloudinary_android`](https://github.com/cloudinary/cloudinary_android) | +| One codebase for iOS and Android | [`cloudinary-react-native`](https://github.com/cloudinary/cloudinary-react-native) | +| Server-side signed uploads, Admin API, anything needing the API secret | [`cloudinary_npm`](https://github.com/cloudinary/cloudinary_npm) | +| A complete runnable example app | [`cloudinary-ios-sample-app`](https://github.com/cloudinary/cloudinary-ios-sample-app) | +| Run Cloudinary operations as agent tools | [Cloudinary MCP servers](https://github.com/cloudinary/mcp-servers) | -## Get Help -If you run into an issue or have a question, you can either: -- [Open a Github issue](https://github.com/cloudinary/cloudinary_ios/issues) (for issues related to the SDK) -- [Open a support ticket](https://cloudinary.com/contact) (for issues related to your account) +All public types are prefixed `CLD` (`CLDCloudinary`, `CLDConfiguration`, `CLDTransformation`, `CLDUploadRequestParams`). -## About Cloudinary -Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive and personalized visual-media experiences—irrespective of the viewing device. +## Links -## Additional Resources -- [Cloudinary Transformation and REST API References](https://cloudinary.com/documentation/cloudinary_references): Comprehensive references, including syntax and examples for all SDKs. -- [DevJams](https://www.youtube.com/playlist?list=PL8dVGjLA2oMr09amgERARsZyrOz_sPvqw): Cloudinary developer podcasts on YouTube. -- [Cloudinary Academy](https://training.cloudinary.com/): Free self-paced courses, instructor-led virtual courses, and on-site courses. -- [Code Explorers and Feature Demos](https://cloudinary.com/documentation/code_explorers_demos_index): A one-stop shop for all code explorers, Postman collections, and feature demos found in the docs. -- [Cloudinary Roadmap](https://cloudinary.com/roadmap): Your chance to follow, vote, or suggest what Cloudinary should develop next. -- [Cloudinary Facebook Community](https://www.facebook.com/groups/CloudinaryCommunity): Learn from and offer help to other Cloudinary developers. -- [Cloudinary Account Registration](https://cloudinary.com/users/register/free): Free Cloudinary account registration. -- [Cloudinary Website](https://cloudinary.com) +- [iOS SDK guide](https://cloudinary.com/documentation/ios_integration) +- [Image and video upload](https://cloudinary.com/documentation/ios_image_and_video_upload) +- [Image transformations](https://cloudinary.com/documentation/ios_image_manipulation) +- [Transformation and API references](https://cloudinary.com/documentation/cloudinary_references) +- [Documentation llms.txt index](https://cloudinary.com/documentation/llms.txt) +- [Package on CocoaPods](https://cocoapods.org/pods/Cloudinary) -## Licence Released under the MIT license.