Search code examples
iosswiftxcodeuitableviewtableview

How can I slowly scroll up and down my table view from a background thread?


I am trying to figure out how I can scroll through my tableview through a background thread in xcode/swift. Here is the code I have so far:

func startBackgroundScrollingThread() {
    DispatchQueue.global(qos: .background).async {
        while self.scrollingMode {
            for row in 0..<self.list.count {
                DispatchQueue.main.async {
                    if self.scrollingMode {
                        Thread.sleep(forTimeInterval: 0.2)
                        let indexPath = IndexPath(row: row, section: 0)
                        self.tableView.scrollToRow(at: indexPath, at: .none, animated: true)
                    }
                }
                
                Thread.sleep(forTimeInterval: 0.2)
            }
            
            for row in (0..<self.list.count).reversed() {
                DispatchQueue.main.async {
                    if self.scrollingMode {
                        Thread.sleep(forTimeInterval: 0.2)
                        let indexPath = IndexPath(row: row, section: 0)
                        self.tableView.scrollToRow(at: indexPath, at: .none, animated: true)
                    }
                }
                Thread.sleep(forTimeInterval: 0.5)
            }
        }
    }
}

This code kinda works but it is not a smooth scroll. It is very janky. I would ideally like it to slowly go down the view and then back up over and over again. I appreciate any help!


Solution

  • Comment this line

    Thread.sleep(forTimeInterval: 0.2)
    

    inside DispatchQueue.main.async as it makes the main thread sleep for a while , but you need to only make the background thread to do the t sleep only

    Edit: without using scrollToRow you can think of contentOffset

    
    struct Country {
        var isoCode: String
        var name: String
    }
    
    class CountriesTableViewController: UITableViewController {
        var scrollingMode = true
        let countries = [
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
            Country(isoCode: "at", name: "Austria"),
            Country(isoCode: "be", name: "Belgium"),
            Country(isoCode: "de", name: "Germany"),
            Country(isoCode: "el", name: "Greece"),
            Country(isoCode: "fr", name: "France"),
        ]
    
        // MARK: - Table view data source
        
        var height:CGFloat = 40
        
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                self.startBackgroundScrollingThread()
            }
        }
        
        func startBackgroundScrollingThread() {
            let max = self.tableView.contentSize.height - self.tableView.frame.height
            DispatchQueue.global(qos: .background).async {
                while self.scrollingMode && self.height < max {
                    DispatchQueue.main.async {
                        //Thread.sleep(forTimeInterval: 0.2)
                        self.tableView.contentOffset = CGPoint(x: self.tableView.contentOffset.x, y: self.height)
                        self.height += 5
                        print(self.height)
                    }
                    Thread.sleep(forTimeInterval: 0.2)
                }
                
                while self.scrollingMode && self.height >= 0 {
                    DispatchQueue.main.async {
                        //Thread.sleep(forTimeInterval: 0.2)
                        self.tableView.contentOffset = CGPoint(x: self.tableView.contentOffset.x, y: self.height)
                        self.height -= 5
                        print(self.height)
                    }
                    Thread.sleep(forTimeInterval: 0.2)
                }
            }
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            self.countries.count
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "CountryCell", for: indexPath)
    
            let country = self.countries[indexPath.row]
            cell.textLabel?.text = country.name
            cell.detailTextLabel?.text = country.isoCode
            cell.imageView?.image = UIImage(named: country.isoCode)
    
            return cell
        }
    
        override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
            "Countries"
        }
    }