diff options
| -rw-r--r-- | ru-ru/swift-ru.html.markdown | 535 | 
1 files changed, 535 insertions, 0 deletions
| diff --git a/ru-ru/swift-ru.html.markdown b/ru-ru/swift-ru.html.markdown new file mode 100644 index 00000000..6a90b474 --- /dev/null +++ b/ru-ru/swift-ru.html.markdown @@ -0,0 +1,535 @@ +--- +language: swift +contributors: +  - ["Grant Timmerman", "http://github.com/grant"] +  - ["Christopher Bess", "http://github.com/cbess"] +filename: learnswift-ru.swift +translators: +  - ["Dmitry Bessonov", "https://github.com/TheDmitry"] +lang: ru-ru +--- + +Swift - это язык программирования, созданный компанией Apple, для разработки +приложений iOS и OS X. Разработанный, чтобы сосуществовать с Objective-C и +быть более устойчивым к ошибочному коду, Swift был представлен в 2014 году на +конференции разработчиков Apple, WWDC. Приложения на Swift собираются +с помощью LLVM компилятора, включенного в Xcode 6+. + +Официальная книга по [языку программирования Swift](https://itunes.apple.com/us/book/swift-programming-language/id881256329) от Apple доступна в iBooks. + +Смотрите еще [начальное руководство](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/LandingPage/index.html) Apple, которое содержит полное учебное пособие по Swift. + +```swift +// импорт модуля +import UIKit + +// +// MARK: Основы +// + +// Xcode поддерживает заметные маркеры, чтобы давать примечания свою коду +// и вносить их в список обозревателя (Jump Bar) +// MARK: Метка раздела +// TODO: Сделайте что-нибудь вскоре +// FIXME: Исправьте этот код + +println("Привет, мир") + +// переменные (var), значение которых можно изменить после инициализации +// константы (let), значение которых нельзя изменить после инициализации + +var myVariable = 42 +let øπΩ = "значение" // именование переменной символами unicode +let π = 3.1415926 +let convenience = "Ключевое слово" // контекстное имя переменной +let weak = "Ключевое слово"; let override = "еще ключевое слово" // операторы +                                      // могут быть отделены точкой с запятой +let `class` = "Ключевое слово" // одинарные кавычки позволяют использовать +                               // ключевые слова в именовании переменных +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 +    println("Не печатается") +    let buildValue = 3 +#else +    let buildValue = 7 +#endif +println("Значение сборки: \(buildValue)") // Значение сборки: 7 + +/* +    Optional - это особенность языка Swift, которая допускает вам сохранять +    `некоторое` или `никакое` значения. + +    Язык Swift требует, чтобы каждое свойство имело значение, поэтому даже nil +    должен явно сохранен как Optional значение. + +    Optional<T> является перечислением. +*/ +var someOptionalString: String? = "optional" // Может быть nil +// как и выше, только ? это постфиксный оператор (синтаксический сахар) +var someOptionalString2: Optional<String> = "optional" + +if someOptionalString != nil { +    // я не nil +    if someOptionalString!.hasPrefix("opt") { +        println("содержит префикс") +    } +     +    let empty = someOptionalString?.isEmpty +} +someOptionalString = nil + +// неявная развертка переменной Optional +var unwrappedString: String! = "Ожидаемое значение." +// как и выше, только ! постфиксный оператор (с еще одним синтаксическим сахаром) +var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Ожидаемое значение." + +if let someOptionalStringConstant = someOptionalString { +    // имеется некоторое значение, не nil +    if !someOptionalStringConstant.hasPrefix("ok") { +        // нет такого префикса +    } +} + +// Swift поддерживает сохранение значение любого типа +// AnyObject == id +// В отличие от `id` в Objective-C, AnyObject работает с любым значением (Class, +// Int, struct и т.д.) +var anyObjectVar: AnyObject = 7 +anyObjectVar = "Изменять значение на строку не является хорошей практикой, но возможно." + +/* +    Комментируйте здесь +     +    /* +        Вложенные комментарии тоже поддерживаются +    */ +*/ + +// +// MARK: Коллекции +// + +/* +    Массив (Array) и словарь (Dictionary) являются структурами (struct). Так +    `let` и `var` также означают, что они изменяются (var) или не изменяются (let) +    при объявлении типов. +*/ + +// Массив +var shoppingList = ["сом", "вода", "лимоны"] +shoppingList[1] = "бутылка воды" +let emptyArray = [String]() // let == неизменный +let emptyArray2 = Array<String>() // как и выше +var emptyMutableArray = [String]() // var == изменяемый + + +// Словарь +var occupations = [ +    "Malcolm": "Капитан", +    "kaylee": "Техник" +] +occupations["Jayne"] = "Связи с общественностью" +let emptyDictionary = [String: Float]() // let == неизменный +let emptyDictionary2 = Dictionary<String, Float>() // как и выше +var emptyMutableDictionary = [String: Float]() // var == изменяемый + + +// +// MARK: Поток управления +// + +// цикл for для массива +let myArray = [1, 1, 2, 3, 5] +for value in myArray { +    if value == 1 { +        println("Один!") +    } else { +        println("Не один!") +    } +} + +// цикл for для словаря +var dict = ["один": 1, "два": 2] +for (key, value) in dict { +    println("\(key): \(value)") +} + +// цикл for для диапазона чисел +for i in -1...shoppingList.count { +    println(i) +} +shoppingList[1...2] = ["бифштекс", "орехи пекан"] +// используйте ..< для исключения последнего числа + +// цикл while +var i = 1 +while i < 1000 { +    i *= 2 +} + +// цикл do-while +do { +    println("привет") +} while 1 == 2 + +// Переключатель +// Очень мощный оператор, представляйте себе операторы `if` с синтаксическим +// сахаром +// Они поддерживают строки, объекты и примитивы (Int, Double, etc) +let vegetable = "красный перец" +switch vegetable { +case "сельдерей": +    let vegetableComment = "Добавьте немного изюма, имитируя муравьев на бревнышке." +case "огурец", "жеруха": +    let vegetableComment = "Было бы неплохо сделать бутерброд с чаем." +case let localScopeValue where localScopeValue.hasSuffix("перец"): +    let vegetableComment = "Это острый \(localScopeValue)?" +default: // обязательный (чтобы преодолеть все возможные вхождения) +    let vegetableComment = "Все вкусы хороши для супа." +} + + +// +// MARK: Функции +// + +// Функции являются типом первого класса, т.е. они могут быть вложены в функциях +// и могут передаваться между собой + +// Функция с документированным заголовком Swift (формат reStructedText) + +/** +    Операция приветствия + +    - Жирная метка в документировании +    - Еще одна жирная метка в документации + +    :param: name - это имя +    :param: day - это день +    :returns: Строка, содержащая значения name и day. +*/ +func greet(name: String, day: String) -> String { +    return "Привет \(name), сегодня \(day)." +} +greet("Боб", "вторник") + +// как и выше, кроме обращения параметров функции +func greet2(#requiredName: String, externalParamName localParamName: String) -> String { +    return "Привет \(requiredName), сегодня \(localParamName)" +} +greet2(requiredName:"Иван", externalParamName: "воскресенье") + +// Функция, которая возвращает множество элементов в кортеже +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 +println(price1 == pricesTuple.1) // вывод: true +println("Цена газа: \(price)") + +// Переменное число аргументов +func setup(numbers: Int...) { +    // это массив +    let number = numbers[0] +    let argCount = numbers.count +} + +// Передача и возврат функций +func makeIncrementer() -> (Int -> Int) { +    func addOne(number: Int) -> Int { +        return 1 + number +    } +    return addOne +} +var increment = makeIncrementer() +increment(7) + +// передача по ссылке +func swapTwoInts(inout a: Int, inout b: Int) { +    let tempA = a +    a = b +    b = tempA +} +var someIntA = 7 +var someIntB = 3 +swapTwoInts(&someIntA, &someIntB) +println(someIntB) // 7 + + +// +// 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] + +// Упрощение замыкания +numbers = sorted(numbers) { $0 > $1 } + +print(numbers) // [18, 6, 3] + +// Суперсокращение, поскольку оператор < выполняет логический вывод типов + +numbers = sorted(numbers, < ) + +print(numbers) // [3, 6, 18] + +// +// MARK: Структуры +// + +// Структуры и классы имеют очень похожие характеристики +struct NamesTable { +    let names = [String]() +     +    // Пользовательский индекс +    subscript(index: Int) -> String { +        return names[index] +    } +} + +// У структур автогенерируемый (неявно) инициализатор +let namesTable = NamesTable(names: ["Me", "Them"]) +let name = namesTable[1] +println("Name is \(name)") // Name is Them + +// +// MARK: Классы +// + +// Классы, структуры и их члены имеют трехуровневый контроль доступа +// Уровни: internal (по умолчанию), public, private + +public class Shape { +    public func getArea() -> Int { +        return 0; +    } +} + +// Все методы и свойства класса являются открытыми (public). +// Если вам необходимо содержать только данные +// в структурированном объекте, вы должны использовать `struct` + +internal class Rect: Shape { +    var sideLength: Int = 1 +     +    // Пользовательский сеттер и геттер +    private var perimeter: Int { +        get { +            return 4 * sideLength +        } +        set { +            // `newValue` - неявная переменная, доступная в сеттере +            sideLength = newValue / 4 +        } +    } +     +    // Ленивая загрузка свойства +    // свойство subShape остается равным nil (неинициализированным), +    // пока не вызовется геттер +    lazy var subShape = Rect(sideLength: 4) +     +    // Если вам не нужны пользовательские геттеры и сеттеры, +    // но все же хотите запустить код перед и после вызовов геттера или сеттера +    // свойств, вы можете использовать `willSet` и `didSet` +    var identifier: String = "defaultID" { +        // аргумент у `willSet` будет именем переменной для нового значения +        willSet(someIdentifier) { +            print(someIdentifier) +        } +    } +     +    init(sideLength: Int) { +        self.sideLength = sideLength +        // всегда вызывается super.init последним, когда init с параметрами +        super.init() +    } +     +    func shrink() { +        if sideLength > 0 { +            --sideLength +        } +    } +     +    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 + +// сравнение объектов, но не как операция ==, которая проверяет эквивалентность +if mySquare === mySquare { +    println("Ага, это mySquare") +} + + +// +// 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 "♧" +        } +    } +} + +// Значения перечислений допускают жесткий синтаксис, нет необходимости +// указывать тип перечисления, когда переменная объявляется явно +var suitValue: Suit = .Hearts + +// Нецелочисленные перечисления требуют прямого указания значений +enum BookName: String { +    case John = "John" +    case Luke = "Luke" +} +println("Имя: \(BookName.John.rawValue)") + + +// +// MARK: Протоколы +// + +// `protocol` может потребовать, чтобы у соответствующих типов +// были определенные свойства экземпляра, методы экземпляра, тип методов, +// операторы и индексы. + +protocol ShapeGenerator { +    var enabled: Bool { get set } +    func buildShape() -> Shape +} + +// Протоколы, объявленные с @objc, допускают необязательные функции, +// которые позволяют вам проверять на соответствие +@objc protocol TransformShape { +    optional func reshaped() +    optional func canReshape() -> Bool +} + +class MyShape: Rect { +    var delegate: TransformShape? +     +    func grow() { +        sideLength += 2 +         +        if let allow = self.delegate?.canReshape?() { +            // проверка делегата на выполнение метода +            self.delegate?.reshaped?() +        } +    } +} + + +// +// MARK: Прочее +// + +// `extension`s: Добавляет расширенный функционал к существующему типу + +// Класс Square теперь "соответствует" протоколу `Printable` +extension Square: Printable { +    var description: String { +        return "Площадь: \(self.getArea()) - ID: \(self.identifier)" +    } +} + +println("Объект Square: \(mySquare)") + +// Вы также можете расширить встроенные типы +extension Int { +    var customProperty: String { +        return "Это \(self)" +    } +     +    func multiplyBy(num: Int) -> Int { +        return num * self +    } +} + +println(7.customProperty) // "Это 7" +println(14.multiplyBy(3)) // 42 + +// Обобщения: Подобно языкам Java и C#. Используйте ключевое слово `where`, +// чтобы определить условия обобщений. + +func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { +    for (index, value) in enumerate(array) { +        if value == valueToFind { +            return index +        } +    } +    return nil +} +let foundAtIndex = findIndex([1, 2, 3, 4], 3) +println(foundAtIndex == 2) // вывод: true + +// Операторы: +// Пользовательские операторы могут начинаться с символов: +//      / = - + * % < > ! & | ^ . ~ +// или +// Unicode- знаков математики, символов, стрелок, декорации и линий/кубов, +// нарисованных символов. +prefix operator !!! {} + +// Префиксный оператор, который утраивает длину стороны, когда используется +prefix func !!! (inout shape: Square) -> Square { +    shape.sideLength *= 3 +    return shape +} + +// текущее значение +println(mySquare.sideLength) // 4 + +// Используя пользовательский оператор !!!, изменится длина стороны +// путем увеличения размера в 3 раза +!!!mySquare +println(mySquare.sideLength) // 12 +``` | 
