TL; DR: RTFD кодирует изображения в формате PNG, но вместо этого вы можете сделать так, чтобы они кодировали JPG, чтобы сэкономить место.Пользовательский формат может быть лучше и проще, хотя, если у вас есть время на его создание.
NSAttributedString
может кодировать в HTML, RTF, RTFD, обычный текст, различные форматы Office / Word,и т.д. Учитывая, что каждый из них является официальным форматом с официальной спецификацией, которой необходимо следовать, мало что можно сделать с точки зрения экономии места, кроме:
- Выбор поддерживаемого формата, который работаетлучше всего подходит для ваших случаев использования и имеет наименьшую площадь.
ИЛИ
Написание собственного формата.
Подход 1: RTFD
Из поддерживаемого формата RTFD действительно лучше всего подходит для вашего случая использования, поскольку включает поддержку вложений, таких как изображения,Не стесняйтесь опробовать другие включенные форматы, описания которых приведены ниже в разделе «Другие форматы».
Сохранение в виде данных, например, с использованием метода rtfd (from: documentAttributes :) и как частьCodable структуры, приводит к очень большой строке, намного больше, чем сам контент, особенно при вставке изображения в NSTextView.Например, вставка изображения размером 200 КБ приведет к получению файла JSON размером 5 МБ.
Чтобы понять, что здесь происходит, попробуйте следующий код:
do {
let rtfd = try someAttributedString.rtfdFileWrapper(from: NSRange(location: 0, length: someAttributedString.length), documentAttributes: [:])
rtfd?.write(to: URL(fileURLWithPath: "/Users/yourname/someFolder/RTFD.rtfd"), options: .atomic, originalContentsURL: nil)
} catch {
print("\(error)")
}
Когда вы звоните rtfd(from:documentAttributes:)
, вы получаете квартиру Data
.Эти плоские данные затем могут быть где-то закодированы и считаны обратно в NSAttributedString
.Но не заблуждайтесь: RTFD - это формат пакета («D» обозначает каталог).Таким образом, вместо вызова rtfdFileWrapper(from:documentAttributes:)
и записи этого в URL
с расширением rtfd
, мы можем увидеть фактический формат пакета, который rtfd(from:documentAttributes:)
реплицирует, но как каталог вместо необработанных данных.В Finder щелкните правой кнопкой мыши созданный файл и выберите «Показать содержимое пакета».
В пакете RTFD содержится файл RTF для указания текста и атрибутов, а также копия каждого вложения.Так почему же ваш пример был намного больше?В моих тестах ответ, кажется, заключается в том, что RTFD ожидает найти свои изображения в формате PNG.При вызове rtfdFileWrapper(from:documentAttributes:)
или rtfd(from:documentAttributes:)
любые вложения изображений выглядят записанными в виде файлов PNG, которые занимают значительно больше места.Это происходит потому, что ваше изображение обернуто в NSImage
до того, как оно будет обернуто в NSTextAttachment
.NSImage
может записывать данные изображения в других форматах, включая большие форматы, такие как PNG.
Я предполагаю, что изображение, которое вы пробовали, было в сжатом формате, таком как JPEG, и NSAttributedString
записало егов RTFD как PNG.
Использование JPEG
вместо
Предполагая, что вы в порядке со сжатым изображением и не имеете информации, такой как альфа-канал, вам следуетбыть в состоянии создать файл RTFD с jpg
изображениями.
Например, мне удалось получить файл RTFD до 2,8 МБ с более чем 12 МБ (большое изображение), просто заменив сгенерированное изображение PNG наоригинальный JPG один.Первоначально это было неприемлемо для TextEdit, но затем я изменил расширение файла изображения на .png
(даже если это все еще JPG), и он принял его.
В коде это было еще проще.Возможно, вам удастся сойти с рук, просто изменив способ добавления вложенных изображений.
// Don't do this unless you want PNG
let image = NSImage(contentsOf: ...) // NSImage will write to a larger PNG file
let attachment = NSTextAttachment()
attachment.image = image
// Do this if you want smaller files
let image = try? Data(contentsOf: ...) // This will remain in raw JPG format
let attachment = NSTextAttachment(data: image, ofType: kUTTypeJPEG as String) // Explicitly specify JPG
Затем, когда вы создадите новый NSAttributedString
с этим NSTextAttachment
и добавите его к NSTextStorage
, записывая данные RTFDбудет значительно меньше.
Конечно, вы не можете контролировать этот процесс, если полагаетесь на пользовательский интерфейс / API Какао для прикрепления изображений.Это может усложнить процесс, и вам, возможно, придется прибегнуть к изменению сгенерированных данных путем замены изображений.
Подход 2. Пользовательский формат
Описанный выше подход может быть неудобным из-за отсутствияиметь контроль над процессом добавления вложений и требовать плоских данных.В этом случае пользовательский формат может быть лучше.
Ничто не мешает вам разработать собственный формат (двоичный, текстовый, пакетный и т. Д.) И затем написать для него кодер.Вы можете указать определенный формат изображения или поддерживать различные.Тебе решать.И если вы не любитель текстовых редакторов, вам, вероятно, не нужно постоянно хранить все атрибуты, например, шрифт.
Мне также интересно, есть ли допустимая опция двоичного кодирования для Codable.
Во-первых, обратите внимание, что NSAttributedString
является классом Objective-C (при использовании на платформах Apple) и соответствует NSSecureCoding
вместо Codable
.
Обратите внимание, чтоВы не можете расширить NSAttributedString
, чтобы соответствовать Codable
, потому что требование init(from:)
для Decodable
может быть выполнено только при условии, что инициализатор будет включен также во все подклассы.Поскольку этот класс не final
, это означает, что он может быть удовлетворен только required init
.Обязательные инициализаторы могут быть указаны только в исходном объявлении, а не в расширениях.
По этой причине, если вы хотите согласовать его с Codable
, вам нужно будет использовать объект-оболочку.enumerateAttributes(in:options:using:)
должно быть полезно для получения атрибутов и необработанных символов, которые необходимо кодировать, но вы должны быть уверены, что обратите внимание и на изображения.
Что касается кодирования в двоичном коде, Codable
совершенно не зависит от формата, поэтому вы можете написать свой собственный объект, соответствующий Coder
, который делает все, что вы хотите, в том числе хранить все, используя необработанные байты.
В стороне: другие форматы
Вот краткое изложение других поддерживаемых форматов (в порядке размера).В этих тестах я использовал очень маленькую строку "Hello World! There's so much to see!"
в системном шрифте.После каждого описания формата (в скобках) указывается количество байтов для хранения этой строки.
- Обычный текст может хранить указанный выше формат в 36 байтах (1 для каждого символа),но не будет сохранять атрибуты или вложения.(36 байт)
- RTF кажется наиболее легковесным, если вам нужно сохранить атрибуты, но не вложения.(331 байт)
- HTML Следующий самый легкий, но на самом деле не предназначен для формата хранения.По моему опыту, некоторые атрибуты, такие как межстрочный интервал, теряются при конвертации в HTML
NSAttributedString
.(536 байт) - Binary Plist , который создается при использовании
NSKeyedArchiver
, является хорошим вариантом, если вам нужна только совместимость с платформами Apple и вам не нравятся указанные выше форматы.Этот формат также поддерживает изображения, но, как правило, по-прежнему больше, чем указано выше (и RTFD).(648 байт) - Веб-архив следующий по размеру, но я не рекомендую использовать его, поскольку WebKit его устарел.Safari все еще использует его для некоторых вещей.(784 байта)
- Слово ML , вероятно, полезно только для тех, кто уже знает, что им это нужно.Этот формат и все, что находится под ним, как правило, будет содержать набор шаблонов, которые будут становиться меньшим процентным содержанием файла по мере добавления текста.(~ 1,2 МБ)
- Открытый документ (OASIS) меньше, чем большинство форматов Word, но вы, вероятно, не использовали бы его без веской причины.(~ 2,4 МБ)
- Office Open XML Это другой формат, который вы используете, только если вам нужен именно этот формат.(~ 3,5 МБ)
- Документ (Microsoft Word) Этот файл очень большой по сравнению с небольшими объемами текста.В то время как я ожидал, что этот формат разрешает изображения, в моем тестировании размер файла фактически не увеличивался, когда я добавлял один.(~ 19,4 МБ)
- Mac Simple Text , кажется, всегда генерирует ошибку.(N / A)
Заключительное примечание
В конце концов, опыт кодирования для NSAttributedString
должен улучшиться, поскольку Foundation продолжает адаптироваться к Swift, а не к Objective-C.Вы можете представить себе день, когда NSAttributedString
или какой-либо аналогичный тип Swifty соответствует Codable
из коробки и затем может быть связан с любым форматом файла Coder
.