UITableView yüklenmesinin sonu nasıl algılanır


141

Yük bittiğinde tablonun ofsetini değiştirmek istiyorum ve bu ofset tabloya yüklenen hücre sayısına bağlıdır.

Bir uitableview yüklemesinin ne zaman bittiğini bilmek yine de SDK'da mı? Ne delege ne de veri kaynağı protokollerinde hiçbir şey göremiyorum.

Yalnızca görünür hücrelerin yüklenmesi nedeniyle veri kaynaklarının sayısını kullanamıyorum.


veri kaynağı sayısı ve 'indexPathsForVisibleRows' birleşimini deneyin
Swapnil Luktuke

1
Bayrağın diğer bilgilerine dayanarak yeniden açıldı: "Yinelenen değil. Görünür hücrelerin yüklenmesi ile ilgili soruyor, veri soran bitirmekle ilgili değil. Kabul edilen cevap güncellemesine bakın"
Kev

Bu çözüm benim için iyi çalışıyor. Kontrol edin stackoverflow.com/questions/1483581/…
Khaled Annajar

Yanıtlar:


224

@RichX cevabı geliştirin: lastRowher ikisi de [tableView numberOfRowsInSection: 0] - 1veya olabilir ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row. Kod şöyle olacak:

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
        //end of loading
        //for example [activityIndicator stopAnimating];
    }
}

GÜNCELLEME: Peki, @ htafoya'nın yorumu doğru. Bu kodun tüm verileri kaynaktan yüklemenin sonunu algılamasını istiyorsanız, olmaz, ancak bu asıl soru değildir. Bu kod, görünür olması amaçlanan tüm hücrelerin ne zaman görüntülendiğini tespit etmek içindir. willDisplayCell:burada daha yumuşak kullanıcı arayüzü için kullanılır (tek hücre genellikle willDisplay:çağrıdan sonra hızlı görüntülenir ). Ayrıca deneyebilirsiniz tableView:didEndDisplayingCell:.


Görünür tüm hücrelerin ne zaman yüklendiğini bilmek için çok daha iyi.
Eric

14
Ancak, kullanıcı daha fazla hücre görüntülemek için her kaydırma yaptığında çağrılır.
htafoya

Buradaki sorun, altbilgi görünümünü hesaba katmamasıdır. Çoğu için bir sorun olmayabilir, ancak eğer aynı fikri ancak viewForFooterInSectionyöntemde uygulayabilirsiniz .
Kyle Clegg

1
@KyleClegg patric.schenke cevabınıza yorumda bulunan nedenlerden birini belirtti. Ayrıca, hücrenin yüklenmesinin sonunda altbilgi görünmezse ne olur?
folex

27
tableView: didEndDisplayingCell: aslında bir hücre görünümden kaldırılırken çağrılır, görünümdeki oluşturma işlemi tamamlandığında değil, böylece çalışmaz. İyi bir yöntem adı değil. Dokümanları okumalıyım.
Andrew Raphael

34

Swift 3 ve 4 ve 5 sürümü:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let lastVisibleIndexPath = tableView.indexPathsForVisibleRows?.last {
        if indexPath == lastVisibleIndexPath {
            // do here...
        }
    }
}

1
ilk kez veri yüklediğimizde bu yöntem çağrılır. Benim durumumda sadece 4 görünür hücre var. 8 satır yükledim ama yine de bu işlev çağrılıyordu. Ne kullanıcı son satır aşağı kaydırmak istediğinizde daha fazla veri yüklemek için
Muhammed Nayab

Merhaba Muhammed Nayab, belki de "if indexPath == lastVisibleIndexPath" ile "if indexPath.row == yourDataSource.count"
saatinde Daniele Ceglia 18:18

1
@DanieleCeglia Buna dikkat ettiğiniz için teşekkür ederiz. indexPath == lastVisibleIndexPath && indexPath.row == yourDataSource.count - 1 bu benim için işe yarar. Alkış !!!
Yogesh Patel

28

Her zaman bu çok basit çözümü kullanıyorum:

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == lastRow){
        //end of loading
        //for example [activityIndicator stopAnimating];
    }
}

son satırı nasıl tespit edebilirim? bu benim için sorun .. eğer bu geçen koşulu koşullara nasıl soktuğunuzu açıklayabilir misiniz?
Sameera Chathuranga

6
Son satır [tableView numberOfRowsInSection: 0] - 1. 0Gereken değerle değiştirmeniz gerekir . Ama sorun bu değil. Sorun, UITableView yüklerinin yalnızca görünür olmasıdır. Ancak ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).rowsorunu çözer.
folex

1
Eğer mutlak tamamlanma arayışımız varsa, en iyisi olmazdı - (void) tableView: (UITableView *) tableView
morcutt

10

İşte benim için işe yarayan başka bir seçenek. ViewForFooter delege yönteminde son bölüm olup olmadığını kontrol edin ve kodunuzu oraya ekleyin. Bu yaklaşım, willDisplayCell'in sahip olduğunuz altbilgileri hesaba katmadığını fark ettikten sonra akla geldi.

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section 
{
  // Perform some final layout updates
  if (section == ([tableView numberOfSections] - 1)) {
    [self tableViewWillFinishLoading:tableView];
  }

  // Return nil, or whatever view you were going to return for the footer
  return nil;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
  // Return 0, or the height for your footer view
  return 0.0;
}

- (void)tableViewWillFinishLoading:(UITableView *)tableView
{
  NSLog(@"finished loading");
}

Ben UITableViewsadece görünür hücreleri değil , tüm için son yükleme bulmak istiyorsanız bu yaklaşım en iyi buluyorum . İhtiyaçlarınıza bağlı olarak sadece görünür hücreleri isteyebilirsiniz, bu durumda folex'in cevabı iyi bir yoldur.


Geri dönen nildan tableView:viewForFooterInSection:Otomatik Düzen kullanarak iOS 7'de benim düzen ile haberci.
ma11hew28

İlginç. Yüksekliği ve genişliği 0 olan bir çerçeveye ayarlarsanız ne olur? return CGRectMake(0,0,0,0);
Kyle Clegg

Bunu denedim ve hatta ayarladım self.tableView.sectionFooterHeight = 0. Her iki durumda da, yaklaşık 10 yüksekliğe sahip bir bölüm altbilgisi görünümü eklemek gibi görünüyor. Bahse girerim döndüğüm görünüme 0 yükseklik kısıtlaması ekleyerek bunu düzeltebilirim. Her neyse, iyiyim çünkü aslında son hücrede UITableView'ı nasıl başlatacağımı bulmak istedim ama önce bunu gördüm.
ma11hew28

1
@MattDiPasquale viewForFooterInSection uygularsanız, heightForFooterInSection uygulamasını da uygulamanız gerekir. Sıfır altbilgisi olan bölümler için 0 döndürmelidir. Bu şimdiye kadar resmi belgelerde de var.
patric.schenke

heightForFooterInSection değerini 0 olarak ayarladıysanız viewForFooterInSection çağrılmaz
Oded Harth

10

Swift 2 çözümü:

// willDisplay function
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let lastRowIndex = tableView.numberOfRowsInSection(0)
    if indexPath.row == lastRowIndex - 1 {
        fetchNewDataFromServer()
    }
}

// data fetcher function
func fetchNewDataFromServer() {
    if(!loading && !allDataFetched) {
        // call beginUpdates before multiple rows insert operation
        tableView.beginUpdates()
        // for loop
        // insertRowsAtIndexPaths
        tableView.endUpdates()
    }
}

9

Özel API kullanma:

@objc func tableViewDidFinishReload(_ tableView: UITableView) {
    print(#function)
    cellsAreLoaded = true
}

Herkese açık API'yı kullanma:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // cancel the perform request if there is another section
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tableViewDidLoadRows:) object:tableView];

    // create a perform request to call the didLoadRows method on the next event loop.
    [self performSelector:@selector(tableViewDidLoadRows:) withObject:tableView afterDelay:0];

    return [self.myDataSource numberOfRowsInSection:section];
}

// called after the rows in the last section is loaded
-(void)tableViewDidLoadRows:(UITableView*)tableView{
    self.cellsAreLoaded = YES;
}

Olası daha iyi bir tasarım, görünür hücreleri bir kümeye eklemektir, daha sonra tablonun yüklü olup olmadığını kontrol etmeniz gerektiğinde, bunun yerine bu kümenin etrafında bir for döngüsü yapabilirsiniz, örn.

var visibleCells = Set<UITableViewCell>()

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    visibleCells.insert(cell)
}

override func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    visibleCells.remove(cell)
}

// example property you want to show on a cell that you only want to update the cell after the table is loaded. cellForRow also calls configure too for the initial state.
var count = 5 {
    didSet {
        for cell in visibleCells {
            configureCell(cell)
        }
    }
}

Diğerlerinden çok daha iyi bir çözüm. Bir tableView yeniden yüklemesi gerektirmez. Çok basit ve viewDidLoadRows: son hücre her yüklendiğinde çağrılmaz.
Matt Hudson

diğer çözümler birden fazla bölümü hesaba
katmadığından

Snarky yorum için üzgünüm, ama bu 'sihir' tam olarak nasıl? Temsilciden başka bir yönteme sesleniyor. Anlamıyorum.
Lukas Petr

@LukasPetr iptal ve afterDelay'a bir göz atın. Bunlar, yöntem çağrısının sonuncu hariç her bölüm için iptal edilmesini sağlar; bu, tablonun tamamen yüklenmesi bittiğinde gerçekleşir.
malhal

@malhal oh, tamam. İlk bakışta düşündüğümden biraz daha akıllı.
Lukas Petr

8

Swift 3'te seçilen cevap sürümü için:

var isLoadingTableView = true

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if tableData.count > 0 && isLoadingTableView {
        if let indexPathsForVisibleRows = tableView.indexPathsForVisibleRows, let lastIndexPath = indexPathsForVisibleRows.last, lastIndexPath.row == indexPath.row {
            isLoadingTableView = false
            //do something after table is done loading
        }
    }
}

Varsayılan hücre seçimi yapmadan önce tablonun yüklenmesini sağlamak istedim çünkü isLoadingTableView değişkeni gerekli. Bunu eklemezseniz, tabloyu her kaydırdığınızda kodunuzu tekrar çağırır.



3

Bir tablo görünümünün içeriğini yüklemeyi ne zaman tamamladığını bilmek için, öncelikle görünümlerin nasıl ekrana getirildiğiyle ilgili temel bir anlayışa sahip olmamız gerekir.

Bir uygulamanın yaşam döngüsünde 4 önemli an vardır:

  1. Uygulamaya bir etkinlik (dokunma, zamanlayıcı, gönderilen blok vb.)
  2. Uygulama etkinliği yönetir (bir kısıtlamayı değiştirir, bir animasyon başlatır, arka planı değiştirir vb.)
  3. Uygulama yeni görünüm hiyerarşisini hesaplar
  4. Uygulama görünüm hiyerarşisini oluşturuyor ve görüntülüyor

2 ve 3 kez tamamen ayrılmıştır. Neden ? Performans nedenlerinden ötürü, her değişiklik yapıldığında moment 3'ün tüm hesaplamalarını yapmak istemiyoruz.

Sanırım böyle bir dava ile karşı karşıyasınız:

tableView.reloadData()
tableView.visibleCells.count // wrong count oO

Burada yanlış olan ne?

Herhangi bir görünüm gibi, tablo görünümü de içeriğini tembel olarak yeniden yükler. Aslında, reloadDatabirden çok kez ararsanız performans sorunları oluşturmaz. Tablo görünümü, yalnızca temsilci uygulamasına göre içerik boyutunu yeniden hesaplar ve hücrelerini yüklemek için 3 anını bekler. Bu zamana düzen geçişi denir.

Peki, düzen pasosuna nasıl girilir?

Düzen geçişi sırasında uygulama, görünüm hiyerarşisinin tüm karelerini hesaplar. Katılmak için, a ve eşdeğer yöntemleri bir görünüm denetleyicisi alt sınıfındaki özel yöntemleri layoutSubviews, updateLayoutConstraintsvb. Geçersiz kılabilirsiniz UIView.

Tablo görünümü tam olarak bunu yapar. Bu geçersiz kılar layoutSubviewsve temsilci dayalı uygulama ekler veya kaldırır hücreleri. cellForRowYeni bir hücre eklemeden ve yerleştirmeden hemen önce, willDisplayhemen sonra çağırır . Aradığınız Eğer reloadDatayoksa sadece hiyerarşiye tablo görünümü eklendi, tablolar görüntülemek gerektiği kadar hücreler bu tuş anda çerçevesini dolduracak şekilde ekler.

Tamam, ama şimdi, bir tablo görünümünün içeriğini yeniden yüklemeyi tamamladığını nasıl öğrenebilirim?

Şimdi bu soruyu yeniden ifade edebiliriz: bir tablo görünümünün alt görünümlerini düzenlemenin ne zaman bittiğini nasıl öğrenebiliriz?

En kolay yol, tablo görünümünün düzenine girmektir:

class MyTableView: UITableView {
    func layoutSubviews() {
        super.layoutSubviews()
        // the displayed cells are loaded
    }
}

Bu yöntemin tablo görünümünün yaşam döngüsünde birçok kez çağrıldığına dikkat edin. Tablo görünümünün kaydırma ve dequeue davranışı nedeniyle, hücreler sık ​​sık değiştirilir, çıkarılır ve eklenir. Ancak super.layoutSubviews(), hücreler yüklendikten hemen sonra çalışır . Bu çözüm, willDisplayson dizin yolunun olayını beklemeye eşdeğerdir . Bu olay, layoutSubviewseklenen her hücre için tablo görünümünün yürütülmesi sırasında çağrılır .

Başka bir yol, uygulama bir düzen geçişi tamamlandığında çağrı almaktır.

Belgelerde açıklandığı gibi, aşağıdakilerden birini kullanabilirsiniz UIView.animate(withDuration:completion):

tableView.reloadData()
UIView.animate(withDuration: 0) {
    // layout done
}

Bu çözüm işe yarıyor ancak ekran, mizanpajın yapıldığı zaman ile bloğun çağrıldığı zaman arasında bir kez yenilenecek. Bu, DispatchMain.asyncçözüme eşdeğerdir ancak belirtilmiştir.

Alternatif olarak, tablo görünümünün düzenini zorlamayı tercih ederim

Herhangi bir görünümü alt görünüm çerçevelerini hemen hesaplamaya zorlamak için özel bir yöntem vardır layoutIfNeeded:

tableView.reloadData()
table.layoutIfNeeded()
// layout done

Ancak dikkatli olun, sistem tarafından kullanılan tembel yüklemeyi kaldıracaktır. Bu yöntemleri tekrar tekrar çağırmak performans sorunları yaratabilir. Tablo görünümünün çerçevesi hesaplanmadan önce çağrılmadığından emin olun, aksi takdirde tablo görünümü yeniden yüklenir ve size bildirim gönderilmez.


Bence mükemmel bir çözüm yok. Alt sınıflar dertlere yol açabilir. Bir düzen geçişi üstten başlar ve alta gider, böylece tüm düzen tamamlandığında bildirim almak kolay değildir. Ve layoutIfNeeded()performans sorunları vb oluşturabilir Ama o seçenekleri bilerek, kendi ihtiyacını uyacak bir alternatif de düşünmek gerekir.


1

Swift 3'te bunu nasıl yapacağınız aşağıda açıklanmıştır:

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

    if indexPath.row == 0 {
        // perform your logic here, for the first row in the table
    }

    // ....
}

1

Swift 3'te bunu nasıl yapacağım

let threshold: CGFloat = 76.0 // threshold from bottom of tableView

internal func scrollViewDidScroll(_ scrollView: UIScrollView) {

    let contentOffset = scrollView.contentOffset.y
    let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;

    if  (!isLoadingMore) &&  (maximumOffset - contentOffset <= threshold) {
        self.loadVideosList()
    }
}

1

İşte yapacağım şey.

  1. Temel sınıfınızda (rootVC BaseVc vb. Olabilir),

    A. "DidFinishReloading" geri çağrısını göndermek için bir Protokol yazın.

    @protocol ReloadComplition <NSObject>
    @required
    - (void)didEndReloading:(UITableView *)tableView;
    @end

    B. Tablo görünümünü yeniden yüklemek için genel bir yöntem yazın.

    -(void)reloadTableView:(UITableView *)tableView withOwner:(UIViewController *)aViewController;
  2. Temel sınıf yöntemi uygulamasında, reloadData ve ardından delegateMethod'u gecikmeli olarak çağırın.

    -(void)reloadTableView:(UITableView *)tableView withOwner:(UIViewController *)aViewController{
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [tableView reloadData];
            if(aViewController && [aViewController respondsToSelector:@selector(didEndReloading:)]){
                [aViewController performSelector:@selector(didEndReloading:) withObject:tableView afterDelay:0];
            }
        }];
    }
  3. Geri aramaya ihtiyacınız olan tüm görünüm denetleyicilerindeki yeniden yükleme tamamlama protokolünü onaylayın.

    -(void)didEndReloading:(UITableView *)tableView{
        //do your stuff.
    }

Referans: https://discussions.apple.com/thread/2598339?start=0&tstart=0


0

@folex yanıtı doğrudur.

Ancak , tableView bir kerede birden fazla bölüm görüntülendiğinde başarısız olur .

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
   if([indexPath isEqual:((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject])]){
    //end of loading

 }
}

0

Swift'te böyle bir şey yapabilirsiniz. Tablonun sonuna her ulaştığınızda aşağıdaki koşul geçerli olacaktır

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row+1 == postArray.count {
            println("came to last row")
        }
}


0

Birden fazla bölümünüz varsa, son bölümdeki son satırı nasıl alacağınız aşağıda açıklanmıştır (Swift 3):

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let visibleRows = tableView.indexPathsForVisibleRows, let lastRow = visibleRows.last?.row, let lastSection = visibleRows.map({$0.section}).last {
        if indexPath.row == lastRow && indexPath.section == lastSection {
            // Finished loading visible rows

        }
    }
}

0

Yanlışlıkla bu çözüme çarptım:

tableView.tableFooterView = UIView()
tableViewHeight.constant = tableView.contentSize.height

ContentSize'ı almadan önce footerView öğesini ayarlamanız gerekir; örneğin, viewDidLoad içinde. Btw. footeView ayarı "kullanılmayan" ayırıcıları silmenizi sağlar


-1

Tabloda görüntülenecek toplam öğe sayısını mı yoksa şu anda görünür durumda olan toplam öğe sayısını mı arıyorsunuz? Her iki durumda da .. 'viewDidLoad' yöntemi tüm veri kaynağı yöntemleri çağrıldıktan sonra yürütmek inanıyoruz. Ancak, bu yalnızca verilerin ilk yüklemesinde çalışır (tek bir ayrı ayrı ViewController kullanıyorsanız).


-1

Andrew'un kodunu kopyalıyorum ve tabloda sadece 1 satırın olduğu durumu hesaba katarak genişletiyorum. Benim için şimdiye kadar çalışıyor!

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// detect when all visible cells have been loaded and displayed
// NOTE: iOS7 workaround used - see: http://stackoverflow.com/questions/4163579/how-to-detect-the-end-of-loading-of-uitableview?lq=1
NSArray *visibleRows = [tableView indexPathsForVisibleRows];
NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
BOOL isPreviousCallForPreviousCell = self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
BOOL isFinishedLoadingTableView = isLastCell && ([tableView numberOfRowsInSection:0] == 1 || isPreviousCallForPreviousCell);

self.previousDisplayedIndexPath = indexPath;

if (isFinishedLoadingTableView) {
    [self hideSpinner];
}
}

NOT: Andrew kodundan sadece 1 bölüm kullanıyorum, bu yüzden aklınızda bulundurun ..


SO @ jpage4500'e hoş geldiniz. Düşük yanıt noktaları ve soru yumruları ile ilgili bilgileri kaldırmak için cevabınızı düzenledim. Başka bir kullanıcının cevabını genişletmek tek başına mükemmel bir cevaptır, böylece bu şeyleri dışarıda bırakarak dağınıklığı azaltabilirsiniz. Andrew kredisi olsa iyi, bu yüzden kaldı.
skrrgwasme

-3

İOS7.0x sürümünde çözüm biraz farklı. İşte ortaya çıkardığım şey.

    - (void)tableView:(UITableView *)tableView 
      willDisplayCell:(UITableViewCell *)cell 
    forRowAtIndexPath:(NSIndexPath *)indexPath
{
    BOOL isFinishedLoadingTableView = [self isFinishedLoadingTableView:tableView  
                                                             indexPath:indexPath];
    if (isFinishedLoadingTableView) {
        NSLog(@"end loading");
    }
}

- (BOOL)isFinishedLoadingTableView:(UITableView *)tableView 
                         indexPath:(NSIndexPath *)indexPath
{
    // The reason we cannot just look for the last row is because 
    // in iOS7.0x the last row is updated before
    // looping through all the visible rows in ascending order 
    // including the last row again. Strange but true.
    NSArray * visibleRows = [tableView indexPathsForVisibleRows];   // did verify sorted ascending via logging
    NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
    // For tableviews with multiple sections this will be more complicated.
    BOOL isPreviousCallForPreviousCell = 
             self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
    BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
    BOOL isFinishedLoadingTableView = isLastCell && isPreviousCallForPreviousCell;
    self.previousDisplayedIndexPath = indexPath;
    return isFinishedLoadingTableView;
}

-3

Hedef C

[self.tableView reloadData];
[self.tableView performBatchUpdates:^{}
                              completion:^(BOOL finished) {
                                  /// table-view finished reload
                              }];

hızlı

self.tableView?.reloadData()
self.tableView?.performBatchUpdates({ () -> Void in

                            }, completion: { (Bool finished) -> Void in
                                /// table-view finished reload
                            })

1
Bu yöntem yalnızca UICollectionViewanladığım kadarıyla kullanılabilir .
Awesome-o

Evet haklısın. UITableView's beginUpdates, UICollectionView'ın performBatchUpdates: completion değerine eşittir. stackoverflow.com/a/25128583/988169
pkc456

Bu yüzden soruya doğru ve geçerli bir cevap verin.
G.Abhisek
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.