Используя текстовый набор, чтобы составить и управлять текстом
Платформа UIKit включает несколько классов, цель которых состоит в том, чтобы вывести на экран текст в пользовательском интерфейсе приложения: UITextView
, UITextField
, UILabel
, и UIWebView
, как описано в Отображении текстового Содержания в iOS. Текстовые представления, создаваемые из UITextView
класс, предназначаются для отображения больших сумм текста. Лежание в основе UITextView
мощный механизм расположения, названный текстовым Набором. Если необходимо настроить процесс создания макета, или необходимо вмешаться в то поведение, можно использовать текстовый Набор. Для меньших сумм текста и специальных потребностей, требующих настраиваемых решений, можно использовать альтернативные, технологии низшего уровня, как описано в Lower Level Text-Handling Technologies.
Текстовый Набор является рядом классов и протоколов в платформе UIKit, предоставляющей высококачественные типографские услуги, позволяющие приложениям сохранить, разметить и вывести на экран текст со всеми характеристиками прекрасного набора, такими как кернинг, лигатуры, повреждение строки и выравнивание. Текстовый Набор создается поверх Базового текста, таким образом, это обеспечивает ту же скорость и питание. UITextView
полностью интегрируется с текстовым Набором; это обеспечивает редактирование и возможности дисплея, позволяющие пользователям ввести текст, указать атрибуты форматирования и просмотреть результаты. Другие текстовые классы Набора обеспечивают текстовые возможности хранения и расположения. Рисунок 9-1 показывает позицию текстового Набора среди другого текста iOS и графических платформ.
Текстовый Набор дает Вам полный контроль над текстовым рендерингом в элементах пользовательского интерфейса. В дополнение к UITextView
, UITextField
и UILabel
создаются поверх текстового Набора, и он эффективно интегрируется с анимациями, UICollectionView
и UITableView
. Текстовый Набор разработан с полностью расширяемой объектно-ориентированной архитектурой, поддерживающей разделение на подклассы, делегацию и полный набор уведомлений, разрешающих глубокую настройку.
Основные текстовые объекты набора
Пути потока данных среди основных текстовых объектов Набора показаны на рисунке 9-2. Текстовые представления являются экземплярами UITextView
класс, текстовые контейнеры являются экземплярами NSTextContainer
класс, менеджер по расположению является экземпляром NSLayoutManager
класс и текстовое хранение являются экземпляром NSTextStorage
класс. В текстовом Наборе, NSTextStorage
объектно-ориентированные памяти текст, выведенный на экран a UITextView
возразите и размеченный NSLayoutManager
объект в область, определенную NSTextContainer
объект.
NSTextContainer
объект определяет область, где может быть размечен текст. Как правило, текстовый контейнер определяет прямоугольную область, но путем создания подкласса NSTextContainer
можно создать другие формы: круги, пятиугольники или неправильные формы, например. Мало того, что текстовый контейнер описывает схему области, которая может быть заполнена текстом, он поддерживает массив путей Безье, которые являются запретными зонами в его области, где не размечается текст. Поскольку это размечается, текстовые потоки вокруг путей исключения, обеспечивая средние значения для включения графики и других нетекстовых элементов макета.
NSTextStorage
определяет фундаментальный механизм хранения расширенной текстовой системы обработки Набора текста. NSTextStorage
подкласс NSMutableAttributedString
это хранит символы и приписывает управляемый текстовой системой. Это гарантирует, что текст и атрибуты сохраняются в непротиворечивом состоянии через редактирование операций. В дополнение к хранению текста, NSTextStorage
объект управляет рядом клиента NSLayoutManager
объекты, уведомляя их относительно любых изменений в его символах или атрибутах так, чтобы они могли передать и восстановить изображение текста по мере необходимости.
NSLayoutManager
объект организует работу другого текста, обрабатывающего объекты. Это ходатайствует в операциях, преобразовывающих данные в NSTextStorage
возразите против представленного текста в области дисплея представления. Это отображает коды символов Unicode на глифы и наблюдает за расположением глифов в областях, определенных NSTextContainer
объекты.
Для справочной информации о UITextView
, посмотрите Ссылку класса UITextView. NSTextContainer
описан в Ссылке класса NSTextContainer для iOS, NSLayoutManager
в Ссылке класса NSLayoutManager для iOS, и NSTextStorage
в Ссылке класса NSTextStorage для iOS.
Текстовые атрибуты
Текстовый Набор обрабатывает три вида текстовых атрибутов: символьные атрибуты, атрибуты абзацев и атрибуты документа. Символьные атрибуты включают черты, такие как шрифт, цвет и нижний индекс, который может быть связан с отдельным символом или диапазоном символов. Атрибуты абзацев являются чертами, такими как добавление отступа, вкладки и межстрочный интервал. Атрибуты документа включают documentwide черты, такие как формат бумаги, поля, и просматривают процент изменения масштаба.
Символьные атрибуты
Приписанная строка хранит символьные атрибуты как пары ключ/значение в NSDictionary
объекты. Ключ является названием атрибута, представленным идентификатором ( NSString
постоянный) такой как NSFontAttributeName
. Рисунок 9-3 показывает, что приписанная строка со словарем атрибута применилась к диапазону в строке.
Концептуально, каждый символ в приписанной строке имеет связанный словарь атрибутов. Как правило, однако, словарь атрибута применяется к более длинному диапазону символов, выполнению текста. NSAttributedString
класс обеспечивает методы, берущие индекс символа и возвращающие связанный словарь атрибута и диапазон, к которому его значения атрибута применяются, такой как attributesAtIndex:effectiveRange:
.
Можно присвоить любую пару ключ/значение атрибута, которую Вы выбираете к диапазону символов, в дополнение к работе с предопределенными атрибутами. Вы добавляете атрибуты к надлежащему диапазону символов в NSTextStorage
объект с помощью NSMutableAttributedString
метод addAttribute:value:range:
. Можно также создать NSDictionary
объект, содержащий имена и значения ряда пользовательских атрибутов и, добавляет их к диапазону символов на единственном шаге с помощью addAttributes:range:
метод. Для использования пользовательских атрибутов Вам нужен пользовательский подкласс NSLayoutManager
работать с ними. Ваш подкласс должен переопределить drawGlyphsForGlyphRange:atPoint:
метод. Ваше переопределение может сначала вызвать суперкласс для рисования глифа, располагаются и затем рисуют собственные атрибуты на вершине. Также Ваше переопределение может нарисовать глифы полностью Ваш собственный путь.
Атрибуты абзацев
Атрибуты абзацев влияют на способ, которым менеджер по расположению располагает строки текста в абзацы на странице. Текстовая система инкапсулирует атрибуты абзацев в объектах NSParagraphStyle
класс. Значение одного из предопределенных символьных атрибутов, NSParagraphStyleAttributeName
, точки к NSParagraphStyle
объект, содержащий атрибуты абзацев для того диапазона символов. Фиксация атрибута гарантирует это только один NSParagraphStyle
объект принадлежит символам всюду по каждому абзацу.
Атрибуты абзацев включают черты, такие как выравнивание, позиции табуляции, повреждающий строку режим и межстрочный интервал (также известный как ведущий).
Атрибуты документа
Атрибуты документа принадлежат документу в целом. Атрибуты документа включают черты, такие как формат бумаги, поля, и просматривают процент изменения масштаба. Несмотря на то, что текстовая система не имеет никакого встроенного механизма для хранения атрибутов документа, NSAttributedString
методы инициализации такой как initWithRTF:documentAttributes:
может заполнить NSDictionary
возразите, что Вы обеспечиваете атрибутами документа, полученными из потока данных HTML или RTF. С другой стороны, методы, пишущие данные RTF, такой как RTFFromRange:documentAttributes:
, запишите атрибуты документа при передаче ссылки на NSDictionary
объект, содержащий их с сообщением.
Фиксация атрибута
Редактирование приписанных строк может вызвать несоответствия, которые должны быть очищены фиксацией атрибута. Расширения UIKit NSMutableAttributedString
определите fixAttributesInRange:
метод для фиксации несоответствий среди присоединения, символа и атрибутов абзацев. Эти методы гарантируют, чтобы присоединения не оставались после того, как их присоединяемые символы удалены, что символьные атрибуты применяются только к символам, доступным в том шрифте и этом, атрибуты абзацев являются непротиворечивыми всюду по абзацам.
Изменение текстового хранения программно
NSTextStorage
объект служит символьным репозиторием данных для текстового Набора. Формат для этих данных является приписанной строкой, которая является последовательностью символов (в кодировании Unicode) и связанные атрибуты (такие как шрифт, цвет и стиль абзаца). Классы, представляющие приписанные строки, NSAttributedString
и NSMutableAttributedString
, из которых NSTextStorage
подкласс. Как описано в Символьных атрибутах, каждый символ в блоке текста имеет словарь ключей и оценивает связанный с ним. Ключ называет атрибут (такой как NSFontAttributeName
), и присваиваемое значение указывает характеристики того атрибута (такие как Helvetica, с 12 точками).
Существует три этапа к редактированию текстового объекта хранения программно. Первая стадия должна отправить ему a beginEditing
сообщение для объявления о группе изменений.
На втором этапе Вы отправляете ему некоторые сообщения редактирования, такой как replaceCharactersInRange:withString:
и setAttributes:range:
, вызвать изменения в символах или атрибутах. Каждый раз, когда Вы отправляете такое сообщение, текстовый объект хранения вызывает edited:range:changeInLength:
отслеживать диапазон его символов, затронутых, так как это получило beginEditing
сообщение.
На третьей стадии, когда Вы сделаны, изменив текстовый объект хранения, Вы отправляете его endEditing
сообщение. Это вызывает, это к отсылает сообщение делегата textStorage:willProcessEditing:range:changeInLength:
и вызовите его собственное processEditing
метод, фиксируя атрибуты в зарегистрированном диапазоне измененных символов. Посмотрите, что Атрибут Фиксирует для получения информации о фиксации атрибута.
После фиксации его атрибутов текстовый объект хранения отправляет метод делегата textStorage:didProcessEditing:range:changeInLength:
, предоставление делегату возможность проверить и возможно изменить атрибуты. (Несмотря на то, что делегат может изменить текстовые символьные атрибуты объекта хранения в этом методе, он не может изменить сами символы, не оставляя текстовое хранение в противоречивом состоянии.) Наконец, текстовый объект хранения отправляет processEditingForTextStorage:edited:range:changeInLength:invalidatedRange:
обменивайтесь сообщениями каждому связанному менеджеру по расположению — указание диапазона в текстовом объекте хранения, изменившемся, вместе с природой тех изменений. Менеджеры по расположению поочередно используют эту информацию, чтобы повторно вычислить их расположения глифа и восстановить изображение при необходимости.
Работа с объектами шрифта
Компьютерный шрифт является файлом данных в формате, таком как OpenType или TrueType, содержа информацию, описывающую ряд глифов, как описано в Символах и Глифах и различной дополнительной информации, используемой в рендеринге глифа. UIFont
класс обеспечивает интерфейс для получения и установки информации о шрифтах. A UIFont
экземпляр обеспечивает доступ к характеристикам и глифам шрифта. Текстовый Набор комбинирует символьную информацию с информацией о шрифтах для выбора глифов, используемых во время текстового расположения. Вы используете объекты шрифта путем передачи их методам, принимающим их в качестве параметра. Объекты шрифта являются неизменными, таким образом, безопасно использовать их от многократных потоков в Вашем приложении.
Вы не создаете UIFont
объекты с помощью alloc
и init
методы; вместо этого, Вы используете preferredFontForTextStyle:
с постоянным стилем текста или fontWithName:size:
. Можно также использовать дескриптор шрифта для создания шрифта с fontWithDescriptor:size:
. Если существует тот, эти методы проверяют на существующий объект шрифта с заданными характеристиками, возвращая его. Иначе, они ищут данные шрифта, которые требуют, и создают надлежащий объект шрифта.
Стили текста
Стили текста, представленные в iOS 7, являются семантическими описаниями надлежащих использований для шрифтов и реализованы механизмом, известным как Динамический Тип. Стили текста организованы использованием и представлены константами, определенными в UIFontDescriptor.h
, как показано в Таблице 9-1. Фактический шрифт, используемый в цели, описанной стилем текста, может варьироваться на основе многих динамических соображений, включая предпочтение категории размера содержания пользователя, представленное UIApplication
свойство preferredContentSizeCategory
. Для получения шрифта возражают для данного стиля текста, Вы передаете соответствующую константу UIFont
метод preferredFontForTextStyle:
. Для получения дескриптора шрифта для стиля текста передайте константу UIFontDescriptor
метод preferredFontDescriptorWithTextStyle:
. (См. Используя Дескрипторы Шрифта для получения дополнительной информации о дескрипторах шрифта.)
Постоянный | Использование |
---|---|
Шрифт используется для заголовков. | |
Шрифт используется для подзаголовков. | |
Шрифт используется для основного текста. | |
Шрифт используется для сносок. | |
Шрифт используется для стандартных заголовков. | |
Шрифт используется для альтернативных заголовков. |
Стили текста приносят много преимуществ для приложений через Динамический механизм Типа, все из которых улучшают удобочитаемость Вашего текста. Динамический Тип отвечает скоординированным способом к пользовательским настройкам и реагирует на настройки доступности для улучшенной четкости и типа больше обычного размера. Т.е. когда Вы вызываете preferredFontForTextStyle:
, определенный шрифт возвратился, включает черты, варьирующиеся согласно пользовательским настройкам и контексту, включая отслеживание (межсимвольного интервала) корректировки, в дополнение к тому, чтобы быть настроенным для использования, указанного определенным постоянным стилем текста.
Шрифты возвратились, константы стиля текста использования предназначаются, чтобы использоваться для всего текста в приложении кроме текста в элементах пользовательского интерфейса, таких как кнопки, панели и метки. Естественно, необходимо выбрать стили текста, выглядящие правильными в приложении. Также важно наблюдать UIContentSizeCategoryDidChangeNotification
когда пользователь изменяет категорию размера содержания, так, чтобы можно было передать текст. Когда Ваше приложение получает то уведомление, оно должно отправить invalidateIntrinsicContentSize
обменивайтесь сообщениями к представлениям, расположенным Автоматическим Расположением, или отправьте setNeedsLayout
к элементам пользовательского интерфейса, расположенным вручную. И это должно лишить законной силы предпочтенные шрифты или дескрипторы шрифта и получить новые по мере необходимости.
Используя дескрипторы шрифта
Дескрипторы шрифта, которые инстанцируют от UIFontDescriptor
класс, обеспечьте способ описать шрифт со словарем атрибутов, и используются для создания UIFont
объекты. В частности можно сделать a UIFont
объект от дескриптора шрифта, можно получить дескриптор от a UIFont
объект, и можно изменить дескриптор и использовать его для создания нового объекта шрифта. Можно также использовать дескриптор шрифта для указания пользовательских шрифтов, предоставленных приложением.
Дескрипторы шрифта могут быть заархивированы, который является преимуществом, работающим со стилями текста. Вы не должны кэшировать объекты шрифта, указанные стилями текста, потому что они являются динамичными — их характеристики варьируются в течение долгого времени согласно пользовательским настройкам. Но можно кэшировать дескриптор шрифта, чтобы сохранить описание шрифта, и затем разархивировать его позже и использовать его для создания объекта шрифта с теми же характеристиками.
Можно использовать дескрипторы шрифта для запросов системы для доступных шрифтов, соответствующих определенные атрибуты, и затем создающих экземпляры шрифтов, соответствующих те атрибуты, такие как имена, черты, языки и другие функции. Например, можно использовать дескриптор шрифта для получения всех шрифтов, соответствующих данное имя семейства шрифтов, с помощью фамилий, определенных стандартом CSS, как показано в Перечислении 9-1.
Соответствие имени Семейства шрифтов перечисления 9-1
UIFontDescriptor *helveticaNeueFamily = |
[UIFontDescriptor fontDescriptorWithFontAttributes: |
@{ UIFontDescriptorFamilyAttribute: @"Helvetica Neue" }]; |
NSArray *matches = |
[helveticaNeueFamily matchingFontDescriptorsWithMandatoryKeys: nil]; |
matchingFontDescriptorsWithMandatoryKeys:
метод как показано возвращает массив дескрипторов шрифта для всех шрифтов Helvetica Neue в системе, такой как HelveticaNeue
, HelveticaNeue-Medium
, HelveticaNeue-Light
, HelveticaNeue-Thin
, и т.д.
Можно изменить шрифты, возвращенные preferredFontForTextStyle:
путем применения символьных черт, такой как полужирных, курсивных, расширенных и сжатых. Можно использовать дескрипторы шрифта для изменения определенных черт, как показано в Перечислении 9-2.
Модификация черты Шрифта перечисления 9-2
UIFontDescriptor *fontDescriptor = |
[UIFontDescriptor preferredFontDescriptorWithTextStyle: UIFontTextStyleBody]; |
UIFontDescriptor *boldFontDescriptor = |
[fontDescriptor fontDescriptorWithSymbolicTraits: UIFontDescriptorTraitBold]; |
UIFont *boldFont = [UIFont fontWithDescriptor: boldFontDescriptor size: 0.0]; |
Этот фрагмент кода сначала получает дескриптор шрифта для стили основного текста, затем изменяет тот дескриптор шрифта для указания полужирной черты, и наконец использует UIFont
метод класса fontWithDescriptor:size:
для возврата фактического шрифта возражают для стили основного текста с полужирной чертой. Передача значения размера 0.0
с fontWithDescriptor:size:
указывает, что атрибут размера первоначально возвратился с дескриптором шрифта, сохраняется. Это поведение желаемо, конечно, потому что размер шрифта определяется динамическим механизмом типа.
Активирование опций шрифта
Другое важное использование для дескрипторов шрифта должно активировать и выбрать среди функций шрифта. Функции шрифта являются типографскими атрибутами шрифта, управляющими аспектами его появления, когда его глифы представляются текстовой системой. Функции шрифта доступны для шрифта, только если разработчик шрифтов принимает решение включать их. В то время как другие характерны для многих шрифтов, некоторые функции шрифта доступны в немногих шрифтах. Кроме того, различные версии того же шрифта, установленного на различных платформах, могут варьироваться по их доступным функциям шрифта.
Функции шрифта сгруппированы в вызванные типы функции категорий, в которых отдельные селекторы функции выбирают определенные настройки функции. Типы функции могут быть монопольными или неисключительными. Если тип функции является монопольным, можно выбрать только один из доступных селекторов функции за один раз, такой как, должны ли числа быть пропорциональными или фиксированная ширина. Если тип функции неисключителен, можно включить любое число селекторов функции сразу. Например, для типа функции лигатуры можно выбрать любую комбинацию доступных классов лигатур, которые поддерживает шрифт.
В то время как другие являются неконтекстными, некоторые функции являются контекстными. Способ, которым контекстные функции применяются к глифу, зависит от позиции глифа по сравнению со смежными глифами. Одним из мощных аспектов текстовой возможности расположения системы является своя возможность применить сложную контекстную обработку автоматически.
Неконтекстные функции применяются таким же образом к глифу независимо от смежных глифов. Эти функции включают выбор альтернативных наборов глифа, чтобы дать тексту различное появление и замену глифа в целях математического набора или улучшения типографской изощренности.
Например, код в Перечислении 9-3 активирует два типа функции, определенные шрифтом Носителя Helvetica Neue.
Перечисление 9-3 , активирующее опции шрифта
NSArray *timeFeatureSettings = @[ |
@{ |
UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType), |
UIFontFeatureSelectorIdentifierKey: @(kProportionalNumbersSelector) |
}, |
@{ |
UIFontFeatureTypeIdentifierKey: @(kCharacterAlternativesType), |
UIFontFeatureSelectorIdentifierKey: @(2) |
}]; |
UIFont *originalFont = [NSFont fontWithName: @"HelveticaNeue-Medium" size: 12.0]; |
UIFontDescriptor *originalDescriptor = [originalFont fontDescriptor]; |
UIFontDescriptor *timeDescriptor = [originalDescriptor |
fontDescriptorByAddingAttributes: @{ |
UIFontDescriptorFeatureSettingsAttribute: timeFeatureSettings }]; |
UIFont *timeFont = [UIFont fontWithDescriptor: timeDescriptor size: 12.0]; |
Код в Перечислении 9-3 активирует тип функции интервала числа (представленный константой kNumberSpacingType
), выбирая цифры пропорциональной ширины (kProportionalNumbersSelector
), и символьный тип функции альтернатив (kCharacterAlternativesType
), со значением ключа идентификатора селектора функции 2
. Константы, используемые в этом примере для представления типов функции шрифта и селекторов, объявляются как перечисления в заголовочном файле SFNTLayoutTypes.h
в Базовой текстовой платформе (CoreText/CoreText.h
). В случае символьного типа альтернатив нет никаких предопределенных констант для представления идентификаторов селектора функции, таким образом, Вы просто используете определенное с помощью шрифта числовое значение.
Поскольку функции шрифта определяются шрифтом, самый надежный способ решить, что поддерживавшие функции должны запросить шрифт непосредственно. Можно сделать это использование CTFontCopyFeatures
функция в Базовом тексте, как показано в Перечислении 9-4.
Перечисление 9-4 , запрашивающее функции шрифта
UIFont *font = [UIFont fontWithName: @"HelveticaNeue-Medium" size: 12.0]; |
CFArrayRef fontFeatures = CTFontCopyFeatures((__bridge CTFontRef) font); |
NSLog(@"properties = %@", fontFeatures); |
Перечисление 9-5 показывает массив функций шрифта, следующих CTFontCopyFeatures
функция в Перечислении 9-4, поскольку это выведено на экран на консольном журнале.
Перечисление 9-5 типичный результат CTFontCopyFeatures
Функция
properties = ( |
{ |
CTFeatureTypeExclusive = 1; |
CTFeatureTypeIdentifier = 6; |
CTFeatureTypeName = "Number Spacing"; |
CTFeatureTypeNameID = 266; |
CTFeatureTypeSelectors = ( |
{ |
CTFeatureSelectorDefault = 1; |
CTFeatureSelectorIdentifier = 0; |
CTFeatureSelectorName = "No Change"; |
CTFeatureSelectorNameID = 264; |
}, |
{ |
CTFeatureSelectorIdentifier = 1; |
CTFeatureSelectorName = "Proportional Numbers"; |
CTFeatureSelectorNameID = 267; |
} |
); |
}, |
{ |
CTFeatureTypeExclusive = 1; |
CTFeatureTypeIdentifier = 17; |
CTFeatureTypeName = "Character Alternatives"; |
CTFeatureTypeNameID = 262; |
CTFeatureTypeSelectors = ( |
{ |
CTFeatureSelectorDefault = 1; |
CTFeatureSelectorIdentifier = 0; |
CTFeatureSelectorName = "No Change"; |
CTFeatureSelectorNameID = 264; |
}, |
{ |
CTFeatureSelectorIdentifier = 1; |
CTFeatureSelectorName = "Alternate Punctuation"; |
CTFeatureSelectorNameID = 263; |
}, |
{ |
CTFeatureSelectorIdentifier = 2; |
CTFeatureSelectorName = "Numbers Punctuation"; |
CTFeatureSelectorNameID = 265; |
} |
); |
} |
) |
В этом случае результат показывает, что эта версия шрифта Носителя Helvetica Neue имеет две функции шрифта: Number Spacing
и Character Alternatives
. При использовании дескрипторов шрифта для активирования опций шрифта и выбора среди их настроек, самые важные значения в этом результате являются идентификаторами типов функции и идентификаторами селектора функции. Вы добавляете эти значения к массиву словарей, представляющих настройки функции шрифта, и Вы используете тот массив в качестве значения UIFontDescriptorFeatureSettingsAttribute
, переданный поочередно fontDescriptorByAddingAttributes:
или fontDescriptorWithFontAttributes:
методы, как показано в Перечислении 9-3. Перечисляемые значения констант, показанных в том перечислении, коррелируют с числовыми значениями идентификаторов типов функции и идентификаторов селектора функции, возвращенных CTFontCopyFeatures
функция.
Как показано в Перечислении 9-5, массиве функций шрифта, следующих CTFontCopyFeatures
функционируйте также показывает, является ли тип функции монопольным или не и какой селектор функции является значением по умолчанию. И, конечно, имя типа функции и значения имени селектора функции обеспечивают человекочитаемую идентификацию для доступных функций шрифта и их настройки.
Запросы метрик шрифта
UIFont
когда та информация доступна, определяет много методов для доступа к данным метрик шрифта. Свойства такой как ascender
, capHeight
, xHeight
, и т.д. все соответствуют данным метрик стандартного шрифта. Рисунок 9-4 показывает, как метрики шрифта применяются к размерностям глифа, и Таблица 9-2 перечисляет имена свойства, коррелирующие с различными метриками. См. описания свойства для более определенной информации.
Разметка текста
Менеджер по расположению объект, который инстанцируют от NSLayoutManager
класс, центральный объект управления для текстового дисплея в текстовом Наборе. Менеджер по расположению выполняет следующие действия:
Текстовое хранение средств управления и текстовые контейнерные объекты
Генерирует глифы от символов
Вычисляет расположения глифа и хранит информацию
Управляет диапазонами глифов и символов
Рисует глифы в текстовых представлениях, когда требуется представлением
Вычисляет прямоугольники ограничительной рамки для строк текста
Расстановка переносов средств управления
Управляет свойства глифа и символьные атрибуты
В парадигме контроллера представления модели менеджер по расположению является контроллером. NSTextStorage
, подкласс NSMutableAttributedString
, обеспечивает часть модели, содержа строку текстовых символов с атрибутами, такими как гарнитура, стиль, цвет и размер. NSTextContainer
может также считаться частью модели, потому что это моделирует геометрическое расположение страницы, на которой размечается текст. UITextView
(или другой UIView
объект), обеспечивает представление, в котором выведен на экран текст. NSLayoutManager
служит контроллером для текстовой системы, потому что это переводит символы в текстовом объекте хранения в глифы, размечает их в строках согласно размерностям одного или более текстовых контейнерных объектов и координирует текстовый дисплей в одном или более текстовых объектах представления.
Процесс создания макета
Менеджер по расположению выполняет текстовое расположение на двух отдельных шагах: генерация глифа и расположение глифа. Менеджер по расположению выполняет оба шага расположения лениво, т.е. по мере необходимости. Соответственно, некоторые NSLayoutManager
методы заставляют генерацию глифа происходить, в то время как другие не делают, и то же является истиной с расположением глифа. После того, как это генерирует глифы и после того, как это вычисляет их расположения расположения, менеджер по расположению кэширует информацию для улучшения производительности последующих вызовов.
Менеджер по расположению глифы кэшей, атрибуты и информация макета. Это отслеживает диапазоны глифов, лишенных законной силы изменениями в символах в текстовом хранении. Существует два пути, которыми может быть автоматически лишен законной силы диапазон символов: если этому нужны сгенерированные глифы или если этому нужны размеченные глифы. Если Вы предпочитаете, можно вручную лишить законной силы или глиф или информацию макета. Когда менеджер по расположению получает сообщение, требующее знания глифов или расположения в лишенном законной силы диапазоне, это генерирует глифы или повторно вычисляет расположение по мере необходимости.
Генерация прямоугольников фрагмента строки
Менеджер по расположению кладет текст в NSTextContainer
объект в строках глифов. Расположение этих строк в текстовом контейнере определяется его формой и любыми путями исключения, которые это содержит. Везде, где прямоугольник фрагмента строки пересекает область, определенную путем исключения, строки в тех частях должны быть сокращены или фрагментированы; если бы существует разрыв через весь регион, строки, которые наложились бы, это должно быть смещено для компенсации.
Менеджер по расположению предлагает прямоугольник для данной строки и затем просит, чтобы текстовый контейнер скорректировал прямоугольник для адаптации. Предложенный прямоугольник обычно охватывает текстовый ограничительный прямоугольник контейнера, но это может быть более узким или более широким, и это может также лечь частично или полностью вне ограничительного прямоугольника. Сообщение, что менеджер по расположению отправляет текстовый контейнер для корректировки предложенного прямоугольника, lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:
, который возвращает самый большой прямоугольник, доступный для предложенного прямоугольника, на основе направления, в котором размечается текст. Это также возвращает прямоугольник, содержащий любое остающееся пространство, такое как пространство, оставленное с другой стороны дыры или разрыва в текстовом контейнере.
Менеджер по расположению вносит одну окончательную корректировку, когда она фактически вмещает текст в прямоугольник. Эта корректировка является мелкой суммой, фиксированной текстовым контейнером, названным дополнением фрагмента строки, определяющим часть на каждом конце прямоугольника фрагмента строки, оставленного незаполненный. Текст вставляется в прямоугольнике фрагмента строки этой суммой (сам прямоугольник незатронут). Дополнение допускает небольшую корректировку текстовой области контейнера в краях (и вокруг любых дыр) и сохраняет текст от непосредственно примыкающего любой другой графикой выведенный на экран около области. Можно изменить дополнение от его значения по умолчанию с lineFragmentPadding
свойство. Обратите внимание на то, что дополнение фрагмента строки не является подходящими средними значениями для выражения полей. Для полей документа необходимо установить UITextView
позиция объекта и размер в его представлении включения. И для полей текста, необходимо установить textContainerInset
свойство текстового представления. Кроме того, можно установить значения добавления отступа для использования отдельных абзацев NSMutableParagraphStyle
свойства такой как headIndent
.
В дополнение к возврату самого прямоугольника фрагмента строки возвращается менеджер по расположению, прямоугольник вызвал используемый прямоугольник. Это - часть прямоугольника фрагмента строки, фактически содержащего глифы или другие метки, которые будут нарисованы. Условно, оба прямоугольника включают дополнение фрагмента строки и пространство шпона (который вычисляется от метрик высоты строки шрифта и параметров межстрочного интервала абзаца). Однако расстояние между абзацами (перед и после) и любое пространство, добавленное вокруг текста, такого как вызванный расположенным с интервалами центром текстом, включено только в прямоугольнике фрагмента строки и не включено в используемый прямоугольник.
Указание путей исключения
Текстовый контейнер поддерживает массив UIBezierPath
объекты, представляющие исключение, соединяют каналом в ограничительном прямоугольнике получателя. Когда менеджер по расположению отправляет текстовый контейнер a lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:
сообщение, предлагающее прямоугольник фрагмента строки, пересекающий одну из областей, определенных путями исключения, текстовый контейнер возвращает скорректированный прямоугольник фрагмента строки, исключая ту область. Этот процесс проиллюстрирован на рисунке 9-6.
Указание многостраничных и многостолбцовых разметок
В самом простом случае текстовые объекты Набора сконфигурированы отдельно, т.е. один текстовый объект хранения, один текстовый контейнер и один менеджер по расположению, как показано на рисунке 9-6. Эта конфигурация инстанцируют автоматически при перетаскивании текстового представления от библиотеки объектов в Интерфейсном Разработчике. UITextView
объект продает другие объекты и соединяет их вместе. Можно также создать это расположение в коде, как показано в Перечислении 9-6.
Можно также создать это расположение в коде, как показано в Перечислении 9-6. Этот код мог быть в контроллере представления, например, подклассе UIViewController
, это имеет NSTextContainer
свойство называют textContainer
.
Создание объекта перечисления 9-6 для единственного текстового потока
NSTextStorage* textStorage = [[NSTextStorage alloc] initWithString:string]; |
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; |
[textStorage addLayoutManager:layoutManager]; |
self.textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size]; |
[layoutManager addTextContainer:self.textContainer]; |
UITextView* textView = [[UITextView alloc] initWithFrame:self.view.bounds textContainer:self.textContainer]; |
[self.view addSubview:textView]; |
Эта конфигурация ограничивается при наличии только одного текстового контейнера и одного текстового представления. В таком расположении текстовые потоки, непрерывные в области, определяются текстовым контейнером. Разрывы страницы, многостолбцовое расположение и более сложные макеты не могут быть размещены этим расположением.
При помощи многократных текстовых контейнеров, каждого со связанным текстовым представлением, расположения более сложного макета возможны. Например, к повреждениям страницы поддержки, приложение может сконфигурировать текстовые объекты как показано на рисунке 9-7.
Каждый текстовый контейнер соответствует странице документа. Представления, выводящие на экран текст, могут быть встроены в пользовательский объект представления, что Ваше приложение обеспечивает как фон для текстовых представлений. Это пользовательское представление, в свою очередь, может быть встроен в a UIScrollView
объект позволить пользователю просмотреть страницы документа путем прокрутки.
Многостолбцовый документ может быть смоделирован с подобным расположением объектов, как показано на рисунке 9-8.
Вместо того, чтобы иметь один текстовый контейнер соответствуют единственной странице, существует теперь два текстовых контейнера — один для каждого столбца на странице. Каждый текстовый контейнер управляет частью документа. Поскольку текст выведен на экран, глифы сначала размечаются в верхнем левом контейнере. Когда больше нет комнаты в том представлении, менеджер по расположению сообщает его делегату, что это закончило заполнять контейнер. Делегат может проверить, чтобы видеть, существует ли больше текста, который должен быть размечен и добавить другой текстовый контейнер при необходимости. Менеджер по расположению продолжает для разметки текста в следующем контейнере, уведомляет делегата по окончании и т.д. Снова, пользовательское представление (изображенный как синий прямоугольник) обеспечивает холст для этих столбцов текста.
Мало того, что у Вас могут быть многократные текстовые контейнеры, Вы можете также иметь многократный NSLayoutManager
объекты, получающие доступ к тому же текстовому хранению. Рисунок 9-9 иллюстрирует объектное расположение с многократными менеджерами по расположению. Эффект этого расположения состоит в том, чтобы обеспечить многократные представления того же текста. Если пользователь изменяет текст в виде сверху, изменение сразу отражается в виде снизу (предполагающий, что расположение изменения в границах вида снизу).