Пользовательские UITableViewCells - PullRequest
4 голосов
/ 16 мая 2011

Я на самом деле очень удивлен тем, как трудно сохранить ваш код хорошо структурированным и читаемым при выполнении приложений для iphone ... но это может быть потому, что я делаю что-то не так.

У меня есть страница регистрации, содержащая различные виды редактируемых данных: день рождения, пол, имя, пароль, номер телефона. Я сделал страницу как табличное представление пользовательских ячеек, где каждая ячейка является экземпляром подкласса UITableViewCell и читается из его собственного файла пера. Это потому, что я подумал, что потом смогу повторно использовать эти разные типы ячеек на других страницах табличного представления.

Однако подход к инкапсуляции различных пользовательских ячеек в их собственном месте работает не так хорошо:

  1. Кто будет контролировать, например, подборщик пола внутри GenderCell?

  2. Как я на самом деле собираюсь повторно использовать ячейки в другом контроллере табличного представления, когда мне нужно было установить SignUpController в качестве владельца файла nib-файлов ячейки?

Я не знаю, понимал ли кто-нибудь, кроме себя, что я только что написал, но если так, я был бы очень благодарен за любые предложения о том, как структурировать мой код по-другому.

Большое спасибо,
Stine

Чтобы прояснить ситуацию (?!), Позвольте мне вставить сюда свой код:

EditableLabel.h

@interface EditableLabel : UILabel {   
    UIView *inputView, *inputAccessoryView; 
}

@property (nonatomic, retain) UIView *inputView, *inputAccessoryView; 

- (void) setInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar;

@end

EditableLabel.m

@implementation EditableLabel

@synthesize inputView, inputAccessoryView;

- (void) dealloc {
    [inputView release];
    [inputAccessoryView release];
    [super dealloc];
}

- (void) setInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar {
    self.inputAccessoryView = aToolbar;
    self.inputView = aView;
}

- (BOOL) canBecomeFirstResponder {
    return YES;
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [self becomeFirstResponder];
}

@end

EditableCell.h

typedef enum {
    USERNAME, PASSWORD, MOBILE, BIRTHDAY, GENDER, DESCRIPTION, CATEGORY
} CellTag;

@interface EditableCell : UITableViewCell {
    CellTag tag;    
    UIView *editPoint;
    IBOutlet UILabel *headerLabel;
}

- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andEditPoint:(UIView *)aView;

@property (nonatomic) CellTag tag;
@property (nonatomic, retain) UIView *editPoint;
@property (nonatomic, retain) UILabel *headerLabel;

- (IBAction) editingDone:(id)sender;

- (void) showInputView;
- (void) hideInputView;

@end

EditableCell.m

@implementation EditableCell

@synthesize tag, editPoint, headerLabel;

- (void) dealloc {
    [editPoint release];
    [headerLabel release];
    [super dealloc];
}

- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andEditPoint:(UIView *)aView {
    self.tag = aTag;
    self.headerLabel.text = aHeader;
    self.editPoint = aView;
}

- (IBAction) editingDone:(id)sender {
    [self hideInputView];
}

- (void) showInputView {   
    [self.editPoint becomeFirstResponder];
}

- (void) hideInputView {
    [self.editPoint resignFirstResponder];    
}

@end

EditableLabelCell.h

@interface EditableLabelCell : EditableCell {
    IBOutlet UILabel *placeHolderLabel;
    IBOutlet EditableLabel *editableLabel;
}

@property (nonatomic, retain) UILabel *placeHolderLabel;
@property (nonatomic, retain) EditableLabel *editableLabel;

- (void) setTag:(CellTag)aTag 
      andHeader:(NSString *)aHeader 
 andPlaceHolder:(NSString *)aPlaceHolder
   andInputView:(UIView *)aView
     andToolbar:(UIToolbar *)aToolbar;

- (void) setValue:(NSString *)aValue;

@end

EditableLabelCell.m

@implementation EditableLabelCell

@synthesize placeHolderLabel, editableLabel;

- (void) dealloc {
    [placeHolderLabel release];
    [editableLabel release];
    [super dealloc];
}

- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andPlaceHolder:(NSString *)aPlaceHolder andInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar {
    [super setTag:aTag andHeader:aHeader andEditPoint:self.editableLabel];
    self.placeHolderLabel.text = aPlaceHolder;
    [self.editableLabel setInputView:aView andToolbar:aToolbar];    
}

- (void) setValue:(NSString *)aValue {
    if (aValue && aValue != @"") {                
        self.placeHolderLabel.hidden = YES;
        self.editableLabel.text = aValue;        
    } else {
        self.editableLabel.text = nil;
        self.placeHolderLabel.hidden = NO;
    }
}

@end

EditableGenderCell.h

@protocol EditableGenderCellDelegate <NSObject>
@required
  - (NSString *) getTextForGender:(Gender)aGender;
  - (void) genderChangedTo:(Gender)aGender forTag:(CellTag)aTag;
@end

@interface EditableGenderCell : EditableLabelCell <UITableViewDataSource, UITableViewDelegate> {
    id<EditableGenderCellDelegate> delegate;    
    Gender gender;
    IBOutlet UITableView *genderTable;
    IBOutlet UIToolbar *doneBar;
}

- (void) setTag:(CellTag)aTag 
    andDelegate:(id<EditableGenderCellDelegate>)aDelegate 
      andHeader:(NSString *)aHeader 
      andGender:(Gender)aGender
 andPlaceHolder:(NSString *)aPlaceHolder;

@property (nonatomic, retain) id<EditableGenderCellDelegate> delegate;
@property (nonatomic) Gender gender;
@property (nonatomic, retain) UITableView *genderTable;
@property (nonatomic, retain) UIToolbar *doneBar;

@end

EditableGenderCell.m

@implementation EditableGenderCell

@synthesize delegate, gender, genderTable, doneBar;

- (void) dealloc {
    [delegate release];
    [genderTable release];
    [doneBar release];
    [super dealloc];
}

- (void) setTag:(CellTag)aTag andDelegate:(id<EditableGenderCellDelegate>)aDelegate andHeader:(NSString *)aHeader andGender:(Gender)aGender andPlaceHolder:(NSString *)aPlaceHolder {
    [super setTag:aTag andHeader:aHeader andPlaceHolder:aPlaceHolder andInputView:self.genderTable andToolbar:self.doneBar];
    self.delegate = aDelegate;
    self.gender = aGender;
    [super setValue:[self.delegate getTextForGender:aGender]];
}

#pragma mark - Table view data source

- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 2;
}

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

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

    switch (indexPath.row) {
        case MALE:
            switch (self.gender) {
                case MALE:
                    cell.accessoryType = UITableViewCellAccessoryCheckmark;    
                    break;
                default:
                    cell.accessoryType = UITableViewCellAccessoryNone;  
            } 
            break;
        case FEMALE:
            switch (self.gender) {
                case FEMALE:
                    cell.accessoryType = UITableViewCellAccessoryCheckmark;    
                    break;
                default:
                    cell.accessoryType = UITableViewCellAccessoryNone; 
            }  
            break;
    }

    cell.textLabel.text = [self.delegate getTextForGender:indexPath.row];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}

#pragma mark - Table view delegate

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    self.gender = indexPath.row;
    [super setValue:[self.delegate getTextForGender:self.gender]];
    [self.delegate genderChangedTo:self.gender forTag:self.tag];   
    [tableView reloadData];
}

@end

Ответы [ 2 ]

4 голосов
/ 16 мая 2011

Посмотрите на мой ответ на Как сделать UITableViewCell с различными подпредставлениями повторно используемыми? .

Вам следует создать резервные копии ваших пользовательских перьев таблиц табличных ячеек с помощью пользовательского класса, представляющего вашу ячейку, и инкапсулировать в нем логику, например, ваш выбор пола. Если вам нужно сообщить внешнему контролеру пол, вы можете использовать шаблон делегата.

Пользовательский пол выбора в TableViewCell

Хорошо, давайте начнем с файла пера, похожего на это:

enter image description here

просмотр иерархии, не устанавливайте владельца файла ...

enter image description here

... установите вместо этого класс ячейки табличного представления вашего пользовательского класса:

enter image description here

Пользовательский класс

Как вы можете видеть, класс почти пуст, предоставляя только сегментированный элемент управления как свойство

GenderPickerTableViewCell.h

@interface GenderPickerTableViewCell : UITableViewCell 
{
    UISegmentedControl *genderPickerSegmentedControl;
}

@property (nonatomic, retain) IBOutlet UISegmentedControl *genderPickerSegmentedControl;

@end

GenderPickerTableViewCell.m

#import "GenderPickerTableViewCell.h"


@implementation GenderPickerTableViewCell

@synthesize genderPickerSegmentedControl;

#pragma mark -
#pragma mark memory management

- (void)dealloc 
{   
    [genderPickerSegmentedControl release];

    [super dealloc];
}

#pragma mark -
#pragma mark initialization

- (void)awakeFromNib
{
    // initialization goes here, for example preselect a specific gender
}

@end

Представление таблицы с использованием нашей новой ячейки

Я приведу только необходимые методы, чтобы сделать эту работу. Класс TableViewCellFactory - просто загрузчик пера, как я написал в моем указанном выше ответе . ГендерPickerTableViewCellWithTableView - просто метод класса удобства, чтобы возвратить этот особый вид ячейки без слишком большого стандартного кода

Последнее, что следует отметить, - это конфигурация ячейки, она остается простой, я просто получаю доступ к сегментированному элементу управления напрямую и добавляю к нему цель, которая информирует этот контроллер представления об изменении.

#pragma mark -
#pragma mark view lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    tableView.rowHeight = 100.0;
    tableView.dataSource = self;
    tableView.delegate = self;
}

#pragma mark -
#pragma mark UITableView methods

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 1;
}

- (UITableViewCell *) tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)anIndexPath
{
    GenderPickerTableViewCell *cell = [TableViewCellFactory genderPickerTableViewCellWithTableView:aTableView];

    [cell.genderPickerSegmentedControl addTarget:self 
                                          action:@selector(genderPicked:) 
                                forControlEvents:UIControlEventValueChanged];

    return cell;
}

#pragma mark -
#pragma mark UISegmentedControl action

- (void)genderPicked:(id)sender
{
    UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;

    NSLog(@"selected index: %d", [segmentedControl selectedSegmentIndex]);
}

Надеюсь, это немного поможет для начала.

1 голос
/ 16 мая 2011

Это код, который вы можете использовать для подпрыгивания:

 -(IBAction)textFieldDidBeginEditing:(UITextField *)textField { //Keyboard becomes visible
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3];
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y - 50, self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];

}

Просто установите y соответственно вызову, когда начнется редактирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...