1 апр. 2014 г.

Objective-C - операции с каталогами

Понимание путей в Objective-C

Имена путей определяются с помощью конвенции UNIX. Таким образом каждый компонент пути отделяется косой чертой (/). Пути, которые не начинаются с косой черты интерпретируются относительно текущего рабочего каталога. Например, если текущий рабочий каталог /home/ ObjC/MyApp/example.m то это считается полный путь. 
Кроме того, домашний каталог текущего пользователя может быть представлен с помощью тильды (~). Например путь ~/example.m ссылается на файл с именем example.m расположенный в домашнем каталоге текущего пользователя. Домашний каталог другого пользователя можно ссылаться, задав имя пользователя с ~. Например, ~ Джон/demo.m ссылается на файл, расположенный в домашнем каталоге пользователя с именем Джон.

Инициализация объекта NSFileManager

NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];


Определение текущей директории

Текущий рабочий каталог можно идентифицировать с помощью метода currentDirectoryPath экземпляра нашего объекта NSFileManager. Текущий путь возвращается из метода в виде объекта NSString:

NSFileManager *filemgr;
NSString *currentpath;

filemgr = [NSFileManager defaultManager];
currentpath = [filemgr currentDirectoryPath];
NSLog (@"Current directory is %@", currentpath);


Изменение пути каталога / директории на другой

Текущий рабочий каталог работающей программы Objective-C может быть изменен с помощью вызова метода changeCurrentDirectoryPath. Путь к каталогу назначения передается в качестве аргумента методу экземпляра в форме объекта NSString. Обратите внимание, что этот метод возвращает логическое ДА или НЕТ если операция прошла успешно:

NSFileManager *filemgr;
NSString *currentpath;

filemgr = [NSFileManager defaultManager];
currentpath = [filemgr currentDirectoryPath];
NSLog (@"Current directory is %@", currentpath);

if ([filemgr changeCurrentDirectoryPath: @"/temp/mydir"] == NO)
        NSLog (@"Cannot change directory.");

currentpath = [filemgr currentDirectoryPath];
NSLog (@"Current directory is %@", currentpath);


Создание нового каталога / директории

Новый каталог создается с помощью метода экземпляра createDirectoryAtURL, в качестве аргумента поступает объект NSURL. Этот метод также принимает дополнительные аргументы в виде набора атрибутов для нового каталога и логическое значение, указывающее, должны ли быть созданы промежуточные каталоги, если они не существуют. Указав ноль (nil), метод будет использовать стандартные атрибуты:

NSFileManager *filemgr;

filemgr = [NSFileManager defaultManager];
NSURL *newDir = [NSURL fileURLWithPath:@"/tmp/mynewdir"];
[filemgr createDirectoryAtURL: newDir withIntermediateDirectories:YES attributes: nil error:nil];

Также после операции выполнения вернет ДА или НЕТ, в зависимости от результата выполнения.

Удаление каталога / директории

Существующий каталог может быть удален из файловой системы с помощью метода removeItemAtPath:

NSFileManager *filemgr;

filemgr = [NSFileManager defaultManager];
[filemgr removeItemAtPath: @"/tmp/mynewdir" handler: nil];


Переименование / Перемещение каталога / директории

Существующий файл или каталог может быть перемещен (переименован) с помощью метода moveItemAtURL. Этот метод принимает путь как аргумент в виде объектов NSURL и требует, чтобы путь назначения не существовал. Логический возвращаемый результат НЕТ, если произошел отказ над операцией:

NSFileManager *filemgr;

filemgr = [NSFileManager defaultManager];

NSURL *oldDir = [NSURL fileURLWithPath:@"/tmp/mynewdir"];
NSURL *newDir = [NSURL fileURLWithPath:@"/tmp/mynewdir2"];

[filemgr moveItemAtURL: oldDir toURL: newDir error: nil];

Получение списка файлов в каталоге / директории


Перечень файлов, содержащихся в указанном каталоге можно получить, используя метод contentsOfDirectoryAtPath. Этот метод принимает путь к каталогу в качестве аргумента и возвращает объект NSArray, содержащий имена файлов и подкаталогов в этом каталоге:

NSFileManager *filemgr;
NSString *currentpath;
NSArray *filelist;
int count;
int i;

filemgr = [NSFileManager defaultManager];
filelist = [filemgr contentsOfDirectoryAtPath: @"/tmp" error: nil];
count = [filelist count];

for (i = 0; i < count; i++)
        NSLog (@"%@", [filelist objectAtIndex: i]);

Получение атрибутов файла или каталога / директории

Атрибуты файла или каталога можно получить, используя метод attributesOfItemAtPath. Он принимает в качестве аргументов путь к каталогу и дополнительный объект NSError в котором хранится информация о любых ошибках. Результаты возвращаются в виде объекта словаря NSDictionary (подробнее о работе с словарных объектов относятся к объектам Objective-C NSDictionary . Ключами для этого словаря являются:


NSFileType
NSFileTypeDirectory
NSFileTypeRegular
NSFileTypeSymbolicLink
NSFileTypeSocket
NSFileTypeCharacterSpecial
NSFileTypeBlockSpecial
NSFileTypeUnknown
NSFileSize
NSFileModificationDate
NSFileReferenceCount
NSFileDeviceIdentifier
NSFileOwnerAccountName
NSFileGroupOwnerAccountName
NSFilePosixPermissions
NSFileSystemNumber
NSFileSystemFileNumber
NSFileExtensionHidden
NSFileHFSCreatorCode
NSFileHFSTypeCode
NSFileImmutable
NSFileAppendOnly
NSFileCreationDate
NSFileOwnerAccountID
NSFileGroupOwnerAccountID

Например, мы можем извлечь права, дату создания, тип файла для каталога /tmp, используя следующий фрагмент кода:

NSFileManager *filemgr;

NSDictionary *attribs;

filemgr = [NSFileManager defaultManager];
attribs = [filemgr attributesOfItemAtPath: @"/tmp" error: NULL];

NSLog (@"Created on %@", [attribs objectForKey: NSFileCreationDate]);
NSLog (@"File type %@", [attribs objectForKey: NSFileType]);
NSLog (@"POSIX Permissions %@", [attribs objectForKey: NSFilePosixPermissions]);

NSFileManager, NSFileHandle и NSData классы (миниобзор)

Foundation Framework предоставляет три класса, которые необходимы, для работы с файлами и каталогами:

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

Класс NSFileHandle предоставляется для выполнения операций с файлами более низкого уровня, таких как извлечение с определенной позиции в файле (курсор), читать и писать содержимое файла на указанное количество байт, добавление данных в существующий файл.

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

NSUserDefaults - сохранение настроек приложения

Использование NSUserDefaults - самый легкий и самый простой способ (существуют и иные способы) сохранения настроек Вашего приложения.

NSUserDefaults - это простой список данных (аналог plist), с помощью которого приложение может хранить простые данные. Нет никаких ограничений на размер данных (помимо собственных ограничений заданных приложением), не используйте этот класс для хранения очень большого объема данных. Файл записывается и считывается атомарно (т.е. целиком), т.е., чем больше данных, которые находятся в файде, тем дольше они будут считыватся. Тем не менее, этот класс подходит для того, чтобы хранить параметры, настройки, и т.п..

К сожалению NSUserDefaultsимеет ряд ограничений по переменным, которые он может сохранять. Это:
– NSArray
– NSData
– NSDictionary
– NSNumber
– NSString

Кроме того, NSArray или NSDictionary должны только содержать упомянутые выше типы (возможно вложение NSArray или NSDictionary). Другие пункты, которые соответствуют протоколу NSCoding, могут быть заархивированы как NSData, т.е., Вы можете сохранить их в переменных. Будем использовать ключи для доступа к данным.

Все что нужно сделать, это загрузить данные в NSUserDefault:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:9001 forKey:@"HighScore"];
[defaults synchronize];

Чтение данных из NSUserDefault:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger theHighScore = [defaults integerForKey:@"HighScore"];

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

31 мар. 2014 г.

Компонент интерфейса в заголовке окна

В обычной программе за отрисовку окна отвечает недокументированный класс NSThemeFrame.
Создаем окно с оутлетом window на это окно. Добавляем NSView и тоже создаем на него привязку оутлет:
Добавляем на вьюху компонент NSPopupButton, убираем флажок Bordered в Инспекторе Атрибутов. В AppDelegate.h должен быть такой код:

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    
    IBOutlet NSWindow *window;
    IBOutlet NSView *itemView;
}

- (void)composeInterface;

@end


AppDelegate.m:

#import "AppDelegate.h"

@implementation AppDelegate

- (void)awakeFromNib
{
[self composeInterface];
}

- (void)composeInterface
{
// Получаем указатель на фрейм окна
NSView *themeFrame = [[window contentView] superview];
NSRect contentWindowFrame = [themeFrame frame]; // размер фрейма окна
NSRect itemViewFrame = [itemView frame]; // размер фрейма вьюхи
NSRect newFrame = NSMakeRect(
                                 contentWindowFrame.size.width - itemViewFrame.size.width, // x позиция
                                 contentWindowFrame.size.height - itemViewFrame.size.height, // y позиция
                                 itemViewFrame.size.width, // ширинв
                                 itemViewFrame.size.height); // высота
    
[itemView setFrame:newFrame];
[themeFrame addSubview:itemView];
}

@end


Вместо NSPopupButton можна добавить любой элемент на вьюху. Главное чтобы высота компонента не была больше чем сам Title Bar.
Дальше все просто. Делаем оутлет на PopupButton, и делаем с ним все что душе угодно.

29 мар. 2014 г.

#pragma mark

Директива #pragma mark добавляет строку в "Function menu". 

'#pragma mark -' - добавляет горизонтальную линию в меню;
'#pragma mark labelname' - добавляет заголовок.

27 мар. 2014 г.