Полный ответ дать сложно, причин очень много и, что еще сложнее, у них разная природа
#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
Когда-то давно, лет 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
Swiftrocks
How Collection Diffing works in Swift
Ordered Collection Diffing is a feature added in Swift 5.1 that allows you to calculate and apply the difference between two collections. Using diffing libraries is common in iOS for a few reasons, the most popular one being to handle the addition and removal…
1❤4 2 2 2
👉 Подумалось мне что это отличная тема для серии постов.
Думаю, разобрать основные семейства структур данных, как они устроены, где их правильно применять и какие подводные камни у них есть. Будет ли это интересно? Может быть погрузимся глубже? Время покажет.
План серии:
- 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
❤12 7
Частая задача — подключить 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
blog.cocoapods.org
The Dependency Manager for iOS & Mac projects.
❤4 3
На медиуме довольно много статей про «скрытые 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
❤3 1 1
Статья о масштбировании команды разработки и распространенные, принимаемые решения.
С ростом команды растут и организационные затраты: больше пересборок, тестов, ожиданий, мердж-конфликтов и т.д.
Расходы бизнеса, в таком случае не решаются усилением железа или наймом — ребята из Tuist, предлагают оптимизировать пайплайны.
Билд-кэширование, импакт анализ на сборке и тестирование, действительно магически помогают снизить накладные издержки и сохранить скорость разработки при масштабировании.
#L #Tuist #BuildCache #ImpactAnalysis
Please open Telegram to view this post
VIEW IN TELEGRAM
tuist.dev
Build Smart Before You Build Fast
Discover how merge throughput evolves as your team grows, and why optimizing build and test times becomes critical for business velocity
❤4
Как сделать ваши кастомные типы пригодными для обмена и передачи между приложениями или компонентами системы?
Если тип соответствует Transferable и описывает, как его сериализовать/десериализовать — его можно «таскать» через drag-and-drop, copy/paste, использовать с ShareLink, PasteButton и др.
#L #Swift #Transferable
Please open Telegram to view this post
VIEW IN TELEGRAM
Create with Swift
Understanding the Transferable Protocol in Swift
Learn how to prepare your custom types to be sharable between applications and system features with the Transferable protocol.
❤7
…или почему
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
Anonymous Poll
14%
Новостные
43%
Короткие и по делу
66%
Большие разборы со всеми пруфами
34%
Карточки с графикой и примерами
7%
Свой вариант в комментарии
🔎 Что такое 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
Rob Kerr's Blog
Building a GraphRAG App: Concepts, Code, and Demo
In this post we’re going to talk about GraphRag — one of the techniques we can use to add knowledge to the context of a large language model prompt. We'll go through the concepts, theory, and end with a video walk-through of a fully functional full-stack…
🔥1