NSPrintInfo printSettings не соответствует KVO, несмотря на то, что в заголовке есть комментарий

Фон: я добавляю вспомогательный вид панели печати в диалог печати (используя addAccessoryController:), с элементами управления, связанными со значениями printSettings NSPrintInfo, чтобы значения сохранялись в предварительных настройках печати. У меня проблемы с наблюдением за изменениями настроек печати. Я собираюсь с SDK 10.6, тестирую на OS X 10.7.

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

- (void)testKVO
{
  NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
  [printInfo addObserver:self forKeyPath:@"printSettings.foo" options:0 context:NULL];
  [printInfo setValue:@"bar" forKeyPath:@"printSettings.foo"]; // observeValueForKeyPath:ofObject:change:context: not called
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
  NSLog(@"%s %@ :: %@", _cmd, keyPath, object);
}

Я также пытался наблюдать printSettings напрямую, но безуспешно, метод наблюдателя также не вызывался (printSettings, возвращаемый NSPrintInfo, фактически является классом NSPrintInfoDictionaryProxy):

- (void)testKVO
{
  NSMutableDictionary *printSettings = [[NSPrintInfo sharedPrintInfo] printSettings];
  [printSettings addObserver:self forKeyPath:@"foo" options:0 context:NULL];
  [printSettings setValue:@"bar" forKey:@"foo"]; // observeValueForKeyPath:ofObject:change:context: not called
}

Я дважды проверил, что моя система KVO работает в нормальных условиях и вызывает метод наблюдателя:

- (void)testKVO
{
  NSMutableDictionary *printSettings = [NSMutableDictionary dictionary];
  [printSettings addObserver:self forKeyPath:@"foo" options:0 context:NULL];
  [printSettings setValue:@"bar" forKey:@"foo"]; // observeValueForKeyPath:ofObject:change:context: called at last!
}

Таким образом, вопрос заключается в следующем: как я могу наблюдать за изменениями printSettings, особенно чтобы узнать, когда пользователь выбрал предустановку печати?

Я также хотел бы, чтобы предварительный просмотр обновлялся автоматически

- (NSSet *)keyPathsForValuesAffectingPreview
{
  return [NSSet setWithObjects:
          @"representedObject.printSettings.foo",
          nil];
}

Существует простой обходной путь для обновления предварительного просмотра: добавление уровня косвенности путем повторного выделения свойств непосредственно в самом NSViewController. Но для изменения настроек печати я понятия не имею.

В конце вот комментарий в NSPrintInfo.h:

- (NSMutableDictionary *)printSettings;

Настройки печати информации о печати. Вы можете поместить значения в этот словарь, чтобы сохранить их в любой предустановке, которую пользователь создает при редактировании этой информации о печати с помощью панели печати. Такие значения должны быть объектами списка свойств. Этот класс совместим с "printSettings" для кодирования значения ключа (KVC) и наблюдения значения ключа (KVO), поэтому вы часто можете привязывать элементы управления в дополнительных представлениях панели печати непосредственно к записям в этом словаре. Вы также можете использовать этот словарь, чтобы получить значения, которые были установлены другими частями системы печати, например расширение диалога печати драйвера принтера (те же самые значения, которые возвращаются функцией PMPrintSettingsGetValue() диспетчера печати на угле). В других частях системы печати часто используются ключевые строки, такие как "com.apple.print.PrintSettings.PMColorSyncProfileID", но точки, подобные тем, которые есть в ключевых строках, не будут хорошо работать с KVC, поэтому эти точки заменяются подчеркиванием в ключах, которые появляются в этом словарь, как в "com_apple_print_PrintSettings_PMColorSyncProfileID". Вы должны использовать то же соглашение при добавлении записей в этот словарь.

Любая помощь приветствуется

Спасибо

1 ответ

Решение

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

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

Это не так просто, как привязка к путям печати printSettings, и мне действительно не нравится использовать недокументированное уведомление (почти так же плохо, как использование частного API с точки зрения удобства сопровождения), но это единственный способ, которым я мог бы разобраться в выполнении работы.

Другие вопросы по тегам