使用Xcode 11 GM种子2的带有Firebase的SwiftUI-Swift UI Firestore

时间:2019-09-21 08:39:16

标签: ios firebase google-cloud-firestore swiftui

我遵循了此https://www.youtube.com/watch?v=_N10q1iR2HQ&t=328s教程;但是,由于对Xcode 11 GM seed 2的语法和术语进行了一些更改,因此已经进行了调整,因为某些内容现在已过时。构建成功,但由于某些原因而崩溃。

我将很感谢您的帮助和建议,并尝试了我能想到的所有尝试和错误。

这是下面的代码(由于GM种子2具有许多命令更改,因此将其全部粘贴):

import SwiftUI
import Combine
import FirebaseFirestore
struct dataset : Identifiable {
var id = ""
var name = ""
var phone = ""
var services = ""
}
class getData : ObservableObject {

var didChange = PassthroughSubject<getData, Never>()

var data = [dataset](){

    didSet{
        didChange.send(self)
    }
}

init(){
    let db = Firestore.firestore()
    let settings = db.settings
    settings.areTimestampsInSnapshotsEnabled = true
    db.settings = settings
    db.collection("venues").addSnapshotListener {(snap,err) in
        if err != nil{
            print((err?.localizedDescription)!)
            return
        }
        for i in (snap?.documentChanges)!{

            let name = i.document.data()["name"] as! String
            let phone = i.document.data()["phone"] as! String
            let services = i.document.data()["services"] as! String
            let id = i.document.documentID

            DispatchQueue.main.async {
                self.data.append(dataset(id: id, name: name, phone: phone, services:services))
            }
        }
    }
}
}
struct ContentView: View {

@ObservedObject var data1 = getData()

var body: some View {
    VStack {
        Text("Hello World")
        List(data1.data){ i in
            cellView(name: i.name, phone: i.phone, services: i.services)
        }
    }
}
}
struct cellView : View {
@State var name = ""
@State var phone = ""
@State var services = ""

var body : some View{
    VStack{
        Text(name)
        Text(phone)
        Text(services)
    }
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
    ContentView()
}
}

这些是结果

  

2019-09-19 20:30:34.724594 + 0600地点[16661:712640]-[I-ACS036002]启用了分析屏幕报告。调用+ [FIRAnalytics setScreenName:setScreenClass:]设置屏幕名称或覆盖默认屏幕类名称。要禁用屏幕报告,请将Info.plist中的标志FirebaseScreenReportingEnabled设置为NO(布尔值)

     

2019-09-19 20:30:34.975422 + 0600地点[16661:712648] 5.12.0-[Firebase / Analytics] [I-ACS023007] Analytics(分析)v.50300000已启动

     

2019-09-19 20:30:34.975634 + 0600地点[16661:712648] 5.12.0-[Firebase / Analytics] [I-ACS023008]要启用调试日志记录,请设置以下应用程序参数:-FIRAnalyticsDebugEnabled   无法将类型'__NSCFNumber'(0x10b8a8610)的值强制转换为'NSString'(0x10954f978)。

     

2019-09-19 20:30:35.073897 + 0600地点[16661:711704]无法将类型'__NSCFNumber'(0x10b8a8610)的值转换为'NSString'(0x10954f978)。   (lldb)

3 个答案:

答案 0 :(得分:0)

如第一条评论所述,您似乎在类型之间存在强制转换问题。

我尝试了相同的示例,并且能够成功构建和运行,但是屏幕上未显示任何数据。经过一番调查,我重新编写了部分代码,终于能够得到结果。

我使用以下结构代替视频的数据集:

  struct Profile : Identifiable {

  var id: Int
  var name: String
  var phoneNumber: String

  init(id: Int, name: String, phoneNumber: String) {
    self.id = id
    self.name = name
    self.phoneNumber = phoneNumber
  }
}

这些是SwiftUI视图:

import SwiftUI
import FirebaseFirestore

struct ContentView: View {

    @State var data1 = [Profile]()

    var body: some View {

        return VStack {
            HStack {
                Text("Penya").font(.largeTitle)
            }
            Divider()
            List(data1) { i in
                cellView(name: i.name, phoneNumber: i.phoneNumber)
            }
        }.onAppear {
            self.getData()
        }
    }


    func getData() {

        var data = [Profile]()

        let db = Firestore.firestore()
        db.collection("patients").addSnapshotListener { (snap, err) in

            if err != nil {
                print((err?.localizedDescription)!)
                return
            }

            for doc in (snap?.documentChanges)! {
                let name = doc.document.data()["name"] as! String
                let phoneNumber = doc.document.data()["phoneNumber"] as! String

                print (name)
                print (phoneNumber)

                DispatchQueue.main.async {
                    data.append(Profile(id: 0,
                                        name: name,
                                        phoneNumber: phoneNumber))
                    self.data1 = data
                }
            }
        }
    }

}

struct cellView : View {

    @State var name = ""
    @State var phoneNumber = ""

    var body: some View {
        VStack {
            Text("Valors:")
            Text(name)
            Text(phoneNumber)
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

只要在Firestore中更改记录,就会在模拟器屏幕上自动执行更新。我仍然只在做一件事:控制台中正确显示了更新的值(我包括两个print()),但是即使在Firestore中更改记录,我也始终在模拟器屏幕上看到相同的原始值。 / p>

答案 1 :(得分:0)

使用Sergi的代码,但他缺少以下内容:

let id = doc.document.documentID

DispatchQueue.main.async {
                    data.append(Profile(id: id,
                                        name: name,
                                        phoneNumber: phoneNumber))
                    self.data1 = data

并将id的所有值更改为String而不是Int。

答案 2 :(得分:0)

我建议使用CombineFirebase 带有pod'FirebaseFirestoreSwift'

然后您可以在项目中为Firestore使用纯合并模式