{"id":13497634,"url":"https://github.com/Oyvindkg/swiftydb","last_synced_at":"2025-03-28T22:31:48.362Z","repository":{"id":56341174,"uuid":"48343151","full_name":"Oyvindkg/swiftydb","owner":"Oyvindkg","description":"💀Neither supported nor maintained for years. A type-safe, protocol-based, pure Swift database offering effortless persistence of any object","archived":true,"fork":false,"pushed_at":"2020-11-13T11:16:38.000Z","size":4236,"stargazers_count":488,"open_issues_count":11,"forks_count":34,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-03-02T14:38:02.594Z","etag":null,"topics":["database","protocol-oriented","swift","swiftydb"],"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/Oyvindkg.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}},"created_at":"2015-12-21T00:53:52.000Z","updated_at":"2024-10-29T07:13:28.000Z","dependencies_parsed_at":"2022-08-15T17:00:21.970Z","dependency_job_id":null,"html_url":"https://github.com/Oyvindkg/swiftydb","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oyvindkg%2Fswiftydb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oyvindkg%2Fswiftydb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oyvindkg%2Fswiftydb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oyvindkg%2Fswiftydb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Oyvindkg","download_url":"https://codeload.github.com/Oyvindkg/swiftydb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246110256,"owners_count":20725022,"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":["database","protocol-oriented","swift","swiftydb"],"created_at":"2024-07-31T20:00:34.883Z","updated_at":"2025-03-28T22:31:47.959Z","avatar_url":"https://github.com/Oyvindkg.png","language":"Swift","funding_links":[],"categories":["Database"],"sub_categories":[],"readme":"![Logo](http://i.imgur.com/uQhXJLJ.png)\n\nThere are many libraries out there that aims to help developers easily create and use SQLite databases. \nUnfortunately developers still have to get bogged down in simple tasks such as writing table definitions \nand SQL queries. SwiftyDB automatically handles everything you don't want to spend your time doing.\n\n[![CI Status](https://img.shields.io/travis/Oyvindkg/swiftydb/master.svg?style=flat)](https://travis-ci.org/Oyvindkg/swiftydb)\n[![Version](https://img.shields.io/cocoapods/v/SwiftyDB.svg?style=flat)](http://cocoapods.org/pods/SwiftyDB)\n[![License](https://img.shields.io/cocoapods/l/SwiftyDB.svg?style=flat)](http://cocoapods.org/pods/SwiftyDB)\n[![Platform](https://img.shields.io/cocoapods/p/SwiftyDB.svg?style=flat)](http://cocoapods.org/pods/SwiftyDB)\n[![Swift](https://img.shields.io/badge/swift-2-brightgreen.svg?style=flat)](http://cocoapods.org/pods/SwiftyDB)\n\nYou can find the [documentation here](http://oyvindkg.github.io/swiftydb/docs/)\n\n**Content**\u003cbr /\u003e\n[Features](#features)\u003cbr /\u003e\n[Usage](#usage)\u003cbr /\u003e\n\u0026emsp; [Access the database](#accessTheDatabase)\u003cbr /\u003e\n\u0026emsp;\u0026emsp; [Synchronous access](#syncAccess)\u003cbr /\u003e\n\u0026emsp;\u0026emsp; [Aynchronous access](#asyncAccess)\u003cbr /\u003e\n\u0026emsp; [Result format](#resultFormat)\u003cbr /\u003e\n\u0026emsp; [Filter results](#filterResults)\u003cbr /\u003e\n\u0026emsp; [Defining your classes](#definingYourClasses)\u003cbr /\u003e\n\u0026emsp;\u0026emsp; [Primary keys](#primaryKeys)\u003cbr /\u003e\n\u0026emsp;\u0026emsp; [Ignoring properties](#ignoringProperties)\u003cbr /\u003e\n\u0026emsp; [How to retrieve objects](#howToRetrieveObjects)\u003cbr /\u003e\n[Installation](#installation)\u003cbr /\u003e\n[License](#license)\n\n### \u003ca name=\"features\"\u003eFeatures\u003c/a\u003e\n- [x] Creates and updates databases, tables, and records automatically\n- [x] Supports optional types\n- [x] Simple equality-based filtering\n- [x] Thread safe database operations\n- [x] Supports asynchronous database access\n- [x] 100% documented\n- [x] Complex filtering\n- [x] Store collections\n- [ ] Store nested objects\n- [ ] Automated migration\n- [ ] Custom indices\n\n## \u003ca name=\"usage\"\u003eUsage\u003c/a\u003e\n\nAlmost pure plug and play. All you have to do is create an instance of SwiftyDB, and everything will be handled automagically behind the scenes 🎩\n\n### \u003ca name=\"accessTheDatabase\"\u003eAccess the database\u003c/a\u003e\n\nTell SwiftyDB what you want to call your database, and you are ready to go. If a database with the provided name does not exist, it will be created.\n\n```Swift\nlet database = SwiftyDB(databaseName: \"dogtopia\")\n```\n\n#### \u003ca name=\"syncAccess\"\u003eSynchronous access\u003c/a\u003e\n\n##### \u003ca name=\"syncAddOrUpdate\"\u003eAdd or update a record\u003c/a\u003e\n```Swift\ndatabase.addObject(dog, update: true)\ndatabase.addObjects(dogs, update: true)\n````\n\n##### \u003ca name=\"syncRetrieveData\"\u003eRetrieve data\u003c/a\u003e\n\nRetrieve data with datatypes matching those of the type's properties\n```Swift\n/* Array of dictionaries representing `Dog` objects from the database */\ndatabase.dataForType(Dog.self)\ndatabase.dataForType(Dog.self, matchingFilters: [\"id\": 1])\n````\nDog data example\n```Swift\n[\n    \"id\": 1,                // As an Int\n    \"name\": \"Ghost\",        // As a String\n    \"owner\": \"John Snow\",   // As a String\n    \"birth\": August 6, 1996 // As an NSDate\n]\n```\n\n##### \u003ca name=\"syncRetrieveObjects\"\u003eRetrieve objects\u003c/a\u003e\n\nRetrieve objects with data from the database\n```Swift\ndatabase.objectsForType(Dog.self)\ndatabase.objectsForType(Dog.self, matchingFilters: [\"id\": 1])\n````\n\n\u003e In order to retrieve objects, Swift currently imposes some [restictions on your classes](#howToRetrieveObjects)\n\n##### \u003ca name=\"syncDelete\"\u003eDelete records\u003c/a\u003e\n```Swift\ndatabase.deleteObjectsForType(Dog.self)\ndatabase.deleteObjectsForType(Dog.self, matchingFilters: [\"name\": \"Max\"])\n```\n\n#### \u003ca name=\"asyncAccess\"\u003eAsynchronous access\u003c/a\u003e\n\n##### \u003ca name=\"asyncAddOrUpdate\"\u003eAdd or update a record\u003c/a\u003e\n```Swift\ndatabase.asyncAddObject(dog) { (result) -\u003e Void in\n    if let error = result.error {\n        // Handle error\n    }\n}\n````\n\n##### \u003ca name=\"asyncRetrieveData\"\u003eRetrieve data\u003c/a\u003e\n\nRetrieve data with datatypes matching those of the type's properties\n```Swift\ndatabase.asyncDataForType(Dog.self) { (result) -\u003e Void in\n    if let data = result.value {\n        // Process data\n    }\n}\n````\n\n##### \u003ca name=\"asyncRetrieveObjects\"\u003eRetrieve objects\u003c/a\u003e\n\nRetrieve data with datatypes matching those of the type's properties\n```Swift\ndatabase.asyncObjectsForType(Dog.self) { (result) -\u003e Void in\n    if let objects = result.value {\n        // Handle objects\n    }\n}\n````\n\n\u003e In order to retrieve objects, Swift currently imposes some [restictions on your classes](#howToRetrieveObjects)\n\n##### \u003ca name=\"asyncDelete\"\u003eDelete records\u003c/a\u003e\n```Swift\ndatabase.asyncDeleteObjectsForType(Dog.self) { (result) -\u003e Void in\n    if let error = result.error {\n        // Handle error\n    }\n}\n```\n\n### \u003ca name=\"filterResults\"\u003eFilter results\u003c/a\u003e\n\n`Filter` objects are used to filter queries. All filters are translated to SQLite before querying the database.\n\n#### \u003ca name=\"simpleFilters\"\u003eSimple filters\u003c/a\u003e\nThe easiest way to define your filter, is by using a dictionary:\n```Swift\ndatabase.objectsForType(Dog.self, matchingFilters: [\"name\": \"Ghost\"])\n```\nAll objects with the name 'Ghost' will be retrieved\n\n#### \u003ca name=\"complexFilters\"\u003eComplex filters\u003c/a\u003e\n\nFor more complex filters, you can instantiate a new `Filter` object, and define your filters\n\n```Swift\nlet filter = Filter.equal(\"name\", value: \"Ghost\")\n                   .like(\"owner\", pattern: \"J_h%\")\n                   .greaterThan(\"id\", value: 3)\n\ndatabase.objectsForType(Dog.self, matchingFilters: filter)\n```\n\nSee all available filters in the [documentation](http://oyvindkg.github.io/swiftydb/docs/Classes/Filter.html).\n\n\u003e It is not possible to filter results using the content of stored collections as these are stored as blobs in the database\n\n### \u003ca name=\"resultFormat\"\u003eResult format\u003c/a\u003e\n\nAll queries returns the result as a `Result`. It will either be a `.Success` wrapping data from the query, or an `.Error` wrapping the thrown error.\n\n```Swift\nenum Result\u003cA: Any\u003e: BooleanType {\n    case Success(A)\n    case Error(ErrorType)\n    \n    var data: A?\n    var error: ErrorType?\n    var isSuccess: Bool\n    var boolValue: Bool {return isSuccess}\n}\n```\n\n#### \u003ca name=\"handlingResults\"\u003eHandling results\u003c/a\u003e\nThe implementation of `Result` makes it a versatile tool that can (hopefully 😬) be adapted to your programming style\n\n##### \u003ca name=\"handlingValues\"\u003eHandling values\u003c/a\u003e\nYou can capture the data from a query with the `value` property. If an error was thrown, this property will be `nil`.\n\n```Swift\nif let object = result.value {\n    // Process objects\n}\n```\n\n##### \u003ca name=\"handlingErrors\"\u003eHandling errors\u003c/a\u003e\nYou can detect an error like this\n```Swift\nif !database.addObject(dog) {\n    // An error occured\n}\n```\nor capture it using the `error` property like this\n\n```Swift\nif let error = result.error {\n    // Process objects\n}\n```\nIf you want to, you can even bring your sledgehammer and start cracking some nuts\n```Swift\nswitch result {\n    case .Success(let value):\n        // Process value\n    case .Error(let error):\n        // Handle error\n}\n```\n\n### \u003ca name=\"definingYourClasses\"\u003eDefining your classes\u003c/a\u003e\n\nLet's use this simple `Dog` class as an example\n\n```Swift\nclass Dog {\n    var id: Int?\n    var name: String?\n    var owner: String?\n    var birth: NSDate?\n}\n```\n\nAll objects must conform to the `Storable` protocol.\n\n```Swift\npublic protocol Storable {\n    init()\n}\n```\n\nBy adding the `Storable` protocol and implementing `init()`, you are already ready to go.\n\n```Swift\nclass Dog: Storable {\n    var id: Int?\n    var name: String?\n    var owner: String?\n    var birth: NSDate?\n    \n    required init() {}\n}\n```\n\n\u003e SwiftyDB supports inheritance. Valid properties from both the class and the superclass will be stored automatically\n\n##### \u003ca name=\"primaryKeys\"\u003ePrimary keys\u003c/a\u003e\nIt is recommended to implement the `PrimaryKeys` protocol. The `primaryKeys()` method should return a set of property names which uniquely identifies an object.\n\n```Swift\nextension Dog: PrimaryKeys {\n    class func primaryKeys() -\u003e Set\u003cString\u003e {\n        return [\"id\"]\n    }\n}\n```\n\n##### \u003ca name=\"ignoringProperties\"\u003eIgnoring properties\u003c/a\u003e\nIf your class contains properties that you don't want in your database, you can implement the `IgnoredProperties` protocol.\n\n```Swift\nextension Dog: IgnoredProperties {\n    class func ignoredProperties() -\u003e Set\u003cString\u003e {\n        return [\"name\"]\n    }\n}\n```\n\u003e Properties with datatypes that are not part of the `Value` protocol, will automatically be ignored by SwiftyDB\n\n### \u003ca name=\"howToRetrieveObjects\"\u003eHow to retrieve objects\u003c/a\u003e\n\nSwiftyDB can also retrieve complete objects with all properties assigned with data from the database. In order to achieve this, the type must be a subclass of `NSObject`, and all property types must be representable in in Objective-C. This is because pure Swift currently does not support dynamic assignment of properties. \n\n**Dynamic property types**\n- [x] `Int`\n- [x] `UInt`\n- [x] `Float`\n- [x] `Double`\n- [x] `Bool`\n- [x] `String` / `String?`\n- [x] `NSNumber` / `NSNumber?`\n- [x] `NSString` / `NSString?`\n- [x] `NSDate` / `NSDate?`\n- [x] `NSData` / `NSData?`\n\n\nAn updated Dog class that can be used to retrieve complete objects from the database:\n\n```Swift\nclass Dog: NSObject, Storable {\n    var id: NSNumber? // Notice that 'Int?' is not supported. Use NSNumber? instead\n    var name: String?\n    var owner: String?\n    var birth: NSDate?\n    \n    override required init() {\n        super.init()\n    }\n}\n```\n\n## \u003ca name=\"installation\"\u003eInstallation\u003c/a\u003e\n\nSwiftyDB is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod \"SwiftyDB\"\n```\n\n## Author\n\nØyvind Grimnes, oyvindkg@yahoo.com\n\n## \u003ca name=\"License\"\u003eLicense\u003c/a\u003e\n\nSwiftyDB 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%2FOyvindkg%2Fswiftydb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FOyvindkg%2Fswiftydb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOyvindkg%2Fswiftydb/lists"}