#ios #swift #swiftui #binding #bug
Как сломать
Результат:
Как сломать
Xcode 16.3, чтобы в логах не было нормального описания ошибки:
import SwiftUI
struct BreakSwiftExample: View {
@State private var isOn = false
private var isOnBinding: Binding<Bool> {
.init(
get: { isOn },
set: changeToggle // не собирается
// set: { isOn = $0 } // собирается
)
}
var body: some View {
Toggle("Демо-тоггл", isOn: isOnBinding)
}
private func changeToggle(_ value: Bool) {
isOn = value
}
}
Результат:
Command SwiftCompile failed with a nonzero exit code❤2👍2🔥1
#ios #swift #swiftui #maps #geocoding #hint
На прошлой неделе заметил, что релиз 3.10 приложения с площадками стал сильно греть телефон, и даже в статистике аккумулятора спустя всего 10 минут использования мое приложение было первым в списке по потреблению энергии 🙈
В том релизе я сделал много классных штук, и в том числе немного обновил старый код для работы с картой, в результате нагрузка на девайс выросла в разы.
На днях выпустил релиз с исправлением этих проблем, и вот главные выводы:
1️⃣ Если нужно получить локацию пользователя с использованием CLLocationManager, то лучше не использовать startUpdatingLocation(), а просто вызывать requestLocation() по таймеру, например раз в 10 секунд - нагрузка ощутимо упадет
2️⃣ Использовать reverseGeocodeLocation нужно не чаще раза в минуту, а лучше еще реже - если координаты ощутимо изменились (на 50 метров, например), и это точно нужно для правильной работы фичи
3️⃣ Если используете MKMapView внутри
На прошлой неделе заметил, что релиз 3.10 приложения с площадками стал сильно греть телефон, и даже в статистике аккумулятора спустя всего 10 минут использования мое приложение было первым в списке по потреблению энергии 🙈
В том релизе я сделал много классных штук, и в том числе немного обновил старый код для работы с картой, в результате нагрузка на девайс выросла в разы.
На днях выпустил релиз с исправлением этих проблем, и вот главные выводы:
1️⃣ Если нужно получить локацию пользователя с использованием CLLocationManager, то лучше не использовать startUpdatingLocation(), а просто вызывать requestLocation() по таймеру, например раз в 10 секунд - нагрузка ощутимо упадет
2️⃣ Использовать reverseGeocodeLocation нужно не чаще раза в минуту, а лучше еще реже - если координаты ощутимо изменились (на 50 метров, например), и это точно нужно для правильной работы фичи
3️⃣ Если используете MKMapView внутри
SwiftUI-обертки, то напишите явную проверку в методе updateUIView, чтобы обновление карты выполнялось только тогда, когда это 100% нужно - я для этого сделал флаг shouldUpdateRegion и передаю его в карту, а в методе updateUIView вызываю замыкание при обновлении карты, чтобы снять флаг🔥5❤2
#ios #swift #swiftui #contest
Нужно сверстать стек, где есть несколько
Должно получиться примерно как на картинке.
Шрифт для
Шрифт для
Не используем
Вот готовые модели для превью:
Кто первый сделает, тот молодец 🚀
Нужно сверстать стек, где есть несколько
Text с одинаковой структурой:
private struct UserInfo: Identifiable {
let id = UUID()
let label: String
let value: String
}
Должно получиться примерно как на картинке.
Шрифт для
label: .system(size: 20, weight: .bold)Шрифт для
value: .system(size: 16, weight: .regular)Не используем
markdown в тексте.Вот готовые модели для превью:
let items: [UserInfo] = [
.init(label: "Почта", value: "[email protected]"),
.init(label: "Телефон", value: "+79123456789"),
.init(
label: "Адрес",
value: "117513, г. Москва, ул. Профсоюзная, д. 129, корп. 3, кв. 117, подъезд 5, этаж 8"
)
]
Кто первый сделает, тот молодец 🚀
👌3
#ios #swift #swiftui #hint
На днях добавлял SwiftUI-вьюху внутрь UIKit-ячейки для экрана с коллекцией.
Вьюха просто принимает на вход данные и показывает что-то внутри себя.
⚠️Но есть нюанс: на iOS < 16 нельзя просто так добавить SwiftUI-вьюху в ячейку - для этого нужно делать костыль с хостингом и т.д.
И вот я все сделал, но наткнулся на проблему: при первом появлении ячейки вьюха не успевает целиком отобразиться, и получается полная фигня. Зато если прокрутить экран вниз или вверх, чтобы вьюха исчезла, и снова вернуться к той ячейке, то все отлично.
На этом экране еще и кнопка есть для скролла к той самой ячейке - и при первом скролле к ней она выглядит плохо.
Решается эта проблема очень просто - можно добавить вьюхе два состояния: "загрузка" и "готово".
В "загрузке" показываем любой принятый в проекте индикатор загрузки или скелетон, а в "готово" - обычное состояние вьюхи.
Ну и в саму вьюху внутрь
✅Теперь при первом рендере этой ячейки появится индикатор загрузки, а потом сразу корректное состояние.
На днях добавлял SwiftUI-вьюху внутрь UIKit-ячейки для экрана с коллекцией.
Вьюха просто принимает на вход данные и показывает что-то внутри себя.
⚠️Но есть нюанс: на iOS < 16 нельзя просто так добавить SwiftUI-вьюху в ячейку - для этого нужно делать костыль с хостингом и т.д.
И вот я все сделал, но наткнулся на проблему: при первом появлении ячейки вьюха не успевает целиком отобразиться, и получается полная фигня. Зато если прокрутить экран вниз или вверх, чтобы вьюха исчезла, и снова вернуться к той ячейке, то все отлично.
На этом экране еще и кнопка есть для скролла к той самой ячейке - и при первом скролле к ней она выглядит плохо.
Решается эта проблема очень просто - можно добавить вьюхе два состояния: "загрузка" и "готово".
В "загрузке" показываем любой принятый в проекте индикатор загрузки или скелетон, а в "готово" - обычное состояние вьюхи.
Ну и в саму вьюху внутрь
onAppear добавляем смену состояний.✅Теперь при первом рендере этой ячейки появится индикатор загрузки, а потом сразу корректное состояние.
❤2🔥1
👀3👍2
#ios #swift #swiftui #uikit
Все еще верстаете на ките и пользуетесь таблицами/коллекциями для создания списков? При этом хочется использовать в этих экранах SwiftUI?
Не беда! В iOS 16 добавили нативную интеграцию SUI в ячейках с помощью contentConfiguration.
Вот так нужно было в apple презентовать этот инструмент😁, а не тихонечко сказать в одном из видео, что вот теперь вы можете в ячейках добавлять SUI.
Алгоритм работы с этой штукой:
1️⃣ Верстаем вьюху для ячейки на SUI
2️⃣ В самой ячейке делаем проверку на iOS 16, и если версия подходит, то добавляем вьюху как показано в документации, можно обращаться напрямую к свойству
3️⃣ Если версия iOS < 16, то либо не показываем обновленный UI (😁), либо используем костыли с
Важный момент: если просто добавить SUI-вьюху в ячейку и не настроить отступы для конфигурации, то будут добавлены дефолтные отступы по горизонтали и вертикали.
Чтобы такой фигни не было, нужно вручную поверх конфигурации добавить отступы через метод margins.
Пример настройки
Весь код для демо-ячейки можно посмотреть в гитхабе.
Все еще верстаете на ките и пользуетесь таблицами/коллекциями для создания списков? При этом хочется использовать в этих экранах SwiftUI?
Не беда! В iOS 16 добавили нативную интеграцию SUI в ячейках с помощью contentConfiguration.
Вот так нужно было в apple презентовать этот инструмент😁, а не тихонечко сказать в одном из видео, что вот теперь вы можете в ячейках добавлять SUI.
Алгоритм работы с этой штукой:
1️⃣ Верстаем вьюху для ячейки на SUI
2️⃣ В самой ячейке делаем проверку на iOS 16, и если версия подходит, то добавляем вьюху как показано в документации, можно обращаться напрямую к свойству
contentConfiguration внутри ячейки3️⃣ Если версия iOS < 16, то либо не показываем обновленный UI (😁), либо используем костыли с
UIHostingControllerВажный момент: если просто добавить SUI-вьюху в ячейку и не настроить отступы для конфигурации, то будут добавлены дефолтные отступы по горизонтали и вертикали.
Чтобы такой фигни не было, нужно вручную поверх конфигурации добавить отступы через метод margins.
Пример настройки
contentConfiguration с нужными отступами:
func setup(with viewModel: DemoCollectionCellViewModel) {
if #available(iOS 16.0, *) {
contentConfiguration = UIHostingConfiguration {
SwiftUIView(viewModel: viewModel)
}.margins(.horizontal, 12) // <- вот тут задали отступы по горизонтали
} else {
setupOld(with: viewModel)
}
}
Весь код для демо-ячейки можно посмотреть в гитхабе.
Apple Developer Documentation
UIHostingConfiguration | Apple Developer Documentation
A content configuration suitable for hosting a hierarchy of SwiftUI views.
❤3🔥2
#ios #swift #swiftui #swiftdata #cloudkit #hint
Создали новое iOS-приложение с использованием Swift Data и CloudKit, но оно крашится после добавления контейнера?
Не беда!
На скриншоте исправление краша в только что созданном приложении, где включена галка
Все поля в моделях
Если оставить поле
При этом краша не будет, если снять галку с контейнера в настройках проекта 😐
Будет здорово, если в новом
Создали новое iOS-приложение с использованием Swift Data и CloudKit, но оно крашится после добавления контейнера?
Не беда!
На скриншоте исправление краша в только что созданном приложении, где включена галка
Host in CloudKit и добавлен ваш CloudKit Container.Все поля в моделях
Swift Data должны быть или опциональными, или иметь дефолтное значение.Если оставить поле
timestamp без дефолтного значения, будет краш:Thread 1: Fatal error: Could not create ModelContainer: SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer, _explanation: nil).При этом краша не будет, если снять галку с контейнера в настройках проекта 😐
Будет здорово, если в новом
Xcode появятся более прозрачные ошибки на этот случай (бету не ставил).🔥8
easy_dev991
#ios #swiftui #performance Убираем лишние вычисления body в SwiftUI View
#ios #swiftui #equatable
Наглядный пример использования протокола
Вьюха принимает на вход несколько свойств, и ни одно из них не изменяется при нажатии на кнопку "избранного" в навбаре, но по умолчанию вьюха обновляется при изменении этого
Все, что нужно было сделать для исправления проблемы:
Это первый случай, когда мне пригодился протокол
Наглядный пример использования протокола
Equatable, чтобы избавиться от лишних перерисовок вьюхи. На первом видео до исправления, на втором - после.Вьюха принимает на вход несколько свойств, и ни одно из них не изменяется при нажатии на кнопку "избранного" в навбаре, но по умолчанию вьюха обновляется при изменении этого
State-свойства на экране.Все, что нужно было сделать для исправления проблемы:
struct HTMLContentView: UIViewRepresentable, @preconcurrency Equatable {
static func == (lhs: HTMLContentView, rhs: HTMLContentView) -> Bool {
lhs.infopost == rhs.infopost && lhs.fontSize == rhs.fontSize
}
// остальной код
}
Это первый случай, когда мне пригодился протокол
Equatable с момента публикации статьи об этом, и все же он пригодился 👌🔥5❤2
This media is not supported in your browser
VIEW IN TELEGRAM
#ios #ios26 #swiftui #navigationview #bug #contest
Представляю вашему вниманию очередной баг iOS 26 при работе с
На iOS 26 экран автоматически закрывается при первом вызове любого из
Исправить ситуацию можно как минимум двумя способами, один из которых совсем простой, а второй чуть посложнее, но применяется в проекте во многих местах с другой целью.
--------
Позже напишу статью на эту тему, а пока что объявляю мини-конкурс: кто правильно назовет причину возникновения бага в iOS 26, тот молодец 🚀
Представляю вашему вниманию очередной баг iOS 26 при работе с
NavigationView, который отлично работает на всех версиях iOS, в том числе на iOS 26.На iOS 26 экран автоматически закрывается при первом вызове любого из
menu/picker/confirmationDialog, а вот код этого экрана, и там нет никаких ошибок, и чинить там нечего 🤦♂️Исправить ситуацию можно как минимум двумя способами, один из которых совсем простой, а второй чуть посложнее, но применяется в проекте во многих местах с другой целью.
--------
Позже напишу статью на эту тему, а пока что объявляю мини-конкурс: кто правильно назовет причину возникновения бага в iOS 26, тот молодец 🚀
🔥5
easy_dev991
#ios #swiftui #scrollview #scrollviewreader #scrollto Скроллим к нужному элементу
#ios #swiftui #scrollview #scrollto
На днях застрял со скроллом к нужному элементу и думал "что же не так?".
У меня есть список элементов в
Все оказалось очень просто - нужно явным образом добавить модификатор
Потом вспомнил, что у меня уже есть статья на эту тему 😁
На днях застрял со скроллом к нужному элементу и думал "что же не так?".
У меня есть список элементов в
ForEach, внутри массив с Identifiable-элементами, но scrollTo(id) не работает.Все оказалось очень просто - нужно явным образом добавить модификатор
.id для всех элементов в цикле ForEach. Потом вспомнил, что у меня уже есть статья на эту тему 😁
❤4😁4😴1