TestsTested | ✗ |
LangLanguage | SwiftSwift |
License | MIT |
ReleasedLast Release | Nov 2017 |
SwiftSwift Version | 3.0 |
SPMSupports SPM | ✗ |
Maintained by Zonily Jame Pesquera.
Depends on: | |
Alamofire | = 4.4.0 |
EVReflection | = 4.2.0 |
SwiftyJSON | = 3.1.4 |
PromiseKit | = 4.4.0 |
PromiseKit/Alamofire | = 4.4.0 |
The Warp iOS SDK is available through the dependency manager CocoaPods.
===================
The Warp iOS SDK is a library built in top of Alamofire, EVReflection, SwiftyJSON, and PromiseKit for implementing the Warp Framework using Swift. It is designed to work with projects built on-top of the Warp Server.
To install the Warp iOS SDK via cocoapods, simply use the add this in your podfile and then run pod install
pod 'WarpSDK'
For projects using Swift 2.3 use the Swift 2.3 branch.
To initialize the SDK for client-side development, simply add the following configruation to the main file of your project:
// Import Warp
import WarpSDK
// Initialize Warp Inside AppDelegate
func applicationDidFinishLaunching(application: UIApplication) {
Warp.Initialize("http://my-warp-server.com/api/1/", apiKey: "12345678abcdefg")
}
Objects represent individual instances of models. In terms of the database, an Object can be thought of as being a row
in a table. Throughout the Warp Framework, Objects are the basic vehicles for data to be transmitted to and fro the server.
Each Object contains different keys which can be set or retrieved as needed. Among these keys are three special ones:
These keys are specifically set by the server and cannot be modified by the user.
To save an Object for a specific model, use the Warp.Object
class:
let alien = Warp.Object(className: "alien")
You can set the values of the Object's keys using the .set(object: value: AnyObject, forKey: String)
method:
alien.set(object: "TheDoctor", forKey: "name")
alien.set(object: "150000", forKey: "age")
alien.set(object: 4, forKey: "type")
Then, save the Object using the .save()
method:
_ = alien.save()
// or
_ = alien.save { (isSucess, error) in
if error != nil {
print(error)
} else {
print("The alien has been created with the following ID:", alien.id)
print("The alien has been named:", alien.get(object: "name"))
}
}
// or
_ = alien.save().then { _ in
print("The alien has been created with the following ID:", alien.id)
print("The alien has been named:", alien.get(object: "name"))
}.catch(execute: { (error) in
print(error)
})
To retrieve an Object for a specific model, you can use Warp Queries
. For more info, see the section on Queries:
let alienQuery = Warp.Query(className: "alien")
// or
let alienQuery = Warp.ObjectQuery(className: "alien")
alienQuery.equalTo(16, forKey: "id")
_ = alienQuery.first { (warpObject, error) in
// You now have a copy of alien (id: 16) from the database
}
// or
_ = alienQuery.first().then { warpObject in
// You now have a copy of alien (id: 16) from the database
}
Now that you have fetched the object, you can also get its keys using the .get(object: key: String)
method:
let name = alien.get(object: "name")
let age = alien.get(object: "age")
let type = alien.get(object: "type")
For special keys as mentioned in the section on Objects, you can retrieve their values via the following properties:
var id = alien.id
var createdAt = alien.createdAt
var updatedAt = alien.updatedAt
Note that these fields cannot be retrieved via the .get(object: key: String)
method.
Whenever you use .save()
or Warp Queries
to save/retrieve objects, you can modify the keys of these objects directly using the same .set(object: value: AnyObject, forKey: String)
method. Warp automatically knows that you've updated these fields and prepares the object for updating.
For example, after the .save()
method:
let alien = Warp.Object(className: "alien")
alien.set(object: "Madam Vestra", forKey: "name")
alien.set(object: 4, forKey: "type")
_ = alien.save { (isSucess, error) in
// If this is the 200th alien, change its type, for example
if alien.id > 200 {
alien.set(object: 5, forKey: "type")
}
// Update the alien
alien.save { (isSucess, error) in
// The alien has been successfully updated
}
}
// or
_ = alien.save().then { _ in
// If this is the 200th alien, change its type, for example
if alien.id > 200 {
alien.set(object: 5, forKey: "type")
}
// Update the alien
return alien.save().promise()
}.then { _ in
// The alien has been successfully updated
}
For example, after retrieving from Warp Queries
:
let alienQuery = Warp.Query(className: "alien")
// or
let alienQuery = Warp.ObjectQuery(className: "alien")
alienQuery.equalTo(5, forKey: "id")
_ = alienQuery.first { (alien, error) in
alien?.set(object: 5, forKey: "age")
alien?.save { (isSucess, error) in
// The alien has been successfully updated
}
}
// or
_ = alienQuery.first().then { alien in
alien?.set(object: 30, forKey: "age")
return alien?.save()
}.then { _ in
// The alien has been successfully updated
}
Additionally, if the key you are trying to update is an integer
and you want to atomically increase or decrease its value, you can opt to use the .increment()
method instead.
COMING SOON
If you want to delete a saved or retrieved object, all you need to do is call the .destroy()
method of the object:
_ = alien.destroy()
Additionally, like .save()
, the .destroy()
method also returns a promise, which you can chain other processes to:
_ = alien.destroy { (isSucess, error) in
print("The alien has been destroyed")
}
// or
_ = alien.destroy().promise().then { _ in
print("The alien has been destroyed")
}
If your objects use pointers for some of its keys, you can directly set them via the .set()
method.
For example, if you are creating a planet
for an alien
object, you can use the following approach:
let planet = Warp.Object(className: "planet")
planet.set(object: "Raxocoricofallipatorius", forKey: "name")
_ = planet.save { (isSucess, error) in
let alien = Warp.Object(className: "alien")
alien.set(object: "Slitheen", forKey: "name")
alien.set(object: planet, forKey: "planet")
alien.save { (isSucess, error) in
// The alien has been successfully saved
}
}
// or
_ = planet.save().then { _ in
let alien = Warp.Object(className: "alien")
alien.set(object: "Slitheen", forKey: "name")
alien.set(object: planet, forKey: "planet")
return alien.save().promise()
}.then { _ in {
// The alien has been successfully saved
}
If, for example, you have an existing planet
and you want to use it for an alien
object, you can use the following approach:
// For Objects, Warp.Object.createWithoutData(id: Int, className: String)
// For users, Warp.User.createWithoutData(id: Int)
let planet = Warp.Object.createWithoutData(id: 2, className: "planet")
let alien = Warp.Object(className: "alien")
alien.set(object: "Captain Jack Harkness", forKey: "name")
alien.set(object: planet, forKey: "planet")
_ = alien.save { (isSucess, error) in
// The alien has been successfully saved
}
// or
_ = alien.save().then { _ in
// The alien has been successfully saved
}
There are certain scenarios when you may need to find Objects from a model. In these instances, it would be convenient to use Queries. Queries allow you to find specific Objects based on a set of criteria.
For example, if you want to query objects from the alien
model, you would use the following code:
// Prepare query
let alienQuery = Warp.Query(className: "alien")
// or
let alienQuery = Warp.ObjectQuery(className: "alien")
// Use `.find()` to get all the objects in the `alien` table
_ = alienQuery.find { (aliens, error) in
// You now have a collection of all the aliens
}
// or
_ = alienQuery.find().then { aliens in
// You now have a collection of all the aliens
}
// Use `.first()` to get the first object in the `alien` table
_ = alienQuery.first { (alien, error) in
// You now have the first alien object
}
// or
_ = alienQuery.first().then { alien in
// You now have the first alien object
}
// Use `.get(_ objectId: Int)` to get a specific object in the `alien` table
let alienQuery = Warp.Query(className: "alien")
_ = alienQuery.get(3) { (object, error) in
// You now have the object with the id 3
}
// or
_ = alienQuery.get(3).then { (object) in
// You now have the object with the id 3
}
Constraints help filter the results of a specific query. In order to pass constraints for a Query, use any of the following constraints you wish to apply:
// Prepare query
let alienQuery = Warp.Query(className: "alien")
// or
let alienQuery = Warp.ObjectQuery(className: "alien")
// Find an exact match for the specified key
alienQuery.equalTo("The Doctor", forKey: "name")
alienQuery.notEqualTo("The Master", forKey: "name")
// If the key is ordinal (i.e. a string, a number or a date), you can use the following constraints
alienQuery.lessThan(21, forKey: "age")
alienQuery.lessThanOrEqualTo("Weeping Angels", forKey: "name")
alienQuery.greaterThanOrEqualTo(500, forKey: "life_points")
alienQuery.greaterThan("2016-08-15 17:30:00+00:00", forKey: "created_at")
// If you need to check if a field is null or not null
alienQuery.existsKey("type")
alienQuery.notExistsKey("type")
// If you need to find if a given key belongs in a list, you can use the following constraints
alienQuery.containedIn("Doctor", "Warrior", forKey: "role")
alienQuery.notContainedIn([18, 20], forKey: "age")
// If you need to search a string for a substring
alienQuery.startsWith("The", forKey: "name")
alienQuery.endsWith("Master", forKey: "name")
alienQuery.contains("M", forKey: "name")
// If you need to search multiple keys for a substring
alienQuery.contains("M", keys: "name", "username", "email")
By default, Warp limits results to the top 100 objects that satisfy the query criteria. In order to increase the limit, you can specify the desired value via the .limit()
method. Also, in order to implement pagination for the results, you can combine the .limit()
with the .skip()
methods. The .skip()
method indicates how many items are to be skipped when executing the query. In terms of scalability, it is advisable to limit results to 1000 and use skip to determine pagination.
For example:
alienQuery.limit(1000) // Top 1000 results
alienQuery.skip(1000) // Skip the first 1000 results
NOTE: It is recommended that you use the sorting methods in order to retrieve more predictable results. For more info, see the section below.
Sorting determines the order by which the results are returned. They are also crucial when using the limit and skip parameters. To sort the query, use the following methods:
alienQuery.sortBy('age'); // Sorts the query by age, in ascending order
alienQuery.sortByDescending(['created_at', 'life_points']); // You can also use an array to sort by multiple keys
In order to include keys that belong to a pointer, we can use the .include(values: [String])
method.
alienQuery.include("planet.name", "planet.color")
The above query will return aliens with their respective planets as pointers:
alienQuery.find { (aliens, error) in
if error == nil {
for alien in aliens! {
let greeting = "I am " + (alien.get(object: "name") as! String) + " and I come from the Planet " + (alien.get(object: "planet")?.get(object: "name") as! String)
print(greeting)
}
}
}
User accounts are often an essential part of an application. In Warp, these are represented by Warp Users. Warp Users are extended from the Warp Object, which means you can use the same methods found in Warp Objects; however, Warp Users have additional methods specifically tailored for user account management.
Aside from id, createdAt and updatedAt, Warp User also has the following get methods:
let userQuery = Warp.UserQuery()
// or
let userQuery = Warp.User.Query()
userQuery.equalTo(5, forKey: "id").first { (user, error) in
if let unwrappedError = error {
print(unwrappedError)
} else {
var id = user?.id
var createdAt = user?.createdAt
var updatedAt = user?.updatedAt
var username = user?.username
var email = user?.email
}
}
Note that for User Queries, instead of using WarpQuery(className: "user")
we should use WarpUser.query()
instead.
In order to log in to a user account, you would use the .login(username: String, password: String, completion: { (isSucess, error) in })
method:
Warp.User().login("username", password: "password") { (isSucess, error) in
if error != nil {
// Successfully logged in
} else {
// There was an error
}
}
To get the currently logged in user, you would use the .current()
method:
var current = WarpUser.current()
To register a new user account, you would use the .signUp({ (isSucess, error) in })
method:
let user = Warp.User()
user.setUsername("Luke Smith")
user.setPassword("k9_and_sara")
user.signUp { (isSucess, error) in
if error != nil {
// Signed up; `.current()` returns the registered user
let current = WarpUser.current()
} else {
// There was an error
}
}
Note that you cannot use .save()
to create a user. You can only use .save()
to update a user which has been registered or logged in.
To log out of a user account, you would use the .logOut()
method:
user.logout { (isSucess, error) in
if error != nil {
// Logged out; `.current()` now returns nil
var current = WarpUser.current()
} else {
// There was an error
}
}
To run Warp Functions from the API, you may use Warp Functions:
// WarpFunction.run(functionName: String, parameters: [String: Any]?, completion: { (result, error) in })
WarpFunction.run("get-votes", parameters: ["from":"2016-08-14", "to":"2016-08-15"]) { (result, error) in
if error == nil {
// `result` contains a JSON Object of the results from the API
} else {
// There was an error
}
}