YDC — Pizza Powered iOS – Telegram
YDC — Pizza Powered iOS
242 subscribers
65 photos
95 links
Young Da Code 👨‍💻
Первый командный дайджест о мобильной разработке 🍕
Download Telegram
🤔 "Почему одни большие проекты стагнируют, а другие живут годами"?
Полный ответ дать сложно, причин очень много и, что еще сложнее, у них разная природа

🤔 Сегодня в своем feedly мне на глаза попался крутой заголовок на Medium, но вот её содержание меня не удовлетворило. На мой вгляд надо сместить акценты

🚬 Чтобы не клепать лонгрид накинул "обзорные" карточки только на технические и около-технические моменты, все для разработчиков 👌

📎 Managing Large-Scale iOS Projects...

#M #iOS #TeamWork #Architecture #Modularization

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
3221
🤫 Что общего у UITableView и git diff

Когда-то давно, лет 10 назад, у меня была задача: получать пачку данных с сервера, находить различия с кэшем и красиво обновлять UITableView, чтобы не было резких reload'ов, а всё плавно вставлялось, удалялось и двигалось.
Тогда задача обошлась мне, не в один день анализа и проектирования, чтобы научиться сравнивать старый и новый массивы.

Тогда ещё не было никакого CollectionDifference, и я просто пошёл реализовывать алгоритм Вагнера–Фишера и работать с вычислением: расстояния Левенштейна и редакционноого предписания - минимального количества действий и их последовательности чтобы из "ABC" получилось "ACD".

Ну и конечно, всё это руками прикручивалось к performBatchUpdates:


tableView.performBatchUpdates {
tableView.deleteRows(at: ...)
tableView.insertRows(at: ...)
}


Весело? Не очень. Но тогда по-другому никак.


Потом, с приходом iOS 13 и Swift 5.1, всё изменилось.
Apple выкатили DiffableDataSource, и вместе с ним — CollectionDifference.
Это была буквально революция, теперь можно просто сформировать снапшот и отдать его таблице:


var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items)
dataSource.apply(snapshot, animatingDifferences: true)


UITableView сама всё поймёт, сама вычислит, что вставить, что удалить, что переместить — и сделает это с анимацией.
А мы — просто передаём новое состояние.

Если копнуть глубже, то под капотом лежит алгоритм Майерса.
Он также находит минимальную последовательность изменений между двумя массивами.

Apple реализует его для CollectionDifference.
Можно глянуть исходники Swift или вот обьяснение алгоритма.

Но если хочется больше контроля или скорости — есть и альтернативы.
Например, DifferenceKit, который использует алгоритм Пола Хекеля.
Вот сам код.
Он быстрее в ряде кейсов, особенно если много данных, на это влияет сложность O(n), бенчмарки можно посмотреть на gh.
И с ним сделали даже backport - DiffableDataSource для старых iOS.

Мораль истории: задача сравнения последовательностей — стара как мир.
Её решают в UI, в git, в текстовых редакторах.
А теперь и мы — наконец-то — можем делать это в UITableView, не теряя нервы на написание сложных алгоритмов и работу с indexPath-ами.

#L #UITableView #DiffableDataSource #CollectionDifference #LevenshteinDistance

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
14222
🤔 Недавно после чтения статьи по коллекциям, обсуждали с коллегами, какие структуры данных мы реально используем в iOS — те, что есть «из коробки» в Swift/ObjC, те, что приезжают из Swift Collections, и те, что иногда приходится реализовывать самому.

👉 Подумалось мне что это отличная тема для серии постов.


Думаю, разобрать основные семейства структур данных, как они устроены, где их правильно применять и какие подводные камни у них есть. Будет ли это интересно? Может быть погрузимся глубже? Время покажет.

План серии:
- Array-like структуры — contiguous/circular buffer, Copy-On-Write, NSPointerArray, BitArray, OrderedArray.
- Set-семейство — HashSet, BitSet, NSSet, NSOrderedSet, CountedSet их особенности и коллизии.
- Dictionary-семейство — HashMap, OrderedDictionary, NSMapTable, NSDictionary, LRUCache, NSCache.
- aka Navigation-структуры (рабочее название) — LinkedList, Stack, Queue, Deque, Heap.
- Приоритетные структуры — PriorityQueue, Min-Max-Heap.
- Деревья — BST, AVL, Red-Black, Splay.
- Графы — базовые реализации, обходы и тд.

А сегодня — первая подборка карточек: Array и всё “семейство” вокруг него.

#L #DataStructures #Swift #Collections

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
127
🤫 Debug-only SDK в iOS

Частая задача — подключить SDK только в Debug, но не тянуть его в Release:
дебажные тулзы вроде Flex, sandbox-SDK и прочее.
И вот как разные инструменты с этим справляются 👇

🍫 CocoaPods — старичок, который решает задачу идеально:

pod 'SomeSDK', :configurations => ['Debug']


И всё — магия происходит автоматически.

CocoaPods:
• генерирует разные .xcconfig под Debug и Release
• добавляет OTHER_LDFLAGS, FRAMEWORK_SEARCH_PATHS только в Debug
Это правильное поведение на уровне линковки.
И работает уже лет 10. Пруфы со времён 0.34.

🧰 Tuist — “сделай сам”:
Tuist ближе к Xcode, но отдельной поддержки Debug-only зависимостей нет. Официальный issue.
Что приходится делать:
• вручную писать xcconfig или BuildSettings и менять OTHER_LDFLAGS по конфигурации
или
• использовать ENV-ы при tuist generate
и
• создавать отдельные targets под Debug/Release
То есть руками воспроизводить то, что CocoaPods делает автоматически.

📦 Swift Package Manager — примерно как Tuist:
Можно исключать код через макросы #if DEBUG.
Вижу что можно колдовать с LinkerSetting-ами руками и использовать unsafeFlags с condition.
Но, что-то исследование через гугление, не дает статей по использованию.
Интересно почему? Все еще так мало адептов?
Сами мы spm в enterprise не используем, только периодически присматриваемся, и постоянно что-то отталкивает.
Поэтому буду рад, если скорректируете.

#L #Cocoapods #Tuist #SPM

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
43
😏 Полезные SwiftUI-компоненты.
На медиуме довольно много статей про «скрытые SwiftUI компоненты». Я как раз прочитал несколько, где автор рассказывает про полезные компоненты, о которых многие не знают.

Из множества вариантов я выбрал три самых интересных, которыми точно стоит пополнить свой инструментальный запас.

⏱️ TimelineView – обновления по расписанию
Этот компонент автоматически перерисовывает View каждую секунду, минуту или по вашему интервалу.

Где нужен:
- часы
- таймеры и обратные отсчёты
- виджеты
- данные, которые должны обновляться «в фоне»

Почему лучше старых решений:
Timer → утечки, ручной поток, лишняя логика
Combine.Timer → громоздко
✔️ TimelineView → нативно, оптимизировано, просто

Плюс еще одно важное преимущество:
В режиме .animation TimelineView ведёт себя похоже на CADisplayLink: обновления идут в такт рендеринга, но без ручного управления runloop’ом и без риска забыть invalidate().
А в режиме .periodic система сама оптимизирует частоту, что экономит энергию.

Пример:
TimelineView(.periodic(from: .now, by: 1)) { context in
Text(Date.now.formatted())
}


🎛 PhaseAnimator – сложные анимации без таймеров
PhaseAnimator позволяет задать список значений (фаз), а SwiftUI сам плавно будет бегать между ними.

Когда использовать:
- shimmer и skeleton
- пульсирующие элементы
- бесконечные анимации

Почему лучше старых подходов:
раньше: onAppear + стейты + таймеры
✔️ сейчас: декларативно, чисто, предсказуемо

Пример:
PhaseAnimator([1, 1.3, 1]) { phase in
Circle().scaleEffect(phase)
}


🎨 Canvas – когда нужен кастомный рендеринг
Если стандартные формы SwiftUI уже не помогают – Canvas позволяет рисовать что угодно, как в CoreGraphics, но нативно в SwiftUI.

Где полезно:
- графики
- диаграммы
- сложные анимации
- частицы
- декоративные фоны

Почему лучше старых решений:
UIViewRepresentable + CoreGraphics → сложно, неудобно
✔️ Canvas → рисуешь прямо в SwiftUI

Пример:
Canvas { context, size in
context.fill(
Path(ellipseIn: CGRect(origin: .zero, size: size)),
with: .color(.orange)
)
}
.frame(width: 120, height: 120)


🍕 Итог:

Три компонента закрывают три разные задачи:

- TimelineView – всё, что зависит от времени
- PhaseAnimator – анимации с логикой фаз
- Canvas – кастомная графика без UIView

Это инструменты, которые позволяют писать SwiftUI-код быстрее и чище – и избавляют от костылей, к которым мы привыкли.

#R #SwiftUI

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
311
🤫 🚀 "Smart before fast" Tuist
Статья о масштбировании команды разработки и распространенные, принимаемые решения.

С ростом команды растут и организационные затраты: больше пересборок, тестов, ожиданий, мердж-конфликтов и т.д.
Расходы бизнеса, в таком случае не решаются усилением железа или наймом — ребята из Tuist, предлагают оптимизировать пайплайны.
Билд-кэширование, импакт анализ на сборке и тестирование, действительно магически помогают снизить накладные издержки и сохранить скорость разработки при масштабировании.

#L #Tuist #BuildCache #ImpactAnalysis

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
4
🤫 📢 Новый взгляд на обмен данными в Swift — протокол Transferable

Как сделать ваши кастомные типы пригодными для обмена и передачи между приложениями или компонентами системы?
Если тип соответствует Transferable и описывает, как его сериализовать/десериализовать — его можно «таскать» через drag-and-drop, copy/paste, использовать с ShareLink, PasteButton и др.

#L #Swift #Transferable

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
7
😜 Сахар VS динамика
…или почему DynamicMemberLookup плавится под взглядом objc_msgSend

Может показаться, что Swift стремится быть «тоже динамичным».
Добавили @dynamicMemberLookup, добавил @dynamicCallable — ну, почти Python! Почти ObjC! Почти магия!

Но потом на сцену выходит Objective-C, закатывает рукава и тихо шепчет:

«Малыш, это не динамика. Это лишь синтаксический сахар.»


Потому что где Swift подменяет свойства через субскрипты,
Objective-C через objc_msgSend прогуливается прямо по таблицам методов, меняет реализации на лету, отлавливает несуществующие селекторы, форвардит вызовы куда захочет и в целом живёт по принципу:

«Если я хочу сделать это — я сделаю.»


В Swift ты получаешь аккуратную коробочку с инструкциями.
В Objective-C — набор динамита и спички.

И да, об этом всём я хочу написать в длинном посте на будущей неделе:
- про рантайм
- про isa
- про swizzling
- про Mirror
- про Swift runtime metadata
и почему у одного языка динамика настоящая, а у другого — сладкая.

Кстати, вопрос: какого формата посты больше нравятся? короткие-новостные? или детальные разборы?
Как в целом используете тг-каналы? Следить за новостями не погружаясь? Или каждо-дневное чтиво?
Буду рад, если дадите ОС.

Всем хороших выходных и отличного вечера пятницы. 😁

#L #objc #runtime #swift #dynamicMemberLookup #dynamicCallable

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
7💯3
🤫 📚 GraphRAG - как LLM + графовая БД = осмысленный интеллект

🔎 Что такое GraphRAG

GraphRAG - это RAG-подход, но с графовой базой знаний под капотом: вместо простого текст-поиска (векторов) мы храним сущности и их связи в графе, так, чтобы отношения между данными были явно выражены.

Это полезно, когда важно не просто найти похожие куски текста, а правильно обрабатывать взаимосвязи: например, «какие врачи делали какие процедуры пациентам в каких клиниках». Такие много-звенные запросы редко нормально обрабатываются через обычный RAG.

🚀 Как это работает - на примере из статьи

1. Пользователь задаёт вопрос (естественным языком)
2. LLM анализирует вопрос, «понимает», какие сущности и связи нужны - что именно ищем (фильтр, категории, сущности).
В демо LLM разбирает, кого/что спрашивают (фильм, актёр, жанр и т.п.).
3. По результатам анализа LLM, backend формирует запрос к графовой БД, подставляя отношения/сущности/фильтры.
4. GraphDB возвращает строго структурированные данные - сущности + связи, удовлетворяющие запросу.
5. Затем LLM дополняет исходный запрос найденной информацией, и генерирует ответ на естественном языке, опираясь на факты из графа.

Связность и точность:
GraphRAG хранит не просто куски текста, а связи между сущностями - это даёт возможность отвечать на сложные вопросы, включающие отношения, фильтры, и многозвенные зависимости.

Меньше галлюцинаций:
Так как контекст - это не распылённые текстовые фрагменты, а проверенные факты и связи; LLM привязан к структуре, не «вымысливает» из воздуха.

Масштабируемость и гибкость:
Можно совмещать граф + векторную бд.
GraphRAG не обязательно заменяет RAG, но дополняет его, давая лучший grounding при необходимости сложных запросов.

#L #LLM #RAG #GraphRAG

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
😃 Tuist снова завозит магию.

Вышла статья: “Teaching AI to read Xcode builds” - и ребята опенсорсят fork Swift Build Service под названием argus.

Это команднй интерфейс для AI-агентов, который позволяет разбирать, понимать и оптимизировать Xcode-сборки.

Как всегда, Tuist невероятно понятно объясняет как работает pipeline сборки в Xcode.

Инструменты которые освещаются в статье:
- сам xcodebuild
- swift-build
- украшатель логов xcbeautify
- xcsift позволяющий получить лог в удобном формате для AI-анализа
- и TOON - оптимизированный JSON
- XCBLoggingBuildService — надстройка над XCBBuildService для перехвата событий
- и испольщуемой эплом MessagePack - еще один вариант оптимизировать JSON
- xclogparser

И показывают, как всё это используется для того, чтобы строить базу данных событий сборки, пригодную для анализа AI-агентами.

То есть они по сути берут весь «чёрный ящик» Xcode-сборки, вскрывают его, упаковывают в структурированные данные и дают агентам возможность понимать, что происходит во время билда.

С учётом того, что у Tuist уже есть Build Insights и Test Insights, которые сами по себе поднимают наблюдаемость на новый уровень — возможность интегрироваться прямо в процесс сборки + дать это агентам на анализ — выглядит как next level.

Мое почтение. 🤓

#L #Tuist #AI

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
33
🤔 Вспомнился ещё полезный материал:
«Code Optimization for Swift and Objective-C»

Он помогает чётко разделить роли инструментов:
Компиляторы: swiftc, clang — превращают код в машинный.
Билд-системы: xcodebuild и swift build — это оркестраторы, которые решают что, в каком порядке и с какими флагами компилировать.

#L #swiftc #clang #xcodebuild #swiftbuild

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
4