我正在寻找一种干净的方法来从Swift中的Firebase检索(有时保存)数据。令我讨厌的是我的所有数据库调用都是在视图控制器代码的中间编写的。所以我正在寻找某种自定义数据服务类。我发现本教程与我想要的很接近:http://www.mobilecyberpunks.com/?p=82。
他们答应了第二部分,但我找不到第二部分,所以我想这从未做过。在第二部分中,他们承诺将使用此自定义数据服务(这对我来说是整个事情中最重要的部分)来检索和保存数据。
我正在考虑一个API类(就像在教程中一样),当我检索数据时,它完成从firebase中检索,我将它保存在这个api类的数据集中。然后我将在通知中心发布通知。但我不确定这是最佳做法还是做这件事的好方法。
有谁知道如何做到这一点(我完成本教程或以其他方式)?
提前致谢!
答案 0 :(得分:4)
如果您需要广泛的功能并对服务器进行大量调用,那么为通信创建自定义类通常是一个好主意。
两种首选方法是: -
Protocol-Delegate
方法
<强> _completionBlocks:
强>
以下答案包含两者。
import Foundation
import Firebase
@objc protocol FIRShowAlertDelegate {
func showFIRAlert(_ message : String)
@objc optional func activityIndic()
}
class FIRController :{
var delegate : FIRShowAlertDelegate!
func loginUser(_ emailAddress : String!, password : String , completionBlock : @escaping ((currentUserID : String!) -> Void)){
FIRAuth.auth()?.signIn(withEmail: emailAddress, password: password,
completion: {(user,err) in
if err != nil{
self.delegate.showFIRAlert("Error logging you in,\(err?.localizedDescription)")
}else{
completionBlock(user!.uid)
}
})
}
func retrieveUserData(_ currentId : String!, completionBlock : @escaping ((_ userName : String?) -> Void)){
FIRDatabase.database().reference().child("Users").child(currentId).observeSingleEvent(of: .value, with: {(userSnap) in
if userSnap.exists(){
if let userDict = userSnap.value! as? [String:AnyObject]{
completionBlock(userDict["username"] as! String
}
}else{
completionBlock(nil, nil)
print("No such user exists: \(currentId)")
}
})
}
}
class AnyViewController : UIViewController, FIRShowAlertDelegate{
let firebaseControllerHandle : FIRController = FIRController()
override func viewDidLoad() {
super.viewDidLoad()
firebaseControllerHandle.delegate = self
firebaseControllerHandle.loginUser("abc@xyz.com", password: "123454321", completionBlock: { (userID) in
print("user : \(userID), logged in")
})
}
func showFIRAlert(_ message : String){
let alertController : UIAlertController = UIAlertController(title: "MyApp", message: message, preferredStyle: .alert)
let okAction : UIAlertAction = UIAlertAction(title: "Ok", style: .default) { (alert) in
print("User pressed ok function")
}
alertController.addAction(okAction)
alertController.popoverPresentationController?.sourceView = view
alertController.popoverPresentationController?.sourceRect = view.frame
self.present(alertController, animated: true, completion: nil)
}
func activityIndic() {
// Use for showing the activity indicator while the data is being retrieved
}
}
答案 1 :(得分:4)
我开始使用这个解决方案并稍微打磨一下,我找到了一个非常方便的解决方案。
我创建了一个名为FirebaseAPI的自定义类。这是一个单身人士班。此类包含Firebase的所有方法(身份验证,数据库,存储,...)。
示例:
<强> FirebaseAPI.swift 强>
import FirebaseAuth
import FirebaseDatabase
class FirebaseAPI {
static let shared = FirebaseAPI()
private init() {}
//Authentication
func logInUser(onCompletion: @escaping (String?) -> Void {
FIRAuth.auth().signInAnonymously(completion: {(user, error) in
if error == nil {
onCompletion(user!.uid)
} else {
onCompletion(nil)
}
})
}
//Database
func getObjects(parameter: ParamaterClass, onCompletion: @escaping ([ObjectClass]) -> Void) {
Constants.Firebase.References.Object?.observe(.value, with: { snapshot in
var objects = [ObjectClass]()
if snapshot.exists() {
for child in snapshot.children.allObjects {
let object = Object(snapshot: child as! FIRDataSnapshot)
objects.append(object)
}
}
onCompletion(objects)
})
}
}
<强> Constants.swift 强>
import FirebaseDatabase
struct Constants {
struct Firebase {
static var CurrentUser: FIRDatabaseReference?
static var Objects: FIRDatabaseReference?
}
}
<强> AppDelegate.swift 强>
import UIKit
import Firebase
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FIRApp.configure()
FirebaseAPI.shared.logInUser(onCompletion { uid in
if uid != nil {
Constants.Firebase.References.CurrentUser = FIRDatabase.database().reference().child("users").child(uid!)
Constants.Firebase.References.CurrentUser.keepSynced(true)
Constants.Firebase.References.Objects = FIRDatabase.database().reference().child("objects")
Constants.Firebase.Reference.Objects?.keepSynced(true)
}
})
}
return true
}
我可以举一个在ViewController中调用FirebaseAPI中方法的示例,但是这里的AppDelegate.swift代码中提供了这种方法的示例(FirebaseAPI.shared.logInUser方法)。
到目前为止,在3个不同的项目中使用了这个结构,它的工作流畅!