This media is not supported in your browser
VIEW IN TELEGRAM
Пятничный Vibe-coding
👀 Решил попробовать этот ваш вайб кодинг
Выглядит, конечно, как магия - тут тебе и дизайнер и разработчик в одном лице. Главная задача - хорошо и понятно написать промпт.
Похоже на то, что в ближайшее время мы уже будем меньше писать кода сами, а больше времени уделять ревью и отладке - местами, код, который получился после генерации, похож на код джуна🥸
Да и видно, что дизайну он соответствует не полностью (хотя он сам его придумал🫠 ).
Но это намного лучше и быстрее, чем писать все изначально с 0🔥
P.S. Я использовал Cursor и плагин для фигмы
Выглядит, конечно, как магия - тут тебе и дизайнер и разработчик в одном лице. Главная задача - хорошо и понятно написать промпт.
Похоже на то, что в ближайшее время мы уже будем меньше писать кода сами, а больше времени уделять ревью и отладке - местами, код, который получился после генерации, похож на код джуна
Да и видно, что дизайну он соответствует не полностью (хотя он сам его придумал
Но это намного лучше и быстрее, чем писать все изначально с 0
P.S. Я использовал Cursor и плагин для фигмы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥3
Пробовали Vibe-coding
Anonymous Poll
29%
Да, Крутая штука
14%
Да, но больше не буду
31%
Нет
26%
Что это вообще такое?
Building Type‑Safe, High‑Performance SwiftData / Core Data Models
🔍 В статье приводятся советы, как сделать модели для
Вот некоторые моменты:
➡️ В отличие от
➡️ Использование библиотеки NonEmpty позволяет гарантировать, что строка не пустая, что улучшает семантику и предотвращает ошибки на этапе компиляции.
➡️ Для многовариантных выборок рекомендуется использовать битовые операции для хранения данных, что значительно повышает производительность запросов в
➡️
CoreData
/SwiftData
типо-безопасными и эффективными.Вот некоторые моменты:
SwiftData
, CoreData
требует использования NSNumber
для опциональных числовых свойств, что нарушает стиль Swift
. Решение включает использование вычисляемых свойств для обеспечения безопасности типов.SQLite
.SwiftData
требует явного определения инициализаторов, что помогает предотвратить ошибки и обеспечивает строгий порядок создания моделей.extension DataContent {
// Public array interface
public var optionSelections: [Int] {
get { optionIDsNumber.toArray() }
set { optionIDsNumber = optionIDsToInt64(optionIDs: newValue) }
}
// Stored as a bitmask
private var optionIDsNumber: Int64
}
func optionIDsToInt64(optionIDs: [Int]) -> Int64 {
var result: Int64 = 0
for id in optionIDs where id >= 0 && id <= 63 {
// Set the bit corresponding to each ID
result |= (1 << id)
}
return result
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2
How a Single Line Of Code Could Brick Your iPhone
🔍 Крутая статья про то, к чему приводит любознательность и понимание механизмов работы различных компонентов.
🔔 Уязвимость в
Вот эта строка:
🆒
🗓 Первоначальный отчет о проблеме был отправлен в Apple 26 июня 2024 года, а уязвимость была исправлена в iOS 18.3 с присвоением CVE-2025-24091.
💵 За это автор получил вознаграждение в размере 17.5 к $.
✔️ Теперь для отправки чувствительных уведомлений Darwin требуется наличие ограниченных прав, что предотвращает несанкционированные действия со стороны приложений.
Darwin notifications
позволяет любому процессу на iOS отправлять уведомления без специальных привилегий.Вот эта строка:
notify_post("com.apple.MobileSync.BackupAgent.RestoreStarted")
+ виджет и fatalError()
окирпичивали телефон.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍1
Swift Error Handling Done Right: Overcoming the Objective-C Error Legacy
👀 Описываешь ошибки в коде, которые конформят
Ну было, да?🤦♂️
Если ответ положительный, то вам нужно прочитать эту статью.
Коротко:
✔️
💡 Автор предлагает свой протокол
Error
протокол, и ожидаешь получить внятное объяснение при выбрасывании, но вместо этого: "The operation couldn't be completed. (YourApp.YourError error 0.)"
enum NetworkError: Error {
case noConnectionToServer
case parsingFailed
var localizedDescription: String {
switch self {
case .noConnectionToServer:
return "No connection to the server."
case .parsingFailed:
return "Data parsing failed."
}
}
}
// Using the error
do {
throw NetworkError.noConnectionToServer
} catch {
print("Error message: \(error.localizedDescription)")
// Expected: "No connection to the server."
// Actual: "The operation couldn't be completed. (AppName.NetworkError error 0.)"
}
Ну было, да?
Если ответ положительный, то вам нужно прочитать эту статью.
Коротко:
Swift
предлагает использовать протокол LocalizedError
для обработки ошибок, но он имеет недостатки, такие как необязательные свойства и неясные названия.Throwable
, который требует единственного обязательного свойства userFriendlyMessage
, что упрощает создание понятных сообщений об ошибках.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2
Руководство по использованию unsafe в Swift
ℹ️ В
⚠️ Использование небезопасных механизмов оправдано при взаимодействии с C API, для оптимизации производительности, низкоуровневого программирования и работы с Objective-C.
⚙️ Важно минимизировать область использования
🔴 Преимущества использования
Swift
существуют различные способы работы с небезопасными операциями, включая прямое использование указателей и встроенные обёртки, такие как UnsafePointer
и UnsafeMutablePointer.
unsafe
, применять конструкции withUnsafe
для безопасного доступа к указателям и тщательно документировать код для предотвращения утечек памяти.unsafe
включают производительность и гибкость, однако риски связаны с утечками памяти и сложностью поддержки кода.import Foundation
let count = 4
// Выделяем память для 4 байтов
let rawPointer = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: MemoryLayout<UInt8>.alignment)
// Инициализируем память
for i in 0..<count {
rawPointer.storeBytes(of: UInt8(i), toByteOffset: i, as: UInt8.self)
}
// Чтение данных через UnsafeRawPointer
let immutableRawPointer = UnsafeRawPointer(rawPointer)
for i in 0..<count {
let byte = immutableRawPointer.load(fromByteOffset: i, as: UInt8.self)
print("Байт \(i): \(byte)")
}
// Освобождаем память
rawPointer.deallocate()
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Bridging interfaces with the Adapter pattern in Swift
➡️ Паттерн адаптер позволяет интегрировать сторонние API или устаревший код, сохраняя при этом чистоту архитектуры приложения.
✏️ В примере показано, как адаптировать интерфейс стороннего SDK с использованием протокола
💡 Использование адаптера помогает сохранить инкапсуляцию и чистое разделение между доменами, что делает код более устойчивым к изменениям.
SearchService
, чтобы обеспечить совместимость с существующим кодом.protocol SearchService {
func search(query: String) async throws -> [SearchResult]
}
class ThirdPartySearch {
func runSearch(term: String, completion: @escaping ([Any]) -> Void) {
// ...
}
}
class ThirdPartySearchAdapter: SearchService {
private let thirdPartySearch = ThirdPartySearch()
func search(query: String) async throws -> [SearchResult] {
try await withCheckedThrowingContinuation { continuation in
thirdPartySearch.runSearch(term: query) { rawResults in
let results = rawResults.compactMap { $0 as? SearchResult }
continuation.resume(returning: results)
}
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Custom subscripts in Swift explained with code examples
➡️
⚙️
можно определить, как методы, и они могут принимать несколько параметров, что позволяет улучшить читаемость кода.
ℹ️ Подписки могут быть как только для чтения, так и для записи, что позволяет не только получать, но и устанавливать значения в коллекциях.
➡️ Статические подписки позволяют обращаться к элементам без необходимости раскрывать детали экземпляра, что улучшает инкапсуляцию.
➡️
Subscript в Swift
позволяют создавать короткие пути к элементам коллекций, что упрощает доступ к данным в классах, структурах и перечислениях.Custom subscripts
можно определить, как методы, и они могут принимать несколько параметров, что позволяет улучшить читаемость кода.
Subscripts
могут принимать необязательные параметры, что добавляет функциональность, например, для получения изображений по базовому URL.extension ImageCache {
subscript(url: URL) -> UIImage? {
get {
imageStore[url]
}
set {
imageStore[url] = newValue
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4👎1
Regular Expressions in Swift
⚙️ В Swift регулярные выражения реализованы через класс
⚠️ Однако стоит помнить, что чрезмерное использование регулярных выражений в больших текстах может негативно сказаться на производительности приложения. С выходом Swift 5.7 появился более современный и удобный инструмент -
💡 В статье подробно рассмотрены основы работы с
NSRegularExpression
из Foundation
, который позволяет создавать шаблоны и искать совпадения в строках. Для удобства можно расширить этот класс, чтобы упростить создание и проверку выражений, например, добавить метод matches()
, который проверяет наличие совпадений в строке. Swift Regex
с лаконичным синтаксисом и билдерами регулярных выражений, который значительно упрощает работу и повышает читаемость кода по сравнению с NSRegularExpression
NSRegularExpression
, примеры использования, а также преимущества новых подходов Swift Regex
с множеством практических примеров. Рекомендуем к прочтению всем, кто хочет глубже понять регулярные выражения в Swift и писать более эффективный и чистый код.// matching a url
let link = Reference(URL.self)
let linkRB = Regex {Capture (as:link){.url()}}
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
From 180 cm to 5′ 11″: A Complete Guide to Swift Measurement
💡 Если вам вдруг нужно поддерживать различные единицы измерения в своем приложении, то вот хороший гайд по работе с Measurement.
✏️ API Measurement в Swift позволяет безопасно и удобно работать с единицами измерения, обеспечивая автоматическую конвертацию и форматирование значений.
➡️ Можно выполнять математические операции с объектами Measurement, если они принадлежат одной категории единиц, что упрощает работу с данными.
➡️ Метод formatted() позволяет легко преобразовывать Measurement в удобочитаемый текст с учетом локализации, что делает его полезным для международных приложений.
➡️ Swift позволяет добавлять новые единицы измерения в существующие категории или создавать совершенно новые категории, что расширяет возможности API.
let heightMeasurement = Measurement<UnitLength>(value: 180, unit: .centimeters)
// Division with a scalar
let half = heightMeasurement / 2
print(half.value) // 90.0
print(half) // "90.0 cm"
// Addition: different units can be added; the result is in the category’s base unit
let h180cm = Measurement<UnitLength>(value: 180, unit: .centimeters)
let h1m = Measurement<UnitLength>(value: 1, unit: .meters)
let totalHeight = h180cm + h1m // 2.8 m (base unit of UnitLength is metres)
print(totalHeight) // "2.8 m"
// Comparison with automatic unit handling
h180cm < h1m // false (180 cm ≮ 1 m)
// Ranges respect units too
let range = h1m ... h180cm
range.contains(Measurement(value: 6, unit: .feet)) // false (~1.83 m is outside)
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10
Изоляция с помощью глобальных акторов в Swift Concurrency: варианты на примере @MainActor
🔍 В статье рассматриваются различные подходы к изоляции с использованием
⚠️ Ошибки, такие как разделение соответствия протоколу и реализации (например, через расширение), могут привести к потере ожидаемой изоляции, несмотря на наличие аннотаций
🔴 Аннотация
⚙️ Выбор подхода к изоляции зависит от контекста: для взаимодействия с UI лучше использовать полную изоляцию, а для повышения производительности — частичную.
@MainActor
включают полную изоляцию на уровне типа, изоляцию отдельных методов и свойств, а также частичную изоляцию через расширения.@MainActor
.@MainActor
повышает безопасность данных в многопоточной среде, но требует внимательного проектирования для предотвращения ошибок.@MainActor
protocol IUpdate {
func update(date: Date) async
}
@Observable
final class LS {
var date: Date = .now
}
// Здесь изоляцию @MainActor получит только update
extension LS: IUpdate {
func update(date: Date) async {
await internalUpdate(date: date)
}
// А здесь изоляция уже не применится
private func internalUpdate(date: Date) async {
self.date = date
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Обсуждем кейсы на митапе Яндекса по мобильной разработке
Я.Субботник — большой митап для мобильных разработчиков. В этот раз кроме докладов участников ждёт практический разрбор кейсов на PeerLab.
PeerLab — камерная встреча с экспертами Яндекса. Для неё мы отобрали актуальные темы из разработки и карьеры. Предложить кейс для обсуждения может каждый участник — приносите их в форму регистрации и приходите на обсуждение!
В Москве точно обсудим:
🔸 Kotlin Multiplatform
🔸 Карьерное развитие
🔸 Платформенные команды
🔸 AI в разработке
А в Питере:
T-Shape разработчик
🔸 Тестирование
🔸 AI в разработке
➡️ Регистрируйтесь и ищите список экспертов-участников дискуссии на сайте
Я.Субботник — большой митап для мобильных разработчиков. В этот раз кроме докладов участников ждёт практический разрбор кейсов на PeerLab.
PeerLab — камерная встреча с экспертами Яндекса. Для неё мы отобрали актуальные темы из разработки и карьеры. Предложить кейс для обсуждения может каждый участник — приносите их в форму регистрации и приходите на обсуждение!
В Москве точно обсудим:
А в Питере:
T-Shape разработчик
➡️ Регистрируйтесь и ищите список экспертов-участников дискуссии на сайте
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2👎1
Protecting mutable state with Mutex in Swift
❓
➡️ Акторы в
ℹ️ Пример класса
⚙️ Выбор между
➡️ Для использования
Mutex
в Swift
используется для защиты состояния от одновременного доступа, обеспечивая эксклюзивный доступ к защищаемым данным.Swift
удобны для асинхронного кода, но могут усложнить код, тогда как Mutex
подходит для быстрого синхронного доступа к данным.Counter
показывает, как использовать Mutex
для безопасного увеличения и уменьшения счетчика, обеспечивая защиту от гонок данных.Mutex
и акторами зависит от удобства, согласованности и намерений разработчика; Mutex
лучше подходит для простых операций без асинхронного кода.Mutex
с SwiftUI
необходимо вручную уведомлять Observable
о доступе и изменении состояния, чтобы обновления интерфейса работали корректно.class Counter {
private let mutex = Mutex(0)
func increment() {
mutex.withLock { count in
count += 1
}
}
func decrement() {
mutex.withLock { count in
count -= 1
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
When the Swift Debugger Lies: The Hidden Cost of Compiler Optimizations
👀 Интересный кейс произошел у автора при отладке приложения: перед выходом из функции массив оказался пустой.
❓ Swift использует оптимизацию управления памятью, что приводит к преждевременному освобождению переменных, таких как
💡 Чтобы сохранить переменные, такие как
func getUserListForAdmin() async -> NetworkResponse<[OtherUser]> {
async let type4Request = RestClient.shared.request(Constants.Network.ENDPOINT_USERS, parameters: ["userType": 4])
async let type2Request = RestClient.shared.request(Constants.Network.ENDPOINT_USERS, parameters: ["userType": 2])
let (result4, result2) = await (type4Request, type2Request)
switch (result4, result2) {
case (.success(let users4), .success(let users2)):
for user in users4 {
user.canSeeThisUsersRequests = users2.contains(where: { $0.id == user.id })
}
return .success(users4) // At this breakpoint, users2 appears EMPTY 🤯
case (.error(let error), _), (_, .error(let error)):
return .error(error)
}
}
users2
, когда они больше не нужны.users2
, используйте withExtendedLifetime(users2)
или извлеките их из switch
-выражения заранее, чтобы избежать их удаления.Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Exploring concurrency changes in Swift 6.2
ℹ️ Swift 6.2 вводит два основных изменения в параллельности: новый флаг по умолчанию
⚠️ Флаг
⚠️ С помощью
❗️ Рекомендуется включить оба новых флага для упрощения работы с параллельностью, однако важно избегать избыточного использования
nonisolated(nonsending)
и выполнение кода на главном акторе по умолчанию с помощью настройки defaultIsolation
.nonisolated(nonsending)
позволяет асинхронным функциям наследовать контекст актора вызывающего кода, что уменьшает количество ошибок компиляции и упрощает работу с параллельностью.defaultIsolation
можно установить выполнение кода на главном акторе по умолчанию для всех объектов в пакете, что упрощает разработку UI и моделей.@concurrent
, чтобы не усложнять код.actor SomeGenerator {
// not allowed
@concurrent
func randomID() async throws -> UUID {
return UUID()
}
// allowed
@concurrent
nonisolated func randomID() async throws -> UUID {
return UUID()
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
Swift Enums vs Structs - Picking the Best Tool for the Job
Очередная статья про выбор между Enum и структурами (классы остались за бортом🫠 )
➡️ Enums обеспечивают исчерпывающее переключение, что делает код более надежным, особенно когда состояния являются взаимно исключающими.
➡️ Structs позволяют добавлять новые случаи и настраивать стили, что делает их идеальными для систем конфигурации и стилей.
⚙️ Можно комбинировать Enums и Structs для достижения наилучших результатов, используя каждый инструмент в зависимости от конкретной ситуации.
💡 Выбирайте Enums для управления состоянием с фиксированным набором опций и Structs для хранения сложных состояний с несколькими свойствами.
Очередная статья про выбор между Enum и структурами (классы остались за бортом
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Swift 6 Refactoring in a Camera App - SLIT_STUDIO Development Log
➡️ Swift 6 требует от разработчиков учитывать новые требования к потокобезопасности, что создает сложности при миграции, особенно с фреймворками Apple.
⚙️ Разработчик
⚠️
➡️ Код приложения был перегружен, и
💡 Важно не только исправлять ошибки, но и переосмысливать структуру приложения, чтобы избежать проблем с потокобезопасностью и улучшить общее качество кода.
Megabits
успешно адаптировал приложение SLIT_STUDIO
, используя новые компоненты, такие как actor
и GlobalActor
, для улучшения структуры кода и безопасности.AVFoundation
использует GCD
, что не совместимо с Swift Concurrency
, требуя от разработчиков находить нестандартные решения для обеспечения потокобезопасности.Megabits
разделил его на более управляемые компоненты, такие как CaptureManageObject
и Recorder
, чтобы улучшить читаемость и поддержку.@globalActor actor CameraActor: GlobalActor {
static let shared = CameraActor()
}
@CameraActor class Camera: NSObject {
let captureQueue = DispatchQueue(label: "com.linearCCD.capture")
var captureSession = AVCaptureSession()
var currentDevice: AVCaptureDevice?
var videoInput: AVCaptureDeviceInput?
var audioInput: AVCaptureDeviceInput?
var videoOutput: AVCaptureVideoDataOutput?
var audioOutput: AVCaptureAudioDataOutput?
...
}
@CameraActor class CapturePipeline: NSObject, ObservableObject {
let renderContext: MTIContext
var renderPoolForFilter = RenderPool()
var renderPoolForRecordingImage = RenderPool()
var cameraFeedRenderTask: Task<(), Never>?
...
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Для чего я написал собственный аудиопроигрыватель
👀 Автор разработал собственный аудиопроигрыватель из-за неудовлетворенности существующими решениями, такими как Apple Music и сторонние приложения, которые не обеспечивали нужного функционала для управления локальной музыкальной библиотекой.
⚙️ Приложение было создано с использованием SwiftUI для упрощения разработки интерфейса и управления данными, а также SQLite для реализации полнотекстового поиска и хранения данных.
⚠️ Приложение включает в себя гибкий поиск по папкам iCloud, управление плейлистами и воспроизведение музыки с возможностью настройки очереди и управления громкостью.
🫠 Существующие приложения часто требуют подписки, имеют ограниченные функции и неудобный интерфейс, что побудило автора создать собственное решение.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Unique values in Swift: Removing duplicates from an array
❓ В
➡️
➡️ Если порядок важен, можно создать расширение для массива, которое использует протокол
👀 Выбор между
Swift
нет встроенных методов для удаления дубликатов из массива, поэтому необходимо использовать альтернативные подходы, такие как использование Set
или создание расширения для массива.Set
по умолчанию содержит только уникальные значения и подходит, если порядок элементов не важен. Это более производительный вариант для решения проблемы уникальности.Hashable
для фильтрации дубликатов, обеспечивая линейную временную сложность.Set
и расширением массива зависит от необходимости сохранения порядка элементов: используйте Set
, если порядок не важен, и расширение массива, если он важен.extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
var seen: Set<Iterator.Element> = []
return filter { seen.insert($0).inserted }
}
}
print(array.unique()) // prints: [1, 2, 3]
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6