2012-07-07 14 views
5

Eski model silme yerine eski model durum değişiklikleriyle eşleştirmek için iOS 5'in şık hareket hareket çağrılarını kullanmak üzere bir tablo görünümünü canlandırmak istiyorum. yerleştirin.UITableView: using moveRowAtIndexPath: toIndexPath: ve reloadRowsAtIndexPaths: withRowAnimation: birlikte bozuk görüntülendi

Değişiklikler hem yeniden sıralama hem de yerinde güncelleştirmeler içerebilir ve her ikisini de canlandırmak istiyorum, bu nedenle bazı satırların reloadRowsAtIndexPaths olması gerekir.

Ama! UITableView, güncellenmiş hücre hamle nedeniyle konumu kaydırırsa, hamle varlığında satır yeniden yüklemelerinin işlenmesinde sadece düz yanlış görünüyor. Eski silme + ekleme çağrılarını, eşdeğer olması gereken şekilde kullanmak iyi çalışır.

İşte bazı kodlar; Ayrıntı için özür dilerim ama derleme ve yürütme. Et doMoves: yöntemindedir. Aşağıdaki sergi.

#define THISWORKS 

@implementation ScrambledList // extends UITableViewController 
{ 
    NSMutableArray *model; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    model = [NSMutableArray arrayWithObjects: 
      @"zero", 
      @"one", 
      @"two", 
      @"three", 
      @"four", 
      nil]; 
    [self.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle: 
#ifdef THISWORKS 
               @"\U0001F603" 
#else 
               @"\U0001F4A9" 
#endif 
                       style:UIBarButtonItemStylePlain 
                      target:self 
                      action:@selector(doMoves:)]]; 
} 

-(IBAction)doMoves:(id)sender 
{ 
    int fromrow = 4, torow = 0, changedrow = 2; // 2 = its "before" position, just like the docs say. 

    // some model changes happen... 
    [model replaceObjectAtIndex:changedrow 
        withObject:[[model objectAtIndex:changedrow] stringByAppendingString:@"\u2032"]]; 
    id tmp = [model objectAtIndex:fromrow]; 
    [model removeObjectAtIndex:fromrow]; 
    [model insertObject:tmp atIndex:torow]; 

    // then we tell the table view what they were 
    [self.tableView beginUpdates]; 
    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:changedrow inSection:0]] 
         withRowAnimation:UITableViewRowAnimationRight]; // again, index for the "before" state; the tableview should figure out it really wants row 3 when the time comes 
#ifdef THISWORKS 
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:fromrow inSection:0]] 
         withRowAnimation:UITableViewRowAnimationAutomatic]; 
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:torow inSection:0]] 
         withRowAnimation:UITableViewRowAnimationAutomatic]; 
#else // but this doesn't 
    [self.tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:fromrow inSection:0] 
         toIndexPath:[NSIndexPath indexPathForRow:torow inSection:0]]; 
#endif 
    [self.tableView endUpdates]; 
} 

#pragma mark - Table view data source boilerplate, not very interesting 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return model.count; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@""]; 
    if (cell == nil) 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@""]; 
    [cell.textLabel setText:[[model objectAtIndex:indexPath.row] description]]; 
    [cell.detailTextLabel setText:[NSString stringWithFormat:@"this cell was provided for row %d", indexPath.row]]; 
    return cell; 
} 

Kod ne yapar: küçük bir model oluşturur (küçük değişken dizi); Bir düğmeye basıldığında, listenin orta elemanında küçük bir değişiklik yapar ve son öğeyi ilk haline getirir. Daha sonra bu değişiklikleri yansıtacak şekilde tablo görünümünü günceller: orta sırayı yeniden yükler, son satırı kaldırır ve yeni bir sırayı sıfırlar.

Bu çalışır. Aslında, cellForRowAtIndexPath'a günlüğe kaydetme eklendiğinde, satır 2'nin yeniden yüklenmesini istediğime rağmen, tablo görünümü, güncelleştirmeyi gerçekte yapmanın zamanı geldiğinde eklentiden dolayı 3. satır için doğru bir şekilde soruyor. Huzzah!

Şimdi bunun yerine moveRowAtIndexPath çağrısını kullanmak için en #ifdef yorumunu yapın.

Şimdi tableview taze satırda sorar (yanlış!), satır 2 kaldırır ve nihai satır-2 konumuna yapıştırır (aynı zamanda yanlış!). Net sonuç, 1. satırın bir yerine iki yuvaya taşınması ve bir yeniden yüklemeyi zorlamak için ekranın üzerine kaydırılması, modelle eşitlenmediğini gösterir. moveRowAtIndexPath, tablo görünümünün özel modelini farklı bir sırada değiştirip değiştirmediğini anlayabiliyordu, yeniden yükleme veya model getirme işlemlerinde "eski" dizin yolları yerine "yeni" kullanımını gerektiriyordu, ancak bu devam ediyor. İkinci "sonrası" resminde, üçüncü ve dördüncü sıraların ters sırada olduğunu unutmayın; hangi hücreyi yeniden yüklediğime bakılmaksızın gerçekleşmemelidir.

after one button push, delete-insert style

before state

after one button push, move-style

Benim kelime renkli küfür Apple büyüdü. Kendimi küfür etmeli miyim? Satır aynı güncelleştirmeler bloğunda satır yeniden yüklemeleriyle uyumsuz (sadece şüphelendiğim, eklediğim ve sildiğim gibi) ile uyumlu mu? Hata raporunu göndermeden önce beni aydınlatabilecek biri var mı?

+0

Çok ilginç! –

+0

Buna bir çözüm buldunuz mu? Aynı konuyla karşılaşıyorum. –

+0

Hayır! "Yeterli bilgi" ile kapatılan bir hata raporu ve bunu ios6 altında test ettiğim bir istekte bulundum (ki bu da etrafımdan geçemedim, ancak sorun yaşıyorsanız muhtemelen düzeltilmemiş ve UICollectionView benzer bir problem.) Çalışmayı beklediğim iki geçici çözüm: iki ayrı başlangıç ​​/ bitişUpUpdates bloğu, biri yeniden yükleme için biri daha sonra hareketler/ekler/silmeler için; veya yeniden yükleyinRowsAtIndexPaths tamamen ve uygun hücreleri el ile bulun. – rgeorge

cevap

3

Kodunuzla biraz zaman geçirdim ve kabul ediyorum; Sadece işe yaramıyor gibi görünüyor.

Bu alan biraz eksik belgelenmiştir, ancak aslında yeniden yükleme yöntemleri ile moveRowAtIndexPath:toIndexPath:'u karıştırabildiğini söylemezler. , satır ekleme ve satır silme yöntemleri ile karıştırılabileceğini söyler. Bunun yerine kodlarını değiştirmek için değiştirirseniz, bu çalışır gibi görünüyor. Yani, bir hata talep etmemek için bir geliştirme talep ediyor olabilirsiniz. Her iki durumda da, onu kesinlikle radar yolladım.

+0

Onay için teşekkürler. Radar başvurdu. Apple bunu çözerse, çözünürlüğü ekleyeceğim. – rgeorge