Просмотра видео, конечно, недостаточно. Нужно скорее изучать следующие темы!
Проект 10 (1/4)
Оставил у меня смешанные чувства: огорчение и восторг.
Я был полон ожидания, что в разделе Focus on data мы начнём с разбора фреймворка базы данных - Core Data. Эта тема действительна интересна для меня, возможно как для backend разработчика. Но мы начали с
🟢 http запросов.
В сравнение с Java/Kotlin - просто вау! Встроенные механизмы, которые для базовых кейсов не требуют почти никаких усилий. Когда разработчики постарались🙂
Насколько мне удалось нагуглить, для любителей перекладывать байтики, инструменты в виде IntputStream/OutputStream имеются😎
🟢 Асинхронная загрузка изображений. Тут дело сложнее чем с обычными картинками, т.к. SwiftUI заранее не знает, какими атрибутами обладает загружаемая картинка. Но мы можем подсказать.
🟢 Disabling Forms. Это совсем не то, что можно ожидать в разделе Focus on Data 🫠
В форме можно указать boolean выражение на секции, которое заблокирует или разрешит взаимодействие с этой секцией.
#hackingwithswift
Проект 10 (1/4)
Оставил у меня смешанные чувства: огорчение и восторг.
Я был полон ожидания, что в разделе Focus on data мы начнём с разбора фреймворка базы данных - Core Data. Эта тема действительна интересна для меня, возможно как для backend разработчика. Но мы начали с
let url = URL(string: "https://itunes.apple.com/search?term=taylor+swift&entity=song")
let (data, _) = try await URLSession.shared.data(from: url)
В сравнение с Java/Kotlin - просто вау! Встроенные механизмы, которые для базовых кейсов не требуют почти никаких усилий. Когда разработчики постарались
Насколько мне удалось нагуглить, для любителей перекладывать байтики, инструменты в виде IntputStream/OutputStream имеются
Section {
Button("Create account") {
print("Creating account…")
}
}
.disabled(username.isEmpty || email.isEmpty)
В форме можно указать boolean выражение на секции, которое заблокирует или разрешит взаимодействие с этой секцией.
#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
Чем дальше, тем больше хочу погрузиться в мир мобильной разработки! 💪
Please open Telegram to view this post
VIEW IN TELEGRAM
🆒2
Антиреклама Xcode
Ожидается, что на симуляторе и превью будет одинаковый контент. Куда пропали остальные секции Пол тоже не знает…😄
Ожидается, что на симуляторе и превью будет одинаковый контент. Куда пропали остальные секции Пол тоже не знает…
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1😱1 1
Недавно я хвалил разработчиков за URLSession, но сегодня случай другой.
Допустим, нам нужно создать JSON, но при этом заменить имена полей на кастомные. В
Это выглядит громоздко, и если мы посмотрим на class + Observable, то поля с подчёркиванием ещё больше усложняют восприятие
В
Допустим, нам нужно создать JSON, но при этом заменить имена полей на кастомные. В
Swift
для этого используется специальный enum CodingKeys: String, CodingKey
:
struct Landmark: Codable {
var name: String
var foundingYear: Int
var location: Coordinate
var vantagePoints: [Coordinate]
enum CodingKeys: String, CodingKey {
case name = "title"
case foundingYear = "founding_date"
case location
case vantagePoints
}
}
Это выглядит громоздко, и если мы посмотрим на class + Observable, то поля с подчёркиванием ещё больше усложняют восприятие
@Observable
class User: Codable {
enum CodingKeys: String, CodingKey {
case _name = "name"
}
var name = "Taylor"
}
В
Kotlin
это делается существенно лаконичнее:
import com.fasterxml.jackson.annotation.JsonProperty
data class Landmark(
@JsonProperty("title") val name: String,
@JsonProperty("founding_date") val foundingYear: Int,
val location: Coordinate,
val vantagePoints: List<Coordinate>
)
@JsonProperty
является аннотацией, которая доступна в рантайм, являющаяся по сути мета информацией к типу Landmark. Библиотека fasterxml использует её при сериализации.👍1
Для
Swift
есть решение похожее на fasterxml
- https://github.com/GottaGetSwifty/CodableWrappers
@CustomCodable @SnakeCase
struct User: Codable {
let firstName: String
let lastName: String
@SecondsSince1970DateCoding
var joinDate: Date
@CustomCodingKey("data")
var imageData: Data
}
👍1
Проект 10
Закончен.
Повторюсь, мне он показался странным. Не то, что я ожидал увидеть.
Я так и не понял зачем был урок про haptic effects - тактильные ощущения, которые создаются с помощью вибрации телефона, причем только на телефоне эта функциональность доступна. В проекте мы это не применяли.
Проект был про приложение для заказа кексиков.
По функционалу состоит из формы и её валидации, асинхронной загрузки картинки, нескольких экранов и отправки http запросов с json на сервер.
Едем дальше🚗
Закончен.
Повторюсь, мне он показался странным. Не то, что я ожидал увидеть.
Я так и не понял зачем был урок про haptic effects - тактильные ощущения, которые создаются с помощью вибрации телефона, причем только на телефоне эта функциональность доступна. В проекте мы это не применяли.
Проект был про приложение для заказа кексиков.
По функционалу состоит из формы и её валидации, асинхронной загрузки картинки, нескольких экранов и отправки http запросов с json на сервер.
Едем дальше
Please open Telegram to view this post
VIEW IN TELEGRAM
Прохожу Проект 11, и там, наконец-то, то, чего я ждал - работа с данными. Думаю, завтра завершу и напишу пост об этом.
⚡1👏1
Это, как говорится, ни в какие ворота не лезет. Я потратил ❗️ 15 минут ❗️ на поиск простой опечатки (параметр называется configurations).
Бесполезный linter…😤
Бесполезный linter…
Please open Telegram to view this post
VIEW IN TELEGRAM
😢1
А теперь вопрос к SwiftUI.
Почему нет конструктора для ClosedRange, но есть для Range? Забыли посахарить? 😄
На первый взгляд ClosedRange является подтипом Range. Но первое впечатление обманчиво, видимо нужно погружаться в теорию типов.
Фиксится через добавление id
В этом случае тип становится
Почему нет конструктора для ClosedRange, но есть для Range? Забыли посахарить? 😄
На первый взгляд ClosedRange является подтипом Range. Но первое впечатление обманчиво, видимо нужно погружаться в теорию типов.
Фиксится через добавление id
ForEach(1...maxRating, id: \.self)
В этом случае тип становится
Data
public init(_ data: Data, id: KeyPath<Data.Element, ID>, @ViewBuilder content: @escaping (Data.Element) -> Content)
🤔1
Проект 11
Этот проект оказался самым полезным, поскольку его функционал сильно пересекается с тем, что я планирую реализовать в своём приложении.
Основные темы:
🟢
🟢
🟢 SwiftData - новый механизм для персистентного хранения данных в iOS, аналогичный
🟢 Кастомные View, которые можно комбинировать и использовать в других View. Это помогает создавать переиспользуемые компоненты, улучшая читаемость и структуру кода.
🟢
Кстати, когда я пытался сделать приложение с помощью ChatGPT, он почему-то предложил использовать CoreData, и про SwiftData ничего не сказал. Хотя последнее идеально подходит для моей задачи.
hackingwithswift.com отличный курс, который уже научил меня многому.
#hackingwithswift
Этот проект оказался самым полезным, поскольку его функционал сильно пересекается с тем, что я планирую реализовать в своём приложении.
Основные темы:
@Binding
- позволяет изменять значение, переданное извне. Используем, когда нужно передать тип данных из View 1 в View 2, и при этом View 2 может модифицировать переданное значение. Это полезно для двусторонней связи между представлением и моделью.TextEditor
- многострочная версия TextField
. Подходит для ввода текста, который может “расти” в высоту или ширину в зависимости от содержимого. Очень удобен для реализации многострочных полей ввода.CoreData
, но более абстрактный и с упрощённым интерфейсом. Несмотря на скромные возможности по сравнению с CoreData, SwiftData легче в освоении и значительно проще в использовании для базовых задач. Это именно то, что мне нужно для быстрого старта.@Query
- позволяет фильтровать и сортировать данные, хранимые в SwiftData, без необходимости писать сложные запросы вручную. Это упрощает работу с данными и позволяет быстрее получить нужную информацию.Кстати, когда я пытался сделать приложение с помощью ChatGPT, он почему-то предложил использовать CoreData, и про SwiftData ничего не сказал. Хотя последнее идеально подходит для моей задачи.
hackingwithswift.com отличный курс, который уже научил меня многому.
#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1👏1💯1
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1👏1
Попробовал посмотреть другие ресурсы для изучения Swift. Вроде выглядит неплохо - codecademy
Проходил модуль про enum: https://www.codecademy.com/courses/learn-swift-enumerations/lessons/swift-enumerations-lesson/exercises/introducing-enumerations
Вроде как сам урок бесплатный, но тест и проект (тут нужно без примеров по инструкции реализовывать функционал) уже платные.
Из полезного: увидел как делается и попробовал на практике
🟢 RawValue - можно каждому enum сопоставить какое-то значение. Тут можно и String сделать.
🟢 CaseIterable - чтобы проитерироваться по всем значениям
🟢 Ассоциированные значения - каждый enum может содержать свою переменную (наверное, несколько тоже можно)
🟢 Мутирующие методы
Попробую ещё несколько модулей, расскажу по мере прохождения. Но пока курс hackingwithswift в приоритете, и я планирую пройти его до конца.
А кто-то уже пользовался codecademy, можете поделиться своим опытом?
Проходил модуль про enum: https://www.codecademy.com/courses/learn-swift-enumerations/lessons/swift-enumerations-lesson/exercises/introducing-enumerations
Вроде как сам урок бесплатный, но тест и проект (тут нужно без примеров по инструкции реализовывать функционал) уже платные.
Из полезного: увидел как делается и попробовал на практике
enum Team: Int {
case alpha = 1
case bravo
case charlie
case delta
}
print(Team.delta.rawValue) // вывод: 4
let team = Team(rawValue: 3) // создаст .charlie
enum Season: CaseIterable {
case winter
case spring
case summer
case fall
}
// потом можно так
for season in Season.allCases {
print(season)
}
enum Dessert {
case cake(flavor: String)
case vanillaIceCream(scoops: Int)
case brownie
}
let tonightsSpecial = Dessert.vanillaIceCream(scoops: 4)
switch tonightsSpecial {
case let .cake(cakeFlavor):
print("Time for \(cakeFlavor) cake")
case let .vanillaIceCream(scoopCount):
print("\(scoopCount) scoops of vanilla ice cream")
case .brownie:
print("Decadent goodness")
}
// Вывод: 4 scoops of vanilla ice cream
enum Season {
case winter, spring, summer, fall
mutating func changeSeason() {
switch self {
case .winter:
self = .spring
case .spring:
self = .summer
case .summer:
self = .fall
case .fall:
self = .winter
}
}
}
Попробую ещё несколько модулей, расскажу по мере прохождения. Но пока курс hackingwithswift в приоритете, и я планирую пройти его до конца.
А кто-то уже пользовался codecademy, можете поделиться своим опытом?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1🤔1👀1
Проект 12: дни 57-59
Это был технический проект направленный на чуть большее понимание деталей работы с SwiftData.
🟢 Чтобы SwiftData заработал, достаточно:
1. Создать модель в виде класса и добавить
2. Заинжектить
3. Во View получить доступ к
Всё действительно просто😍
🟢 Для
🟢 Показана фильтрация в 😮
🟢
🟢 🔍
Забавно, что у SwiftData есть свой значок📦
#hackingwithswift
Это был технический проект направленный на чуть большее понимание деталей работы с SwiftData.
1. Создать модель в виде класса и добавить
@Model
макрос.2. Заинжектить
modelContainer
для этого класса.3. Во View получить доступ к
modelContext
через @Environment(\.modelContext) var modelContext
Всё действительно просто
#Preview
можно сделать свой modelContainer
, который будет храниться в памяти. Выглядит это немного громоздко, но явно есть инструменты позволяющие сократить код. Удивлюсь если их нет, preview весьма полезный инструмент, и используется часто.@Query
- как же ужасно это выглядит! Особенно, если развернуть макрос. Почему там нельзя использовать обычную лямбду/замыкание? SwiftData
умеет неявно делать связи между моделями. Мы можем просто объявить новое поле, тип которого другая модель (или даже список/массив). Каскадное удаление также присутствует, но тут уже нужно добавить макрос как в этом примере: @Relationship(deleteRule: .cascade) var jobs = [Job]()
CloudKit
- пока загадочный для меня фреймворх для хранения там данных приложения. Классно, что SwiftData
может с ним синхронизироваться, позволяя также синхронизировать данные между девайсами. Но, почитав документация, я понимаю, что он предназначен для публичных данных, а iCloud для приватных. Я могу сказать, что всё что на моём телефоне и связано со мной - приватное! Какой у этого реальный юзкейс ещё предстоит выяснить Забавно, что у SwiftData есть свой значок
#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1👏1
В дополнение к пункту про фильтрацию в
Посмотрите сами… этот код не является валидным
@Query
Посмотрите сами… этот код не является валидным
@Query(filter: #Predicate<User> { user in
if user.name.localizedStandardContains("R") {
if user.city == "London" {
return true
}
}
return false
}, sort: \User.name) var users: [User]
Please open Telegram to view this post
VIEW IN TELEGRAM
Продолжаю эксперименты с ChatGPT - что называется, ожидание vs. реальность 😄
Но в целом, результат неплохой!
Я тем временем присматриваюсь к различным дизайнам, внимание уделяю больше функциональности, а не красоте.
Кстати, заметил, что стал иначе воспринимать приложения, которыми пользуюсь ежедневно. Теперь обращаю внимание на детали интерфейса: что удобно, а что нет, как реализованы те или иные элементы. Такой новый взгляд помогает лучше понимать, какие решения стоит взять на заметку, а что нужно избегать.
Но в целом, результат неплохой!
Я тем временем присматриваюсь к различным дизайнам, внимание уделяю больше функциональности, а не красоте.
Кстати, заметил, что стал иначе воспринимать приложения, которыми пользуюсь ежедневно. Теперь обращаю внимание на детали интерфейса: что удобно, а что нет, как реализованы те или иные элементы. Такой новый взгляд помогает лучше понимать, какие решения стоит взять на заметку, а что нужно избегать.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
День 60
Сегодняшний челлендж:
✅ Загрузить JSON, содержащий массив объектов с информацией о людях и списком их друзей.
✅ Отобразить список людей.
✅ При выборе конкретного человека показать его подробную информацию.
#hackingwithswift
Сегодняшний челлендж:
#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
JSON можно посмотреть тут: https://www.hackingwithswift.com/samples/friendface.json
Это задание я сделал практически самостоятельно. Единственное исключение - поиск примеров некоторых конструкций в официальной документации и, конечно, на всеми любимом Stack Overflow.
Этот трюк с настройкой тулбара как раз нашел там👩💻
Кстати, официальная документация Apple организована действительно хорошо: удобная навигация, детальные описания, кросс-ссылки на связанные элементы и, главное, примеры. Правда, не все из них оказываются полезными. Например, настройка декодера там не отражена:
Хотя, если подумать, это instance property, так что логично, что его нужно просто присвоить. Просто это выбивается из уже привычного синтаксиса, когда мы вызываем метод и конфигурируем всё через параметры.
https://developer.apple.com/documentation/foundation/jsondecoder/2895216-datedecodingstrategy
Это задание я сделал практически самостоятельно. Единственное исключение - поиск примеров некоторых конструкций в официальной документации и, конечно, на всеми любимом Stack Overflow.
.toolbar {
ToolbarItem(placement: .principal) {
HStack {
Image(systemName: user.isActive ? "person.fill.checkmark.rtl" : "person.fill.xmark.rtl")
Text(user.name).font(.headline)
}
}
}
Этот трюк с настройкой тулбара как раз нашел там
Кстати, официальная документация Apple организована действительно хорошо: удобная навигация, детальные описания, кросс-ссылки на связанные элементы и, главное, примеры. Правда, не все из них оказываются полезными. Например, настройка декодера там не отражена:
decoder.dateDecodingStrategy = .iso8601
Хотя, если подумать, это instance property, так что логично, что его нужно просто присвоить. Просто это выбивается из уже привычного синтаксиса, когда мы вызываем метод и конфигурируем всё через параметры.
https://developer.apple.com/documentation/foundation/jsondecoder/2895216-datedecodingstrategy
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2