1
0
mirror of https://github.com/adambard/learnxinyminutes-docs.git synced 2025-08-06 06:47:54 +02:00

[swift/ru] Updated code to Swift v.3, added some new sections from english version (#2429)

This commit is contained in:
Alexey Nazaroff
2016-10-08 23:29:13 +03:00
committed by ven
parent 0ec3d660e0
commit a18f6a596e

View File

@@ -4,9 +4,11 @@ contributors:
- ["Grant Timmerman", "http://github.com/grant"] - ["Grant Timmerman", "http://github.com/grant"]
- ["Christopher Bess", "http://github.com/cbess"] - ["Christopher Bess", "http://github.com/cbess"]
- ["Joey Huang", "http://github.com/kamidox"] - ["Joey Huang", "http://github.com/kamidox"]
- ["Alexey Nazaroff", "http://github.com/rogaven"]
filename: learnswift-ru.swift filename: learnswift-ru.swift
translators: translators:
- ["Dmitry Bessonov", "https://github.com/TheDmitry"] - ["Dmitry Bessonov", "https://github.com/TheDmitry"]
- ["Alexey Nazaroff", "https://github.com/rogaven"]
lang: ru-ru lang: ru-ru
--- ---
@@ -21,6 +23,8 @@ Swift - это язык программирования, созданный к
Смотрите еще [начальное руководство](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) Apple, которое содержит полное учебное пособие по Swift. Смотрите еще [начальное руководство](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) Apple, которое содержит полное учебное пособие по Swift.
```swift ```swift
// Версия Swift: 3.0
// импорт модуля // импорт модуля
import UIKit import UIKit
@@ -31,10 +35,14 @@ import UIKit
// Xcode поддерживает маркеры, чтобы давать примечания своему коду // Xcode поддерживает маркеры, чтобы давать примечания своему коду
// и вносить их в список обозревателя (Jump Bar) // и вносить их в список обозревателя (Jump Bar)
// MARK: Метка раздела // MARK: Метка раздела
// MARK: - Метка с разделителем
// TODO: Сделайте что-нибудь вскоре // TODO: Сделайте что-нибудь вскоре
// FIXME: Исправьте этот код // FIXME: Исправьте этот код
println("Привет, мир") // Начиная со второй версии Swift, println и print объединены в методе print.
// Перенос строки теперь добавляется в конец автоматически.
print("Привет, мир!") // println теперь просто print
print("Привет, мир!", terminator: "") // вывод текста без переноса строки
// переменные (var), значение которых можно изменить после инициализации // переменные (var), значение которых можно изменить после инициализации
// константы (let), значение которых нельзя изменить после инициализации // константы (let), значение которых нельзя изменить после инициализации
@@ -56,12 +64,12 @@ let piText = "Pi = \(π), Pi 2 = \(π * 2)" // Вставка переменны
// Сборка особых значений // Сборка особых значений
// используя ключ -D сборки конфигурации // используя ключ -D сборки конфигурации
#if false #if false
println("Не печатается") print("Не печатается")
let buildValue = 3 let buildValue = 3
#else #else
let buildValue = 7 let buildValue = 7
#endif #endif
println("Значение сборки: \(buildValue)") // Значение сборки: 7 print("Значение сборки: \(buildValue)") // Значение сборки: 7
/* /*
Опционалы - это особенность языка Swift, которая допускает вам сохранять Опционалы - это особенность языка Swift, которая допускает вам сохранять
@@ -79,31 +87,41 @@ var someOptionalString2: Optional<String> = "опционал"
if someOptionalString != nil { if someOptionalString != nil {
// я не nil // я не nil
if someOptionalString!.hasPrefix("opt") { if someOptionalString!.hasPrefix("opt") {
println("содержит префикс") print("содержит префикс")
} }
let empty = someOptionalString?.isEmpty let empty = someOptionalString?.isEmpty
} }
someOptionalString = nil someOptionalString = nil
/*
Использование ! для доступа к несуществующему опциональному значению генерирует
рантайм ошибку. Всегда проверяйте, что опционал содержит не пустое значение,
перед тем как раскрывать его через !.
*/
// неявная развертка опциональной переменной // неявная развертка опциональной переменной
var unwrappedString: String! = "Ожидаемое значение." var unwrappedString: String! = "Ожидаемое значение."
// как и выше, только ! - постфиксный оператор (с еще одним синтаксическим сахаром) // как и выше, только ! - постфиксный оператор (с еще одним синтаксическим сахаром)
var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Ожидаемое значение." var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Ожидаемое значение."
// If let конструкции -
// If let это специальная конструкция в Swift, которая позволяет проверить Optional
// справа от `=` непустой, и если это так - разворачивает его и присваивает левой части.
if let someOptionalStringConstant = someOptionalString { if let someOptionalStringConstant = someOptionalString {
// имеется некоторое значение, не nil // имеется некоторое (`Some`) значение, не `nil`
if !someOptionalStringConstant.hasPrefix("ok") { if !someOptionalStringConstant.hasPrefix("ok") {
// нет такого префикса // нет такого префикса
} }
} }
// Swift поддерживает сохранение значения любого типа // Swift поддерживает сохранение значения любого типа
// Для этих целей есть два ключевых слова `Any` и `AnyObject`
// AnyObject == id // AnyObject == id
// В отличие от `id` в Objective-C, AnyObject работает с любым значением (Class, // `Any` же, в отличие от `id` в Objective-C, `Any` работает с любым значением (Class, Int, struct и т.д.)
// Int, struct и т.д.) var anyVar: Any = 7
var anyObjectVar: AnyObject = 7 anyVar = "Изменять значение на строку не является хорошей практикой, но возможно."
anyObjectVar = "Изменять значение на строку не является хорошей практикой, но возможно." let anyObjectVar: AnyObject = Int(1) as NSNumber
/* /*
Комментируйте здесь Комментируйте здесь
@@ -129,6 +147,7 @@ shoppingList[1] = "бутылка воды"
let emptyArray = [String]() // let == неизменный let emptyArray = [String]() // let == неизменный
let emptyArray2 = Array<String>() // как и выше let emptyArray2 = Array<String>() // как и выше
var emptyMutableArray = [String]() // var == изменяемый var emptyMutableArray = [String]() // var == изменяемый
var explicitEmptyMutableStringArray: [String] = [] // так же как и выше
// Словарь // Словарь
@@ -140,31 +159,39 @@ occupations["Jayne"] = "Связи с общественностью"
let emptyDictionary = [String: Float]() // let == неизменный let emptyDictionary = [String: Float]() // let == неизменный
let emptyDictionary2 = Dictionary<String, Float>() // как и выше let emptyDictionary2 = Dictionary<String, Float>() // как и выше
var emptyMutableDictionary = [String: Float]() // var == изменяемый var emptyMutableDictionary = [String: Float]() // var == изменяемый
var explicitEmptyMutableDictionary: [String: Float] = [:] // то же
// //
// MARK: Поток управления // MARK: Поток управления
// //
// С помощью "," можно указать дополнительные условия для раскрытия
// опциональных значений.
let someNumber = Optional<Int>(7)
if let num = someNumber, num > 3 {
print("Больше 3х")
}
// цикл for для массива // цикл for для массива
let myArray = [1, 1, 2, 3, 5] let myArray = [1, 1, 2, 3, 5]
for value in myArray { for value in myArray {
if value == 1 { if value == 1 {
println("Один!") print("Один!")
} else { } else {
println("Не один!") print("Не один!")
} }
} }
// цикл for для словаря // цикл for для словаря
var dict = ["один": 1, "два": 2] var dict = ["один": 1, "два": 2]
for (key, value) in dict { for (key, value) in dict {
println("\(key): \(value)") print("\(key): \(value)")
} }
// цикл for для диапазона чисел // цикл for для диапазона чисел
for i in -1...shoppingList.count { for i in -1...shoppingList.count {
println(i) print(i)
} }
shoppingList[1...2] = ["бифштекс", "орехи пекан"] shoppingList[1...2] = ["бифштекс", "орехи пекан"]
// используйте ..< для исключения последнего числа // используйте ..< для исключения последнего числа
@@ -176,8 +203,8 @@ while i < 1000 {
} }
// цикл do-while // цикл do-while
do { repeat {
println("привет") print("привет")
} while 1 == 2 } while 1 == 2
// Переключатель // Переключатель
@@ -204,7 +231,7 @@ default: // обязательный (чтобы предусмотреть вс
// Функции являются типом первого класса, т.е. они могут быть вложены в функциях // Функции являются типом первого класса, т.е. они могут быть вложены в функциях
// и могут передаваться между собой // и могут передаваться между собой
// Функция с документированным заголовком Swift (формат reStructedText) // Функция с документированным заголовком Swift (формат Swift-модифицированный Markdown)
/** /**
Операция приветствия Операция приветствия
@@ -212,20 +239,20 @@ default: // обязательный (чтобы предусмотреть вс
- Маркер в документировании - Маркер в документировании
- Еще один маркер в документации - Еще один маркер в документации
:param: name - это имя - Parameter name : Это имя
:param: day - это день - Parameter day : Это день
:returns: Строка, содержащая значения name и day. - Returns : Строка, содержащая значения name и day.
*/ */
func greet(name: String, day: String) -> String { func greet(name: String, day: String) -> String {
return "Привет \(name), сегодня \(day)." return "Привет \(name), сегодня \(day)."
} }
greet("Боб", "вторник") greet(name: "Боб", day: "вторник")
// как и выше, кроме обращения параметров функции // как и выше, кроме обращения параметров функции
func greet2(#requiredName: String, externalParamName localParamName: String) -> String { func greet2(name: String, externalParamName localParamName: String) -> String {
return "Привет \(requiredName), сегодня \(localParamName)" return "Привет \(name), сегодня \(localParamName)"
} }
greet2(requiredName:"Иван", externalParamName: "воскресенье") greet2(name: "Иван", externalParamName: "Воскресенье")
// Функция, которая возвращает множество элементов в кортеже // Функция, которая возвращает множество элементов в кортеже
func getGasPrices() -> (Double, Double, Double) { func getGasPrices() -> (Double, Double, Double) {
@@ -235,8 +262,31 @@ let pricesTuple = getGasPrices()
let price = pricesTuple.2 // 3.79 let price = pricesTuple.2 // 3.79
// Пропускайте значения кортежей с помощью подчеркивания _ // Пропускайте значения кортежей с помощью подчеркивания _
let (_, price1, _) = pricesTuple // price1 == 3.69 let (_, price1, _) = pricesTuple // price1 == 3.69
println(price1 == pricesTuple.1) // вывод: true print(price1 == pricesTuple.1) // вывод: true
println("Цена газа: \(price)") 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()
// Переменное число аргументов // Переменное число аргументов
func setup(numbers: Int...) { func setup(numbers: Int...) {
@@ -246,7 +296,7 @@ func setup(numbers: Int...) {
} }
// Передача и возврат функций // Передача и возврат функций
func makeIncrementer() -> (Int -> Int) { func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int { func addOne(number: Int) -> Int {
return 1 + number return 1 + number
} }
@@ -256,15 +306,15 @@ var increment = makeIncrementer()
increment(7) increment(7)
// передача по ссылке // передача по ссылке
func swapTwoInts(inout a: Int, inout b: Int) { func swapTwoInts(a: inout Int, b: inout Int) {
let tempA = a let tempA = a
a = b a = b
b = tempA b = tempA
} }
var someIntA = 7 var someIntA = 7
var someIntB = 3 var someIntB = 3
swapTwoInts(&someIntA, &someIntB) swapTwoInts(a: &someIntA, b: &someIntB)
println(someIntB) // 7 print(someIntB) // 7
// //
@@ -291,13 +341,13 @@ numbers = numbers.map({ number in 3 * number })
print(numbers) // [3, 6, 18] print(numbers) // [3, 6, 18]
// Хвостовое замыкание // Хвостовое замыкание
numbers = sorted(numbers) { $0 > $1 } numbers = numbers.sorted { $0 > $1 }
print(numbers) // [18, 6, 3] print(numbers) // [18, 6, 3]
// Суперсокращение, поскольку оператор < выполняет логический вывод типов // Суперсокращение, поскольку оператор < выполняет логический вывод типов
numbers = sorted(numbers, < ) numbers = numbers.sorted(by: <)
print(numbers) // [3, 6, 18] print(numbers) // [3, 6, 18]
@@ -307,7 +357,7 @@ print(numbers) // [3, 6, 18]
// Структуры и классы имеют очень похожие характеристики // Структуры и классы имеют очень похожие характеристики
struct NamesTable { struct NamesTable {
let names = [String]() let names: [String]
// Пользовательский индекс // Пользовательский индекс
subscript(index: Int) -> String { subscript(index: Int) -> String {
@@ -316,9 +366,48 @@ struct NamesTable {
} }
// У структур автогенерируемый (неявно) инициализатор // У структур автогенерируемый (неявно) инициализатор
let namesTable = NamesTable(names: ["Me", "Them"]) let namesTable = NamesTable(names: ["Иван", "Яков"])
let name = namesTable[1] let name = namesTable[1]
println("Name is \(name)") // Name is Them 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()
// //
// MARK: Классы // MARK: Классы
@@ -329,7 +418,7 @@ println("Name is \(name)") // Name is Them
public class Shape { public class Shape {
public func getArea() -> Int { public func getArea() -> Int {
return 0; return 0
} }
} }
@@ -351,6 +440,11 @@ internal class Rect: Shape {
} }
} }
// Вычисляемые свойства должны быть объявлены с помощью `var`, ведь они могут меняться
var smallestSideLength: Int {
return self.sideLength - 1
}
// Ленивая загрузка свойства // Ленивая загрузка свойства
// свойство subShape остается равным nil (неинициализированным), // свойство subShape остается равным nil (неинициализированным),
// пока не вызовется геттер // пока не вызовется геттер
@@ -400,7 +494,7 @@ let aShape = mySquare as Shape
// сравнение экземпляров, в отличие от ==, которая проверяет эквивалентность // сравнение экземпляров, в отличие от ==, которая проверяет эквивалентность
if mySquare === mySquare { if mySquare === mySquare {
println("Ага, это mySquare") print("Ага, это mySquare")
} }
// Опциональная инициализация (init) // Опциональная инициализация (init)
@@ -423,13 +517,13 @@ class Circle: Shape {
} }
var myCircle = Circle(radius: 1) var myCircle = Circle(radius: 1)
println(myCircle?.getArea()) // Optional(3) print(myCircle?.getArea()) // Optional(3)
println(myCircle!.getArea()) // 3 print(myCircle!.getArea()) // 3
var myEmptyCircle = Circle(radius: -1) var myEmptyCircle = Circle(radius: -1)
println(myEmptyCircle?.getArea()) // "nil" print(myEmptyCircle?.getArea()) // "nil"
if let circle = myEmptyCircle { if let circle = myEmptyCircle {
// не будет выполняться, поскольку myEmptyCircle равен nil // не будет выполняться, поскольку myEmptyCircle равен nil
println("circle не nil") print("circle не nil")
} }
@@ -456,12 +550,13 @@ enum Suit {
// указывать тип перечисления, когда переменная объявляется явно // указывать тип перечисления, когда переменная объявляется явно
var suitValue: Suit = .Hearts var suitValue: Suit = .Hearts
// Нецелочисленные перечисления требуют прямого указания значений // Значения нецелочисленных перечислений должны быть указаны явно
// или могут выводится с помощью функции `rawValue` из имени
enum BookName: String { enum BookName: String {
case John = "Иоанн" case John
case Luke = "Лука" case Luke = "Лука"
} }
println("Имя: \(BookName.John.rawValue)") print("Имя: \(BookName.John.rawValue)")
// Перечисление (enum) со связанными значениями // Перечисление (enum) со связанными значениями
enum Furniture { enum Furniture {
@@ -481,9 +576,9 @@ enum Furniture {
} }
var desk: Furniture = .Desk(height: 80) var desk: Furniture = .Desk(height: 80)
println(desk.description()) // "Письменный стол высотой 80 см." print(desk.description()) // "Письменный стол высотой 80 см."
var chair = Furniture.Chair("Foo", 40) var chair = Furniture.Chair("Foo", 40)
println(chair.description()) // "Стул марки Foo высотой 40 см." print(chair.description()) // "Стул марки Foo высотой 40 см."
// //
@@ -500,10 +595,10 @@ protocol ShapeGenerator {
} }
// Протоколы, объявленные с @objc, допускают необязательные функции, // Протоколы, объявленные с @objc, допускают необязательные функции,
// которые позволяют вам проверять на соответствие // которые позволяют вам проверять на соответствие. Для функций также необходимо указать @objc
@objc protocol TransformShape { @objc protocol TransformShape {
optional func reshaped() @objc optional func reshape()
optional func canReshape() -> Bool @objc optional func canReshape() -> Bool
} }
class MyShape: Rect { class MyShape: Rect {
@@ -511,12 +606,13 @@ class MyShape: Rect {
func grow() { func grow() {
sideLength += 2 sideLength += 2
// Размещайте знак вопроса перед опционным свойством, методом // Размещайте знак вопроса перед опционным свойством, методом
// или индексом, чтобы не учитывать nil-значение и возвратить nil // или индексом, чтобы не учитывать nil-значение и возвратить nil
// вместо выбрасывания ошибки выполнения (т.н. "опционная цепочка") // вместо выбрасывания ошибки выполнения (т.н. "опционная цепочка")
if let allow = self.delegate?.canReshape?() { if let reshape = self.delegate?.canReshape?(), reshape {
// проверка делегата на выполнение метода // проверка делегата на выполнение метода
self.delegate?.reshaped?() self.delegate?.reshape?()
} }
} }
} }
@@ -528,14 +624,14 @@ class MyShape: Rect {
// `extension`s: Добавляет расширенный функционал к существующему типу // `extension`s: Добавляет расширенный функционал к существующему типу
// Класс Square теперь "соответствует" протоколу `Printable` // Класс Square теперь "соответствует" протоколу `CustomStringConvertible`
extension Square: Printable { extension Square: CustomStringConvertible {
var description: String { var description: String {
return "Площадь: \(self.getArea()) - ID: \(self.identifier)" return "Площадь: \(self.getArea()) - ID: \(self.identifier)"
} }
} }
println("Объект Square: \(mySquare)") print("Объект Square: \(mySquare)")
// Вы также можете расширить встроенные типы // Вы также можете расширить встроенные типы
extension Int { extension Int {
@@ -548,22 +644,22 @@ extension Int {
} }
} }
println(7.customProperty) // "Это 7" print(7.customProperty) // "Это 7"
println(14.multiplyBy(3)) // 42 print(14.multiplyBy(num: 3)) // 42
// Обобщения: Подобно языкам Java и C#. Используйте ключевое слово `where`, // Обобщения: Подобно языкам Java и C#. Используйте ключевое слово `where`,
// чтобы определить условия обобщений. // чтобы определить условия обобщений.
func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) { for (index, value) in array.enumerated() {
if value == valueToFind { if value == valueToFind {
return index return index
} }
} }
return nil return nil
} }
let foundAtIndex = findIndex([1, 2, 3, 4], 3) let foundAtIndex = findIndex(array: [1, 2, 3, 4], valueToFind: 3)
println(foundAtIndex == 2) // вывод: true print(foundAtIndex == 2) // вывод: true
// Операторы: // Операторы:
// Пользовательские операторы могут начинаться с символов: // Пользовательские операторы могут начинаться с символов:
@@ -571,19 +667,33 @@ println(foundAtIndex == 2) // вывод: true
// или // или
// Unicode- знаков математики, символов, стрелок, декорации и линий/кубов, // Unicode- знаков математики, символов, стрелок, декорации и линий/кубов,
// нарисованных символов. // нарисованных символов.
prefix operator !!! {} prefix operator !!!
// Префиксный оператор, который утраивает длину стороны, когда используется // Префиксный оператор, который утраивает длину стороны, когда используется
prefix func !!! (inout shape: Square) -> Square { prefix func !!! (shape: inout Square) -> Square {
shape.sideLength *= 3 shape.sideLength *= 3
return shape return shape
} }
// текущее значение // текущее значение
println(mySquare.sideLength) // 4 print(mySquare.sideLength) // 4
// Используя пользовательский оператор !!!, изменится длина стороны // Используя пользовательский оператор !!!, изменится длина стороны
// путем увеличения размера в 3 раза // путем увеличения размера в 3 раза
!!!mySquare !!!mySquare
println(mySquare.sideLength) // 12 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"
``` ```