John Doah
John Doah

Reputation: 1999

Else on If Else statement won't get triggered, can't understand why

I have this block of code:

func fetchFriends() {
    if let window = UIApplication.shared.keyWindow {
        guard let userId = Auth.auth().currentUser?.uid else { return }
        DispatchQueue.main.async {
            FirestoreService.shared.fetchFriendList(userId) { (fetchedFriends) in
                //// WONT GET HERE ////
                if fetchedFriends != nil {
                    self.fetchedFriends = fetchedFriends! // Can force unwrap here because we already know that fetchedFriends in not nil.
                    self.friendsTable.reloadData()
                }else {
                    self.fetchedFriends = []
                    self.friendsTable.reloadData()
                }
            }
        }
    }
}

This block of code is using this function:

func fetchFriendList(_ id: String, completion: @escaping([Friend]?)->()) {
    var fetchedFriends: [Friend] = []
    db.collection(USERS_COLLECTION).document(id).getDocument { (doc, err) in
        if err == nil && doc != nil {
            guard let results = doc?.data()?[USER_FOLLOWING] as? [String: Any] else { return }
            for result in results { // Getting the data in firebase
                if let resultValue = result.value as? [String: Any] { // Getting only the value of the MAP data, we do not need the key.

                    //Getting the fields from the result
                    guard let id = resultValue[FRIEND_ID] as? String else { return }
                    guard let profilePic = resultValue[FRIEND_PROFILE_PIC] as? String else { return }
                    guard let username = resultValue[FRIEND_NAME] as? String else { return }
                    guard let email = resultValue[FRIEND_MAIL] as? String else { return }

                    //Creating a new Friend object from the fields
                    let friend = Friend(id: id, profilePicture: profilePic, username: username, email: email)

                    fetchedFriends.append(friend)
                }
                completion(fetchedFriends)
            }
        }else {
            print(err!.localizedDescription)
            completion(fetchedFriends)
        }
    }
}

Whats happening here, is that I'm going into a user's document, getting it's 'Friends' from a Map I have in the document, creating a Friend Array and sending it in the completion to the first function. In the first function, I'm checking if what I got is nil, if not, I'm assigning it to an array, else, if it is nil, I want the array to be empty.

The purpose here is to show the "Friends" in the tableView if the user has any.

My problem is this situation:

For start, the list of friends is empty, adding a friend and viewing the list, the friend I just added is showing, which is good. the problem is, when I'm removing this friend from the list (and it is deleted in the Database in Firestore), showing the list again does not deletes him from the list and still showing it. It seems that after removing a friend from the "following" section, and showing the list again, after FirestoreService.shared... it just returns and won't get to the "Won't get here" line.

The FetchFriends() function does gets called everytime I'm opening the FriendsList.

This is a picture of the list I'm referring to, this demouser is removed from the friends list but still showing up.

enter image description here

EDIT: Just noticed that when I have more than one user on the list, it does gets deleted and it works as I want. When I have just one user (or just one left on the list) it won't delete it.

Upvotes: 0

Views: 60

Answers (1)

Sulthan
Sulthan

Reputation: 130102

fetchFriendList never calls the callback with a nil value:

var fetchedFriends: [Friend] = []

Therefore your else branch is unnecessary and the completion handler could be @escaping ([Friend]) -> Void without optionals.

By the way, there is also a situation when your method does not call completion at all:

guard let results = doc?.data()?[USER_FOLLOWING] as? [String: Any] else { return }

In general, there are many unsafe places. For example, when err is nil and doc is nil, then your else will crash unwraping err!.

A better alternative:

guard err == nil, let doc = doc else {
   print(err?.localizedDescription)
   completion([])
   return
}

let results = (doc.data()?[USER_FOLLOWING] as? [String: Any]) ?? [:]

let fetchedFriends = results.compactMap { result in
   guard
      let resultValue = result.value as? [String: Any],
      let id = resultValue[FRIEND_ID] as? String,
      let profilePic = resultValue[FRIEND_PROFILE_PIC] as? String,
      let username = resultValue[FRIEND_NAME] as? String,
      let email = resultValue[FRIEND_MAIL] as? String
   else { return nil }

   return Friend(id: id, profilePicture: profilePic, username: username, email: email)
}
completion(fetchedFriends)

Upvotes: 2

Related Questions