{"id":18626170,"url":"https://github.com/adboco/unsplasher-sdk","last_synced_at":"2025-04-11T05:30:48.377Z","repository":{"id":56185008,"uuid":"126161906","full_name":"adboco/Unsplasher-SDK","owner":"adboco","description":"An Unsplash API client written in Swift.","archived":false,"fork":false,"pushed_at":"2020-11-22T00:28:51.000Z","size":431,"stargazers_count":5,"open_issues_count":1,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-25T09:47:48.714Z","etag":null,"topics":["api","apple","cocoapods","codable","ios","library","pod","result-type","sdk","swift","swift-library","swift4","unsplash","unsplash-api","unsplash-client","xcode","xcode9"],"latest_commit_sha":null,"homepage":null,"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/adboco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-21T10:27:05.000Z","updated_at":"2023-07-25T14:15:50.000Z","dependencies_parsed_at":"2022-08-15T14:20:13.227Z","dependency_job_id":null,"html_url":"https://github.com/adboco/Unsplasher-SDK","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adboco%2FUnsplasher-SDK","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adboco%2FUnsplasher-SDK/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adboco%2FUnsplasher-SDK/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adboco%2FUnsplasher-SDK/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adboco","download_url":"https://codeload.github.com/adboco/Unsplasher-SDK/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248347343,"owners_count":21088627,"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":["api","apple","cocoapods","codable","ios","library","pod","result-type","sdk","swift","swift-library","swift4","unsplash","unsplash-api","unsplash-client","xcode","xcode9"],"created_at":"2024-11-07T04:37:07.268Z","updated_at":"2025-04-11T05:30:48.099Z","avatar_url":"https://github.com/adboco.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UNSPLASHER SDK\n\n[![build](https://travis-ci.org/adboco/Unsplasher-SDK.svg?branch=master)](https://travis-ci.org/adboco/Unsplasher-SDK)\n[![codecov](https://codecov.io/gh/adboco/Unsplasher-SDK/branch/master/graph/badge.svg)](https://codecov.io/gh/adboco/Unsplasher-SDK)\n[![maintainability](https://api.codeclimate.com/v1/badges/fdeb03a2a9519f7b4063/maintainability)](https://codeclimate.com/github/adboco/Unsplasher-SDK/maintainability)\n![platform](https://img.shields.io/badge/platform-iOS%209.0%2B-lightgrey.svg)\n![platform](https://img.shields.io/badge/xcode-9.0%2B-lightgrey.svg)\n![swift version](https://img.shields.io/badge/swift-4.2-orange.svg)\n[![cocoapods](https://img.shields.io/cocoapods/v/UnsplasherSDK.svg?style=flat)](https://cocoapods.org/pods/UnsplasherSDK)\n[![license](https://img.shields.io/cocoapods/l/KeyboardSwift.svg?style=flat)](https://cocoapods.org/pods/KeyboardSwift)\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fadboco%2FUnsplasher-SDK.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fadboco%2FUnsplasher-SDK?ref=badge_shield)\n\nAn Unsplash API client written in Swift. It supports user authentication, likes, manage collections and every feature of the [official API](https://unsplash.com/documentation).\n\n## Requirements\n* Platform: iOS 9.0+\n* Xcode 9.0+\n* Dependencies:\n\t- [Alamofire](https://github.com/Alamofire/Alamofire)\n\t- [SwiftKeychainWrapper](https://github.com/jrendel/SwiftKeychainWrapper)\n\n## Installation\nUsing [CocoaPods](https://cocoapods.org):\n```ruby\npod \"UnsplasherSDK\"\n```\n\n## Usage\n```swift\nimport UnsplasherSDK\n```\n\nFirst thing you need is to configure the Unsplash instance with your credentials and scopes. Do it, for example, in your AppDelegate:\n```swift\n// Setup application ID and Secret\nUnsplash.configure(appId: \"{YOUR_APPLICATION_ID}\", secret: \"{YOUR_SECRET}\", scopes: Unsplash.PermissionScope.allCases) // All scopes\n// or\nUnsplash.configure(appId: \"{YOUR_APPLICATION_ID}\", secret: \"{YOUR_SECRET}\", scopes: [.readUser, .writeLikes, ...]) // Specific scopes\n```\n\n### Authentication\nTo authenticate the user, you need to call ``authenticate`` method when your View Controller has been presented, because it'll show a modal View Controller where the user can login in his/her account:\n```swift\nUnsplash.shared.authenticate(self) { result in\n\tswitch result {\n\tcase .success:\n\t\tgetUser()\n\t\tgetPhotos()\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\nUnsplash.share.signOut() // Close session\n```\n\nTo sign in with different user and avoid automatic authentication with the old one, you can remove cookies this way:\n```swift\nprivate func removeCookies() {\n    let dataStore = WKWebsiteDataStore.default()\n    dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in\n        dataStore.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), for: records.filter { $0.displayName.contains(\"unsplash\") }, completionHandler: {\n            logger.debug(\"Cookies for Unsplash deleted successfully\")\n        })    \n    }\n}\n```\n\n\u003e _Note:_ Make sure your Authorization callback URL is set to ``unsplash-{YOUR_APPLICATION_ID}://token``.\n\n### Current User\n```swift\nlet currentUserClient = Unsplash.shared.currentUser\n\n// Get user's profile\ncurrentUserClient.profile(completion: { result in\n\tswitch result {\n\tcase .success(let user):\n\t\tprint(\"Name: \\(user.name)\")\n\t\tprint(\"Followers: \\(user.followersCount)\")\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\n// Update user's profile\nuser.bio = \"Photography lover since 1998\"\ncurrentUserClient.update(user) { result in \n\tswitch result {\n\tcase .success(let user):\n\t\tprint(\"User's profile updated.\")\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n```\n\n### Users\n```swift\nlet usersClient = Unsplash.shared.users\n\n// Get user by nickname\nusersClient.user(\"ari_spada\") { result in \n\tswitch result {\n\tcase .success(let user):\n\t\tprint(\"User found: \\(user.name)\")\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\n// Get user's portfolio url\nusersClient.portfolio(by: user.username) { result in \n\tswitch result {\n\tcase .success(let link):\n\t\tprint(\"Portfolio url: \\(link.url?.absoluteString)\")\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\n// Get user's photos\nusersClient.photos.by(user.username, page: 3, perPage: 5, orderBy: .latest) { result in \n\tswitch result {\n\tcase .success(let photos):\n\t\tfor photo in photos {\n\t\t\tprint(\"\\(photo.id), Likes: \\(photo.likes)\")\n\t\t}\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\n// Photos liked by user\nusersClient.photos.liked(by: user.username) { result in /* handle the result */ }\n\n// Get user's collections\nusersClient.collections.by(user.username) { result in /* handle the result */ }\n```\n\n### Photos\n```swift\nlet photosClient = Unsplash.shared.photos\n\n// Get photos\nphotosClient.photos(page: 1, perPage: 10, orderBy: .popular, curated: true) { result in \n\tswitch result {\n\tcase .success(let photos):\n\t\tfor photo in photos {\n\t\t\tprint(\"\\(photo.id), Full photo url: \\(photo.urls?.full.absoluteString)\")\n\t\t}\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\n// Get photo by id\nphotosClient.photo(id: photo.id, width: 1200, height: 800) { result in /* handle the result */ }\n\n// Update photo\nphoto.location.country = \"Spain\"\nphoto.location.city = \"Valencia\"\nphotosClient.update(photo) { result in /* handle the result */ }\n\n// Like and unlike a photo\nphotosClient.like(id: photo.id) { result in /* handle the result */ }\n\nphotosClient.unlike(id: photo.id) { result in /* handle the result */ }\n\n// Get a list of random photos\nphotosClient.randomPhotos(query: \"city\", orientation: .landscape, count: 20) { result in /* handle the result */ }\nphotosClient.randomPhotos(collectionIds: [176316]) { result in /*handle the result */ }\n\n// Get a random photo\nphotosClient.randomPhoto(featured: true, query: \"forest\", username: \"henry\") { result in /* handle the result */ }\n\n// Get download link\nphotosClient.downloadLink(id: photo.id) { result in /* handle the result */ }\n```\n\n### Collections\n```swift\nlet collectionsClient = Unsplash.shared.collections\n\n// Get a list of collections\ncollectionsClient.collections(list: .featured, page: 1, perPage: 10) { result in \n\tswitch result {\n\tcase .success(let collections):\n\t\tfor collection in collections {\n\t\t\tprint(\"\\(collection.title), Total photos: \\(collection.totalPhotos)\")\n\t\t}\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\n// Get collection by id\ncollectionsClient.collection(id: collection.id) { result in /* handle the result */ }\n\n// Get collection's photos\ncollectionsClient.photos(in: collection.id, page: 2, perPage: 8) { result in /* handle the result */ }\n\n// Get a list of collections related with a given one\ncollectionsClient.collections(relatedWith: collection.id) { result in /* handle the result */ }\n\n// Create a new collection\ncollectionsClient.create(title: \"My collection\", description: \"Amazing landscape photos!\", isPrivate: false) { result in /* handle the result */ }\n\n// Update collection\ncollection.title = \"New title\"\ncollection.isPrivate = true\ncollectionsClient.update(collection) { result in /* handle the result */ }\n\n// Deleta a collection\ncollectionsClient.delete(id: collection.id) { result in /* handle the result */ }\n\n// Add a photo to a collection\ncollectionsClient.add(photoId: \"3794hdjks\", to: collection.id) { result in /* handle the result */ }\n\n// Remove a photo from a collection\ncollectionsClient.remove(photoId: \"3975yjksd\", from: collection.id) { result in /* handle the result */ }\n```\n\n### Search\n```swift\nlet searchClient = Unsplash.shared.search\n\n// Search users\nsearchClient.users(query: \"tom\", page: 1, perPage: 10) { result in\n\tswitch result {\n\tcase .success(let search):\n\t\tfor user in search.users {\n\t\t\tprint(\"\\(user.username)\")\n\t\t}\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\n// Search photos\nsearchClient.photos(query: \"landscape\", page: 3, perPage: 20, orientation: .portrait) { result in\n\tlet photos = result.value?.photos\n}\n\n// Search collections\nsearchClient.collections(query: \"urban\", page: 2, perPage: 25) { result in\n\tlet collections = result.value?.collections\n}\n```\n\n### Pagination\nThere is a simple way to iterate over pages if you use a paginated request. Here's an example:\n```swift\n// Get next page of the current request\nphotosClient.next { result in \n\tswitch result {\n\tcase .success(let photos):\n\t\tprint(\"Total photos: \\(photos.count)\")\n\tcase .failure(let error):\n\t\tprint(\"Error: \" + error.localizedDescription)\n\t}\n}\n\n// Previous page\nphotosClient.prev { result in /* handle the result */ }\n\n// Last page\nphotosClient.last { result in /* handle the result */ }\n\n// First page\nphotosClient.first { result in /* handle the result */ }\n\n// Also available in users, collections and search\nUnsplash.shared.users.photos.{next,prev,last,first}\nUnsplash.shared.users.collections.{next,prev,last,first}\nUnsplash.shared.collections.{next,prev,last,first}\nUnsplash.shared.search.{next,prev,last,first}\n```\n\nThis methods will return error if the requested page is not available or the last request made doesn't match with the new expected response type:\n```swift\nUnsplash.shared.photos.randomPhotos { result in /* ... */ }\n\nUnsplash.shared.photos.next { result in /* Success */ }\n\n/* \n * Returns error because the previous request returns an array of Photo\n * and the new request expects an array of Collection\n */\nUnsplash.shared.collections.next { result in /* Failure */ }\n```\n\n## About\nThis project is funded and maintained by [adboco](https://github.com/adboco). It's a contribution to open source software! 🔶\n\n## License\nUnsplasher SDK is available under MIT license. See the LICENSE file for more information.\n\n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fadboco%2FUnsplasher-SDK.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fadboco%2FUnsplasher-SDK?ref=badge_large)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadboco%2Funsplasher-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadboco%2Funsplasher-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadboco%2Funsplasher-sdk/lists"}