mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-11-28 10:59:26 +03:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
f4ab326784
@ -213,7 +213,7 @@ say $x; #=> 52
|
|||||||
# - `if`
|
# - `if`
|
||||||
# Before talking about `if`, we need to know which values are "Truthy"
|
# Before talking about `if`, we need to know which values are "Truthy"
|
||||||
# (represent True), and which are "Falsey" (or "Falsy") -- represent False.
|
# (represent True), and which are "Falsey" (or "Falsy") -- represent False.
|
||||||
# Only these values are Falsey: (), 0, "", Nil, A type (like `Str` or `Int`),
|
# Only these values are Falsey: (), "", Nil, A type (like `Str` or `Int`),
|
||||||
# and of course False itself.
|
# and of course False itself.
|
||||||
# Every other value is Truthy.
|
# Every other value is Truthy.
|
||||||
if True {
|
if True {
|
||||||
|
@ -11,6 +11,8 @@ lang: ru-ru
|
|||||||
Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень
|
Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень
|
||||||
маленький Тьюринг-полный язык программирования лишь с 8 командами.
|
маленький Тьюринг-полный язык программирования лишь с 8 командами.
|
||||||
|
|
||||||
|
Вы можете испытать brainfuck в вашем браузере с помощью [brainfuck-визуализатора](http://fatiherikli.github.io/brainfuck-visualizer/).
|
||||||
|
|
||||||
```
|
```
|
||||||
Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек.
|
Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек.
|
||||||
|
|
||||||
|
@ -1,105 +1,170 @@
|
|||||||
---
|
---
|
||||||
language: Objective-C
|
language: Objective-C
|
||||||
filename: LearnObjectiveC.m
|
filename: LearnObjectiveC-ru.m
|
||||||
contributors:
|
contributors:
|
||||||
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
|
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
|
||||||
- ["Yannick Loriot", "https://github.com/YannickL"]
|
- ["Yannick Loriot", "https://github.com/YannickL"]
|
||||||
|
- ["Levi Bostian", "https://github.com/levibostian"]
|
||||||
translators:
|
translators:
|
||||||
- ["Evlogy Sutormin", "http://evlogii.com"]
|
- ["Evlogy Sutormin", "http://evlogii.com"]
|
||||||
|
- ["Dmitry Bessonov", "https://github.com/TheDmitry"]
|
||||||
lang: ru-ru
|
lang: ru-ru
|
||||||
---
|
---
|
||||||
|
|
||||||
Objective-C — компилируемый объектно-ориентированный язык программирования, используемый корпорацией Apple,
|
Objective-C — основной язык программирования, используемый корпорацией Apple
|
||||||
построенный на основе языка Си и парадигм Smalltalk.
|
для операционных систем OS X и iOS и их соответствующих фреймворках Cocoa и
|
||||||
В частности, объектная модель построена в стиле Smalltalk — то есть объектам посылаются сообщения.
|
Cocoa Touch.
|
||||||
|
Он является объектно-ориентированным языком программирования общего назначения,
|
||||||
|
который добавляет обмен сообщениями в Smalltalk-стиле к языку программирования C.
|
||||||
|
|
||||||
```objective_c
|
```objective_c
|
||||||
// Однострочный комментарий
|
// Однострочные комментарии начинаются с //
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Многострочный
|
Так выглядят многострочные комментарии
|
||||||
комментарий
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Импорт файлов фреймворка Foundation с помощью #import
|
// Импорт заголовочных файлов фреймворка Foundation с помощью #import
|
||||||
|
// Используйте <>, чтобы импортировать глобальные файлы (обычно фреймворки)
|
||||||
|
// Используйте "", чтобы импортировать локальные файлы (из проекта)
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "MyClass.h"
|
#import "MyClass.h"
|
||||||
|
|
||||||
// Точка входа в программу это функция main,
|
// Если вы включили модули для iOS >= 7.0 или OS X >= 10.9 проектов в
|
||||||
// которая возвращает целый тип integer
|
// Xcode 5, вы можете импортировать фреймворки подобным образом:
|
||||||
|
@import Foundation;
|
||||||
|
|
||||||
|
// Точка входа в программу - это функция main,
|
||||||
|
// которая возвращает целый тип
|
||||||
int main (int argc, const char * argv[])
|
int main (int argc, const char * argv[])
|
||||||
{
|
{
|
||||||
// Создание autorelease pool для управления памятью
|
// Создание autorelease pool для управления памятью в программе
|
||||||
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
// В место этого воспользуйтесь @autoreleasepool, если вы используете
|
||||||
|
// автоматический подсчет ссылок (ARC)
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
// Используйте NSLog для печати в консоль
|
// Используйте NSLog для печати в консоль
|
||||||
NSLog(@"Hello World!"); // Напечатает строку "Hello World!"
|
NSLog(@"Привет Мир!"); // Напечатает строку "Привет Мир!"
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Типы и переменные
|
// Типы и переменные
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
// Простое объявление
|
// Объявление простых типов
|
||||||
int myPrimitive1 = 1;
|
int myPrimitive1 = 1;
|
||||||
long myPrimitive2 = 234554664565;
|
long myPrimitive2 = 234554664565;
|
||||||
|
|
||||||
|
// Объявление объектов
|
||||||
// Помещайте * в начало названия объекта для строго типизированного объявления
|
// Помещайте * в начало названия объекта для строго типизированного объявления
|
||||||
MyClass *myObject1 = nil; // Строгая типизация
|
MyClass *myObject1 = nil; // Строгая типизация
|
||||||
id myObject2 = nil; // Слабая типизация
|
id myObject2 = nil; // Слабая типизация
|
||||||
|
|
||||||
NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)"
|
|
||||||
// %@ – это объект
|
// %@ – это объект
|
||||||
// 'description' это общий для всех объектов метод вывода данных
|
// 'description' - это общий для всех объектов метод вывода данных
|
||||||
|
NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)"
|
||||||
|
|
||||||
// Строка
|
// Строка
|
||||||
NSString *worldString = @"World";
|
NSString *worldString = @"Мир";
|
||||||
NSLog(@"Hello %@!", worldString); // напечатает "Hello World!"
|
NSLog(@"Привет %@!", worldString); // напечатает "Привет Мир!"
|
||||||
|
// NSMutableString - это изменяемая версия NSString-объекта
|
||||||
|
NSMutableString *mutableString = [NSMutableString stringWithString:@"Привет"];
|
||||||
|
[mutableString appendString:@" Мир!"];
|
||||||
|
NSLog(@"%@", mutableString); // напечатает => "Привет Мир!"
|
||||||
|
|
||||||
// Символьные литералы
|
// Символьные литералы
|
||||||
NSNumber *theLetterZNumber = @'Z';
|
NSNumber *theLetterZNumber = @'Z';
|
||||||
char theLetterZ = [theLetterZNumber charValue];
|
char theLetterZ = [theLetterZNumber charValue]; // или 'Z'
|
||||||
NSLog(@"%c", theLetterZ);
|
NSLog(@"%c", theLetterZ);
|
||||||
|
|
||||||
// Целочисленный литералы
|
// Целочисленные литералы
|
||||||
NSNumber *fortyTwoNumber = @42;
|
NSNumber *fortyTwoNumber = @42;
|
||||||
int fortyTwo = [fortyTwoNumber intValue];
|
int fortyTwo = [fortyTwoNumber intValue]; // или '42'
|
||||||
NSLog(@"%i", fortyTwo);
|
NSLog(@"%i", fortyTwo);
|
||||||
|
|
||||||
// Беззнаковый целочисленный литерал
|
// Беззнаковый целочисленный литерал
|
||||||
NSNumber *fortyTwoUnsignedNumber = @42U;
|
NSNumber *fortyTwoUnsignedNumber = @42U;
|
||||||
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
|
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; // или 42
|
||||||
NSLog(@"%u", fortyTwoUnsigned);
|
NSLog(@"%u", fortyTwoUnsigned);
|
||||||
|
|
||||||
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
|
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
|
||||||
short fortyTwoShort = [fortyTwoShortNumber shortValue];
|
short fortyTwoShort = [fortyTwoShortNumber shortValue]; // или 42
|
||||||
NSLog(@"%hi", fortyTwoShort);
|
NSLog(@"%hi", fortyTwoShort);
|
||||||
|
|
||||||
|
NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41];
|
||||||
|
unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // или 41
|
||||||
|
NSLog(@"%u", fortyOneUnsigned);
|
||||||
|
|
||||||
NSNumber *fortyTwoLongNumber = @42L;
|
NSNumber *fortyTwoLongNumber = @42L;
|
||||||
long fortyTwoLong = [fortyTwoLongNumber longValue];
|
long fortyTwoLong = [fortyTwoLongNumber longValue]; // или 42
|
||||||
NSLog(@"%li", fortyTwoLong);
|
NSLog(@"%li", fortyTwoLong);
|
||||||
|
|
||||||
|
NSNumber *fiftyThreeLongNumber = @53L;
|
||||||
|
unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // или 53
|
||||||
|
NSLog(@"%lu", fiftyThreeUnsigned);
|
||||||
|
|
||||||
// Вещественный литерал
|
// Вещественный литерал
|
||||||
NSNumber *piFloatNumber = @3.141592654F;
|
NSNumber *piFloatNumber = @3.141592654F;
|
||||||
float piFloat = [piFloatNumber floatValue];
|
float piFloat = [piFloatNumber floatValue]; // или 3.141592654f
|
||||||
NSLog(@"%f", piFloat);
|
NSLog(@"%f", piFloat); // напечатает 3.141592654
|
||||||
|
NSLog(@"%5.2f", piFloat); // напечатает " 3.14"
|
||||||
|
|
||||||
NSNumber *piDoubleNumber = @3.1415926535;
|
NSNumber *piDoubleNumber = @3.1415926535;
|
||||||
double piDouble = [piDoubleNumber doubleValue];
|
double piDouble = [piDoubleNumber doubleValue]; // или 3.1415926535
|
||||||
NSLog(@"%f", piDouble);
|
NSLog(@"%f", piDouble);
|
||||||
|
NSLog(@"%4.2f", piDouble); // напечатает "3.14"
|
||||||
|
|
||||||
|
// NSDecimalNumber - это класс с фиксированной точкой, который является
|
||||||
|
// более точным, чем float или double
|
||||||
|
NSDecimalNumber *oneDecNum = [NSDecimalNumber decimalNumberWithString:@"10.99"];
|
||||||
|
NSDecimalNumber *twoDecNum = [NSDecimalNumber decimalNumberWithString:@"5.002"];
|
||||||
|
// NSDecimalNumber не способен использовать стандартные +, -, *, / операторы,
|
||||||
|
// поэтому он предоставляет свои собственные:
|
||||||
|
[oneDecNum decimalNumberByAdding:twoDecNum];
|
||||||
|
[oneDecNum decimalNumberBySubtracting:twoDecNum];
|
||||||
|
[oneDecNum decimalNumberByMultiplyingBy:twoDecNum];
|
||||||
|
[oneDecNum decimalNumberByDividingBy:twoDecNum];
|
||||||
|
NSLog(@"%@", oneDecNum); // напечатает "10.99", т.к. NSDecimalNumber - изменяемый
|
||||||
|
|
||||||
// BOOL (булевый) литерал
|
// BOOL (булевый) литерал
|
||||||
NSNumber *yesNumber = @YES;
|
NSNumber *yesNumber = @YES;
|
||||||
NSNumber *noNumber = @NO;
|
NSNumber *noNumber = @NO;
|
||||||
|
// или
|
||||||
|
BOOL yesBool = YES;
|
||||||
|
BOOL noBool = NO;
|
||||||
|
NSLog(@"%i", yesBool); // напечатает 1
|
||||||
|
|
||||||
// Массив
|
// Массив
|
||||||
|
// Может содержать различные типы данных, но должен быть объектом Objective-C
|
||||||
NSArray *anArray = @[@1, @2, @3, @4];
|
NSArray *anArray = @[@1, @2, @3, @4];
|
||||||
NSNumber *thirdNumber = anArray[2];
|
NSNumber *thirdNumber = anArray[2];
|
||||||
NSLog(@"Third number = %@", thirdNumber); // Print "Third number = 3"
|
NSLog(@"Третье число = %@", thirdNumber); // Напечатает "Третье число = 3"
|
||||||
|
// NSMutableArray - это изменяемая версия NSArray, допускающая вам изменять
|
||||||
|
// элементы в массиве и расширять или сокращать массив.
|
||||||
|
// Удобный, но не эффективный как NSArray.
|
||||||
|
NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:2];
|
||||||
|
[mutableArray addObject:@"Привет"];
|
||||||
|
[mutableArray addObject:@"Мир"];
|
||||||
|
[mutableArray removeObjectAtIndex:0];
|
||||||
|
NSLog(@"%@", [mutableArray objectAtIndex:0]); // напечатает "Мир"
|
||||||
|
|
||||||
// Словарь
|
// Словарь
|
||||||
NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
|
NSDictionary *aDictionary = @{ @"ключ1" : @"значение1", @"ключ2" : @"значение2" };
|
||||||
NSObject *valueObject = aDictionary[@"A Key"];
|
NSObject *valueObject = aDictionary[@"Ключ"];
|
||||||
NSLog(@"Object = %@", valueObject); // Напечатает "Object = (null)"
|
NSLog(@"Объект = %@", valueObject); // Напечатает "Объект = (null)"
|
||||||
|
// NSMutableDictionary тоже доступен, как изменяемый словарь
|
||||||
|
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:2];
|
||||||
|
[mutableDictionary setObject:@"значение1" forKey:@"ключ1"];
|
||||||
|
[mutableDictionary setObject:@"значение2" forKey:@"ключ2"];
|
||||||
|
[mutableDictionary removeObjectForKey:@"ключ1"];
|
||||||
|
|
||||||
|
// Множество
|
||||||
|
NSSet *set = [NSSet setWithObjects:@"Привет", @"Привет", @"Мир", nil];
|
||||||
|
NSLog(@"%@", set); // напечатает {(Hello, World)} (порядок может отличаться)
|
||||||
|
// NSMutableSet тоже доступен, как изменяемое множество
|
||||||
|
NSMutableSet *mutableSet = [NSMutableSet setWithCapacity:2];
|
||||||
|
[mutableSet addObject:@"Привет"];
|
||||||
|
[mutableSet addObject:@"Привет"];
|
||||||
|
NSLog(@"%@", mutableSet); // напечатает => {(Привет)}
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Операторы
|
// Операторы
|
||||||
@ -124,13 +189,13 @@ int main (int argc, const char * argv[])
|
|||||||
// Условный оператор
|
// Условный оператор
|
||||||
if (NO)
|
if (NO)
|
||||||
{
|
{
|
||||||
NSLog(@"I am never run");
|
NSLog(@"Я никогда не выполнюсь");
|
||||||
} else if (0)
|
} else if (0)
|
||||||
{
|
{
|
||||||
NSLog(@"I am also never run");
|
NSLog(@"Я тоже никогда не выполнюсь");
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
NSLog(@"I print");
|
NSLog(@"Я напечатаюсь");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ветвление с множественным выбором
|
// Ветвление с множественным выбором
|
||||||
@ -138,15 +203,15 @@ int main (int argc, const char * argv[])
|
|||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
NSLog(@"I am never run");
|
NSLog(@"Я никогда не выполнюсь");
|
||||||
} break;
|
} break;
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
NSLog(@"I am also never run");
|
NSLog(@"Я тоже никогда не выполнюсь");
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
NSLog(@"I print");
|
NSLog(@"Я напечатаюсь");
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +235,7 @@ int main (int argc, const char * argv[])
|
|||||||
// "2,"
|
// "2,"
|
||||||
// "3,"
|
// "3,"
|
||||||
|
|
||||||
// // Цикл просмотра
|
// Цикл просмотра
|
||||||
NSArray *values = @[@0, @1, @2, @3];
|
NSArray *values = @[@0, @1, @2, @3];
|
||||||
for (NSNumber *value in values)
|
for (NSNumber *value in values)
|
||||||
{
|
{
|
||||||
@ -180,20 +245,32 @@ int main (int argc, const char * argv[])
|
|||||||
// "2,"
|
// "2,"
|
||||||
// "3,"
|
// "3,"
|
||||||
|
|
||||||
|
// Цикл for для объектов. Может использоваться с любым объектом Objective-C
|
||||||
|
for (id item in values) {
|
||||||
|
NSLog(@"%@,", item);
|
||||||
|
} // напечатает => "0,"
|
||||||
|
// "1,"
|
||||||
|
// "2,"
|
||||||
|
// "3,"
|
||||||
|
|
||||||
// Обработка исключений
|
// Обработка исключений
|
||||||
@try
|
@try
|
||||||
{
|
{
|
||||||
// Ваше исключение здесь
|
// Ваше исключение здесь
|
||||||
@throw [NSException exceptionWithName:@"FileNotFoundException"
|
@throw [NSException exceptionWithName:@"FileNotFoundException"
|
||||||
reason:@"File Not Found on System" userInfo:nil];
|
reason:@"Файл не найден в системе" userInfo:nil];
|
||||||
} @catch (NSException * e)
|
} @catch (NSException * e)
|
||||||
{
|
{
|
||||||
NSLog(@"Exception: %@", e);
|
NSLog(@"Исключение: %@", e);
|
||||||
} @finally
|
} @finally
|
||||||
{
|
{
|
||||||
NSLog(@"Finally");
|
NSLog(@"В конце отводится время для очистки.");
|
||||||
} // => напечатает "Exception: File Not Found on System"
|
} // => напечатает "Исключение: Файл не найден в системе"
|
||||||
// "Finally"
|
// "В конце отводится время для очистки."
|
||||||
|
|
||||||
|
// NSError - это полезные объекты для аргументов функции, чтобы заполнить их
|
||||||
|
// пользовательскими ошибками.
|
||||||
|
NSError *error = [NSError errorWithDomain:@"Неправильный эл. адрес." code:4 userInfo:nil];
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Объекты
|
// Объекты
|
||||||
@ -203,13 +280,16 @@ int main (int argc, const char * argv[])
|
|||||||
// Объект не является полнофункциональным пока обе части не выполнятся.
|
// Объект не является полнофункциональным пока обе части не выполнятся.
|
||||||
MyClass *myObject = [[MyClass alloc] init];
|
MyClass *myObject = [[MyClass alloc] init];
|
||||||
|
|
||||||
// В Objective-C можель ООП базируется на передаче сообщений.
|
// В Objective-C модель ООП базируется на передаче сообщений.
|
||||||
// В Objective-C Вы не просто вызваете метод; вы посылаете сообщение.
|
// В Objective-C Вы не просто вызваете метод; вы посылаете сообщение.
|
||||||
[myObject instanceMethodWithParameter:@"Steve Jobs"];
|
[myObject instanceMethodWithParameter:@"Стив Джобс"];
|
||||||
|
|
||||||
// Очищайте память, перед завершением работы программы.
|
// Очищайте память, перед завершением работы программы.
|
||||||
[pool drain];
|
[pool drain];
|
||||||
|
|
||||||
|
// Конец @autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
// Конец программы.
|
// Конец программы.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -222,63 +302,144 @@ int main (int argc, const char * argv[])
|
|||||||
// Синтаксис объявления:
|
// Синтаксис объявления:
|
||||||
// @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы>
|
// @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы>
|
||||||
// {
|
// {
|
||||||
// Объявление переменных;
|
// тип имя; <= Объявление переменных;
|
||||||
// }
|
// }
|
||||||
|
// @property тип имя; <= объявление свойств
|
||||||
// -/+ (тип) Объявление метода(ов).
|
// -/+ (тип) Объявление метода(ов).
|
||||||
// @end
|
// @end
|
||||||
|
@interface MyClass : NSObject <MyProtocol> // NSObject - это базовый класс в Objective-C.
|
||||||
|
|
||||||
@interface MyClass : NSObject <MyProtocol>
|
|
||||||
{
|
{
|
||||||
int count;
|
// Объявления экземпляров переменных (может существовать в файлах интерфейса или реализвации)
|
||||||
id data;
|
int count; // По умолчанию защищенный доступ.
|
||||||
|
@private id data; // Приватный доступ (Намного удобнее объявлять в файле реализации)
|
||||||
NSString *name;
|
NSString *name;
|
||||||
}
|
}
|
||||||
// При объявлении свойств сразу генерируются геттер и сеттер
|
// Удобное обозначение для переменных с открытым (public) доступом
|
||||||
@property int count;
|
// автоматически генерируется сеттер-метод
|
||||||
@property (copy) NSString *name; // Скопировать объект в ходе присвоения.
|
// По умолчанию название сеттер-метода начинается с 'set' с последующим именем
|
||||||
@property (readonly) id data; // Генерация только геттера
|
// переменной из @property
|
||||||
|
@property int propInt; // Имя сеттер-метода = 'setPropInt'
|
||||||
|
@property (copy) id copyId; // (copy) => Скопировать объект в ходе присвоения.
|
||||||
|
// (readonly) => Не позволяет установить значение вне @interface
|
||||||
|
@property (readonly) NSString *roString; // Используйте @synthesize
|
||||||
|
// в @implementation, чтобы создать аксессор
|
||||||
|
// Вы можете настроить геттер и сеттер имена вместо используемого 'set'-имени по умолчанию:
|
||||||
|
@property (getter=lengthGet, setter=lengthSet:) int length;
|
||||||
|
|
||||||
// Методы
|
// Методы
|
||||||
+/- (return type)methodSignature:(Parameter Type *)parameterName;
|
+/- (возвращаемый тип)сигнатураМетода:(Параметр типа *)имяПараметра;
|
||||||
|
|
||||||
// + для методов класса
|
// + для методов класса
|
||||||
+ (NSString *)classMethod;
|
+ (NSString *)classMethod;
|
||||||
|
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight;
|
||||||
|
|
||||||
// - для метода объекта
|
// - для методов объекта
|
||||||
- (NSString *)instanceMethodWithParameter:(NSString *)string;
|
- (NSString *)instanceMethodWithParameter:(NSString *)string;
|
||||||
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
|
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
|
||||||
|
|
||||||
@end
|
// Методы-конструктор с аргументом:
|
||||||
|
- (id)initWithDistance:(int)defaultDistance;
|
||||||
|
// В Objective-C имена методов очень описательные. Всегда имена методов соответствуют своим аргументам
|
||||||
|
|
||||||
|
@end // Устанавливает конец интерфейса (interface)
|
||||||
|
|
||||||
|
|
||||||
|
// Чтобы обратиться к открытым (public) переменным из файла реализации, @property генерирует сеттер-метод
|
||||||
|
// автоматически. Название метода - это 'set' с последующим именем переменной из @property:
|
||||||
|
MyClass *myClass = [[MyClass alloc] init]; // создает экземпляр объекта класса MyClass
|
||||||
|
[myClass setCount:10];
|
||||||
|
NSLog(@"%d", [myClass count]); // напечатает => 10
|
||||||
|
// Или используйте свой геттер и сеттер методы, которые определены в @interface:
|
||||||
|
[myClass lengthSet:32];
|
||||||
|
NSLog(@"%i", [myClass lengthGet]); // напечатает => 32
|
||||||
|
// Для удобства вы можете использовать точечную нотацию,
|
||||||
|
// чтобы установить и получить доступ к переменным объекта:
|
||||||
|
myClass.count = 45;
|
||||||
|
NSLog(@"%i", myClass.count); // напечатает => 45
|
||||||
|
|
||||||
|
// Вызов методов класса:
|
||||||
|
NSString *classMethodString = [MyClass classMethod];
|
||||||
|
MyClass *classFromName = [MyClass myClassFromName:@"Привет"];
|
||||||
|
|
||||||
|
// Вызов методов экземпляра:
|
||||||
|
MyClass *myClass = [[MyClass alloc] init]; // Создает экземпляр объекта MyClass
|
||||||
|
NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Привет"];
|
||||||
|
|
||||||
|
// Селекторы
|
||||||
|
// Это способ динамически представить методы. Используйте для вызова методов класса, передайте методы
|
||||||
|
// через функции, чтобы сказать другим классам, что они должны вызвать их и сохранить методы
|
||||||
|
// как переменные
|
||||||
|
// SEL - это тип данных. @selector() вернет селектор из предоставленного имени метода
|
||||||
|
// methodAParameterAsString:andAParameterAsNumber: - это название метода в MyClass
|
||||||
|
SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:);
|
||||||
|
if ([myClass respondsToSelector:selectorVar]) { // Проверяет содержит ли класс метод
|
||||||
|
// Необходимо установить все аргументы метода в один объект, что отправить его в performSelector-функцию
|
||||||
|
NSArray *arguments = [NSArray arrayWithObjects:@"Привет", @4, nil];
|
||||||
|
[myClass performSelector:selectorVar withObject:arguments]; // Вызывает метод
|
||||||
|
} else {
|
||||||
|
// NSStringFromSelector() вернет NSString название метода полученного селектором
|
||||||
|
NSLog(@"MyClass не содержит метод: %@", NSStringFromSelector(selectedVar));
|
||||||
|
}
|
||||||
|
|
||||||
// Имплементируйте методы в файле МойКласс.m:
|
// Имплементируйте методы в файле МойКласс.m:
|
||||||
|
@implementation MyClass {
|
||||||
|
long distance; // Переменная экземпляра с закрытым (private) доступом
|
||||||
|
NSNumber height;
|
||||||
|
}
|
||||||
|
|
||||||
@implementation MyClass
|
// To access a public variable from the interface file, use '_' followed by variable name:
|
||||||
|
_count = 5; // References "int count" from MyClass interface
|
||||||
|
// Access variables defined in implementation file:
|
||||||
|
distance = 18; // References "long distance" from MyClass implementation
|
||||||
|
// To use @property variable in implementation, use @synthesize to create accessor variable:
|
||||||
|
@synthesize roString = _roString; // _roString available now in @implementation
|
||||||
|
|
||||||
|
// Called before calling any class methods or instantiating any objects
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
if (self == [MyClass class]) {
|
||||||
|
distance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Вызывается при высвобождении памяти под объектом
|
// Вызывается при высвобождении памяти под объектом
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
|
[height release]; // Если не используется ARC, убедитесь в освобождении переменных объекта класса
|
||||||
|
[super dealloc]; // and call parent class dealloc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Конструкторы – это способ осздания объектов класса.
|
// Конструкторы – это способ создания объектов класса.
|
||||||
// Это обычный конструктор вызываемый при создании объекта клсааа.
|
// Это конструктор по умолчанию, который вызывается, когда объект инициализируется.
|
||||||
- (id)init
|
- (id)init
|
||||||
{
|
{
|
||||||
if ((self = [super init]))
|
if ((self = [super init])) // 'super' используется для того, чтобы обратиться к методам родительского класса
|
||||||
{
|
{
|
||||||
self.count = 1;
|
self.count = 1; // 'self' используется для вызова самого себя
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
// Можно создать конструкторы, которые содержат аргументы:
|
||||||
|
- (id)initWithDistance:(int)defaultDistance
|
||||||
|
{
|
||||||
|
distance = defaultDistance;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSString *)classMethod
|
+ (NSString *)classMethod
|
||||||
{
|
{
|
||||||
return [[self alloc] init];
|
return [[self alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
|
||||||
|
{
|
||||||
|
height = defaultHeight;
|
||||||
|
return [[self alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *)instanceMethodWithParameter:(NSString *)string
|
- (NSString *)instanceMethodWithParameter:(NSString *)string
|
||||||
{
|
{
|
||||||
return @"New string";
|
return @"Новая строка";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
|
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
|
||||||
@ -286,23 +447,364 @@ int main (int argc, const char * argv[])
|
|||||||
return @42;
|
return @42;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Objective-C не содержит объявление приватных методов, но вы можете имитировать их.
|
||||||
|
// Чтобы сымитировать приватный метод, создайте метод в @implementation, но не в @interface.
|
||||||
|
- (NSNumber *)secretPrivateMethod {
|
||||||
|
return @72;
|
||||||
|
}
|
||||||
|
[self secretPrivateMethod]; // Вызывает приватный метод
|
||||||
|
|
||||||
// Методы объявленные в МyProtocol (см. далее)
|
// Методы объявленные в МyProtocol (см. далее)
|
||||||
- (void)myProtocolMethod
|
- (void)myProtocolMethod
|
||||||
{
|
{
|
||||||
// имплементация
|
// операторы
|
||||||
|
}
|
||||||
|
|
||||||
|
@end // Устанавливает конец реализации (implementation)
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Категории
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Категория - это группа методов предназначенные для того, чтобы расширить класс. Они позволяют вам добавить новые методы
|
||||||
|
// к существующему классу для организационных целей. Это не стоит путать с подклассами.
|
||||||
|
// Подклассы предназначены для ИЗМЕНЕНИЯ функциональности объекта пока как категории ДОБАВЛЯЮТ
|
||||||
|
// функциональность в объект.
|
||||||
|
// Категории позволяют вам:
|
||||||
|
// -- Добавлять методы в существующий класс для организационных целей.
|
||||||
|
// -- Допускает вам расширять объекты Objective-C классов (напр.: NSString) добавить ваши собственные методы.
|
||||||
|
// -- Добавляет возможность создать защищенные и закрытые методы классов.
|
||||||
|
// ПРИМЕЧАНИЕ: Не переопределяйте методы базового класса в категории даже если у вас есть возможность это сделать
|
||||||
|
// to. Переопределение методов может привести к ошибкам компиляции позднее между различными категориями и это
|
||||||
|
// нарушает цель категорий, чтобы добавлять только функциональность. Вместо этого подклассы переопределяют методы.
|
||||||
|
|
||||||
|
// Здесь простой базовый класс Car.
|
||||||
|
@interface Car : NSObject
|
||||||
|
|
||||||
|
@property NSString *make;
|
||||||
|
@property NSString *color;
|
||||||
|
|
||||||
|
- (void)turnOn;
|
||||||
|
- (void)accelerate;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// И реализация базового класса Car:
|
||||||
|
#import "Car.h"
|
||||||
|
|
||||||
|
@implementation Car
|
||||||
|
|
||||||
|
@synthesize make = _make;
|
||||||
|
@synthesize color = _color;
|
||||||
|
|
||||||
|
- (void)turnOn {
|
||||||
|
NSLog(@"Машина заведена.");
|
||||||
|
}
|
||||||
|
- (void)accelerate {
|
||||||
|
NSLog(@"Ускорение.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
// Теперь, если мы хотели создать грузовой объект, мы должны вместо создания подкласса класса Car, как это будет
|
||||||
|
// изменять функциональность Car чтобы вести себя подобно грузовику. Но давайте посмотрим, если мы хотим только добавить
|
||||||
|
// функциональность в существующий Car. Хороший пример должен быть чистить автомобиль. Итак мы создадим
|
||||||
|
// категорию для добавления его очистительных методов:
|
||||||
|
// @interface ИмяФайла: Car+Clean.h (ИмяБазовогоКласса+ИмяКатегории.h)
|
||||||
|
#import "Car.h" // Убедитесь в том, что базовый класс импортирован для расширения.
|
||||||
|
|
||||||
|
@interface Car (Clean) // Имя категории внутри (), следующие после имени базового класса.
|
||||||
|
|
||||||
|
- (void)washWindows; // Названия новых методов, которые мы добавляем в наш объект Car.
|
||||||
|
- (void)wax;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// @implementation имя файла: Car+Clean.m (ИмяБазовогоКласса+ИмяКатегории.m)
|
||||||
|
#import "Car+Clean.h" // Импортируйте Очистку файл @interface категории.
|
||||||
|
|
||||||
|
@implementation Car (Clean)
|
||||||
|
|
||||||
|
- (void)washWindows {
|
||||||
|
NSLog(@"Окна промыли.");
|
||||||
|
}
|
||||||
|
- (void)wax {
|
||||||
|
NSLog(@"Воском натерли.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// Любой экземпляр объекта Car имеет возможность воспользоваться категорией. Все, что нужно сделать, это импортировать ее:
|
||||||
|
#import "Car+Clean.h" // Импортировать как множество различных категорий, как вы хотите использовать.
|
||||||
|
#import "Car.h" // Кроме того, необходимо импортировать базовый класс для использования его оригинальные функциональные возможности.
|
||||||
|
|
||||||
|
int main (int argc, const char * argv[]) {
|
||||||
|
@autoreleasepool {
|
||||||
|
Car *mustang = [[Car alloc] init];
|
||||||
|
mustang.color = @"Красный";
|
||||||
|
mustang.make = @"Форд";
|
||||||
|
|
||||||
|
[mustang turnOn]; // Используйте методы из базового класса Car.
|
||||||
|
[mustang washWindows]; // Используйте методы категории Clean из класса Car.
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Objective-C не поддерживает объявление защищенных методов, но вы можете имитировать их.
|
||||||
|
// Создайте категорию, содержащую все защищенные методы, затем импортируйте ее только в
|
||||||
|
// @implementation-файле класса, относящегося к классу Car:
|
||||||
|
@interface Car (Protected) // Наименование категории с помощью 'Protected'
|
||||||
|
// дает знать, что методы защищенные.
|
||||||
|
|
||||||
|
- (void)lockCar; // Здесь перечисляются методы, которые должны быть созданы
|
||||||
|
// только с помощью объектов класса Car.
|
||||||
|
|
||||||
|
@end
|
||||||
|
// Чтобы воспользоваться защищенными методами, импортируйте категорию, затем реализуйте методы:
|
||||||
|
#import "Car+Protected.h" // Запомните, делайте импорт только в файле с @implementation.
|
||||||
|
|
||||||
|
@implementation Car
|
||||||
|
|
||||||
|
- (void)lockCar {
|
||||||
|
NSLog(@"Машина закрыта."); // Экземпляры класса Car не могут использовать
|
||||||
|
// метод lockCar, потому что он объявлен не в @interface.
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Расширения
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Расширения позволяют вам переопределять атрибуты свойств и методов
|
||||||
|
// с открытым доступом в @interface.
|
||||||
|
// @interface имя файла: Shape.h
|
||||||
|
@interface Shape : NSObject // Расширение базового класса Shape переопределяет
|
||||||
|
// свои поля ниже.
|
||||||
|
|
||||||
|
@property (readonly) NSNumber *numOfSides;
|
||||||
|
|
||||||
|
- (int)getNumOfSides;
|
||||||
|
|
||||||
|
@end
|
||||||
|
// Вы можете переопределить numOfSides-переменную или getNumOfSides-метод
|
||||||
|
// Внесение изменений с помощью расширения делается следующим образом:
|
||||||
|
// @implementation имя файла: Shape.m
|
||||||
|
#import "Shape.h"
|
||||||
|
// Расширения "живут" в том же файле, где и @implementation класса.
|
||||||
|
@interface Shape () // После имени базового класса скобки () объявляют расширение.
|
||||||
|
|
||||||
|
@property (copy) NSNumber *numOfSides; // Делает numOfSides-свойство
|
||||||
|
// копирующим (copy) вместо свойства только для чтения (readonly).
|
||||||
|
-(NSNumber)getNumOfSides; // Изменяет метод getNumOfSides так,
|
||||||
|
// чтобы он возвращал объект NSNumber вместо типа int.
|
||||||
|
-(void)privateMethod; // Вы также можете создать новый закрытый метод
|
||||||
|
// внутри расширения.
|
||||||
|
|
||||||
|
@end
|
||||||
|
// Главный @implementation:
|
||||||
|
@implementation Shape
|
||||||
|
|
||||||
|
@synthesize numOfSides = _numOfSides;
|
||||||
|
|
||||||
|
-(NSNumber)getNumOfSides { // Все операторы внутри расширения
|
||||||
|
// должны быть в @implementation.
|
||||||
|
return _numOfSides;
|
||||||
|
}
|
||||||
|
-(void)privateMethod {
|
||||||
|
NSLog(@"Закрытый метод созданный с помощью расширения.");
|
||||||
|
NSLog(@"Экземпляр Shape не может вызвать этот метод.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Протоколы
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Протокол объявляет методы, которые могут быть реализованы с помощью
|
||||||
|
// любого класса. Протоколы сами по себе не являются классами. Они просто
|
||||||
|
// определяют интерфейс, который должен быть реализован другими объектами.
|
||||||
|
// @protocol имя файла: "CarUtilities.h"
|
||||||
|
@protocol CarUtilities <NSObject> // <NSObject> => Имя другого протокола,
|
||||||
|
// который включен в этот протокол.
|
||||||
|
@property BOOL engineOn; // Адаптирующий класс должен определить
|
||||||
|
// все @synthesize для @property и
|
||||||
|
- (void)turnOnEngine; // определить все методы.
|
||||||
|
@end
|
||||||
|
// Ниже пример класса, реализующий протокол.
|
||||||
|
#import "CarUtilities.h" // Импорт файла с @protocol.
|
||||||
|
|
||||||
|
@interface Car : NSObject <CarUtilities> // Внутри <> имя протокола
|
||||||
|
// Здесь вам не нужно указывать @property или имена методов для CarUtilities.
|
||||||
|
// Они нужны только для @implementation.
|
||||||
|
- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // Вы также можете
|
||||||
|
// указать тип протоколов.
|
||||||
|
@end
|
||||||
|
// В @implementation нужно реализовать все @property и методы для протокола.
|
||||||
|
@implementation Car : NSObject <CarUtilities>
|
||||||
|
|
||||||
|
@synthesize engineOn = _engineOn; // Создайте @synthesize-оператор
|
||||||
|
// для "@property engineOn".
|
||||||
|
|
||||||
|
- (void)turnOnEngine { // Реализуйте turnOnEngine как вам угодно. Протоколы
|
||||||
|
// не определят,
|
||||||
|
_engineOn = YES; // как вам реализовать метод, он только требует,
|
||||||
|
// чтобы вы реализовали его.
|
||||||
|
}
|
||||||
|
// Вы можете использовать протокол как данные, если вы знаете, что он реализует
|
||||||
|
// методы и переменные.
|
||||||
|
- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind {
|
||||||
|
[objectOfSomeKind engineOn]; // У вас есть доступ к переменным объекта
|
||||||
|
[objectOfSomeKind turnOnEngine]; // и методам.
|
||||||
|
[objectOfSomeKind engineOn]; // Может или не может быть значение YES. Класс
|
||||||
|
// реализует как нужно.
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
// Экземпляры класса Car сейчас имеют доступ к протоколу.
|
||||||
|
Car *carInstance = [[Car alloc] init];
|
||||||
|
[carInstance setEngineOn:NO];
|
||||||
|
[carInstance turnOnEngine];
|
||||||
|
if ([carInstance engineOn]) {
|
||||||
|
NSLog(@"Двигатель запущен."); // напечатает => "Двигатель запущен."
|
||||||
|
}
|
||||||
|
// Убедитись в том, что объект типа 'id' реализует протокол перед вызовом методов протокола:
|
||||||
|
if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
|
||||||
|
NSLog(@"Не работает, т.к. класс MyClass не реализует протокол CarUtilities.");
|
||||||
|
} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) {
|
||||||
|
NSLog(@"Работает как класс Car, который реализует протокол CarUtilities.");
|
||||||
|
}
|
||||||
|
// Категории тоже могут реализовать протоколы:
|
||||||
|
// @interface Car (CarCategory) <CarUtilities>
|
||||||
|
// Вы можете реализовать много протоколов:
|
||||||
|
// @interface Car : NSObject <CarUtilities, CarCleaning>
|
||||||
|
// ЗАМЕЧАНИЕ: Если два или более протоколов полагаются друг на друга,
|
||||||
|
// убедитесь, что они ранее объявлены:
|
||||||
|
#import "Brother.h"
|
||||||
|
|
||||||
|
@protocol Brother; // Оператор раннего объявления. Без него компилятор
|
||||||
|
// выдаст ошибку.
|
||||||
|
|
||||||
|
@protocol Sister <NSObject>
|
||||||
|
|
||||||
|
- (void)beNiceToBrother:(id <Brother>)brother;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// Рассмотрите проблему, где протокол Sister полагается на протокол Brother,
|
||||||
|
// а Brother полагается на Sister.
|
||||||
|
#import "Sister.h"
|
||||||
|
|
||||||
|
@protocol Sister; // Эти строки предотвращают рекурсию, решая этим проблему.
|
||||||
|
|
||||||
|
@protocol Brother <NSObject>
|
||||||
|
|
||||||
|
- (void)beNiceToSister:(id <Sister>)sister;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Блоки
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Блоки - это операторы кода, наподобие функции, которую возможно использовать
|
||||||
|
// как данные.
|
||||||
|
// Ниже простой блок с целочисленным аргументом, и возвращает аргумент плюс 4.
|
||||||
|
int (^addUp)(int n); // Объявите переменную, чтобы сохранить блок.
|
||||||
|
void (^noParameterBlockVar)(void); // Пример объявления блока-переменной
|
||||||
|
// без аргументов.
|
||||||
|
// Блоки имею доступ к переменным в той же области видимости. Но переменные
|
||||||
|
// будут только для чтения, и значения переданных в блок станут значением
|
||||||
|
// переменной, когда блок создастся.
|
||||||
|
int outsideVar = 17; // Если мы редактируем outsideVar после объявления addUp,
|
||||||
|
// outsideVar остается равным 17.
|
||||||
|
__block long mutableVar = 3; // __block делают переменные перезаписываемыми
|
||||||
|
// в блоках, в отличие от outsideVar.
|
||||||
|
addUp = ^(int n) { // Удалите (int n) в блоке, чтобы не принимать
|
||||||
|
// какие-либо параметры.
|
||||||
|
NSLog(@"Вы можете иметь столько строк в блоке, сколько вы хотели.");
|
||||||
|
NSSet *blockSet; // Также вы можете объявить локальные переменные.
|
||||||
|
mutableVar = 32; // Присвоить новое значение к __block-переменной.
|
||||||
|
return n + outsideVar; // Необязательный оператор возврата.
|
||||||
|
}
|
||||||
|
int addUp = add(10 + 16); // Вызывает блок кода с аргументами.
|
||||||
|
// Блоки часто используются как аргументы функции, чтобы позже их вызвать, или
|
||||||
|
// как функции обратного вызова (callbacks).
|
||||||
|
@implementation BlockExample : NSObject
|
||||||
|
|
||||||
|
- (void)runBlock:(void (^)(NSString))block {
|
||||||
|
NSLog(@"В аргументе блок ничего не возвращает и принимает NSString-объект.");
|
||||||
|
block(@"Аргумент передан блоку на исполнение."); // Вызов блока.
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Управление памятью
|
||||||
|
///////////////////////////////////////
|
||||||
/*
|
/*
|
||||||
* Протокол объявляет методы которые должны быть имплементированы
|
Для каждого объекта, используемого в приложении, должна быть выделена память
|
||||||
* Протокол не является классом. Он просто определяет интерфейс,
|
для таких объектов. Когда приложение прекращает использование объекта, память
|
||||||
* который должен быть имплементирован.
|
должна быть освобождена, чтобы гарантировать эффективность приложения.
|
||||||
|
Objective-C не использует сборщик мусора, а вместо этого применяет подсчет ссылок.
|
||||||
|
Пока существует по крайней мере одна ссылка на объект (также называется
|
||||||
|
"владение" объектом), то объект будет доступен к использованию (еще известно
|
||||||
|
как "право владения").
|
||||||
|
|
||||||
|
Когда экземпляр владеет объектом, его ссылка увеличивается на один. Когда
|
||||||
|
объекта освобождается, счетчик ссылки уменьшается на один. Когда счетчик ссылки
|
||||||
|
равен нулю, объект удаляется из памяти.
|
||||||
|
|
||||||
|
Над всеми объектами взаимодействуют, следуя паттерну:
|
||||||
|
(1) создание объекта, (2) использование объекта, (3) затем освобождение объекта из памяти.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@protocol MyProtocol
|
MyClass *classVar = [MyClass alloc]; // 'alloc' устанавливает счетчик ссылки
|
||||||
- (void)myProtocolMethod;
|
// объекта classVar на 1 и возвращает указатель на объект.
|
||||||
@end
|
[classVar release]; // Уменьшает счетчик ссылки объекта classVar
|
||||||
|
// 'retain' заявляет право собственности на существующий экземпляр объекта
|
||||||
|
// и увеличивает счетчик ссылки. Затем вернет указатель на объект.
|
||||||
|
MyClass *newVar = [classVar retain]; // Если classVar освободится, объект
|
||||||
|
// останется в памяти, потому что newVar - владелец
|
||||||
|
[classVar autorelease]; // Удалит право на владение объектом
|
||||||
|
// в конце @autoreleasepool блока. Вернет указатель на объект.
|
||||||
|
|
||||||
|
// @property может использовать 'retain' и 'assign' тоже для маленького
|
||||||
|
// удобного определения
|
||||||
|
@property (retain) MyClass *instance; // Освободит старое значение и сохранит
|
||||||
|
// одно новое (строгая ссылка)
|
||||||
|
@property (assign) NSSet *set; // Укажет на новое значение
|
||||||
|
// без сохранения/освобождения старого значения (слабая ссылка)
|
||||||
|
|
||||||
|
// Автоматический подсчет ссылок (ARC)
|
||||||
|
// Управление памятью может быть трудным, поэтому в Xcode 4.2 и iOS 4 введен
|
||||||
|
// автоматический подсчет ссылок (ARC).
|
||||||
|
// ARC - это особенность компилятора, который помещает "retain", "release"
|
||||||
|
// и "autorelease" автоматически за вас тогда, когда используется ARC,
|
||||||
|
// вам не нужно больше обращаться к "retain", "relase" или "autorelease"
|
||||||
|
MyClass *arcMyClass = [[MyClass alloc] init];
|
||||||
|
// ... код, использующий объект arcMyClass
|
||||||
|
// Без ARC, вам нужно было бы вызвать: [arcMyClass release] после того, как вы
|
||||||
|
// завершите работу с объектом arcMyClass. Но с ARC,
|
||||||
|
// теперь этого не нужно делать. Он будет помещать release-вызов за вас
|
||||||
|
|
||||||
|
// Что касается 'assign' и 'retain' @property атрибутов, в ARC вы должны
|
||||||
|
// использовать 'weak' и 'strong'
|
||||||
|
@property (weak) MyClass *weakVar; // 'weak' не принимает право на владение
|
||||||
|
// объектом. Если исходный счетчик ссылки экземпляра обнуляется,
|
||||||
|
// weakVar-свойство автоматически примет значение nil,
|
||||||
|
// во избежание падения приложения
|
||||||
|
@property (strong) MyClass *strongVar; // 'strong' принимает право на владение
|
||||||
|
// объектом. Гарантирует, что объект останится в памяти для использования
|
||||||
|
|
||||||
|
// Для обычных переменных (не объявленных с помощью @property), используйте
|
||||||
|
// следующий способ:
|
||||||
|
__strong NSString *strongString; // По умолчанию. Переменная сохраняется в памяти,
|
||||||
|
// пока она не покинет область видимости
|
||||||
|
__weak NSSet *weakSet; // Слабая ссылка на существующий объект. Когда существующий
|
||||||
|
// объект освобождается, weakSet принимает nil
|
||||||
|
__unsafe_unretained NSArray *unsafeArray; // Похож на __weak, но unsafeArray
|
||||||
|
// не принимает nil, когда существующий объект освобождается
|
||||||
|
|
||||||
```
|
```
|
||||||
## На почитать
|
## На почитать
|
||||||
|
|
||||||
|
@ -173,6 +173,8 @@ array[1..3] #=> [2, 3, 4]
|
|||||||
|
|
||||||
# Add to an array like this
|
# Add to an array like this
|
||||||
array << 6 #=> [1, 2, 3, 4, 5, 6]
|
array << 6 #=> [1, 2, 3, 4, 5, 6]
|
||||||
|
# Or like this
|
||||||
|
array.push(6) #=> [1, 2, 3, 4, 5, 6]
|
||||||
|
|
||||||
# Check if an item exists in an array
|
# Check if an item exists in an array
|
||||||
array.include?(1) #=> true
|
array.include?(1) #=> true
|
||||||
|
12
tcl.html.markdown
Executable file → Normal file
12
tcl.html.markdown
Executable file → Normal file
@ -121,7 +121,8 @@ puts lots\nof\n\n\n\n\n\nnewlines
|
|||||||
|
|
||||||
|
|
||||||
# A word enclosed in braces is not subject to any special interpretation or
|
# A word enclosed in braces is not subject to any special interpretation or
|
||||||
# substitutions, except that a backslash before a brace is not counted when look#ing for the closing brace
|
# substitutions, except that a backslash before a brace is not counted when
|
||||||
|
# looking for the closing brace
|
||||||
set somevar {
|
set somevar {
|
||||||
This is a literal $ sign, and this \} escaped
|
This is a literal $ sign, and this \} escaped
|
||||||
brace remains uninterpreted
|
brace remains uninterpreted
|
||||||
@ -163,7 +164,7 @@ set greeting "Hello, $person(name)"
|
|||||||
# A namespace holds commands and variables
|
# A namespace holds commands and variables
|
||||||
namespace eval people {
|
namespace eval people {
|
||||||
namespace eval person1 {
|
namespace eval person1 {
|
||||||
set name Neo
|
variable name Neo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +190,10 @@ set greeting "Hello $people::person1::name"
|
|||||||
namespace delete ::
|
namespace delete ::
|
||||||
|
|
||||||
|
|
||||||
# Because of name resolution behaviour, it's safer to use the "variable" command to declare or to assign a value to a namespace.
|
# Because of name resolution behaviour, it's safer to use the "variable" command to
|
||||||
|
# declare or to assign a value to a namespace. If a variable called "name" already
|
||||||
|
# exists in the global namespace, using "set" here will assign a value to the global variable
|
||||||
|
# instead of creating a new variable in the local namespace.
|
||||||
namespace eval people {
|
namespace eval people {
|
||||||
namespace eval person1 {
|
namespace eval person1 {
|
||||||
variable name Neo
|
variable name Neo
|
||||||
@ -256,7 +260,7 @@ proc greet greeting\ name return\ \"Hello,\ \$name!
|
|||||||
proc fold {cmd args} {
|
proc fold {cmd args} {
|
||||||
set res 0
|
set res 0
|
||||||
foreach arg $args {
|
foreach arg $args {
|
||||||
set res [cmd $res $arg]
|
set res [$cmd $res $arg]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fold ::tcl::mathop::* 5 3 3 ;# -> 45
|
fold ::tcl::mathop::* 5 3 3 ;# -> 45
|
||||||
|
Loading…
Reference in New Issue
Block a user