iOS swift Firestore failed on loading gRPC-C++ Framework - ios

When I run my firestore code , beginning it is ok. When it comes to running with simulators or my new phone, it goes to this exception regardless of my firestore version :
Some said that it is related to the pen issues but this is not gonna work.Am I not encouraged to use anonymous login ?
Here is my code :
Auth.auth().signInAnonymously() { (result , error) in
guard let authResult = result else {
return
}
let user = authResult.user
let isAnonymous = user.isAnonymous // true
if(isAnonymous){
let uid = user.uid
User.shared.userId = uid
print("user id : \(User.shared.userId)")
let userRef = db.collection("user").document(User.shared.userId)
userRef.getDocument { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
if (querySnapshot?.get("progress") == nil) {
var dataDict : Dictionary<String , Any> = [:]
dataDict["progress"] = 0
userRef.setData(dataDict)
}else{
let dict = querySnapshot?.data()
let sssresult = dict!.filter{ $0.key == "progress" }.first?.value as? Int ?? 0
User.shared.progress = sssresult
}
}
}
}
// Do any additional setup after loading the view.
}
// CocoaPods: try to load from the gRPC-C++ Framework.
NSBundle* _Nullable FindGrpcCppFrameworkBundle() {
return [NSBundle bundleWithIdentifier:#"org.cocoapods.grpcpp"];
}

Related

Firebase / Firestore not getting document and running code

I am getting a document from firebase in swift. However the line isn't being run and is not getting the data.
This is my code:
let db = Firestore.firestore()
db.collection("chats").document(userDefaults.string(forKey: "currentGroup")!).collection("messages").document("variable").getDocument { (document, error) in
if error != nil{
print("error getting document")
}
else{
let documentData = document!.data()
let startNumOfMessages = documentData!["numOfMessages"] as! Int
var messageArray: Array<String> = []
if startNumOfMessages > 0 {
for message in 1...startNumOfMessages{
print(message)
//THIS LINE ISNT RUNNING
db.collection("chats").document(self.userDefaults.string(forKey: "currentGroup")!).collection("messages").document("\(message)").getDocument { (messageDoc, err) in
if err != nil{
print("Error getting message \(message)")
}
else{
if messageDoc!.exists && messageDoc != nil{
let messData = messageDoc!.data()
print(messData!["message"]!)
messageArray.append(messData!["message"] as! String)
}
else{
print("error in document")
}
}
}
}
//Display them
for num in 0...messageArray.count{
let label = UILabel()
label.text = messageArray[num]
self.stackView.addArrangedSubview(label)
}
}
}
}
The line below the comment is the line that isn't running. And the line that says label.text = messageArray[num] displays an error
Fatal error: Index out of range
Showing it doesn't get the data.
You miss the asynchronous way use DispatchGroup ( numbered from 1 to 4 )
let db = Firestore.firestore()
db.collection("chats").document(userDefaults.string(forKey: "currentGroup")!).collection("messages").document("variable").getDocument { (document, error) in
if error != nil{
print("error getting document")
}
else{
let documentData = document!.data()
let startNumOfMessages = documentData!["numOfMessages"] as! Int
var messageArray: Array<String> = []
if startNumOfMessages > 0 {
let g = DispatchGroup() /// 1
for message in 1...startNumOfMessages{
print(message)
//THIS LINE ISNT RUNNING
g.enter() /// 2
db.collection("chats").document(self.userDefaults.string(forKey: "currentGroup")!).collection("messages").document("\(message)").getDocument { (messageDoc, err) in
if err != nil{
print("Error getting message \(message)")
}
else{
if messageDoc!.exists && messageDoc != nil{
let messData = messageDoc!.data()
print(messData!["message"]!)
messageArray.append(messData!["message"] as! String)
}
else{
print("error in document")
}
}
g.leave() /// 3
}
}
g.notify(queue: .main) { /// 4
//Display them
for num in 0...messageArray.count{
let label = UILabel()
label.text = messageArray[num]
self.stackView.addArrangedSubview(label)
}
}
}
}
}

Getting incorrect value form firebase in swift

This is my code
let db = Firestore.firestore()
db.collection("chats").document(userDefaults.string(forKey: "currentGroup")!).collection("messages").document("variable").addSnapshotListener { (snapshot, error) in
if error != nil{
print("Error fetching document")
}
else{
let documentData = snapshot!.data()
print(documentData!["numOfMessages"])
self.numOfMessages = documentData!["numOfMessages"] as! Int
print(self.numOfMessages)
//Get texts and display them
db.collection("chats").document(self.userDefaults.string(forKey: "currentGroup")!).collection("messages").document("\(self.numOfMessages)").getDocument { (document, err) in
let newMessageData = document!.data()
let newMessage = newMessageData!["message"] as! String
let newAuthor = newMessageData!["author"] as! String
let authorLabel = UILabel()
authorLabel.text = newAuthor
self.stackView.addArrangedSubview(authorLabel)
let label = UILabel()
label.text = newMessage
self.stackView.addArrangedSubview(label)
}
}
}
This line self.numOfMessages = documentData!["numOfMessages"] as! Int has an error of
Could not cast value of type 'NSTaggedPointerString' (0x1ed6ed450) to 'NSNumber' (0x1ed6f98c8).
This is every since I deleted the collection messages and replaced it with one of the exact same name
The value that documentData!["numOfMessages"] returns is Optional(1) even though in firebase the value is 2.
This is how the Firestore looks:
Either you are listening to the wrong document (perhaps because of an incorrect user default) or you are unwrapping the value incorrectly. To debug this, try the following and see what the problem actually is. The following is a more idiomatic way of handling documents.
if let currentGroup = userDefaults.string(forKey: "currentGroup") {
print(currentGroup) // this could be your problem
Firestore.firestore().collection("chats").document(currentGroup).collection("messages").document("variable").addSnapshotListener { (snapshot, error) in
if let snapshot = snapshot {
if let numOfMessages = snapshot.get("numOfMessages") as? Int {
print(numOfMessages)
} else {
print("field error")
}
} else if let error = error {
print(error)
}
}
} else {
print("no current group")
}

Access Other Projects Firestore Data in iOS

I am using Firestore to build chat between multiple projects using this Doc
i.e. I have 2 applications / Firebase Projects.
App A and App B
Now I have implemented simple collection in Firestore of App A, it works fine without any issues.
My problem is when I want to access Firestore of App A from App B using the above documentation
I am getting error Error Domain=FIRFirestoreErrorDomain Code=7 "Missing or insufficient permissions
I have attached image of collection
Rules are
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
The Code I am using to configure on ChatViewController of App B is as follows
let secondaryOptions = FirebaseOptions(googleAppID: "1:27992087142:ios:2a4732a34787067a",
gcmSenderID: "27992087142")
secondaryOptions.apiKey = "AIzaSyBicqfAZPvMgC7NZkjayUEsrepxuXzZDsk"
secondaryOptions.projectID = "projectid-12345"
secondaryOptions.bundleID = "com.google.firebase.devrel.FiroptionConfiguration"
secondaryOptions.databaseURL = "https://myproject.firebaseio.com"
guard let secondary = FirebaseApp.app(name: "secondary")
else { assert(false, "Could not retrieve secondary app") }
// Retrieve a Real Time Database client configured against a specific app.
let _ = Database.database(app: secondary)
var collectionReference:CollectionReference?
collectionReference =
Firestore.firestore().collection("eclinic").document("1002").collection("chats")
collectionReference?.order(by: "timestamp", descending: false).addSnapshotListener { [self] (snapShot, err) in
if let error = err {
print("Error \(error)")
}else{
guard let snapDoc = snapShot?.documents else {
print("Return ")
return
}
}
}
Exploring this documentation link I was able to get over my problem, the code is as follows
let secondaryOptions = FirebaseOptions(googleAppID: "1:27992087142:ios:2a4732a34787067a",
gcmSenderID: "27992087142")
secondaryOptions.apiKey = "AIzaSyBicqfAZPvMgC7NZkjayUEsrepxuXzZDsk"
secondaryOptions.projectID = "projectid-12345"
secondaryOptions.bundleID = "com.google.firebase.devrel.FiroptionConfiguration"
secondaryOptions.databaseURL = "https://myproject.firebaseio.com"
FirebaseApp.configure(name: "secondary", options: secondaryOptions)
// Retrieve a Real Time Database client configured against a specific app.
guard let secondary = FirebaseApp.app(name: "secondary")
else { assert(false, "Could not retrieve secondary app") }
let firestoreSecondary = Firestore.firestore(app: secondary)
var collectionReference:CollectionReference?
collectionReference =
firestoreSecondary.collection("eclinic").document("1002").collection("chats")
collectionReference?.order(by: "timestamp", descending: false).addSnapshotListener { [self] (snapShot, err) in
if let error = err {
print("Error \(error)")
}else{
guard let snapDoc = snapShot?.documents else {
print("Return ")
return
}
}
}

CloudKit Public Records And Changes not Downloaded

CloudKit Public Records And Changes not Downloaded
I have a CloudKit app with records for both a Public and a Custom Private
Zone. I seem to have the change token process working for the custom
private zone but am unable to get the public data to work. The code I am
using is identical for both databases except for the public/private
names and using the default zone for the public. I understand that
subscriptions do not work on default zones, but I could not find any
references to limitations on change tokens for public data. Xcode 10.1, iOS 12.0
I create my PubicData class and initialize it:
var publicDatabase : CKDatabase!
init() {
let kAppDelegate = UIApplication.shared.delegate as! AppDelegate
context = kAppDelegate.context
let container = CKContainer.default()
publicDatabase = container.publicCloudDatabase
}//init
the download function that is called from the app entry scene - a tableview:
func downloadPublicUpdates(finishClosure : # escaping(UIBackgroundFetchResult) -> Void) {
var listRecordsUpdated : [CKRecord] = []
var listRecordsDeleted : [String : String] = [:]
var publicChangeToken : CKServerChangeToken!
var publicChangeZoneToken : CKServerChangeToken!
let userSettings = UserDefaults.standard
if let data = userSettings.value(forKey: "publicChangeToken") as? Data {
if let token = try? NSKeyedUnarchiver.unarchivedObject(ofClass : CKServerChangeToken.self, from : data) {
publicChangeToken = token
print("publicChangeToken exists")
}
} else {
print("userSettings entry for publicChangeToken does not exist")
}//if let data
if let data = userSettings.value(forKey: "publicChangeZoneToken") as? Data {
if let token = try? NSKeyedUnarchiver.unarchivedObject(ofClass: CKServerChangeToken.self, from: data) {
publicChangeZoneToken = token
}
}//if let data
let zone = CKRecordZone.default()
var zonesIDs : [CKRecordZone.ID] = [zone.zoneID]
let operation = CKFetchDatabaseChangesOperation(previousServerChangeToken: publicChangeToken)
operation.recordZoneWithIDChangedBlock = {(zoneID) in
zonesIDs.append(zoneID)
}
operation.changeTokenUpdatedBlock = {(token) in
publicChangeToken = token
}
operation.fetchDatabaseChangesCompletionBlock = {(token, more, error) in
if error != nil{
finishClosure(UIBackgroundFetchResult.failed)
} else if !zonesIDs.isEmpty {
publicChangeToken = token
let configuration = CKFetchRecordZoneChangesOperation.ZoneConfiguration()
configuration.previousServerChangeToken = publicChangeZoneToken
let fetchOperation = CKFetchRecordZoneChangesOperation(recordZoneIDs: zonesIDs, configurationsByRecordZoneID: [zonesIDs[0] : configuration])
fetchOperation.recordChangedBlock = {(record) in
listRecordsUpdated.append(record)
}//fetchOperation.recordChangedBlock
fetchOperation.recordWithIDWasDeletedBlock = {(recordID, recordType) in
listRecordsDeleted[recordID.recordName] = recordType
}//fetchOperation.recordWithIDWasDeletedBlock
fetchOperation.recordZoneChangeTokensUpdatedBlock = {(zoneID, token, data) in
publicChangeZoneToken = token
}//fetchOperation.recordZoneChangeTokensUpdatedBlock
fetchOperation.recordZoneFetchCompletionBlock = {(zoneID, token, data, more, error) in
if let ckerror = error as? CKError {
self.processErrors(error: ckerror)
} else {
publicChangeZoneToken = token
self.updateLocalRecords(listRecordsUpdated : listRecordsUpdated)
self.deleteLocalRecords(listRecordsDeleted : listRecordsDeleted)
listRecordsUpdated.removeAll()
listRecordsDeleted.removeAll()
}//if else
}//fetchOperation.recordZoneFetchCompletionBlock
fetchOperation.fetchRecordZoneChangesCompletionBlock = {(error) in
if error != nil {
print("Error fetchRecordZoneChangesCompletionBlock")
finishClosure(UIBackgroundFetchResult.failed)
} else {
if publicChangeToken != nil {
if let data = try? NSKeyedArchiver.archivedData(withRootObject: publicChangeToken, requiringSecureCoding: false) {
userSettings.set(data, forKey : "publicChangeToken")
}
}//if changeToken != nil
if publicChangeZoneToken != nil {
if let data = try? NSKeyedArchiver.archivedData(withRootObject: publicChangeZoneToken, requiringSecureCoding: false) {
userSettings.set(data, forKey : "publicChangeZoneToken")
}
}
//self.updateInterface()
self.updateLocalReferences()
finishClosure(UIBackgroundFetchResult.newData)
}
}//fetchOperation.fetchRecordZoneChangesCompletionBlock
self.publicDatabase.add(fetchOperation)
} else {//else if !zonesIDs.isEmpty
finishClosure(UIBackgroundFetchResult.noData)
}//if zoneid not empty
}//fetchDatabaseChangesCompletionBlock
print("listRecordsUpdated.count is \(listRecordsUpdated.count)")
publicDatabase.add(operation)
}//downloadPublicUpdates
Outside of class: var PD = PDData()
I call the download method in viewDidLoad from the initial TableViewController:
PD.downloadPublicUpdates { (result) in
print("in ctvc viewDidLoad and downloadPublicUpdates")
switch result {
case .noData:
print("no data")
case .newData:
print("new data")
case .failed:
print("failed to get data")
}//switch
}//downloadPublicUpdates
The console output is always:
userSettings entry for publicChangeToken does not exist
listRecordsUpdated.count is 0
in ctvc viewDidLoad and downloadPublicUpdates
failed to get data
Any guidance would be appreciated.
There are no change tokens available in a public database. Those only exist in private and shared databases.
To keep things in sync, you typically have to keep a modification date on records locally, and then query for stuff that is newer on the CloudKit server using a CKQueryOperation.
Good luck!

Swift Firebase - get current user with document UID to populate list

So I have done this on my android app (and it works), to populate a list with the document names from a collection
db.collection("usersAuth/${FirebaseAuth.getInstance().uid!!}/KitLists")
.addSnapshotListener(EventListener<QuerySnapshot> { value, e ->
if (e != null) {
Log.w("TAG", "Listen failed.", e)
return#EventListener
}
for (document in value.documents) {
val data = document
val kitName = data.id
firstKitList.add(kitName)
}
mainListViewAdapter.notifyDataSetChanged()
})
I am trying to do the same on my iOS version but I don't know whats wrong
override func viewWillAppear(_ animated: Bool) {
setListener()
}
func setListener() {
db.collection("usersAuth/\(String(describing: Auth.auth().currentUser))/KitLists")
.addSnapshotListener { (snapshot, error ) in
if let err = error {
debugPrint("Error fetching docs: \(err)")
} else {
guard let snap = snapshot else {return}
for document in snap.documents {
let data = document.data()
let kitListName = data["KitLists"] as? String
let newLists = KitList(kitListName: kitListName!)
self.lists.append(newLists)
}
self.tableView.reloadData()
}
}
}
any ideas? Thanks
-- EDIT
Firestore
Firestore2
You need to get the uid from the currentUser, for example:
if let userId = Auth.auth().currentUser.uid {
db.collection("usersAuth").document(userId).collection("KitLists")
.addSnapshotListener { (snapshot, error ) in
//...
}
To get the KitLists documentId
for document in snap.documents {
let documentName = document.documentID // <--- This
let newLists = KitList(kitListName: documentName)
self.lists.append(newLists)
}

Resources