Использование Табличного Представления

Добрый день! Я уже довольно давно пытаюсь заставить себя выучить другой язык программирования/платформу для Mac OS X/iOS. Меня особенно интересует разработка приложений с нативным графическим интерфейсом, поскольку консольные приложения можно разрабатывать на чем угодно, от C и C++ до модного сейчас Nodejs. Как показала практика, кроссплатформенные фреймворки типа Qt здесь не очень подходят хотя бы потому, что они не обеспечивают тот нативный Look and Feel, к которому привыкли пользователи этой ОС.

В хабе имеется достаточное количество материалов по языку Objective-C и фреймворку Cocoa. С точки зрения GUI интерес представляет именно Cocoa, но здесь большинство статей ограничиваются кнопками и текстовыми полями.

Попробую исправить это недоразумение и описать работу с Table View на примере приложения, отображающего список процессов.

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

Буду рад услышать ошибки и конструктивную критику в комментариях.

Кому интересно, добро пожаловать под кат.



Теория

Для разработки нам понадобятся некоторые знания о Table View. Начнем с них.

Подробное описание работы с Table View приведено в [1], здесь я ограничусь кратким изложением основных идей.



Типы представлений таблиц
Существует два типа представления таблицы:
  • клеточный — каждая ячейка таблицы представлена подклассом НСКелл .

    В большинстве случаев этого достаточно, но это создает трудности при разработке таблиц со сложными ячейками, т.к.

    требует создания подкласса НСКелл .

    В версиях Mac OS X 10.6 и более ранних версиях это был единственный существовавший тип таблицы.

  • на основе просмотров — каждая ячейка представляет отдельное представление.

    Это позволяет без особого труда строить сложные таблицы даже с поддержкой анимации.

    Этот тип таблицы появился только в Mac OS X 10.7.

В этой статье мы рассмотрим работу с представление таблицы на основе ячеек , так как его функций нам достаточно, то решение будет проще и будет работать не только с новыми версиями OS X.

Передача данных в табличное представление
Данные можно перенести в табличный вид двумя способами:
  • Использование реализации протоколов (интерфейсов) Нстаблевиевделегате , Нстаблевиевдатасаурце , а затем свяжите представление таблицы с классом, реализующим эти протоколы, с помощью Interface Builder. Розетки должны быть связаны источник данных И делегат .

    И в этом классе в самом простом случае нужно реализовать два метода:

    • числоОфРовсинТаблевиев: - возвращает общее количество строк в таблице
    • tableView:objectValueForTableColumn:строка: — возвращает элемент строки, переданной в аргументе ряд .

      Номер столбца в этом случае определяется различными способами с помощью второго аргумента объектвалуефортаблеколумн .

  • Использование контроллера и привязок.

    Этот метод основан на шаблоне Модель-Представление-Контроллер (MVC) [2] и технологии Cocoa Bindings. Про MVC, наверное, нет смысла говорить — о нем слышали все, а кто не слышал, тот может прочитать по данной ссылке в Wiki. Давайте подробнее рассмотрим Cocoa Bindings.



Переплеты какао
Привязки Cocoa появились в Mac OS X версии 10.3. Его основная цель — сократить объем кода контроллера для соединения объектов Model и View. Cocoa Bindings основан на двух механизмах:
  • Кодирование ключ-значение (KVC) — механизм доступа к полям объекта по именам этих полей.

  • Наблюдение за ключом и значением (KVO) — механизм, позволяющий одним объектам отслеживать изменения в других объектах.

Вы можете прочитать больше о привязках какао в [3].

Теперь, когда мы закончили с теорией, мы можем перейти к практике.



Упражняться

Откройте Xcode и создайте новый проект «Приложение Cocoa».

Назовем его «Монитор процессов».

Я использую последнюю версию Xcode на момент публикации (4.2.1), поэтому некоторые шаги могут отличаться.



Создание графического интерфейса
Откройте файл MainMenu.xib и выберите «Окно».

Давайте установим его размеры 480 на 500. Это делается в инспекторе размеров (значок линейки на правой боковой панели).

Там мы зададим минимальные размеры — галочку и необходимые размеры.

Добавьте в окно элемент «Табличное представление» из библиотеки объектов (значок куба в правом нижнем углу боковой панели) (найдите слово «таблица»).

По умолчанию создается таблица на основе ячеек.

Вы можете убедиться в этом, открыв Инспектор атрибутов (на правой боковой панели, слева от линейки).

Измените размер представления таблицы так, чтобы оно занимало все окно.

Затем откройте Инспектор размеров и выделите все элементы на картинке Авторазмера — это необходимо для того, чтобы Табличный вид растянулся вместе с окном.

Теперь нам нужно добавить столбцы в таблицу.

Мы отобразим три столбца — PID процесса, значок и имя процесса.

По умолчанию в таблицу добавляются два столбца.

Вам необходимо изменить это число на 3. Для этого выберите таблицу (Table View), щелкнув в окне.

Здесь нужно сделать небольшое отступление.

Дело в том, что объекты окон вложены друг в друга и выбрать нужный совсем не просто.

Варианта два: это либо выбор нужного элемента в иерархии объектов в окне "Объекты" (думаю, он появился в Xcode 4, раньше не видел), либо Command+Control+Shift Кликнуть по окну с выделением желаемого объекта.

Выбрав таблицу, перейдите в Инспектор атрибутов и установите для столбцов значение 3. Теперь давайте присвоим названия столбцам.

Это делается двойным щелчком по заголовку столбца.

Имя первого столбца — PID, второй останется пустым, а третий — Имя процесса.

Изменение размера столбцов таблицы.

Для этого выберите столбец и задайте его размеры в Инспекторе размеров.

Для первого (PID): 60, для второго (Иконка): 40, для третьего (Имя процесса) — всё оставшееся место.

Давайте изменим тип второго столбца таблицы с текстового на изображение.

Для этого найдите ячейку изображения в библиотеке объектов (найдите «изображение») и перетащите ее во второй столбец.

После всех этих действий вы можете нажать кнопку «Выполнить» и увидеть следующее окно:

Использование табличного представления



Добавление контроллера и привязок
Теперь добавим контроллер, который будет взаимодействовать с таблицей.

Наиболее подходящий тип контроллера для таблицы — NSArrayController. Давайте найдем его в библиотеке объектов (найдите «массив») и перетащим в список объектов.

Настроим привязки для таблицы.

Для этого выберите «Табличное представление» и перейдите в «Инспектор привязок» (предпоследняя вкладка на правой боковой панели).

Там в разделе «Содержимое таблицы» выберите «Содержимое» и установите для параметра «Привязка» значение: «Контроллер массива с ключом контроллера: ArrayObjects».

Теперь воспользуемся техникой KVC и укажем, какие данные должен отображать каждый столбец.

Для этого мы поочередно выбираем каждый столбец (столбец таблицы) и в инспекторе привязок устанавливаем значение для привязки: Контроллер массива с ключом контроллера: ArrayObjects. И для каждого столбца значения Model Key Path соответственно:processIdentifier, icon, localizedName. Почему установлены эти значения, будет описано ниже.

Вот так мы подключили стол к контроллеру.

Остается только подключить контроллер к данным.

Прежде всего, давайте определим эти данные.

Откроем файл AppDelegate.h и определим свойство содержимого типа NSArray:

  
  
  
  
   

@property (retain) NSArray* contents;

В файле AppDelegate.m напишем:

@synthesize contents;

Теперь вернемся к MainMenu.xib и сообщим контроллеру, какие данные использовать.

Перейдите в инспектор привязок и в разделе «Содержимое контроллера» установите для массива содержимого значение «Привязка к: делегату приложения» и «Путь к ключу модели: содержимое».

На этом установка креплений завершена; все, что нам нужно сделать, это заполнить массив содержимого в AppDelegate необходимыми данными.



Получение списка запущенных процессов
Есть несколько способов получить список всех запущенных процессов.

Когда-нибудь я напишу об этом в отдельной статье.

Теперь давайте рассмотрим самый простой и очевидный способ — использование Cocoa. Он не получает полный список процессов, но пока не беспокойтесь об этом.

Давайте определим метод updateProcessList в AppDelegate:

- (void)updateProcessList { NSWorkspace* workspace = [NSWorkspace sharedWorkspace]; self.contents = [NSArray arrayWithArray:[workspace runningApplications]]; }

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

Немного прокомментирую код. В первой строке мы получаем объект класса НСворкспейс .

Объект этого класса существует в программе в единственном экземпляре, своего рода синглтоне, и получается методом общая рабочая область .

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

Это просто.

И мы используем этот массив как данные для контроллера.

Каждый элемент этого массива представляет объект класса.

NSRunningApplication .

Этот класс имеет несколько свойств, среди которых идентификатор процесса , икона , локализованное имя .

Помните, мы установили их для столбцов таблицы? Итак, благодаря KVC, при отображении таблицы эти значения из NSRunningApplication .

Теперь добавим вызов созданного метода при запуске приложения.

Для этого вам нужно добавить строку:

[self updateProcessList];

метод ПриложениеДидФинишЗапуск .

Завершение приложения В Mac OS X принято, что приложение не обязательно завершать работу после закрытия последнего окна.

В нашем примере это не имеет особого смысла, поэтому давайте добавим автоматическое завершение.

Это можно сделать очень просто, добавив в AppDelegate.m один метод:

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { return YES; }



Заключение

Теперь наше приложение готово.

Если все сделано правильно, то после запуска вы увидите примерно следующее:

Использование табличного представления

В качестве упражнения предлагаю читателю реализовать периодическое обновление списка процессов.

Для этого вы можете использовать класс НСтимер и метод запланированныйTimerWithTimeInterval этот класс [5].

Итак, в этой статье мы рассмотрели процесс создания простого приложения с использованием Table View. Большая часть работы выполнялась в Interface Builder и вообще не требовала программирования.

Все, что можно было упростить, было упрощено - оконные контроллеры не рассматривались( НСвиндовконтроллер ), контроллеры просмотра ( НСвиевконтроллер ), управление памятью и многое другое.

В следующей статье я планирую рассмотреть иерархический список ( НСаутлиневиев ), чтобы отобразить дерево процессов.

И, если там достаточно кода, сделаю репозиторий на github. Всем спасибо за внимание!

Ссылки

  1. Руководство по программированию табличного представления (RU)
  2. Шаблон модель-представление-контроллер (ru)
  3. Привязки какао работают (ru)
  4. Справочник классов NSWorkspace (ru)
  5. Справочник классов NSTask (ru)
Обновление.

Я собрал немного кармы и перенес ее в Mac OS X. Теги: #objective-c #Cocoa #osx #Разработка для MacOS

Вместе с данным постом часто просматривают: