{"id":2599,"url":"https://github.com/cely-tools/Cely","last_synced_at":"2025-08-06T13:31:47.571Z","repository":{"id":56905746,"uuid":"71150044","full_name":"cely-tools/Cely","owner":"cely-tools","description":"Plug-n-Play login system for iOS written in Swift","archived":false,"fork":false,"pushed_at":"2020-02-23T07:25:42.000Z","size":2220,"stargazers_count":166,"open_issues_count":5,"forks_count":17,"subscribers_count":25,"default_branch":"master","last_synced_at":"2024-11-21T07:05:37.765Z","etag":null,"topics":["keychain","login","swift"],"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/cely-tools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-17T14:57:08.000Z","updated_at":"2024-08-15T10:52:04.000Z","dependencies_parsed_at":"2022-08-20T18:50:37.534Z","dependency_job_id":null,"html_url":"https://github.com/cely-tools/Cely","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cely-tools%2FCely","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cely-tools%2FCely/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cely-tools%2FCely/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cely-tools%2FCely/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cely-tools","download_url":"https://codeload.github.com/cely-tools/Cely/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228905434,"owners_count":17989763,"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":["keychain","login","swift"],"created_at":"2024-01-05T20:16:17.999Z","updated_at":"2024-12-09T14:30:36.834Z","avatar_url":"https://github.com/cely-tools.png","language":"Swift","funding_links":[],"categories":["UI","Libs"],"sub_categories":["Login","Authentication"],"readme":"\u003cdiv style=\"text-align:center\"\u003e\u003cimg src =\"Images/READMEHeader.png\" /\u003e\u003c/div\u003e\n\n![Swift 4.0](https://img.shields.io/badge/Swift-3.0-orange.svg?style=flat)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![CocoaPods compatible](https://img.shields.io/cocoapods/v/Cely.svg)](https://cocoapods.org/pods/Cely)\n[![Cookiecutter-Swift](https://img.shields.io/badge/cookiecutter--swift-framework-red.svg)](http://github.com/cookiecutter-swift/Framework)\n[![Build Status](https://app.bitrise.io/app/aff729145cb46dfe/status.svg?token=YUV0bymd7P_w2tdiKw2xOQ\u0026branch=master)](https://app.bitrise.io/app/aff729145cb46dfe)\n[![codecov](https://codecov.io/gh/initFabian/Cely/branch/master/graph/badge.svg)](https://codecov.io/gh/initFabian/Cely)\n\u003e Prounounced Cell-Lee\n\nCely’s goal is to add a login system into your app in under 30 seconds!\n\n- [Overview](#overview)\n- [Requirements](#requirements)\n- [Usage](#usage)\n- [API](#api)\n- [Installation](#installation)\n- [License](#license)\n\n## Overview\nCely's goal is to add a login system into your app in under 30 seconds! \n\n\u003cimg style=\"height: 600px\" src =\"Images/background_cely_login.gif\" /\u003e\n\n### Background\nWhether you're building an app for a client or for a hackathon, building a login system, no matter how basic it is, can be very tedious and time-consuming. Cely's architecture has been battle tested on countless apps, and Cely guarantees you a fully functional login system in a fraction of the time. You can trust Cely is handling login credentials correctly as well since Cely is built on top of [Locksmith](https://github.com/matthewpalmer/Locksmith), swift's most popular Keychain wrapper. \n\n#### Details:\nWhat does Cely does for you? \n\n1. Simple API to store user creditials and information **securely**\n - `Cely.save(\"SUPER_SECRET_STRING\", forKey: \"token\", securely: true)`\n2. Manages switching between your app's Home Screen and Login Screen with:\n - `Cely.changeStatus(to: .loggedIn) // or .loggedOut`\n3. Customizable starter Login screen(or you can use your login screen)\n \nWhat Cely **does not do** for you? \n\n1. Network requests\n2. Handle Network errors\n3. Anything with the network \n\n## Requirements\n\n- iOS 11.0+ \u003c!-- / Mac OS X 10.10+ / tvOS 9.0+ / watchOS 2.0+ --\u003e\n- Xcode 9.0+\n- Swift 4.0+\n\n## Usage\n\n### Setup(30 seconds)\n\n#### User Model (`User.swift`)\nLet's start by creating a `User` model that conforms to the [`CelyUser`](#Cely.CelyUser) Protocol:\n\n```swift\n// User.swift\n\nimport Cely\n\nstruct User: CelyUser {\n\n  enum Property: CelyProperty {\n    case token = \"token\"\n  }\n}\n\n```\n#### Login redirect(`AppDelegate.swift`)\n\nCely's **Simple Setup** function will get you up and running in a matter of seconds. Inside of your `AppDelegate.swift` simply `import Cely` and call the [`setup(_:)`](#Cely.setup) function inside of your `didFinishLaunchingWithOptions` method.\n\n```swift\n// AppDelegate.swift\n\nimport Cely\n\nfunc application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: Any]?) -\u003e Bool {\n  \n  Cely.setup(with: window, forModel: User(), requiredProperties: [.token])\n  \n  ...\n}\n```\n\n\u003ch3 style=\"text-align: center\"\u003eHit RUN!!\u003c/h3\u003e\n\n### CelyOptions\n#### Handle Login Credentials\nNow how do we get the `username` and `password` from Cely's default LoginViewController? It's easy, just pass in a completion block for the `.loginCompletionBlock`. Check out [`CelyOptions`](#Cely.CelyOptions) for more info.\n\n```swift\n\nfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -\u003e Bool {\n\n    Cely.setup(with: window!, forModel: User(), requiredProperties: [.token], withOptions: [\n        .loginCompletionBlock: { (username: String, password: String) in\n            if username == \"asdf\" \u0026\u0026 password == \"asdf\" {\n                Cely.save(username, forKey: \"username\")\n                Cely.save(\"FAKETOKEN:\\(username)\\(password)\", forKey: \"token\", securely: true)\n                Cely.changeStatus(to: .loggedIn)\n            }\n        }\n    ])\n\n    return true\n}\n```\n#### Customize Default Login Screen\n\nCreate an object that conforms to the [`CelyStyle`](#Cely.CelyStyle) protocol and set it to `.loginStyle` inside of the [`CelyOptions`](#Cely.CelyOptions) dictionary when calling Cely's [`setup(_:)`](#Cely.setup) method.\n\n```swift\n// LoginStyles.swift\nstruct CottonCandy: CelyStyle {\n    func backgroundColor() -\u003e UIColor {\n        return UIColor(red: 86/255, green: 203/255, blue: 249/255, alpha: 1) // Changing Color\n    }\n    func buttonTextColor() -\u003e UIColor {\n        return .white\n    }\n    func buttonBackgroundColor() -\u003e UIColor {\n       return UIColor(red: 253/255, green: 108/255, blue: 179/255, alpha: 1) // Changing Color\n    }\n    func textFieldBackgroundColor() -\u003e UIColor {\n        return UIColor.white.withAlphaComponent(0.4)\n    }\n    func appLogo() -\u003e UIImage? {\n        return UIImage(named: \"CelyLogo\")\n    }\n}\n\n...\n\n// AppDelegate.swift\n\nfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -\u003e Bool {\n\n    Cely.setup(with: window!, forModel: User.ref, requiredProperties: [.token], withOptions: [\n        .loginStyle: CottonCandy(), // \u003c--- HERE!!\n        .loginCompletionBlock: { ... }        \n    ])\n\n    return true\n}\n\n```\n\n#### Customize Transitions\nIn order to create a custom transition, create an object that conforms to [`CelyAnimator`](#Cely.CelyAnimator) protocol and set it to `.celyAnimator` inside of the [`CelyOption`](#Cely.CelyOptions) dictionary when calling Cely's [`setup(_:)`](#Cely.setup) method.\n\n```swift\nstruct DefaultAnimator: CelyAnimator {\n    func loginTransition(to destinationVC: UIViewController?, with celyWindow: UIWindow) {\n        guard let snapshot = celyWindow.snapshotView(afterScreenUpdates: true) else {\n            return\n        }\n\n        destinationVC?.view.addSubview(snapshot)\n        // Set the rootViewController of the `celyWindow` object\n        celyWindow.setCurrentViewController(to: destinationVC)\n\n        // Below here is where you can create your own animations\n        UIView.animate(withDuration: 0.5, animations: {\n            // Slide login screen to left\n            snapshot.transform = CGAffineTransform(translationX: 600.0, y: 0.0)\n        }, completion: {\n            (value: Bool) in\n            snapshot.removeFromSuperview()\n        })\n    }\n\n    func logoutTransition(to destinationVC: UIViewController?, with celyWindow: UIWindow) {\n        guard let snapshot = celyWindow.snapshotView(afterScreenUpdates: true) else {\n            return\n        }\n\n        destinationVC?.view.addSubview(snapshot)\n        // Set the rootViewController of the `celyWindow` object\n        celyWindow.setCurrentViewController(to: destinationVC)\n\n        // Below here is where you can create your own animations\n        UIView.animate(withDuration: 0.5, animations: {\n            // Slide home screen to right\n            snapshot.transform = CGAffineTransform(translationX: -600.0, y: 0.0)\n        }, completion: {\n            (value: Bool) in\n            snapshot.removeFromSuperview()\n        })\n    }\n}\n\n...\n\n// AppDelegate.swift\n\nfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -\u003e Bool {\n\n    Cely.setup(with: window!, forModel: User.ref, requiredProperties: [.token], withOptions: [\n    .celyAnimator: CustomAnimator(), // \u003c--- HERE!!\n    .loginCompletionBlock: { ... }        \n    ])\n\n    return true\n}\n\n```\n\n\n#### Use your own Screens\nTo use your own login screen, simply create a storyboard that contains your login screen and pass that in as `.loginStoryboard` inside of the [`CelyOptions`](#Cely.CelyOptions) dictionary when calling Cely's [`setup(_:)`](#Cely.setup) method. \n\nLastly, if your app uses a different storyboard other than `Main.storyboard`, you can pass that in as `.homeStoryboard`.\n\n**⚠️⚠️⚠️⚠️ Be sure to make your Login screen as the `InitialViewController` inside of your storyboard!⚠️⚠️⚠️⚠️**\n\n```swift\n\n// AppDelegate.swift\n\nfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -\u003e Bool {\n\n    Cely.setup(with: window!, forModel: User.ref, requiredProperties: [.token], withOptions: [\n        .loginStoryboard: UIStoryboard(name: \"MyCustomLogin\", bundle: nil),\n        .homeStoryboard: UIStoryboard(name: \"NonMain\", bundle: nil)\n    ])\n\n    return true\n}\n\n```\n\n### Recommended User Pattern\n\n```swift\nimport Cely\n\nstruct User: CelyUser {\n\n    enum Property: CelyProperty {\n        case username = \"username\"\n        case email = \"email\"\n        case token = \"token\"\n\n        func securely() -\u003e Bool {\n            switch self {\n            case .token:\n                return true\n            default:\n                return false\n            }\n        }\n\n        func persisted() -\u003e Bool {\n            switch self {\n            case .username:\n                return true\n            default:\n                return false\n            }\n        }\n\n        func save(_ value: Any) {\n            Cely.save(value, forKey: rawValue, securely: securely(), persisted: persisted())\n        }\n\n        func get() -\u003e Any? {\n            return Cely.get(key: rawValue)\n        }\n    }\n}\n\n// MARK: - Save/Get User Properties\n\nextension User {\n\n    static func save(_ value: Any, as property: Property) {\n        property.save(value: value)\n    }\n\n    static func save(_ data: [Property : Any]) {\n        data.forEach { property, value in\n            property.save(value)\n        }\n    }\n\n    static func get(_ property: Property) -\u003e Any? {\n        return property.get()\n    }\n}\n\n```\n\nThe reason for this pattern is to make saving data as easy as:\n\n```swift\n// Pseudo network code, NOT REAL CODE!!!\nApiManager.logUserIn(\"username\", \"password\") { json in\n  let apiToken = json[\"token\"].string\n  \n  // REAL CODE!!!\n  User.save(apiToken, as: .token)\n}\n\n```\nand getting data as simple as:\n\n```swift\nlet token = User.get(.token)\n```\n\n## API\n\n### Cely\nCely was made to help handle user credentials and handling login with ease. Below you will find documentation for Cely's Framework. **Please do not hesitate to open an issue if something is unclear or is missing.** \n#### Variables\n\u003cdiv id=\"Cely.store\"\u003e\u003c/div\u003e\n\n##### `store`\n\nA class that conforms to the [`CelyStorageProtocol`](#Cely.CelyStorageProtocol) protocol. By default is set to a singleton instance of `CelyStorage`.\n\n\n#### Methods\n\n\u003cdiv id=\"Cely.setup\"\u003e\u003c/div\u003e\n\n##### `setup(with:forModel:requiredProperties:withOptions:)`\n\nSets up Cely within your application\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```swift\nCely.setup(with: window, forModel: User(), requiredProperties:[.token])\n\n// or \n\nCely.setup(with: window, forModel: User(), requiredProperties:[.token], withOptions:[\n  .loginStoryboard: UIStoryboard(name: \"MyCustomLogin\", bundle: nil),\n  .HomeStoryboard: UIStoryboard(name: \"My_NonMain_Storyboard\", bundle: nil),\n  .loginCompletionBlock: { (username: String, password: String) in\n        if username == \"asdf\" \u0026\u0026 password == \"asdf\" {\n            print(\"username: \\(username): password: \\(password)\")\n        }\n    }\n])\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eParameters\u003c/summary\u003e\n\nKey | Type| Required? | Description\n----|------|----------|--------\n`window` | `UIWindow` | ✅ | window of your application.\n`forModel` | [`CelyUser`](#Cely.CelyUser) | ✅ | The model Cely will be using to store data.\n`requiredProperties` | `[CelyProperty]` | no | The properties that cely tests against to determine if a user is logged in. \u003cbr\u003e **Default value**: empty array.\n`options` | `[CelyOption]` | no | An array of [`CelyOptions`](#Cely.CelyOptions) to pass in additional customizations to cely.\n\n\u003c/details\u003e\n\n\n\u003cdiv id=\"Cely.currentLoginStatus\"\u003e\u003c/div\u003e\n\n##### `currentLoginStatus(requiredProperties:fromStorage:)`\n\nWill return the `CelyStatus` of the current user.\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```swift\nlet status = Cely.currentLoginStatus()\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eParameters\u003c/summary\u003e\n\nKey | Type| Required? | Description\n----|------|----------|--------\n`properties` | [`CelyProperty`] | no | Array of required properties that need to be in store.\n`store` | `CelyStorage` | no |    Storage `Cely` will be using. Defaulted to `CelyStorage`\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType| Description\n----|------\n[`CelyStatus`](#Cely.CelyStatus) | If `requiredProperties` are all in store, it will return `.loggedIn`, else `.loggedOut`\n\n\u003c/details\u003e\n\n\n\u003cdiv id=\"Cely.get\"\u003e\u003c/div\u003e\n\n##### `get(_:fromStorage:)`\n\nReturns stored data for key.\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```swift\nlet username = Cely.get(key: \"username\")\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eParameters\u003c/summary\u003e\n\nKey | Type| Required? | Description\n----|------|----------|--------\n`key` | String | ✅ | The key to the value you want to retrieve.\n`store` | CelyStorage | no | Storage `Cely` will be using. Defaulted to `CelyStorage`\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType| Description\n----|------\n`Any?` | Returns an `Any?` object in the case the value nil(not found).\n\n\u003c/details\u003e\n\n\n\n\n\u003cdiv id=\"Cely.save\"\u003e\u003c/div\u003e\n\n##### `save(_:forKey:toStorage:securely:persisted:)`\n\nSaves data in store\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```swift\nCely.save(\"test@email.com\", forKey: \"email\")\nCely.save(\"testUsername\", forKey: \"username\", persisted: true)\nCely.save(\"token123\", forKey: \"token\", securely: true)\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eParameters\u003c/summary\u003e\n\nKey | Type| Required? | Description\n----|------|----------|--------\n`value` | \u003ccode\u003e**Any?**\u003c/code\u003e | ✅ | The value you want to save to storage.\n`key` | \u003ccode\u003e**String**\u003c/code\u003e | ✅ | The key to the value you want to save.\n`store` | \u003ccode\u003e**CelyStorage**\u003c/code\u003e | no | Storage `Cely` will be using. Defaulted to `CelyStorage`.\n`secure` | \u003ccode\u003e**Boolean**\u003c/code\u003e | no | If you want to store the value securely.\n`persisted` | \u003ccode\u003e**Boolean**\u003c/code\u003e | no | Keep data after logout.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType| Description\n----|------\n  `StorageResult` | Whether or not your value was successfully set.\n\n\u003c/details\u003e\n\n\n\u003cdiv id=\"Cely.changeStatus\"\u003e\u003c/div\u003e\n\n##### `changeStatus(to:)`\n\nPerform action like `LoggedIn` or `LoggedOut`.\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```swift\nchangeStatus(to: .loggedOut)\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eParameters\u003c/summary\u003e\n\nKey | Type| Required? | Description\n----|------|----------|--------\n`status` | \u003ccode\u003e**CelyStatus**\u003c/code\u003e | ✅ | enum value\n\n\u003c/details\u003e\n\n\n\u003cdiv id=\"Cely.logout\"\u003e\u003c/div\u003e\n\n##### `logout(usesStorage:)`\n\nConvenience method to logout user. Is equivalent to `changeStatus(to: .loggedOut)`\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n\n```swift\nCely.logout()\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eParameters\u003c/summary\u003e\n\nKey | Type| Required? | Description\n----|------|----------|--------\n`store` | \u003ccode\u003e**CelyStorage**\u003c/code\u003e | no | Storage `Cely` will be using. Defaulted to `CelyStorage`.\n\n\u003c/details\u003e\n\n\n\u003cdiv id=\"Cely.isLoggedIn\"\u003e\u003c/div\u003e\n\n##### `isLoggedIn()`\n\nReturns whether or not the user is logged in\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```swift\nCely.isLoggedIn()\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType| Description\n----|------\n`Boolean` | Returns whether or not the user is logged in\n\n\u003c/details\u003e\n\n\n### Constants\n#### Protocols\n\u003cdiv id=\"Cely.CelyUser\"\u003e\u003c/div\u003e\n\n##### `CelyUser `\n\n`protocol` for model class to implements\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```swift\nimport Cely\n\nstruct User: CelyUser {\n\n  enum Property: CelyProperty {\n    case token = \"token\"\n  }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eRequired\u003c/summary\u003e\n\nvalue | Type| Description\n----|------|---\n`Property ` | `associatedtype` | Enum of all the properties you would like to save for a model\n\n\u003c/details\u003e\n\n\u003cdiv id=\"Cely.CelyStorageProtocol\"\u003e\u003c/div\u003e\n\n##### `CelyStorageProtocol `\n\n`protocol` a storage class must abide by in order for Cely to use it\n\n\u003cdetails\u003e\n\u003csummary\u003eRequired\u003c/summary\u003e\n\n```swift\nfunc set(_ value: Any?, forKey key: String, securely secure: Bool, persisted: Bool) -\u003e StorageResult\nfunc get(_ key: String) -\u003e Any?  \nfunc removeAllData()  \n\n```    \n\u003c/details\u003e\n\n\u003cdiv id=\"Cely.CelyStyle\"\u003e\u003c/div\u003e\n\n\n##### `CelyStyle`\n\nThe `protocol` an object must conform to in order to customize Cely's default login screen. Since all methods are optional, Cely will use the default value for any unimplemented methods.\n\n\u003cdetails\u003e\n\u003csummary\u003eMethods\u003c/summary\u003e\n\n```swift\nfunc backgroundColor() -\u003e UIColor\nfunc textFieldBackgroundColor() -\u003e UIColor\nfunc buttonBackgroundColor() -\u003e UIColor\nfunc buttonTextColor() -\u003e UIColor\nfunc appLogo() -\u003e UIImage?\n\n```    \n\u003c/details\u003e\n\n\u003cdiv id=\"Cely.CelyAnimator\"\u003e\u003c/div\u003e\n\n\n##### `CelyAnimator`\n\nThe `protocol` an object must conform to in order to customize transitions between home and login screens.\n\n\u003cdetails\u003e\n\u003csummary\u003eMethods\u003c/summary\u003e\n\n```swift\nfunc loginTransition(to destinationVC: UIViewController?, with celyWindow: UIWindow)\nfunc logoutTransition(to destinationVC: UIViewController?, with celyWindow: UIWindow)\n\n```    \n\u003c/details\u003e\n\n#### Typealias\n\u003cdiv id=\"Cely.CelyProperty\"\u003e\u003c/div\u003e\n\n##### `CelyProperty `\n\n`String` type alias. Is used in User model\n\n\u003cdiv id=\"Cely.CelyCommands\"\u003e\u003c/div\u003e\n\n##### `CelyCommands `\n\n`String` type alias. Command for cely to execute\n\n#### enums\n\u003cdiv id=\"Cely.CelyOptions\"\u003e\u003c/div\u003e\n\n##### `CelyOptions`\n\n`enum` Options that you can pass into Cely on [`setup(with:forModel:requiredProperties:withOptions:)`](#Cely.setup)\n\n\u003cdetails\u003e\n\u003csummary\u003eOptions\u003c/summary\u003e\n\nCase | Description\n----|------\n`storage ` | Pass in you're own storage class if you wish not to use Cely's default storage. Class must conform to the `CelyStorage` protocol.\n`homeStoryboard ` | Pass in your app's default storyboard if it is not named \"Main\"\n`loginStoryboard ` | Pass in your own login storyboard.\n`loginStyle` | Pass in an object that conforms to [`CelyStyle`](#Cely.CelyStyle) to customize the default login screen.\n`loginCompletionBlock ` | `(String,String) -\u003e Void` block of code that will run once the Login button is pressed on Cely's default login Controller\n`celyAnimator` | Pass in an object that conforms to [`CelyAnimator`](#Cely.CelyAnimator) to customize the default login screen.\n\n\u003c/details\u003e\n\u003cdiv id=\"Cely.CelyStatus\"\u003e\u003c/div\u003e\n\n##### `CelyStatus`\n\n`enum` Statuses for Cely to perform actions on\n\n\u003cdetails\u003e\n\u003csummary\u003eStatuses\u003c/summary\u003e\n\nCase | Description\n----|------\n`loggedIn ` | Indicates user is now logged in.\n`loggedOut ` | Indicates user is now logged out.\n\n\u003c/details\u003e\n\n\u003cdiv id=\"Cely.StorageResult\"\u003e\u003c/div\u003e\n\n##### `StorageResult `\n\n`enum` result on whether or not Cely successfully saved your data.\n\n\u003cdetails\u003e\n\u003csummary\u003eResults\u003c/summary\u003e\n\nCase| Description\n----|------\n`success ` | Successfully saved your data\n`fail(error) ` | Failed to save data along with a `LocksmithError`. \n\n\u003c/details\u003e\n\n## Installation\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```bash\n$ gem install cocoapods\n```\n\n\u003e CocoaPods 1.1.0+ is required to build Cely 2.0.0+.\n\nTo integrate Cely into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n```ruby\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '8.0'\nuse_frameworks!\n\npod 'Cely', '~\u003e 2.1'\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\n### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application.\n\nYou can install Carthage with [Homebrew](http://brew.sh/) using the following command:\n\n```bash\n$ brew update\n$ brew install carthage\n```\n\nTo integrate Cely into your Xcode project using Carthage, specify it in your `Cartfile`:\n\n```ogdl\ngithub \"initFabian/Cely\" ~\u003e 2.1\n```\n\n### Manually\n\nIf you prefer not to use either of the aforementioned dependency managers, you can integrate Cely into your project manually.\n\n#### Git Submodules\n\n- Open 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```bash\n$ git init\n```\n\n- Add Cely as a git [submodule](http://git-scm.com/docs/git-submodule) by running the following command:\n\n```bash\n$ git submodule add https://github.com/initFabian/Cely.git\n$ git submodule update --init --recursive\n```\n\n- Open the new `Cely` folder, and drag the `Cely.xcodeproj` into the Project Navigator of your application's Xcode project.\n\n    \u003e It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.\n\n- Select the `Cely.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.\n- Next, 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- In the tab bar at the top of that window, open the \"General\" panel.\n- Click on the `+` button under the \"Embedded Binaries\" section.\n- You will see two different `Cely.xcodeproj` folders each with two different versions of the `Cely.framework` nested inside a `Products` folder.\n\n    \u003e It does not matter which `Products` folder you choose from.\n\n- Select the `Cely.framework`.\n\n- And that's it!\n\n\u003e The `Cely.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.\n\n#### Embeded Binaries\n\n- Download the latest release from https://github.com/initFabian/Cely/releases\n- Next, 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- In the tab bar at the top of that window, open the \"General\" panel.\n- Click on the `+` button under the \"Embedded Binaries\" section.\n- Add the downloaded `Cely.framework`.\n- And that's it!\n\n## License\n\nCely is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcely-tools%2FCely","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcely-tools%2FCely","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcely-tools%2FCely/lists"}