15 мар. 2014 г.

KVC (Key-Value Coding) Ключ - Значение

Ключ-значение кодирования представляет собой механизм для доступа к свойству объекта косвенно, с помощью строк для идентификации свойств, а не через вызов аксессора или доступ к ним непосредственно через переменных экземпляра. Что это значит. Допустим у Вас есть таблица с множеством колонок, каждое имя колонки можно превратить в ключ и обращаться по ключу вместо индекса колонки, ведь так проще, да и запомнить название колонки проще чем ее индекс.

В данном примере мы не будем работать с таблицами, а реализуем некий класс Books (Книги). Основное что нам требуется для книги это "Автор книги", "Название книги" и "Количество страниц в книге".


Итак добавили новый класс наследованный от NSObject:

Books.h :

#import <Foundation/Foundation.h>

@interface Books : NSObject

@property (strong) NSString *bookAuthor;
@property (strong) NSString *bookName;
@property int pageCount;

@end

Books.m - оставим пустым, т.к. остальное мы реализуем в классе AppDelegate

#import "Books.h"

@implementation Books

@end

В AppDelegate.h создадим массив booksArray со списком книг. Ведь у нас будет не одна книга. Также не забудем подключить наш класс Books.

#import <Cocoa/Cocoa.h>
#import "Books.h"

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    NSMutableArray *booksArray;
}

@property (assign) IBOutlet NSWindow *window;
- (IBAction)printListBooks:(id)sender;

@end

На нашу форму поместим кнопку и сделаем связь кнопки с методом printListBooks.

В AppDelegate.m создадим несколько объектов книг и добавим их в массив который будет хранить список наших книг.

#import "AppDelegate.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    
    booksArray = [[NSMutableArray alloc] init];
    
    // Добавляем наши книги-объекты в массив обычным способом
    
    Books *firstBook = [[Books alloc] init];
    [firstBook setBookAuthor:@"Т.Г. Шевченко"];
    [firstBook setBookName:@"Кобзарь"];
    [firstBook setPageCount:283];
    
    [booksArray insertObject:firstBook atIndex:[booksArray count]];
    
    Books *secondBook = [[Books alloc] init];
    [secondBook setBookAuthor:@"И. Франко"];
    [secondBook setBookName:@"Городские повести"];
    [secondBook setPageCount:478];
    
    [booksArray insertObject:secondBook atIndex:[booksArray count]];
}

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

- (IBAction)printListBooks:(id)sender {
    
    for (Books *currentBook in booksArray) {
        NSLog(@"Книга: %@, Автор книги: %@, К-во страниц: %i",
              [currentBook bookName],
              [currentBook bookAuthor],
              [currentBook pageCount]);
    }
}
@end

Запустим и получим результат:


А как же KVC ? Все довольно просто. Добавим еще одну книгу, но теперь будем обращаться не к переменным нашего объекта, а по ключу (аналогично названию переменным) и будем задавать ему значение:

 // Добавляем наши книги-объекты с помощью ключей (KVC)
    
    Books *threeBook = [[Books alloc] init];
    [threeBook setValue:@"Леся Украинка" forKey:@"bookAuthor"];
    [threeBook setValue:@"Боярыня" forKey:@"bookName"];
    [threeBook setValue:@"184" forKey:@"pageCount"];
    
    [booksArray insertObject:threeBook atIndex:[booksArray count]];

Здесь bookAuthor, bookName, pageCount являются ключами, а Value - значениями для каждого ключа. Запустим наше приложение:


Результат - добавлена третья книга в массив-список книг с помощью KVC.

11 мар. 2014 г.

Objective-C подтверждение адресса электронной почты

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

Этот метод использует класс NSRegularExpression. Описание по этому классу можно посмотреть в документации Apple.

- (BOOL) validEmail:(NSString*) emailString {
    if([emailString length]==0) {
        return NO;
    } 

    NSString *regExPattern = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
    NSRegularExpression *regEx = [[NSRegularExpression alloc] initWithPattern:regExPattern options:NSRegularExpressionCaseInsensitive error:nil];
    NSUInteger regExMatches = [regEx numberOfMatchesInString:emailString options:0 range:NSMakeRange(0, [emailString length])];
    NSLog(@"%i", regExMatches);

    if (regExMatches == 0) {
        return NO;
    } else {
        return YES;
    }
}

Конвертация NSString-даты в удобно читаемую дату

Идея состоит в том чтобы полученную дату (например: 11/03/2014) перевести в более удобно читаемый, более человечный формат (например: вторник 11 марта 2014г.). Значит будем работать с NSDateFormatter.

-(NSString *) getHumanDate: (NSString *) strDate {
    
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"dd/MM/yyyy"];
    NSDate *date = [dateFormat dateFromString:strDate];
    [dateFormat release];

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"EEEE',' dd ' ' MMMM ' ' yyyy"];
    NSLocale *loc = [[NSLocale alloc] initWithLocaleIdentifier:@"uk_UA"]; // ru_RU
    [formatter setLocale:loc ] ;
    return [formatter stringFromDate:date];
}
 
 

Аватарка с закругленными углами в iOS приложении

Закругленные аватары, кажется, очень модно. Даже Apple делает закругленные изображения для контактов. Если вам интересно, как этого добиться в вашем приложении вот ответ.

Все, что нужно сделать, это настроить CALayer отвечающий за вид изображения, представляющего аватар:

self.avatarImageView.layer.cornerRadius = 150.0f;
self.avatarImageView.layer.borderWidth = 2.0f;
self.avatarImageView.layer.borderColor = [UIColor blackColor].CGColor;
self.avatarImageView.clipsToBounds = YES;

Предположим, что у нас есть квадратное изображение размером 300 × 300, в противном случае мы не сможем получить идеальный круг. Мы добавим черную рамку, и зададим clipsToBounds равным YES. И что в итоге имеем - большое скругленное изображение.

10 мар. 2014 г.

NSSlider "ползунок"

Объект NSSlider отображает диапазон значений для чего-то (какого-нибудь контрола) в приложении. Ползунки могут быть вертикальными или горизонтальными полосами или круговыми циферблатами.

Создадим форму и расположим на ней некоторые контролы интерфейса:

Добавим:
- Label;
- Slider.

В Label установим текст со значением 50 (можно любое другое или вообще никакого текста на изменять, далее будет понятно почему). Добавим слайдер, выровняем, и сделаем наши связи со соледующими оутлетами:

IBOutlet NSTextField *sliderTextLabel;
IBOutlet NSSlider *slider;

Также добавим экшен на наш слайдер, который будет срабатывать при изменении ползунка слайдера:

- (IBAction)sliderChange:(id)sender;

В метод applicationDidFinishLaunching добавим следующий код инициализации нашего слайдера и нашего лейбла:

[slider setIntValue:50];
[sliderTextLabel setIntValue:[slider intValue]];

Можно установить любое значение слайдеру при инициализации. Дальше в нашем экшене-методе sliderChange напишем такие строчки кода:

[sliderTextLabel setIntValue:[slider intValue]];

При изменении местоположения ползунка будет меняться значение нашего лэйбла. Но есть один нюанс. Значение в лэйбле устанавливается (текущего значения слайдера) только тогда когда Вы остановили перемещение ползунка. Но нам бы хотелось пойти дальше и сделать более правильно, т.е. чтобы значение лэйбла менялось в реальном времени во время перемещения ползунка слайдера. Для этого нужно в Дизайнере форм пометить слайдер и в Инспекторе аттрибутов в секции Control выставить чекбокс Continuous. Вот и все.

NSPopupButton выпадающий список

Класс NSPopUpButton определяет объекты, которые реализуют всплывающее окно и ниспадающие меню, в графическом интерфейсе пользователя.

Создадим форму, на которой расположим наши контролы интерфейса:

- PopUpButton;
- TextField;
- Button;
- Label.

Сделаем связи наших контролов с нашими аутлетами и экшенами:

IBOutlet NSTextField *textLabel; // к Label
IBOutlet NSTextField *textField; // к TextField
IBOutlet NSPopUpButton *popUpButton; // к popUpButton


- (IBAction)addItemToPopUpButton:(id)sender; // к кнопке "Добавить"
- (IBAction)itemPopUpButtonDidSelected:(id)sender; // к popUpButton

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


- (IBAction)addItemToPopUpButton:(id)sender {
    
    if (![[textField stringValueisEqual: @""]) {
        [popUpButton addItemWithTitle: [textField stringValue]];
    }
}

- (IBAction)itemPopUpButtonDidSelected:(id)sender {
    
    [textLabel setStringValue:[popUpButton titleOfSelectedItem]];
}

Наш результат:
Теперь когда мы введем текст в TextField - поле и нажмем кнопку добавить, то наш текст будет добавлен в выпадающий список элемент за элементом. Если мы выберем какой-то элемент из выпадающего списка, то этот текст отобразится в нашем Label.

9 мар. 2014 г.

StatusBar приложение

Простой пример приложения которое имеет свое меню в статус баре OS X.

Создадим новый проект в Xcode. Перейдем в Interface Builder и добавим до нашего созданного окна "меню" (Выберем в списке контролов интерфейса Menu и положим где-то рядом с окном.
Отредактируем элементы списка меню:

- Показать окно;
- Выход.

В AppDelegate.h добавим следующие строки:

IBOutlet NSMenu *statusBarMenu;
NSStatusItem *statusBarItem;

- (IBAction)showWindow:(id)sender;
- (IBAction)quitApp:(id)sender;

Соединим наш оутлет NSMenu с нашим добавленным меню. Наши экшены соотвествующими элементами меню.

В AppDelegate.m в методе awakeFromNib напишем следующий код:

statusBarItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
[statusBarItem setMenu:statusBarMenu];
[statusBarItem setTitle:@"МоеМеню"];
[statusBarItem setHighlightMode:YES];

В экшене showWindow пишем следующее:

[NSApp activateIgnoringOtherApps:YES];
[_window makeKeyAndOrderFront:nil];

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

В экшене quitApp пишем:

[NSApp terminate:nil];

Ну вот и все.
Также можно добавить иконку к нашему меню. Если убрать setTitle, то у нас будет вместо надписи в статус баре только иконка. Иконка должна быть соотвествующих размеров как для обычных экранов так и для ретина-экранов.


8 мар. 2014 г.

Установить бэйдж на иконку приложения с помощью Objective-C

Для быстрой установки бэйджа на иконку своего приложения можно с помощью метода NSDockTitle.

[[NSApp dockTile] setBadgeLabel:@"МойБэйдж"];

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

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



А вот тут уже другая история. Середина текста выковыряна, т.к. текст больше чем сама ширина иконки.