Как обратиться к вызывающему классу в Objective-C - PullRequest
3 голосов
/ 14 января 2010

Можете ли вы сослаться на отправителя сообщения, не передавая его в качестве параметра? Это упрощенный код для обсуждения:

// mainTableViewController.m
    [dataModel loadData];    //Table is requesting data based on user input

// dataModel.m
  -(void) loadData{

    // I want to store the sender for later reference
    sendingTableViewController = ???? ;  
  }

  - (void) connectionDidFinishLoading:(NSURLConnection *)connection {
        // Web data is loaded. Ask the sending tableViewController to 
        //  reload it's data.
    [sendingTableViewController.tableView reloadData];
  } 

Я все еще привыкаю к ​​тому, как обращаться к методам и свойствам, которые находятся в ведении другого объекта. Я хочу отправить сообщение на dataModel, чтобы загрузить некоторые данные, используя NSURLConnection. Но я не просто хочу вернуть данные, потому что я не хочу сидеть сложа руки в ожидании загрузки данных. Я хочу отправить сообщение на номер mainTableViewController после вызова connectionDidFinishLoading.

Поскольку метод loadData можно вызывать с любого числа tableViewControllers, я не могу просто сказать [mainTableViewController reloadData].

Дополнительный вопрос
Отличная информация! Мне нравится природа StackOverflow без суждений.

То есть mainTableViewController будет делегатом dataModel?
Было бы правильно сказать, что dataModel класс определяет неофициальный протокол?
В настоящее время я создаю экземпляр своего dataModel класса из моего mainTableViewController. Поэтому я могу изменить свой код так:

// mainTableViewController.m
    dataModel *myDataModel = [[dataModel alloc] initWithDelegate:self ];

    // Does this method need to be defined in the mainTableViewController header file
    //  since I will already have defined it in the dataModel header file?
  -(void) dataDidFinishLoading {
    [self.tableView reloadData];
  }

// dataModel.m
  -(id) initWithDelegate:(id)aDelegate{
    self.delegate = aDelegate;
  }

  -(void) connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.delegate dataDidFinishLoading];
  }  

Это плохо, что мой TableViewController создает экземпляр моей модели данных, потому что тогда мой dataModel принадлежит TableViewController? Должен ли я действительно создать экземпляр dataModel из AppDelegate?

Спасибо!

Ответы [ 2 ]

8 голосов
/ 14 января 2010

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

В Какао использование объектов делегатов используется повсеместно. Объект делегата - это объект, который реализует определенный протокол с методами обратного вызова, которые могут быть вызваны, когда происходят вещи или события (например, загрузка данных из удаленного местоположения, в вашем случае). Я рекомендую вам создать свойство делегата в вашей модели данных, иметь интерфейс, который реализует mainTableViewController (или любой другой класс, действительно), и назначить этот класс в качестве делегата. Затем, когда данные будут загружены, вызовите соответствующий метод на self.delegate. В этом методе обратного вызова вы можете вызвать [tableView reloadData].

Опять же, вы не хотите, чтобы ваша модель данных была связана (имеется в виду) с существованием классов вашего контроллера.

Редактировать

Я только что перечитал последнюю часть вашего вопроса о наличии нескольких контроллеров таблиц, которые должны прослушивать уведомления о завершении загрузки данных. Для этого я предлагаю вам использовать Observer pattern в Какао, используя NSNotificationCenter. Вы используете центр уведомлений в модели данных для отправки уведомлений наблюдателям (вам все равно, кто наблюдает; центр уведомлений обрабатывает эти детали), и вы также используете его в контроллерах своей таблицы, чтобы подписаться на уведомление. Делегаты - это хорошее, простое решение, если вам нужен только один объект для непосредственного вызова, когда что-то происходит. Уведомления более сложны и имеют больше накладных расходов, но дают вам возможность иметь произвольное количество объектов, «прослушивающих» уведомление для публикации.

Последующий ответ

Класс не определяет неформальный протокол; разработчик делает. Вы также можете определить формальный протокол в отдельном файле .h и заставить контроллер реализовать его, если вы хотите принудительно заключить контракт. С формальным протоколом вы также можете использовать @optional для методов, которые не должны быть реализованы классом, соответствующим протоколу.

Также неплохо создать экземпляр модели данных из контроллера табличного представления. На самом деле, это один очень правильный способ сделать это. Поскольку модель данных существует для инкапсуляции данных, которые (предположительно) контроллер захочет отобразить позже, вы можете думать о контроллере как о владельце модели данных. Вы можете даже подумать о создании переменной экземпляра (и, возможно, свойства) для хранения вашей модели данных. Кроме того, ваш переписанный код выглядит хорошо для меня!

0 голосов
/ 14 января 2010

Вы имеете в виду ключевое слово self?

-(void)canHazCheeseburger:(BOOL)canHaz
{
    if (canHaz) {
        self.cheeseBurger = [[[CheeseBurger alloc] init] autorelease];
        [cheeseBurger onNomNom];
    }       
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...