iOS Makes Me Hate
3.94K subscribers
1.16K photos
167 videos
15 files
1.33K links
Авторский канал про iOS разработку. Путь продуктовых самураев в MAANG.

Самое больше iOS сообщество практиков: https://boosty.to/lionbond/

Автор: @lvbond Senior iOS Yandex, ex-Avito, VK
Download Telegram
Ну че, в связи с быстроменяющийся обстановкой в мире, давайте выясним кто после выпилов из сторов и сокращений остается лучшей компанией для работы и развития иос-разрабом?

(опрос на основе последних открытых вакансий)
Anonymous Poll
16%
Альфа-банк
24%
Авито
3%
Билайн
11%
ВК
18%
Вайлберис
5%
МТС
7%
Магнит
26%
Озон
11%
Сбер
39%
Яндекс
2
📺 Swift Concurrency: В каком порядке смотреть WWDC

Проблема всех телеграм каналов, блогов, твитторов — отсутствие системы. Чаще это посты, которые по рефлексу или по реакциям пишут интересные им темы, пересказывают чужие посты, реагируют на новости первыми ради репостов. Это хорошо работает как медиа, но не работает как источник обучения.

В такой методике легко получить клиповое мышление и отрафировать скилл композиции материала. Где старт и где финал особо не поймешь в ленте постов. Вся усвоенная инфа становится калейдоскопом рандомных фактов. Моя же цель делать изучение структурным и понятным (прям как Structured Concurrency 🤤). Последовательным. С понятным началом и концом...

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

Продолжаем погружаться системно в изучение Swift Concurrency. В прошлом посте мы поняли какие proposals нам читать, а теперь идем в сторону WWDC. Че же надо посмотреть и в каком порядке?

1️⃣ Фаза 1: Hello, Swift Concurrency

Meet async/await in Swift. Самый первый видос про эпоху SC. Тут вкратце рассказывают про проблемы кода на GCD и как async/await помогает избежать забытые completion (кстати, забытыми completion в guard часто подлавливают на собесах)

Explore structured concurrency in Swift. Тут можно хорошо понять почему и для чего вообще вся эта движуха. Мне больше нравится не попсовая формулировка "это просто лучше читать", а что "теперь мы лучше знаем время жизни потока управления, памяти функций и переменных". Звучит осознанней и практичней.

Protect mutable state with Swift actors. Ну тут нам конкретно помогают понять проблемы Data Race на примере всем известного Counter'а, ImageLoader'а. Вы ищите хорошие формулировки для чего же нам акторы, изоляции, Actror Reentrancy, Main Actor.

В отдельных постах пройдемся по практическим точкам каждых секций.
Please open Telegram to view this post
VIEW IN TELEGRAM
273
Дисциплина не помогает

Еще в догонку темы системы и плана.

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

Когда я был ментором много раз слышал истории в стиле «да я бы мог мир перевернуть, если бы захотел и был дисциплинирован». На такую наивность я и сам попадал, когда думал, что достаточно только 5 тренировок в неделю и я стану мистером Олимпия. И знаете что? Даже с 5 тренировками в неделю я толком никуда не продвинулся.

Дисциплина это только один вспомогательный навык из многих, которые помогают пройти весь путь и дистанцию.

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

У всего должна быть четкая и яркая система, методика и нормативы. А также внутренняя любовь к тому, что делаешь.

https://youtu.be/OPJJDsBYxRk?si=L_HoBn_W0EKKKRP0
118
How to measure productivity part 2

Время перфоманс ревью и начало следующего полугодия. Тут есть отличный шанс понять что улучшить за прошлый период и начать планировать следующий.

Мы уже обсуждали очень важную статью про output’ы и outcome’ы. Но правила перфоманс ревью каждую калибровку меняются. Они не стоят на месте.

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

Это очень важно. Помню как в одной компании ребята внедряли KMP и у них вроде было много работы, но ауткамов не было. В итоге их работы чуть ли не приняли за вредную и не поставили «ниже ожиданий». Поэтому нужно понимать ясно туда ли вы гребете.

Я тоже начал планировать следующие полгода. Идей очень много, но фильтровать их помогают разные метрики. Вот интересные статьи:

🌟Как измерять качество. Очень важная статья про метрики качества. Автор статьи говорит про повышения тимлидам и сеньорам благодаря им:)

🌟Результаты 25000 перфоманс ревью. Интересные наблюдения и выводы на основе многих данных.

🌟Perfomance review в Microsoft. Интересный опыт про эксперименты с перфоманс ревью в майкрософт
Please open Telegram to view this post
VIEW IN TELEGRAM
7
Типичные списки 75 задач из Литкода

Нашел в сети пост про список интересных задач.

В интернетах есть куча разных списков задач, которые все ОБЯЗАНЫ прорешать перед тем как идти на интервью. Опять же, решать наугад задачи — не иметь структуры и плана, а значит терять время. Think about it 😏

Самые известные из них:

Top Interview 150
Blind 75
LeetCode 75
NeetCode 150

Эти списки охватывают основную часть паттернов, алгоритмов и структур данных необходимых для алгособесов. Считается, что начинать с этих задач — правильная стратегия.

Задачи из списков выше — хорошая база. Можно хорошо их миксовать с курсами и теорией.
Please open Telegram to view this post
VIEW IN TELEGRAM
155
Делюсь небольшим спойлером замеров лайаута с доклада Паши НеДурова про его оптимизацию проекта. Мы там не просто разобрали тему хитчей, мейнтреда, герцовка и render server, а прям детально прошлись по практическим инструментам.

Много жирного контекта по PinLayout, Texture, AutoLayout, голыми фреймами и другое. Такое вы нигде не увидите.

Релиз на днях.
208
📺 Асинхронный Layout: AsyncDisplayKit

Решил перед выпусками наваливать ЛОРа за темы, которые будем обсуждать. Так и весь контекст обсуждений можно понять, и экспозицию доклада сделать шире.

Не секрет, что мессенджеры — это отдельный вид приложений, не похожий ни на что. Модные SwiftUI, SC или CMP туда не запихнешь, тк он требует высокой производительности от очень старых устройств и версий. Здесь нужно уходить глубже, чем документации смузи штук. Обсуждать все сложности можно часами.

Поговорим про забытую многими технологию. Но оставившую свой след в индустрии.

Либа, AsyncDisplayKit aka Texture, знакома многими по исходникам телеграма. Много боли она принесла с конкурсами, когда нужно работать с исходной кодовой базой. Такие конкурсы на понимание и чтение исходников телеграма имели повышенную сложность. Именно в таком участвовал наш гость Паша.

В чем ее плюсы?

1️⃣ Асинхронный рендеринг — Рендеринг и layout происходят в фоновом потоке (да да), что уменьшает нагрузку на мейнтред. Вы думаете почему телеграм такой быстрый? Ну, потому что он эффективно работает с лайаутом.

Фейсбук* (запрещенная организация в РФ) создавала его для приложений с большим количеством контента (Pinterest, Facebook Paper).

2️⃣ Декларативный стиль через ASLayoutSpec еще до SwiftUI

3️⃣ Прерасчет лайаута до отображения.

В чем же минусы?

1️⃣ Сложность. Если вы где либо видите сложность — это плохой дизайн. Будь это текста авторов в телеграме, книги, кино, все что угодно. А уж тем более software engineering. Закон жанра: то, что остается сложным — умрет.

Асинхронный лайаут, при его очевидных плюсов на бумаге, стал мертворожденной идеей. Сами разрабы телеграма говорят, что было ошибкой затаскивать AsyncDisplayKit. А разрабы этой библиотеки давно отказались от поддержки в пользу своих более простых внутренних библиотек.

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

Полезные ссылки:
- Using AsyncDisplayKit to Develop Responsive UIs in iOS
- Build Timeline View with AsyncDisplayKit

1/3
Please open Telegram to view this post
VIEW IN TELEGRAM
1153
Асинхронный рендеринг в AsyncDisplayKit

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

Асинхронный рендеринг — это когда drawRect, генерация изображений и т.д. не происходят на мейнтреде, а выносится в фон. Это позволяет избежать всяких фризов при сложном лайауте. Но как этого добивается сама либа?

Давайте по порядку. Условно, это полная замена UIKit'а. Где мы работаем с CALayer'ом не через вью (UIView), а нодами (ASDisplayNode). Они умеют: рассчитывать размер, рисовать свой контент и всё это в фоновом потоке. В отличие от UIKit лайаут считается заранее, а не на главном потоке.

Если кратко то как это работает:
1. Каждая нода отмечается флагом
2. С помощью ASDisplayQueue планируется очередь расчета лайаута или изображений с помощью CGContext
3. Дальше вызывается функция displayBlock, которая уже весь готовый контекст передает на главный поток.
4. node.contents безопасно обновляет UI

Примерная схема:

setNeedsDisplay() →
_setNeedsDisplay() →
_scheduleDisplay() →
displayNode:asynchronously:YES →
dispatch_async(displayQueue) {
image = displayBlock()
dispatch_async(main) {
node.contents = image.CGImage
}
}


Или по этапам:
- calculateLayoutThatFits — Оптимизирует лайаут в фоне до появления на экране
- displayBlock — генерация вьюх и изображения в CGContext
- layer.contents — обновления готового и расчитанного контента на главном потоке

2/3
1011
Асинхронный layout. Так стоит ли?

Помните, я говорил, что не люблю разбирать чужие либы? Тогда зачем я сделал это щас?

Потому что асинхронный лайаут — это как единорог. Его все пытается поймать, но никто не может. VK, Avito, Yandex — каждый хотел сделать самую быструю ленту и дать ответ рынку. Но почти все забросили эту идею...

В индустрии уже сложилось мнение, что асихнронный лайаут и его расчет в бэкграунд очередях должны быть только в очень, очень, ОЧЕНЬ сложных экранах. Тк проблем по контролю и сайд-эффектам будет в разы больше, чем выхлопа от перфоманса. Это самая крайняя крайность, к которой нужно приходить от безвыходности.

А вы как думаете? Нужен ли асинхронный лайаут, который считает размеры в фоновых очередях? Какие есть альтернативы?

3/3
1021
Перфоманс переоценен?

В одной компании (не буду показывать пальцем) провели эксперимент. Они увеличили искусственно скорость загрузки главного экрана на 1.5 секунд и…. Никакие продуктовые метрики не упали. Вообще. Пользователи будто и не заметили.

Мы все привыкли, что приложения должны быть быстрые и отзывчивые. Но этого больше хотят разработчики или юзеры?

какие бы метрики предложили вы?
7
📺 Воркшоп: Создание сложных коллекций в UIKit

Всю неделю я готовил фактуру и контексты для видео. Мы с Пашей, призером телеграм конкурсов и крутым разрабом, собрали плотную лекцию с кодом и замерами перфоманса:
🔘Кишки UIKit
🔘Render Server и хитчи
🔘Texture, Pinlayout, FrameBased Development vs AutoLaout
🔘много замеров
🔘много примеров из практики
🔘и другое

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

🧬 Получить доступ 💰тут или ⭐️ тут
Please open Telegram to view this post
VIEW IN TELEGRAM
212
Так, мы определились с форматом первой сходки. Это будут митапы с нетворкингом и играми. Камерный тимбилдинг.

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

Всем заинтересованным спасибо!🙏🏻

https://forms.gle/UiciPysajTNBpfTy8
10
Прелести Москвы это понять с переездом насколько же прикольное приложение золотого яблока. Разрабы и дизайнеры - молодцы
31
Туториал от Antropics по промт-инженерингу

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

За год вся эта тема из крепкого скептицизма до слепой истерии дошла до +- здоровую позицию. Мертвые сгенерированные текста бросаются сразу, но и сделанные в ручную контенты в умелых руках становятся богаче и продуманнее.

Вот и создатели Claude.ai поделились туториалми как сделать свою работу лучше
81
Forwarded from Банки, деньги, два офшора
Путин обязал Apple предустанавливать RuStore на все новые iPhone и планшеты в России с 1 сентября. @bankrollo
1151
Об алгоритмах на собеседовании

У меня, на первый взгляд, противоречивое мнение про алгоритмы. С одной стороны, я долго их решал и даже учавствовал в соревнованиях и шел "365 дней Богу Алгоритмов". С другой, я все также не умею проходить алгоритмические собеседования 😄

Опыт долгих тренировок определенно точно помог мне в кодинге, мышлении, какой-то базе. Но вот секции с алгосами для меня отдельный вид спорта 😂 Устно решать вслух != комфортненько молча за столом.

Но эти секции точно не стоит бояться. Мне нравится, как о них расписал наш руководитель отдела разработки Яндекс Еды Дима Александров @vit_ded

У нас во фронтендах часто не понимают зачем алгосы, а автор не редко сравнивает разные точки зрения и может найти сложные алгоритмы даже в нашей практике!
8
Действительно ли вы хорошо знаете SwiftUI?

Нашел супер крутую статью, о которой преступно умалчивают другие авторы.
В этой статье автор задает вопрос "А действительно ли вы хорошо знаете SwiftUI?".

Взяв самую популярную демо-задачу с Counter'ом он начинает подсвечивать самые частые заблуждения: начиная от использования незадокументированного _printChanges() заканчивая причинами зависаний экрана.

As you can see by adding .debugBackground() to every Text cell we can observe updating each cell whenever we click on theCounter +1 button. And as you remember we have 100_000 values🤯. That causes lagging! To be more precise — lagging is caused by the List cell creation behavior. Whenever List is created, it has to create all its inside items first because it needs to know how many items are on the screen. By clicking on the button we change the view state, and SwiftUI detects the state change and starts rebuilding the view, and because of the large number of values — this view rebuilds long.


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

Автор круто подчеркивает, что SwiftUI лишь обманчив простотой. Чтобы сделать хороший по перфомансу лайаут нужно приложить много ресурсов и изучить много вещей, которые плохо задокументированы и требуют собрать мозаику знаний. Ну и главное, чтобы это все не сломал Apple со след версией iOS 🙂

Многие советы вам известные, но дают чуть контекста на проблему. Например, тема про POD vs Non-POD чуть лучше расскрывается.

P.S. Говорят, что одна из ключевых черт зрелого инженера — умение выбирать правильные инструменты. Ну и одно из моих любимых правил: Если слишком сложно, то возможно не ты тупой, а плохой дизайн и проектирование инструмента для этих задач. Попробуй взять или придумать другой инструмент.
13
Forwarded from Воробей
Вернуть блюрную заливку
Убрать стекло
Переименоваться в iOS 19
5021
Swift Concurrency: что делает компилятор?

Я не считаю, что обучение по чужим статьям и твиторам — эффективно. Чаще это инфошум. Поэтому продолжаю структурировать и делым понятным то, что разбросано по кускам. Мы уже немного познакомились с Swift Concurrency по первоисточникам. Выяснили какие proposals почитать и какие wwdc посмотреть.

Теперь перейдем к кратким формулировкам и структурированию мозаик. Все абстракции и примерные мыслительные модели бесполезны, если мы не поймем как работает код.

Давайте по порядку. В теории, можно разделить все на такие ключевые слова:
- Компилятор ->
- State Machine ->
- suspension points ->
- Continuation ->
- Executor ->
- Co-operative thread pool

🟣Компилятор и State Machine. Каждый раз, когда компилятор видит await, то он режет функцию на структуру с полем resumePoint. Разбивает код на блоки и вставляет переходы между ними.

🟣Suspension points. Каждое await — это место приостановки. В интернете нет явной инфы, но общая формулировка такая: Функция приостанавливается и текущий стэк с переменными и позицией сохраняются в кучу. Создаётся continuation.

Swift implements asynchronous functions by transforming them into state machines. Each call to an asynchronous function and each await is a suspension point, where the function can suspend execution


🟣Continuation. Это объект, который хранит что делать дальше, после await. Он хранит в каком месте приостановилось выполнение, какие переменные были в контексте, что делать, когда результат будет готов.

“Continuations are the fundamental building block for suspending and resuming execution in Swift’s concurrency model.”


🟣Executor. Это условный планировщик, который решает, на каком потоке и когда выполнять async-код. Если continuation — это инструкция, то Executor — исполнитель. Сontinuation возобновляется и передаётся в executor, который решает где и когда продолжить выполнение.

“The continuation resumes execution via an executor, which may be the same as the original or different, depending on actor context.”


🟣Co-operative thread pool. Если Executor — это манагер задач, то Co-operative thread pool — это рабочие потоки, на которых Executor исполняет эти задачи. Это общий пул потоков, управляемый Swift Runtime. Потоки не создаются на каждую задачу, вместо этого задачи добровольно уступают выполнение, когда достигают await. Потоки переключаются на другие задачи, пока первая ждёт. Executor получает задачу, ставит ее в очередь и запускает на одном из потоков пулла.

Полезные ссылки:
- Apple Docs
- 0392-custom-actor-executors
- Swift concurrency: Behind the scenes

1/5
Please open Telegram to view this post
VIEW IN TELEGRAM
221
Swift Concurrency: Cooperative thread pool

Если затрагивать SC, то нельзя не остановиться отдельно на этой теме.

Для чего это придумали? GCD и DispatchQueue.global().async мог создавать на каждую задачу отдельный поток. Это приводит ко многим пролемам оптимизации, но главная — это thread explosion. Это когда создается слишком много потоков одновременно и врызвается жопа ОС.


for _ in 0..<10_000 {
DispatchQueue.global().async {
// что-то делает
}
}


Cooperative Thread Pool — это ключевая часть архитектуры Swift Concurrency. Если простыми словами, то это пул с потоками, которые делят CPU по договорённости. Swift Concurrency использует ограниченный пул потоков — примерно от 4 до 8, в зависимости от устройства и от кол-ва ядер в устройстве. Они уступают управление когда задача "приостанавливается" (await и Suspension points).

Swift runtime использует global concurrent executor. Этот executor основан на libdispatch (GCD), но с отдельной очередью с флагом COOPERATIVE. Это concurrent dispatch queue с названием com.apple.root.default-qos.cooperative. Даже если ты создашь тысячу Task { ... }, они не запустятся параллельно. Они будут ставиться в очередь и по очереди исполняться на тех же 8 потоках.

Чуть позже разберем пару НО и как Swift 6 помогает их избежать.

Полезные ссылки:
- How is the Cooperative Thread Pool integrated in Swift?
- Swift concurrency: Behind the scenes
- How does cooperative thread pool work?
- Limit Swift Concurrency's cooperative pool

2/5
121