Руководство по программированию документо-ориентированных приложений для Mac

Проектирование document-based приложений

Документы - это контейнеры для пользовательских данных. Документы могут храниться локально или в iCloud.


В документной архитектуре Cocoa используется паттерн Model-View-Controller (MVC):
  • объекты модели инкапсулируют данные приложения;
  • объекты представления отображают данные;
  • контроллеры действуют как посредники между объектами модели и представлениями.

Документ это экземпляр дочернего класса NSDocument (в iOS это UIDocument). В дочернем классе нужно переписать методы для чтения и записи документа. Фреймворк (AppKit) предоставляет данные методу чтения и тот загружает их в объектную модель. Обратное метод записи передает данные фреймворку, а тот их записывает либо локально либо в iCloud.

Документная архитектура предоставляет следующие возможности:
  • autosaving,
  • asynchronous document reading and writing, 
  • file coordination, 
  • multilevel undo support.

Для расширения предоставляются следующие механизмы:
  • delegation, 
  • subclassing and overriding existing methods with custom implementations,
  • integration of custom objects.

NSMetadataQuery используются для нахождения документов хранящихся в iCloud.

В контексте Cocoa документ это интерфейс NSDocument который знает как представить хранящиеся данные так чтобы их можно было отобразить в окне. Документный объект знает как считать данные из файла и создать object graph в памяти для модели данных документа. Также он знает как модифицировать модель данных и записать данные обратно на диск.

Document file, object, and data model

Используя iCloud документы могут разделяться между пользователями компьютера и iOS устройствами. Система сама синхронизирует изменения в данных документа без вмешательства пользователя.

Очень важно на ранем этапе выбрать базовый стиль приложения, потому что от этого сильно зависит дальнейший процесс проектирования. Это может single-window utility приложение типа Калькулятора или library-style “shoebox” приложение типа iPhoto. Если же есть необходимость для пользователя создавать множество дискретных наборов данных, которые могут редактироваться в графической среде и храниться в файлах, то надо выбирать document-based app.

Документная архитектура Cocoa предоставляет фреймворк для документо-ориентированных приложений позволяющий делать следующее:
  • Создание новых документов. The first time the user chooses to save a new document, it presents a dialog in which the user names and saves the document in a disk file in a user-chosen location. 
  • Открытие существующих документов хранящихся в файлах. A document-based app specifies the types of document files it can read and write, as well as read-only and write-only types. It can represent the data of different document types internally and display the data appropriately.
  • Автоматическое сохранение документов. Document-based apps can adopt autosaving in place, and its documents are automatically saved at appropriate times so that the data the user sees on screen is effectively the same as that saved on disk. Saving is done safely, so that an interrupted save operation does not leave data inconsistent. To avoid automatic saving of inadvertent changes, old files are locked from editing until explicitly unlocked by the user.
  • Асинхронное чтение и запись данных документа. Reading and writing are done asynchronously on a background thread, so that lengthy operations do not make the app’s user interface unresponsive. In addition, reads and writes are coordinated using the NSFilePresenter protocol and the NSFileCoordinator class to reduce version conflicts.
  • Manage multiple versions of documents. Autosave creates versions at regular intervals, and users can manually save a version whenever they wish. Users can browse versions and revert the document’s contents to a chosen version using a Time Machine–like interface. The version browser is also used to resolve version conflicts from simultaneous iCloud updates.
  • Печать документов. Users can specify various page layouts in the print dialog and page setup dialog.
  • Track changes and set the document’s edited status. The document manages its edited status and implements multilevel undo and redo.
  • Validate menu items. The document enables or disables menu items automatically, depending on its edited status and the applicability of the associated action methods.
  • Handle app and window delegation. Notifications are sent and delegate methods called at significant life cycle events, such as when the app terminates.

Основные классы в документной архитектуре:
  • NSDocument - создает, представляет, и хранит данные документа;
  • NSWindowController - управляет окном в котором отображается документ;
  • NSDocumentController - управляет всеми документами в приложении.

Технология iCloud storage позволяет предоставлять множеству компьютеров на которых запущено ваше document-based app общий доступ к документам и другим данным приложения. Есть два типа iCloud storage: document storage и key-value data storage. Например тексты и иллюстрации для книги можно хранить в document storage, а текущий номер страницы читателя в key-value storage. NSDocument реализует file coordination, version management и разрешение конфликтов среди документов.

Документная архитектура поддерживает App Sandbox - технологию управления доступом, которая защищает против кражи, повреждения, и удаления пользовательских данных, если вредоносный код эксплуатирует ваше приложение. NSDocument автоматически работает с Powerbox чтобы сделать items доступными вашему приложению, когда пользователь открывает и сохраняет документы или использует drag and drop. NSDocument также предоставляет поддержку удержания документов в вашем sandbox, когда пользователь перемещает их в Finder. (App Sandbox Design Guide)

Модель данных документа это объект или граф взаимосвязанных объектов, который содержит данные для отображения и манипулирования. 

Документная архитектура Cocoa использует паттерн проектирования Model-View-Controller.

Document object это контроллер для управления объектами в модели данных документа. Каждый document object это наследник NSDocument спроектированный специально управлять конкретным типом модели данных. Document-based apps могут управлять одним или несколькими типами документов, каждый тип со своей моделью данных и соответствующим наследником NSDocument. В app’s bundle хранится information property list файл <appName>-Info.plist в котором указывается информация, которая может использоваться в runtime режиме. Document-based apps используют этот файл чтобы указать типы документов, которые могут отображаться или редактироваться в приложении. Например, когда NSDocumentController создает новый документ или открывает уже существующий, он ищет в property list такие вещи как:
  • document class, который может обработать тип документа;
  • uniform type identifier (UTI) для типа;
  • может ли приложение только отобразить или еще редактировать документ.

Любые объекты, которые являются persistent state частью документа должны рассматриваться как часть документной модели. Например, Sketch sample app имеет наследника NSDocument - SKTDocument. У объектов данного класса есть массив объектов SKTGraphic, который содержит данные описывающие формы, которые могут быть нарисованы приложением Sketch. Поэтому они формируют модель данных документа. Помимо SKTGraphic объектов, SKTDocument содержит дополнительные данные типа front-to-back ordering объектов SKTGraphic.

Чтение и запись документов находится в области отвественности класса SKTDocument. Sketch реализует NSDocument data-based writing метод, который преобразует объекты модели данных в NSData объект и записывает его в файл. Метод чтения обратно реконструирует модель данных в памяти из NSData объекта.

Есть три способа реализации чтения и записи данных в document-based app:
  • Чтение и запись native object типов. NSDocument has methods that read and write NSData and NSFileWrapper objects natively. You must override at least one writing method to convert data from the document model’s internal data structures into an NSData object or NSFileWrapper object in preparation for writing to a file. Conversely, you must also override at least one reading method to convert data from an NSData or NSFileWrapper object into the document model’s internal data structures in preparation for displaying the data in a document window.
  • Использование Core Data. If you have a large data set or require a managed object model, you may want to use NSPersistentDocument to create a document-based app that uses the Core Data framework. Core Data is a technology for object graph management and persistence. One of the persistent stores provided by Core Data is based on SQLite. Although Core Data is an advanced technology requiring an understanding of Cocoa fundamental design patterns and programming paradigms, it brings many benefits to a document-based app, such as:
    • Incremental reading and writing of document data
    • Data compatibility for apps with iOS and OS X versions
  • Custom object форматы. If you need to read and write objects without using NSData and NSFileWrapper, you can override other NSDocument methods to do so, but your code needs to duplicate what NSDocument does for you. Naturally, this means your code will have greater complexity and a greater possibility of error.

Используя iCloud, общий доступ к документу предоставляется document-based приложениям на OS X и iOS. Однако между платформами есть различия, которые нужно учитывать:
  • Если вы используете rich text format (RTF) в качестве формата документа на OS X, то это не будет работать на iOS потому что её текстовая система не имеет встроенной поддержки формата rich text (хотя конечно вы можете реализовать такую поддержку в вашем iOS приложении). 
  • default coordinate system для каждой платформы различается, что может повлиять на рисованный контент.
  • If you archive a document’s model object graph, you may need to perform suitable conversions using NSCoder methods when you encode and decode the model objects.
  • Есть значительные различия между классами представляющими цвета (UIColor и NSColor), изображения (UIImage и NSImage), и Bezier paths (UIBezierPath и NSBezierPath). Например, объекты NSColor определены в терминах color space (NSColorSpace), а в UIKit нет класса color space.

Одна из стратегий обеспечения совместимости заключается в том чтобы опуститься на низкоуровневый фреймворк, который используется обеими платформами. Например, на стороне iOS, UIColor определяет CIColor свойство содержащее Core Image object представляющий цвет; на OS X стороне, ваше приложение создает объект NSColor из CIColor объекта используя метод colorWithCIColor:.

Классы обеспечивающие поддержку документо-ориентированных приложений

В документной архитектуре есть три главных класса: NSDocumentController, NSDocument, и NSWindowController. Объекты этих классов управляют работой по созданию, открытию, сохранению и управлению документами. Они упорядочены в многоуровневую one-to-many свзязь. Приложение может иметь только один NSDocumentController, который создает и управляет объектами NSDocument (по одному на каждую New или Open операцию). NSDocument создает и управляет одним или несколькими объектами NSWindowController.


Приложение Cocoa содержит несколько ключевых объектов в дополнение к трем основным классам в документной архитектуре.


--