Задачи набора PDF
Эта глава показывает, как можно реализовать общие задачи с Набором PDF.
Реализация PDFView
Большинство разработчиков просто захочет вывести на экран информацию о PDF в своих представлениях, таким образом, PDFView будет отвечать всем требованиям приятно.
Элемент пользовательского интерфейса PDFView доступен в Интерфейсном Разработчике, таким образом, необходимо использовать это везде, где Вы хотите, чтобы Ваше приложение вывело на экран содержание PDF. Обратите внимание на то, что необходимо установить палитру PDF Kit в /Developer/Extras/Palettes/PDFKit.palette
сделать PDFViews доступный.
Для добавления палитры PDFKit в Интерфейсном Разработчике выберите вкладку Palettes в панели Preferences. Нажмите Add … кнопка, перейдите к /Developer/Extras/Palettes
папка и выбор палитра PDFKit. Затем, выберите пункт меню Customize Toolbar в меню Tools/Palettes и перетащите палитру PDFKit на панель инструментов для создания его видимым.
После добавления элемента PDFView в Вашем файле пера можно добавить содержание PDF из приложения путем вызова метода PDFDocument initWithURL
. Например, Вы могли использовать код как следующее:
PDFDocument *pdfDoc; |
pdfDoc = [[PDFDocument alloc] initWithURL: [NSURL fileURLWithPath: [self fileName]]]; |
[_pdfView setDocument: pdfDoc]; |
Также, если Ваши данные PDF хранятся в другой форме, можно использовать метод PDFDocument initWithData:
. Пользователи могут также перетащить документы в представление.
Получающийся PDFView обрабатывает основную функциональность, требуемую просмотреть и перейти через документ в формате PDF. Простая прокрутка и активные ссылки работают автоматически, и Вы также заставляете контекстное меню обрабатывать масштабирование и навигацию.
Набор PDF в предварительном просмотре
Предварительный просмотр в OS X v10.4 использует Набор PDF, таким образом, можно использовать это приложение в качестве руководства для наблюдения то, что возможно в собственных представлениях PDF. Много вызовов метода в Наборе PDF имеют сопоставимый пункт меню в Предварительном просмотре. Таблица 2-1 показывает корреспонденцию между различными пунктами меню и их эквивалентами API.
Меню | Подменю | Метод |
---|---|---|
Представление | Дисплей PDF | PDFView: |
Увеличение | PDFView: | |
Уменьшение | PDFView: | |
Пойти | Затем | PDFView: |
Предыдущий | PDFView: | |
Перейдите к странице | PDFView: | |
Сначала | PDFView: | |
В последний раз | PDFView: | |
Назад | PDFView: | |
Передать | PDFView: | |
Инструменты | Вращайтесь оставленный | PDFPage: |
Поверните право | PDFPage: | |
Аннотация |
|
Создание основ
Много документов в формате PDF содержат основы, таким образом, Ваше приложение будет обычно хотеть вывести на экран эту информацию также.
Обратите внимание на то, что, потому что некоторые документы в формате PDF не содержат информацию о схеме, необходимо, вероятно, сделать контурное отображение дополнительным элементом в пользовательском интерфейсе. Например, можно вывести на экран основы в секции, которая может быть закрыта если не необходимый.
Можно использовать класс NSOutlineView для отображения основ PDF. Экземпляры этого класса автоматически выводят на экран иерархию схемы с треугольниками раскрытия и активными ссылками с надлежащими страницами PDF. Перечисление 2-1 показывает, как Вы могли бы сделать так.
Перечисление 2-1 , Загружающее PDF, обрисовывает в общих чертах информацию
_outline = [[_pdfView document] outlineRoot];// 1 |
if (_outline) |
{ |
[_noOutlineText removeFromSuperview];// 2 |
_noOutlineText = NULL; |
[_outlineView reloadData];// 3 |
} |
else |
{ |
[[_outlineView enclosingScrollView] removeFromSuperview];// 4 |
_outlineView = NULL; |
} |
Вот то, как работает код:
Получает корневой (самый верхний) элемент схемы.
_outline
экземпляр PDFOutline.Если корневая схема существует, удаляет текст заполнителя, указывающий “Схему”.
Загрузки PDF обрисовывают в общих чертах информацию в представление схемы. Представление схемы вызывает Ваши методы делегата определить элементы в иерархии схемы.
Если корневая схема не существует, удаляет представление схемы, оставляя позади текст заполнителя.
После вызова reloadData
метод, представление схемы вызывает различные методы делегата источника данных заполнить схему. Эти методы делегата определяются в протоколе NSOutlineViewDataSource. Ваше приложение должно реализовать эти методы так, чтобы надлежащие данные PDF были добавлены к схеме.
Перечисление 2-2 показывает метод делегата для получения числа дочерних элементов, просто возвращающего значение, полученное методом PDFOutline numberOfChildren
. Если параметр элемента NULL
, этот метод возвращает число дочерних элементов для корневой схемы.
Метод делегата перечисления 2-2 для определения числа дочерних элементов
- (int) outlineView: (NSOutlineView *) outlineView numberOfChildrenOfItem: (id) item |
{ |
if (item == NULL) |
{ |
if (_outline) |
return [_outline numberOfChildren]; |
else |
return 0; |
} |
else |
return [(PDFOutline *)item numberOfChildren]; |
} |
Перечисление 2-3 показывает метод делегата для получения определенной дочерней схемы путем вызова метода PDFOutline childAtIndex
. Если параметр элемента NULL
, этот метод возвращает соответствующий дочерний элемент корневой схемы.
Метод делегата перечисления 2-3 для получения дочернего элемента
- (id) outlineView: (NSOutlineView *) outlineView child: (int) index ofItem: (id) item |
{ |
if (item == NULL) |
{ |
if (_outline) |
return [_outline childAtIndex: index]; |
else |
return NULL; |
} |
else |
return [(PDFOutline *)item childAtIndex: index]; |
Перечисление 2-4 показывает метод делегата для определения, если элемент схемы расширяем (т.е. имеет ли это дочерние основы).
Метод делегата перечисления 2-4 для определения, если элемент имеет дочерние элементы
- (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item |
{ |
if (item == NULL) |
{ |
if (_outline) |
return ([_outline numberOfChildren] > 0); |
else |
return NO; |
} |
else |
return ([(PDFOutline *)item numberOfChildren] > 0); |
} |
Перечисление 2-5 показывает метод делегата для получения метки элемента схемы, вызывающей метод PDFOutline label
. Метка является просто строкой, выведенной на экран в представлении схемы (например, заголовок главы).
Метод делегата перечисления 2-5 для получения содержания элемента
- (id) outlineView: (NSOutlineView *) outlineView |
objectValueForTableColumn: (NSTableColumn *) tableColumn |
byItem: (id) item |
{ |
return [(PDFOutline *)item label]; |
} |
Когда пользователь выбирает элемент схемы, Ваше приложение должно обновить дисплей PDF для показа страницы, соответствующей тому элементу. Самый простой способ сделать так состоит в том, чтобы вызвать PDFView’s goToDestination
метод, как показано в Перечислении 2-6.
Перечисление 2-6 , Выводящее на экран страницу, связалось с элементом схемы
- (IBAction) takeDestinationFromOutline: (id) sender |
{ |
[_pdfView goToDestination: [[sender itemAtRow: |
[sender selectedRow]] destination]]; |
} |
Кроме того, если пользователь прокручивает или иначе перемещается через документ, Ваше приложение должно обновить схему для выделения элемента схемы, соответствующего в настоящее время выводимой на экран странице. Можно сделать так путем установки обработчика уведомления, который вызовут каждый раз изменениями страницы (т.е. когда PDFViewPageChangedNotification отправляется). Перечисление 2-7, как то, как Вы могли бы сделать так.
Перечисление 2-7 , Обновляющее схему, когда изменяется страница
- (void) pageChanged: (NSNotification *) notification |
{ |
unsigned int newPageIndex; |
int numRows; |
int i; |
int newlySelectedRow; |
if ([[_pdfView document] outlineRoot] == NULL)// 1 |
return; |
newPageIndex = [[_pdfView document] indexForPage: // 2 |
[_pdfView currentPage]]; |
// Walk outline view looking for best firstpage number match. |
newlySelectedRow = -1; |
numRows = [_outlineView numberOfRows]; |
for (i = 0; i < numRows; i++)// 3 |
{ |
PDFOutline *outlineItem; |
// Get the destination of the given row.... |
outlineItem = (PDFOutline *)[_outlineView itemAtRow: i]; |
if ([[_pdfView document] indexForPage: |
[[outlineItem destination] page]] == newPageIndex) |
{ |
newlySelectedRow = i; |
[_outlineView selectRow: newlySelectedRow |
byExtendingSelection: NO]; |
break; |
} |
else if ([[_pdfView document] indexForPage: |
[[outlineItem destination] page]] > newPageIndex) |
{ |
newlySelectedRow = i - 1; |
[_outlineView selectRow: newlySelectedRow |
byExtendingSelection: NO]; |
break; |
} |
} |
if (newlySelectedRow != -1)// 4 |
[_outlineView scrollRowToVisible: newlySelectedRow]; |
} |
Вот то, как работает код:
Проверки, чтобы видеть, существует ли корневая схема. В противном случае тогда нет никакой схемы для обновления, таким образом, просто возвращаются.
Получает индексное значение для текущей страницы. Метод PDFView
currentPage
возвращает объект PDFPage и метод PDFDocumentindexForPage
возвращает фактический индекс для той страницы. Это индексное значение основано на нуле, таким образом, оно не обязательно соответствует номеру страницы.Выполните итерации через каждый видимый элемент в схеме, проверив, чтобы видеть, происходит ли одно из следующего:
Индекс элемента схемы соответствует индекс новой страницы. Если так, выделите этот элемент (использующий метод NSTableView
selectRow:byExtendingSelection
).Индекс элемента схемы больше, чем индекс страницы. Если так, соответствие не было возможно, поскольку индекс соответствует скрытому дочернему элементу видимого элемента. В этом случае использовать
selectRow
выделить родительский элемент схемы (текущая строка-1).
Вызовите метод NSTableView
scrollRowToVisible
скорректировать представление схемы (если необходимый) для создания выделенного элемента видимым.
Поиск документа в формате PDF
Пользователи часто должны перерывать документ в формате PDF. Набор PDF предлагает два метода для того, чтобы сделать так:
Поиск строки строкой через документ. Т.е. когда пользователь ищет строку, Набор PDF возвращает первое возникновение строки. Дополнительные поиски (“Находят Снова”) возвращают последовательные экземпляры строки. Этот метод поиска синхронен.
Получение перечисления всех случаев строки в документе. Этот метод поиска может быть синхронным или асинхронным.
Для простой строки поиском строки Ваше приложение может просто вызвать метод PDFDocument findString:fromSelection:withOptions:
.
- (PDFSelection *) findString:(NSString *)string |
fromSelection:PDFSelection *selection:withOptions:(int)options |
Вывести на экран выбор возвратилось, можно вызвать метод PDFView setCurrentSelection
, который выделяет выбор, сопровождаемый scrollSelectionToVisible
.
Можно указать следующие опции:
NSCaseInsensitiveSearch
: Игнорируйте регистр при создании соответствия.NSLiteralSearch
: Поиск непрерывных слов, разделенных пробелами.NSBackwardsSearch
: Ищите назад от текущего выбора.
Путем передачи NULL
для выбора можно начать поиск с начала (или конец) документа. Путем передачи нового соответствия для выбора можно реализовать, “Находят Снова” поведение. Если findString
вызовите возвраты NULL
, это означает, что или строка не была найдена, или поиск достиг конца (или начинающийся) документа.
Для получения всех случаев данной строки можно использовать любой из следующих методов PDFDocument:
findString:withOptions:
синхронно получить объект NSArray, содержащий все соответствияbeginFindString:withOptions:
асинхронно начать поиск всех случаев. Набор PDF вызывает Ваш метод делегата каждый раз, когда соответствие найдено.
Если Вы не уверены, что поиск будет краток, необходимо принять решение использовать beginFindString:withOptions:
Поскольку это - асинхронный поиск, PDFDocument включает две других полезных находки связанные методы:
isFinding
определить если поиск в в настоящее время происходящемcancelFindString
завершать текущий поиск.
Перечисление 2-8 показывает, как Вы могли бы инициировать поиск:
Перечисление 2-8 , Начинающее асинхронный поиск
- (void) doFind: (id) sender |
{ |
if ([[_pdfView document] isFinding])// 1 |
[[_pdfView document] cancelFindString]; |
if (_searchResults == NULL)// 2 |
_searchResults = [NSMutableArray arrayWithCapacity: 10]; |
[[_pdfView document] beginFindString: [sender stringValue] // 3 |
withOptions: NSCaseInsensitiveSearch]; |
} |
Вот то, как работает код:
Отмены любые текущие поиски.
Выделяет непостоянный массив для содержания результатов поиска, если Вы уже не существуете.
Вызывает метод PDFDocument
beginFindString:withOptions:
с желаемой строкой поиска.
Во время поиска Набор PDF отсылает уведомления, на которые может реагировать Ваше приложение:
PDFDocumentDidBeginFindNotification
PDFDocumentDidEndFindNotification
PDFDocumentDidBeginPageFindNotification
PDFDocumentDidEndPageFindNotification
PDFDocumentDidFindMatchNotification
Когда поиск запускается или заканчивает поиск, первые два уведомления отправляются. Можно использовать эти уведомления, чтобы установить и удалить индикаторы выполнения или любые другие инициализации.
Когда поиск начинается или концы, ищущие страницу в документе, начинание и уведомления страницы конца отправляются. Можно использовать эти уведомления для обновления счетчика страницы или индикатора выполнения.
Уведомление соответствия находки отправляется каждый раз, когда соответствие найдено для строки поиска. Обычно Вы захотите получить строковый выбор и сохранить его в массиве для более позднего дисплея. Однако в большинстве случаев может быть проще использовать метод делегата PDFDocument didMatchString
, который автоматически передает Вас соответствующий выбор. Перечисление 2-9 показывает, как Вы могли бы реализовать делегата, чтобы взять каждую соответствующую строку и добавить его к массиву результатов поиска в NSTableView.
Перечисление 2-9 , Добавляющее результаты поиска к табличному представлению
- (void) didMatchString: (PDFSelection *) instance |
{ |
// Add page label to our array. |
[_searchResults addObject: [instance copy]]; |
// Force a reload. |
[_searchTable reloadData]; |
} |
Здесь _searchResults
экземпляр NSMutableArray, и _searchTable
экземпляр NSTableView.
Чтобы удостовериться, что NSTableView выводит на экран результаты поиска правильно, необходимо реализовать методы источника данных делегата (подобный требуемым для NSOutlineView). Эти методы делегата определяются в протоколе NSTableDataSource.
Перечисление 2-10 показывает метод делегата для определения числа строк в табличном представлении. Этот метод просто получает число элементов в результатах поиска путем вызова метода NSMutableArray count
.
Перечисление 2-10 , Определяющее число строк в таблице
- (int) numberOfRowsInTableView: (NSTableView *) aTableView |
{ |
return ([_searchResults count]); |
} |
Перечисление 2-11 показывает метод источника данных делегата для получения значения определенного столбца.
Перечисление 2-11 Получая значение для столбца
- (id) tableView: (NSTableView *) aTableView objectValueForTableColumn: |
(NSTableColumn *) theColumn |
row: (int) rowIndex |
{ |
if ([[theColumn identifier] isEqualToString: @"page"]) |
return ([[[[_searchResults objectAtIndex: rowIndex] pages] |
objectAtIndex: 0] label]); |
else if ([[theColumn identifier] isEqualToString: @"section"]) |
{ |
NSString *label = [[[_pdfView document] outlineItemForSelection: |
[_searchResults objectAtIndex: rowIndex]] label]; |
return label; |
} |
else |
return NULL; |
} |
Табличное представление вызывает этот метод каждый раз, когда это должно определить значение определенного табличного элемента (такой, подготовив таблицу к дисплею).
Таблица результатов поиска в этом примере содержит только два столбца: страница, содержащая хит и раздел схемы, содержащий хит. (В более сложном примере можно хотеть вывести на экран часть текста, содержащего соответствующую строку, как Предварительный просмотр делает.) Вы ссылаетесь на эти столбцы с помощью идентификатора, тегирует Вас указанный для них в инспекторе NSTableColumn окно в Интерфейсном Разработчике (как показано на рисунке 2-1).
Для этого примера:
Если идентификатор столбца является «страницей», возвратите номер страницы хита путем вызова метода PDFSelection
pages
.Если идентификатор столбца является «разделом», возвратите метку схемы для выбора путем вызова метода PDFDocument
outlineItemForSelection
.
Когда пользователь выбирает элемент в результатах поиска, Ваше приложение должно вывести на экран соответствующую страницу. Перечисление 2-12 показывает, как Вы могли бы сделать настолько использующее уведомление NSTableView.
Перечисление 2-12 , Обрабатывающее выбор в таблице
- (void) tableViewSelectionDidChange: (NSNotification *) notification |
{ |
int rowIndex; |
// What was selected. Skip out if the row has not changed. |
rowIndex = [(NSTableView *)[notification object] selectedRow];// 1 |
if (rowIndex >= 0) |
{ |
[_pdfView setCurrentSelection: // 2 |
[_searchResults objectAtIndex: rowIndex]]; |
[_pdfView scrollSelectionToVisible: self];// 3 |
} |
} |
Когда элемент выбран и вызывает Ваш метод делегата, табличное представление отправляет NSTableViewSelectionDidChangeNotification tableViewSelectionDidChange
. Вот то, как работает код:
Проверки, чтобы видеть, допустим ли выбор.
Устанавливает текущий выбор в тот, по которому щелкнул пользователь.
Обновляет представление PDF для показа страницы, содержащей выбор.
Для получения дополнительной информации о реализации этих методов делегата, см. Руководство по программированию Табличного представления для Mac в Документации Опыта Потребителя Какао.