3 мая 2014 г.
29 апр. 2014 г.
Категории - теория и пример
Язык Objective-C обладает возможностью добавлять новые методы к уже существующим классам (т.е. расширение функциональности класса). При этом не требуется исходников класса и добавленные методы автоматически становятся доступными всем классам, унаследованным от изменяемого. Так можно добавить новый метод классу NSString (возьмем за пример) и этот метод автоматически добавится во все остальные классы.
Механизм, позволяющий расширять уже существующие классы (путем добавления новых методов, новые instance-переменные добавить таким образом нельзя), называется категорией.
Категория имеет свое имя, список методов и имя класса, который она расширяет. Описание категории имеет следующий вид:
Реализация категории выглядит следующим образом:
Ограничения при создании категорий:
Механизм, позволяющий расширять уже существующие классы (путем добавления новых методов, новые instance-переменные добавить таким образом нельзя), называется категорией.
Категория имеет свое имя, список методов и имя класса, который она расширяет. Описание категории имеет следующий вид:
#import "ClassName.h"
@interface ClassName (CategoryName)
// объявление методов
@end
#import "CategoryName.h"
@implementation ClassName (CategoryName)
// реализация методов
@end
- Невозможность добавления переменных;
- Возможная коллизия имен с самим классом, поэтому необходимо использовать оригинальные префиксы в наименовании своих методов.
Пример.
Расширим класс NSString, добавим метод который будет проверять является ли файл аудио-файлом. Создадим проект Foundation и добавим в проект новый класс-категорию NSStringAudioExtension (наследуемый от NSString):
Объявим в NSStringAudioExtension.h метод - (BOOL) isAudioFile:
В NSStringAudioExtension.m реализуем метод:
Дальше возвращаемся в main.m (технически класс NSString должен подхватить его расширение):
Пример.
Расширим класс NSString, добавим метод который будет проверять является ли файл аудио-файлом. Создадим проект Foundation и добавим в проект новый класс-категорию NSStringAudioExtension (наследуемый от NSString):
Объявим в NSStringAudioExtension.h метод - (BOOL) isAudioFile:
#import <Foundation/Foundation.h>
@interface NSString (NSStringAudioExtension)
- (BOOL) isAudioFile;
@end
В NSStringAudioExtension.m реализуем метод:
#import "NSString+NSStringAudioExtension.h"
@implementation NSString (NSStringAudioExtension)
- (BOOL) isAudioFile {
if ([self hasSuffix:@".mp3"] || [self hasSuffix:@".wav"] || [self hasSuffix:@".arm"]) {
return YES;
}
return NO;
}
@end
Дальше возвращаемся в main.m (технически класс NSString должен подхватить его расширение):
#import <Foundation/Foundation.h>
#import "NSString+NSStringAudioExtension.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSString *audioFileStr = @"Scooter feat. Vicky Leandros - C'est Bleu.mp3";
if ([audioFileStr isAudioFile]) {
NSLog(@"Да, это аудио-файл");
} else {
NSLog(@"Нет, это не аудио-файл");
}
}
return 0;
}
Результат выполнения приложения:
Заменим .mp3 на .mp4, результат выполнения:
27 апр. 2014 г.
View-based NSTableView на основе ячеек из NSView (Злосчастная кнопка). Продолжение
В предыдущей статье о View-based NSTableView на основе ячеек из NSView не было реализации по использованию кнопки на виде (замечание в комментарии читателя). Порывшись в поиске (вместе с несуразными лексическими словосочетаниями), хоть какого-то решения так и не было найдено. Было решено использовать делегат и дать право AppDelegate кликать на эту злосчастную кнопку.
Все бы ничего, но как узнать индекс этой чертовой вьюхи, на которой находится эта кнопка? Подумав, поломав голову вместе с мозгами, решил по нажатию кнопки AppDelegate-м передавать ему эту вьюху. Ведь все они разные, т.к. под каждую строку выделена память, естественно и адреса их будут разные.
Создаем делегат - добавляем в проект новый protocol-файл. Объявим в нем метод который будет передавать право тыканья этой кнопки AppDelegate-у.
#import <Foundation/Foundation.h>
@protocol ButtonControllerProtocol <NSObject>
@required
- (void) viewButtonClicked: (NSButton *) clickedButton view: (NSView *) viewCell;
@end
Далее в ViewController.h добавим экшен на кнопку, подключим AppDelegate и укажем какой метод использовать при нажатии этой кнопки.
- (IBAction)buttonInfo:(id)sender {
AppDelegate *myAppDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
[myAppDelegate viewButtonClicked:sender view:[self view]];
}
В AppDelegate.h подключим созданный протокол и пропишем делегат:
#import "ButtonControllerProtocol.h"
@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDelegate, NSTableViewDataSource, ButtonControllerProtocol> {
Реализуем протокольный метод:
- (void)viewButtonClicked: (NSButton *) clickedButton view: (NSView *) viewCell {
NSLog (@"click");
}
Все бы хорошо, метод обрабатывается, выдает определенный результат, а дальше-то что? А дальше нам якобы нужно как-то менять данные на вьюхе. Вот здесь-то и пришлось помучатся. Хотя все оказалось немного проще. Мы помним что окно как главный вид, состоит из подвидов разной сложности, т.е. проще говоря на нашей вьюхе-подвиде тоже есть подвиды (subviews) - nsimageview, nstextfield и т.д. Остается лишь получить к ним доступ. Получим подвиды на вьхе-строке:
Загоним эти объекты в массив и потом создадим указатели на эти объекты и будем обращаться к непосредственно новым объектам-подвидам:
- (void)viewButtonClicked: (NSButton *) clickedButton view: (NSView *) viewCell {
// Получаем строку-вид в нашей таблице
NSView *clickedView = [clickedButton superview];
// Получаем список подвидов в строке-виде
NSArray *viewObjectsArray = [NSArray arrayWithArray:[clickedView subviews]];
// Коннектимся к подвиду и задаем значение
NSImageView *viewObjectImage = [viewObjectsArray objectAtIndex:0];
[viewObjectImage setImage:[NSImage imageNamed:@"Slice 1"]];
NSTextField *viewObjectFirstTextField = [viewObjectsArray objectAtIndex:1];
[viewObjectFirstTextField setStringValue:@"Slice 1"];
}
Вот такое вот нетривиальное, не претендующее ни на что, решение. Если есть более человеческое решение - прошу указать в комментариях.
20 апр. 2014 г.
Кастомизация строки / Атрибуты строки
Кастомизация строки состоит в том чтобы изменить в строке в определенном слове или символе цвет, шрифт, высоту и т.д. За все это отвечают классы NSAttributedString и NSMutableAttributedString. Например поменяем шрифт для первых пяти символов:
NSMutableAttributedString *seatText = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"Seats\n%d", seats]];
Для большего ознакомления и понимания использования классов можно воспользоваться техдокументацией от Apple.
NSMutableAttributedString *seatText = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"Seats\n%d", seats]];
[seatText addAttribute:NSFontAttributeName
value:[UIFont boldSystemFontOfSize:25.0F]
range:NSMakeRange(0,5)];
return seatText;
Для большего ознакомления и понимания использования классов можно воспользоваться техдокументацией от Apple.
14 апр. 2014 г.
View-based NSTableView на основе ячеек из NSView
Суть построения View-based таблицы заключается в том, чтобы вместо обычных строк, состоящих из NSImageView и NSTextField (как показано в предыдущем примере), создать кастомную (свою модель компонентов в строке) строку. И здесь как всегда на помощь приходит NSView, а точнее NSViewController - класс.
Создаем новый проект. Назовем его ViewBasedNSTableViewWithNSView (Вы можете его назвать по своему, суть этого не меняется). Как и в предыдущем примере добавим таблицу, сделаем строку View-based (прочтите предыдущий пример, здесь в этом посте я упущу эти тонкости). Далее добавим новый класс наследуемый от NSViewController c xib-формой. Добавим компоненты интерфейса на xib-форму. Я добавил два Label, кнопку с изображением ImageCell и ProgressBar. Т.е. можно накидать компоненты по своему желанию и усмотрению, а также целевому типу. Должно получится что-то из этого:
В ViewController.h сделаем оутлеты к нашим компонентам и к самой вьюхе и парочку методов.
В ViewController.m распишем код для наших методов, также по умолчанию зададим текст для лэйблов:
Подключим хидер контроллера-модели ячейки в AppDelegate.h. Объявим массив в котором будем хранить вьюхи-объекты, свяжем оутлет переменной NSTableView с таблицей на форме, добавим объект-контроллер (по которому будем обращаться к индексу массива объектов и получать наш объект для текущего индекса строки. Помните?, я уже упоминал что строки в таблицу добавляются строчка-за-строчкой.).
Дальше будем создавать объекты, задавать им соответствующие иконки и значения лэйблам, помещать в массив и дальше дело техники делегированных методов NSTableView.
Должна получится вот такая каша:
В принципе все. Самое главное - это понять как работает делегирование в таблице и сама таблица. Все остальное дело техники. При моей занятости (работа, семья) на понимание всей этой каши (по работе с таблицами в целом) ушло месяц-полтора. Если посчитать время уделенное на разборку всего этого, то общая затраченная сумма при интенсивном изучении заняла бы всего-то меньше недели.
Продолжение
Создаем новый проект. Назовем его ViewBasedNSTableViewWithNSView (Вы можете его назвать по своему, суть этого не меняется). Как и в предыдущем примере добавим таблицу, сделаем строку View-based (прочтите предыдущий пример, здесь в этом посте я упущу эти тонкости). Далее добавим новый класс наследуемый от NSViewController c xib-формой. Добавим компоненты интерфейса на xib-форму. Я добавил два Label, кнопку с изображением ImageCell и ProgressBar. Т.е. можно накидать компоненты по своему желанию и усмотрению, а также целевому типу. Должно получится что-то из этого:
#import <Cocoa/Cocoa.h>
@interface ViewController : NSViewController {
IBOutlet NSImageView *iconView;
IBOutlet NSTextField *messageLabelOne;
IBOutlet NSTextField *messageLabelTwo;
NSView *_mainView;
}
- (void) setStringValueForFirstTextFields: (NSString *) stringValue;
- (void) setStringValueForSecondTextFields: (NSString *) stringValue;
- (void) setIconForRowOnView: (NSImage *) iconContent;
@end
В ViewController.m распишем код для наших методов, также по умолчанию зададим текст для лэйблов:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
}
return self;
}
- (id)init {
[self.view addSubview: _mainView];
[messageLabelOne setStringValue:@"Message One"];
[messageLabelTwo setStringValue:@"Message Two"];
return self;
}
- (void) setStringValueForFirstTextFields: (NSString *) stringValue {
[messageLabelOne setStringValue:stringValue];
}
- (void) setStringValueForSecondTextFields: (NSString *) stringValue {
[messageLabelTwo setStringValue:stringValue];
}
- (void) setIconForRowOnView: (NSImage *) iconContent {
[iconView setImage:iconContent];
}
@end
Подключим хидер контроллера-модели ячейки в AppDelegate.h. Объявим массив в котором будем хранить вьюхи-объекты, свяжем оутлет переменной NSTableView с таблицей на форме, добавим объект-контроллер (по которому будем обращаться к индексу массива объектов и получать наш объект для текущего индекса строки. Помните?, я уже упоминал что строки в таблицу добавляются строчка-за-строчкой.).
#import <Cocoa/Cocoa.h>
#import "ViewController.h"
@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDelegate, NSTableViewDataSource> {
NSMutableArray *objArray;
ViewController *vController;
}
@property (assign) IBOutlet NSWindow *window;
@property (weak) IBOutlet NSTableView *tableView;
@end
Дальше будем создавать объекты, задавать им соответствующие иконки и значения лэйблам, помещать в массив и дальше дело техники делегированных методов NSTableView.
#import "AppDelegate.h"
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
- (void)awakeFromNib {
objArray = [[NSMutableArray alloc] init];
ViewController *oneController = [[ViewController alloc] init];
ViewController *twoController = [[ViewController alloc] init];
ViewController *treeController = [[ViewController alloc] init];
ViewController *fourController = [[ViewController alloc] init];
ViewController *fiveController = [[ViewController alloc] init];
ViewController *sixController = [[ViewController alloc] init];
ViewController *sevenController = [[ViewController alloc] init];
[oneController setStringValueForFirstTextFields:@"Hello World"];
[oneController setStringValueForSecondTextFields:@"Hello To You"];
[oneController setIconForRowOnView:[NSImage imageNamed:@"layers.icns"]];
[twoController setStringValueForFirstTextFields:@"Hello World"];
[twoController setStringValueForSecondTextFields:@"Hello To You"];
[twoController setIconForRowOnView:[NSImage imageNamed:@"Slice 1.icns"]];
[objArray addObject:oneController];
[objArray addObject:twoController];
[objArray addObject:treeController];
[objArray addObject:fourController];
[objArray addObject:fiveController];
[objArray addObject:sixController];
[objArray addObject:sevenController];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [objArray count];
}
- (id)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
vController = [objArray objectAtIndex:row];
return [vController view];
}
@end
Должна получится вот такая каша:
В принципе все. Самое главное - это понять как работает делегирование в таблице и сама таблица. Все остальное дело техники. При моей занятости (работа, семья) на понимание всей этой каши (по работе с таблицами в целом) ушло месяц-полтора. Если посчитать время уделенное на разборку всего этого, то общая затраченная сумма при интенсивном изучении заняла бы всего-то меньше недели.
Продолжение
9 апр. 2014 г.
Класс NSNumber - примеры
Этот класс является одним из самых странных дополнений в языке Objective-C. Для обработки числовых типов достаточно внутренних функций и методов. Единственная, как бы, цель класса NSNumber это обработка объектов NSArray, который хранит в себе только объекты.
Инициализация объекта NSNumber
Суть такова, что основные методы инициализации начинаются одинаково, но отличаются лишь конечным типом числа, т.е. что имеется в виду:
numberWith<Unsigned><Type>
Исходя из этого полное имя метода, для определенного типа числа, выглядит так:
numberWithBool
numberWithChar
numberWithDouble
numberWithFloat
numberWithInt
numberWithInteger
numberWithLong
numberWithLongLong
numberWithShort
numberWithUnsignedChar
numberWithUnsignedInt
numberWithUnsignedInteger
numberWithUnsignedLong
numberWithUnsignedLongLong
numberWithUnsignedShort
Например:
Возвращение и приведение к другому типу числа из переменной-объекта класса
boolValue
charValue
decimalValue
doubleValue
floatValue
intValue
integerValue
longLongValue
longValue
shortValue
unsignedCharValue
unsignedIntegerValue
unsignedIntValue
unsignedLongLongValue
unsignedLongValue
unsignedShortValue
Например:
NSNumber *myFloat;
Сравнение числовых объектов
Для сравнения значения, хранящихся в объектах необходимо использовать isEqualToNumber метод. isEqualToNumber возвращает логическое значение в зависимости от содержания двух объектов. Например:
Или просто сравнить эти объекты методом compare:
Конвертация числа в строку
Инициализация объекта NSNumber
Суть такова, что основные методы инициализации начинаются одинаково, но отличаются лишь конечным типом числа, т.е. что имеется в виду:
numberWith<Unsigned><Type>
Исходя из этого полное имя метода, для определенного типа числа, выглядит так:
numberWithBool
numberWithChar
numberWithDouble
numberWithFloat
numberWithInt
numberWithInteger
numberWithLong
numberWithLongLong
numberWithShort
numberWithUnsignedChar
numberWithUnsignedInt
numberWithUnsignedInteger
numberWithUnsignedLong
numberWithUnsignedLongLong
numberWithUnsignedShort
Например:
NSNumber *myFloat;
myFloat = [NSNumber numberWithFloat: 10.09];
Возвращение и приведение к другому типу числа из переменной-объекта класса
boolValue
charValue
decimalValue
doubleValue
floatValue
intValue
integerValue
longLongValue
longValue
shortValue
unsignedCharValue
unsignedIntegerValue
unsignedIntValue
unsignedLongLongValue
unsignedLongValue
unsignedShortValue
Например:
NSNumber *myFloat;
float floatvalue;
myFloat = [NSNumber numberWithDouble: 10.09];
floatvalue = [myFloat floatValue];
NSLog (@"Value = %f", floatvalue);
Сравнение числовых объектов
Для сравнения значения, хранящихся в объектах необходимо использовать isEqualToNumber метод. isEqualToNumber возвращает логическое значение в зависимости от содержания двух объектов. Например:
NSNumber *myFloat1;
NSNumber *myFloat2;
myFloat1 = [NSNumber numberWithDouble: 10.09];
myFloat2 = [NSNumber numberWithDouble: 10.08];
if ([myFloat1 isEqualToNumber: myFloat2])
NSLog (@"Numbers are equal");
else
NSLog (@"Numbers are not equal");
Или просто сравнить эти объекты методом compare:
NSNumber *myFloat1;
NSNumber *myFloat2;
myFloat1 = [NSNumber numberWithDouble: 10.09];
myFloat2 = [NSNumber numberWithDouble: 10.08];
NSComparisonResult result;
result = [myFloat1 compare: myFloat2];
if (result == NSOrderedSame)
NSLog(@"Numbers are equal");
else if (result == NSOrderedAscending)
NSLog(@"Float1 is less than Float2");
else if (result == NSOrderedDescending)
NSLog(@"Float1 is greater than Float2");
Конвертация числа в строку
NSNumber *myFloat;
NSString *myString;
myFloat = [NSNumber numberWithDouble: 10.09];
myString = [myFloat stringValue];
NSLog (@"Number as string is %@", myString);
6 апр. 2014 г.
Определение объема HDD и оставшегося свободного места
Определение объема HDD и оставшегося свободного места
//get startup disk total size
+(NSNumber *)getDiskTotalSize
{
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfFileSystemForPath:@"/" error:nil];
return [attr objectForKey:NSFileSystemSize];
}
//get startup disk's free size
+(NSNumber *)getDiskAvailableSize
{
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfFileSystemForPath:@"/" error:nil];
return [attr objectForKey:NSFileSystemFreeSize];
}
//get startup disk total size
+(NSNumber *)getDiskTotalSize
{
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfFileSystemForPath:@"/" error:nil];
return [attr objectForKey:NSFileSystemSize];
}
//get startup disk's free size
+(NSNumber *)getDiskAvailableSize
{
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfFileSystemForPath:@"/" error:nil];
return [attr objectForKey:NSFileSystemFreeSize];
}
Определение домашней папки пользователя
Определение домашней папки пользователя
//get user home
+(NSString *)getUserHome
{
const char *home = getpwuid(getuid())->pw_dir;
NSString *path = [[NSFileManager defaultManager]
stringWithFileSystemRepresentation:home
length:strlen(home)];
NSString *realHomeDirectory = [[NSURL fileURLWithPath:path isDirectory:YES] path];
return realHomeDirectory;
}
//get user home
+(NSString *)getUserHome
{
const char *home = getpwuid(getuid())->pw_dir;
NSString *path = [[NSFileManager defaultManager]
stringWithFileSystemRepresentation:home
length:strlen(home)];
NSString *realHomeDirectory = [[NSURL fileURLWithPath:path isDirectory:YES] path];
return realHomeDirectory;
}
Перекодировка строки в UTF8 и обратно
Код перекодировки строки в UTF8 и обратно
//Encode NSString to UTF8
+ (NSString *)encode2UTF8:(NSString *)originalStr
{
NSString *encodedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,(CFStringRef)originalStr,NULL,NULL,kCFStringEncodingUTF8));
return encodedString;
}
//Decode UTF8 NSString
+ (NSString *)decodeFromUTF8:(NSString *)utf8Str
{
return [utf8Str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
//Encode NSString to UTF8
+ (NSString *)encode2UTF8:(NSString *)originalStr
{
NSString *encodedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,(CFStringRef)originalStr,NULL,NULL,kCFStringEncodingUTF8));
return encodedString;
}
//Decode UTF8 NSString
+ (NSString *)decodeFromUTF8:(NSString *)utf8Str
{
return [utf8Str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
3 апр. 2014 г.
Системные директории в Objective-C
Директория /tmp
Большинство операционных систем имеют стандартный каталог предоставленный специально для целей временного хранения файлов. Другие системы также обеспечивают другую временную папку для каждого пользователя. Точное место отличается в зависимости от платформы. Самым безопасным будет использование NSTemporaryDirectory(), чтобы определить соответствующий каталог. Эта функция возвращает временный каталог для текущего пользователя в виде объекта NSString.
Следующий фрагмент кода определяет и затем отображает временный каталог, используя NSTemporaryDirectory() функцию:
NSString *tempdir;
tempdir = NSTemporaryDirectory();
NSLog (@"Temp Dir = %@", tempdir);
Определение домашней папки пользователя
Домашний каталог текущего пользователя может быть определен с помощью NSHomeDirectory() функции. Эта функция не принимает аргументов и возвращает объект NSString, содержащий путь к домашней директории пользователя:
NSString *homedir;
homedir = NSHomeDirectory();
NSLog (@"Home directory of current user is %@", homedir);
Определение домашней папки конкретно заданного пользователя
Домашний каталог любого пользователя в системе может быть получен с помощью NSHomeDirectoryForUser() функции. Эта функция принимает в качестве единственного аргумента объекта NSString, содержащий имя пользователя и возвращает другой объект NSString, содержащий соответствующий домашний каталог:
NSString *homedir;
NSString *username = @"Paul";
homedir = NSHomeDirectoryForUser(username);
NSLog (@"Home directory of user %@ is %@", username, homedir);
Если заданного пользователя не существует, запрос вернет nil.
Извлечение имени файла
Как уже говорилось ранее, путь может состоять из каталога, в котором находится файл, за которым следует имя файла. Общим требованием при работе с файлами при программировании на любом языке является извлечение только имя файла из пути. Это может быть легко достигнуто с помощью lastPathComponent метод:
NSString *samplepath = @"/Users/demo/objc/sample.m";
NSString *filename;
filename = [samplepath lastPathComponent];
NSLog (@"lastPathComponent = %@", filename);
Извлечение расширения файла
Имена файлов после '.' имеют некое расширение. Например, расширение файла myfile.txt является TXT. Расширение файла может быть извлечено из пути с использованием метода pathExtension:
NSString *samplepath = @"/Users/demo/objc/sample.m";
NSString *pathext;
pathext = [samplepath pathExtension];
NSLog (@"pathExtension = %@", pathext);
Стандартизация пути
Удивительно, как быстро путь может осложниться, особенно когда пользователь перемещаться по файловой системе. Пакет NSUtilities предоставляет метод stringByStandardizingPath. В следующем коде Мы будем использовать этот метод, чтобы сделать упрощение пути:
Например: ~demo/objc/code/../header/./../includes/mycode.h
NSString *samplepath = @"/Users/demo/objc/code/../header/./../includes/mycode.h";
NSString *cleanpath;
cleanpath = [samplepath stringByStandardizingPath];
NSLog (@"Standardized path = %@", cleanpath);
В результате выполнения получим правильный путь: /Users/demo/objc/includes/mycode.h
Разложение пути на его составляющие директории
Метод pathComponents извлекает различные части пути, которые составляют полный путь и возвращает их в NSArray:
NSString *samplepath = @"/Users/demo/objc/code/includes/mycode.h";
NSString *component;
NSArray *pathcomponents;
pathcomponents = [samplepath pathComponents];
for (component in pathcomponents)
NSLog (@"component = %@", component);
В результате получим массив-список директорий из которых состоит путь:
component = /
component = Users
component = demo
component = objc
component = code
component = includes
component = mycode.h
Большинство операционных систем имеют стандартный каталог предоставленный специально для целей временного хранения файлов. Другие системы также обеспечивают другую временную папку для каждого пользователя. Точное место отличается в зависимости от платформы. Самым безопасным будет использование NSTemporaryDirectory(), чтобы определить соответствующий каталог. Эта функция возвращает временный каталог для текущего пользователя в виде объекта NSString.
Следующий фрагмент кода определяет и затем отображает временный каталог, используя NSTemporaryDirectory() функцию:
NSString *tempdir;
tempdir = NSTemporaryDirectory();
NSLog (@"Temp Dir = %@", tempdir);
Определение домашней папки пользователя
Домашний каталог текущего пользователя может быть определен с помощью NSHomeDirectory() функции. Эта функция не принимает аргументов и возвращает объект NSString, содержащий путь к домашней директории пользователя:
NSString *homedir;
homedir = NSHomeDirectory();
NSLog (@"Home directory of current user is %@", homedir);
Определение домашней папки конкретно заданного пользователя
Домашний каталог любого пользователя в системе может быть получен с помощью NSHomeDirectoryForUser() функции. Эта функция принимает в качестве единственного аргумента объекта NSString, содержащий имя пользователя и возвращает другой объект NSString, содержащий соответствующий домашний каталог:
NSString *homedir;
NSString *username = @"Paul";
homedir = NSHomeDirectoryForUser(username);
NSLog (@"Home directory of user %@ is %@", username, homedir);
Если заданного пользователя не существует, запрос вернет nil.
Извлечение имени файла
Как уже говорилось ранее, путь может состоять из каталога, в котором находится файл, за которым следует имя файла. Общим требованием при работе с файлами при программировании на любом языке является извлечение только имя файла из пути. Это может быть легко достигнуто с помощью lastPathComponent метод:
NSString *samplepath = @"/Users/demo/objc/sample.m";
NSString *filename;
filename = [samplepath lastPathComponent];
NSLog (@"lastPathComponent = %@", filename);
Извлечение расширения файла
Имена файлов после '.' имеют некое расширение. Например, расширение файла myfile.txt является TXT. Расширение файла может быть извлечено из пути с использованием метода pathExtension:
NSString *samplepath = @"/Users/demo/objc/sample.m";
NSString *pathext;
pathext = [samplepath pathExtension];
NSLog (@"pathExtension = %@", pathext);
Стандартизация пути
Удивительно, как быстро путь может осложниться, особенно когда пользователь перемещаться по файловой системе. Пакет NSUtilities предоставляет метод stringByStandardizingPath. В следующем коде Мы будем использовать этот метод, чтобы сделать упрощение пути:
Например: ~demo/objc/code/../header/./../includes/mycode.h
NSString *samplepath = @"/Users/demo/objc/code/../header/./../includes/mycode.h";
NSString *cleanpath;
cleanpath = [samplepath stringByStandardizingPath];
NSLog (@"Standardized path = %@", cleanpath);
В результате выполнения получим правильный путь: /Users/demo/objc/includes/mycode.h
Разложение пути на его составляющие директории
Метод pathComponents извлекает различные части пути, которые составляют полный путь и возвращает их в NSArray:
NSString *samplepath = @"/Users/demo/objc/code/includes/mycode.h";
NSString *component;
NSArray *pathcomponents;
pathcomponents = [samplepath pathComponents];
for (component in pathcomponents)
NSLog (@"component = %@", component);
В результате получим массив-список директорий из которых состоит путь:
component = /
component = Users
component = demo
component = objc
component = code
component = includes
component = mycode.h