Kotlin/Swift (iOS) Туда и Обратно
36 subscribers
130 photos
21 videos
9 files
88 links
Канал - журнал, рассказывающий об опыте изучения Swift & iOS backend-разработчиком на Java & Kotlin
Download Telegram
➡️Day 7: Functions, parameters, and return values

Интересный топик, т.к. тут я нашёл для себя отличный функционал, а именно алиасы (ака внешнее имя) для параметров. Выглядит это так:

func printTimesTables(for number: Int) {
for i in 1...12 {
print("\(i) x \(number) is \(i * number)")
}
}

printTimesTables(for: 5)

💡 Что это даёт?
Внутри функции мы обращаемся к параметру как number, а при вызове - используем более понятное имя for. Это значительно улучшает читаемость и восприятие кода.

Кстати, Swift позволяет использовать даже зарезервированные слова вроде for в качестве алиасов, что тоже приятно удивляет.

А вот работа с Tuple оказалась приятной неожиданностью.

func printTupleValues(tuple: (a: Int, b: Int, c: Int)) {
print(tuple.a)
print(tuple.b)
print(tuple.c)
}

printTupleValues(tuple: (1, 2, 3))
printTupleValues(tuple: (a: 2, b: 3, c: 1))


В Kotlin отсутствует встроенная структура данных, аналогичная кортежам в Swift. Вместо этого там есть Pair (для двух элементов) и Triple (для трёх элементов). Если требуется больше элементов, обычно используются data class или списки.

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

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
В ближайшие дни я планирую закончить с первыми 14 уроками, которые посвящены основам Swift как языка. Эти уроки дают базу, необходимую для понимания ключевых концепций, таких как работа с типами, функциями и структурами данных. Всё это несомненно пригодится в дальнейшем.

Что дальше?
После этого нас ждет работа с серией занятий про SwiftUI - жду с нетерпением! 🥺
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21🎉1
➡️Day 8: Default values, throwing functions, and checkpoint 4

Дефолтные значения параметров не стали для меня откровением, так как они присутствуют и в Kotlin, поэтому тут всё ожидаемо.
А вот конструкция для перехвата исключений выглядит немного странно

do {
try throwingFunction1()
nonThrowingFunction1()
try throwingFunction2()
nonThrowingFunction2()
try throwingFunction3()
} catch {
// handle errors
}

Думаю, когда я буду писать подобные конструкции, понимание такого решения будет более понятным.
Пока мне всё же привычно как это выглядит в Kotlin:

try {
// Code that may throw an exception
} catch (e: SomeException) {
// Code for handling the exception
}

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

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Большая тема впереди

➡️Day 9: Closures, passing functions into functions, and checkpoint 5

В переменной можно хранить функцию:

func greetUser() {
print("Hi there!")
}

greetUser()

var greetCopy = greetUser
greetCopy()

📌 Запишу в #todo list: “изучить как это работает внутри”

Получается мы можем использовать функцию как аргумент для другой функции - это функции первого класса (first-class functions), в современных языках вполне распространённая штука!

Понравилось как авторы Swift задизайнили неявное именование аргументов

let reverseTeam = team.sorted { $0 > $1 }

В Kotlin доступен только один неявный параметр, который называется it. Если понадобится использовать 2 и больше параметра - нужно будет явно написать названия этих параметров.

Эта тема очень важная, т.к. эти знания пригодятся почти в любом проекте 👩‍💻

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
Под недавними постами вы можете оставить комментарий ✏️
Буду рад вашему фидбэку!

Также поддержите меня реакциями — это даст дополнительную мотивацию делиться своим прогрессом в деталях 🙏
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1👀1
Если кто-то проходит этот же курс, или будете рекомендовать его друзьям, не забудьте выделить важность Optional статей, они не содержат видео и небольшие по объему. Несмотря на то, что они подаются как оциональные - материал действительно стоящий внимания.

Отдельно подчеркну, что наличие текста под каждым видео невероятно полезно! Это позволяет воспользоваться поиском, скопировать листинги показанные на видео, или же воспользоваться переводчиком и лучше понять, то о чем рассказывает автор.

#hackingwithswift
👍2
➡️Day 10: Structs, computed properties, and property observers

Это очень круто! Пока мне не понятно в чём существенное отличие struct & class (об этом будет потом). Но подход к mutable/immutable объектам (если они называются объектами, наверное, точнее будет определение экземпляр структуры) домонстрирует совершенно новый для меня подход.

📼 mutating func
В примере автора демонстрируется mutating func и запрет компилятора на вызов такого метода, если переменная объявлена с модификатором let.
Если опустить mutating, компилятор нам укажет, что нельзя модифицировать vacationRemaining, несмотря на то, что переменная содержит модификатор var


struct Employee {
let name: String
var vacationRemaining: Int

mutating func takeVacation(days: Int) {
if vacationRemaining > days {
vacationRemaining -= days
print("I'm going on vacation!")
print("Days remaining: \(vacationRemaining)")
} else {
print("Oops! There aren't enough days remaining.")
}
}
}

let employee = Employee.init(name: "Person", vacationRemaining: 10)
employee.takeVacation(days: 5) // не будет работать, т.к. employee объявлен как let


📼 Вычисляемые поля работают похожим образом как и в Kotlin. Думаю, что это тоже вполне распространённая возможность современных языков, но могу ошибаться!


var vacationRemaining: Int {
get {
vacationAllocated - vacationTaken
}
set {
vacationAllocated = vacationTaken + newValue
}
}


📼 init и self
init это аналог constructor в Kotlin. Позволяет задать явный конструктор с различным набором параметров.
С self тоже всё довольно таки просто - это аналог this в Java & Kotlin. Если название поля совпадает с именем параметра, то self позволит их отличить.

📼 Наблюдатели свойства (property observers)

struct App {
var age: Int = 0 {
willSet {
print("Возраст скоро изменится на \(newValue)")
}
didSet {
print("Возраст изменился с \(oldValue) на \(age)")
}
}
}

Данная вещь позволяет выполнить код перед и после изменения поля. Не припоминаю, чтобы в Kotlin было что-то подобное на уровне языка, но это можно достичь с помощью AOP (Aspect-oriented programming). Пока не уверен, что это что-то полезное, но может при работе с UI это пригодится. Берём на вооружение!

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Очень объемный урок 😰
Похоже следующие меньше не будут…
Please open Telegram to view this post
VIEW IN TELEGRAM
👨‍💻3🔥1
Всем привет, сегодня будет последний день, за который я планирую закончить оставшиеся из 14 уроков 💪

➡️Day 11: Access control, static properties and methods, and checkpoint 6

Модификаторы доступа всегда вызывают у меня смешанные чувства. Я отношусь к ним скептически. Пока у меня складывается ощущение, что мне не придётся писать сложную иерархию классов, а поэтому я буду ограничен только использованием этих модификаторов в библиотечных классах.

Статические поля и методы, они и в Африке статические

➡️Day 12: Classes, inheritance, and checkpoint 7

Изначально я ожидал, что это будет большая тема, но зная что такое struct понимание class существенно упрощается.
В целом классы в Swift очень похожи на классические классы ООП. Тут есть практически всё, что есть в struct, но в дополнение идёт наследование, отсутствие автоматических init методов для полей, и пожалуй самое интересное: объекты передаются по ссылке. Рассмотрим пример:


class User {
var username = “Ivan”
}

let user1 = User()
let user2 = user1

print(user1.username) // Ivan
print(user2.username) // Ivan

user2.username = “Petr”

print(user1.username) // Petr
print(user2.username) // Petr


Несмотря на то, что обе переменные объявлены с помощью let, поля могут быть изменены. Изменение user2.username меняет так же user1.username.
В случае использования struct User, нам нужно будет изменить var user2 = user1, чтобы была возможность изменить поле username. И что самое отличительное тут, это изменение user2.username не влечёт изменение user1.username. Насколько я понимаю, в какой-то момент создаётся копия экземпляра.

Также есть тонкости с тем, когда Swift удаляет ненужные объекты. Но это отдельный топик требующий внимания #todo

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Финишная прямая 🏁🏎

➡️Day 13: Protocols, extensions, and checkpoint 8

Протоколы это что-то вроде интерфейсов в Java/Kotlin. И struct и class могут реализовывать протоколы. В целом, можно использовать как я привык это делать, но до тех пор пока не потребуется что-то делать с типом Self и (или) associatedtype.

Насколько я понял, это тип будущей реализации протокола (как в случае с Self) или же какой-то тип, который будет определён в реализации протокола (как в случае с associatedtype). Выглядит как продвинутые фишки, но полезны они, скорее всего, авторам библиотек. #todo хочется изучить этот концепт более детально!

К слову, в Kotlin это достигается с помощью шаблонов (generics), но возможно есть ключевые отличия. И я жду, когда же в Swift я увижу generics? 🤔
var arr = [[String]]() не в счёт 🤣

Extensions
Так же присутствуют в Kotlin. Возможность добавить новый функционал для уже существующих protocol, struct, class.
Кстати, это и механизм для создания дефолтной реализации метода в протоколе. В Java/Kotlin это можно сделать напрямую в определении интерфейса.

Хоть меня сложно испугать типами, после того как я осилил Higher-Kinded Types в Scala 👩‍💻, Self, associatedtype, type erasure, some, any заставляют извилины пошевелиться вновь 🧠

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
➡️Day 14: Optionals, nil coalescing, and checkpoint 9

Концепция опциональных (nullable) типов давно не нова, изначально это были различные обёртки (очень современно в Java, они там есть до сих пор, называется Optional), потом, если не ошибаюсь, C# ввели синтаксис вида Type?.
На мой взгляд это лаконично и элегантно - отличное решение авторов Swift & Kotlin переиспользовать это 👍

Я нашёл любопытной подход guard, когда мы делаем проверку входящих параметров:

func printSquare(of number: Int?) {
guard let number = number else {
print("Missing input")

// 1: We *must* exit the function here
return
}

// 2: `number` is still available outside of `guard`
print("\(number) x \(number) is \(number * number)")
}

Возможно это ничем не лучше

if let unwrappedNumber = number {
printSquare(of: unwrappedNumber)
}

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

Оператор объединения с nil

Данная конструкция присутствует и в Kotlin, но там она выглядит интереснее - Элвис оператор ?:
Наклоните голову налево и поймете почему он так называется 😋

optional try

Классно! Просто классно!

do {
let result = try runRiskyFunction()
print(result)
} catch {
// it failed!
}

можно переписать как

if let result = try? runRiskyFunction() {
print(result)
}

но так в случае если ошибка совсем не важна.

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Вот и всё! Основы Swift в кармане, и я готов погружаться в SwiftUI 👶

Дальше, скорее всего, будет много кода, и меня немного смущает, как Telegram отображает сниппеты. Например, нет нумерации строк, что не очень удобно.

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

Вот какие варианты я рассматриваю:
🟢Создавать проекты на GitHub 👩‍💻 - но чтение кода через GitHub может быть неудобным по сравнению с Telegram.
🟢Использовать GitHub Gist - это сниппеты кода в GitHub, но как это будет смотреться в Telegram, не уверен.
🟢Использовать страницы в Telegraph - они открываются прямо в Telegram, но пока не понятно, как будет выглядеть форматирование кода.
🟢Продолжить использовать стандартные Telegram-сниппеты - но мне не нравится, как это выглядит с большим количеством кода.
🟢Прикреплять код как изображения - возможно, так будет проще для восприятия, но зумить и искать по ним не получится

Если у кого-то есть идеи по этому вопросу - буду рад, если вы поделитесь! 😇
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🤔1
Нууу.. начинаем 🔢 👶
Первым проектом будет приложения для разделения счёта в кафе/ресторане
Проект состоит из 3х частей, попробую осилить за один день
https://www.hackingwithswift.com/100/swiftui/16

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1👏1
За сегодняшний день я прошёл всё, что запланировал (нужны ли ссылки на уроки?)
🟢Day 16 – Project 1, part one
🟢Day 17 – Project 1, part two
🟢Day 18 – Project 1, part three
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
В конечном итоге у меня получилось приложение такого вида
Это приложение по своей сути является калькулятором, позволяющим разделить определенную сумму и чаевые на указанное количество человек поровну
👍1
WeSplit.png
4 MB
Попробую скинуть код в таком формате. Telegram сохраняет качество, если отправлять как файл
👍1
И ещё продублирую кодом, а вы можете полайкать тот вариант, который больше нравится

import SwiftUI

struct ContentView: View {
@State private var totalAmount: Double = 0.0
@State private var numberOfPeople: Int = 2
@State private var tipPercentage: Int = 15
@FocusState private var isKeyboardFocused: Bool

private var amountPerPerson: Double {
return amountWithTips / Double(numberOfPeople)
}
private var amountWithTips: Double {
return totalAmount * (1 + Double(tipPercentage) / 100.0)
}

var body: some View {
NavigationView {
Form {
Section {
TextField("Amount", value: $totalAmount, format: .currency(code: "USD"))
.keyboardType(.decimalPad)
.focused($isKeyboardFocused)
Picker("Number of people", selection: $numberOfPeople) {
ForEach(2...20, id: \.self) {
Text("\($0) people")
}
}
}
Section("Tips") {
Picker("Tips size", selection: $tipPercentage) {
ForEach(0...100, id: \.self) {
Text($0, format: .percent)
}
}
.pickerStyle(.navigationLink)
}
Section("Amount per persion") {
Text(amountPerPerson, format: .currency(code: "USD"))
}
Section("Total") {
Text(amountWithTips, format: .currency(code: "USD"))
}
}
.navigationTitle("WeSplit")
.toolbar {
if isKeyboardFocused {
Button("Done") {
isKeyboardFocused = false
}
}
}
}
}
}
👍3
Что я узнал за эти уроки?
🟢NavigationView, Form, Section — базовые элементы для построения интерфейса.
🟢Safe Area — SwiftUI по умолчанию ограничивает рабочую область, чтобы интерфейс корректно отображался с вырезами на новых моделях iPhone (чёлка, строка статуса и т. д.).
🟢 Работа кнопок и изменение переменных через них.
🟢 @State - хитрая вещь, позволяет изменять переменные внутри struct
🟢 Привязка View и Model через $ перед именем переменной.
🟢 Ввод пользователя и работа с текстовыми полями.
🟢 Базовые принципы навигации в приложении.
🟢 Вычисляемые свойства.
🟢 @Focus управление видимостью элементов (например, клавиатуры).

Впечатления

Мне нравится подача материала: видео короткие, по делу, с полезными наблюдениями. Автор плавно усложняет темы, показывая новые концепции на основе уже изученных. Есть вещи, которые пока не до конца понятны, но это нормально — SwiftUI невозможно понять за пару уроков. Интересно разобраться, как он устроен под капотом (а может, и не стоит 🤔).

Отдельно отмечу внимание к деталям. Автор объясняет важность доступности (Accessibility), например, почему текстовые поля, даже если они не видны, нужны для экранных озвучивателей, помогающих слабовидящим пользователям.

So far, so good! А как вам
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Попробовал создать “пустое” приложение на Android, по типу “Hello World”. При первом запуске получил такое… Что называется встречают с караваем 🤣🤣
👍2😢1