Стендап Сьогодні
📢 Канал в Telegram @stendap_sogodni
🦣 @stendap_sogodni@shevtsov.me в Федиверсі

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

Пости з тегом #Ping

02.01.2025

Мій власний Steam Replay, або в що я грав у 2024 році

Як я обіцяв собі зробити звіт на кшталт Steam Replay, так і зробив. Причому навіть як функціональність застосунку, тобто можна такий саме звіт зібрати з будь-чого. Обираєш тег-“всесвіт” (бо якщо не обмежувати вибірку, то вийде повна каша) - тут це тег gaming. А потім набір тегів-категорій - з тих, що з ним перетинаються. Отримуєш ось такий цікавий графік.

…Насправді зі звітом все складніше. Те, що ви бачите — це я, після першого поганого досвіду, обрав топ-10 ігор. Бо там ще купа дрібних записів на 1-2 години, які вже перетворюють графік на шум. В кольорах розібратися неможливо. (Гадаю, треба відразу автоматично залишати на графіку топ-10.)

Технічно цей функціонал включав купу рефакторингу коду деревної мапи — бо там сидить обчислення “покривної” статистики. А ще форми пінга — бо там є UI вибору тегів. В цілому у Swift це приємно робиться, але: він любить кидатися помилкою про “не можу розібратися в типах”, та далі ми залишаємося на самоті: або розпилюй на менші функції — без допомоги IDE, або шукай помилку — теж наосліп. Вихід примітивний: коментую шматки коду, поки не скомпілюється; тоді поламане місце десь в коментарях.

…А тепер, до результатів. BG3 я так і не пройшов; досяг level cap та стало якось не цікаво. Сталкер здивував; але його поки теж закинув. Evil Within 2 - нудьгуватий, але компетентний. Hades - екшн-Roguelike з безліччю цікавих комбінацій. Echo Night Beyond на PS2 - гра випередила час, вигадлива, але логічна адвенчура від першого лиця. Ashes of the Apocalypse - вже писав, бумер-шутер з мистецьки зробленим світом.

Dread Delusion - не закінчив, але все ще планую, це як King’s Field з відкритим світом. Morrowind - цього року досліджував Tamriel Rebuilt. Rule of Rose - ще одна гра на PS2, SIlent Hill 2-like в цікавому сетінгу. Cyberpunk 2077 - а ви знаєте, що з виходом доповнення вони повністю переробили всю рольову систему та лут? Я таке вперше бачу.

Нагадаю, що вся ця статистика зібрана моїм стохастичним таймтрекером, який ось-ось можна буде завантажити в TestFlight… як тільки відділ підтримки Apple виспиться.


21.04.2025

Резервне копіювання для Ping

Три місяці тому писав про резервне копіювання даних мого стохастичного таймтрекера Ping. Але нарешті тільки сьогодні вивів його в бету.

На жаль, забув випустити раніше. Але ось що допомогло. Моя власна копія почала зависати на запуску. В XCode дуже легко зрозуміти. що зависає — достатньо поставити застосунок на паузу. Тому коли дістався до XCode, то відразу побачив, що висне — не сама резервна копія — а її завантаження до iCloud, метод setUbiquitous.

Як мені здається, проблема була в тому, що моя альфа-версія робила копію на кожний запуск, та їх накопичилося дві з гаком тисячі в одній директорії в iCloud. Як мені здається, така кількість файлів уповільнює роботу iCloud. Бо більше нічого не змінювалося, а сам файл розміром лише 300 Кб.

Так що довелося закінчити фічу — робити копіювання раз на день, додати вимикач та допомогу. Завдяки використанню @globalActor виніс роботу з головного потоку. Тут у Swift цікаво: async/await роблять код рівночасним, але залишають виконання в головному потоці (тобто гальмують інтерфейс застосунку.) Щоб зробити код ще й паралельним, потрібно винести його в актора.

Також зазначу. що бета-версії застосунків в Apple TestFlight згоряють за 90 днів. Тобто кожні 90 днів потрібно викладати нову версію, щоб бета-користувачі не втратили доступ. Та в мене сьогодні минуло 79! Радий, що через цю ситуацію встиг згадати та скоригувати курс.


30.04.2025

SwiftUI - рефакторинг та оточення

Сьогодні додав маленьку фічу до свого стохастичного таймтрекера — а саме, можливість передивитися всі пінги, які відмічені конкретним тегом. Що корисно, щоб згадати минуле. Щоправда, я досі не зробив перегляду більше за 50 пінгів, бо для того потрібне ліниве завантаження — тож не дуже далеке минуле.

Фіча звучить зовсім простою. Запит для останніх пінгів вже є. Додаєш до нього фільтр по тегу (до речі, із CTE) та виводиш списком. Але є й проблема.

Натискання на пінг відкриває форму редагування. Така можливість, звісно, потрібна й на новому списку. Ця форма не така проста річ — бо вона є модальним вікном, та на екрані ніколи не повинно бути двох форм. Тому її стан є глобальним.

Цей стан в мене поки зберігався просто в @State var formModel на структурі застосунку, та передавався глибше через @Binding. Цього разу я прикинув, через скільки шарів доведеться прокинути @Binding та вирішив, нарешті, переробити.

У SwiftUI є можливість, схожа на контексти в React - це Оточення, @Environment. Нею можна передати вглиб структури презентації якесь значення. Але — саме значення, не змінну, редагувати його не можна.

Або… можна? Спочатку я спробував передавати функцію-сетер, setFormModel. Це спрацювало! Далі пошукав більш ідіоматичне рішення та знайшов, що взагалі-то в @Environment можна передати Binding(FormModel), та тоді його можна буде призначати через formModel.wrappedValue = newFormModel.

(Binding, який лежить в основі моделі стану SwiftUI, як раз і є абстракцією над гетером та сетером, яка загортає змінне значення у незмінну обгортку.)

Код став гнучкіше та чистіше. До речі, в останньому SwiftUI цей @Environment значно спростили, так що якщо давно не бачили — подивіться.

🕜🏷️ Нагадаю, що я пишу Ping - застосунок на iOS для нетрадиційного обліку часу. Якщо цікаво, до бети можна доєднатися тут.