Показаны сообщения с ярлыком Программирование на Objective-C. Показать все сообщения
Показаны сообщения с ярлыком Программирование на Objective-C. Показать все сообщения

Программирование на Objective-C

12. Программирование на Objective-C. Протоколы, динамическая типизация, предупреждения, обработка исключений

Пример протокола:

#import <Foundation/Foundation.h>

@protocol MYProtocol <NSObject>
@required
- (void)exampleMethod;
@optional
- (void)optionalMethod;
@end

@interface MYClass : NSObject<MYProtocol>
- (void)exampleMethod;
@end

@implementation MYClass
- (void)exampleMethod
{
    NSLog(@"%i", (arc4random() % 3) + 1);
}
@end

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        id theObject = [[MYClass alloc] init];
        @try {
            [theObject exampleMethod];
        }
        @catch (NSException *exception) {
            NSLog(@"Error is : << %@ >>", exception);
        }
        @finally {
            NSLog(@"Final");
        }
        
    }
    return 0;
}

В Xcode можно настраивать предупреждения:
  • Treat Warnings as Errors
  • Unused Variables
  • и др.



11. Программирование на Objective-C. Архивация объектов



#import <Foundation/Foundation.h>


@interface Car : NSObject {
    @private
    NSString *name;
    float engCap;
}

@property (retain) NSString *name;
@property float engCap;

@end


@implementation Car

@synthesize name;
@synthesize engCap;

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:name forKey:@"name"];
    [aCoder encodeObject:[NSNumber numberWithFloat:engCap] forKey:@"engCap"];
}

- initWithCoder:(NSCoder *)aCoder
{
#if !__has_feature(objc_arc)
    name = [[aCoder decodeObjectForKey:@"name"] retain];
#else
    name = [aCoder decodeObjectForKey:@"name"];
#endif
    engCap = [[aCoder decodeObjectForKey:@"engCap"] floatValue];
    return self;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"The engine capacity of %@ is %f liter", name, engCap];
}

@end


int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        Car *kamaz =  [[Car alloc] init];
        [kamaz setName:@"Kamaz"];
        [kamaz setEngCap:10.8f];
        [NSKeyedArchiver archiveRootObject:kamaz toFile:@"/Users/Abbas/Documents/kamaz.plist"];
        NSLog(@"%@", kamaz);
        
        Car *newKamaz = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/Users/Abbas/Documents/kamaz.plist"];
        NSLog(@"%@", newKamaz);
    }
    return 0;
}


10. Программирование на Objective-C. Наследование и категории




Пример наследования:

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

-(NSString *)description;

@end

@implementation MyClass

-(NSString *)description
{
    return @"MyClass";
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        MyClass *my = [[MyClass alloc] init];
        NSLog(@"%@", my);
    }
    return 0;
}


Пример категории:

#import <Foundation/Foundation.h>

@interface NSString(MyClass)

-(NSString *)removeDigits;

@end

@implementation NSString(MyClass)

-(NSString *)removeDigits
{
    NSCharacterSet *theDigits = [NSCharacterSet decimalDigitCharacterSet];
    return [self stringByTrimmingCharactersInSet:theDigits];
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        NSString *my = [[NSString alloc] init];
        my = @"123test456";
        NSLog(@"%@", [my removeDigits]);
    }
    return 0;
}


9. Программирование на Objective-C. Работа с файлами



#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        NSFileManager *theFileManager = [[NSFileManager alloc] init];
        if ([theFileManager fileExistsAtPath:@"/etc/hosts"] == YES)
        {
            NSDictionary *theAttributes = [theFileManager attributesOfItemAtPath:@"/etc/hosts" error:nil];
            for (NSString *attribute in theAttributes)
            {
                NSLog(@"%@ = %@", attribute, [theAttributes objectForKey:attribute]);
            }
        }
        
        NSURL *theURL = [NSURL URLWithString:@"file:///Users/John/Documents/CodingStandards-Style.pdf"];
        NSURL *theOtherURL = [NSURL fileURLWithPath:@"/Users/John/Downloads/CodingStandards-Style.pdf"];
        [theFileManager moveItemAtURL:theURL toURL:theOtherURL error:nil];
        
        NSURL *theExampleURL = [NSURL fileURLWithPath:@"/Users/John/Documents/example.txt"];
        NSMutableString *theString = [NSMutableString stringWithContentsOfURL:theExampleURL
            encoding:NSUTF8StringEncoding error:nil];
        [theString appendFormat:@"example2"];
        [theString writeToURL:theExampleURL atomically:YES];
    }
    return 0;
}


8. Программирование на Objective-C. Массивы и словари



#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        int theArray[] = {5, 0, 1, 2, 3, 4};
        while (theArray[0])
        {
            NSLog(@"%i\n", theArray[theArray[0]--]);
        }
        
        
        NSString *pets[3] = {@"cat", @"dog", @"cock"};
        NSLog(@"%@", pets[0]);
        
        
        NSArray *theMyArray = [[NSArray alloc] initWithObjects:@"name", @"family", nil];
        for (int i = 0; i < theMyArray.count; i++)
        {
            NSLog(@"%@", [theMyArray objectAtIndex:i]);
        }
        
        NSArray *theOtherArray = [NSArray arrayWithObjects:@"1", @"2", @"3", nil];
        for (NSString *theElement in theOtherArray)
        {
            NSLog(@"%@\n", theElement);
        }
        
        NSMutableArray *theMutableArray = [[NSMutableArray alloc] init];
        [theMutableArray addObject:@"test"];
        NSLog(@"%@", [theMutableArray objectAtIndex:0]);
        [theMutableArray removeObjectAtIndex:0];
        NSLog(@"%lu", theMutableArray.count); // 0
        
        NSDictionary *theDomains = [NSDictionary dictionaryWithObjectsAndKeys:@"Russia", @"ru", @"Kazakhstan", @"kz", @"USA", @"us", nil];
        NSLog(@"%@", [theDomains objectForKey:@"ru"]);
        
        NSMutableDictionary *theMutableDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"One", "1", nil];
        [theMutableDictionary setObject:@"Two" forKey:@"2"];
    }
    return 0;
}



7. Программирование на Objective-C. Свойства классов и их инициализация



#import <Foundation/Foundation.h>


@interface Developer : NSObject {
    @private
    NSString *name;
    NSDate *birthday;
}
@property NSString *name;
- (void)printInfo;
- (NSDate *)birthday;
- (void)setBirthday:(NSDate *)value;
@end


@implementation Developer
@synthesize name;
- (id)init
{
    self = [super init];
    if (self)
    {
    }
    return self;
}
- (id)initWithName:(NSString *)n
{
    self = [super init];
    if (self)
    {
        name = n;
    }
    return self;
}
- (void)printInfo
{
    NSLog(@"name: %@\nbirthday: %@", name, birthday);
}
- (NSDate *)birthday
{
    return birthday;
}
- (void)setBirthday:(NSDate *)value
{
    birthday = value;
}
@end


int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        Developer *theDeveloper = [[Developer alloc] init];
        
        theDeveloper.birthday = [NSDate date];
        theDeveloper.name = @"John Smith";
        [theDeveloper printInfo];
        
        [theDeveloper setBirthday:[NSDate date]];
        [theDeveloper setName:@"Василий Пупкин"];
        [theDeveloper printInfo];
        
        Developer *theOtherDeveloper = [[Developer alloc] initWithName:@"Mahmud"];
    }
    return 0;
}



6. Программирование на Objective-C. Управление памятью



До Xcode 4.2 управление памятью осуществлялось вручную.

В Java, Ruby, Python управлением памятью занимается сборщик мусора.

В Objective-C тоже есть подобная штука, но она не работает на iPhone, iPad, Mac OS X ниже Leopard.


Сборщика мусора по умолчанию в проекте нет.


5. Программирование на Objective-C. Введение в ООП и указатели

Основные принципы:
  • абстракция (например, класс NSObject)
  • инкапсуляция (сокрытие методов (поведения) и свойств (полей, переменных) внутри класса)
  • полиморфизм
  • насследование

Примеры классов из фреймворка Foundation (подключается как #import <Foundation/Foundation.h>):
  • NSData
  • NSButton
  • NSCalendar
  • NSViewController
  • NSArray
  • NSString
  • NSDate
  • NSCoder
  • NSLock
  • NSError


        NSString * theFirstName = @"";
        NSString* theLastName = @"";
        NSString *theMiddleName = @"";
        NSLog(@"%@ %@ %@", theFirstName, theMiddleName, theLastName);

Пример создания объектов класса NSString.

Звездочка говорит о том что переменная является указателем. Т.е. фактические в ней хранится не сам объект, а адрес в памяти по которому можно найти объект.

Некоторые утверждают, что звездочку надо ставить отдельно от переменной, как первых двух строках примера выше, потому что она не относится к имени переменной, а скорее подчеркивает тип переменной.

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


Другие стандарты.

Еще пример:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSDate *theToday = [NSDate date];
        NSLog(@"theToday = %@", theToday); // theToday = 2014-08-15 10:00:02 +0000
        
        NSString *theHelloWorld = @"Hello, World!";
        unsigned long theSize = [theHelloWorld length];
        NSLog(@"theHelloWorld.length = %lu", theSize); // theHelloWorld.length = 13

    }
    return 0;
}

Если выделить класс то в Quick help inspector отражается помощь по классу.


Аналогичную помощь можно получить если нажать на классе с зажатой клавишей ⌥ Option или Windows logo клавишей, если вы под Хакинтошем. В справке по методам класса, + значит что метод классовый. а - значит что метод объектный.

Некоторые методы класса NSString:
  • lowercaseString
  • uppercaseString
  • length
  • hasSuffix
  • hasPrefix

Правила наименования методов в Objective-C иногда приводят к таким вот длинным конструкциям.


Как расшифровать сигнатуру метода в Objective-C

4. Программирование на Objective-C. enum (перечисления), typedef (синоним для типа), define (директива препроцессора), if (директива препроцессора)

Пример кода:

#import <Foundation/Foundation.h>

#define pi 3.14

enum pet { cat, dog, chicken, cock, kitten };
typedef enum { notebook, netbook, ultrabook } laptop;

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        enum pet theMyPet = kitten;
        laptop theMyLaptop = notebook;
        
#if DEBUG
        NSLog(@"theMyPet = %i", theMyPet); // theMyLaptop = 4
        NSLog(@"theMyLaptop = %i", theMyLaptop); // theMyLaptop = 0
        NSLog(@"pi = %f", pi);
#endif
    }
    return 0;
}

Сменить Debug на Release можно в меню Edit Scheme...


Далее Run PROJECT_NAME -> Info -> Build Configuration



3. Программирование на Objective-C. Примитивные типы данных

Примитивные типы данных:
  • int - 4 байта
  • long int (long) - на 32-bit 4 байта, на 64-bit 8 байт
  • long long int (long long) - 8 байт
  • short int (short) - 2 байта
  • char - 1 байт
  • float - 4 байта (пример: float f = 3.14f;)
  • double - 8 байт (пример: double d = 3.14;)
  • long double - 16 байт (Apple почему-то говорят что это не работает)
  • BOOL - 1 байт
  • bool - 1 байт
Целочисленные типы могут быть еще и unsigned.

Заполнители:
  • %i - целые числа
  • %f - десятичная запись, 6 чисел по умолчанию после запятой
  • %e - экспоненциальная запись
  • %g - автоматическое определение
  • %lu - unsigned long
String Programming Guide: String Format Specifiers

Для валютных операций лучше использовать объектный тип NSDecimal. Для строк - NSString, а для дат - NSDate.

2. Программирование на Objective-C. Создание первого приложения

Чтобы создать Objective-C проект надо в типе проекта выбирать Foundation:


После создания проекта можно выбрать Base SDK.


Код сгенерированный по умолчанию в файле main.m (расширение .m произошло от сокращения messages).

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSLog(@"Hello, World!");
        
        int theCoolNumber = 42;
        NSLog(@"theCoolNumber = %i", theCoolNumber);
        
        float thePi = 3.14;
        NSLog(@"thePi = %f", thePi);
    }
    return 0;
}

Директива import отличается от классической Си-директивы include тем что она более "умная" и обеспечивает то что ни один заголовочный файл не будет вставлен дважды.

autoreleasepool - эта штука связана с управлением памятью.

В Xcode если сделать двойной клик по фигурной скобке блока кода, то выделяется весть блок кода.

При создании нового файла Xcode вставляет в начало файла комментарий с информацией о файле, авторе, и компании. Эта информация может указывается при создании проекта, или браться из контактов Mac OS X (Launchpad -> Контакты). Поэтому если например нужно изменить имя компании вставляемое в комментарий при создании новых файлов, то можно попробовать изменить его в контактах для того пользователя под проходит работа в системе.

Для вставки готовых заготовок надо открыть панель Code Snippet library и выбрать нужный шаблон. Эту библиотеку можно пополнять, если переносить в неё выделенный код.

Для того чтобы выровнять отступы в коде нужны выделить его и выбрать из контекстного меню Structure -> Re-Indent.

1. Программирование на Objective-C. Установка Xcode


  1. Перейти на http://developer.apple.com
  2. Перейти в Mac Dev Center
  3. Выбрать View all downloads
  4. Выбрать в списке .dmg образ дистрибутива Xcode

Раньше Xcode устанавливался в папку /Developer/, теперь в новых версиях Mac OS X этой папки нет вообще и Xcode устанавливается в папку /Applications/ как и все другие приложения.

В настройках Xcode -> Preferences... (под Хакинтошем можно просто нажать Alt + ,) на вкладке Fonts & Colors можно сразу выбрать тему на свой вкус.

На вкладке Text Editing лучше сразу включить Show Line numbers потому что иначе вы не сможете найти строку в которой возникла ошибка, а компилятор в сообщении об ошибке всегда выдает номер строки. Кстати компилятор в Xcode называется LLVM.

На вкладке Behaviors -> Generates new issues можно настроить поведение Xcode при обнаружении ошибок компиляции. Можно например звуковое оповещение сделать и пр. Этот пункт работает в реальном времени, т.е. система на ходу build-ит ваш код.

Можно также настроить поведение среды при начале, успехе, и провале build-a.