Category: iOS

15
Ноя
2021

После получения доступов открывается стандартный вид камера по вверх wkwebview swift

У меня есть сайт на js, который использует камеру для сканирования QR-кода. И веб-приложение на swift которое тянет мой сайт через wkwebview.
x-код http://joxi.ru/5md9aqpCadREo2
Проблема в том, что когда запрашиваю использование камеры из …

05
Ноя
2021

Как декодировать сжатую строку из PHP в Swift?

У меня есть текстовый файл сжатый с помощью функции zlib в php:
base64_encode(gzcompress(‘привет’)) // "eJy7sP9iw4UdFzZd2HqxCQA6EAjD"

Теперь мне нужно прочитать этот файл в iOS приложении.
Для этого я попытался использовать библ…

05
Ноя
2021

Как декодировать сжатую строку из PHP в Swift?

У меня есть текстовый файл сжатый с помощью функции zlib в php:
base64_encode(gzcompress(‘привет’)) // "eJy7sP9iw4UdFzZd2HqxCQA6EAjD"

Теперь мне нужно прочитать этот файл в iOS приложении.
Для этого я попытался использовать библ…

04
Ноя
2021

🍏 Самоучитель для начинающих: освойте основы Swift за 30 минут

Думаете, чтобы освоить Swift нужно много времени? И да, и нет. В изучении языков программирования важна практика, но что может сделать начинающий за 30 минут? Только познакомиться с базовым синтаксисом с помощью нашего самоучителя.

Создать Playground

Запустим Xcode и создадим Playground. Назовем его “BasicSwift”:

File → New → Playground…

⌥⇧⌘N

Swift Playground – это такой тип файлов, который представляет из себя игровую площадку для ваших экспериментов с кодом Swift. Результат исполнения каждой строчки кода вы можете наблюдать в боковой панели (Sidebar).

Переменные, константы, типы

Переменные обозначаются с помощью ключевого слова var

        var hello = "Hello Proglib"
    

Чтобы объявить константу используется ключевое слово let

        let brandName = "Proglib"
    
Swift – это статистический типизированный язык, а это значит, что мы должно явно задать тип каждой переменной во время компиляции.

Указывать тип переменной необязательно. Компилятор Swift автоматически его определит. Эта особенность называется интерференцией типов(type inference).

Swift предлагает следующие базовые типы: Int или UInt, Double, Float, String, Character, Bool, Tuples, Optional.

Множество типов фундаментально и чаще всего используется для объявления переменных. Забегая вперед скажу, что вы также можете создавать и свои собственные типы.

Мы не будет детально разбирать их все! Посвятим этой теме следующую 30-ти минутку.

Укажем тип нашей константы.

        let brandName: String = "Proglib"
    
Больше полезной информации вы можете найти на нашем телеграм-канале «Библиотека мобильного разработчика».

Интерполяция строк

Давайте теперь выведем имя бренда в консоль при помощи функции print().

        print(brandName)
    

Интерполяция – это способ объединить переменные и константы внутри строки.

Теперь присвоим переменной hello новое значение, и выведем в консоль.

        hello = "Hello \(brandName)"
print(hello)
    

Вот еще пример:

        let name = "Ivan" 
var age: UInt8 = 30
print("\(hello). My name is \(name). I am \(age)")

    

Базовые операторы

Здесь все интуитивно. Предлагаю вам поэкспериментировать с ними самостоятельно и посмотреть на результаты.

Арифметические операторы

+ сложение
вычитание
/ деление
% деление по модулю
        var a = 1, b = 2
var result = a + b
// etc

    

Операторы присвоения

= , +=, -=, /=, %=

        var h = 10
h += 1
h /= 2
h %= 2
// etc

    

Операторы сравнения

Операторы сравнения в качестве результата возвращают значения типа Bool

==, ≠, >, <, ≥, ≤

        let condition = 2 > 3
let condition2 = 1 != 0
let resultCondition = condition == condition2
// etc

    

Логические операторы

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

Рассмотрим на примере:

        // логическое И
print(true && true)      // true
print(true && false)     // false

// логическое ИЛИ
print(true || false)      // true

// логическое НЕ – инвертирует булево значение
print(!true)              // false

    

Это еще не все операторы, которые существуют в Swift. Остальные мы рассмотрим в контексте целей их предназначения.

Коллекции

Swift предлагает нам три основных типа коллекций: Array(Массивы), Dictionary(Словари) и Set(Множества). Сейчас мы рассмотрим первые два.

Array

Используйте квадратные скобки [], чтобы создавать массивы(Array) и словари(Dictionary).

Получить доступ к элементам массива можно написав индекс внутри скобок.

        let digits: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8 ,9]
 print(digits[3])

    

Попробуйте изменить значение в массиве digits. Что произойдет?

        digits[0] = 1
    
🪲
Cannot assign through subscript: ‘digits’ is a ‘let’ constant

Поскольку мы объявили массив как константу, то и все его значения становится не изменчивыми (immutable), как и его размер. А если мы объявим массив как переменную, то он будет изменчивым (mutable). Такое свойство называют изменчивостью коллекций (mutability of collection).

Это утверждение справедливо и для Словарей.

        // mutable
var numbers = [50, 10, 20, 34, 45]
print(numbers[0])
numbers[0] = numbers[0] + 1

    

Dictionary<Key, Value>

Создадим словарь sunSystemData, в который добавим данные о солнечной системе.

Пусть ключами (key) данного словаря будут номера объектов солнечной системы, а значениями (value) названия объектов. Поскольку звезда рождается первой, то будем считать, что ключ со значением 0 всегда указывает на звезду. Остальные объекты следуют в порядке по отношению к звезде.

        var sunSystemData = [ 0: "Sun", 1:"Mercury", 2:"Venus", 
	3:"Earth", 4:"Mars", 5:"Jupiter", 6:"Saturn", 7:"Uranus", 8:"Neptune"]

    

Мы не указали типы для словаря явно. Вы можете проверить как их определил Swift, используя функцию стандартной библиотеки Swift (Swift Standard Library) type(of: T).

        type(of: sunSystemData) // Dictionary<Int, String>

    

Обратиться к элементу словаря можно, написав ключ внутри скобок. Результат будет содержать значение опционального типа (Optional), а если по заданному ключу (в скобках) нет соответствующего элемента, то получим nil.

nil в Swift означает отсутствие значения.

Получим нашу родную планету и выведем ее в консоль.

        var homePlanet = sunSystemData[3]
print("My home is \(homePlanet)")

    

Когда мы попытались вывести переменную в консоль, то получили предупреждение!

🪲
String interpolation produces a debug description for an optional value; did you mean to make this explicit?

Давайте посмотрим какой именно тип приняла переменная.

        type(of: homePlanet) // Optional<String>

    

Чтобы избавиться от предупреждения в интерполяции строки, нам необходимо указать что именно мы выводим. Сделать это можно при помощи оператора as. В этом случаи мы увидим напечатанный nil , когда значение отсутствует. Попробуйте обратиться к элементу с ключом 0.

        print("My home is \(sunSystem[0] as String?)") // My home is nil
print("My home is \(homePlanet as String?)") // My home is Earth
    

Другим решением может быть присвоение переменной значения по умолчанию.

Сделать это мы можем при помощи оператора объединения по nil??

        var homePlanet = sunSystem[3] ?? "Unknown planet"
print("My home is \(homePlanet)") // My home is Earth

    

Пока опустим темы об опциональных типах и приведении типов(type casting).

В следующих статьях я расскажу о них подробней.

Продолжим!

Кстати, если вы считаете, что Плутон это планета, то можете добавить её самостоятельно!

        sunSystem[9] = "Pluto"

    

Чем отличаются массивы от словарей?

  • Массивы хранят множество значений определенного типа в упорядоченном списке. Любое значение может присутствовать несколько раз в списке.
  • Словари хранят множество значение определенного типа, где каждое значение связано с уникальным ключом, который идентифицирует это значение внутри словаря. Элементы в словаре не имеют определенного порядка, как в массивах.

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

Например:

        var HierarchyOfNumbers: [Character:String] = [
	"N":"Natural Numbers"
	"Z":"Integers"
	"Q":"Rational Numbers"
	"R":"Real Numbers"
	"C":"Complex Numbers"
]

    

Управление потоком

Часто необходимо выполнять различный код базирующийся на определенных условий (conditions).

  • Если вам необходимо написать различную логику, которая зависит от определенных условий, тогда используйте условные инструкцииif, switch. Инструкцияifхорошо подходит для простых сравнений, и нескольких вариантов исходов.
  • Инструкция switch подходит для более сложных условий. Лучше использовать ее, когда вам необходимо выбрать из множества вариантов альтернатив, основываясь на каком-либо значении, т.е. выполнить код соответствующий определенному шаблону.
  • Когда вам необходимо многократно повторить какие либо инструкции, используйте циклы: for-in,while.

If…else

Инструкция if бывает трех форм.

Традиционное ее представление выглядит так:

        var condition = true
if condition {
	// 
} else {
	//
}

    

В зависимости от условия, мы попадаем в определенные блоки кода. Когда условие истинно(true), выполняется блок следующий за if, а когда ложно(false), выполняется блок следующий за else.

Например, вы решили, что Плутон планета? Сейчас узнаем!

        var isPluto = sunSystemData[9] != nil

if isPluto {
	print("Pluto is planet")
} else {
	print("Pluto is not planet")
}

    

if…

Мы можем опустить блок else, когда нам необходимо выполнить только одно условие.

Рассмотрим такой случай. У нас есть данные, и мы не хотим перезаписать значение. Тогда необходимо проверить наличие данных, и только после добавить значение.

        var key = 0, value = "Sun"
var isExists = sunSystemData[key] != nil // false
if !isExists { // true
	sunSystemData[key] =  value
}

    

if…else if…else

Также мы можем добавить условия следующее за else.

        var value = 0
if value > 0 {
	print("\(value)")
} else if value == 0  {
	print(value)
} else {
	print(value)
}

    

Вы можете комбинировать if else.

Например:

        var a = 0, b = 3, c = 1
if a > b {
	print(a - b)
} else if b > a { 
	print(b - a)
} else if c < a {
	print(a - c)
} else {
	 print(a + b + c)
}

    

switch

В самой простой форме switch выглядит так:

        var value = "R2-D2"
switch value {
	case "R2-D2": print("Take him!")
	case "C-3PO": print("Take him!")
	default: 
		print("These aren't the droids you're looking for.")
}

    

Ключевое слово case определяет возможный случай (шаблон), с которым сравнивается значение value. Затем исполняется соответствующий блок кода на основе первого успешно совпавшего шаблона. В случаи если совпадений не найдено, исполняется блок default , который всегда следует после остальных случаев. Условие default гарантирует что наша конструкция полная и законченная.

Поменяйте значение value, и посмотрите, какой блок кода исполнился.

for-in

Цикл for-in упрощает перебор по последовательностям, т.к. массивы, словари, строки.

Синтаксис for-in выглядит так:

        for value in sequence{
  // 
}

    

Цикл for-in исполняет инструкции определенное количества раз, пока мы не достигнем конца последовательности.

valueэлемент последовательности на каждой итерации(iteration, повторении).

Рассмотрим пример перебора значений массива и словаря.

        for digit in digits  {
	print(digit)
}
for (key, value) in sunSystemData {
	print("Key:\(key) Value:\(value)")
}

    

while

while имеет две формы.

Первая из них начинается с вычисления условия. Такой цикл можно рассматривать как повторяющаяся инструкция if.

        var condition = true;
while (condition) {
	// тело цикла
}

    

Например, мы хотим пройти 10 000 шагов.

        var stepGoal = 10_000
var mySteps = 0
while mySteps < 10_000 {
	mySteps += 1
}

    

Цикл будет работать пока условие mySteps < 10_000 принимает булево значение true.

Внутри тела цикла мы увеличиваем переменную mySteps на один шаг.

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

Расчет факториала числа.

        var counter = 5                
var factorial = 1 // начальное значение             

while counter > 0 {            
    factorial *= counter       
    counter -= 1               
}

print(factorial)  

    

Здесь я вам предлагаю разобраться самостоятельно 😉

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

В остальном repeat-while ведет себя идентично while.

        var condition = true
repeat {
	// тело цикла 
} while (condition)

    

Также цикл while используется, когда нам заранее неизвестно число итераций последовательности. В отличии от цикла for-in.

Функции

В Swift есть два типа функций:

Пользовательские(User-defined Function) и функции стандартной библиотеки (Standard Library Functions).

Функции помогают организовывать код, разбив его на более мелкие части, что делает код более легким для понимания и переиспользования. Мы уже использовали функции стандартной библиотеки, такие как print() и type(). Рассмотрим, как создаются пользовательские функции.

Функция – блок кода, который выполняет конкретную задачу.

Каждая функция имеет уникальное имя, которое является ее идентификатором.

        func functionName(parameters) -> returnType {
  // тело функии 
}

    

Объявить функцию можно при помощи ключевого слова func.

За ним следует имя функцииfunctionName.

В скобках указываются параметры(parameters) функции.

Параметр – это значение определенного типа, принимаемое функцией.

returnType – указывает, какого типа значение возвращает функция

Чтобы исполнить функцию, ее необходимо вызвать (как мы уже делали это с print()).

        // вызов функции
functionName()

    

Функции без параметров

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

        func greetings() {
	 print("Hello Proglib!")
}
greetings()

print("Done!")

    

Мы объявили функцию с именем greetings() , которая просто печатает "Hello Proglib!" в консоли. Она не имеет параметров и возвращаемого значения. При вызове функции управление программой переходит к определению функции. Затем исполняется код, который содержится внутри тела функции:

        print("Hello Proglib!")
    

Как только функция завершится, управление потоком переходит к следующей инструкции после вызова функции.

        print("Done!")
    

Функции с параметрами

Функции, в которым мы передаем аргументы, называются функциями с параметрами. Если мы хотим, чтобы функция возвращала значение, нужно использовать оператор return.

Например, разница между двумя значениями:

        func difference(a: Int, b: Int) -> Int {
	return a - b 
}
var result = difference(a: 3, b: 2)
print(result)

    

Мы объявили функцию с именем difference, которая принимает два параметра типа Int и возвращает значение типа → Int. При вызове функции, мы передаем параметры в круглых скобках (a: 3, b: 2).

Каждый параметр функции состоит из метки аргумента и имени параметра. Имена параметров используются при реализации функции.

        func difference(of a: Int, less b: Int) -> Int {
  return a - b
}

    

Метка аргумента используется при вызове функции.

        difference(of: 1, less: 2)
    

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

Если вам не нужна метка для аргумента, то напишите _ вместо конкретного названия метки для аргумента.

        func difference(_ x: Int, _ y: Int) -> Int {
  return x - y
}

difference(3, 4)

    

Мы можем опустить оператор return , когда тело функции является одним выражением.

        func difference(a: Int, b: Int) -> Int {
	a - b 
}

    

Заключение

Мы познакомились с фундаментальным синтаксисом языка программирования Swift. Рассмотрели основные операторы, научились объявлять переменные и объединять код в функции. В следующие полчаса разберем каждую тему более глубоко. На сегодня все! Playground доступен на Github.

04
Ноя
2021

🍏 Самоучитель для начинающих: освойте основы Swift за 30 минут

Думаете, чтобы освоить Swift нужно много времени? И да, и нет. В изучении языков программирования важна практика, но что может сделать начинающий за 30 минут? Только познакомиться с базовым синтаксисом с помощью нашего самоучителя.

Создать Playground

Запустим Xcode и создадим Playground. Назовем его “BasicSwift”:

File → New → Playground…

⌥⇧⌘N

Swift Playground – это такой тип файлов, который представляет из себя игровую площадку для ваших экспериментов с кодом Swift. Результат исполнения каждой строчки кода вы можете наблюдать в боковой панели (Sidebar).

Переменные, константы, типы

Переменные обозначаются с помощью ключевого слова var

        var hello = "Hello Proglib"
    

Чтобы объявить константу используется ключевое слово let

        let brandName = "Proglib"
    
Swift – это статистический типизированный язык, а это значит, что мы должно явно задать тип каждой переменной во время компиляции.

Указывать тип переменной необязательно. Компилятор Swift автоматически его определит. Эта особенность называется интерференцией типов(type inference).

Swift предлагает следующие базовые типы: Int или UInt, Double, Float, String, Character, Bool, Tuples, Optional.

Множество типов фундаментально и чаще всего используется для объявления переменных. Забегая вперед скажу, что вы также можете создавать и свои собственные типы.

Мы не будет детально разбирать их все! Посвятим этой теме следующую 30-ти минутку.

Укажем тип нашей константы.

        let brandName: String = "Proglib"
    
Больше полезной информации вы можете найти на нашем телеграм-канале «Библиотека мобильного разработчика».

Интерполяция строк

Давайте теперь выведем имя бренда в консоль при помощи функции print().

        print(brandName)
    

Интерполяция – это способ объединить переменные и константы внутри строки.

Теперь присвоим переменной hello новое значение, и выведем в консоль.

        hello = "Hello \(brandName)"
print(hello)
    

Вот еще пример:

        let name = "Ivan" 
var age: UInt8 = 30
print("\(hello). My name is \(name). I am \(age)")

    

Базовые операторы

Здесь все интуитивно. Предлагаю вам поэкспериментировать с ними самостоятельно и посмотреть на результаты.

Арифметические операторы

+ сложение
вычитание
/ деление
% деление по модулю
        var a = 1, b = 2
var result = a + b
// etc

    

Операторы присвоения

= , +=, -=, /=, %=

        var h = 10
h += 1
h /= 2
h %= 2
// etc

    

Операторы сравнения

Операторы сравнения в качестве результата возвращают значения типа Bool

==, ≠, >, <, ≥, ≤

        let condition = 2 > 3
let condition2 = 1 != 0
let resultCondition = condition == condition2
// etc

    

Логические операторы

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

Рассмотрим на примере:

        // логическое И
print(true && true)      // true
print(true && false)     // false

// логическое ИЛИ
print(true || false)      // true

// логическое НЕ – инвертирует булево значение
print(!true)              // false

    

Это еще не все операторы, которые существуют в Swift. Остальные мы рассмотрим в контексте целей их предназначения.

Коллекции

Swift предлагает нам три основных типа коллекций: Array(Массивы), Dictionary(Словари) и Set(Множества). Сейчас мы рассмотрим первые два.

Array

Используйте квадратные скобки [], чтобы создавать массивы(Array) и словари(Dictionary).

Получить доступ к элементам массива можно написав индекс внутри скобок.

        let digits: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8 ,9]
 print(digits[3])

    

Попробуйте изменить значение в массиве digits. Что произойдет?

        digits[0] = 1
    
🪲
Cannot assign through subscript: ‘digits’ is a ‘let’ constant

Поскольку мы объявили массив как константу, то и все его значения становится не изменчивыми (immutable), как и его размер. А если мы объявим массив как переменную, то он будет изменчивым (mutable). Такое свойство называют изменчивостью коллекций (mutability of collection).

Это утверждение справедливо и для Словарей.

        // mutable
var numbers = [50, 10, 20, 34, 45]
print(numbers[0])
numbers[0] = numbers[0] + 1

    

Dictionary<Key, Value>

Создадим словарь sunSystemData, в который добавим данные о солнечной системе.

Пусть ключами (key) данного словаря будут номера объектов солнечной системы, а значениями (value) названия объектов. Поскольку звезда рождается первой, то будем считать, что ключ со значением 0 всегда указывает на звезду. Остальные объекты следуют в порядке по отношению к звезде.

        var sunSystemData = [ 0: "Sun", 1:"Mercury", 2:"Venus", 
	3:"Earth", 4:"Mars", 5:"Jupiter", 6:"Saturn", 7:"Uranus", 8:"Neptune"]

    

Мы не указали типы для словаря явно. Вы можете проверить как их определил Swift, используя функцию стандартной библиотеки Swift (Swift Standard Library) type(of: T).

        type(of: sunSystemData) // Dictionary<Int, String>

    

Обратиться к элементу словаря можно, написав ключ внутри скобок. Результат будет содержать значение опционального типа (Optional), а если по заданному ключу (в скобках) нет соответствующего элемента, то получим nil.

nil в Swift означает отсутствие значения.

Получим нашу родную планету и выведем ее в консоль.

        var homePlanet = sunSystemData[3]
print("My home is \(homePlanet)")

    

Когда мы попытались вывести переменную в консоль, то получили предупреждение!

🪲
String interpolation produces a debug description for an optional value; did you mean to make this explicit?

Давайте посмотрим какой именно тип приняла переменная.

        type(of: homePlanet) // Optional<String>

    

Чтобы избавиться от предупреждения в интерполяции строки, нам необходимо указать что именно мы выводим. Сделать это можно при помощи оператора as. В этом случаи мы увидим напечатанный nil , когда значение отсутствует. Попробуйте обратиться к элементу с ключом 0.

        print("My home is \(sunSystem[0] as String?)") // My home is nil
print("My home is \(homePlanet as String?)") // My home is Earth
    

Другим решением может быть присвоение переменной значения по умолчанию.

Сделать это мы можем при помощи оператора объединения по nil??

        var homePlanet = sunSystem[3] ?? "Unknown planet"
print("My home is \(homePlanet)") // My home is Earth

    

Пока опустим темы об опциональных типах и приведении типов(type casting).

В следующих статьях я расскажу о них подробней.

Продолжим!

Кстати, если вы считаете, что Плутон это планета, то можете добавить её самостоятельно!

        sunSystem[9] = "Pluto"

    

Чем отличаются массивы от словарей?

  • Массивы хранят множество значений определенного типа в упорядоченном списке. Любое значение может присутствовать несколько раз в списке.
  • Словари хранят множество значение определенного типа, где каждое значение связано с уникальным ключом, который идентифицирует это значение внутри словаря. Элементы в словаре не имеют определенного порядка, как в массивах.

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

Например:

        var HierarchyOfNumbers: [Character:String] = [
	"N":"Natural Numbers"
	"Z":"Integers"
	"Q":"Rational Numbers"
	"R":"Real Numbers"
	"C":"Complex Numbers"
]

    

Управление потоком

Часто необходимо выполнять различный код базирующийся на определенных условий (conditions).

  • Если вам необходимо написать различную логику, которая зависит от определенных условий, тогда используйте условные инструкцииif, switch. Инструкцияifхорошо подходит для простых сравнений, и нескольких вариантов исходов.
  • Инструкция switch подходит для более сложных условий. Лучше использовать ее, когда вам необходимо выбрать из множества вариантов альтернатив, основываясь на каком-либо значении, т.е. выполнить код соответствующий определенному шаблону.
  • Когда вам необходимо многократно повторить какие либо инструкции, используйте циклы: for-in,while.

If…else

Инструкция if бывает трех форм.

Традиционное ее представление выглядит так:

        var condition = true
if condition {
	// 
} else {
	//
}

    

В зависимости от условия, мы попадаем в определенные блоки кода. Когда условие истинно(true), выполняется блок следующий за if, а когда ложно(false), выполняется блок следующий за else.

Например, вы решили, что Плутон планета? Сейчас узнаем!

        var isPluto = sunSystemData[9] != nil

if isPluto {
	print("Pluto is planet")
} else {
	print("Pluto is not planet")
}

    

if…

Мы можем опустить блок else, когда нам необходимо выполнить только одно условие.

Рассмотрим такой случай. У нас есть данные, и мы не хотим перезаписать значение. Тогда необходимо проверить наличие данных, и только после добавить значение.

        var key = 0, value = "Sun"
var isExists = sunSystemData[key] != nil // false
if !isExists { // true
	sunSystemData[key] =  value
}

    

if…else if…else

Также мы можем добавить условия следующее за else.

        var value = 0
if value > 0 {
	print("\(value)")
} else if value == 0  {
	print(value)
} else {
	print(value)
}

    

Вы можете комбинировать if else.

Например:

        var a = 0, b = 3, c = 1
if a > b {
	print(a - b)
} else if b > a { 
	print(b - a)
} else if c < a {
	print(a - c)
} else {
	 print(a + b + c)
}

    

switch

В самой простой форме switch выглядит так:

        var value = "R2-D2"
switch value {
	case "R2-D2": print("Take him!")
	case "C-3PO": print("Take him!")
	default: 
		print("These aren't the droids you're looking for.")
}

    

Ключевое слово case определяет возможный случай (шаблон), с которым сравнивается значение value. Затем исполняется соответствующий блок кода на основе первого успешно совпавшего шаблона. В случаи если совпадений не найдено, исполняется блок default , который всегда следует после остальных случаев. Условие default гарантирует что наша конструкция полная и законченная.

Поменяйте значение value, и посмотрите, какой блок кода исполнился.

for-in

Цикл for-in упрощает перебор по последовательностям, т.к. массивы, словари, строки.

Синтаксис for-in выглядит так:

        for value in sequence{
  // 
}

    

Цикл for-in исполняет инструкции определенное количества раз, пока мы не достигнем конца последовательности.

valueэлемент последовательности на каждой итерации(iteration, повторении).

Рассмотрим пример перебора значений массива и словаря.

        for digit in digits  {
	print(digit)
}
for (key, value) in sunSystemData {
	print("Key:\(key) Value:\(value)")
}

    

while

while имеет две формы.

Первая из них начинается с вычисления условия. Такой цикл можно рассматривать как повторяющаяся инструкция if.

        var condition = true;
while (condition) {
	// тело цикла
}

    

Например, мы хотим пройти 10 000 шагов.

        var stepGoal = 10_000
var mySteps = 0
while mySteps < 10_000 {
	mySteps += 1
}

    

Цикл будет работать пока условие mySteps < 10_000 принимает булево значение true.

Внутри тела цикла мы увеличиваем переменную mySteps на один шаг.

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

Расчет факториала числа.

        var counter = 5                
var factorial = 1 // начальное значение             

while counter > 0 {            
    factorial *= counter       
    counter -= 1               
}

print(factorial)  

    

Здесь я вам предлагаю разобраться самостоятельно 😉

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

В остальном repeat-while ведет себя идентично while.

        var condition = true
repeat {
	// тело цикла 
} while (condition)

    

Также цикл while используется, когда нам заранее неизвестно число итераций последовательности. В отличии от цикла for-in.

Функции

В Swift есть два типа функций:

Пользовательские(User-defined Function) и функции стандартной библиотеки (Standard Library Functions).

Функции помогают организовывать код, разбив его на более мелкие части, что делает код более легким для понимания и переиспользования. Мы уже использовали функции стандартной библиотеки, такие как print() и type(). Рассмотрим, как создаются пользовательские функции.

Функция – блок кода, который выполняет конкретную задачу.

Каждая функция имеет уникальное имя, которое является ее идентификатором.

        func functionName(parameters) -> returnType {
  // тело функии 
}

    

Объявить функцию можно при помощи ключевого слова func.

За ним следует имя функцииfunctionName.

В скобках указываются параметры(parameters) функции.

Параметр – это значение определенного типа, принимаемое функцией.

returnType – указывает, какого типа значение возвращает функция

Чтобы исполнить функцию, ее необходимо вызвать (как мы уже делали это с print()).

        // вызов функции
functionName()

    

Функции без параметров

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

        func greetings() {
	 print("Hello Proglib!")
}
greetings()

print("Done!")

    

Мы объявили функцию с именем greetings() , которая просто печатает "Hello Proglib!" в консоли. Она не имеет параметров и возвращаемого значения. При вызове функции управление программой переходит к определению функции. Затем исполняется код, который содержится внутри тела функции:

        print("Hello Proglib!")
    

Как только функция завершится, управление потоком переходит к следующей инструкции после вызова функции.

        print("Done!")
    

Функции с параметрами

Функции, в которым мы передаем аргументы, называются функциями с параметрами. Если мы хотим, чтобы функция возвращала значение, нужно использовать оператор return.

Например, разница между двумя значениями:

        func difference(a: Int, b: Int) -> Int {
	return a - b 
}
var result = difference(a: 3, b: 2)
print(result)

    

Мы объявили функцию с именем difference, которая принимает два параметра типа Int и возвращает значение типа → Int. При вызове функции, мы передаем параметры в круглых скобках (a: 3, b: 2).

Каждый параметр функции состоит из метки аргумента и имени параметра. Имена параметров используются при реализации функции.

        func difference(of a: Int, less b: Int) -> Int {
  return a - b
}

    

Метка аргумента используется при вызове функции.

        difference(of: 1, less: 2)
    

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

Если вам не нужна метка для аргумента, то напишите _ вместо конкретного названия метки для аргумента.

        func difference(_ x: Int, _ y: Int) -> Int {
  return x - y
}

difference(3, 4)

    

Мы можем опустить оператор return , когда тело функции является одним выражением.

        func difference(a: Int, b: Int) -> Int {
	a - b 
}

    

Заключение

Мы познакомились с фундаментальным синтаксисом языка программирования Swift. Рассмотрели основные операторы, научились объявлять переменные и объединять код в функции. В следующие полчаса разберем каждую тему более глубоко. На сегодня все! Playground доступен на Github.

31
Окт
2021

Как Facebook идентифицирует приложение?

Всем привет. В java и react native нулевые скилы, пытаюсь для маркетологов разобраться в одной проблеме. Если кто знаком с подключением приложений в рекламные кабинеты, расскажите пожалуйста как FB идентифицирует приложение ? Есть какой-ни…

24
Окт
2021

SVG Text Trace по-другому отображается на устройствах iOS

Я использую анимацию трассировки SVG с помощью CSS, меняя значения stroke-dasdoffset с помощью анимации ключевых кадров.
При тестировании моих проектов на устройствах iOS (iPad / iPhone) кажется, что stroke-dasdoffset / массив рассчитывает…

28
Сен
2021

🍏 Взаимодействие SwiftUI с вебом. Часть 3: JavaScript – инструкция для новичков

В предыдущей статье мы разложили по полочкам навигацию в WebView. Самое время разобраться, как подружить SwiftUI с JavaScript, поскольку без этого языка программирования не обходится ни один современный сайт или мобильное приложение.

Мы уже добавили в проект (код доступен на GitHub – прим. ред.) перечисление WebViewNavigationAction, которое описывает три действия: назад, вперед, перезагрузить, а затем разобрались с пользовательским интерфейсом приложения, навигацией и получением информации с веб-страницы в Swift. Сегодня более подробно рассмотрим работу с JavaScript.

Создаем local.html

Подготовим простой файл HTML и отобразим его в WebView.

Создадим папку www в проекте. Внутрь положим файл local.html со следующим содержимым:

local.html
        <!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta http-equiv="Content-Style-Type" content="text/css">
  <title>Local HTML</title>
  <style>
    body {
      background: -webkit-linear-gradient(bottom left, #2b2f44 0%,#312442 100%);
      text-align: center;
      font-family: monospace;
      font-weight: bold;
      font-size: large;
    }
    .title {
      color: #FFFFFF;
    }
    .container {
      display: grid;
      justify-content: center;
      align-content: center;
      grid-auto-flow: row;
      gap: 12px;
    }
    .item {
      max-width: 600px;
      padding: 12px;
      background: #000000;
      border-radius: 5px;
      color: #FFFFFF;
    }
    #ok {
      background-color: #000000;
      color: #FFFFFF;
      font-size: medium;
      padding: 12px;
    }
  </style>
</head>
<body>
  <header>
    <h1 class="title">Interaction with JavaScript</h1>
  </header>
    <div class="container">
      <div class="item">
        <h1>Swift</h1>
      </div>
      <div class="item">
        <h1>JavaScript</h1>
      </div>
      <button id="ok">OK</button>
    </div>
</body>
</html>
    

При добавлении не забудьте указать create folder reference.

Чтобы показать локальный файл HTML, нам необходимо доработать WebView, но для начала обновим конфигурацию WebView в ContentView:

        WebView(type: .local, url: "local", viewModel: viewModel)
    

Вернемся в WebView и обновим логику в updateUIView:

        func updateUIView(_ webView: WKWebView, context: Context) {
	if let urlValue = url  {
		if type == .local {
			if let localUrl = Bundle.main.url(forResource: urlValue, withExtension: "html", subdirectory: "www") {
			webView.loadFileURL(localUrl, allowingReadAccessTo: localUrl.deletingLastPathComponent())
				}
			} else if type == .public {
				if let requestUrl = URL(string: urlValue) {
					webView.load(URLRequest(url: requestUrl))
				}
			}
		}
	}
    

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

        func loadFileURL(_ URL: URL, allowingReadAccessTo readAccessURL: URL) -> WKNavigation?
    
Важный момент!
Если readAccessURL ссылается на один файл, то Webkit сможет загрузить только его; если это директория, то и файлы внутри каталога могут быть загружены WebKit. В данный момент мы загружаем только один файл и все описываем внутри него (стили, скрипты).

Протестируем что у нас получилось!

А зачем оно все?

На практике встречаются такие задачи, когда нам нужно подгрузить веб-страницу с определенным контентом. Иногда мы хотим показать только часть содержимого и скрыть, например, <header> веб-страницы, который добавляет избыточную навигацию в приложение. В других случаях нам нужно понимать, что пользователь нажал на кнопку OK (когда это событие произошло).

Отладка JavaScript
Далее мы рассмотрим как работать с JavaScript из Swift, и наоборот. Если вы еще не знакомы с Web технологиями, такими как JavaScript, HTML, CSS, то ничего страшного. Я расскажу теоретический минимум, которые необходимо знать. Прежде чем добавлять сценарии JavaScript в приложение, я рекомендую проверить их в браузере. Откройте инструменты разработчика и протестируйте код в консоли.

Когда вы будете запускать код в WKWebView, global scope (глобальная область видимости) может стать проблемой, которая приводит к краху приложения из-за ошибок повторного объявления переменных и т.п.

Пара слов о global scope

В JavaScript используют const для объявления констант и let – для обычных переменных. Вы также можете воспользоваться var, но здесь тоже есть некоторые особенности, которые могут привести в замешательство.

Поэкспериментируйте с объявлением переменных. Например, получите заголовок всей веб-страницы document.title, как мы это уже делали в прошлой статье. Объявите переменные с const, let.

Если вы выполните в консоли несколько раз const title = document.title, то получите ошибку. Это можно исправить, если заменить const на let или ввести локальную область видимости (local scope), заключив код в фигурные скобки:

        { const title  = document.title; }
    

Чтобы проблем, стоит оборачивать код в функции. Поскольку они дают нам дополнительный контекст, вы можете быть уверены, что не получите подобных ошибок.

        function getDocTittle() { 
	const title  = document.title; 
	console.log(title);
}
getDocTitle();
    
Если вы хотите разобраться, как работают переменные и области видимости (scope), прочтите этот пост.

Селекторы

Чтобы произвести какие-либо действия с элементами веб-страницы, нужно получить на них ссылку. Selectors API предоставляет нам простой и эффективный способ получить элемент из DOM (Document-Object-Model), сопоставляя элементы заданному в параметре множеству селекторов. Спецификация добавляет два метода, которые мы можем применять к документу (Document), элементу (Element), и фрагменту документа (DocumentFragment):

  • querySelector(selectors) вернет первое совпадение. Если совпадений не найдено, то null.
  • querySelectorAll(selectors) вернет все совпадения (NodeList), или пустой NodeList, если их нет.

Когда сайты имеют хорошую разметку, чаще всего в качестве параметра (selectors) мы передаем CSS-класс, ID элемента, имя тега элемента. Для для формирования более точных запросов следует передавать множество CSS-селекторов.

Рассмотрим все вышеизложенное на примерах.

Например, в <body> на веб-странице у нас есть:

  • <header> внутри которого заголовок.
  • <h1> c классом title.
  • <div> – блок с классом container, в котором содержатся:
  • два блока <div> с классом item, в котором содержатся:
  • заголовки <h1>;
  • кнопка <button> с идентификатором ok.

Получим наш заголовок из тега <head>:

        const h1 = document.querySelector('h1');
    
Поскольку в нашем примере заголовок в документе самый первый, то мы получили нужное. А если в <head> определили два заголовка? Например, мог быть заголовок в шапке сайта, который описывает бренд, а за ним следует заголовок, который задает название контенту содержимого. В таком случае нам бы пришлось создать более точный запрос.

Классы более общие, а идентификаторы всегда уникальные во всем документе, и у каждого элемента в HTML есть глобальные атрибуты.

Атрибут class – один из них. Он позволяет CSS и JavaScript выбрать и получить элемент при помощи селекторов CSS или функций JavaScript.

Если хотим получить именно название (title), то лучше воспользоваться более точным запросом. В передаваемом селекторе, точка означает, что мы имеем дело с именем класса.

        const title = document.querySelector('.title');
    

Оба запроса вернули один и тот же результат:

        <h1 class="title">Interaction with JavaScript</h1>
    

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

Теперь получим кнопку с идентификатором ok:

        const button = document.querySelector('#ok');
    

В передаваемом селекторе решетка означает, что это имя идентификатора.

Результат:

        <button id="ok">OK</button>
    

Воспользуемся следующим запросом, чтобы исследовать элементы тега div:

        let divs =  document.querySelectorAll("div")


    

В результате получим состоящий из трех элементов NodeList:

        [div.container, div.item, div.item]


    

Создадим более точные запросы, чтобы получить контент заголовков <h1> внутри элементов div.item:

         let itemsContent = document.querySelectorAll("div.item h1");


    

C помощью метода forEach мы можем перебирать элементы NodeList. Выведем результат в консоль:

        itemsContent.forEach(function(title) { console.log(title.innerText)) }
    
Управление элементами
Как получить элементы из документа, мы уже разобрались. Давайте научимся ими манипулировать. Стоить отметить, что существует несколько способов как и получения элементов, так и несколько способов выполнить ту или иную задачу с некоторыми тонкостями и особенностями. Например, такие задачи как, скрытия элементов, проверки на существование элемента в документе и т.д. Поэтому если вы уже подкованы в этой области, поделитесь своим опытом в комментариях. Далее мы не будем останавливаться на всевозможных способах и деталях. Просто посмотрим на часто распространенные примеры.

Скрытие элементов

Например, чтобы скрыть title, воспользуемся свойством display:

        title.style.display = 'none';
    

Разумеется, при обновлении WebView элемент снова появится.

Существует ли элемент?

Часто встречающаяся задача – проверка присутствия элемента. Если вы не совсем уверены в получаемом результате, оберните его в условный оператор if. Попробуем получить первый заголовок второго уровня <h2>, которого не существует в примере, и скрыть его:

        const h2 = document.querySelector('h2');
if(h2) { h2.style.display = 'none'; }
    

Клики и события

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

JavaScript предоставляет нам метод addEventListener, в котором два параметра:

  • название события, например, ‘click’.
  • функция, которая выполняет какой-либо код, когда происходит событие.
        button.addEventListener('click', function(e) { 
  console.log(e); 
  console.log('OK Clicked');
});
    

Мы добавили событие click, и по нажатию на кнопку OK должны увидеть в консоли: ”OK Clicked”.

Параметр е, который передается в функцию, описывает само событие click. К самому элементу можно обратиться через e.target.

Стоить отметить, что в JavaScript есть стрелочные функции, однако если вы незнакомы с особенностями языка, это может вызвать замешательство. Чтобы избежать путаницы с тем, куда указывает this, я использовал обычную функцию, где this в теле функции указывает на саму кнопку.

Как получить контент элемента или атрибута?

Существует несколько способов в DOM API получить контент элемента, но у каждого свои особенности и назначения. Допустим мы хотим получить контент нашего названия title.

Например, при помощи свойств:

  • textContent
  • innerText

title.innerText и title.textContent в данном случае возвращают одни и те же результаты. Однако они весьма отличаются. textContent может вернуть нам даже текстовое содержимое блока <style>.

Поскольку чаще всего нам требуется получить читабельный контент, то innerText является лучшим выбором и используется в большинстве случаев, но его результат зависит от стилей. Если элемент скрыт, то мы ничего не получим.

Чтобы разница была явно видна, получите элемент HTML и посмотрите, что будет в этих свойствах.

Для более подробного изучения смотрите документацию, а также обратите внимание на свойства outerText, innerHtml и outerHtml.

Порой нам необходимо вытащить у элемента <img> ссылку на изображение, которая находится в атрибуте src или значение элемента <input>. Сделать это довольно просто:

        let imgSrc = img.src;
    
        const input = document.querySelector('#mylInput');
let inputValue = input.value
    

Run JS! Run!

В предыдущей статье мы использовали метод evaluateJavaScript для получения заголовка документа. Остановимся на нем поподробней.

        open func evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil)


    
В этот метод мы передаем строку, которая представляет из себя код на JavaScript и получаем результат. Если мы ничего не возвращаем явно, то JavaScript runtime вернет нам undefined. Для отслеживания, каких либо блоков кода на JavaScript удобно использовать в качестве возвращаемого результата true или false. В completionHandler передается результат исполнения скрипта или ошибка.

В документации сказано, что вызов этого метода равноценен вызову метода, где значение framenil представляет главный фрейм, а значение contentWorldWKContentWorld.pageWorld:

        public func evaluateJavaScript(_ javaScript: String, in frame: WKFrameInfo? = nil, in contentWorld: WKContentWorld, completionHandler: ((Result<Any, Error>) -> Void)? = nil)


    

Данное улучшение доступно начиная с iOS 14.

  • WKFrameInfo содержит информацию о фрейме на странице.
  • WKContentWorld – этот объект определяет область видимости выполнения кода JavaScript, т.е. мы должны использовать его как пространство имен (namespace).
Рассмотрим его более подробно. Это ключевой параметр функции, который дает нам большую гибкость и обеспечивает предотвращение многих конфликтов. Мы можем его использовать для предотвращения конфликтов между скриптами на веб-странице. Выполнение сценарии JavaScript в собственном WKContentWorld дает нам отдельную копию переменных среды для изменения.

Получим заголовок из шапки и покажем его в нашем NavigationView. Для этого создадим файл JSUserScripts.swift, где напишем сценарии JavaScript, которые будут модифицировать страницу и забирать из нее данные.

Напишем две функции для получения и скрытия заголовка на веб-странице:

JSUserScripts.swift
        let getHeaderTitle  = """
function getHeaderTitle() {
	const headerTitle = document.querySelector('h1.title');
	return headerTitle.innerText;
}
getHeaderTitle();
"""

let hideHeaderTitle = """
function hideHeaderTitle() {
	const headerTitle = document.querySelector('h1.title');
	headerTitle.style.display = 'none';
}
hideHeaderTitle();
"""
    

Теперь заменим старый метод evaluateJavaScript улучшенной версией:

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
	print("didFinish")
	self.parent.viewModel.isLoaderVisible.send(false)
			
	webView.evaluateJavaScript(getHeaderTitle, in: nil, in: .defaultClient) { result in
		switch result {
			case .success(let value):
				if let title = value as? String {
					self.parent.viewModel.webTitle.send(title)
				}
						
			case .failure(let error):
				print(error.localizedDescription)
		}
	}
			
	webView.evaluateJavaScript(hideHeaderTitle, in: nil, in: .defaultClient)
}

    

Свойство .defaultClient предоставляет пространство имен (namespace) по умолчанию для приложения.

Если нам нужно запустить скрипт внутри пространства имен текущей веб-страницы, мы можем использовать .page

        webView.evaluateJavaScript(hideHeaderTitle, in: nil, in: .page)

    

Также мы можем создавать собственные пространства имен:

        webView.evaluateJavaScript(hideHeaderTitle, in: nil, in: .world(name: "magic"))


    

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

Еще один интересный метод, который пришел вместе с iOS 14:

         public func callAsyncJavaScript(_ functionBody: String, arguments: [String : Any] = [:], in frame: WKFrameInfo? = nil, in contentWorld: WKContentWorld, completionHandler: ((Result<Any, Error>) -> Void)? = nil)
    

В параметр functionBody, в качестве строки мы передаем само тело функции, а в качестве arguments мы можем передавать переменные, которые будут использованы в функции, что очень удобно. Такая гибкость позволяет нам переиспользовать блоки кода JavaScript.

Как видно из названия, Async означает, что строка будет запущена как асинхронная функция. В этом случае можно использовать await и работать с JavaScript-обещаниями (Promise). Такая техника необходима, когда мы не знаем, когда именно будет завершена работа функции или когда необходимо что-то запустить через определенное время (например setTimeout).

Рассмотрим несколько примеров:

        let hideAnyElement  = """
	const element = document.querySelector(selector);
	element.style.display = 'none';
"""

let getElementInnerText = """
	const element = document.querySelector(selector);
	return element.innerText;
"""
    

Исполним JavaScript:

        webView.callAsyncJavaScript(hideAnyElement, arguments: ["selector":"#ok"], in: nil, in: .defaultClient)

    

Код стал элегантней. Теперь мы можем передавать селекторы в качестве аргументов и скрывать любые элементы веб-страницы.

Напишем простое обещание (promise):

        let setTimeoutFor = """

	const myPromise = new Promise((resolve, reject) => {
        window.setTimeout(function (){
		  resolve('foo');
		}, timeout);
	  });

	
	 await myPromise;
	 return myPromise;
"""
    

Исполним JavaScript:

        let timeout = 3000;
webView.callAsyncJavaScript(setTimeoutFor, arguments: [ "timeout":"\(timeout)"], in: nil, in: .defaultClient) { (result) in
				
				switch result {
				case .success(let response):
					print("Done...");
					print(response);
				case .failure(let error):
					print("Error...");
					print(error)
				}
			}

    

После трех секунд ожидания мы получим результат “foo” в приложении.

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

Такую коммуникацию нам помогает реализовать протокол WKScriptMessageHandler и объект WKUserContentController, который предоставляет возможность отправки сообщений JavaScript в WKWebView. Протокол WKScriptMessageHandler определяет всего одну функцию, в которой мы можем получить сообщение из запущенных на веб-странице сценариев.

Напишем расширение для Coordinator, в которое и добавим реализацию этой функции:

        extension WebView.Coordinator: WKScriptMessageHandler {
	func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
		if message.name == "messageAppHandler" {
			if let body = message.body as? String {
				print("Message body: \(body)")
			}
		}
	}
}

    

В методе makeUIView (здесь мы создаем WebView и задаем его конфигурацию) укажем наш класс, который реализует обработчик сообщений и его имя:

        webView.configuration.userContentController.add(context.coordinator, contentWorld: .page, name: "messageAppHandler")

    
  • Аргумент name определяет название нашего обработчика сообщений WKScriptMessageHandler. Обратите внимание, что namе (имя обработчика сообщений) используется для определения, какой именно WKUserContentController отправляет сообщение.
  • Свойство body содержит наше сообщение (строку или объект JSON).
  • На веб-странице, чтобы отправить сообщение нашему обработчику, мы должны вызвать у него метод postMessage.

Добавим скрипт на веб-страницу, и отправим сообщение:

        <script type="text/javascript">
	  sendValueToApp();
	  
	  function sendValueToApp() {
		  window.webkit.messageHandlers.messageAppHandler.postMessage('Hello from web page');
	  }
  </script>
    

Запустим и проверим, что получаем наше сообщение с веб-страницы в консоли.

На этом пока все. Код проекта доступен на Github.

P.S. Happy Code!

14
Авг
2021

Вопрос: как сделать игру/программу с загружаемым кешем [закрыт]

Возможно ли сделать такое, что:
на андроид или iOS будет установлено приложение, которое в зависимости от того, появилась ли новая версия, будет закачивать кеш и использовать его, но не будет обновлять саму программу?
Я такое видел уже во …

21
Июл
2021

🍏 Разработка мобильных игр для iOS: с чего начать, что изучать и какие инструменты использовать

Платформа Apple пользуется огромной популярностью – это привлекает начинающих разработчиков мобильных игр. Разбираемся, какие инструменты придется изучить новичку, чтобы создать очередной хит для AppStore.

13
Июл
2021

🍏 Изучение iOS-разработки в 2021 году: 5 советов новичкам

Если вы пытаетесь изучить разработку мобильных приложений для iOS с нуля, в куче доступных гайдов и дорожных карт легко потеряться. В небольшом обзоре мы собрали необходимый минимум навыков для старта в профессии. Правильный подход – не пыт…

13
Июл
2021

🍏 Изучение iOS-разработки в 2021 году: 5 советов новичкам

Если вы пытаетесь изучить разработку мобильных приложений для iOS с нуля, в куче доступных гайдов и дорожных карт легко потеряться. В небольшом обзоре мы собрали необходимый минимум навыков для старта в профессии. Правильный подход – не пыт…

02
Июл
2021

🍏 Путь в профессию: интервью с iOS-разработчиком Кевином Ренскерсом

Создание приложений для iOS – одно из самых перспективных направлений в IT. Наш корреспондент пообщался с программистом-фрилансером из Голландии, который трудится в этой сфере уже 11 лет. Он рассказал о своем пути в iOS, Swift и SwiftUI, а также о будущем iOS-разработки.

– Как вы пришли к разработке приложений для iOS?

В 2009 году я начал работать в местной компании в качестве программиста на Python. Мы создавали веб-сайты для крупных компаний, используя Plone и Django. В 2010 году некоторые клиенты начали просить приложения для iPhone, и это стало началом моей карьеры разработчика iOS: мне платили за то, чтобы научиться создавать эти приложения.

К тому времени у меня уже был десятилетний опыт работы в программировании. Я начал в 2000 году создавать веб-сайты с помощью HTML и Flash, в 2001 году занялся PHP и JavaScript, а в 2009 году перешел на Python.


– Вы занялись разработкой для iOS в 2010 году. Что изменилось сейчас?

Почти все. Когда я начинал, мы не только все еще использовали Objective-C (который мне действительно очень нравился), но даже ARC еще не существовало. Xcode еще не был интегрированным инструментом, Interface Builder был отдельным приложением, поэтому вы могли открывать обе программы одновременно. Это было очень мило.


Даже блоки (замыкания, обработчики завершения) еще не существовали, не было дополнительных элементов, не существовали литералы массивов и словарей и раскадровки – список можно продолжать и продолжать.

– 11 лет – большой срок. Чему вам пришлось научиться за это время?

Очевидно, мне сначала нужно было изучить Objective-C, UIKit, Foundation и другие фреймворки. Позже мне пришлось изучить Swift, функциональное программирование, реактивное программирование, а также все новые фреймворки и API, которые Apple представила за эти годы. MVC, MVVM, координаторы, составная архитектура – обучение никогда не прекращается!

Однако написание приложений для iOS сильно отличается от написания веб-приложения, поэтому освоение правильных шаблонов, таких как делегаты и способы работы с (фоновыми) потоками, было своего рода кривой обучения.

– В 2010 году Apple была не такой огромной корпорацией. Почему вы выбрали разработку под iOS?

Я бы не сказал, что они не были крупной компанией в 2010 году. Конечно, сейчас они огромны, но iPhone стал хитом с самого первого выпуска. В любом случае меня не волновал размер, я просто знал с первых же слухов о телефоне Apple, что он будет отличным. Когда Джобс представил iPhone, я был влюблен и знал, что мне нужен именно такой. Требовалось, чтобы iPhone 3GS был доступен в Нидерландах.

Я хотел разрабатывать приложения для этого устройства, потому что оно было таким безупречным и гладким. Все было быстро, приложения удобны для пользователя и хорошо спроектированы… это было намного лучше, чем что-либо до него, это было революционно.


Что вы думаете о Swift и SwiftUI? Хотите что-то в них изменить?

Обожаю Свифт! Я дождался Swift 3, пока не начал его использовать. Я работал над большими сложными приложениями Objective-C, мне очень нравился Objective-C, поэтому я дождался подходящего момента для перехода. Этот момент наступил в декабре 2016 года: я только начал работать фрилансером и начал новый проект с нуля, поэтому в тот момент Swift казался очевидным выбором.

SwiftUI, с другой стороны… Мне нравится его концепция, я бы хотел иметь возможность использовать его, но он еще не готов. Я создал побочный проект средней сложности с использованием SwiftUI 1, когда он был только что выпущен, и хотя мне понравилось первоначальное повышение производительности, это быстро превратилось в раздражение, так как я потратил слишком много времени, работая над ошибками и сбоями в самом SwiftUI. Легкие вещи стали действительно легкими, а сложные – невозможными. Я отказался от этого побочного проекта.

Я действительно надеюсь, что SwiftUI стал лучше с iOS 15, но если вы не пишете приложение только для iOS 15+, это не имеет значения. На самом деле я не думаю, что буду использовать SwiftUI для производства в ближайшие 2 или 3 года.

Я бы хотел изменить то, чтобы изменения Swift и SwiftUI можно было использовать со старыми версиями iOS. Например, новая поддержка async/await в Swift действительно потрясающая. Но… только для iOS 15+. Я бы хотел, чтобы Apple нашла способ удалить такие зависимости из самой базовой ОС, чтобы отдельные фреймворки могли обновляться без полного обновления ОС. То же самое и с такими приложениями, как Mail, Weather, Notes и т. д. Почему они являются частью самой iOS? Если бы они были в App Store, как и любое другое приложение, их можно было бы обновлять чаще и с меньшими проблемами.

– Какие ресурсы вы используете для работы и обучения?

– Были у вас ошибки, и что бы вы посоветовали ребятам из России, которые только начинают осваивать профессию?

На самом деле это не ошибка, но мне бы хотелось, чтобы я вскочил на подножку FRP немного раньше. Мне никогда не нравился RxSwift (или ReactiveCocoa во времена Obj-C), он никогда не работал до тех пор, пока я не начал использовать ReactiveKit и Bond еще в 2019 году. Теперь я использую Combine во всех своих приложениях с 2020 года, и не могу представить, что вернусь к старому способу создания приложений.

Если вы только начинаете разработку iOS, совет номер один – не перегружаться всеми вариантами архитектуры и не пытаться делать все идеально с самого начала. Просто используйте MVC, не волнуйтесь, получите ли вы в итоге массивные контроллеры представления или нет. Используйте раскадровку с переходами, если они вам нравятся, даже не думайте пока о координаторах. Забудьте о комбинированном и реактивном функциональном программировании.

Просто начните с основ и получайте удовольствие! Вы поймете, что не масштабируется, когда начнете создавать большие приложения, и будете искать решения проблем по мере их появления. Но если вы хотите делать все идеально с самого начала, вы просто закончите аналитическим параличом и вообще ничего не сделаете.

– Какое будущее у iOS-разработки?

SwiftUI и async/await. Жаль, что будущее реальных приложений, где вы должны поддерживать старые версии iOS – это буквально несколько лет.

– Чем вы занимаетесь сейчас и какие у вас планы?

Я занимаюсь проектом для клиента, в котором также работаю над приложением iOS и серверным кодом. Планирую продолжать получать удовольствие как разработчик-фрилансер, принимая проекты, которые меня интересуют.

Мне почти 40 лет, и я не знаю, как долго захочу оставаться разработчиком или фрилансером. Так что со временем я, возможно, захочу больше сосредоточиться на том, чтобы быть наставником, чем мне действительно нравится заниматься сейчас несколько часов в неделю. Посмотрим 🙂
***

Если вы хотите получить необходимые знания в структурированном виде и без лишней воды, стоит обратить внимание на курс Факультета iOS-разработки образовательной онлайн-платформы GeekBrains. За 12 месяцев вы освоите два языка программирования и современные технологии создания приложений, научитесь писать чистый код и реализуете несколько проектов для портфолио. Обучение будут курировать эксперты-практики, а после защиты финального проекта студентам выдадут электронные сертификаты и дипломы о профессиональной переподготовке. HR-специалисты GeekBrains помогут выпускникам с трудоустройством.

29
Июн
2021

Как разрешить iphone обрабатывать js скрипты в браузере chrome, safary?

Столкнулся с блокировкой js скрипта в iphone 12 при загрузке веб-сайта. Простой скрипт, который переключает видимость меню и загружает пак иконок не работает. Кто с этим сталкивался, как обойти это ограничение без настроек в системе устрой…

21
Июн
2021

Apple Tech Business Week. День 3

Эксперты обсудят безопасность macOS, интерфейс-тренды, Combine, SwiftUI, проектирование сложных B2B-продуктов и организацию ИТ-офисов.
— Читать дальше «Apple Tech Business Week. День 3»

20
Июн
2021

Нужна помощь в копировании в буфер обмена в Safari(ios, mac и тд) JavaScript(React) Подкажите возможно кт то сталкивался с такой проблемой

function App() {

const copyToClipboard = (textToCopy: string) => {

var el: any = document.createElement(‘textarea’);
el.value = textToCopy;
el.setAttribute(‘readonly’, ”);
el.style = { position: ‘absolute’, lef…

11
Июн
2021

Пользователи Apple смогут использовать Face ID и Touch ID вместо пароля при регистрации на сайтах

Доступ к бета-версии новой функции появится до конца 2021 года.
— Читать дальше «Пользователи Apple смогут использовать Face ID и Touch ID вместо пароля при регистрации на сайтах»

09
Июн
2021

Хакатон INNOHACK 2.0

Команды из разработчиков, аналитиков, тестировщиков, DevOps-инженеров и UI/UX-дизайнеров должны решить одну из 5 бизнес-задач. Призовой фонд — 1,2 млн рублей. Заявки принимаются до 15 июня.
— Читать дальше «Хакатон INNOHACK 2.0»

01
Июн
2021

Конференция WWDC 2021

На Всемирной конференции разработчиков Apple представят последние обновления и дадут участникам возможность пообщаться с ведущими инженерами компании.
— Читать дальше «Конференция WWDC 2021»

31
Май
2021

🍏 Карьерный гид от новичка до профи: дорожная карта iOS-разработчика

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

Согласно MacRumors, количество активных iPhone достигло 1 млрд. единиц. Если вы хотите заниматься разработкой приложений для мобильной платформы Apple, наша дорожная карта познакомит вас с перечнем необходимых технологий.

Преимущества разработки для iOS во многом схожи с достоинствами других востребованных специализаций в программировании: высокая заработная плата, постоянная нехватка квалифицированных специалистов, возможность реализации творческого и карьерного потенциала.

Используя представленную дорожную карту, начинающий специалист сможет составить индивидуальный план обучения и следовать ему, чтобы стать настоящим профессионалом. Обратите внимание, что Roadmap посвящен исключительно технической стороне развития iOS-разработчика (т.н. hard skills).


1. Swift


Swift – основной язык программирования для iOS. Он достаточно молод, но успел полюбиться многим за простоту, читабельность и безопасность. Создатели Swift взяли все лучшее из Objective-C, C/C++ и Java. Обучение стоит начинать со знакомства со средой разработки Xcode, потому что большую часть времени вы будете проводить именно в ней. Далее все по классике: объектно-ориентированное программирование (ООП), знакомство с переменными, типами данных, операторами условий, циклами, классами, наследованием, исключениями. Структуры данных, алгоритмы и паттерны проектирования вынесены в отдельный блок, потому что эти темы займут значительную часть времени на изучение, и вопросы по ним задают практически на каждом собеседовании.

Продолжительность обучения: 6-8 месяцев.

2. Фреймворки

Когда вы поработаете со Swift, стоит познакомиться и с основными фреймворками. Фреймворк – это каркас будущего приложения, т.е. набор инструментов для ускорения разработки. Начать стоит со SwiftUI, поскольку это тоже обязательный пункт при трудоустройстве. Фреймворк используется для создания визуальной части приложения (полей ввода, таблиц, изображений и т.д.). Также рекомендуется изучить UIKit, как более зрелый написанный для Objective-C инструментарий.

Продолжительность обучения: 1 месяц.

3. Работа в сети

Ваша программа может взаимодействовать с другими внешними приложениями и сервисами, поэтому важно научиться работать с Rest API, принимать и отправлять JSON-объекты.

Продолжительность обучения: 2-3 недели.

4. Взаимодействие с БД

Важный навык любого разработчика – уметь обращаться к базе данных, чтобы получить, изменить, либо добавить в нее информацию. Для этого необходимо знать, как происходит подключение к БД, а также изучить основные команды CRUD (create, read, update, delete).

Продолжительность обучения: 2-3 недели.

5. Система контроля версий


Следующий обязательный навык – умение работать в команде. Для этого используется система контроля версий (version control system). Наиболее популярной из них является Git. Овладев ее базовыми командами, вы сможете вести параллельную разработку с коллегами, откатывать изменения, если обнаружился баг, а также предоставить рекрутерам код для оценки ваших навыков.

Продолжительность обучения: 2 недели.

Представленный выше набор технологий является минимальным, чтобы получить должность младшего iOS-разработчика (джуна). В процессе дальнейшего развития придется существенно его расширить.

6. Тестирование

Написание тестов – важный шаг при разработке приложения. Можно сказать, что качество вашего кода напрямую зависит от наличия (количества) тестовых сценариев. В техминимум входит модульное тестирование, охватывающее базовую функциональность программы (например, взаимодействие с контроллером), работу с UI и т.д. Если вы будете обладать навыком написания тестовых сценариев, это позволит вашему работодателю сэкономить время и деньги.

Продолжительность обучения: 1 неделя.

7. Многопоточность

Важнейшим навыком в профессиональном развитии разработчика является способность реализовать асинхронное выполнение задач. Вам предстоит ознакомиться с понятием потока, проблемами многопоточности (взаимная блокировка, состояние гонки, инверсия приоритетов), разобраться с библиотекой GCD для параллельного выполнения задач и Operation.

Продолжительность обучения: 1-2 месяца.

8. Работа с App Store


Умение работать с магазином приложений добавит еще один жирный плюс к вашим навыкам iOS-разработки. Желательно научиться не только алгоритму добавления в маркет, но и освоить коммуникацию с модераторами, следовать регламентам компании Apple.

Продолжительность обучения: 1 неделя.

Минимально необходимое вам для освоения всех перечисленных технологий время составит около 10 месяцев.

Заключение

Представленная дорожная карта отражает только основные технологии, знание которых необходимо iOS-разработчику в 2021 году. Эта, как и большинство других в сфере ИТ, предполагает непрерывное самосовершенствование. Постоянно осваивайте новое, практикуйте его и внедряйте в работу. Успехов в обучении!

***

Основные вопросы, которыми задаются интересующиеся iOS-разработкой новички: как получить структурированную информацию, как обратиться за помощью и как реализовать несколько проектов для портфолио, если без опыта никуда не берут? Обратите внимание курс Факультета iOS-разработки образовательной онлайн-платформы GeekBrains. За 12 месяцев вы поработаете на языках программирования Swift и Objective-C, на практике примените основные паттерны проектирования и современные фреймворки. К окончанию обучения в вашем портфолио будет несколько готовых проектов, среди которых аналог мессенджера ВКонтакте, приложение для API сериала Rick & Morty и другие. Вы также получите электронный сертификат и диплом о профессиональной переподготовке, а HR-специалисты помогут выпускникам с трудоустройством.

28
Май
2021

Не скачивается PDF в сафари через JS

Использую следующее решение , в нормальных браузерах таких как хром, фаерфокс , опера.
Но сафари просто открывает в новом окне pdf
function SaveToDisk(fileURL, fileName) {
// for non-IE
if (!window.ActiveXObject) {
var save = docum…

28
Май
2021

Не скачивается PDF в сафари через JS

Использую следующее решение , в нормальных браузерах таких как хром, фаерфокс , опера.
Но сафари просто открывает в новом окне pdf
function SaveToDisk(fileURL, fileName) {
// for non-IE
if (!window.ActiveXObject) {
var save = docum…

26
Май
2021

🕵 GPG и все-все-все: настраиваем шифрование переписки за 10 минут по методу Кристофера Робина

Как обмениваться критически важными коммерческими сведениями с контрагентами, если вы слабо разбираетесь в вопросах информационной безопасности? Прочтите наш мануал и настройте шифрование GPG на смартфоне и компьютере за 10 минут.

25
Май
2021

Как подключить Circle (Крипто обменник) к IOS/Android приложению (Просто идеи)?

Всем привет хотела узнать как можно подключить Circle(circle.com) к Android/IOS приложении. Даже идей нет как это сделать. Можете поделиться идеями как можно это реализовать 🙂

17
Май
2021

🍏 Где изучать iOS-разработку в 2021 году: каналы, блоги, комьюнити и курсы

Если вы хотите писать востребованные у пользовательской аудитории мобильные приложения, наш обзор поможет вам найти посвященные разработке для iOS ресурсы.

В рейтинге наиболее востребованных в 2021 году языков программирования от профильного ресурса DOU.UA Swift (iOS) находится в ТОП-10.

Новички обычно не хотят тратить несколько лет на получение профильного образования. Для них важнее быстрое перепрофилирование (в среднем в течение года) и возможность применить полученные знания на практике. В представленном обзоре ресурсов начинающие iOS-разработчики смогут найти необходимую информацию, которая вкупе с ежедневной практикой поможет получить долгожданный оффер.

Каналы


Школа iOS-разработчиков

YouTube-канал Александра Сенина, разработчика приложений для iOS и OS X. Александр делится с подписчиками основами программирования на языке Swift, объясняет, как работать в среде Xcode, а также отвечает на вопросы студентов своего обучающего курса. Вместе с ним вы сможете создать приложение «ToDo List» и попробовать выполнить тестовое задание на позицию iOS-разработчика.

Школа Брата Антония

Проект Антона Марченко, iOS-разработчика из Беларуси. В своих видео Антон на интересных примерах объясняет основы создания приложений для iOS: от переменных, констант и типов данных до классов и объектов. Испытайте себя на практике, сделав вместе с Братом Антонием простое приложение«Камень Ножницы Бумага».

Ivan Skorokhod

YouTube-канал об iOS-разработке с небольшой аудиторией. Главное его преимущество – русскоязычные пояснения к лекциям Стэнфордского университета по программированию на Swift. Это облегчит изучение тем, кто не уверен в своих языковых способностях.

Гоша Дударь

Один из крупнейших каналов по программированию в русскоязычном сегменте. Отдельный блок по iOS рассчитан на быстрое погружение в основу разработки на языке Swift. Благодаря размещенным на канале урокам вы сможете написать простой «Калькулятор» и небольшую 2D-игру с помощью библиотеки SpriteKit. У проекта есть большое сообщество, в котором присутствуют специалисты по разным направлениям.

iOS Academy

Американский YouTube-канал Афраза (Afraz) разработчика из Microsoft. В своих видео автор делится знаниями iOS-разработки для Apple Watch, рассказывает об алгоритмах, Swift и Objective-C, а также в упрощенной форме показывает как создавать приложения Spotify и Instagram.

Блоги


Блог Stfalcon

Блог компании-разработчика сервисов и мобильных приложений Stfalcon. Кроме публикаций по основам программирования для iOS здесь можно найти идеи для приложений, изучить опыт других разработчиков, разобраться в шаблонах, а также познакомиться с понятием «чистый код».

iOS Blog

Этот блог будет интересен всем любителям «яблочных гаджетов». Здесь делятся новостями компании Apple, слухами и инсайдами, а также дают советы по использованию различных функций в устройствах Apple.

Комьюнити


CocoaHeads Russia

CocoaHeads это сообщество, предоставляющее iOS-разработчикам возможность участия во множестве митапов, открытых столов и викторин. Все спикеры и организаторы – действующие iOS-разработчики, с которыми вы можете познакомиться и обменяться опытом. У сообщества есть свой телеграм-канал: в нем публикуется актуальная информация о предстоящих мероприятиях.

iOS developers

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

Ios – DEV Community

Сообщество разработчиков, которое основали Ben Halpern, Jess Lee и Peter Frank. Проект будет интересен специалистам всех направлений, поскольку охватывает большую часть технологического стека. В частности, iOS-разработчики оценят идеи для создания мобильных приложений, использование SwiftUI, а также смогут предложить сообществу собственные решения каких-либо проблем.

Курсы


GeekBrains

Образовательная онлайн-платформа GeekBrains предлагает множество программ обучения по различным ИТ-направлениям. iOS-разработчики смогут найти здесь курсы по Swift для начинающих, а также по клиент-серверным приложениям iOS и пользовательскому интерфейсу. Вдобавок ко всему портал предлагает множество вебинаров, развитое сообщество и возможность подготовки к трудоустройству.

SwiftBook

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

Swiftme

Курсы Василия Усова автора нескольких книг по iOS-разработке на языке Swift. Пользователь может выбрать самостоятельное обучение, индивидуальные занятия с наставником или обучение в группе. Также вы можете присоединиться к телеграм-каналу, в котором представители сообщества разработчиков делятся опытом и помогает друг другу в решении задач.

iOS & Swift – The Complete iOS App Development Bootcamp

Это большой курс (55 часов) от Dr. Angela Yu, работавшей с Twitter, Facebook и Google. У него один из самых высоких рейтингов на Udemy: за время обучения вы познакомитесь с основами программирования на Swift и дизайн-паттернами, а также узнаете как работать с документацией и как правильно гуглить.

Apple Developer

Посвященный обучению iOS-разработке ресурс компании Apple. Здесь вы сможете детально познакомиться со средой Xcode 12, фреймворком SwiftUI, а также изучить документацию и понять, как разместить ваше приложение в App Store.

Заключение

Есть довольно много качественных источников информации для изучения iOS-разработки. Лучший вариант – комбинировать разные ресурсы, чтобы охватить больше нужных для профессионального развития тем. Желаем вам успехов в обучении. Удачи!

***

Если вы хотите получить необходимые знания в структурированном виде и без лишней воды, стоит обратить внимание на курс Факультета iOS-разработки образовательной онлайн-платформы GeekBrains. За 12 месяцев вы освоите два языка программирования и современные технологии создания приложений, научитесь писать чистый код и реализуете несколько проектов для портфолио. Обучение будут курировать эксперты-практики, а после защиты финального проекта студентам выдадут электронные сертификаты и дипломы о профессиональной переподготовке. HR-специалисты GeekBrains помогут выпускникам с трудоустройством.

22
Апр
2021

safari скачивает файл вместо открытия страницы

Добрый день сайт на MODX, во всех браузерах кроме safari, все нормально, при открытии в safari, скачивается файл с названием сайта(содержимое не могу посмотреть Мака нет, проверял в эмуляторе, в реальном маке та же проблема)
Хостинг ActivC…

17
Апр
2021

🍏 Взаимодействие SwiftUI с вебом. Часть вторая: Web Navigation

В предыдущей статье мы создали WebView и подгрузили в него сайт proglib.io. Сегодня займемся пользовательским интерфейсом приложения, навигацией и получением информации с веб-страницы в Swift c помощью JavaScript.