SwiftUI dev
1.17K subscribers
87 photos
37 videos
1 file
74 links
Mobile development, SwiftUI, Compose, feel free to reach me: @lexkraev
Download Telegram
SwiftUI dev pinned «Meet async/await in Swift https://developer.apple.com/videos/play/wwdc2021/10132/ ❗️Главное: 1. Async/await существенно сокращает код, позволяет не думать о всех случаях в замыканиях 2. ⚙️ Принцип работы строится на следующем: если синхронная процедура возвращает…»
SwiftUI dev pinned «Discover concurrency in SwiftUI https://developer.apple.com/videos/play/wwdc2021/10019/ Рассмотрим следующий код: class Photos: ObservableObject { @Published var items: [Photos] = [] func updateItems() { let fetched = fetchPhotos() items = fetched…»
SwiftUI dev pinned «Protect mutable state with Swift actors https://developer.apple.com/videos/play/wwdc2021/10133/ 1️⃣ Обзор на сессию выложу в виде последовательных постов (номер по порядку смотрите в начале поста), так как инфы оч много, а тема достаточно интересная и нетрививальная.…»
SwiftUI dev pinned a file
This media is not supported in your browser
VIEW IN TELEGRAM
Наглядный пример, почему Apple депрекэйтнула модификатор .animation с одним параметром (типом анимации): из-за некорректной отрисовки самой анимации, SUI не понимает, на какое именно событие анимировать. 👇🏻

#readthis
SwiftUI dev
Наглядный пример, почему Apple депрекэйтнула модификатор .animation с одним параметром (типом анимации): из-за некорректной отрисовки самой анимации, SUI не понимает, на какое именно событие анимировать. 👇🏻 #readthis
Рассмотрим, код:

Предположим, хотим сделать zoom-zoom анимацию при тапе на кнопку. Для этого сделаем модификатор:

public struct ScaleButtonStyle: ButtonStyle {
public init() {}

public func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.scaleEffect(configuration.isPressed ? 0.95 : 1)
.animation(.linear(duration: 0.2))
.brightness(configuration.isPressed ? -0.05 : 0)
}
}

public extension ButtonStyle where Self == ScaleButtonStyle {
static var scale: ScaleButtonStyle {
ScaleButtonStyle()
}
}


Далее применим этот модификатор для отрисовки элемента в горизонтальном Lazy стэке:

ScrollView(.horizontal, showsIndicators: false) {
LazyHStack {
ForEach(data, id: \.self) { card in
Button {

} label: {
VStack(alignment: .leading
) {
AsyncImage(…)
.resizable()
.frame(width: elementSize.width, height: elementSize.height)
.cornerRadius(8)

Text(…)
.boldFont(…)
.foregroundColor(…)
}
}
.buttonStyle(ScaleButtonStyle())
}
}


В итоге получаем представленный баг: некорректная анимация на onAppear в lazy стеке. Фиксим путем добавления value в .animation, тем самым указывая конкретное значение для отслеживания изменений.

public struct ScaleButtonStyle: ButtonStyle {
public init() {}

public func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.scaleEffect(configuration.isPressed ? 0.95 : 1)
.animation(.linear(duration: 0.2), value: configuration.isPressed)
.brightness(configuration.isPressed ? -0.05 : 0)
}
}


#readthis
База знаний про SwiftUI, собранная в одном месте

SwiftUI knowledge based in one place

#readthis
SwiftUI dev pinned «База знаний про SwiftUI, собранная в одном месте SwiftUI knowledge based in one place #readthis»
Сделал package для добавления swipe-меню на любое View для iOS 13.0 (Apple-овский аналог доступен только для List, начиная с iOS 15.0)

Made the package for creating swipe actions for any SwiftUI View, similar to Apple's swipeActions(edge:allowsFullSwipe:content:) that available from iOS 15 and only in List 🤷🏼‍♂️. You can use SwipeActions in project targeting iOS 13 with any view (for ex. Text in VStack)

#swiftpm #getsources
Must-have SUI-frame extension

Весьма удобные модификаторы, позволяющие избегать Spacer() и .frame(). Взял у Kavsoft :)
Забрать можно отсюда

Useful modifiers to avoid Spacer() and .frame(). Check out here.

#howto #getsources
SwiftUI dev pinned a photo
List vs LazyVStack

Что лучше использовать и когда?
Зависит, конечно, от поставленной задачи. Например, если приложение на UIKit, и хотите подтянуть SwiftUI, то необходимо учитывать, что разделители у ячеек в List, если они не нужны, до iOS 15 убираются весьма костыльным способом:
.onAppear {
UITableView.appearance().separatorStyle = .none
}

Тем самым можно зааффектить дизайн UITableView во всем приложении. В iOS 15 для этого уже появился специальный модификатор .listRowSeparator(.hidden).

Но, на мой взгляд, ключевой особенностью является рендеринг у List и LazyVStack, который отличается в зависимости от версий iOS. В iOS < 15 List рендерит ячейки “с запасом”, а именно, если List растянут на весь экран, то ленивой загрузки нет у первых 15 (iPhone 6s) - 20 элементов, при этом без разницы, какая высота фрейма у элемента. Напротив, LazyVStack рендерит только те элементы, которые видны на экране. Таким образом, например, вешая модификатор .onAppear{…}, мы получаем ожидаемое поведение только у LazyVStack.
Начиная с iOS 15, List рендерит уже только элементы, видимые на экране. Получается, что пагинацию на List для iOS < 15 можно сделать только, если загружать > 20 элементов. Это не всем может подойти, в приоритете окажется LazyVStack.

Which one is best to use and when?
It depends, of coz, on the task. For ex, if the app based on on UIKit, and you want to add SwiftUI, then you should be considered that the separators between cells in the List, if they are not needed, are removed in a very “crutch” way before iOS 15:
.onAppear {
UITableView.appearance().separatorStyle = .none
}

This can affect the design of the UITableView throughout the whole application. Beginning with iOS 15 a special modifier .listRowSeparator(.hidden) has already appeared for this.

Imho the key feature is the difference in the rendering (which depend on iOS versions) of List and LazyVStack. In iOS < 15 List renders cells “with a margin”, namely, if the List is stretched to full screen, then the first 15 (iPhone 6s) - 20 elements do not have lazy loading, and it doesn’t matter what the element’s frame height is. Opp. LazyVStack renders only elements that are visible on the screen. Thus, for ex, by setting the .onAppear{…} modifier, we get the expected behavior only for LazyVStack.
Beginning with iOS 15 List renders only items that are visible on the screen. Turns out that in iOS < 15 using List pagination can only be done if you should load > 20 items. This may not suit for everyone and LazyVStack should be used.

#readthis
Статья про базовые протоколы в SwiftUI

Nice article about main protocols in SwiftUI

#readthis
This media is not supported in your browser
VIEW IN TELEGRAM
У LazyVGrid отсутствует возможность объединения столбцов.
Сделал пример, как можно это реализовать

LazyVGrid does not have a column span feature.
This tutorial demonstrate how we could implement it easily.

#howto #getsources
This media is not supported in your browser
VIEW IN TELEGRAM
Сделал package с примером реализации показа всплывающих окон/alert-ов/popover-ов/sheet-ов из любого места в приложении на SwiftUI.
Перед просмотром советую освежить в памяти про EnvironmentValues и прочитать эту статью.

Made a package with an example of the implementation of showing pop-up windows / alerts / popovers / sheets from anywhere in the application on SwiftUI.
Before watching, I advise you to refresh in memory for EnvironmentValues and read this article.

#swiftpm #getsources