2

I am fetching some data from firebase and showing it to the UITableView but each time when I scroll the tableview it freezes for 2-3 second.Here is the UITableViewDataSource

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        list.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIndetifire) as? HallListCell else {
            return UITableViewCell()
        }
        cell.configure(list: list[indexPath.row])
        return cell
    }

and here is the loadData function which observe and fetch data from firebase and reload the UITableView

func loadData(){
        guard let uid = currentUID else {
            return
        }
        list.removeAll()
        self.ref.child("users/\(uid)").child("SWITCH/HALL").observe(.childAdded, with: { (snapshot) -> Void in
         
            guard let value = (snapshot.value)  as? [String : String] else {
                return
            }
            guard let name = value["name"],let img = value["img"], let status = value["status"]  else {
                return
            }
            self.list.append(DataModel(name: name, img: img, status: status,keyPrimices: "HALL",keyAppliances: snapshot.key))
            DispatchQueue.main.async {
                self.tblListOfHallAppliances.reloadData()
                self.tblListOfHallAppliances.isHidden = false
                self.activityIndicator.isHidden = true
            }
            
        })
    }

code in cell.configure(list: list[indexPath.row]) is written below which is placed in cell

func configure(list: DataModel) {
        keyPrimices = list.keyPrimices
        keyAppliances = list.keyAppliances
        lblAppliancesName.text = list.name
        switchStauts.isOn = (list.status == "ON")
        
        switch keyAppliances {
        case "FAN":
            list.status == "ON" ? imgIcon.fanAnimation() : imgIcon.fanAnimationStop()
        case "LIGHT":
            list.status == "ON" ? imgIcon.lightAnimation() : imgIcon.lightAnimationStop()
        case "AC":
            list.status == "ON" ? imgIcon.acAnimation(): imgIcon.acAnimationStop()
        case "TV":
            list.status == "ON" ? imgIcon.tvAnimation(): imgIcon.tvAnimationStop()
        default:
            if let url = URL(string: list.img) {
                loadImage(url: url, imageOutlet: imgIcon)
            }
        }
    }

UIImageView extension is below

extension UIImageView {
    func fanAnimation() {
        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.toValue = NSNumber(value: Double.pi * 2)
        rotation.duration = 0.5
        rotation.repeatCount = Float.greatestFiniteMagnitude
        self.image = UIImage(named: "fan")
        self.layer.add(rotation, forKey: "rotationAnimation")
        
    }
    
    func fanAnimationStop() {
        self.layer.removeAllAnimations()
        self.image = UIImage(named: "fan")
    }
    
    func lightAnimation() {
        let animation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
        animation.fromValue = 0.2
        animation.toValue = 1.0
        animation.duration = 0.5
        animation.autoreverses = true
        animation.repeatCount = Float.greatestFiniteMagnitude
        self.image = UIImage(named: "light_on")
        self.layer.add(animation, forKey: "fade")
    }
    func lightAnimationStop() {
        self.layer.removeAllAnimations()
        self.image = UIImage(named: "light_off")
    }
    func acAnimation () {
        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.toValue = NSNumber(value: Double.pi/9)
        rotation.fromValue = NSNumber(value: -Double.pi/9)
        rotation.duration = 0.5
        rotation.autoreverses = true
        rotation.repeatCount = Float.greatestFiniteMagnitude
        self.image = UIImage(named: "ac_on")
        self.layer.add(rotation, forKey: "acAnimation")
    }
    func acAnimationStop() {
        self.layer.removeAllAnimations()
        self.image = UIImage(named: "ac_off")
    }
    
    func tvAnimation () {
        let rotation = CABasicAnimation(keyPath: "transform.scale")
        rotation.toValue = NSNumber(value: 1)
        rotation.fromValue = NSNumber(value: 0.5)
        rotation.duration = 0.5
        rotation.autoreverses = true
        rotation.repeatCount = Float.greatestFiniteMagnitude
        self.image = UIImage(named: "tv_on")
        self.layer.add(rotation, forKey: "tvAnimation")
    }
    func tvAnimationStop() {
        self.layer.removeAllAnimations()
        self.image = UIImage(named: "tv_off")
    }
}
Purvesh Dodiya
  • 594
  • 3
  • 17
  • Could you provide the code of `cell.configure(list: list[indexPath.row])` – IvanovDeveloper Apr 10 '21 at 18:08
  • Looks like you manage the data in the main queue, probably it is reason of the freezes. – IvanovDeveloper Apr 10 '21 at 18:11
  • remove DispatchQueue.main.async { line. – Emre Gürses Apr 10 '21 at 18:29
  • after removing DispatchQueue.main.async { same problem.....here I have added cell.configure(list: list[indexPath.row]) code – Purvesh Dodiya Apr 11 '21 at 04:45
  • Welcome to Stack Overflow, although it's difficult to guess what's happening here because the whole code is not clear, I'm guessing either your `loadData()` method is called several times or the observer for firebase datachange `.observe(.childAdded, with: observer)` is called several times. – Nick Kim Apr 11 '21 at 08:16
  • nope,On ```viewWillDisappear``` I am removing observer so there is no chance to call observer servel times and also ```loadData()``` is called in in ```viewWillAppear``` – Purvesh Dodiya Apr 11 '21 at 09:11
  • Just a FYI, you don't need `DispatchQueue.main.async` in Firebase closures; UI calls are always done on the main thread and networking is done on a background thread. – Jay Apr 11 '21 at 13:40
  • Are you trying to load an image from the internet while you're scrolling? `loadImage(url: url, imageOutlet: imgIcon)`?? – Jay Apr 11 '21 at 13:43
  • nope,I am not trying to load image but yes I am setting animation to imageView in```configure``` – Purvesh Dodiya Apr 12 '21 at 05:10
  • Then what does this `loadImage` do if it doesn't load an image? When responding in comments, please respond with the @ sign, like @Jay. – Jay Apr 12 '21 at 17:10
  • @jay you are right but it's default case.Right now I have ```keyAppliances``` as TV,AC,LIGHT and FAN so it will load image from system assest. I am editing this post and adding that ```UIImageView``` extension code.Kindly check it. – Purvesh Dodiya Apr 13 '21 at 04:12
  • Good updates. The only thing that's jumping out at me is the Firebase load. DispatchGroup is being called over and over again with every node that loaded `.childAdded`. I would alter the approach; leverage that .value events are called after .childAdded and refresh the tableView in a .value event. See my answer [here](https://stackoverflow.com/questions/57450794/swift-5-how-to-execute-code-after-fetching-all-childadded-from-firebase/57465578#57465578) or maybe [this](https://stackoverflow.com/questions/41082347/swift-firebase-loading-records-with-long-delay/41108155#41108155) – Jay Apr 13 '21 at 17:05

0 Answers0