Центр уведомлений на C

#c #objective-c #notifications #nsnotificationcenter #cocoa-design-patterns

#c #objective-c #уведомления #nsnotificationcenter #cocoa-шаблоны проектирования

Вопрос:

После некоторого программирования с использованием фреймворков objective C для iOS и Mac мне понравился общий шаблон уведомлений, реализованный классами NSNotificationCenter и NSNotification. Возвращаясь к C , который всегда был моим языком выбора для большинства вещей, я обнаружил, что пытаюсь воспроизвести этот шаблон и считаю, что на самом деле уже должна быть общая реализация аналогичных классов C , предлагающая поддержку для этого.

Похоже, что шаблон несколько сложнее реализовать на C , чем Objective C, из-за более динамичного характера более поздней версии, но это кажется далеко не невозможным. Я просмотрел библиотеки boost, поскольку они, как правило, потрясающие, и мне было грустно не найти там свою удачу. Хотя boost::bind, boost::lamda, boost::function, похоже, выполняют большую часть работы. Я пропустил что-то очевидное? Есть ли что-нибудь уже существующее, что позволило бы мне легко воспроизвести поведение NSNotification / NSNotificationCenter?

Комментарии:

1. Вы пробовали Boost.signals?

2. Я посмотрю, спасибо за предложение.

3. С немного другим подходом Qt реализовал «сигналы и слоты» с помощью специального инструмента предварительной обработки (moc <-> компилятор метаобъектов). Однако использовать его разумно, только если qt ui соответствует вашим потребностям.

Ответ №1:

Теоретически вы могли бы создать класс, у которого есть вектор указателей на функции для вызова при вызове определенного уведомления — класс, у которого есть словарь, где объектами являются векторы функций для вызова при отправке уведомления

Ответ №2:

В дополнение к boost пакетам, упомянутым в других ответах, есть еще один вариант poco::NotificationCenter .

Эта реализация ближе к платформе уведомлений Cocoa, как конкретно обсуждается в документации Poco:

Класс NotificationCenter в основном является реализацией C класса NSNotificationCenter, найденного в Cocoa от Apple (или OpenStep).

Ответ №3:

Следуя рекомендации @anno взглянуть на boot ::signal, после проверки это кажется возможным вариантом, хотя, как и ожидалось, не таким простым, как решения objective C. Просматривая руководство по boost ::signal, я подумал, что рассмотрю наиболее важные аспекты для рассматриваемой проблемы.


Для создания отправителей уведомлений:

Рассмотрим простую службу доставки новостей, в которой клиенты подключаются к поставщику новостей, который затем отправляет новости всем подключенным клиентам по мере поступления информации. Служба доставки новостей может быть построена следующим образом:

 class NewsItem { /* ... */ };
boost::signal<void (const NewsItemamp;)> deliverNews;
  

Цель deliverNews состоит в том, чтобы информировать наблюдателей о том, что NewsItem было сгенерировано.


Наблюдатели могут быть добавлены следующим образом (с использованием библиотеки boost::bind):

Клиентам, которые хотят получать обновления новостей, нужно только подключить функциональный объект, который может получать новостные элементы, к сигналу deliverNews. Например, у нас может быть специальная область сообщений в нашем приложении специально для новостей, например,:

 struct NewsMessageArea : public MessageArea
{
public:
  // ...

  void displayNews(const NewsItemamp; news) const
  {
    messageText = news.text();
    update();
  }
};

// ...
NewsMessageArea newsMessageArea = new NewsMessageArea(/* ... */);
// ...
deliverNews.connect(boost::bind(amp;NewsMessageArea::displayNews, newsMessageArea, _1));
  

Для решения проблемы удаления наблюдателей, которые были освобождены из списка, boost::signal предлагает следующее решение

Однако, что, если пользователь закроет область новостных сообщений, уничтожив объект newsMessageArea, о котором знает deliverNews? Скорее всего, произойдет ошибка сегментации. Однако с повышением.Сигналы нужно только сделать NewsMessageArea отслеживаемым, и слот, включающий newsMessageArea, будет отключен, когда newsMessageArea будет уничтожен. Класс NewsMessageArea становится отслеживаемым путем публичного вывода из класса boost::signals::trackable, например:

 struct NewsMessageArea : public MessageArea, public boost::signals::trackable
{
  // ...
};
  

В настоящее время существует значительное ограничение на использование отслеживаемого
объекты при подключении к слоту: функциональные объекты, созданные с использованием
Повышение.Подразумевается привязка, так что указатели или ссылки на
отслеживаемые объекты, переданные в boost::bind, будут найдены и отслежены.