Добрый день! Я уже довольно давно пытаюсь заставить себя выучить другой язык программирования/платформу для 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.
Передача данных в табличное представление
Данные можно перенести в табличный вид двумя способами:- Использование реализации протоколов (интерфейсов) Нстаблевиевделегате , Нстаблевиевдатасаурце , а затем свяжите представление таблицы с классом, реализующим эти протоколы, с помощью Interface Builder. Розетки должны быть связаны источник данных И делегат .
И в этом классе в самом простом случае нужно реализовать два метода:
- числоОфРовсинТаблевиев: - возвращает общее количество строк в таблице
- tableView:objectValueForTableColumn:строка: — возвращает элемент строки, переданной в аргументе ряд .
Номер столбца в этом случае определяется различными способами с помощью второго аргумента объектвалуефортаблеколумн .
- Использование контроллера и привязок.
Этот метод основан на шаблоне Модель-Представление-Контроллер (MVC) [2] и технологии Cocoa Bindings. Про MVC, наверное, нет смысла говорить — о нем слышали все, а кто не слышал, тот может прочитать по данной ссылке в Wiki. Давайте подробнее рассмотрим Cocoa Bindings.
Переплеты какао
Привязки Cocoa появились в Mac OS X версии 10.3. Его основная цель — сократить объем кода контроллера для соединения объектов Model и View. Cocoa Bindings основан на двух механизмах:- Кодирование ключ-значение (KVC) — механизм доступа к полям объекта по именам этих полей.
- Наблюдение за ключом и значением (KVO) — механизм, позволяющий одним объектам отслеживать изменения в других объектах.
Теперь, когда мы закончили с теорией, мы можем перейти к практике.
Упражняться
Откройте 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:
В файле AppDelegate.m напишем:@property (retain) NSArray* contents;
@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. Всем спасибо за внимание!
Ссылки
- Руководство по программированию табличного представления (RU)
- Шаблон модель-представление-контроллер (ru)
- Привязки какао работают (ru)
- Справочник классов NSWorkspace (ru)
- Справочник классов NSTask (ru)
Я собрал немного кармы и перенес ее в Mac OS X. Теги: #objective-c #Cocoa #osx #Разработка для MacOS
-
Второе Воплощение Kindle
19 Oct, 24