{"id":1913,"url":"https://github.com/SwiftyVK/SwiftyVK","last_synced_at":"2025-08-02T05:33:18.118Z","repository":{"id":56922399,"uuid":"44483750","full_name":"SwiftyVK/SwiftyVK","owner":"SwiftyVK","description":"Easy and powerful way to interact with VK API for iOS and macOS","archived":false,"fork":false,"pushed_at":"2023-07-22T13:54:59.000Z","size":70509,"stargazers_count":255,"open_issues_count":6,"forks_count":54,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-04-23T19:19:37.794Z","etag":null,"topics":["ios","library","longpoll","mac","macos","osx","swift","swiftyvk","vk","vk-api","vk-application","vk-sdk","vkapi","vkontakte","vkontakte-api","vkontakte-client","vkontakte-oauth2","vkontakte-sdk","vkontakteapi"],"latest_commit_sha":null,"homepage":"","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/SwiftyVK.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-10-18T15:30:58.000Z","updated_at":"2024-04-17T06:34:49.000Z","dependencies_parsed_at":"2023-12-31T04:11:02.890Z","dependency_job_id":null,"html_url":"https://github.com/SwiftyVK/SwiftyVK","commit_stats":{"total_commits":1006,"total_committers":20,"mean_commits":50.3,"dds":"0.041749502982107334","last_synced_commit":"6201cefc1e6618068f574dd9d72fd95b1faaf8fa"},"previous_names":[],"tags_count":61,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwiftyVK%2FSwiftyVK","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwiftyVK%2FSwiftyVK/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwiftyVK%2FSwiftyVK/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwiftyVK%2FSwiftyVK/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SwiftyVK","download_url":"https://codeload.github.com/SwiftyVK/SwiftyVK/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228443770,"owners_count":17920786,"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":["ios","library","longpoll","mac","macos","osx","swift","swiftyvk","vk","vk-api","vk-application","vk-sdk","vkapi","vkontakte","vkontakte-api","vkontakte-client","vkontakte-oauth2","vkontakte-sdk","vkontakteapi"],"created_at":"2024-01-05T20:15:58.853Z","updated_at":"2024-12-06T09:30:43.635Z","avatar_url":"https://github.com/SwiftyVK.png","language":"Swift","funding_links":[],"categories":["SDK"],"sub_categories":["Unofficial","Other free courses"],"readme":"[![SwiftyVK](./SwiftyVK_logo.png)](./)\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"http://cocoadocs.org/docsets/SwiftyVK\"\u003e\n    \u003cimg src=\"https://img.shields.io/cocoapods/p/SwiftyVK.svg?style=flat\" alt=\"Platform\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://developer.apple.com/swift/\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Swift-5.0-orange.svg?style=flat\" alt=\"Swift\"\u003e\n  \u003c/a\u003e\n    \u003ca href=\"https://vk.com/dev/versions\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/VK_API-\u003e5.92-blue.svg?style=flat\" alt=\"VK API\"\u003e\n  \u003c/a\u003e\n    \u003ca href=\"https://cocoapods.org/pods/SwiftyVK\"\u003e\n    \u003cimg src=\"https://img.shields.io/cocoapods/v/SwiftyVK.svg?style=flat\" alt=\"Cocoapods compatible\"\u003e\n  \u003c/a\u003e\n    \u003ca href=\"https://github.com/Carthage/Carthage\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Carthage-supported-brightgreen.svg\" alt=\"Carthage compatible\"\u003e\n  \u003c/a\u003e\n    \u003ca href=\"./LICENSE.txt\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-MIT-lightgrey.svg\" alt=\"License\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://travis-ci.org/SwiftyVK/SwiftyVK\"\u003e\n    \u003cimg src=\"https://travis-ci.org/SwiftyVK/SwiftyVK.svg?branch=master\" alt=\"Build status\"\u003e\n  \u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/SwiftyVK/SwiftyVK\"\u003e\n    \u003cimg src=\"https://codecov.io/gh/SwiftyVK/SwiftyVK/branch/master/graph/badge.svg\" alt=\"Codecov\" /\u003e\n  \u003c/a\u003e\n    \u003ca href=\"https://codebeat.co/projects/github-com-swiftyvk-swiftyvk-master\"\u003e\n    \u003cimg src=\"https://codebeat.co/badges/e9f1cca3-b81d-4c6d-9129-50205465cb8a\" alt=\"Codebeat\" \u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://houndci.com\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg\" alt=\"Reviewed by Hound\" \u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://money.yandex.ru/to/41001399791481\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Donate-💰-lightgrey.svg\" alt=\"Donale\"\u003e\n   \u003c/a\u003e\n\u003c/p\u003e\n\n# Easy and powerful way to interact with [VK API](https://vk.com/dev) for iOS and macOS.\n\n## Key features\n\n\u003cp align=\"center\"\u003e\n😊 It's not \u003cb\u003eios-vk-sdk\u003c/b\u003e 😊\u003cbr /\u003e\n🍏 One library for iOS and mac OS 🍏\u003cbr /\u003e\n🤘 Fully written in Swift and doesn't contain any Objective-C code 🤘\u003cbr /\u003e\n🎮 Very simple interface, made with care about those who will use it 🎮\u003cbr /\u003e\n⛑ Fully strong typed that you can not shoot yourself in the leg ⛑\u003cbr /\u003e\n🏆 High code quality with lot of unit tests, linter integration and CI 🏆\u003cbr /\u003e\n🚀 Frequent updates and bug fixes 🚀\u003cbr /\u003e\n🔊 LongPoll support 🔊\u003cbr /\u003e\n\u003c/p\u003e\n\n## Table of contents\n* [Requirements](#requirements)\n* [Integration](#integration)\n  - [Carthage (recommended)](#carthage-recomended)\n  - [CocoaPods](#cocoapods)\n  - [Manually](#manually)\n* [Getting started](#getting-started)\n  - [Implement SwiftyVKDelegate](#implement-swiftyvkdelegate)\n  - [Setting up VK application](#setting-up-vk-application)\n  - [Authorization](#authorization)\n      - [oAuth WebView](#oauth-webview)\n      - [Official VK Application](#official-vk-application)\n      - [Raw token string](#raw-token-string)\n* [Interaction with VK API](#interaction-with-vk-api)\n  - [Request](#request)\n  - [Parameters](#parameters)\n  - [Callbacks](#callbacks)\n      - [onSuccess](#onsuccess)\n      - [onError](#onerror)\n  - [Cancellation](#cancellation)\n  - [Chaining](#chaining)\n* [Configuring](#configuring)\n* [Upload files](#upload-files)\n* [Interaction with LongPoll](#interaction-with-longpoll)\n    - [Start LongPoll](#start-longpoll)\n    - [Handle updates](#handle-updates)\n    - [Stop LongPoll](#stop-longpoll)\n* [Share dialog](#share-dialog)\n* [FAQ](#faq)\n* [License](#license)\n\n\n\n----\n## **Requirements**\n* Swift 4.0 +\n* iOS 8.0 +\n* macOS 10.10 +\n* Xcode 9.0 +\n\n## **Integration**\n\n### [Carthage](https://github.com/Carthage/Carthage) (recommended)\n```\ngithub \"SwiftyVK/SwiftyVK\"\n```\n\n### [CocoaPods](https://github.com/CocoaPods/CocoaPods)\n```ruby\nuse_frameworks!\n\ntarget '$MySuperApp$' do\n  pod 'SwiftyVK'\nend\n```\n\n### Manually\n  1. Just drag **SwiftyVK.framework** or include the whole **SwiftyVK.xcodeproj** into project\n  2. Link **SwiftyVK.framework** with application in **Your target preferences -\u003e General -\u003e Embedded binaries**\n\n## **Getting started**\n### Implement SwiftyVKDelegate\n\nTo start using `SwiftyVK` you should implement `SwiftyVKDelegate` protocol in your custom `VKDelegate` class.\nIt is used to notify your app about important SwiftyVK lifecycle events.\n\nFor example:\n\n```swift\nimport SwiftyVK\n```\n\n```swift\nclass VKDelegateExample: SwiftyVKDelegate {\n\n    func vkNeedsScopes(for sessionId: String) -\u003e Scopes {\n      // Called when SwiftyVK attempts to get access to user account\n      // Should return a set of permission scopes\n    }\n\n    func vkNeedToPresent(viewController: VKViewController) {\n      // Called when SwiftyVK wants to present UI (e.g. webView or captcha)\n      // Should display given view controller from current top view controller\n    }\n\n    func vkTokenCreated(for sessionId: String, info: [String : String]) {\n      // Called when user grants access and SwiftyVK gets new session token\n      // Can be used to run SwiftyVK requests and save session data\n    }\n\n    func vkTokenUpdated(for sessionId: String, info: [String : String]) {\n      // Called when existing session token has expired and successfully refreshed\n      // You don't need to do anything special here\n    }\n\n    func vkTokenRemoved(for sessionId: String) {\n      // Called when user was logged out\n      // Use this method to cancel all SwiftyVK requests and remove session data\n    }\n}\n```\n*See full implementation in Example project*\n\n### Setting up VK application\n\n1. [Create new standalone application](https://vk.com/editapp?act=create)\n2. Save `application ID` from **Preferences -\u003e Application ID**\n3. Set up **SwiftyVK** with `application ID` and `VKDelegate` obtained in the previous steps:\n\n```swift\nVK.setUp(appId: String, delegate: SwiftyVKDelegate)\n```\n\n### Releasing\n\nin order to free up resources that holds SwiftyVK use:\n\n```swift\nVK.release()\n```\nnote you must setup it again for further using\n\n\n## **Authorization**\n\nSwiftyVK provides several ways to authorize user. Choose the one that's more suitable for you.\n\n### oAuth WebView\nThis is a standard authorization method which shows web view with oAuth dialog. Suitable for most cases.\n\n```swift\nVK.sessions.default.logIn(\n      onSuccess: { _ in\n        // Start working with SwiftyVK session here\n      },\n      onError: { _ in\n        // Handle an error if something went wrong\n      }\n  )\n```\n\n### Official VK Application\nIf a user has the official VK app installed on their device, SwiftyVK can be authorized using it. To do that:\n\n1. In *Xcode -\u003e Target -\u003e Info -\u003e URL Types*\n\n    - Add new URL Type like `vk$YOUR_APP_ID$` (e.g. vk1234567890)\n    - Add app schemas to Info.plist file:\n\n```html\n\u003ckey\u003eLSApplicationQueriesSchemes\u003c/key\u003e\n  \u003carray\u003e\n    \u003cstring\u003evkauthorize\u003c/string\u003e\n    \u003cstring\u003evk$YOUR_APP_ID$\u003c/string\u003e\n  \u003c/array\u003e\n```\n\n2. Copy `Application Bundle` from\n*Xcode -\u003e $App Target$ -\u003e General -\u003e Bundle Identifier* (e.g. com.developer.applicationName)\n2. Set copied `Application Bundle` to\n*https://vk.com/apps?act=manage -\u003e Edit App -\u003e Settings -\u003e App Bundle ID for iOS* field\n\n4. Add the following code to AppDelegate:\n\n\n  - For iOS 9 and below\n  \n ```swift\nfunc application(\n    _ application: UIApplication,\n    open url: URL,\n    sourceApplication: String?,\n    annotation: Any\n    ) -\u003e Bool {\n    VK.handle(url: url, sourceApplication: sourceApplication)\n    return true\n}\n```\n  - For iOS 10 and above\n\n```swift\nfunc application(\n    _ app: UIApplication,\n    open url: URL,\n    options: [UIApplicationOpenURLOptionsKey : Any] = [:]\n    ) -\u003e Bool {\n    let app = options[.sourceApplication] as? String\n    VK.handle(url: url, sourceApplication: app)\n    return true\n}\n```\n4. Authorize as described in [oAuth WebView](#oauth-webview).\n\n    ***If user denies authorization in VK App, SwiftyVK will present oAuth dialog***\n\n### Raw token string\nIf you have previously received user token, just pass it to the following method:\n\n```swift\nVK.sessions.default.logIn(rawToken: String, expires: TimeInterval)\n\n// Start working with SwiftyVK session here\n```\n\n`TimeInterval` is a time, after which the token will no longer be valid. Pass `0` if you want token to never expire.\n\n## **Interaction with VK API**\n\nSwiftyVK provides a very simple interface for interaction with VK API.\nAll requests are performed asynchronously in a private queue by API scheduler\n(the scheduler sends no more than 3 requests per second by default).\nYou can just send a request and get a response without a lot of work.\n\nAll API methods are listed [here](https://vk.com/dev/methods)\n\nLet's look closer to requests syntax:\n\n### Request\nThe basic request calls look like **VK.methodGroup.methodName()**.\n\nFor example, to [get short info about current user](https://vk.com/dev/users.get):\n\n```swift\nVK.API.Users.get(.empty)\n    .onSuccess { /* handle and parse response */ }\n    .onError { /* handle error */ }\n    .send()\n```\n\nObject created with\n```swift\nVK.API.Users.get(.empty)\n```\nrepresents a request that can be sent immediately or can be configured first and sent later.\n\n### Parameters\nIf you want to get additional fields for a user in previous example, you can set request parameters:\n\n```swift\nVK.API.Users.get([\n    .userId: \"1\",\n    .fields: \"sex,bdate,city\"\n    ])\n```\n\nUse `.empty` if you don't want to pass any parameters.\n\n### Callbacks\nRequests are executed asynchronously and provide some callbacks for handling execution results:\n\n#### onSuccess\n\nThis callback will be called when request has succeeded and returned `Data` object.\nYou can handle and parse response using any JSON parsing method\n(e.g. `JSONSerialization`, `Codable`, [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) and others)\n\n```swift\nVK.API.Users.get(.empty)\n    .onSuccess {\n        let response = try JSONSerialization.jsonObject(with: $0)\n    }\n```\n\nYou can throw errors in `onSuccess` callback, which will cause `onError` to be called with your error.\n\n#### onError\n\nThis callback will be called when request has failed for some reason.\nYou may handle the error that was thrown in this callback.\n\n```swift\nVK.API.Users.get(.empty)\n    .onError {\n        print(\"Request failed with error: ($0)\")\n     }\n```\n\n### Cancellation\n\nIf you no longer need to send sheduled request (e.g. screen was popped out), just cancel it:\n\n```swift\n// `send()` function returns `Task` object which has `cancel()` function\nlet request = VK.API.Users.get([\n    .userId: \"1\",\n    .fields: \"sex,bdate,city\"\n    ])\n    .onSuccess { print($0) }\n    .send()\n\n// Cancel sheduled request.\n// onSuccess callback will never be executed.\nrequest.cancel()\n```\n\n### Chaining\n\nSwiftyVK allows you to chain requests. If your second request needs to consume a response from the first one, just chain them together:\n\n```swift\nVK.API.Users.get(.empty)\n    .chain { response in\n        // This block will be called only\n        // when `users.get` method is successfully executed.\n        // Receives result of executing `users.get` method.\n        let user = try JSONDecoder().decode(User.self, from: response)\n        return VK.API.Messages.send([\n            .userId: user.id,\n            .message: \"Hello\"\n        ])\n    }\n    .onSuccess { response in\n        // This block will be called only when both `users.get` and `messages.send`\n        // methods are successfully executed.\n        // `response` is a result of `messages.send` method\n    }\n    .onError { error in\n        // This block will be called when either `users.get` or `messages.send` methods is failed.\n        // Receives error of executing `users.get` or `messages.send` method.\n    }\n    .send()\n```\n\nYou can make very long chains with SwiftyVK!\n\n## **Configuring**\nIn SwiftyVK each session has default configuration for its requests.\nEach request gets configuration from its session.\nConfiguration contains settings such as `httpMethod`, `attemptTimeout` and others.\n\nYou can change configuration for a single request\n\n```swift\n// Set different httpMethod only for this request\nVK.API.Users.get(.empty)\n    .configure(with: Config(httpMethod: .POST))\n```\n\nor for the whole session\n\n```swift\n// Set default apiVersion value for all requests in default session\nVK.sessions.default.config.apiVersion = \"5.68\"\n```\n\nYou may change following configuration properties:\n\nProperty            | Default               | Description\n:-------------      | -------------         | :-------------\n`httpMethod`        | `.GET`                | [HTTP method](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods). You can use `GET` or `POST`. For big body (e.g. long message text in `message.send` method) use `POST` method.  \n`apiVersion`        | `latest version`      | [VK API version](https://vk.com/dev/versions). By default uses latest version. If you need different version - change this value.\n`language`          | `User system language`| Language of response. For EN `Pavel Durov`, for RU `Павел Дуров`.\n`attemptsMaxLimit`  | `3`                   | Maximum number of attempts to send request before returning an error.\n`attemptTimeout`    | `10`                  | Timeout in seconds of waiting for a response before returning an error.\n`handleErrors`      | `true`                | Allow to handle specific VK errors automatically by presenting a dialog to a user when authorization, captcha solving or validation is required.\n\n## Upload files\n\nSwiftyVK provides the ability to easily upload a file to VK servers. For example:\n\n```swift\n// Get path to image file\nguard let path = Bundle.main.path(forResource: \"testImage\", ofType: \"jpg\") else { return }\n\n// Get data from image file by path\nguard let data = try Data(contentsOf: URL(fileURLWithPath: path)) else { return }\n\n// Create SwiftyVK Media representation from given data\nlet media = Media.image(data: data, type: .jpg)\n\n// Upload image to server\nVK.API.Upload.Photo.toWall(media, to: .user(id: \"4680178\"))\n    .onSuccess { print($0) }\n    .onError { print($0) }\n    .onProgress {\n        // This callback available only for uploading requests\n        // Use it to handle uploading status and show it to user\n        \n        switch $0 {\n            case let .sent(current, of):\n                print(\"sent\", current, \"of\": of)\n            case let .recieve(current, of):\n                print(\"recieve\", current, \"of\": of)\n        }\n    } \n    .send()\n```\n\n**Some upload requests do not immediately download files**\n\n\ne.g `VK.API.Upload.Photo.toMessage` will return `photoId`\nwhich you can use in `messages.send` method.\nSee [docs](https://vk.com/dev/upload_files) for more info.\n## **Interaction with LongPoll**\n\n## Start LongPoll\n\nWith SwiftyVK you can interact with VK [LongPoll](https://vk.com/dev/using_longpoll) server very easily.\nJust call:\n\n```swift\nVK.sessions.default.longPoll.start {\n    // This callback will be executed each time\n    // long poll client receives a set of new events\n    print($0)\n}\n```\n\n## Handle updates\n\nData format is described [here](https://vk.com/dev/using_longpoll).\nLongPollEvent is an enum with associated value of type `Data` in each case.\nYou can parse this data to JSON using your favorite parser like this:\n\n```swift\nVK.sessions.default.longPoll.start {\n    for event in $0 {\n        switch event {\n            case let .type1(data):\n                let json = JSON(data)\n                print(json)\n            default:\n                break\n        }\n    }\n}\n```\n\nLongPollEvent has two special cases:\n\n`.forcedStop` - returned when LongPoll has experienced unexpected error and stop. You can restart it again.\n\n`.historyMayBeLost` - returned when LongPoll was disconnected from server for a long time\nand either `lpKey` or `timestamp` is outdated.\nYou do not need to reconnect LongPoll manually, client will do it itself.\nUse this case to **refresh data that could have been updated while network was unavailable**.\n\n## Stop LongPoll\n\nIf you don't need to receive LongPoll updates anymore, just call this function:\n```swift\nVK.sessions.default.longPoll.stop()\n```\n\n## **Share dialog**\n\nWith SwiftyVK can make a post to user wall. To do this, you need:\n\n- [Implement SwiftyVKDelegate](#implement-swiftyvkdelegate)\n- [SetUp VK application](#setting-up-vk-application)\n- Present share dialog with context:\n\n```swift\nVK.sessions.default.share(\n    ShareContext(\n        text: \"This post made with #SwiftyVK 🖖🏽\",\n        images: [\n            ShareImage(data: data, type: .jpg), // JPG image representation\n        ],\n        link: ShareLink(\n            title: \"Follow the white rabbit\", // Link description\n            url: link // URL to site\n        )\n    ),\n    onSuccess: { /* Handle response */ },\n    onError: { /* Handle error */ }\n```\n\n***Images and link are optional, text is required***\n***Sharing not available on macOS 10.10. If you want to use it, please make pull request to this repo.***\n\n## **FAQ**\n\n[I can't find some API method or parameter in library](https://github.com/SwiftyVK/SwiftyVK/wiki/I-can't-find-some-API-method-or-parameter-in-library)\n\n## **License**\n\nSwiftyVK is released under the MIT license.\nSee [LICENSE](./LICENSE.txt) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSwiftyVK%2FSwiftyVK","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSwiftyVK%2FSwiftyVK","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSwiftyVK%2FSwiftyVK/lists"}