2015-01-19 14:40:07 +00:00
---
language: swift
contributors:
- ["Grant Timmerman", "http://github.com/grant"]
- ["Christopher Bess", "http://github.com/cbess"]
2015-03-04 08:07:48 +00:00
- ["Joey Huang", "http://github.com/kamidox"]
2016-10-08 20:29:13 +00:00
- ["Alexey Nazaroff", "http://github.com/rogaven"]
2015-01-19 14:54:12 +00:00
filename: learnswift-ru.swift
2015-01-19 14:40:07 +00:00
translators:
- ["Dmitry Bessonov", "https://github.com/TheDmitry"]
2016-10-08 20:29:13 +00:00
- ["Alexey Nazaroff", "https://github.com/rogaven"]
2015-01-19 14:40:07 +00:00
lang: ru-ru
---
2015-01-25 11:56:52 +00:00
Swift - это язык программирования, созданный компанией Apple, для приложений
под iOS и OS X. Разработанный, чтобы сосуществовать с Objective-C и
2015-01-19 14:40:07 +00:00
быть более устойчивым к ошибочному коду, Swift был представлен в 2014 году на
конференции разработчиков Apple, WWDC. Приложения на Swift собираются
2015-01-25 11:56:52 +00:00
с помощью LLVM-компилятора, включенного в Xcode 6+.
2015-01-19 14:40:07 +00:00
Официальная книга по [языку программирования Swift ](https://itunes.apple.com/us/book/swift-programming-language/id881256329 ) от Apple доступна в iBooks.
2015-01-28 08:24:31 +00:00
Смотрите еще [начальное руководство ](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html ) Apple, которое содержит полное учебное пособие по Swift.
2015-01-19 14:40:07 +00:00
```swift
2016-10-08 20:29:13 +00:00
// Версия Swift: 3.0
2015-01-19 14:40:07 +00:00
// импорт модуля
import UIKit
//
// MARK: Основы
//
2015-01-25 11:56:52 +00:00
// Xcode поддерживает маркеры, чтобы давать примечания своему коду
2015-01-19 14:40:07 +00:00
// и вносить их в список обозревателя (Jump Bar)
// MARK: Метка раздела
2016-10-08 20:29:13 +00:00
// MARK: - Метка с разделителем
2015-01-19 14:40:07 +00:00
// TODO: Сделайте что-нибудь вскоре
// FIXME: Исправьте этот код
2016-10-08 20:29:13 +00:00
// Начиная с о второй версии Swift, println и print объединены в методе print.
// Перенос строки теперь добавляется в конец автоматически.
print("Привет, мир!") // println – теперь просто print
print("Привет, мир!", terminator: "") // вывод текста без переноса строки
2015-01-19 14:40:07 +00:00
// переменные (var), значение которых можно изменить после инициализации
// константы (let), значение которых нельзя изменить после инициализации
var myVariable = 42
let øπΩ = "значение" // именование переменной символами unicode
let π = 3.1415926
let convenience = "Ключевое слово" // контекстное имя переменной
let weak = "Ключевое слово"; let override = "еще ключевое слово" // операторы
// могут быть отделены точкой с запятой
2015-01-25 11:56:52 +00:00
let `class` = "Ключевое слово" // обратные апострофы позволяют использовать
2015-01-19 14:40:07 +00:00
// ключевые слова в именовании переменных
let explicitDouble: Double = 70
let intValue = 0007 // 7
let largeIntValue = 77_000 // 77000
let label = "некоторый текст " + String(myVariable) // Приведение типа
let piText = "Pi = \(π), Pi 2 = \(π * 2)" // Вставка переменных в строку
// Сборка особых значений
// используя ключ -D сборки конфигурации
#if false
2016-10-08 20:29:13 +00:00
print("Н е печатается")
2015-01-19 14:40:07 +00:00
let buildValue = 3
#else
let buildValue = 7
#endif
2016-10-08 20:29:13 +00:00
print("Значение сборки: \(buildValue)") // Значение сборки: 7
2015-01-19 14:40:07 +00:00
/*
2015-01-25 11:56:52 +00:00
Опционалы - это особенность языка Swift, которая допускает вам сохранять
2015-01-19 14:40:07 +00:00
`некоторое` или `никакое` значения.
Язык Swift требует, чтобы каждое свойство имело значение, поэтому даже nil
2015-01-25 11:56:52 +00:00
должен быть явно сохранен как опциональное значение.
2015-01-19 14:40:07 +00:00
Optional< T > является перечислением.
*/
2015-01-25 11:56:52 +00:00
var someOptionalString: String? = "опционал" // Может быть nil
// как и выше, только ? - это постфиксный оператор (синтаксический с а х а р )
var someOptionalString2: Optional< String > = "опционал"
2015-01-19 14:40:07 +00:00
if someOptionalString != nil {
// я не nil
if someOptionalString!.hasPrefix("opt") {
2016-10-08 20:29:13 +00:00
print("содержит префикс")
2015-01-19 14:40:07 +00:00
}
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
let empty = someOptionalString?.isEmpty
}
someOptionalString = nil
2016-10-08 20:29:13 +00:00
/*
Использование ! для доступа к несуществующему опциональному значению генерирует
рантайм ошибку. Всегда проверяйте, что опционал содержит не пустое значение,
перед тем как раскрывать е г о через !.
*/
2015-01-25 11:56:52 +00:00
// неявная развертка опциональной переменной
2015-01-19 14:40:07 +00:00
var unwrappedString: String! = "Ожидаемое значение."
2015-01-25 11:56:52 +00:00
// как и выше, только ! - постфиксный оператор (с еще одним синтаксическим сахаром)
2015-01-19 14:40:07 +00:00
var unwrappedString2: ImplicitlyUnwrappedOptional< String > = "Ожидаемое значение."
2016-10-08 20:29:13 +00:00
// If let конструкции -
// If let это специальная конструкция в Swift, которая позволяет проверить Optional
// справа от `=` непустой, и если это так - разворачивает е г о и присваивает левой части.
2015-01-19 14:40:07 +00:00
if let someOptionalStringConstant = someOptionalString {
2016-10-08 20:29:13 +00:00
// имеется некоторое (`Some`) значение, не `nil`
2015-01-19 14:40:07 +00:00
if !someOptionalStringConstant.hasPrefix("ok") {
// нет такого префикса
}
}
2015-01-25 11:56:52 +00:00
// Swift поддерживает сохранение значения любого типа
2016-10-08 20:29:13 +00:00
// Для этих целей есть два ключевых слова `Any` и `AnyObject`
2015-01-19 14:40:07 +00:00
// AnyObject == id
2016-10-08 20:29:13 +00:00
// `Any` же, в отличие от `id` в Objective-C, `Any` работает с любым значением (Class, Int, struct и т.д.)
var anyVar: Any = 7
anyVar = "Изменять значение на строку не является хорошей практикой, но возможно."
let anyObjectVar: AnyObject = Int(1) as NSNumber
2015-01-19 14:40:07 +00:00
/*
Комментируйте здесь
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
/*
Вложенные комментарии тоже поддерживаются
*/
*/
//
// MARK: Коллекции
//
/*
Массив (Array) и словарь (Dictionary) являются структурами (struct). Так
`let` и `var` также означают, что они изменяются (var) или не изменяются (let)
2015-01-25 11:56:52 +00:00
при объявлении переменных этих типов.
2015-01-19 14:40:07 +00:00
*/
// Массив
var shoppingList = ["сом", "вода", "лимоны"]
shoppingList[1] = "бутылка воды"
let emptyArray = [String]() // let == неизменный
let emptyArray2 = Array< String > () // как и выше
var emptyMutableArray = [String]() // var == изменяемый
2016-10-08 20:29:13 +00:00
var explicitEmptyMutableStringArray: [String] = [] // так же как и выше
2015-01-19 14:40:07 +00:00
// Словарь
var occupations = [
"Malcolm": "Капитан",
"kaylee": "Техник"
]
occupations["Jayne"] = "Связи с общественностью"
let emptyDictionary = [String: Float]() // let == неизменный
let emptyDictionary2 = Dictionary< String , Float > () // как и выше
var emptyMutableDictionary = [String: Float]() // var == изменяемый
2016-10-08 20:29:13 +00:00
var explicitEmptyMutableDictionary: [String: Float] = [:] // то же
2015-01-19 14:40:07 +00:00
//
// MARK: Поток управления
//
2016-10-08 20:29:13 +00:00
// С помощью "," можно указать дополнительные условия для раскрытия
// опциональных значений.
let someNumber = Optional< Int > (7)
if let num = someNumber, num > 3 {
print("Больше 3х ")
}
2015-01-19 14:40:07 +00:00
// цикл for для массива
let myArray = [1, 1, 2, 3, 5]
for value in myArray {
if value == 1 {
2016-10-08 20:29:13 +00:00
print("Один!")
2015-01-19 14:40:07 +00:00
} else {
2016-10-08 20:29:13 +00:00
print("Н е один!")
2015-01-19 14:40:07 +00:00
}
}
// цикл for для словаря
var dict = ["один": 1, "два": 2]
for (key, value) in dict {
2016-10-08 20:29:13 +00:00
print("\(key): \(value)")
2015-01-19 14:40:07 +00:00
}
// цикл for для диапазона чисел
for i in -1...shoppingList.count {
2016-10-08 20:29:13 +00:00
print(i)
2015-01-19 14:40:07 +00:00
}
shoppingList[1...2] = ["бифштекс", "орехи пекан"]
// используйте ..< для исключения последнего числа
// цикл while
var i = 1
while i < 1000 {
i *= 2
}
// цикл do-while
2016-10-08 20:29:13 +00:00
repeat {
print("привет")
2015-01-19 14:40:07 +00:00
} while 1 == 2
// Переключатель
// Очень мощный оператор, представляйте с е б е операторы `if` с синтаксическим
// сахаром
// Они поддерживают строки, объекты и примитивы (Int, Double, etc)
let vegetable = "красный перец"
switch vegetable {
case "сельдерей":
2015-01-21 10:24:34 +00:00
let vegetableComment = "Добавьте немного изюма, имитируя муравьев на бревнышке."
2015-01-25 11:56:52 +00:00
case "огурец", "кресс-салат":
2015-01-19 14:40:07 +00:00
let vegetableComment = "Было бы неплохо сделать бутерброд с чаем."
case let localScopeValue where localScopeValue.hasSuffix("перец"):
let vegetableComment = "Это острый \(localScopeValue)?"
2015-01-25 11:56:52 +00:00
default: // обязательный (чтобы предусмотреть все возможные вхождения)
let vegetableComment = "В супе все овощи вкусные."
2015-01-19 14:40:07 +00:00
}
//
// MARK: Функции
//
// Функции являются типом первого класса, т.е . они могут быть вложены в функциях
// и могут передаваться между собой
2016-10-08 20:29:13 +00:00
// Функция с документированным заголовком Swift (формат Swift-модифицированный Markdown)
2015-01-19 14:40:07 +00:00
/**
Операция приветствия
2015-01-25 11:56:52 +00:00
- Маркер в документировании
- Еще один маркер в документации
2015-01-19 14:40:07 +00:00
2016-10-08 20:29:13 +00:00
- Parameter name : Это имя
- Parameter day : Это день
- Returns : Строка, содержащая значения name и day.
2015-01-19 14:40:07 +00:00
*/
func greet(name: String, day: String) -> String {
return "Привет \(name), сегодня \(day)."
}
2016-10-08 20:29:13 +00:00
greet(name: "Боб", day: "вторник")
2015-01-19 14:40:07 +00:00
// как и выше, кроме обращения параметров функции
2016-10-08 20:29:13 +00:00
func greet2(name: String, externalParamName localParamName: String) -> String {
return "Привет \(name), сегодня \(localParamName)"
2015-01-19 14:40:07 +00:00
}
2016-10-08 20:29:13 +00:00
greet2(name: "Иван", externalParamName: "Воскресенье")
2015-01-19 14:40:07 +00:00
// Функция, которая возвращает множество элементов в кортеже
func getGasPrices() -> (Double, Double, Double) {
return (3.59, 3.69, 3.79)
}
let pricesTuple = getGasPrices()
let price = pricesTuple.2 // 3.79
// Пропускайте значения кортежей с помощью подчеркивания _
let (_, price1, _) = pricesTuple // price1 == 3.69
2016-10-08 20:29:13 +00:00
print(price1 == pricesTuple.1) // вывод: true
print("Цена газа: \(price)")
// Именованные параметры кортежа
func getGasPrices2() -> (lowestPrice: Double, highestPrice: Double, midPrice: Double) {
return (1.77, 37.70, 7.37)
}
let pricesTuple2 = getGasPrices2()
let price2 = pricesTuple2.lowestPrice
let (_, price3, _) = pricesTuple2
print(pricesTuple2.highestPrice == pricesTuple2.1) // вывод: true
print("Самая высокая цена за газ: \(pricesTuple2.highestPrice)")
// guard утверждения
func testGuard() {
// guards обеспечивают прерывание дальнейшего выполнения функции,
// позволяя держать обработчики ошибок рядом с проверкой условия
// Объявляемая переменная находится в той же области видимости, что и guard.
guard let aNumber = Optional< Int > (7) else {
return
}
print("число равно \(aNumber)")
}
testGuard()
2015-01-19 14:40:07 +00:00
// Переменное число аргументов
func setup(numbers: Int...) {
// это массив
let number = numbers[0]
let argCount = numbers.count
}
// Передача и возврат функций
2016-10-08 20:29:13 +00:00
func makeIncrementer() -> ((Int) -> Int) {
2015-01-19 14:40:07 +00:00
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
// передача по ссылке
2016-10-08 20:29:13 +00:00
func swapTwoInts(a: inout Int, b: inout Int) {
2015-01-19 14:40:07 +00:00
let tempA = a
a = b
b = tempA
}
var someIntA = 7
var someIntB = 3
2016-10-08 20:29:13 +00:00
swapTwoInts(a: & someIntA, b: & someIntB)
print(someIntB) // 7
2015-01-19 14:40:07 +00:00
//
// MARK: Замыкания
//
var numbers = [1, 2, 6]
// Функции - это частный случай замыканий ({})
// Пример замыкания.
// `->` отделяет аргументы и возвращаемый тип
// `in` отделяет заголовок замыкания от тела замыкания
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
// Когда тип известен, как и выше, мы можем сделать так
numbers = numbers.map({ number in 3 * number })
// Или даже так
//numbers = numbers.map({ $0 * 3 })
print(numbers) // [3, 6, 18]
2015-01-25 11:56:52 +00:00
// Хвостовое замыкание
2016-10-08 20:29:13 +00:00
numbers = numbers.sorted { $0 > $1 }
2015-01-19 14:40:07 +00:00
print(numbers) // [18, 6, 3]
// Суперсокращение, поскольку оператор < выполняет логический вывод типов
2016-10-08 20:29:13 +00:00
numbers = numbers.sorted(by: < )
2015-01-19 14:40:07 +00:00
print(numbers) // [3, 6, 18]
//
// MARK: Структуры
//
// Структуры и классы имеют очень похожие характеристики
struct NamesTable {
2016-10-08 20:29:13 +00:00
let names: [String]
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
// Пользовательский индекс
subscript(index: Int) -> String {
return names[index]
}
}
// У структур автогенерируемый (неявно) инициализатор
2016-10-08 20:29:13 +00:00
let namesTable = NamesTable(names: ["Иван", "Яков"])
2015-01-19 14:40:07 +00:00
let name = namesTable[1]
2016-10-08 20:29:13 +00:00
print("Имя :\(name)") // Имя: Яков
//
// MARK: Обработка ошибок
//
// Протокол `Error` используется для перехвата выбрасываемых ошибок
enum MyError: Error {
case BadValue(msg: String)
case ReallyBadValue(msg: String)
}
// фунции помеченные словом `throws` должны вызываться с помощью `try`
func fakeFetch(value: Int) throws -> String {
guard 7 == value else {
throw MyError.ReallyBadValue(msg: "Действительно плохое значение")
}
return "тест"
}
func testTryStuff() {
// предполагается, что не будет выброшено никаких ошибок,
// в противном случае мы получим рантайм исключение
let _ = try! fakeFetch(value: 7)
// Если возникает ошибка, то выполнение продолжится. Н о если значение равно nil,
// то результат будет опционалом
let _ = try? fakeFetch(value: 7)
do {
// обычно try оператор, позволяющий обработать ошибку в `catch` блоке
try fakeFetch(value: 1)
} catch MyError.BadValue(let msg) {
print("Ошибка: \(msg)")
} catch {
// все остальное
}
}
testTryStuff()
2015-01-19 14:40:07 +00:00
//
// MARK: Классы
//
// Классы, структуры и их члены имеют трехуровневый контроль доступа
// Уровни: internal (по умолчанию), public, private
public class Shape {
public func getArea() -> Int {
2016-10-08 20:29:13 +00:00
return 0
2015-01-19 14:40:07 +00:00
}
}
// В с е методы и свойства класса являются открытыми (public).
// Если вам необходимо содержать только данные
// в структурированном объекте, вы должны использовать `struct`
internal class Rect: Shape {
var sideLength: Int = 1
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
// Пользовательский сеттер и геттер
private var perimeter: Int {
get {
return 4 * sideLength
}
set {
// `newValue` - неявная переменная, доступная в сеттере
sideLength = newValue / 4
}
}
2016-10-01 20:33:04 +00:00
2016-10-08 20:29:13 +00:00
// Вычисляемые свойства должны быть объявлены с помощью `var` , ведь они могут меняться
var smallestSideLength: Int {
return self.sideLength - 1
}
2015-01-19 14:40:07 +00:00
// Ленивая загрузка свойства
// свойство subShape остается равным nil (неинициализированным),
// пока не вызовется геттер
lazy var subShape = Rect(sideLength: 4)
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
// Если вам не нужны пользовательские геттеры и сеттеры,
// но все же хотите запустить код перед и после вызовов геттера или сеттера
// свойств, вы можете использовать `willSet` и `didSet`
var identifier: String = "defaultID" {
// аргумент у `willSet` будет именем переменной для нового значения
willSet(someIdentifier) {
print(someIdentifier)
}
}
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
init(sideLength: Int) {
self.sideLength = sideLength
2015-01-25 11:56:52 +00:00
// последним всегда вызывается super.init, когда init с параметрами
2015-01-19 14:40:07 +00:00
super.init()
}
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
func shrink() {
if sideLength > 0 {
2016-10-01 20:33:04 +00:00
sideLength -= 1
2015-01-19 14:40:07 +00:00
}
}
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
override func getArea() -> Int {
return sideLength * sideLength
}
}
// Простой класс `Square` наследует `Rect`
class Square: Rect {
convenience init() {
self.init(sideLength: 5)
}
}
var mySquare = Square()
print(mySquare.getArea()) // 25
mySquare.shrink()
print(mySquare.sideLength) // 4
// преобразование объектов
let aShape = mySquare as Shape
2015-01-25 11:56:52 +00:00
// сравнение экземпляров, в отличие от ==, которая проверяет эквивалентность
2015-01-19 14:40:07 +00:00
if mySquare === mySquare {
2016-10-08 20:29:13 +00:00
print("А г а , это mySquare")
2015-01-19 14:40:07 +00:00
}
2015-03-04 07:59:54 +00:00
// Опциональная инициализация (init)
class Circle: Shape {
var radius: Int
override func getArea() -> Int {
return 3 * radius * radius
}
2016-10-01 20:33:04 +00:00
2015-03-04 07:59:54 +00:00
// Поместите постфиксный знак вопроса после `init` - это и будет опциональная инициализация,
// которая может вернуть nil
init?(radius: Int) {
self.radius = radius
super.init()
2016-10-01 20:33:04 +00:00
2015-03-04 07:59:54 +00:00
if radius < = 0 {
return nil
}
}
}
var myCircle = Circle(radius: 1)
2016-10-08 20:29:13 +00:00
print(myCircle?.getArea()) // Optional(3)
print(myCircle!.getArea()) // 3
2015-03-04 07:59:54 +00:00
var myEmptyCircle = Circle(radius: -1)
2016-10-08 20:29:13 +00:00
print(myEmptyCircle?.getArea()) // "nil"
2015-03-04 07:59:54 +00:00
if let circle = myEmptyCircle {
2015-03-05 07:33:48 +00:00
// не будет выполняться, поскольку myEmptyCircle равен nil
2016-10-08 20:29:13 +00:00
print("circle не nil")
2015-03-04 07:59:54 +00:00
}
2015-01-19 14:40:07 +00:00
//
// MARK: Перечисления
//
// Перечисления могут быть определенного или своего типа.
// Они могут содержать методы подобно классам.
enum Suit {
case Spades, Hearts, Diamonds, Clubs
func getIcon() -> String {
switch self {
case .Spades: return "♤"
case .Hearts: return "♡"
case .Diamonds: return "♢"
case .Clubs: return "♧"
}
}
}
2015-01-25 11:56:52 +00:00
// Значения перечислений допускают сокращенный синтаксис, нет необходимости
2015-01-19 14:40:07 +00:00
// указывать тип перечисления, когда переменная объявляется явно
var suitValue: Suit = .Hearts
2016-10-08 20:29:13 +00:00
// Значения нецелочисленных перечислений должны быть указаны явно
// или могут выводится с помощью функции `rawValue` из имени
2015-01-19 14:40:07 +00:00
enum BookName: String {
2016-10-08 20:29:13 +00:00
case John
2015-01-25 11:56:52 +00:00
case Luke = "Лука"
2015-01-19 14:40:07 +00:00
}
2016-10-08 20:29:13 +00:00
print("Имя: \(BookName.John.rawValue)")
2015-01-19 14:40:07 +00:00
2015-03-04 07:59:54 +00:00
// Перечисление (enum) с о связанными значениями
enum Furniture {
// Связать с типом Int
case Desk(height: Int)
// Связать с типами String и Int
case Chair(String, Int)
2016-10-01 20:33:04 +00:00
2015-03-04 07:59:54 +00:00
func description() -> String {
switch self {
case .Desk(let height):
return "Письменный стол высотой \(height) см."
case .Chair(let brand, let height):
2015-03-05 07:33:48 +00:00
return "Стул марки \(brand) высотой \(height) см."
2015-03-04 07:59:54 +00:00
}
}
}
var desk: Furniture = .Desk(height: 80)
2016-10-08 20:29:13 +00:00
print(desk.description()) // "Письменный стол высотой 80 см."
2015-03-04 07:59:54 +00:00
var chair = Furniture.Chair("Foo", 40)
2016-10-08 20:29:13 +00:00
print(chair.description()) // "Стул марки Foo высотой 40 см."
2015-03-04 07:59:54 +00:00
2015-01-19 14:40:07 +00:00
//
// MARK: Протоколы
//
// `protocol` может потребовать, чтобы у соответствующих типов
// были определенные свойства экземпляра, методы экземпляра, тип методов,
// операторы и индексы.
protocol ShapeGenerator {
var enabled: Bool { get set }
func buildShape() -> Shape
}
// Протоколы, объявленные с @objc , допускают необязательные функции,
2016-10-08 20:29:13 +00:00
// которые позволяют вам проверять на соответствие. Для функций также необходимо указать @objc
2015-01-19 14:40:07 +00:00
@objc protocol TransformShape {
2016-10-08 20:29:13 +00:00
@objc optional func reshape()
@objc optional func canReshape() -> Bool
2015-01-19 14:40:07 +00:00
}
class MyShape: Rect {
var delegate: TransformShape?
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
func grow() {
sideLength += 2
2016-10-08 20:29:13 +00:00
2015-01-25 11:56:52 +00:00
// Размещайте знак вопроса перед опционным свойством, методом
// или индексом, чтобы не учитывать nil-значение и возвратить nil
// вместо выбрасывания ошибки выполнения (т.н. "опционная цепочка")
2016-10-08 20:29:13 +00:00
if let reshape = self.delegate?.canReshape?(), reshape {
2015-01-19 14:40:07 +00:00
// проверка делегата на выполнение метода
2016-10-08 20:29:13 +00:00
self.delegate?.reshape?()
2015-01-19 14:40:07 +00:00
}
}
}
//
// MARK: Прочее
//
// `extension` s: Добавляет расширенный функционал к существующему типу
2016-10-08 20:29:13 +00:00
// Класс Square теперь "соответствует" протоколу `CustomStringConvertible`
extension Square: CustomStringConvertible {
2015-01-19 14:40:07 +00:00
var description: String {
return "Площадь: \(self.getArea()) - ID: \(self.identifier)"
}
}
2016-10-08 20:29:13 +00:00
print("Объект Square: \(mySquare)")
2015-01-19 14:40:07 +00:00
// Вы также можете расширить встроенные типы
extension Int {
var customProperty: String {
return "Это \(self)"
}
2016-10-01 20:33:04 +00:00
2015-01-19 14:40:07 +00:00
func multiplyBy(num: Int) -> Int {
return num * self
}
}
2016-10-08 20:29:13 +00:00
print(7.customProperty) // "Это 7"
print(14.multiplyBy(num: 3)) // 42
2015-01-19 14:40:07 +00:00
// Обобщения: Подобно языкам Java и C#. Используйте ключевое слово `where` ,
// чтобы определить условия обобщений.
func findIndex< T: Equatable > (array: [T], valueToFind: T) -> Int? {
2016-10-08 20:29:13 +00:00
for (index, value) in array.enumerated() {
2015-01-19 14:40:07 +00:00
if value == valueToFind {
return index
}
}
return nil
}
2016-10-08 20:29:13 +00:00
let foundAtIndex = findIndex(array: [1, 2, 3, 4], valueToFind: 3)
print(foundAtIndex == 2) // вывод: true
2015-01-19 14:40:07 +00:00
// Операторы:
// Пользовательские операторы могут начинаться с символов:
// / = - + * % < > ! & | ^ . ~
// или
// Unicode- знаков математики, символов, стрелок, декорации и линий/кубов,
// нарисованных символов.
2016-10-08 20:29:13 +00:00
prefix operator !!!
2015-01-19 14:40:07 +00:00
// Префиксный оператор, который утраивает длину стороны, когда используется
2016-10-08 20:29:13 +00:00
prefix func !!! (shape: inout Square) -> Square {
2015-01-19 14:40:07 +00:00
shape.sideLength *= 3
return shape
}
// текущее значение
2016-10-08 20:29:13 +00:00
print(mySquare.sideLength) // 4
2015-01-19 14:40:07 +00:00
// Используя пользовательский оператор !!!, изменится длина стороны
// путем увеличения размера в 3 раза
!!!mySquare
2016-10-08 20:29:13 +00:00
print(mySquare.sideLength) // 12
// Операторы также могут быть обобщенными
infix operator < - >
func < - > < T: Equatable > (a: inout T, b: inout T) {
let c = a
a = b
b = c
}
var foo: Float = 10
var bar: Float = 20
foo < - > bar
print("foo это \(foo), bar это \(bar)") // "foo = 20.0, bar = 10.0"
2015-01-19 14:40:07 +00:00
```