27 мая 2014 г.

25 мая 2014 г.

NSCollectionView без байндингов: Ячейки из NSView

В предыдущей статье я описал как создать NSCollectionView программно. В этой короткой статье я опишу как создать ячейки / итемы на основе кастомной NSView. Все почти также само как и с View-based NSTableView. Добавляем новый класс NSViewController, подключаем его в BVView.h:



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

@interface BVView : NSView {
    
    ViewController *customView;

}

@end

#import "BVView.h"

@implementation BVView

- (id)initWithFrame:(NSRect)frameRect
{
    // Создаем модель-вьюху
    customView = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];    
    
    self = [super initWithFrame:(NSRect)customView.view.frame];
    
    if (self) {
        
        [self addSubview:[customView view]];
        
    }
    
    return self;
}


В принципе все. Обращаться к элементам интерфейса можно через протокол/делегат (пример NSTableView).

24 мая 2014 г.

16 мая 2014 г.

NSCollectionView без байндингов - пример / NSCollectionView without bindings

NSCollectionView — это класс, позволяющий показывать на экране коллекцию айтемов. Структура коллекции — абсолютно произвольная, но обычно NSCollectionView используется для всяких сетко-подобных контролов с ячейками, хедерами и футерами. Понимая, насколько абстрактен данный класс, разработчики Apple создали мощный механизм для создания любых лейаутов. По большому счету, даже NSTableView это конкретная реализация NSCollectionView  Возможности данного класса, в каком-то смысле, фантастические.
На просторах сети очень много примеров по созданию NSCollectionView с байндингами (NSCollectionView with bindings). Как бы все хорошо, все работает, но вопрос в том как оно работает?

В NSCollectionView также как и в NSTableView есть парочка важных методов, без которых ничего работать не будет, т.е. будет, но ничего не выдаст.

Метод -setPrototype - в него нужно передать экземпляр сабкласса NSCollectionViewItem.

@interface BVPrototype : NSCollectionViewItem
@end

@implementation BVPrototype
- (void)loadView {
    [self setView:[[BVView alloc] initWithFrame:NSZeroRect]];
}
- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];
    [[(BVView *)[self view] button] setTitle:representedObject];
}
@end

Метод -setContent - в него нужно передать массив модели.

@interface BVAppDelegate ()
@property (strong) NSArray *titles;
@end

@implementation BVAppDelegate

@synthesize window = _window;
@synthesize titles;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    self.titles = [NSArray arrayWithObjects:@"Case", @"Molly", @"Armitage",
                   @"Hideo", @"The Finn", @"Maelcum", @"Wintermute", @"Neuromancer", nil];
    
    NSCollectionView *cv = [[NSCollectionView alloc]
                            initWithFrame:[[[self window] contentView] frame]];
    [cv setItemPrototype:[BVPrototype new]];
    [cv setContent:[self titles]];
    
    [cv setAutoresizingMask:(NSViewMinXMargin
                             | NSViewWidthSizable
                             | NSViewMaxXMargin
                             | NSViewMinYMargin
                             | NSViewHeightSizable
                             | NSViewMaxYMargin)];
    [[[self window] contentView] addSubview:cv];
}

@end

Метод -setRepresentedObject - (указан в коде выше) в него передаем нашу модель.

static const NSSize buttonSize = { 80, 20 };
static const NSSize itemSize = { 100, 40 };
static const NSPoint buttonOrigin = { 10, 10 };


@interface BVView : NSView
@property (weak) NSButton *button;
@end

@implementation BVView
@synthesize button;
- (id)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:(NSRect){frameRect.origin, itemSize}];
    if (self) {
        NSButton *newButton = [[NSButton alloc]
                               initWithFrame:(NSRect){buttonOrigin, buttonSize}];
        [self addSubview:newButton];
        self.button = newButton;
    }
    return self;
}
@end

Документация по NSCollectionView сама по себе немного скудновата, но если хорошо пошерстить вэб-сеть, то можно что-то и нарыть.

В следующих статьях под тегом "Мой проект", я опишу как можно создать NSCollectionView на основе NSView. В принципе там не так уж и сложно, почти как с таблицами в предыдущих постах.

6 мая 2014 г.

3 мая 2014 г.

NSMutableString - пример

Класс NSString используется для хранения строк, но в нем присутствует небольшой недостаток. Мы не можем изменять строку которая хранится в экземпляре этого класса. С этой проблемой очень хорошо справляется класс NSMutableString. У него намного больше возможностей обработки строк в отличии от NSString.

Рассмотрим небольшой пример:
Создадим экземпляр класса NSMutableString.

NSMutableString *stringOne = [NSMutableString initWithCapacity: 15];
NSMutableString *stringTwo = [[NSMutableString alloc] initWithCapacity: 30];

В первом и втором примере мы создаем экземпляр класса с выделением под строку определенное количество символов (15 и 30). Второй пример характерен тем, что, мы сами контролируем процесс выделения и очистки памяти. Что произойдет если мы к выделенному количеству символов добавим еще некое количество и случайно выйдем за пределы выделенного количества символов? Ничего не произойдет. Приложение будет и дальше работать также само. Этот параметр носит характер оптимизации для компилятора по выделении памяти и значение этого параметра никак не влияет на длину строки.

По-практикуем:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        NSMutableString *mtStr = [[NSMutableString alloc] initWithCapacity:15];
        [mtStr appendString:@"— Будете у нас, на Колыме – милости просим!"];
        NSLog(@"%@", mtStr);
        
        [mtStr appendFormat:@" — Нет,%@", @" уж лучше вы к нам!"];
        NSLog(@"%@", mtStr);
        
        NSRange strRng = [mtStr rangeOfString:@" — Нет,"];
        [mtStr deleteCharactersInRange:strRng];
        NSLog(@"%@", mtStr);
        
        //[mtStr insertString:@" - Да" atIndex:43];
        //NSLog(@"%@", mtStr);
        
        [mtStr insertString:@" - Да" atIndex:strRng.location];
        NSLog(@"%@", mtStr);
        
        [mtStr setString:@"Новая строка"];
        NSLog(@"%@", mtStr);
    }
    return 0;
}

Результат выполнения: