I want to set the data from Firebase to the properties in the class.

Asked 2 years ago, Updated 2 years ago, 125 views

class ViewController:UIViewController {
    //.....
    var friendId—String!
    userID="098752"
    letPath=ref.child("user/\(userID)/friend/userId")
       Path.observeSingleEvent(of:.value, with:{(snapshot)in
           self.friendId=snapshot.value as? String
           print(self.friendId!) // Displayed correctly here
       }) {(error) in
           print(error.localizedDescription)
       }
   print(self.friendId)// The value is not set well here
}

This process has done enough to retrieve the data, but (print(self.friendId!) is displayed correctly on the console.) After this process, self.guideId cannot be called.

I'd like to use this self.friendId to specify a path when retrieving other data.↓

let namePath=ref.child("user/\(self.friendId)/name")
    namePath.observeSingleEvent(of:.value, with:{(snapshot)in
        self.friendNameLabel.text=snapshot.value as? String
    }) {(error) in
        print(error.localizedDescription)
    }

If anyone knows what the problem is, please let me know...
It hasn't been long since I started Swift, so I'm sorry if it's such a silly question...

swift4 firebase

2022-09-30 19:43

1 Answers

The results obtained from asynchronous methods are incorrectly used.

This part of your code:

...{(snapshot)in
    self.friendId=snapshot.value as? String
    print(self.friendId!)
}

This is passed to the observeSingleEvent(of:with:withCancel:) method with the meaning "Do this when the process is complete" and is not executed immediately; the method ends once and the next line begins to run.

Since the above closure is not running at that time, it is normal for print(self.friendId) to not have a set value.

The theory is that the value obtained from the asynchronous method is always to be used in the completion handler.

...{(snapshot)in
    self.friendId=snapshot.value as? String
    print(self.friendId!)
    // `self.friendId` must be used in this
    //....
    // (If it's going to be long, you can make another method and call it)
}

iOS uses a lot of asynchronous processing, not just Firebase, so if you don't remember this theory, you won't be able to create an app that works properly.If Firebase is not limited, there are many cases where the same asynchronous processing actually causes it to fail here in the Japanese stack overflow.

Your question has been edited, so please add a little more.

The acquired self.friendId seems to say "I want to use it to specify a path for another data retrieval", but it's not long enough to say "get longer", so you can write the entire process of "get another data" in the completion handler.

You don't even need to "set into properties" like the one in the title of your question.

let path=ref.child("user/\(userID)/friend/userId")
    path.observeSingleEvent(of:.value, with:{(snapshot)in
        guard let friendId = snapshot.value as ? String else {
            print("friendId is not a String")
            return
        }
        print(friendId) // It should be displayed correctly here
        //### The value obtained from the asynchronous method must be used in the completion
        let namePath=ref.child("user/\(friendId)/name")
        namePath.observeSingleEvent(of:.value, with:{(snapshot)in
            guard let friendName = snapshot.value as ? String else {
                print("friendName is not a String")
                return
            }
            //### UI parts must be updated within the main thread (UI thread)
            DispatchQueue.main.async {
                self.friendNameLabel.text=friendName
            }
        }) {(error) in
            print(error.localizedDescription)
        }
    }) {(error) in
        print(error.localizedDescription)
    }

It's a mix of different levels of things, from what's very important to creating apps that work properly to what everyone is following, but I've noticed a few things.

  • Swift uses only type names with capitalization identifiers
    It is a very well-observed rule among experienced Swift programmers.On the other hand, if you see a code that doesn't keep it, you'd better suspect that it's a reliable code.Your Path has been rewritten to path.

  • snapshot.value as? String results in the Optional<String> type
    If you keep Optional and continue to process it, there will be many harmful effects, so use the guard statement to unwrap it in a safe way as soon as possible.

    Although the original code uses the implicit unwrapped Optional type, such as var friendId:String!, the use of the implicitly unwrapped Optional type should be avoided as much as possible.If you can be nil, you should use the explicit Optional type (String? type).
    For example, the code "user/\(self.friendId)/name" in the add-on section is odd if self.friendId is of type Optional.(You will notice that the current Swift will give you a warning.)

  • Make sure to update UI parts within the main thread (UI thread)
    This is the basis of iOS programming, but asynchronous method completion handlers like this are usually referred to outside the main thread.When updating UI components, be sure to enclose them with DispatchQueue.main.async {...}.

    (By the way, friendNameLabel is probably UILabel, but you didn't write that down anywhere...)

Swift uses only the type name with a capital letter start identifier.
It is a very well-observed rule among experienced Swift programmers.On the other hand, if you see a code that doesn't keep it, you'd better suspect that it's a reliable code.Your Path has been rewritten to path.

snapshot.value as? String results in the Optional<String> type
If you keep Optional and continue to process it, there will be many harmful effects, so use the guard statement to unwrap it in a safe way as soon as possible.

Although the original code uses the implicit unwrapped Optional type, such as var friendId:String!, the use of the implicitly unwrapped Optional type should be avoided as much as possible.If you can be nil, you should use the explicit Optional type (String? type).
For example, the code "user/\(self.friendId)/name" in the add-on section is odd if self.friendId is of type Optional.(You will notice that the current Swift will give you a warning.)

Make sure to update UI parts within the main thread (UI thread)
This is the basis of iOS programming, but asynchronous method completion handlers like this are usually referred to outside the main thread.When updating UI components, be sure to enclose them with DispatchQueue.main.async {...}.

(By the way, friendNameLabel is probably UILabel, but you didn't write that down anywhere...)

The actual code may be a little more complicated, but for the time being, it looks like this if you summarize it as far as you can understand from the question.If you have any questions, please edit them again or add comments.


2022-09-30 19:43

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.