SwiftUI 与 Firebase 使用 Xcode 11 GM 种子 2 - Swift UI Firestore

Posted

技术标签:

【中文标题】SwiftUI 与 Firebase 使用 Xcode 11 GM 种子 2 - Swift UI Firestore【英文标题】:SwiftUI With Firebase Using Xcode 11 GM seed 2 - Swift UI Firestore 【发布时间】:2019-09-21 08:39:16 【问题描述】:

我遵循了这个https://www.youtube.com/watch?v=_N10q1iR2HQ&t=328s 教程;但是,针对 Xcode 11 GM 种子 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 Venue[16661:712648] 5.12.0 - [Firebase/Analytics][I-ACS023008] 要启用调试日志记录,请设置以下应用程序参数:-FIRAnalyticsDebugEnabled 无法将“__NSCFNumber”(0x10b8a8610)类型的值转换为“NSString”(0x10954f978)。

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

【问题讨论】:

鉴于错误消息“无法将 '__NSCFNumber' (0x10b8a8610) 类型的值转换为 'NSString'”,您似乎正在尝试将数字强制转换为字符串,这不是不可能。您的字段namephoneservices 很可能包含一个数值。如果您右键单击红色错误指示器,您应该能够找到准确的线。 【参考方案1】:

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

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

我使用了以下结构,而不是视频的数据集:

  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 中的记录,我也总是在模拟器屏幕上看到相同的原始值。

【讨论】:

【参考方案2】:

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

let id = doc.document.documentID

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

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

【讨论】:

【参考方案3】:

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

然后你可以在你的项目中为 Firestore 使用纯组合模式

【讨论】:

以上是关于SwiftUI 与 Firebase 使用 Xcode 11 GM 种子 2 - Swift UI Firestore的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 与 Firebase 使用 Xcode 11 GM 种子 2 - Swift UI Firestore

在 SwiftUI 应用程序上使用 firebase 数据初始化变量

AdMob/Firebase 使用 cocoapods 与 SwiftUI 集成:发现意外的 Mach-O 标头代码:0x72613c21

数据在 Firebase 中的保存顺序与 SwiftUI 的传输顺序不同

将 Firebase 身份验证与新的 @App 协议一起使用

swiftui 请求 渲染数据