2012-03-27 4 views
25

Ich habe eine UITableView in meiner iOS App, die regelmäßig aktualisiert wird. Der Benutzer kann die Tabellenansichtszeilen jederzeit verschieben (die Tabellenansicht befindet sich immer im Bearbeitungsmodus).Wie man von UITableViewCell benachrichtigt wird, verschiebe Start und Ende

Ich möchte den Aktualisierungstimer stoppen, wenn der Benutzer beginnt, eine Zeile zu ziehen und sie erneut zu starten, wenn die Zeile gelöscht wird.

Der letzte Teil sollte einfach mit moveRowAtIndexPath sein, aber wie man über Drag Start benachrichtigt werden?

Danke!

Antwort

34

Ihre UITableViewDelegate wird die folgenden Meldungen in Reaktion auf Neuordnungs Aktionen erhalten:

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

Ich sehe diese Delegate-Methoden nicht in der UITableView.h-Schnittstelle deklariert. Können Sie bitte erklären, wo wir sie finden können? – imnk

+2

@mprudhom Ich habe die Rückrufe erhalten, aber sie sind nicht dokumentiert. Verfügen Sie über diese Delegatmethoden in einer Produktionsanwendung? Wird dies als private API betrachtet? – Torsten

+0

Diese Methoden werden tatsächlich am Delegierten des UITableView aufgerufen. Da sie undokumentiert sind, könnte Apple sie in zukünftigen Versionen von iOS einfach brechen, aber von iOS 5 bis zu iOS 7 funktioniert das immer noch. Ich muss noch herausfinden, ob Apple tatsächlich eine App mit diesen implementierten Methoden erlauben würde, im App Store veröffentlicht zu werden (viel Glück für mich, denke ich), aber ich glaube nicht, dass es einen guten Grund gibt, nicht zu implementieren Diese 3 Methoden in meinem UIViewController, und sie sind nicht dokumentiert und sie beginnen nicht mit Unterstrichen oder was auch immer, wie unterscheiden sie sich von meinen eigenen Methoden? – Argentumko

9

Ich stieß vor einiger Zeit auf das gleiche Problem und fand keine Lösung. Während ich diese Antwort mit einer Erklärung begann, warum es nicht möglich ist, habe ich tatsächlich herausgefunden, wie es geht! :-)

Kurz gesagt: Sie müssen eine benutzerdefinierte Unterklasse von UITableViewCell erstellen. Überschreibe layoutSubviews, um eine UILongPressGestureRecognizer an UITableViewCellReorderControl anzuhängen. Definieren Sie ein Protokoll und verwenden Sie einen Delegaten, um den Benutzer über den Ziehstatus zu informieren.

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 

Beachten Sie, dass während dieser Code keine privaten APIs verwenden, ist es immer noch funktioniert möglicherweise nicht mehr, wenn Apple seine interne Implementierung ändert (zB durch Ändern des Klassennamens von UITableViewCellReorderControl).

+0

Dank Peter, muss ich neu zu denken f meine aktuelle Implementierung ist das Risiko wert, sich auf den Klassennamen zu verlassen, oder wenn ich das Paradigma "Tabellenansicht wird immer editieren" besser ändern sollte, damit ich die Aktualisierung stoppen kann, sobald der Benutzer auf die Bearbeitung klickt. Scheint zuverlässiger, nur nicht sicher, wie das in meine UI zu integrieren;) – Cornelius

+0

Dies war die akzeptierte Antwort, änderte es auf die Antwort von @mprudhom seit Apple hinzugefügt und dokumentiert neue Delegiertenmethoden. – Cornelius

+1

@Cornelius Wo hat Apple die neuen Delegate-Methoden hinzugefügt und dokumentiert? Ich bin auf iOS 8 und sie sind immer noch private API. –

0

diese Methode aufgerufen wird, wenn Sie in Bewegung Zellen fertig sind:

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

Nur fand ich einen Hack, da Apfel wird das Alpha reduzieren, können wir verwenden, dass ich denke,

@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]; 
    } 
} 
Verwandte Themen