<img src="https://github.com/1amageek/Salada/blob/master/Salada.png", width="480">
Logo was designed by Take.
Salad is a Model for Firebase database. It can handle Snapshot of Firebase easily.
- iOS 8 or later
- Swift 2.3
- Firebase database
- Firebase storage
Add the following to the pod file, Pods install
pod 'Firebase'
pod 'Firebase/Database'
pod 'Firebase/Storage'
- Download this project
- Put
Salada.Swift
in your project.
Model of the definition is very simple.
To inherit the Ingredient
.
class User: Ingredient {
typealias Tsp = User
dynamic var name: String?
dynamic var age: Int = 0
dynamic var gender: String?
dynamic var groups: Set<String> = []
dynamic var items: [String] = []
}
When you want to create a property that you want to ignore.
// Group
class Group: Ingredient {
typealias Tsp = Group
dynamic var name: String?
dynamic var users: Set<String> = []
}
Property are four that can be specified in Salada.
Propery | Description |
---|---|
String | Simple string. |
Number(Int, UInt, Double ...) | Simple number. |
NSURL | URL |
Array<String> | Array of strings. |
Set <String> | Array of strings. Set is used in relationships. |
AnyObject | Use encode, decode function. |
Do not forget to change the database rule
{
"rules": {
".read": true,
".write": true
}
}
The new model is stored in the save()
or save(completion: ((NSError?, FIRDatabaseReference) -> Void)?)
.
It is updated automatically when you change the property Model that have already been saved.
let group: Group = Group()
group.name = "iOS Development Team"
group.save { (error, ref) in
do {
let user: User = User()
user.name = "john appleseed"
user.gender = "man"
user.age = 22
user.items = ["Book", "Pen"]
user.groups.insert(ref.key)
user.save({ (error, ref) in
group.users.insert(ref.key) // It is updated automatically
})
}
do {
let user: User = User()
user.name = "Marilyn Monroe"
user.gender = "woman"
user.age = 34
user.items = ["Rip"]
user.groups.insert(ref.key)
user.save({ (error, ref) in
group.users.insert(ref.key) // It is updated automatically
})
}
}
observeSingle(eventType: FIRDataEventType, block: ([Tsp]) -> Void)
observeSingle(id: String, eventType: FIRDataEventType, block: (Tsp) -> Void)
User.observeSingle(FIRDataEventType.Value) { (users) in
users.forEach({ (user) in
// do samething
if let groupId: String = user.groups.first {
Group.observeSingle(groupId, eventType: .Value, block: { (group) in
// do samething
})
}
})
}
if let groupId: String = user.groups.first {
Group.observeSingle(groupId, eventType: .Value, block: { (group) in
group.remove()
})
}
class User: Ingredient {
typealias Tsp = User
dynamic var name: String?
dynamic var age: Int = 0
dynamic var gender: String?
dynamic var groups: Set<String> = []
dynamic var items: [String] = []
dynamic var location: CLLocation?
var tempName: String?
override var ignore: [String] {
return ["tempName"]
}
override func encode(key: String, value: Any) -> AnyObject? {
if "location" == key {
if let location = self.location {
return ["latitude": location.coordinate.latitude, "longitude": location.coordinate.longitude]
}
}
return nil
}
override func decode(key: String, value: Any) -> AnyObject? {
if "location" == key {
if let location: [String: Double] = value as? [String: Double] {
return CLLocation(latitude: location["latitude"]!, longitude: location["longitude"]!)
}
}
return nil
}
}
You can easily save the file if you use the SaladaFile. SaladaFile saves the File in FirebaseStorage.
let user: User = User()
let image: UIImage = UIImage(named: "Salada")!
let data: NSData = UIImagePNGRepresentation(image)!
let thumbnail: SaladaFile = SaladaFile(name: "salada_test.png", data: data)
thumbnail.data = data
user.thumbnail = thumbnail
user.save({ (error, ref) in
// do something
})
Download of File is also available through the SaladaFile.
guard let user: User = self.datasource?.objectAtIndex(indexPath.item) else { return }
user.thumbnail?.dataWithMaxSize(1 * 200 * 200, completion: { (data, error) in
if let error: NSError = error {
print(error)
return
}
cell.imageView?.image = UIImage(data: data!)
cell.setNeedsLayout()
})
For example
// in ViewController property
var salada: Salada<User>?
// in viewDidLoad
self.salada = Salada.observe({ [weak self](change) in
guard let tableView: UITableView = self?.tableView else { return }
let deletions: [Int] = change.deletions
let insertions: [Int] = change.insertions
let modifications: [Int] = change.modifications
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths(insertions.map { NSIndexPath(forRow: $0, inSection: 0) }, withRowAnimation: .Automatic)
tableView.deleteRowsAtIndexPaths(deletions.map { NSIndexPath(forRow: $0, inSection: 0) }, withRowAnimation: .Automatic)
tableView.reloadRowsAtIndexPaths(modifications.map { NSIndexPath(forRow: $0, inSection: 0) }, withRowAnimation: .Automatic)
tableView.endUpdates()
})
// TableViewDatasource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.salada?.count ?? 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath)
configure(cell, atIndexPath: indexPath)
return cell
}
func configure(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
guard let user: User = self.salada?.objectAtIndex(indexPath.item) else { return }
cell.textLabel?.text = user.name
}