2012-01-27 4 views
1

У меня есть три разделенных класса, UIViewController (A) и два UITableViewControllers (B и C).Как получить доступ к другому контроллеру/представлению (iOS)

добавить таблицу В и С в А.

[A.view addSubview:B.tableView]; 

[A.view addSubview:C.tableView]; 

Теперь нужно изменить/перезагрузить одну таблицу путем выбора в другой таблице. Например, выберите «мясо» в B, затем C станет «курицей, свининой ...», выберите «фрукты», затем получите «яблоко, томаты ...».

Мой вопрос в целом Как получить доступ к другому контроллеру/представлению. Что я должен писать в файле didSelectRowAtIndexPath в B для доступа к другому контроллеру (A, C)?

ответ

2

Вы ищете delegation. Добавьте протокол к B и C, а другой выполните его.

Я написал sample code совсем недавно.

В этом случае CheckTableController может информировать ShowFavoritesTableController, поскольку второй реализует протокол делегата первого.

+0

Спасибо @vikingosegundo. какова разница между делегированием и уведомлением в этом случае, с точки зрения принципов программирования. Я думаю, что их принципы очень схожи, и пусть кто-то другой сделает это за них. – ThinkChris

+2

Есть общие черты. Но большие различия также. Уведомления транслируют: они могут сообщать о многих объектах, которые «настроены» на объекте, но их отправитель не может получать из него никаких сообщений или объектов. Делегирование - это сообщение 1 к 1, но методы делегата могут возвращать объекты. Вы можете использовать методы с подписями любого типа. Передача уведомлений является дорогостоящей, а делегации - это просто обычная отправка сообщений. – vikingosegundo

+1

http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/CommunicateWithObjects.html – vikingosegundo

2

Обычно я делаю это через NSNotificationCenter. В

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 

Передача сообщения с использованием NotificationCenter.

[[NSNotificationCenter defaultCenter]postNotificationName:@"NotificationName" object:myObj]; 

В классе, который имеет приемный конец установить его на прослушивание этого уведомления в viewDidLoad или метод инициализации

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadTable:) name:@"NotificationName" object:nil]; 

ли ваш метод, объявленный в файле .m

-(void)reloadTable:(NSNotification*)n { 
[tableView reloadData]; 
} 

Не забудьте удалить наблюдателя, когда объект был уничтожен в методе dealloc Если вы используете ARC

- (void)dealloc { 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

Если вы не используете ARC помнить супер

- (void)dealloc { 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
    [super dealloc]; 
} 
+0

Спасибо @ Justin. Это кажется хорошим способом сделать это. Давайте посмотрим, есть ли другие способы. Просто хочу знать лучший метод. – ThinkChris

+0

Мне также нравится стратегия @ asops для обработки нескольких видов таблиц в одном классе. Я также сделал это раньше, и он работает хорошо. Иногда я переключаю ту таблицу, которая, устанавливая свойство tag (table) tableView, поэтому мне не нужно удерживать слабые ссылки на tableView при использовании Interface Builder. Центр центра уведомлений работает хорошо, когда вы говорите об объектах и ​​не хотите придавать жесткость структуре вашего кода. Кроме того, вам не нужно беспокоиться о сохранении циклов таким образом. – MobileOverlord

+0

Уведомления будут считаться дорогостоящими. Они хороши для ситуаций, когда вы не можете знать, если какие-либо (или многие) объекты должны быть проинформированы - и если они еще существуют. также они могут использоваться, если вы передаете информацию с дистанционной части вашего приложения на другую, вместо того, чтобы использовать пользовательский синглтон. Но вопрос не описывает такой сценарий. – vikingosegundo

0

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

@interface MyController : UIViewController <UITableViewDataSource, UITableViewDelegate> 
    UITableView *firstTableView; 
    UITableView *secondTableView; 
@end 

Теперь в файле .m установите таблицы вверх, как так:

- (id)init { 
    if ((self = [super init])) { 
     firstTableView = [[UITableView alloc] initWithFrame:/*desired frame*/ style:/*desired style*/]; 
     secondTableView = [[UITableView alloc] initWithFrame:/*desired frame*/ style:/*desired style*/]; 

     firstTableView.delegate = self; 
     firstTableView.dataSource = self; 

     secondTableView.delegate = self; 
     secondTableView.dataSource = self; 
    } 
} 

- (void)dealloc { 
    [firstTableView release]; 
    [secondTableView release]; 
    [super dealloc]; 
} 

Тогда, реализуют желаемое UITableViewDataSource методов, например:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if (tableView == firstTableView) { 
     // Do something 
    } else if (tableView == secondTableView) { 
     // Do something else 
    } 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    if (tableView == firstTableView) { 
     // Configure the cell 
    } else if (tableView == secondTableView) { 
     // Configure the cell a different way 
    } 
} 

Наконец, в didSelectRowAtIndexPath:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (tableView == firstTableView) { 
     // Update something that is linked to the return values of secondTableView's dataSource methods 
     [secondTableView reloadData]; 
    } 
} 

Такой подход гарантирует, что ваш контроллер получает право -viewDidLoad, -viewWillAppear, и так далее, автоматически. Помните, что просто добавляет представления диспетчера вида, так как subviews означает, что ваш контроллер не получит эти вызовы.

+0

Лично я думаю, это очень грязный способ, так как вам придется поддерживать джунгли if/else-statements. – vikingosegundo

+0

Спасибо @aopsfan, огромный класс является мощным, но также трудно поддерживать, использовать его с осторожностью – ThinkChris

+0

Я согласен с идеей, что нужно использовать только один контроллер вида (OF COURSE!), Но я думаю, что лучше всего создать отдельный файлов для каждого вида таблицы, который обрабатывает соответствующие методы источника данных/делегата. – sosborn

Смежные вопросы