#ios #objective-c #xcode #uitableview
#iOS #objective-c #xcode #uitableview
Вопрос:
Я (довольно) знаком с переходами и делегатами для передачи данных между UIViewControllers, но моя текущая ситуация немного отличается, и я не могу заставить ее работать. Контекст: XCode 5 и iOS7 с Objective C.
У меня есть tableview (динамические прототипы), который загружает пользовательскую ячейку (из отдельного кончика), содержащую UILabel и UISwitch. CustomCell.xib загружает свои данные из CustomCell.h /m. Основное содержимое находится в ViewController.h / m, и в этом файле мне нужно знать, изменилось ли значение переключателя (или фактически новое значение пользовательского переключателя). Очевидно, я знаю это в файлах CustomCell.h / m, но мне нужно передать их в ViewController.h / m.
Я пытался использовать делегат, но я не могу установить делегат для экземпляра UINib (в отличие от установки делегата для экземпляра viewcontroller). Кроме того, пользовательская ячейка реализована в viewcontroller, поэтому она не передается, как другой viewcontroller, в стек навигации.
CustomCell.h
#import <UIKit/UIKit.h>
@protocol CustomCellDelegate <NSObject>
- (void)switchControlValueChanged:(UISwitch*)switchControl toNewValue:(BOOL)value;
@end
@interface CustomCell : UITableViewCell
@property (nonatomic, weak) IBOutlet UILabel *titleLabel;
@property (nonatomic, weak) IBOutlet UISwitch *switchControl;
@property (nonatomic, assign) id <CustomCellDelegate> delegate;
- (void)setValueForSwitchControlTo:(BOOL)value;
- (IBAction)changeColorForSwitchControl;
@end
CustomCell.m
- (void)changeColorForSwitchControl // value changed method
{
...
[self.delegate switchControlValueChanged:self.switchControl toNewValue:self.switchControl.on];
}
ViewController.h
#import <UIKit/UIKit.h>
#import "CustomCell.h"
@interface ViewController : UITableViewController <CustomCellDelegate>
...
@end
ViewController.m
- (void)viewDidLoad
{
...
// cannot set a delegate on the cellNib
UINib *cellNib = [UINib nibWithNibName:kCustomCell bundle:nil];
[self.tableView registerNib:cellNib forCellReuseIdentifier:kCustomCell];
}
- (void)switchControlValueChanged:(UISwitch *)switchControl toNewValue:(BOOL)value
{
NSLog(@"Switch changed!"); // this is not getting displayed
}
Комментарии:
1. Когда и как вы настраиваете делегаты
CustomCell
? Проблема с этим может заключаться в том, что из-за того, что ячейки используются повторно, шаблон делегирования не работает в этом контексте…2. Какой объект
CustomCell
представляет / содержит / ссылку? Другим вариантом было бы позволить этому объекту обрабатывать изменение значения сразу изнутриCustomCell
. Или вам нужна информация, доступная вViewController
?3. Вам нужно назначить делегата после создания ячейки. В методе cellForRowAtIndexPath.
4. @Schmidt: действительно, спасибо! Я проголосовал за другой вариант, поскольку код был немного более полезным, но решение такое же
Ответ №1:
Подходящее время для настройки вашего контроллера просмотра в качестве делегата вашей ячейки — это когда вы настраиваете другие атрибуты вашей ячейки. Вы делаете это в tableView:cellForRowAtIndexPath:
.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCustomCell forIndexPath:indexPath];
...
cell.delegate = self;
return cell;
}
Примечание сбоку: registerNib:forCellReuseIdentifier:
делает именно то, что написано, он просто регистрирует ваше перо для повторного использования. Содержимое nib не загружается до тех пор, пока табличное представление не решит это сделать. Он создает копии ячейки, содержащейся в nib, по мере необходимости.
Ответ №2:
Одним из вариантов было бы использовать NSNotification
, не так элегантно, но будет работать для вашей цели. Каждый раз, когда изменяется значение переключателя, вы можете отправлять уведомление в CustomCell.m
, что-то вроде:
NSDictionary *cellInfo = @{}; // add useful information to identify the cell to this dictionary
[[NSNotificationCenter defaultCenter] postNotificationName:@"SwitchValueChanged" object:nil userInfo:cellInfo];
Затем вы перехватываете уведомление в своем ViewController
, регистрируя его как наблюдателя с помощью:
-(void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(yourMethod) name:@"SwitchValueChanged" object:nil];
}
Комментарии:
1. Другое решение работало лучше, но попробую это позже в качестве альтернативы