easy_dev991
605 subscribers
22 photos
16 videos
3 files
159 links
Делюсь интересными находками/лайфхаками в процессе разработки под iOS, и возможно ты найдешь что-то полезное для себя!

GitHub: https://github.com/easydev991
Download Telegram
#ios #swift #swiftui #maps #geocoding #hint

На прошлой неделе заметил, что релиз 3.10 приложения с площадками стал сильно греть телефон, и даже в статистике аккумулятора спустя всего 10 минут использования мое приложение было первым в списке по потреблению энергии 🙈

В том релизе я сделал много классных штук, и в том числе немного обновил старый код для работы с картой, в результате нагрузка на девайс выросла в разы.

На днях выпустил релиз с исправлением этих проблем, и вот главные выводы:

1️⃣ Если нужно получить локацию пользователя с использованием CLLocationManager, то лучше не использовать startUpdatingLocation(), а просто вызывать requestLocation() по таймеру, например раз в 10 секунд - нагрузка ощутимо упадет

2️⃣ Использовать reverseGeocodeLocation нужно не чаще раза в минуту, а лучше еще реже - если координаты ощутимо изменились (на 50 метров, например), и это точно нужно для правильной работы фичи

3️⃣ Если используете MKMapView внутри SwiftUI-обертки, то напишите явную проверку в методе updateUIView, чтобы обновление карты выполнялось только тогда, когда это 100% нужно - я для этого сделал флаг shouldUpdateRegion и передаю его в карту, а в методе updateUIView вызываю замыкание при обновлении карты, чтобы снять флаг
🔥52
easy_dev991
#ios #swift #swiftui #maps #geocoding #hint На прошлой неделе заметил, что релиз 3.10 приложения с площадками стал сильно греть телефон, и даже в статистике аккумулятора спустя всего 10 минут использования мое приложение было первым в списке по потреблению…
Любопытный момент: вот эти правки снизили потребление процессора почти до нуля во время работы приложения.

Я уже и не помню, почему вообще решил до этого сделать NetworkMonitorActor, хотя можно было использовать стандартный AsyncIterator 🙈

Зато в следующем релизе приложение будет потреблять минимум энергии ✔️
3
#ios #uitest #xctest #bug #hint

Любопытный момент: оба скриншота сделаны при запуске одного и того же UI-теста, но внимательный глаз заметит разницу - слева у приложения accentColor синий, т.е. дефолтный, а справа - черный (такой и должен быть).

Не заметил, в какой момент тесты сломались и перестали уважать настройку accentColor в assets, но вот фикс этой проблемы:


WindowGroup {
RootScreen()
.tint(.accent) // <- исправляет accentColor в тестах
}


Еще раз повторю, что в обычном режиме работы приложение корректно распознает accentColor, и только в режиме UI-тестов нужен фикс.
4👍2
#ios #automation #fastlane

Я уже рассказывал как мне нравится Xcode Cloud для публикации сборок - минимум настроек, все работает хорошо.

Вчера настроил публикацию скриншотов в пет-проекте с использованием fastlane, и выключил воркфлоу в Xcode Cloud, потому что:

⚠️ Он работает медленно - сборка на ноуте (с fastlane) занимает меньше минуты, а в облаке это растягивается на 5 минут
⚠️ Для публикации скриншотов в любом случае нужно или делать ручную работу, или запустить fastlane

Теперь про публикацию скриншотов через fastlane
Для наглядности вот логи:

[18:40:04]: Driving the lane 'ios upload_screenshots' 🚀
...
[18:40:09]: Starting with the upload of screenshots...
[18:40:11]: Deleted 'ru APP_IPAD_PRO_3GEN_129' - (0.814763 secs)
[18:40:11]: Deleted 'en-US APP_IPHONE_67' - (0.814563 secs)
[18:40:11]: Deleted 'ru APP_IPHONE_67' - (0.837923 secs)
[18:40:11]: Deleted 'en-US APP_IPAD_PRO_3GEN_129' - (0.915516 secs)
[18:40:12]: Number of screenshots not deleted: 0
[18:40:12]: Successfully deleted all screenshots
...
[18:40:17]: Uploaded './fastlane/screenshots/ru/iPhone 15 Pro Max-1-[18:40:21]: Uploaded './fastlane/screenshots/ru/iPhone 15 Pro Max-3-sortByDate.png'... (3.672329 secs)
[] Waiting for all the screenshots to finish being processed...
[18:40:28]: Successfully uploaded all screenshots
[] Sorting screenshots uploaded...
[18:40:29]: Successfully uploaded screenshots to App Store Connect


Итого: с момента запуска команды до окончания публикации и сортировки скриншотов прошло 26 секунд - это намного быстрее, чем вручную публиковать скриншоты для двух локализаций на iPad/iPhone, еще и в правильном порядке.
В appstoreconnect для сохранения нужного порядка отображения скриншотов приходится загружать картинки по одной в желаемом порядке🙈

Теперь важные нюансы.

1️⃣ Несмотря на возможность вручную загрузить скриншоты для нужных диагоналей с самых новых девайсов (iPhone 16 Pro Max, iPad M4), fastlane так не может - нужно делать скриншоты на других девайсах, подробнее написал в ридми.
Если попытаться загрузить скриншоты для 16 Pro Max и iPad M4, будут ошибки типа таких:

[16:44:44]: 🚫 Invalid screenshots were detected! Here are the reasons:
[16:44:44]: 🚫 Error: ./fastlane/screenshots/en-US/iPad Pro 13-inch (M4)-1-demoList.png - Invalid screen size (Actual size is 2064x2752. See the specifications to fix https://help.apple.com/app-store-connect/#/devd274dd925)
...
[16:44:44]: 🚫 Error: ./fastlane/screenshots/ru/iPhone 16 Pro Max-3-sortByDate.png - Invalid screen size (Actual size is 1320x2868. See the specifications to fix https://help.apple.com/app-store-connect/#/devd274dd925)

Да, я прочитал документ по ссылке из логов с ошибкой, и я нашел там iPhone 16 Pro Max + iPad Pro (M4), но fastlane не может их опубликовать 🤔

2️⃣ Если ваш аккаунт связан с несколькими командами разработки, то при настройке fastlane нужно явно указать идентификатор команды в поле itc_team_id, пример есть в Appfile - даже если вы не знаете идентификатор, то при первом запуске команды для публикации скриншотов fastlane сам предложит выбрать команду, там и можно скопировать идентификатор и поставить в Appfile.

3️⃣ По умолчанию fastlane делает много всего в команде upload_to_app_store, и лучше сразу выключить лишнее, например, публикацию бинарного файла приложения, запуск precheck перед отправкой и т.д., более подробно про все эти настройки можно почитать в официальной документации к fastlane.

4️⃣ Лучше сразу настроить overwrite_screenshots на true, чтобы после загрузки новых скриншотов не приходилось вручную удалять старые.

Готовый fastfile можно посмотреть в гитхабе.
🔥3
#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: "test@example.com"),
.init(label: "Телефон", value: "+79123456789"),
.init(
label: "Адрес",
value: "117513, г. Москва, ул. Профсоюзная, д. 129, корп. 3, кв. 117, подъезд 5, этаж 8"
)
]


Кто первый сделает, тот молодец 🚀
👌3
#ios #swift #swiftui #hint

На днях добавлял SwiftUI-вьюху внутрь UIKit-ячейки для экрана с коллекцией.
Вьюха просто принимает на вход данные и показывает что-то внутри себя.

⚠️Но есть нюанс: на iOS < 16 нельзя просто так добавить SwiftUI-вьюху в ячейку - для этого нужно делать костыль с хостингом и т.д.

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

На этом экране еще и кнопка есть для скролла к той самой ячейке - и при первом скролле к ней она выглядит плохо.

Решается эта проблема очень просто - можно добавить вьюхе два состояния: "загрузка" и "готово".
В "загрузке" показываем любой принятый в проекте индикатор загрузки или скелетон, а в "готово" - обычное состояние вьюхи.
Ну и в саму вьюху внутрь onAppear добавляем смену состояний.

Теперь при первом рендере этой ячейки появится индикатор загрузки, а потом сразу корректное состояние.
2🔥1
#ios #swift #swiftui #contest

Субботний челлендж по знанию SwiftUI 🤓

Во вложении два варианта анимации разворачивания и сворачивания секции.

Нужно реализовать целевое поведение.
Задача очень простая, если знать как делать 😁

Код для старта тут.

Кто первый, тот молодец 🚀
👀3👍2
#ios #appstore #appstoreconnect

Опубликовал приложение с площадками для воркаута под своим аккаунтом, т.к. отключили Xcode Cloud для РФ и я не мог больше обновлять приложение на аккаунте владельца сайта workout.su.

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

Решил попробовать сначала отправить приложение на проверку, и не удалять старое приложение.

В результате получил временный бан от эпол в appstoreconnect, и они запросили мои документы (уже в третий раз за год).
Отправил им документы, бан сняли, как и в прошлые разы.

При этом завернули новое приложение по причине Spam 😁
Там перечисляли, что у меня и дизайн копирует существующее приложение, и код, и вообще полный дубликат.

Спросил их, можно ли опубликовать новое приложение после удаления старого - сказали можно.

Согласовал с владельцем сайта удаление старого приложения, удалил его, и теперь могу обновлять приложение уже в своем аккаунте в максимально удобном формате (через fastlane).
3🔥1