A type-safe, protocol-based, pure Swift database offering effortless persistence of any object

Overview

Logo

There are many libraries out there that aims to help developers easily create and use SQLite databases. Unfortunately developers still have to get bogged down in simple tasks such as writing table definitions and SQL queries. SwiftyDB automatically handles everything you don't want to spend your time doing.

CI Status Version License Platform Swift

You can find the documentation here

Content
Features
Usage
Access the database
   Synchronous access
   Aynchronous access
Result format
Filter results
Defining your classes
   Primary keys
   Ignoring properties
How to retrieve objects
Installation
License

Features

  • Creates and updates databases, tables, and records automatically
  • Supports optional types
  • Simple equality-based filtering
  • Thread safe database operations
  • Supports asynchronous database access
  • 100% documented
  • Complex filtering
  • Store collections
  • Store nested objects
  • Automated migration
  • Custom indices

Usage

Almost pure plug and play. All you have to do is create an instance of SwiftyDB, and everything will be handled automagically behind the scenes 🎩

Access the database

Tell 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.

let database = SwiftyDB(databaseName: "dogtopia")

Synchronous access

Add or update a record
database.addObject(dog, update: true)
database.addObjects(dogs, update: true)
Retrieve data

Retrieve data with datatypes matching those of the type's properties

/* Array of dictionaries representing `Dog` objects from the database */
database.dataForType(Dog.self)
database.dataForType(Dog.self, matchingFilters: ["id": 1])

Dog data example

[
    "id": 1,                // As an Int
    "name": "Ghost",        // As a String
    "owner": "John Snow",   // As a String
    "birth": August 6, 1996 // As an NSDate
]
Retrieve objects

Retrieve objects with data from the database

database.objectsForType(Dog.self)
database.objectsForType(Dog.self, matchingFilters: ["id": 1])

In order to retrieve objects, Swift currently imposes some restictions on your classes

Delete records
database.deleteObjectsForType(Dog.self)
database.deleteObjectsForType(Dog.self, matchingFilters: ["name": "Max"])

Asynchronous access

Add or update a record
database.asyncAddObject(dog) { (result) -> Void in
    if let error = result.error {
        // Handle error
    }
}
Retrieve data

Retrieve data with datatypes matching those of the type's properties

database.asyncDataForType(Dog.self) { (result) -> Void in
    if let data = result.value {
        // Process data
    }
}
Retrieve objects

Retrieve data with datatypes matching those of the type's properties

database.asyncObjectsForType(Dog.self) { (result) -> Void in
    if let objects = result.value {
        // Handle objects
    }
}

In order to retrieve objects, Swift currently imposes some restictions on your classes

Delete records
database.asyncDeleteObjectsForType(Dog.self) { (result) -> Void in
    if let error = result.error {
        // Handle error
    }
}

Filter results

Filter objects are used to filter queries. All filters are translated to SQLite before querying the database.

Simple filters

The easiest way to define your filter, is by using a dictionary:

database.objectsForType(Dog.self, matchingFilters: ["name": "Ghost"])

All objects with the name 'Ghost' will be retrieved

Complex filters

For more complex filters, you can instantiate a new Filter object, and define your filters

let filter = Filter.equal("name", value: "Ghost")
                   .like("owner", pattern: "J_h%")
                   .greaterThan("id", value: 3)

database.objectsForType(Dog.self, matchingFilters: filter)

See all available filters in the documentation.

It is not possible to filter results using the content of stored collections as these are stored as blobs in the database

Result format

All 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.

enum Result<A: Any>: BooleanType {
    case Success(A)
    case Error(ErrorType)
    
    var data: A?
    var error: ErrorType?
    var isSuccess: Bool
    var boolValue: Bool {return isSuccess}
}

Handling results

The implementation of Result makes it a versatile tool that can (hopefully 😬 ) be adapted to your programming style

Handling values

You can capture the data from a query with the value property. If an error was thrown, this property will be nil.

if let object = result.value {
    // Process objects
}
Handling errors

You can detect an error like this

if !database.addObject(dog) {
    // An error occured
}

or capture it using the error property like this

if let error = result.error {
    // Process objects
}

If you want to, you can even bring your sledgehammer and start cracking some nuts

switch result {
    case .Success(let value):
        // Process value
    case .Error(let error):
        // Handle error
}

Defining your classes

Let's use this simple Dog class as an example

class Dog {
    var id: Int?
    var name: String?
    var owner: String?
    var birth: NSDate?
}

All objects must conform to the Storable protocol.

public protocol Storable {
    init()
}

By adding the Storable protocol and implementing init(), you are already ready to go.

class Dog: Storable {
    var id: Int?
    var name: String?
    var owner: String?
    var birth: NSDate?
    
    required init() {}
}

SwiftyDB supports inheritance. Valid properties from both the class and the superclass will be stored automatically

Primary keys

It is recommended to implement the PrimaryKeys protocol. The primaryKeys() method should return a set of property names which uniquely identifies an object.

extension Dog: PrimaryKeys {
    class func primaryKeys() -> Set<String> {
        return ["id"]
    }
}
Ignoring properties

If your class contains properties that you don't want in your database, you can implement the IgnoredProperties protocol.

extension Dog: IgnoredProperties {
    class func ignoredProperties() -> Set<String> {
        return ["name"]
    }
}

Properties with datatypes that are not part of the Value protocol, will automatically be ignored by SwiftyDB

How to retrieve objects

SwiftyDB 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.

Dynamic property types

  • Int
  • UInt
  • Float
  • Double
  • Bool
  • String / String?
  • NSNumber / NSNumber?
  • NSString / NSString?
  • NSDate / NSDate?
  • NSData / NSData?

An updated Dog class that can be used to retrieve complete objects from the database:

class Dog: NSObject, Storable {
    var id: NSNumber? // Notice that 'Int?' is not supported. Use NSNumber? instead
    var name: String?
    var owner: String?
    var birth: NSDate?
    
    override required init() {
        super.init()
    }
}

Installation

SwiftyDB is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "SwiftyDB"

Author

Øyvind Grimnes, [email protected]

License

SwiftyDB is available under the MIT license. See the LICENSE file for more info.

Comments
  • TinySQLite in SwiftDB does not support Swift 3

    TinySQLite in SwiftDB does not support Swift 3

    Hi your library is using the TinySQLite library but I see it has not upgraded to Swift 3? Is the current version 2.0 support running without any problem?

    opened by dlpigpen 5
  • TinySQLite.Error: SQL error or missing database (1)

    TinySQLite.Error: SQL error or missing database (1)

    I get TinySQLite.Error: SQL error or missing database (1) when trying to save a object.

     let database = SwiftyDB(databaseName: "Elements")
    
            let element = Element()
            element.id = 1
            element.name = "hu"
    
            database.asyncAddObjects([element]) { (result) -> Void in
                if let error = result.error {
                    // Handle error
                    print(error)
                }
            }
    
    bug 
    opened by emilpedersen 5
  • Arrays?

    Arrays?

    Add support for arrays?

    class Person: NSObject, Storable {
        var person:[Children]
    }
    
    class Children: NSObject, Storable {
    
        var name:String!
        var age:NSNumber!
    }
    

    I'm getting this [testapp.Children encodeWithCoder:]: unrecognized selector sent to instance

    question 
    opened by steelzeh 3
  • Getting error on retrieving data

    Getting error on retrieving data

    I am getting a error when i am using bool or integer as data type of a attributes , its save to the data without showing any errors but then i am trying to retrieve the data its give me a error saying NSUnknownKeyException this class is not key value coding-compliant for the key

    this is my class

    class Message: NSObject,Storable{
    
        let database: SwiftyDB! = SwiftyDB(databaseName: AppConfig.DATABASE_NAME)
    
        var id : String?
        var body : String?
        var status : String?
        var timestamp : String?
        var isHide : Bool?
        var location : String?
        var msgType : String?
        var roomId : String?
        var userId : String?
    
        override required  init() {
            super.init()
        }
    
    
        func saveMesssage(shouldUpdate: Bool = false, completionHandler: (success: Bool) -> Void) {
            database.asyncAddObject(self, update: shouldUpdate) { (result) -> Void in
                if let error = result.error {
                    print(error)
                    completionHandler(success: false)
                }
                else {
                    completionHandler(success: true)
                }
            }
        }
    
    
    }
    

    can anybody tell me what i am doing wrong here

    opened by kamalupasena 3
  • BUG. [addObjects] add some different object

    BUG. [addObjects] add some different object

    public func addObjects <S: Storable> (objects: [S], update: Bool = true) -> Result<Bool> {
        guard objects.count > 0 else {
            return Result.Success(true)
        }
    
        do {
            if !(try tableExistsForType(S)) {
                //!!! BUG !!! , if objects is different model, they have different table, 
                createTableForTypeRepresentedByObject(objects.first!)
            }
    
            let insertStatement = StatementGenerator.insertStatementForType(S.self, update: update)
    
    
            try databaseQueue.transaction { (database) -> Void in
                let statement = try database.prepare(insertStatement)
    
                defer {
                    /* If an error occurs, try to finalize the statement */
                    let _ = try? statement.finalize()
                }
    
                for object in objects {
                    let data = self.dataFromObject(object)
                    try statement.executeUpdate(data)
                }
            }
        } catch let error {
            return Result.Error(error)
        }
    
        return Result.Success(true)
    }
    
    bug wontfix 
    opened by izouxv 2
  • Cannot invoke 'asyncDataForType' with an argument list of type '(SiteRecord.Type, (_) -> Void)'

    Cannot invoke 'asyncDataForType' with an argument list of type '(SiteRecord.Type, (_) -> Void)'

    What's wrong with my code, did I do something wrong?

    let database = SwiftyDB(databaseName: "gogogo") database.asyncDataForType(SiteRecord.self) { (result) -> Void in }

    /Users/zhihuitang/repo/ios/Letsgo/Letsgo/JSBridgeHandler.swift:32:18: Cannot invoke 'asyncDataForType' with an argument list of type '(SiteRecord.Type, (_) -> Void)'

    opened by zhihuitang 2
  • Missing Column

    Missing Column

    I am using SwiftyDB in conjunction with TinySQLite. On some cases, when I install a new version that adds new columns to my SQLite scheme, it isn't get updated for some reason.

    On a new install, we clean up the database. We completely delete all the records, but not the tables.

    The app crashes because a couple of columns are missing. I have no idea why.

    question 
    opened by toptierlabs 1
  • Ability to include a sqlite database in the target.

    Ability to include a sqlite database in the target.

    Added the ability to include a sqlite database in your project, instead of always creating a new database. It checks for in the bundle for the sqlite database, if not found then i proceeds as usual and creates a new sqlite database. This gives the user the ability to include pre-defined data in the sqlite database with his app

    opened by steelzeh 1
  • update not work

    update not work

    class func primaryKeys() -> Set<String> {
        return ["id"]
    }
    
    static func save(array: [DisModel]) {
        let database = SwiftyDB(databaseName: "dogtopia")
    //        database.deleteObjectsForType(DisModel.self)
        database.addObjects(array, update: true)
     }
    

    8ba1f7b9-2de9-4b1a-9192-4fc2e749f5ae

    As above, even if I put the update parameter is true, add object database is to be repeated.

    opened by huanghe810229530 1
  • chaining filters to find dates within a month..

    chaining filters to find dates within a month..

    so i've been trying to filter the query to get all dates within the month, but nothing comes up... if i drop one portion of the filter or the other, it gets me more than what i'm looking for:

    ` let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) let components = NSDateComponents() components.year = dayOfMonth.year components.month = dayOfMonth.month components.day = 1 let dateFrom = calendar?.dateFromComponents(components) print("From: (dateFrom)")

        components.month = dayOfMonth.month + 1
        let dateTo = calendar?.dateFromComponents(components)
        print("To: \(dateTo)")      
    
        let filter = Filter
        .greaterOrEqual("buttonPressedTimestamp", value: dateFrom)
        .lessOrEqual("buttonPressedTimestamp", value: dateTo)
        let results = database.objectsForType(Event.self, matchingFilter: filter)
    

    `

    any suggestions?

    bug 
    opened by galileomd 1
  • syntax issue

    syntax issue

    Hi, I am trying to execute SwiftyDB in 8.3.3 but it's getting a syntax error and throwing 93 errors in TinySqlite framework. Please tell me what should I do to implement? thank You

    opened by dhanarajkawde 0
  • pod SwiftyDB cause TinySQLite Swift Compile error

    pod SwiftyDB cause TinySQLite Swift Compile error

    Here is my pod file and got TinySQLite Swift Compile Error. I am now ising Xcode 8.3.3 , swift 3.0 . What should I do to fix?

    Uncomment the next line to define a global platform for your project

    platform :ios, '9.0'

    target 'PMTools' do

    project 'PMTools.xcodeproj' use_frameworks!

    pod ‘SwiftyDB’ pod 'SwiftyJSON' pod 'Timepiece' pod 'SwiftSpinner' pod 'SwiftyUserDefaults' pod 'PayPal-iOS-SDK' pod 'Charts' pod 'Eureka' pod 'SnapKit' end

    opened by burkaslarry 4
Owner
Øyvind Grimnes
Øyvind Grimnes
A Generic CoreData Manager to accept any type of objects. Fastest way for adding a Database to your project.

QuickDB FileManager + CoreData ❗️ Save and Retrieve any thing in JUST ONE line of code ❗️ Fast usage dataBase to avoid struggling with dataBase comple

Behrad Kazemi 17 Sep 24, 2022
AppCodableStorage - Extends `@AppStorage` in SwiftUI to support any Codable object

AppCodableStorage Extends @AppStorage in SwiftUI to support any Codable object.

Andrew Pouliot 19 Nov 25, 2022
Safe and easy wrappers for common Firebase Realtime Database functions.

FirebaseHelper FirebaseHelper is a small wrapper over Firebase's realtime database, providing streamlined methods for get, set, delete, and increment

Quan Vo 15 Apr 9, 2022
SQLite.swift - A type-safe, Swift-language layer over SQLite3.

SQLite.swift provides compile-time confidence in SQL statement syntax and intent.

Stephen Celis 8.7k Jan 3, 2023
Swift APIs for SQLite: Type-safe down to the schema. Very, very, fast. Dependency free.

Lighter Lighter is a set of technologies applying code generation to access SQLite3 databases from Swift, e.g. in iOS applications or on the server. L

Lighter.swift 330 Dec 26, 2022
Store and retrieve Codable objects to various persistence layers, in a couple lines of code!

tl;dr You love Swift's Codable protocol and use it everywhere, who doesn't! Here is an easy and very light way to store and retrieve Codable objects t

null 149 Dec 15, 2022
🛶Shallows is a generic abstraction layer over lightweight data storage and persistence.

Shallows Shallows is a generic abstraction layer over lightweight data storage and persistence. It provides a Storage<Key, Value> type, instances of w

Oleg Dreyman 620 Dec 3, 2022
Typed key-value storage solution to store Codable types in various persistence layers with few lines of code!

?? Stores A typed key-value storage solution to store Codable types in various persistence layers like User Defaults, File System, Core Data, Keychain

Omar Albeik 94 Dec 31, 2022
A fast, pure swift MongoDB driver based on Swift NIO built for Server Side Swift

A fast, pure swift MongoDB driver based on Swift NIO built for Server Side Swift. It features a great API and a battle-tested core. Supporting both MongoDB in server and embedded environments.

null 646 Dec 10, 2022
CRUD is an object-relational mapping (ORM) system for Swift 4+.

CRUD is an object-relational mapping (ORM) system for Swift 4+. CRUD takes Swift 4 Codable types and maps them to SQL database tables. CRUD can create tables based on Codable types and perform inserts and updates of objects in those tables. CRUD can also perform selects and joins of tables, all in a type-safe manner.

PerfectlySoft Inc. 61 Nov 18, 2022
A Swift library to fetch the schema from a SQLite3 database.

SQLite3Schema A small library to fetch the schema of a SQLite database. Contains a SQLite3 helper module for Linux. TBD. Uses just the raw SQLite API.

Helge Heß 4 Sep 17, 2022
This Project domonstrate the latest Swift on Server to create RESTFul API's connected via Database: MongoDB NoSql

Swift is a general-purpose programming language built using a modern approach to safety & performance that make it specifically suitable for Server applications. Vapor is a web framework for Swift, allowing you to write backends, web apps APIs and HTTP servers in Swift

Furqan 3 Aug 23, 2022
Listens to changes in a PostgreSQL Database and via websockets.

realtime-swift Listens to changes in a PostgreSQL Database and via websockets. A Swift client for Supabase Realtime server. Usage Creating a Socket co

Supabase 35 Dec 1, 2022
Realm is a mobile database: a replacement for Core Data & SQLite

Realm is a mobile database that runs directly inside phones, tablets or wearables. This repository holds the source code for the iOS, macOS, tvOS & wa

Realm 15.7k Jan 1, 2023
WCDB is a cross-platform database framework developed by WeChat.

WCDB 中文版本请参看这里 WCDB is an efficient, complete, easy-to-use mobile database framework used in the WeChat application. It's currently available on iOS,

Tencent 9.6k Jan 8, 2023
Sync Realm Database with CloudKit

IceCream helps you sync Realm Database with CloudKit. It works like magic! Features Realm Database Off-line First Thread Safety Reactive Programming O

Soledad 1.8k Jan 6, 2023
Movies Information DataBase (Add - Delete - Edit - Search)

MoviesInformation Movies Information DataBase (Add - Delete - Edit - Search) This Code Provide Simple Program About Movies Information This Program Ca

Mohammad Jaha 2 Sep 15, 2021
Easy direct access to your database 🎯

OHMySQL ★★ Every star is appreciated! ★★ The library supports Objective-C and Swift, iOS and macOS. You can connect to your remote MySQL database usin

Oleg 210 Dec 28, 2022
A simple order manager, created in order to try Realm database

Overview A simple order manager, created in order to get acquainted with the features and limitations of the local Realm database. The project is writ

Kirill Sidorov 0 Oct 14, 2021