2012-03-27 17 views
25

Ho un UITableView nella mia app per iOS che viene aggiornato periodicamente. L'utente è anche in grado di spostare le file tableview in qualsiasi momento (il tableview è sempre in modalità di modifica).Come ricevere notifica di spostamento UITableViewCell inizio e fine

Voglio interrompere il timer di aggiornamento quando l'utente inizia a trascinare una riga e ricominciare da capo quando la riga viene rilasciata.

L'ultima parte dovrebbe essere semplice con moveRowAtIndexPath, ma come ottenere la notifica dell'avvio di trascinamento?

Grazie!

risposta

34

tuo UITableViewDelegate riceverà i seguenti notifiche in risposta alle azioni di riordino:

- (void)tableView:(UITableView *)tableView willBeginReorderingRowAtIndexPath:(NSIndexPath *)indexPath; 
- (void)tableView:(UITableView *)tableView didEndReorderingRowAtIndexPath:(NSIndexPath *)indexPath; 
- (void)tableView:(UITableView *)tableView didCancelReorderingRowAtIndexPath:(NSIndexPath *)indexPath; 
+0

Non vedo questi metodi delegati dichiarati nell'interfaccia UITableView.h. Puoi spiegare dove possiamo trovarli? – imnk

+2

@mprudhom Ho ricevuto i callback ma non sono documentati. Avete questi metodi delegati in un'app di produzione? Questa è considerata API privata? – Torsten

+0

Questi metodi sono effettivamente chiamati su delegato di UITableView. Poiché non sono documentati, Apple potrebbe semplicemente romperli nelle versioni future di iOS, ma da iOS 5 e fino a iOS 7, funziona ancora. Devo ancora scoprire se Apple consentirà effettivamente a un'App con questi metodi implementati di essere pubblicati su App Store (buona fortuna a me, immagino), ma non credo ci sia un buon motivo per non farlo: se implemento questi 3 metodi nel mio UIViewController, e non sono documentati e non iniziano con underscore o quant'altro, come sono diversi dai miei metodi? – Argentumko

9

Ho incontrato lo stesso problema qualche tempo fa e non ho trovato una soluzione. Mentre ho iniziato questa risposta con una spiegazione del perché non può essere fatto, in realtà ho scoperto come si può fare! :-)

In breve: è necessario creare una sottoclasse personalizzata di UITableViewCell. Sostituire layoutSubviews per allegare un UILongPressGestureRecognizer a UITableViewCellReorderControl. Definire un protocollo e utilizzare un delegato per informare chiunque desideri dello stato di trascinamento.

CustomTableViewCell.h:

#import <UIKit/UIKit.h> 

@protocol CustomTableViewCellDelegate; 

@interface CustomTableViewCell : UITableViewCell { 
} 

@property (nonatomic, assign) id <CustomTableViewCellDelegate> delegate; 

@end 

@protocol CustomTableViewCellDelegate 
- (void)CustomTableViewCell:(CustomTableViewCell *)cell isDragging:(BOOL)value; 
@end 

CustomTableViewCell.m:

#import "CustomTableViewCell.h" 

@implementation CustomTableViewCell 

@synthesize delegate = _delegate; 

- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer { 
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { 
     [_delegate CustomTableViewCell:self isDragging:YES]; // Dragging started 
    } else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { 
     [_delegate CustomTableViewCell:self isDragging:NO];  // Dragging ended 
    } 
} 

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    for (UIView *view in self.subviews) { 
     if ([NSStringFromClass ([view class]) rangeOfString:@"ReorderControl"].location != NSNotFound) { // UITableViewCellReorderControl 
      if (view.gestureRecognizers.count == 0) { 
       UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)]; 
       gesture.cancelsTouchesInView = NO; 
       gesture.minimumPressDuration = 0.150; 
       [view addGestureRecognizer:gesture]; 
      } 
     } 
    } 
} 

@end 

essere consapevoli del fatto che, mentre questo codice non utilizza alcun API private ancora potrebbe smettere di funzionare se Apple cambia la sua implementazione interna (cioè cambiando il nome della classe di UITableViewCellReorderControl).

+0

Grazie Peter, avrò bisogno di ripensare Per la mia attuale implementazione vale il rischio di fare affidamento sul nome della classe o se è meglio cambiare il paradigma "tableview is always edit" in modo che possa smettere di aggiornarlo una volta che l'utente tocca la modifica. Sembra più affidabile, ma non sono sicuro di come integrarlo nell'interfaccia utente;) – Cornelius

+0

Questa è stata la risposta accettata, modificata nella risposta di @mprudhom da quando Apple ha aggiunto e documentato nuovi metodi delegati. – Cornelius

+1

@Cornelius In che modo Apple ha aggiunto e documentato i nuovi metodi dei delegati? Sono su iOS 8 e sono ancora API private. –

0

questo metodo viene chiamato quando hai finito le cellule in movimento:

- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath 
1

solo ho trovato un hack, dal momento che Apple ridurrà l'alfa, possiamo usare quello che immagino

@interface CustomTableViewCell() 
@property (nonatomic, assign) BOOL isDragging; 
@end 

-(void)draggingWillBegan 
{ 
    //use a delegate method to inform tableview 
} 

-(void)draggingDidEnd 
{ 
    //use a delegate method to inform tableview 
} 

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    //Since apple wont provide en 
    if(self.alpha <= 0.95 && !self.isDragging){ 
     self.isDragging = YES; 
     [self draggingWillBegan]; 
    } 

    if(self.alpha >= 0.95 && self.isDragging){ 
     self.isDragging = NO; 
     [self draggingDidEnd]; 
    } 
} 
Problemi correlati