Быстрая загрузка 10 строк в таблицеView за раз [дубликат]

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

79
задан rokridi 28 November 2013 в 17:11
поделиться

16 ответов

Вы можете сделать это, добавив проверку, где вы находитесь в методе cellForRowAtIndexPath:. Этот метод легко понять и реализовать:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Classic start method
    static NSString *cellIdentifier = @"MyCell";
    MyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (!cell)
    {
        cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainMenuCellIdentifier];
    }

    MyData *data = [self.dataArray objectAtIndex:indexPath.row];
    // Do your cell customisation
    // cell.titleLabel.text = data.title;

    BOOL lastItemReached = [data isEqual:[[self.dataArray] lastObject]]; 
    if (!lastItemReached && indexPath.row == [self.dataArray count] - 1)
    {
        [self launchReload];
    }
}

EDIT: добавлена ​​проверка последнего элемента для предотвращения вызовов рекурсии. Вам нужно будет реализовать метод, определяющий, достигнут ли последний элемент или нет.

EDIT2: объяснено lastItemReached

91
ответ дан shinyuX 18 August 2018 в 18:37
поделиться
  • 1
    Что делать, если пользователь прокручивается вверх и вниз, поэтому cellForRowAtIndexPath вызывается МНОГО ВРЕМЕНИ! ?? – onmyway133 19 March 2014 в 09:38
  • 2
    Первый раз он прокручивается донизу, его список будет перезагружен. И каждый раз, когда он попадает в нижнюю часть, будет собран новый фрагмент данных. Если какое-либо конкретное обращение должно применяться, то метод метода launchReload должен обрабатывать его (например, только одно асинхронное действие перезагрузки за раз) – shinyuX 19 March 2014 в 10:58
  • 3
    Я должен был добавить флаг, чтобы предотвратить проблему рекурсии при ударе последнего элемента: if !lastItemReached && indexPath.row == dataArray!.hits.count - 1 { – Albert Bori 22 November 2014 в 19:51
  • 4
    Что такое метод self.launchReload? – chicobermuda 22 February 2016 в 19:23
  • 5
    Метод launchReload - это ваш собственный метод сбора данных, которые будут заполнять ваш dataArray. Может быть вызов веб-службы, какой-то локальный синтаксический анализ json, .. – shinyuX 25 February 2016 в 11:33

Просто хочу поделиться этим подходом:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSLog(@"%@", [[YourTableView indexPathsForVisibleRows] lastObject]);
    [self estimatedTotalData];
}

- (void)estimatedTotalData
{
    long currentRow = ((NSIndexPath *)[[YourTableView indexPathsForVisibleRows] lastObject]).row;

    long estimateDataCount = 25;

    while (currentRow > estimateDataCount)
    {
        estimateDataCount+=25;
    }

    dataLimit = estimateDataCount;

    if (dataLimit == currentRow+1)
    {
        dataLimit+=25;
    }

    NSLog(@"dataLimit :%ld", dataLimit);

    [self requestForData];

    // this answers the question..
    //
    if(YourDataSource.count-1 == currentRow)
    {
        NSLog(@"LAST ROW"); //loadMore data
    }
}

NSLog(...); вывод будет примерно таким:

<NSIndexPath: 0xc0000000002e0016> {length = 2, path = 0 - 92}
dataLimit :100
<NSIndexPath: 0xc000000000298016> {length = 2, path = 0 - 83}
dataLimit :100
<NSIndexPath: 0xc000000000278016> {length = 2, path = 0 - 79}
dataLimit :100
<NSIndexPath: 0xc000000000238016> {length = 2, path = 0 - 71}
dataLimit :75
<NSIndexPath: 0xc0000000001d8016> {length = 2, path = 0 - 59}
dataLimit :75
<NSIndexPath: 0xc0000000001c0016> {length = 2, path = 0 - 56}
dataLimit :75
<NSIndexPath: 0xc000000000138016> {length = 2, path = 0 - 39}
dataLimit :50
<NSIndexPath: 0xc000000000120016> {length = 2, path = 0 - 36}
dataLimit :50
<NSIndexPath: 0xc000000000008016> {length = 2, path = 0 - 1}
dataLimit :25
<NSIndexPath: 0xc000000000008016> {length = 2, path = 0 - 1}
dataLimit :25

Это хорошо для отображения данных, хранящихся локально. Изначально я объявляю dataLimit равным 25, что означает, что uitableview будет иметь 0-24 (изначально).

Если пользователь прокручивается в нижнюю часть и отображается последняя ячейка dataLimit, будет добавлено 25 .. .

Примечание. Это больше похоже на подкачку данных UITableView,:)

0
ответ дан 0yeoj 18 August 2018 в 18:37
поделиться
let threshold = 100.0 // threshold from bottom of tableView
var isLoadingMore = false // flag


func scrollViewDidScroll(scrollView: UIScrollView) {
    let contentOffset = scrollView.contentOffset.y
    let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;

    if !isLoadingMore && (maximumOffset - contentOffset <= threshold) {
        // Get more data - API call
        self.isLoadingMore = true

        // Update UI
        dispatch_async(dispatch_get_main_queue()) {
            tableView.reloadData()
            self.isLoadingMore = false
        }
    }
  }
0
ответ дан Alok SInha 18 August 2018 в 18:37
поделиться

Swift

Способ 1: Прокрутка вниз

Ниже приведена версия Swift версии Педро Романо . Когда пользователь останавливает прокрутку, он проверяет, достиг ли он дна.

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {

    // UITableView only moves in one direction, y axis
    let currentOffset = scrollView.contentOffset.y
    let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height

    // Change 10.0 to adjust the distance from bottom
    if maximumOffset - currentOffset <= 10.0 {
        self.loadMore()
    }
}

Способ 2: Достиг последней строки

И вот версия Swift shinyuX . Он проверяет, достиг ли пользователь последней строки.

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

    // set up cell
    // ...

    // Check if the last row number is the same as the last current data element
    if indexPath.row == self.dataArray.count - 1 {
        self.loadMore()
    }

}

Пример метода loadMore()

Я установил эти три переменные класса для извлечения партий данных.

// number of items to be fetched each time (i.e., database LIMIT)
let itemsPerBatch = 50

// Where to start fetching items (database OFFSET)
var offset = 0

// a flag for when all database items have already been loaded
var reachedEndOfItems = false

Это функция для загрузки большего количества элементов из базы данных в представление таблицы.

func loadMore() {

    // don't bother doing another db query if already have everything
    guard !self.reachedEndOfItems else {
        return
    }

    // query the db on a background thread
    DispatchQueue.global(qos: .background).async {

        // determine the range of data items to fetch
        var thisBatchOfItems: [MyObjects]?
        let start = self.offset
        let end = self.offset + self.itemsPerBatch

        // query the database
        do {
            // SQLite.swift wrapper
            thisBatchOfItems = try MyDataHelper.findRange(start..<end)
        } catch _ {
            print("query failed")
        }

        // update UITableView with new batch of items on main thread after query finishes
        DispatchQueue.main.async {

            if let newItems = thisBatchOfItems {

                // append the new items to the data source for the table view
                self.myObjectArray.appendContentsOf(newItems)

                // reload the table view
                self.tableView.reloadData()

                // check if this was the last of the data
                if newItems.count < self.itemsPerBatch {
                    self.reachedEndOfItems = true
                    print("reached end of data. Batch count: \(newItems.count)")
                }

                // reset the offset for the next data query
                self.offset += self.itemsPerBatch
            }

        }
    }
}
41
ответ дан Community 18 August 2018 в 18:37
поделиться
  • 1
    Я использовал метод 1, потому что мне хотелось потренироваться. Он отлично работает. Спасибо вам обоим! – Bob Wakefield 15 August 2016 в 18:10
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

NSInteger sectionsAmount = [tableView numberOfSections];
NSInteger rowsAmount = [tableView numberOfRowsInSection:[indexPath section]];
if ([indexPath section] == sectionsAmount - 1 && [indexPath row] == rowsAmount - 1) {
    //get last row
    if (!isSearchActive && !isFilterSearchActive) {
        if (totalRecords % 8 == 0) {
            int64_t delayInSeconds = 2.0;
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {


            [yourTableView beginUpdates];
            [yourTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
            [yourTableView endUpdates];
            });
        }
    }
}
}
0
ответ дан David 'mArm' Ansermot 18 August 2018 в 18:37
поделиться
  • 1
    после отображения последней строки, вставьте строки i.e beginUpdates .. и используйте некоторую задержку для получения сбоя. – Sahila Mirajkar 10 June 2016 в 08:18

Лучший способ решить эту проблему - добавить ячейку в нижней части таблицы, и эта ячейка будет содержать индикатор.

В swift вам нужно добавить это:

  1. Создать новую ячейку типа cellLoading, это будет содержать индикатор. Посмотрите на код ниже
  2. Посмотрите на количество строк и добавьте 1 к нему (это для загрузки ячейки).
  3. вам нужно проверить rawAtIndex, если idexPath.row = = yourArray.count, а затем вернуть ячейку загрузки.

смотрите код ниже:

import UIKit

class LoadingCell: UITableViewCell {

@IBOutlet weak var indicator: UIActivityIndicatorView!


}

Для просмотра таблицы: numOfRows:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return  yourArray.count + 1
}

cellForRawAt indexPath:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.row == users.count  {
        // need to change
        let loading = Bundle.main.loadNibNamed("LoadingCell", owner: LoadingCell.self , options: nil)?.first as! LoadingCell
        return loading

    }

    let yourCell = tableView.dequeueReusableCell(withIdentifier: "cellCustomizing", for: indexPath) as! UITableViewCell

    return yourCell

}

Если вы заметили, что моя загрузочная ячейка создана из файла nib. Это видео объяснит, что я сделал.

0
ответ дан Mohammed Ali Khaled 18 August 2018 в 18:37
поделиться

Я реализовал одно решение, которое я нашел в stackoverflow, и он отлично работает, но я думаю, что решение shinyuX очень легко реализовать и отлично работает для моего предложения. Если кто-то хочет другое решение, вы можете использовать это ниже.

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{

   // UITableView only moves in one direction, y axis
    CGFloat currentOffset = scrollView.contentOffset.y;
    CGFloat maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;

    //NSInteger result = maximumOffset - currentOffset;

    // Change 10.0 to adjust the distance from bottom
    if (maximumOffset - currentOffset <= 10.0) {
        [self loadOneMorePage];
        //[self methodThatAddsDataAndReloadsTableView];
    }
}
11
ответ дан rsc 18 August 2018 в 18:37
поделиться
  • 1
    Я думаю, что есть разные сценарии для представления презентации, в моем случае ваше решение работало, мне нужно было что-то вроде этого – Raheel Sadiq 10 November 2015 в 08:35
  • 2
    Если пользователь сильно ударяет, т. Е. На 1,5 экрана, нижняя часть может быть достигнута без повторного запуска. – dyson returns 10 August 2016 в 09:24
  • 3
    но он прокручивает список вверх – Mansuu.... 13 October 2017 в 11:15
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    NSInteger lastSectionIndex = [tableView numberOfSections] - 1;
    NSInteger lastRowIndex = [tableView numberOfRowsInSection:lastSectionIndex] - 1;
    if ((indexPath.section == lastSectionIndex) && (indexPath.row == lastRowIndex)) {
        // This is the last cell
        [self loadMore];
    }
}

Если вы используете Core Data и NSFetchedResultsController, тогда loadMore может выглядеть следующим образом:

// Load more
- (void)loadMore {
    [self.fetchedResultsController.fetchRequest setFetchLimit:newFetchLimit];
    [NSFetchedResultsController deleteCacheWithName:@"cache name"];
    NSError *error;
    if (![self.fetchedResultsController performFetch:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }

    [self.tableView reloadData];
}
16
ответ дан samwize 18 August 2018 в 18:37
поделиться
  • 1
    Я пытаюсь реализовать это, но я использую массив результатов, а не sqlite, задавался вопросом, как я собираюсь добавить больше в текущий NSMutableArray, который у меня есть, а затем перезагружать данные, потому что в противном случае данные будут перезаписаны ... Я попробовал this [names addObjectsFromArray: [responseObject valueForKeyPath: @ & quot; name & quot;]]; но он не работает ... вот ссылка на мой вопрос stackoverflow.com/questions/23446780/… – Lion789 3 May 2014 в 17:35
  • 2
    Какой смысл повторно собирать данные каждый раз, когда вы получаете новые данные? Если frc настроен правильно, достаточно одной выборки, он будет соответствующим образом обновляться по мере необходимости. Выбирая его каждый раз, предполагая, что запрос на выборки frc настроен на контекст основного потока, будет блокировать основной поток при попадании на диск, что совершенно не хорошо для пользователя, когда пользователь хочет новые данные. – MANIAK_dobrii 2 February 2015 в 10:58
  • 3
    Спасибо, что первая половина этого была очень полезной. (Не использовать FetchedResultsVC) – weienw 24 April 2015 в 17:47
  • 4
    @MANIAK_dobrii верен. Одной из ключевых особенностей NSFetchedResultsController является то, что он вычисляет данные поискового вызова, чтобы вы могли бесплатно получать виртуальную прокрутку при подключении к UITableView. Реализация такой функции loadMore должна быть необходима только в том случае, если вы фактически заполняете свой хранилище CoreData большим количеством данных, и в этом случае нет необходимости выполнять другую функцию executeFetch, если ваш NSFetchedResultsController настроен правильно. – Ali Gangji 28 May 2016 в 21:54
  • 5
    Те же вопросы, что и другие ответы. reloadData приводит к тому, что это происходит несколько раз. – dyson returns 10 August 2016 в 09:23

Используйте лимит и смещение в ваших запросах и заполните таблицу с этим контентом. Когда пользователь прокручивается вниз, загрузите следующее смещение.

Внесите метод tableView:willDisplayCell:forRowAtIndexPath: в ваш UITableViewDelegate и проверьте, является ли это последней строкой

37
ответ дан sooper 18 August 2018 в 18:37
поделиться
  • 1
    это не лучше, так как reloadData снова вызовет этот метод? – Marcin 5 May 2015 в 10:16

Подробности

xCode 8.3.1, Swift 3.1

Решение

import UIKit

class LoadMoreActivityIndicator {

    let spacingFromLastCell: CGFloat
    let spacingFromLastCellWhenLoadMoreActionStart: CGFloat
    let activityIndicatorView: UIActivityIndicatorView
    weak var tableView: UITableView!

    private var defaultY: CGFloat {
        return tableView.contentSize.height + spacingFromLastCell
    }

    init (tableView: UITableView, spacingFromLastCell: CGFloat, spacingFromLastCellWhenLoadMoreActionStart: CGFloat) {
        self.tableView = tableView
        self.spacingFromLastCell = spacingFromLastCell
        self.spacingFromLastCellWhenLoadMoreActionStart = spacingFromLastCellWhenLoadMoreActionStart
        let size:CGFloat = 40
        let frame = CGRect(x: (tableView.frame.width-size)/2, y: tableView.contentSize.height + spacingFromLastCell, width: size, height: size)
        activityIndicatorView = UIActivityIndicatorView(frame: frame)
        activityIndicatorView.color = .black
        activityIndicatorView.isHidden = false
        activityIndicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin]
        tableView.addSubview(activityIndicatorView)
        activityIndicatorView.isHidden = isHidden
    }

    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private var isHidden: Bool {
        if tableView.contentSize.height < tableView.frame.size.height {
            return true
        } else {
            return false
        }
    }

    func scrollViewDidScroll(scrollView: UIScrollView, loadMoreAction: ()->()) {
        let offsetY = scrollView.contentOffset.y
        activityIndicatorView.isHidden = isHidden
        if !isHidden && offsetY >= 0 {
            let contentDelta = scrollView.contentSize.height - scrollView.frame.size.height
            let offsetDelta = offsetY - contentDelta

            let newY = defaultY-offsetDelta
            if newY < tableView.frame.height {
                activityIndicatorView.frame.origin.y = newY
            } else {
                if activityIndicatorView.frame.origin.y != defaultY {
                    activityIndicatorView.frame.origin.y = defaultY
                }
            }

            if !activityIndicatorView.isAnimating {
                if offsetY > contentDelta && offsetDelta >= spacingFromLastCellWhenLoadMoreActionStart && !activityIndicatorView.isAnimating {
                    activityIndicatorView.startAnimating()
                    loadMoreAction()
                }
            }

            if scrollView.isDecelerating {
                if activityIndicatorView.isAnimating && scrollView.contentInset.bottom == 0 {
                    UIView.animate(withDuration: 0.3) { [weak self] in
                        if let bottom = self?.spacingFromLastCellWhenLoadMoreActionStart {
                            scrollView.contentInset = UIEdgeInsetsMake(0, 0, bottom, 0)
                        }
                    }
                }
            }
        }
    }

    func loadMoreActionFinshed(scrollView: UIScrollView) {

        let contentDelta = scrollView.contentSize.height - scrollView.frame.size.height
        let offsetDelta = scrollView.contentOffset.y - contentDelta
        if offsetDelta >= 0 {
            // Animate hiding when activity indicator displaying
            UIView.animate(withDuration: 0.3) {
                scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
            }
        } else {
            // Hiding without animation when activity indicator displaying
            scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
        }

        activityIndicatorView.stopAnimating()
        activityIndicatorView.isHidden = false
    }
}

Использование

extension ViewController: UITableViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        activityIndicator.scrollViewDidScroll(scrollView: scrollView) {
            DispatchQueue.global(qos: .utility).async {
                for i in 0..<3 {
                    print(i)
                    sleep(1)
                }
                DispatchQueue.main.async { [weak self] in
                    self?.activityIndicator.loadMoreActionFinshed(scrollView: scrollView)
                }
            }
        }
    }
}

Полный образец

ViewController.swift

import UIKit

class ViewController: UIViewController {

    var count = 30

    @IBOutlet weak var tableView: UITableView!
    fileprivate var activityIndicator: LoadMoreActivityIndicator!
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.dataSource = self
        tableView.delegate = self
        tableView.tableFooterView = UIView()
        activityIndicator = LoadMoreActivityIndicator(tableView: tableView, spacingFromLastCell: 10, spacingFromLastCellWhenLoadMoreActionStart: 60)
        print(tableView.frame)
    }
}

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = "\(indexPath)"
        return cell
    }
}

extension ViewController: UITableViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        activityIndicator.scrollViewDidScroll(scrollView: scrollView) {
            DispatchQueue.global(qos: .utility).async {
                for i in 0..<3 {
                    print("!!!!!!!!! \(i)")
                    sleep(1)
                }
                DispatchQueue.main.async { [weak self] in
                    self?.activityIndicator.loadMoreActionFinshed(scrollView: scrollView)
                }
            }
        }
    }
}

Main.storyboard

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_20269474" customModuleProvider="target" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="6la-L6-Fo3">
                                <rect key="frame" x="0.0" y="20" width="375" height="647"/>
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                            </tableView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="6la-L6-Fo3" firstAttribute="bottom" secondItem="wfy-db-euE" secondAttribute="top" id="GvO-lp-VW8"/>
                            <constraint firstAttribute="trailing" secondItem="6la-L6-Fo3" secondAttribute="trailing" id="aGF-Ie-T6Y"/>
                            <constraint firstItem="6la-L6-Fo3" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="obO-Sn-WYo"/>
                            <constraint firstItem="6la-L6-Fo3" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" id="zp5-B1-sWe"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="tableView" destination="6la-L6-Fo3" id="4lR-IX-vtT"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="48.799999999999997" y="37.331334332833585"/>
        </scene>
    </scenes>
</document>

Результат

8
ответ дан Vasily Bodnarchuk 18 August 2018 в 18:37
поделиться
  • 1
    Прекрасно работает. Но у меня есть заголовок в моем представлении таблицы, после перетаскивания, чтобы загрузить больше, заголовок будет находиться под навигационной панелью. UIEdgeInsetsMake в loadMoreActionFinshed должен быть установлен на (62, 0, 0, 0), учитывая 66 = navbar.height + 22 – Desmond 20 August 2017 в 06:59
  • 2
    могу я использовать это в виде коллекции .... – Hari Narayanan 23 March 2018 в 08:40
  • 3
    Он должен работать в CollectionView при прокрутке по вертикали. – Vasily Bodnarchuk 23 March 2018 в 08:42

Еще одна опция для использования (Swift 3 и iOS 10 +):

class DocumentEventsTableViewController: UITableViewController, UITableViewDataSourcePrefetching {

     var currentPage: Int = 1

     override func viewDidLoad() {
         super.viewDidLoad()

         self.tableView.prefetchDataSource = self
     }

     func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
         let upcomingRows = indexPaths.map { $0.row }

         if let maxIndex = upcomingRows.max() {

            let nextPage: Int = Int(ceil(Double(maxIndex) / Double(APICall.defaultPageSize))) + 1

            if nextPage > currentPage {
                 // Your function, which attempts to load respective page from the local database
                 loadLocalData(page: nextPage)

                 // Your function, which makes a network request to fetch the respective page of data from the network
                 startLoadingDataFromNetwork(page: nextPage) 

                 currentPage = nextPage
             }
         }
     }
 }

Для довольно маленьких страниц (~ 10 элементов) вы можете вручную добавить данные для страниц 1 и 2, потому что nextPage может быть где-то около 1-2, пока в таблице не будет прокручено несколько элементов. Но он будет отлично работать для всех следующих страниц.

3
ответ дан Vitalii 18 August 2018 в 18:37
поделиться
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    if (news.count == 0) {
        return 0;
    } else {
        return news.count +  1 ;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    @try {

        uint position = (uint) (indexPath.row);
        NSUInteger row = [indexPath row];
        NSUInteger count = [news count];

        //show Load More
        if (row == count) {
            UITableViewCell *cell = nil;

            static NSString *LoadMoreId = @"LoadMore";
            cell = [tableView dequeueReusableCellWithIdentifier:LoadMoreId];
            if (cell == nil) {
                cell = [[UITableViewCell alloc]
                        initWithStyle:UITableViewCellStyleDefault
                      reuseIdentifier:LoadMoreId];
            }
            if (!hasMoreLoad) {
                cell.hidden = true;
            } else {

                cell.textLabel.text = @"Load more items...";
                cell.textLabel.textColor = [UIColor blueColor];
                cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
                NSLog(@"Load more");
                if (!isMoreLoaded) {
                    isMoreLoaded = true;
                    [self performSelector:@selector(loadMoreNews) withObject:nil afterDelay:0.1];
                }
            }

            return cell;

        } else {
            NewsRow *cell = nil;

            NewsObject *newsObject = news[position];
            static NSString *CellIdentifier = @"NewsRow";
            cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

            if (cell == nil) {
                // Load the top-level objects from the custom cell XIB.
                NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
                // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
                cell = topLevelObjects[0];
                // Configure the cell...

            }

            cell.title.text = newsObject.title;             
            return cell;
        }

    }
    @catch (NSException *exception) {
        NSLog(@"Exception occurred: %@, %@", exception, [exception userInfo]);
    }
    return nil;
}

очень хорошее объяснение на этом посту.

http://useyourloaf.com/blog/2010/10/02/dynamically-loading-new-rows-into-a -table.html

просто вам нужно добавить последнюю строку и скрыть ее, а когда строка таблицы попадет в последнюю строку, чем показать строку и загрузить больше элементов.

2
ответ дан vlad sol 18 August 2018 в 18:37
поделиться

Ниже ссылки будет приведен пример кода. # Swift3

Пользователь должен поднять последнюю ячейку представления таблицы, по крайней мере, высоту 2 ячейки, чтобы получить больше данных с сервера.

Вы также обнаружите, что ячейка процесса также показывает процесс загрузки, как в последней ячейке.

Его в Swift3

https://github.com/ yogendrabagoriya / YBTableViewPullData

5
ответ дан Yogi 18 August 2018 в 18:37
поделиться
37
ответ дан sooper 7 September 2018 в 02:57
поделиться
0
ответ дан Bhavesh.iosDev 30 October 2018 в 07:07
поделиться
37
ответ дан sooper 30 October 2018 в 07:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: