Soru Swift tableView Sayfalandırması


Ben json ayrıştırma kodları ile başarılı çalışma tableview var.Ama yan kaydırma yaparken 1000 öğe daha çok sayfalama gerekebilir. Bunu kodlarımın altında nasıl yapabilirim bilmiyorum. Objektif-c için çok fazla örnek var ama hızlı bir şekilde çalışma örneği bulamadım. Yardımlarını bekliyorum. Bence çok fazla insan olacak. Teşekkür ederim !

import UIKit

class ViewController: UIViewController, UITableViewDataSource,UITableViewDelegate {

    let kSuccessTitle = "Congratulations"
    let kErrorTitle = "Connection error"
    let kNoticeTitle = "Notice"
    let kWarningTitle = "Warning"
    let kInfoTitle = "Info"
    let kSubtitle = "You've just displayed this awesome Pop Up View"


    @IBOutlet weak var myTableView: UITableView!
    @IBOutlet weak var myActivityIndicator: UIActivityIndicatorView!

    var privateList = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        loadItems()

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return privateList.count
    }




    internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {

       let cell:myCell = tableView.dequeueReusableCellWithIdentifier("myCell") as! myCell

        cell.titleLabel.text = privateList[indexPath.row]


        return cell
    }


    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

        if (editingStyle == UITableViewCellEditingStyle.Delete){

         print(indexPath.row)


            let alert = SCLAlertView()
            alert.addButton("Hayır"){ }
            alert.addButton("Evet") {

                self.myTableView.beginUpdates()

                 self.privateList.removeAtIndex(indexPath.row)
                tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Left)
                print("Silindi")

                self.myTableView.endUpdates()

                  self.loadItems()

            }
            alert.showSuccess(kSuccessTitle, subTitle: kSubtitle)

        }


    }





    func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // the cells you would like the actions to appear needs to be editable
        return true
    }



    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {


        if(segue.identifier == "Detail") {

            let destinationView = segue.destinationViewController as! DetailViewController

            if let indexPath = myTableView.indexPathForCell(sender as! UITableViewCell) {

                destinationView.privateLista = privateList[indexPath.row]

            }
        }
    }



    internal func tableView(tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat
    {
        return 0.0
    }


    func loadItems()
    {
     loadItemsNow("privateList")

    }

    func loadItemsNow(listType:String){
        myActivityIndicator.startAnimating()
        let listUrlString =  "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString
        let myUrl = NSURL(string: listUrlString);
        let request = NSMutableURLRequest(URL:myUrl!);
        request.HTTPMethod = "GET";

        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
            data, response, error in

            if error != nil {
                print(error!.localizedDescription)
                dispatch_async(dispatch_get_main_queue(),{
                    self.myActivityIndicator.stopAnimating()
                })

                return
            }


            do {

                let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSArray

                if let parseJSON = json {


                        self.privateList = parseJSON as! [String]

                }

            } catch {
                print(error)

            }

            dispatch_async(dispatch_get_main_queue(),{
                self.myActivityIndicator.stopAnimating()
                self.myTableView.reloadData()
            })


        }

        task.resume()
    }


}

32
2018-02-12 16:26


Menşei


Bir seferde bin nesne mi getiriyorsunuz? - Shehzad Ali
@ShehzadAli hayır ama alt kaydırma iyi olacak zaman yenilerini yenilemek gerekir. Ayrıca birçok öğe çok zaman alacak. - SwiftDeveloper


Cevaplar:


Bunun için de sunucu tarafında değişiklik yapmanız gerekir.

  1. Sunucu kabul edecek fromIndex ve batchSize içinde API sorgu param olarak url.

    let listUrlString =  "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex
    
  2. Sunucu yanıtında, fazladan bir anahtar olacak totalItems. Bu, alınan veya alınmayan tüm öğeleri tanımlamak için kullanılacaktır. Bir dizi veya öğeler fromIndex için batchSize öğe sayısı.

Uygulama tarafında

  1. İlk loadItem() ile çağrılacak fromIndex = 0 ve batchSize = 20 (örneğin viewDidLoad() veya viewWillAppear). fromAll öğeleri kaldır privateList çağrıdan önce dizi loadItem() ilk kez

  2. Sunucu ilk 20 öğeden oluşan bir dizi döndürür ve totalItems sunucudaki toplam öğe sayısı.

  3. İçindeki 20 öğeyi ekle privateList dizi ve yeniden yükle tableView

  4. İçinde tableView:cellForRowAtIndexPath Hücrenin son hücre olup olmadığını kontrol edin. Ve kontrol edin totalItems (form sunucusu) daha büyüktür privateList.count. Bu, sunucuda yüklenecek daha fazla öğe olduğu anlamına gelir

    if indexPath.row == privateList.count - 1 { // last cell
        if totalItems > privateList.count { // more items to fetch
            loadItem() // increment `fromIndex` by 20 before server call
        }
    }
    

Soru:  where is refresh ? will be scrolling ?

Sunucu yanıtı alındığında dizide yeni öğeler ekledikten sonra yenileyin. (Aşama 3)

Kaydırma tetiklenecek tableView:cellForRowAtIndexPath Kullanıcı kaydırdığında her hücre için. Kod, son hücre olup olmadığını kontrol eder ve kalan öğeleri alır. (adım 4)

Örnek proje eklendi:
https://github.com/rishi420/TableViewPaging


38
2018-02-18 07:26



yenileme nerede? kaydırma yapacak? - SwiftDeveloper
test edeceğim kodun tamamını tam kod yazabilir miyim - SwiftDeveloper
@SwiftDeveloper Cevap Örnek proje linki ile güncellendi. İndir, koş ve gör print log. - Warif Akhand Rishi
:) bana bir örnek URL ver http://bla.com/json2.php?listType=... nerede vurup test edebilirim - Warif Akhand Rishi
Mükemmel cevap bu kolay çözüm için çok teşekkür ederim. - Hardik Thakkar


Bunu yapmanın iyi ve verimli yolu kullanmaktır scrollviewDelegate masaüstünde Sadece ekle UIScrollViewDelegate senin içinde viewController Denetleyici içinde

//For Pagination
var isDataLoading:Bool=false
var pageNo:Int=0
var limit:Int=20
var offset:Int=0 //pageNo*limit
var didEndReached:Bool=false
viewDidLoad(_){
tableview.delegate=self //To enable scrollviewdelegate
}

Bu temsilci tarafından iki yöntemi geçersiz kıl

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

        print("scrollViewWillBeginDragging")
        isDataLoading = false
    }



    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        print("scrollViewDidEndDecelerating")
    }
    //Pagination
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

            print("scrollViewDidEndDragging")
            if ((tableView.contentOffset.y + tableView.frame.size.height) >= tableView.contentSize.height)
            {
                if !isDataLoading{
                    isDataLoading = true
                    self.pageNo=self.pageNo+1
                    self.limit=self.limit+10
                    self.offset=self.limit * self.pageNo
                    loadCallLogData(offset: self.offset, limit: self.limit)

                }
            }


    }

7
2017-12-30 11:20



İyi iş ... Büyük sorun senin basit mantığı çöz - Jayesh Miruliya


Bu, iOS10'da yeni bir protokolün eklenmesiyle artık biraz daha kolay: UITableViewDataSourcePrefetching

https://developer.apple.com/documentation/uikit/uitableviewdatasourceprefetching


4
2017-12-16 19:19





Masa bölümünüze başka bir bölüm ekleyin, bu bölümün yüklemeyi belirtmek için bir etkinlik göstergesi içeren bir hücre olacak yalnızca 1 satırı olsun.

internal func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
    return 2;
}

internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        if section == 0 {
            return privateList.count
        } else if section == 1 {    // this is going to be the last section with just 1 cell which will show the loading indicator
            return 1
        }
    }

internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
   if section == 0 {
       let cell:myCell = tableView.dequeueReusableCellWithIdentifier("myCell") as! myCell

        cell.titleLabel.text = privateList[indexPath.row]


        return cell
    } else if section == 1 { 
        //create the cell to show loading indicator
        ...

        //here we call loadItems so that there is an indication that something is loading and once loaded we relaod the tableview
        self.loadItems()
    }
}

2
2018-02-19 10:12





SWIFT 3.0 - 4 ...

Sayfa numarasını API isteğinde gönderiyorsanız, bu, uygulamanızda sayfalandırma işlemini gerçekleştirmenin en ideal yoludur.

1) Başlangıç ​​Değeri 0 olan değişken akım Sayfasını ve herhangi bir listenin başlangıç ​​değeri hatalı olarak yüklenip yüklenmediğini kontrol etmek için bir boole bildirir.

var currentPage : Int = 0
var isLoadingList : Bool = false

2) Bu liste örneğini alan işlevdir:

 func getListFromServer(_ pageNumber: Int){
 self.isloadingList = false
 self.table.reloadData()
 } 

3) Bu, sayfa sayısını artıran ve API işlevini çağıran işlevdir.

 func loadMoreItemsForList(){
 currentPage += 1
 getListFromServer(currentPage)
 }

4) Bu, scrollView scrolls olduğunda çağrılacak yöntemdir

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if (((scrollView.contentOffset.y + scrollView.frame.size.height) > scrollView.contentSize.height ) && ! isLoadingList){
        self. isLoadingList = true
        self. loadMoreItemsForList()
    }
}

Not; bool isLoadingList rolü, kaydırma görünümünün tek bir sürüklemede tablo görünümünün altına daha fazla liste almasını engellemektir.


2
2017-12-14 14:08





Bunu yapmanın başka bir yolu: Her seferinde istek gönderirken öğe almak için bir eşik ayarlayabilirsiniz:

İlk defa 20 element aldığınızı söyleyelim. Sonraki 20 öğenin listesini almak için son getirilen kayıt kimliğini veya numarasını kaydedeceksiniz.

let lastFetchedIndex = 20;

Bu kayıtları myArray'ınıza zaten eklediğinizi varsayıyorum. MyArray, tablo Görünümü'nün veri kaynağıdır. Artık myArray, 40 nesne içeriyor. Şimdi TableView'a eklenmesi gereken indexPath satırlarının listesini yapacağım.

var indexPathsArray = [NSIndexPath]()


for index in lastFetchedIndex..<myArray.count{
    let indexPath = NSIndexPath(forRow: index, inSection: 0)
    indexPathsArray.append(indexPath)

}

İşte masaüstümü güncelliyorum. Veri kaynağınızın myArray öğenizin zaten güncellendiği anlamına geldiğinden emin olun. Böylece satırları düzgün bir şekilde ekleyebilir.

self.tableView.beginUpdates()
tableView!.insertRowsAtIndexPaths(indexPathsArray, withRowAnimation: .Fade)
self.tableView.endUpdates()

1
2018-02-12 17:52



Cevap için teşekkürler dostum ama bu kodları nereye ekleyebilirim? - SwiftDeveloper
Adımları açıkladım. Yeni nesnelerin yığınlarını aldıktan sonra kodunuzu bu kod ile güncelleyin. Sunucudan gelen öğelerin yığınlarını, tablo görünümünün veri kaynağı olarak kullanılan dizinize ekleyin. Ardından, yukarıda belirtilen kodu kodunuza ekleyin. Yukarıdaki kod bir yönteme yerleştirilebilir. - Shehzad Ali
Lütfen cevabınızı düzenleyin ve orjinal kodlarımı geçmiş ve daha sonra kontrol edeceğim ve eğer çalışırsa, cevabınızı onaylayacağım. - SwiftDeveloper


Bir projeye benzer bir şeye ihtiyacım vardı ve çözümüm şunlardı:

1 - bir değişken numberOfObjectsInSubArray (başlangıç ​​değeri 30 veya istediğiniz her şey) oluşturun

2 - "daha fazlasını göster" seçeneğine her dokunduğumda privateList dizinizden bir dizi nesne eklemek için bir alt dizi oluşturun.

    let subArray = privateList?.subarrayWithRange(NSMakeRange(0, numberOfObjectsInSubArray))

Ve onu kullan

internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return subArray.count
}

3- Daha fazla nesne göstermeniz gerektiğinde şunları yapın:

func addMoreObjectsOnTableView () {

    numberOfObjectsInSubArray += 30

    if (numberOfObjectsInSubArray < privateList.count) {

        subArray = privateList?.subarrayWithRange(NSMakeRange(0, numberOfObjectsInSubArray))  

    } else {

        subArray = privateList?.subarrayWithRange(NSMakeRange(0, privateList.count))  
    }

    tableView.reloadData()
}

Umut ediyorum bu yardım eder


1
2018-02-18 21:58