2012-05-29 24 views
15

के बटन के लिए बटन स्पर्श ईवेंट को संभालने का सर्वोत्तम अभ्यास कस्टम UITableViewCell के बटन के लिए बटन स्पर्श ईवेंट को संभालने का सबसे अच्छा अभ्यास क्या है?उद्देश्य सी - कस्टम UITableViewCell

मेरी कक्षाएं: MyViewController, MyCustomCell

मैं तीन विकल्प के बारे में सोच सकते हैं:

पहले विकल्पMyCustomCell की एक संपत्ति के रूप में बटन है, और फिर MyViewController में इसे करने के लिए एक लक्ष्य जोड़ने लक्ष्य के रूप में MyViewController के साथ .m फ़ाइल।

MyViewController मीटर फ़ाइल

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"customCell"; 

    MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
    cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

    [cell.theButton addTarget:self 
         action:@selector(theButtonTapped:) 
      forControlEvents:UIControlEventTouchUpInside]; 
    } 

    // Configure the cell...  
    [self configureCell:cell atIndexPath:indexPath]; 

    return cell; 
} 

- (void)theButtonTapped:(UIButton *)sender 
{ 
    MyCustomCell *selectedCell = (MyCustomCell *)sender.superview; 

    if (selectedCell) { 
     NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell]; 
     MyModel *selectedModel = [self.model objectAtIndex:indexPath.row]; 

     // do something with the model... 
    } 
} 

दूसरा विकल्प कस्टम सेल आईबी में बनाया गया था, तो, सेट निब फ़ाइल के मालिक MyViewController होने की MyViewController में buttonTapped: विधि को लागू करने और कनेक्ट बटन के टच अप के अंदर घटना buttonTapped: विधि के लिए।

तीसरा विकल्प यदि कस्टम सेल आईबी में नहीं बनाया गया था, एक लक्ष्य बटन को MyCustomCell मीटर फ़ाइल में MyCustomCell लक्ष्य के रूप में के साथ जोड़ें।
MyCustomCellDelegate@property (nonatomic, assign) id<MyCustomCellDelegate> delegateMyCustomCell को परिभाषित करें और बटन को टैप करते समय इस प्रतिनिधि को कॉल करें।
कक्ष बनाने के दौरान सेल के प्रतिनिधि के रूप में MyViewController सेट करें और MyCustomCellDelegate प्रोटोकॉल को लागू करें।

MyCustomCell ज फ़ाइल

@class MyCustomCell; 

@protocol MyCustomCellDelegate <NSObject> 
- (void)buttonTappedOnCell:(MyCustomCell *)cell; 
@end 

@interface MyCustomCell : UITableViewCell 

@property (nonatomic, retain) UIButton *theButton; 
@property (nonatomic, assign) id<MyCustomCellDelegate> delegate; 

@end 

MyCustomCell मीटर फ़ाइल

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
{ 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) { 
     // Initialization code 
     self.theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
     self.theButton.frame = CGRectMake(10,10,50,30); 
     [self addSubview:self.theButton]; 

     [self.theButton addTarget:self 
          action:@selector(theButtonTapped:) 
       forControlEvents:UIControlEventTouchUpInside]; 
    } 
    return self; 
} 

- (void)theButtonTapped:(UIButton *)sender 
{ 
    [self.delegate buttonTappedOnCell:self]; 
} 

MyViewController मीटर फ़ाइल

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"customCell"; 

    MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     cell.delegate = self; 
    } 

    // Configure the cell...  
    [self configureCell:cell atIndexPath:indexPath]; 

    return cell; 
} 

- (void)buttonTappedOnCell:(MyCustomCell *)selectedCell 
{ 
    if (selectedCell) { 
     NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell]; 
     MyModel *selectedModel = [self.model objectAtIndex:indexPath.row]; 

     // do something with the model... 
    } 
} 
+1

मैं विकल्प 1. साथ जाना होगा यह मेरे लिए सबसे पठनीय लगता है। मैं एक समान दृष्टिकोण का उपयोग करता हूं, लेकिन मैंने कस्टम सेल में प्रतिनिधि सेट किया है और कस्टम सेल में बटन को संभाला है और फिर प्रतिनिधि नियंत्रक में एक फ़ंक्शन को कॉल करके यह जांच कर कॉल करें कि क्या प्रतिनिधि है। –

उत्तर

11

स्टोर सेल की पंक्ति के रूप में tag अपने कस्टम बटन की संपत्ति ।

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // bla bla bla 
    if (!cell) 
    { 
     //bla bla bla 
     [cell.yourButton addTarget:self selector:@selector(yourButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; 
    } 
    // bla bla bla 
    cell.yourButton.tag = indexPath.row; 
} 

-(void)yourButtonTapped:(id)sender 
{ 
    int tag = [(UIButton *)sender tag]; 
    NSLog(@"tapped button in cell at row %i", tag); 
} 
+0

क्या ऐसा करने का कोई फायदा है और मैंने जो नहीं किया है? MyCustomCell * चयनितसेल = (MyCustomCell *) प्रेषक। सुपरव्यू; – Eyal

+0

पिछली बार मैंने चेक किया था, कस्टम सेल में एक बटन में सेल के सामग्री दृश्य पर्यवेक्षण के रूप में होगा। – Kreiri

+0

बटन को सामग्री दृश्य में जोड़ा जाना चाहिए, जिसका पर्यवेक्षण कक्ष है। – hwaxxer

1

टैग के उपयोग से, मेरे दृष्टिकोण से, आपके कोड की सख्तता तोड़ देगा। इसके अतिरिक्त, जब आपके पास एकाधिक अनुभाग होते हैं, तो टैग का उपयोग करके निश्चित रूप से आपके कोड का गड़बड़ हो जाएगा।

इस समस्या से बचने के लिए, आप UITableViewCell उपखंड कर सकते हैं और इसे indexPath संपत्ति बना सकते हैं ताकि सेल को इसकी सटीक स्थिति पता चल सके।

यहाँ एक अन्य समस्या है अगर UITableView को insert या delete पंक्ति एपीआई का आह्वान, आप दिखाई कोशिकाओं की स्थिति डेटा

अद्यतन करने के लिए मुझे नहीं लगता कि सबसे अच्छा अभ्यास है करते।

एक बेहतर तरीका मौजूद है।


मैं दृढ़ता से MVVM उपयोग करने के लिए आप अपने सेल में अलग स्पर्श घटनाओं को संभालने के लिए है जब सलाह देते हैं।

इस पैटर्न में, आपके कस्टम UITableViewCell पर एक कस्टम CellViewModel होगा। यह वर्ग आपके द्वारा सेल के साथ संबद्ध सभी डेटा रखने के लिए ज़िम्मेदार होगा, ताकि आप डेटा पुनर्प्राप्त कर सकें और सेल के अंदर ईवेंट हैंडलिंग तर्क डाल सकें।

0

मैं UIButton उपवर्गीकरण द्वारा ब्लॉक आधारित दृष्टिकोण को लागू किया है:

typedef void (^ActionBlock)(id sender); 

@interface UIBlockButton : UIButton { 
    ActionBlock _actionBlock; 
} 

-(void)handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock) action; 
​@end 

@implementation UIBlockButton 

-(void) handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock) action 
    { 
     _actionBlock = action; 
     [self addTarget:self action:@selector(callActionBlock:) forControlEvents:event]; 
     } 

    -(void) callActionBlock:(id)sender{ 
    _actionBlock(sender); 
    } 

@end 

और tableview प्रतिनिधि में:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (!cell) 
    { 
    cell.yourButton.tag = indexPath.row;// pass tag 
    [cell.yourButton handleControlEvent:UIControlEventTouchUpInside withBlock:^(id sender) { 
    // your selector action code 
    NSLog(@"tapped button in cell at row %i",[(UIButton *)sender tag]); 
    }]; 
    } 
} 
0

कुछ बिंदु पर अपने बटन उपयोग किया जाता है, और उस बिंदु पर इसके बारे में एक subview है एक सेल जो कुछ टेबलव्यू का सबव्यूव्यू है।

बस एक विधि लिखें जो दृश्य लेता है, युक्त सेल ढूंढने के लिए पर्यवेक्षण श्रृंखला चला जाता है, तालिकादृश्य खोजने के लिए आगे जाता है, और फिर सेल के इंडेक्सपाथ के लिए टेबलव्यू पूछता है।

यह एक पंक्ति युक्त टैग संग्रहीत करने से बहुत आसान और अधिक विश्वसनीय है, क्योंकि जब आप टेबलव्यू संपादित करते हैं तो समस्याएं नहीं चलती हैं, और यह पता लगाना बेहतर होता है कि कौन सा इंडेक्सपैथ है जब आपको आवश्यकता है इंडेक्सपैथ, और जब सेल बनाया जाता है तो कुछ पूरी तरह से असंबंधित कोड में नहीं।

0

स्विफ्ट 3.0 समाधान

cell.btnRequest.tag = indexPath.row 

cell.btnRequest.addTarget(self,action:#selector(buttonClicked(sender:)), for: .touchUpInside) 

func buttonClicked(sender:UIButton) { 

    let buttonRow = sender.tag 
} 
संबंधित मुद्दे