СПРАВОЧНИК ПО SWIFT

Часть 1: Тур по Swift

 

Ознакомительная текстовая информация для новичков.

 

СМОТРЕТЬ ВИДЕОУРОКИ

Вы здесь:

О языке Swift

Swift – это новый язык разработки iOS и OS X приложений, который включает в себя все лучшее из С и Objective C, при этом не ограничивая себя совместимостью с C.

Swift применяет безопасные практики программирования и добавляет современные функции, чтобы сделать разработку более простым, гибким и веселым занятием.

Написанный с чистого листа, Swift, опираясь на зрелый и любимый всеми фреймворк Cocoa (и CocoaTouch) – это возможность для разработчиков пересмотреть подход к разработке ПО.

Swift разрабатывался несколько лет. Компания Apple прокладывала фундамент для языка, работая над существующим компилятором, дебаггером и инфраструктурой фреймворков.

Apple упростили управление памятью, используя автоматический подсчет ссылок (ARC). Стэк фреймворков, построенный на мощном основании Foundation и Cocoa, модернизировался и стандартизировался.

Сам Objective-C эволюционировал, добавив поддержку блоков, литералы для коллекций, модули и другие функции, не нарушая существующего кода. Благодаря этой работе, Apple теперь имеет возможность представить новый язык для будущего разработки приложений.

Swift покажется знакомым для разработчиков Objective-C. Он перенимает читаемость именованных параметров из Objective-C и силу его динамической объектной модели. Он предоставляет простой доступ к существующим фреймворкам Cocoa и возможность смешивать код с Objective-C кодом.

Основываясь на этой общей площадке, Swift предоставляет многие новые возможности и унифицирует процедурные и объектно-ориентированные части языка.

Swift дружественен к новым программистам. Это первый язык для разработки систем индустриального качества, который так же выразителен и прост, как скриптовый язык. Он поддерживает “песочницу” – инновационную функцию, позволяющую разработчикам экспериментировать с кодом и сразу видеть результат, без сборки и запуска приложения.

Swift совмещает лучшие идеи из современных языков с мудростью инженерной культуры Apple. Компилятор оптимизирован для производительности и язык оптимизирован для разработки – без компромиссов с той или другой стороны. Он разработан для приложений от “Hello, world” до масштабов целой операционной системы. Все это делает Swift солидным вкладом для разработчиков и для самой Apple.

Swift – это фантастический способ разработки iOS и OS X приложений и продолжит развиваться с новыми функциями и возможностями.

Содержание

book

Инициализация пустой строки
Изменение строк
Строки это тип-значение
Работа с символами
Подсчет символов
Конкатенация строк и символов
Интерполяция строк
Сравнение строк
ПРОПИСНЫЕ и строчные буквы в строках
Юникод

Циклы for
for-in
For-условие-инкремент
Циклы while
While
Do-While
Условные выражения
If
Switch

null

Тур по Swift

Традиционно, рассказ о новом языке начинается с Hello, world!

В Swift это делается так:

print("Hello, world!")

Если вы писали код в C или Objective-C, этот синтаксис выглядит знакомым – в Swift, эта строка кода является завершенной программой. Не нужно импортировать библиотеку для работы с вводом/выводом или работой со строками. Код, написанный в глобальной области видимости (global scope), используется как входная точка для приложения, поэтому функция main() не нужна. Также не нужно ставить точки с запятой в конце каждого оператора.

В этом туре вы узнаете достаточно информации для того, чтобы начать писать код в Swift – мы решим ряд типичных задач. Не волнуйтесь, если что-то будет непонятно – все, о чем будет рассказано в этом туре, далее в книге будет объяснено еще более подробно.

Для лучшего результата, советуем открыть эту главу в песочнице (playground) XCode. Она позволит вам редактировать код и сразу видеть результат.

null

Простые значения

Используйте let для создания констант и var для объявления переменных. Значение константы не обязательно должно быть известно на момент компиляции, но оно должно присваиваться строго один раз. Это значит, что вы можете использовать константу для обозначения значения, определяемого единажды, но используемого во многих местах.

var myVariable =42
myVariable =50
let myConstant =42

Константа или переменная должна иметь тот е тип, что и значение, которое вы хотите присвоить ей, однако вам не обязательно всегда объявлять тип – компилятор сам может определить тип, если при создании константы или переменной вы указываете ее значение. В приведенном выше примере, компилятор определит, что myVariable – это целое число (integer), т.к. начальное значение – целое число.

Если начальное значение не предоставляет достаточной информации (или его нет), укажите тип вручную:

let implicitInteger =70
let implicitDouble =70.0
let explicitDouble:Double=70

Попробуйте сами создать константу типа Float со значением 4.

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

let label ="The width is"
let width =94
let widthLabel =label + String(width)

Попробуйте удалить конвертацию из String в последнией строке. Какую ошибку вы получите?

Есть еще более простой способ включить значения в строки:

let apples =3
let oranges =5
let appleSummary ="I have \(apples) apples."
let fruitSummary ="U have \(apples + oranges) pieces of fruit."

Попробуйте использовать \() для включения дробных чисел в строку и для вставки чьего-нибудь имени в приветствие.

Массивы и словари создаются с помощью [], как и доступ к их элементу (по ключу или по индексу):

var shoppingList =["catfish","water","tulips","blue paint"]
shoppingList[1]="bottle of water"
var occupations =["Malcolm":"Captain","Kaylee":"Mechanic"]
occupations["Jayne"]="Public relations"

Чтобы создать пустой массив или словарь, используйте синтаксис инициализации:

let emptyArray =String[]()
let emptyDictionary =Dictionary<String,Float>()

null

Контроль управления

if и switch используются для условий, for-in, for, while, do-while – для циклов. Скобки вокруг условий опциональны. Фигурные скобки вокруг тела – обязательны.

let individualScores =[75,43,103,87,12]
var teamScore =0
for score in individualScores {
    if score >50{
        teamScore +=3}
    else{
        teamScore +=1}
}
teamScore

В if выражение должно возвращать Boolean, поэтому код типа if score { … } – это ошибка, никакого неявного сравнения с нулем не будет.

Можно использовать if и let вместе для работы со значениями, которые могут отсутствовать – они представлены, как опциональные значения. Опциональное значение может содержать значение или nil для обозначения того, что значение отсутствует. Для создания “опционального значения” используется знак вопроса:

var optionalString:String?="Hello"
optionalString ==nil
var optionalName:String?="John Appleseed"
var greeting ="Hello!"
if let name = optionalName {
    greeting ="Hello, \(name)"}

Измените optionalName на nil. Какое приветствие вы получите? Добавьте else, отображающий другое приветствие для случаев, когда optionalName является nil.

Если опциональное значение равно nil, то условие вернет false и код будет пропущен. Иначе, опциональное значение будет присвоено константе и мы сможем использовать его внутри блока кода.

Switch поддерживает любой вид данных и широкое монжество операторов сравнения – он не ограничен одними лишь целыми числами и сравнениями на равенство:

let vegetable ="red pepper"
switch vegetable {
    case"celery":
        let vegetableComment ="Add some raisins and make ants on a log."
    case"cucumber","watercress":
        let vegetableComment ="That would make a good tea sandwich."
    case let x where x.hasSuffix("pepper"):
        let vegetableComment ="Is it a spicy \(x)?"
    default:
        let vegetableComment ="everything tastes good in soup"}

Попробуйте убрать default случай. Какую ошибку вы получите?

После выполнения кода внутри switch-кейса, который совпал по условию, программа выходит из switch (а не продолжает идти по остальным свитчам, поэтому нет необходимости использовать break).

Можно использовать for-in для итерации по элементам в словаре, указав пару имен для каждого ключа-значения:

let interestingNumbers =["Prime":[2,3,5,7,11,13],"Fibonacci":[1,1,2,3,5,8],"Square":[1,4,9,16,25],]
var largest =0
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
largest

Добавьте другую переменную для хранения информации о том, какого типа является самое большое число

While используется для повторения блока кода, пока не измениься условие. Можно перенести условие в конеч и использовать do-while:

var n =2
while n <100{
    n = n *2}
n

var m =2
do{
    m = m *2
}while m <100
m

Можно хранить индекс в цикле – или используя .. для создания диапазона индексов, или написав явную инициализацию, условие и инкремент.

Следующие два цикла делают одно и то же:

var firstForLoop =0
for i in 0..3{
    firstForLoop +=1}
firstForLoop
var secondForLoop =0;
for var i =0; i < 3; ++i {
    secondForLoop +=1}
secondForLoop

Используйте .. для создания диапазона, не включающего верхнее значение (т.е. цикл идет для i = 0, 1, 2) и … для диапазона, включающего оба значения (т.е. for i in 0…3 – это i = 0, 1, 2, 3).

null

Функции и замыкания (closures)

Используйте func для объявления функции. Функция вызывается по ее имени и списку параметров в скобках. Используйте -> для отделения имен параметров и типов от возвращаемого значения функции:

func greet(name:String, day:String)->String{
    return"Hello \(name), today is \(day)."
}
greet("Bob","Tuesday")

Удалите параметр day. Добавьте параметр для включения сегодняшнего особого блюда в приветствие.

Используйте кортеж (tuple) для возврата нескольких значений из функции:

func getGasPrices()->(Double,Double,Double){
    return(3.59,3.69,3.79)
}
getGasPrices()

Функции могут использовать разное число аргументов, собирая их в массив:

func sumOf(numbers:Int...)->Int{
    var sum =0 
    for number in numbers {
        sum += number
    }
    return sum
}

sumOf()
sumOf(42,597,12)

Напишите функцию, которая считает среднее значение для ее аргументов

Функции могут быть вложенными. Вложенные функции имеют доступ к переменным, объявленным во внешнем функции. Используйте вложенные функции для организации кода длинной и сложной функции.

func returnFifteen()->Int{
    var y =10
    func add(){
        y +=5
    }
    add()
    return y
}
returnFifteen()

Функции по своей сути являются типом – то есть вы можете возвращать функцию из функции:

func makeIncrementer()->(Int->Int){
    func addOne(number:Int)->Int{
        return 1 + number
    }
    return addOne
}

var increment = makeIncrementer()
increment(7)

Функция может принимать другую функцию, как ее аргумент:

func hasAnyMatches(list:Int[], condition:Int->Bool)->Bool{
    for item in list {
        if condition(item){
            return true
        }
    }
    return false
}

func lessThanTen(number:Int)->Bool{
    return number <10
} 

var numbers =[20,19,7,12]
hasAnyMatches(numbers, lessThanTen)

Функции – это на самом деле специальный случай замыканий. Вы можете написать замыкание без имени, окружив код фигурными скобками. Используйте in для разделения аргументов и типа возвращаемого значения от тела замыкания:

numbers.map({(number:Int)->Int in let result =3* number
    return result
})

Перепишите замыкание так, чтобы оно возвращало 0 для всех нечетных номеров

У вас есть несколько опций для написания замыканий более кратко. Когда тип замыкания уже известен, например обратный вызов делегата (callback), вы можете пропустить тип его параметров, тип возвращаемого значения или и то и другое. Однострочное замыкание в примере ниже возвращает значение своего единственного выражения:

numbers.map({ number in 3 * number })

Вы можете ссылаться на параметры по номеру, вместо его имени – этот подход особенно удобен в очень коротких замыканиях.

Замыкание, переданное как последний аргумент для функции, может появляться сразу после скобок:

sort([1,5,3,12,2]){ $0 > $1 }

null

Объекты и классы

Используйте слово class с именем класса для создания класса.

Объявление свойства класса делается так же, как объявление обычной переменной или константы – с тем лишь исключением, что оно теперь находится в контексте класса. Аналогично, методы и функции задаются внутри класса:

class Shape{
    var numberOfSides = 0
    func simpleDescription()->String{
        return "A shape with \(numberOfSides) sides."
    }
}

Добавьте константное свойство с помощью let; добавьте метод, который принимает аргумент.

Создается объект из класса, используя скобки после имени класса. Используйте синтаксис с точкой для доступа к свойствам и методам объекта:

var shape =Shape()
shape.numberOfSides =7
var shapeDescription = shape.simpleDescription()

Эта версия класса Shape не имеет одного важного свойства – инициализатора, который настроит объект при его создании.

Используем метод init для этого:

class NamedShape{
    var numberOfSides:Int=0 
    var name:String
    init(name:String){
        self.name = name
    }
    func simpleDescription()->String{
        return "A shape with \(numberOfSides) sides."
    }
}

Обратите внимание на то, что для доступа к своим свойствам класс использует self.

Аргументы инициализатору передаются так же, как при вызове функции:

var shape =NamedShape("My shape")

Каждое свойство должно иметь значение – заданное или при объявлении (как в случае numberOfSides), или в инициализаторе (как в случае name).

Используйте метод deinit для создания деинициализатора, если нужно перед уничтожением объекта выполнить какую-то очистку.

Классы могут наследоваться. Наследующие классы включают имя суперкласса (их родителя) после своего имени. При этом, классу не обязательно наследоваться от какого-то другого класса (в отличие от Objective-C, где нужно было наследоваться от NSObject – примечание переводчика), в этих случаях имя родителя можно пропустить.

Класс-наследник может определять методы своего родителя, используя слово override – в противном случае, компилятор сообщит об ошибке. Компилятор также определяет методы, которые помечены как override, но на самом деле ничего не переопределяют.

Проиллюстрируем все это с помощью кода:

class Square:NamedShape{
    var sideLength:Double
    init(sideLength:Double, name:String){
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides =4}
    func area()->Double{
        return sideLength * sideLength
    }
    override func simpleDescription()->String{
        return"A square with sides of length \(sidesLength)."
    }
}
let test =Square(sideLength:5.2, name:"my test square")
test.area()
test.simpleDescription()

Создайте другой подкласс NamedShape – например, Circle, который принимает в качестве параметров радиус и имя. Напишите метод area и describe для описания класса Circle

В дополнение к простым хранимым свойствам, свойства могут также иметь getter и setter методы, т.е. методы, используемые для получения и установки их значения.

Например:

class EquilateralTriangle:NamedShape{
    var sideLength:Double=0.0
    init(sideLength:Double, name:String){
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides =3
    } 
    var perimeter:Double{
        get{
            return 3.0 * sideLength
        }
        set{
            sideLength = newValue /3.0
        }
    }
    override func simpleDescription()->String{
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}

var triangle =EquilateralTriangle(sideLength:3.1, name:"a triangle")
triangle.perimeter
triangle.perimeter =9.9
triangle.sideLength

В сеттере для свойства perimeter, newValue – это псевдоним для нового значения, которое передается. Можно предоставить другой псевдоним, указав его в скобках после set.

Обратите внимание, что инициализатор для EqualiateralTriangle имеет три разных шага:

Устанавливает значение свойств, объявляемых подклассом
Вызывает инициализатор класса-предка
Изменяет значение свойств, объявленных предком.
Любые дополнитеьлные действия так же можно сделать на последнем шаге.

Если вам не нужно вычислять свойство, но по прежнему нужно предоставить код, который будет запущен до и после получения нового значения, используйте willSet и didSet. Например, класс ниже проверяет, что длина стороны треугольника всегда такая же, как длина стороны квадрата:

class TriangleAndSquare{
    var triangle:EquilateralTriangle{
        willSet {
            square.sideLength = newValue.sideLength
        }
    }
    var square:Square{
        willSet {
            triangle.sideLength = newValue.sideLength
        }
    }
    init(size:Double, name:String){
        square =Square(sideLength: size, name: name)
        triangle =EquilateralTriangle(sideLength: size, name: name)
    }
}

var triangleAndSquare =TriangleAndSquare(size:10, name:"another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square =Square(sideLength:50,
name:"larger square")
triangleAndSquare.triangle.sideLength

Методы в классах имеют одно важное отличие от функций. Имена параметров в функциях используются только внутри функции, но имена параметров в методах используются так же при вызове метода (кроме первого параметра). По умолчанию, метод имеет одно и то же имя параметра при вызове и внутри самого метода. Но можно указать второе имя, используемое в самом методе:

classCounter{
    var count :Int=0
    func incrementBy(amount:Int, numberOfTimes times:Int){
        count += amount * times
    }
} 
var counter =Counter()
counter.incrementBy(2, numberOfTimes:7)

Работая с опциональными значениями, вы можете написать ? перед операциями типа методов, свойств и обращений к элементам массива или словаря. Если значение перед ? – nil, то все после ? игнорируется и значение всего выражения – nil. Иначе, опциональное значение используется для вычисления выражения. В обоих случаях, значение всего выражение также является опциональным значением:

let optionalSquare:Square?=Square(sideLength:2.5, name:"optional square")
let sideLength = optionalSquare?.sideLength

null

Перечисления (enumerations) и структуры

enum используется для создания перечисления. Как классы и другие именованные типы, перечисления могут иметь ассоциированные с ними методы:

enum Rank:Int{
    case Ace = 1
    case Two,Three,Four,Five,Six,Seven,Eigth,Nine,Ten
    case Jack,Queen,King
    func simpleDescription()->String{
        switch self{
            case .Ace: return "ace"
            case .Jack: return"jack"
            case .Queen: return"queen"
            case .King: return"king"
            default: return String(self.toRaw())
        }
    }
}
let ace =Rank.Ace
let aceRawValue = ace.toRaw()

Напишите функцию, которая сравнивает два значения Rank, используя их “исходные” (toRaw()) значения

В примере выше, исходное значение перечисления имеет тип Int, поэтому мы указали только первое – Ace равное 1. Остальные были добавлены по очереди (2, 3, 4 и т.д.). Можно также использовать строки или дробные числа в качестве исходных значений перечисления.

Используйте toRaw и fromRaw для перехода от исходного значения к значению перечисления и обратно.

if let convertedRank =Rank.fromRaw(3){
    let threeDescription =convertedRank.simpleDescription()
}

Значения элементов перечисления – это настоящие значения, а не просто другой способ записи исходных значений. По сути, в случаях, где нет разумного исходного значения, его не обязательно подставлять:

enum Suit{
    case Spades,Hearts,Diamonds,Clubs
    func simpleDescription()->String{
        switch self{
            case .Spades: return "spades"
            case .Hearts: return "hears"
            case .Diamonds: return"diamonds"
            case .Clubs: return"clubs"
        }
    }
}
let hearts =Suit.Hearts
let heartsDescription = hearts.simpleDescription()

Добавьте метод color к Suit, который возвращает “black” для Spades и Clubs и “red” для hearts и diamonds

Обратите внимание на то, как мы используем Hearts в двух разных случаях: когда присваиваем значение константе hearts, мы используем полное имя Suit.Hearts, т.к. константа не имеет определенного типа. Внутри switch’a, мы используем .Hearts, т.к. находимся внутри self. Можно использовать эту сокращенную форму всегда, когда тип значения уже известен.

Используйте struct, чтобы создать структуру. Структуры поддерживают многое из поведения классов, включая методы и инициализаторы. Одно из самых важных отличий между структурами и классами заключается в том, что структуры всегда копируются, когда передаются внутри кода, а классы – всегда передаются по ссылке.

structCard{var rank:Rankvar suit:Suit
    func simpleDescription()->String{
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}
let threeOfSpades =Card(rank:.Three, suit:.Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

Добавьте к Card метод, который создает полную колоду карт, с одной картой для каждой комбинации номера и рубашки

Объект перечисления может иметь значения, ассоциирующиеся с объектом. Объекты одного и того же члена перечисления могут иметь разные значения, ассоциированные с ними. Вы предоставляете ассоциированные значения, когда создаете объект. Ассоциированные значения и исходные значения различны: исходное значение члена перечисления одинаковы для всех его объектов, вы задаете его при определении перечисления. Например, рассмотрим случай запроса времени заката и рассвета с сервера. Сервер отвечает или информацией, или ошибкой.

enumServerResponse{
    case Result(String,String)
    case Error(String)
}
let success =ServerResponse.Result("6:00 am","8:09 pm")
let failure =ServerResponse.Error("Out of cheese.")
switch success {
    case let.Result(sunrise, sunset): let serverResponse ="Sunrise is at \(sunrise) and sunset is at \(sunset)."
    case let.Error(error): let serverResponse ="Failure… \(error)"
}

Добавьте третий случай для ServerResponse к switch’у

Обратите внимание, как время заката и рассвета достаются из ServerResponse как пара значений, соответствующих случаям case.

null

Протоколы и расширения

Используйте слово protocol для объявления протокола.

protocol ExampleProtocol{var simpleDescription:String{get}
    mutating fund adjust()}

Классы, перечисления и структуры могут соответствовать протоколам:

class SimpleClass:ExampleProtocol{
    var simpleDescription:String="A very simple class." 
    var anotherProperty:Int=66923
    func adjust(){
        simpleDescription +=" Now 100% adjusted."
    }
}
var a =SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
structSimpleStructure:ExampleProtocol{
    var simpleDescription:String="A simple structure"
    mutating fund adjust(){
        simpleDescription +=" (adjusted)"
    }
} 
var b =SimpleStructure()
b.adjust()let bDescription = b.simpleDescription

Напишите перечисление, которое будет отвечать этому протоколу

Обратите внимание на ключевое слово mutating, которое обозначает метод, модифицирующий структуру. Объявление класса не требует добавления слова mutating, т.к. методы класса всегда могут модифицировать класс.

Используйте слово extension (расширение) для добавления функциональности существующему типу, например новых методов или вычисленных свойств. Вы можете использовать расширение для добавления совместимости с протоколом типу, который объявлен в другом месте, или даже типу, который вы импортировали из библиотеки или фреймворка:

xtension Int:ExampleProtocol{
    var simpleDescription:String{
        return "The number \(self)"
    }
    mutating func adjust(){
        self+=42
    }
}
simpleDescription

Напишите расширение для типа Double, которое добавляет свойство absoluteValue

Вы можете использовать имя протокола, как любой другой именованный тип – например, создать коллекцию объектов, которые имеют разные типы, но все соответствуют одному протоколу. Когда вы работаете со значениями, тип которых – протокол, методы вне объявления протокола недоступны.

let protocolValue:ExampleProtocol= a
protocolValue.simpleDescription
// protocolValue.anotherProperty 
// раскомментируйте и посмотрите на ошибку

Хотя переменная protocolValue будет иметь тип SimpleClass во время исполнения, компилятор работает с ней как с переменной типа ExampleProtocol – это значит, что вы не сможете случайно обратиться к методам или свойствам, которые класс реализует в дополнение к протоколу.

null

Общие функции и типы

Напишите имя внутри <>, чтобы создать общую функцию или тип:

func repeat<ItemType>(item :ItemType, times:Int)->ItemType[]{
    var result =ItemType[]()
    for i in 0..times {
        result += item
    }
    return result
}
repeat("knock",4)

Вы можете создать общие формы функций и методов, так же как и классов, перечислений и структур.

// Переопределяем опциональный тип из стандартной библиотеки Swift:
enumOptionalValue<T>{ caseNonecaseSome(T) }
var possibleInteger:OptionalValue<Int> =.None
possibleInteger =.Some(100)

Используйте where после имени типа, чтобы указать список требований – например, потребовать, чтобы тип реализовывал протокол, потребовать чтобы два типа были одинаковы или потребовать, чтобы класс имел определенный суперкласс:

func anyCommonElements <T, U where T:Sequence, U:Sequence,
    T.GeneratorType.Element:Equatable, T.GeneratorType.Element== U.GeneratorType.Element>(lhs: t, rhs: U)->Bool{
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem {return true}
        }
    }
    return false
}
anyCommonElements([1,2,3],[3])

Модифицируйте anyCommonElements, чтобы сделать функцию, возвращающую массив элементов, общих для обоих последовательностей

В простых случаях, where можно пропустить и просто написать имя класса или протокола после двоеточия. Т.е. написать – это то же самое, что и .

Создайте свое приложение для iOS с нуля
SWIFT С НУЛЯ

Этот видео курс, который предназначен для новичков без опыта кодирования, и разработчикам с некоторым опытом программирования iOS. Коллекция видео уроков пополняется каждую неделю.

 

ТВОЕ ПЕРВОЕ iOS ПРИЛОЖЕНИЕ

На видео курсах вы создадите свое собственное приложение готовое к размещению в AppStore.

Учитесь, делая
app-1-26

Xcode 10
Вы познакомитесь с основными инструментами разработки iOS, включая Xcode, Interface Builder и Playgrounds.

app-2-26

Swift
Узнаете, как разработать приложение для iOS в Swift и создадите свое приложение, готовое к загрузке в AppStore.

app-3-26

Sketch
Sketch самый популярный инструмент разработки для пользовательского интерфейса. Научитесь взаимодействовать с дизайнерами.

Хотите перейти на следующий уровень?
Наши курсы помогут вам в этом. Хотите создавать 2D и 3D игры? Или разрабатывать приложения для Apple Watch? Нет ничего проще!

«Разработка 2D игр»

Разработка 2D игр на Swift

Целью данного курса является получение практических знаний и навыков в написании игр. Вы создадите 4 игры для своего портфолио.

 

ПЕРЕЙТИ К КУРСУ

«Разработка 3D игр»

mobile-game

Создание 3D игр с помощью SceneKit на iOS, watchOS, tvOS и macOS! Посмотрев курс вы поймете, что это легко! Вы создадите 3 игры для своего портфолио.

 

ПЕРЕЙТИ К КУРСУ

«Apple Watch»

watch_course_swift1

Целью онлайн-курса, является научить вас правильно строить интерфейс программ, использовать шаблоны и другие полезные возможности.

 

ПЕРЕЙТИ К КУРСУ

«Бесплатные вебинары»

webinars_main

Вебинары проходят каждый месяц! Научись программировать на Swift от уровня новичка до профи разработчика! Не забудь зарегистрироваться!

 

ПЕРЕЙТИ К КУРСУ

Изучайте, экспериментируйте, развивайтесь
Учебная библиотека. Наша цель — научить программировать и создавать приложение для iOS. Здесь вы можете найти коллекцию статей, которые помогут вам в изучении программирования для iOS.