Kotlin/Swift (iOS) Туда и Обратно
36 subscribers
127 photos
21 videos
9 files
84 links
Канал - журнал, рассказывающий об опыте изучения Swift & iOS backend-разработчиком на Java & Kotlin
Download Telegram
Проект 16 (день 81)

Поскольку уроки небольшие, прохожу несколько за раз.
День 81 предлагает следующие темы:

🟢 Можно добавить кастомные свайп-кнопки на элементы списка

List {
Text("Taylor Swift")
.swipeActions {
Button("Delete", systemImage: "minus.circle", role: .destructive) {
print("Deleting")
}
}
.swipeActions(edge: .leading) {
Button("Pin", systemImage: "pin") {
print("Pinning")
}
.tint(.orange)
}
}


🟢 Нотификации. Фреймворк, насколько я понял, используется, скажем, не новый 😆

Запрашиваем права

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
if success {
print(“Всё ок!”)
} else if let error {
print(error.localizedDescription)
}
}


Делаем отправку

let content = UNMutableNotificationContent()
content.title = “Накорми кота”
content.subtitle = “Он “голодный
content.sound = UNNotificationSound.default

// показать нотификацию через 5 секунд
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)

// выбираем рандомный ид
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)

UNUserNotificationCenter.current().add(request)


🟢 Подключение проектов как зависимости. Выглядит, на самом деле, как git submodule. Что тут ещё написать…?

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1😁1
Пример git submodule: https://github.com/robocorp/example-use-git-submodule-for-shared-code

Выглядит это как отдельная папка с указанием хэша коммита 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Проект 16 (день 82)

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

🟢 Создали 4 основных таба, отражающих списки людей: все, с кем познакомились, с кем предстоит встретиться и информация о себе.
Для первых 3 табов используем одну и ту же View. Определяем тип с помощью перечисления:


enum FilterType {
case none, contacted, uncontacted
}


🟢 Добавили SwiftData, для этого подготовили такую модель


@Model
class Prospect {
var name: String
var emailAddress: String
var isContacted: Bool

init(name: String, emailAddress: String, isContacted: Bool) {
self.name = name
self.emailAddress = emailAddress
self.isContacted = isContacted
}
}


🟢Добавили динамическую фильтрацию в зависимости от FilterType при инициализации View:


init(filter: FilterType) {
self.filter = filter

if filter != .none {
let showContactedOnly = filter == .contacted

_prospects = Query(filter: #Predicate {
$0.isContacted == showContactedOnly
}, sort: [SortDescriptor(\Prospect.name)])
}
}


#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Применяю полученные навыки для самообучения!
Не todo-list же делать 😀
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21
Проект 16 (день 83)

Сегодня мы разбирались:

🟢 Как генерировать QR код
Для генерации использовали CIFilter.qrCodeGenerator(). Даже не подозревал, что настолько просто это можно сделать.
Тут пригодилась интерполяция, т.к. она включена по-умолчанию и изображение при масштабировании становится “мыльным”. Скину скрины для сравнения.

🟢 Как сканировать QR код
Для чтения использовали код автора (думаю, что это как раз тот код, упоминаемый тут https://t.me/kotlin2swift/86, по крайней мере называется он именно так).

🟢 Добавили возможность удаления записей с помощью свайпа.

Ниже приложу скриншоты 📸

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
1 - интерполяция
2, 3 - кнопки для разного типа записей
4 - множественное редактирование
👍2🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Небольшой прогресс с приложением DerDieDas
Добавил сюда отображение правильного артикля.

Правда у меня есть ощущение, что анимация отрабатывает не одинаково для обоих слов 🤔

Чтобы подебажить это, я увеличил duration анимации, но в замедленном варианте это ощущение пропадает.
Это обман зрения? И если да, то как его исправить, помимо отключения анимации 🤣
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Проект 16 (день 84)

Две темы сегодня:

➡️ Контекстное меню на изображении - добавили кнопку “пошарить” QR код. Делается это довольно таки просто, что называется one-liner:


Image(uiImage: qrCode)
.interpolation(.none)
.resizable()
.scaledToFit()
.frame(width: 200, height: 200)
.contextMenu {
ShareLink(item: Image(uiImage: qrCode), preview: SharePreview("My QR Code", image: Image(uiImage: qrCode)))
}


Но тут мы столкнулись с чем-то новым: изменение UI во время изменения UI❗️
qrCode переменная - это @State, и код ниже вызывается при отрисовки UI. Присвоение qrCode нового значения меняет состояние, тогда это событие должно порождать новую итерацию перерисовки.


if let outputImage = filter.outputImage {
if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
qrCode = UIImage(cgImage: cgImage)
return qrCode
}
}


➡️ Нотификации: проверка настроек нотификаций и добавление кнопки, чтобы мы получили нотификацию о конкретном человеке из нашего списка.

#hackingwithswift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Функционал кнопки “пошарить”
🔥3
Кнопка уведомления и как оно выглядит на экране блокировки
🔥3
Это как Xcode уведомляет нас, о том, что мы делаем что-то не то. Происходит когда мы делаем “изменение UI во время изменения UI”.
Интересный цвет они подобрали 😀
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Проект 16 завершён, по итогу получилось такое приложение!

Сделал задания челенжа:

🟢 Добавить иконку на Everyone таб, который будет отражать добавлен ли он в Contacted или нет
🟢 Возможность редактировать записи - имя и емейл
🟢 Сортировка по имени или емейлу - оказалось самое сложное, т.к. SwiftData Query не реагирует на изменения сортировки. Получилось решить это следую подсказке из https://www.hackingwithswift.com/quick-start/swiftdata/how-to-dynamically-change-a-querys-sort-order-or-predicate где предлагается вынесение списка в отдельную View, и передачу сортировки туда как параметр


var body: some View {
NavigationStack {
ProspectListView(filter: filter, sort: sortOrder)
.navigationTitle(title)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Menu("Sort", systemImage: "arrow.up.arrow.down") {
Picker("Sort", selection: $sortOrder) {
Text("Sort by Name")
.tag(SortDescriptor(\Prospect.name))
Text("Sort by email")
.tag(SortDescriptor(\Prospect.emailAddress))
}
}
}
}
}
}


Причем я обратил внимание, что при изменении сортировки SwiftUI пересоздаёт ProspectListView, но если я редактирую какую-нибудь запись - пересоздания нет, причем запись ставится на правильную позицию в списке, и он остаётся правильно отсортированным.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
HotProspects-test.png
689.3 KB
Тест сдал на отлично 🥳
Попробовать можно тут https://www.hackingwithswift.com/review/ios-swiftui/hot-prospects
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3🆒2💯1