We're trying to implement transitions between TabView pages similar to what the Fitness app does on watchOS. As the user swipes or uses the Digital Crown to move between pages, the large rings gauge in the center transitions smoothly to a toolbar item. The code to implement this transition is described in two places in Apple's documentation:
https://developer.apple.com/documentation/watchos-apps/creating-an-intuitive-and-effective-ui-in-watchos-10 (See the section “Provide continuity with persistent elements”)
The WWDC23 session "Design and build apps for watchOS 10", around 9:30
However, copying the code from Apple's documentation doesn't give animation as reliable as what we're seeing in the Fitness app. Any slight reversal of motion causes the transition animation to jump back to the starting state. Has anyone else figured out how to replicate what the Fitness app is doing on watchOS?
I've included our View implementation below. Debug prints show what's going wrong: the page variable decrements immediately the user moves backward by any amount. But somehow, the Fitness app gets around this problem. How?
struct ContentView: View {
@Namespace var namespace
@State var page = 0
var body: some View {
NavigationStack {
TabView(selection: $page) {
globeView
.containerBackground(Color.blue.gradient, for: .tabView)
.navigationTitle("One")
.matchedGeometryEffect(
id: "globe",
in: namespace,
properties: .frame,
isSource: page == 0)
.tag(0)
Text("Page two")
.containerBackground(Color.green.gradient, for: .tabView)
.navigationTitle("Two")
.tag(1)
}
.tabViewStyle(.verticalPage)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
globeView
.matchedGeometryEffect(
id: "globe",
in: namespace,
properties: .frame,
isSource: page == 1)
}
}
}
}
@ViewBuilder
var globeView: some View {
Image(systemName: "globe")
.resizable()
.scaledToFit()
}
}
Thanks for any help!
—Chris
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi!
I have a multi-line string I'd like to display as text in a long-press preview (using .contextMenu). However, text after 3rd or 4th linebreak (\n) gets clipped. The intended effect is to have the minimum preview size that can fit all of the text.
Tried .frame(maxWidth: .infinity, maxHeight: .infinity) on Text() but it didn't have any effect. The only modifier that somewhat works is .containerRelativeFrame([.horizontal, .vertical]) but this gives the maximum preview size, instead of minimum. Any suggestions? TIA.
struct RedditView: View {
@State private var text = "AAAAAAAAAAAAAAAAAAAAAA?\n\nBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\nCCCCCCCCCCCCCCCCCCCCCCCCCC"
var body: some View {
Text("Long press this")
.frame(width: 300, height: 100)
.contentShape(.rect)
.border(Color.blue)
.contextMenu(menuItems: {
Button {
// do something
} label: {
Label {
Text("Edit")
} icon: {
Image(systemName: "pencil")
}
}
}, preview: {
Text(text)
// .frame(maxWidth: .infinity, maxHeight: .infinity)
.multilineTextAlignment(.center)
.padding()
//.containerRelativeFrame([.horizontal, .vertical])
}
)
}
}
I have an object that is an NSRuleEditorDelegate for an NSRuleEditor whose nestingMode is NSRuleEditorNestingModeList. There are 8 different possible criteria. Each criterion is optional but at least 1 is required (ruleEditor.canRemoveAllRows = NO). Each criterion should only be added once. How can I limit adding a criterion for a row if it is already in the editor at a different row?
Thanks!
Hi everyone,
I’m having an issue with a SwiftUI Table inside a Form in a macOS app. When the Form style is set to .grouped, the Table does not resize to the full width of the Form or Sheet. However, when I switch to a .plain style, it resizes correctly.
Here’s a simplified version of my code:
Section(header: Text("Header")) {
Table(data) {
TableColumn("Column 1", value: \.col1)
TableColumn("Column 2", value: \.col2)
// Add more columns as needed
}
.frame(height: 100)
}
}
.formStyle(.grouped) // Issue occurs only with this style
Has anyone else experienced this? Any workarounds or suggestions would be greatly appreciated!
Thanks!
`struct OpenMainAppIntent: AppIntent {
static let title: LocalizedStringResource = "OpenMainAppIntent"
static var openAppWhenRun: Bool = true
init() {}
@MainActor
func perform() async throws -> some IntentResult & OpensIntent {
guard let url = URL(string: "myapp://open") else {
throw OpenURLError.invalidURL
}
return .result(opensIntent: OpenURLIntent(url))
}
}
`
This is an action in my custom control widget, and i want to use this deeplink open my application and get the link's info, but it won't perform onOpenURL
`@main
struct TestControlWidgetApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
print("url: \(url)")
}
}
}
}`
Topic:
UI Frameworks
SubTopic:
General
While working with the Emoji Rangers Sample Code, I noticed that .redacted(reason:) seems to ignore the minimumScaleFactor() modifier - I have reproduced this behaviour with Xcode 16 and Xcode 16.1 beta 2 on iOS and on the Mac:
struct ContentView: View {
@State private var isRedacted: Bool = false
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
.font(.largeTitle)
Toggle("Redacted", isOn: $isRedacted)
}
.padding()
.minimumScaleFactor(0.1)
.redacted(reason: isRedacted ? .placeholder : .invalidated)
}
}
As long as the minimumScaleFactor does not kick in, redacted seems to work as expected:
But then it does not:
I tried changing the order of both modifiers with no effect. Wonder if this is expected and there is a way to make it work so it preserves the scaled down layout or a bug?
Filed just in case: FB15270541 (.redacted(reason:) modifier ignores .minimumScaleFactor)
In the app's Live Activity, Text (timerInterval:) is well displayed on Dynamic Island, but there seems to be a bug in Live Activity (Smart Stack in watchOS) that automatically transfers from iOS 18 to watchOS 11. Does anyone know about this?
Hi,
I've encountered the following phenomenon when comparing drag&drop in iOS 18.0 with iOS 17.5:
Let's say you have a small child view sitting on top of a larger parent view.
In iOS 18.0, when hovering over the child view with a drag object and leaving the child view, the child view will propagate a
"dropInteraction:sessionDidExit:" call to the UIDropInteractionDelegate of its parent view.
The parent view now thinks, that the drag object is moved away from it (which is not the case!) and in turn its delegate doesn't receive any "dropInteraction:performDrop:" calls anymore.
In iOS 17.5 this case is handled correctly (without "dropInteraction:sessionDidExit:" being propagated wrongly by child views to their parent views).
Is this change in behavior intended or is this a bug?
Topic:
UI Frameworks
SubTopic:
UIKit
Hi, in my macOS app I am modifying the mouse cursor image for some user interactions. I also have an NSSlider in the app which can be changed programmatically by setting its doubleValue. I've noticed that whenever the slider is set programmatically the custom mouse cursor is lost and changes back to an arrow. This doesn't happen if other controls are changed programmatically, e.g. the progress bar. Any ideas on how I can prevent this happening?
Topic:
UI Frameworks
SubTopic:
AppKit
My iOS app crashes, when kept idle in the background for sometime. Below is the detailed crash report.
Incident Identifier: 90DF0404-7A1D-4AF3-8892-19AB744DF0FD
Distributor ID: com.apple.AppStore
Hardware Model: iPhone13,3
Process: Runner [35073]
Path: /private/var/containers/Bundle/Application/894B2440-D20C-4C01-B278-A0DC4B199530/Runner.app/Runner
Identifier: com.era.tk
Version: 5.0.2 (5)
AppStoreTools: 15F31e
AppVariant: 1:iPhone13,3:15
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.era.tk [793]
Date/Time: 2024-09-25 13:17:31.3101 +0100
Launch Time: 2024-09-25 12:29:23.1866 +0100
OS Version: iPhone OS 17.6.1 (21G93)
Release Type: User
Baseband Version: 4.70.01
Report Version: 104
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000100c75e48
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [35073]
Triggered by Thread: 0
Thread 0 Crashed:
0 Runner 0x0000000100c75e48 0x100c2c000 + 302664
1 Runner 0x0000000100c75e80 0x100c2c000 + 302720
2 UIKitCore 0x00000001a7e937e8 -[UIViewController _setViewAppearState:isAnimating:] + 1224 (UIViewController.m:6441)
3 UIKitCore 0x00000001a80520b0 -[UIViewController __viewWillDisappear:] + 108 (UIViewController.m:6705)
4 UIKitCore 0x00000001a8602cec -[UINavigationController _startCustomTransition:] + 1476 (UINavigationController.m:2260)
5 UIKitCore 0x00000001a7e97400 -[UINavigationController _startDeferredTransitionIfNeeded:] + 496 (UINavigationController.m:8062)
6 UIKitCore 0x00000001a7efc248 -[UINavigationController __viewWillLayoutSubviews] + 96 (UINavigationController.m:8369)
7 UIKitCore 0x00000001a81be688 -[UILayoutContainerView layoutSubviews] + 172 (UILayoutContainerView.m:89)
8 UIKitCore 0x00000001a7da7918 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1528 (UIView.m:20054)
9 QuartzCore 0x00000001a720626c CA::Layer::layout_if_needed(CA::Transaction*) + 504 (CALayer.mm:10816)
10 QuartzCore 0x00000001a7205df0 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 148 (CALayer.mm:2598)
11 QuartzCore 0x00000001a7260fd8 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 464 (CAContextInternal.mm:2760)
12 QuartzCore 0x00000001a71d5ee0 CA::Transaction::commit() + 648 (CATransactionInternal.mm:432)
13 QuartzCore 0x00000001a721fc34 CA::Transaction::flush_as_runloop_observer(bool) + 88 (CATransactionInternal.mm:942)
14 UIKitCore 0x00000001a7e50ee8 _UIApplicationFlushCATransaction + 52 (UIApplication.m:3181)
15 UIKitCore 0x00000001a7e4e660 _UIUpdateSequenceRun + 84 (_UIUpdateSequence.mm:119)
16 UIKitCore 0x00000001a7e4e2a4 schedulerStepScheduledMainSection + 172 (_UIUpdateScheduler.m:1058)
17 UIKitCore 0x00000001a7e4f148 runloopSourceCallback + 92 (_UIUpdateScheduler.m:1221)
18 CoreFoundation 0x00000001a5b6b834 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 28 (CFRunLoop.c:1957)
19 CoreFoundation 0x00000001a5b6b7c8 __CFRunLoopDoSource0 + 176 (CFRunLoop.c:2001)
20 CoreFoundation 0x00000001a5b69298 __CFRunLoopDoSources0 + 244 (CFRunLoop.c:2038)
21 CoreFoundation 0x00000001a5b68484 __CFRunLoopRun + 828 (CFRunLoop.c:2955)
22 CoreFoundation 0x00000001a5b67cd8 CFRunLoopRunSpecific + 608 (CFRunLoop.c:3420)
23 GraphicsServices 0x00000001ea5b51a8 GSEventRunModal + 164 (GSEvent.c:2196)
24 UIKitCore 0x00000001a81a1ae8 -[UIApplication _run] + 888 (UIApplication.m:3713)
25 UIKitCore 0x00000001a8255d98 UIApplicationMain + 340 (UIApplication.m:5303)
26 Runner 0x0000000100c4e660 0x100c2c000 + 140896
27 dyld 0x00000001c933f154 start + 2356 (dyldMain.cpp:1298)
Topic:
UI Frameworks
SubTopic:
UIKit
After updating to Mac OS Sonoma, we have encountered compatibility issues with our iPad-designed application, specifically with the AirPrint functionality, when it is run on MacOS. The AirPrint feature stopped working properly through UIPrintInteractionController.shared.
We have noticed that when we compile the application using Catalyst, the AirPrint functionality is restored and works as expected. However, this solution is not viable for us due to the restrictions associated with the frameworks we are utilizing.
We are seeking alternative solutions, and any help or guidance would be highly appreciated to resolve this issue and ensure a seamless and uninterrupted user experience in our application.
STEPS TO REPRODUCE
Create an app for ipad with just a button and this code
var str = "TEST"
let printInfo = UIPrintInfo(dictionary:nil)
printInfo.outputType = .general
printInfo.jobName = "Report"
printInfo.orientation = .portrait
let printController = UIPrintInteractionController.shared
printController.printInfo = printInfo
printController.showsNumberOfCopies = false
printController.showsPageRange = false
printController.showsNumberOfCopies = false
let formatter = UIMarkupTextPrintFormatter(markupText: str)
formatter.contentInsets = UIEdgeInsets(top: 72, left: 72, bottom: 72, right: 72)
printController.printFormatter = formatter
printController.present(animated: true, completionHandler: nil)
2.Run it on a MacOS with Sonoma, there is no error on console or anything but it don't work.
-If you run it with Catalyst it just works when adding the Printing permission of App Sandbox in Signing & Capabilities.
Hi everyone,
I’m wondering about Core Data. When creating a private context using newBackgroundContext(), does it automatically set the parent to the view context, or is it independent? I'd appreciate it if anyone could clarify this for me.
Thanks in advance! 😊
Using just basic rule
.chartScrollableAxes(.horizontal)
.chartXVisibleDomain(length: 6)
Feature is working fine for iOS 17.x devices
Hi everyone,
I’m wondering about Core Data. When creating a private context using newBackgroundContext(), does it automatically set the parent to the view context, or is it independent?
Additionally, if I update objects in the context created by newBackgroundContext(), will the view context automatically notice the changes, and vice versa?
Lastly, are there other ways to set parent-child context relationships between contexts?
I'd appreciate it if anyone could clarify this for me.
Thanks in advance! 😊
I am trying to set my UITextView as the first responder with [self.textView becomeFirstResponder] when my view controller called viewDidAppear.
But sometimes it will cause crash with the error: [__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]
all I did is just:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.textView becomeFirstResponder];
}
So if anyone can tell me what happened and how to do? when I call the [self.textView becomeFirstResponder], what will be insert into the responders list? self.textView itself?
Thanks very much!
Hi folks, I'm struggling with an issue on MacCatalyst. I'm using a dynamic menu that is supposed to show the current state of a setting (state = .on / .off). The UIDeferredMenuElement works great on iOS, the closure is called on each display of the (context) menu.
On MacCatalyst however - where I use the menu as a submenu in the main menu - the closure is called only once on first menu display. The system seems to show a cached menu item even though I'm using UIDeferredMenuElement.uncached.
Here's the relevant code:
func getMenuElement() {
let element = UIDeferredMenuElement.uncached { completion in
let modeString = mode.myLocalizedDescription
let trackingMode = <current setting>
let mode = <menu item setting option>
let state = trackingMode == mode ? .on : .off
let action = UIAction(title: modeString,
image: <image>,
state: state) { _ in
viewController.setUserTrackingMode(mode)
}
completion([action])
}
return element
}
Any ideas how to trick the system into generating the dynamic menu item on each menu display?
While I am able to use #Preview to preview a Widget, it seems to be not possible to easily preview a Widget placeholder. With a "classic" preview I can use .redacted(reason: .placeholder), but this has limitation e.g. it will ignore .contentMarginsDisabled()
struct MyWidget_Previews: PreviewProvider {
static var previews: some View {
Group {
MyWidgetView(entry: SimpleEntry(date: .now, emoji: "😀"))
MyWidgetView(entry: SimpleEntry(date: .now, emoji: "😀"))
.redacted(reason: .placeholder)
}
.previewContext(WidgetPreviewContext(family: .systemMedium))
.containerBackground(.white, for: .widget)
}
}
If I use #Preview, the .redacted modifier won't work, and I seem to have to put it in the MyWidget implementation.
#Preview(as: .systemMedium) {
MyWidget()
} timeline: {
SimpleEntry(date: .now, emoji: "😀")
SimpleEntry(date: .now, emoji: "🤩")
}
Am I missing something?
XCode Version 16.0 (16A242d)
iPhone 12 - iOS 18 (22A3354)
Macbook Air M1 - Sonoma 14.6.1
I am currently working on building Control Buttons for our app and I have consistently run into the same issue:
Unknown NSError The operation couldn’t be completed. (LNActionExecutorErrorDomain error 2018.)
This error can be found in the following posts:
Apple Developer Forums - Post 1
Apple Developer Forums - Post 2
Apple Developer Forums - Post 3
StackOverflow - Post 4
Github - Post 5
I've tried every single solution recommended within these posts, however nothing has worked successfully so far.
Additionally, I've tried the using .widgetUrl() on the Label() within the ControlWidgetButton like so:
ControlWidgetButton(action: JournalControlIntent()) {
Label("Open App", systemImage: "pencil.line")
.widgetURL(URL(string: "app://control/page"))
}
But this did not work either.
Using the recommended approach to open the app as seen here:
https://developer.apple.com/documentation/widgetkit/creating-controls-to-perform-actions-across-the-system#Open-your-app-with-a-control
simply won't work since we have a Flutter app with deep linking setup. Meaning the only option is launching either a deep link or universal link. Our URL scheme is setup correctly since it's currently working for our iOS Widgets & Shortcuts(which use widgetURL & openURL).
In Post 3, the accepted answer mentions that the control file must have the Target Membership with the App and Widget Targets to work. When I try using this solution the build fails without any errors(until you run it in VSCode where there are many errors about Derived Data - Deleting the derived data doesn't fix this error)
I'm wondering if I have added the Control Widget to the incorrect folder within my XCode project? Since if you use the approach of creating a Control through XCode(File > New > Target > Widget Extension > "Include Control" > Next) it creates a top level directory in the project similar to a Stickers or Watch extension.
My Control Widgets currently reside in the [App] Widgets > Control Buttons > Control Button.swift. It's then added to my main widget definition(App Widget > App_Widget.swift):
@main
struct App_Widget: WidgetBundle {
var body: some Widget {
App_Widget() // works
App_Widget_One() // works
if #available(iOSApplicationExtension 18.0, *) {
ControlButtonOne() // does not open app
ControlButtonTwo() // does not open app
}
}
}
Thank you for your help and time!
I am making an IOS application using XCode Storyboard.
I have a UICollectionViewController in the following structure
UIViewController -> UIView -> UITabBarController -> UICollectionViewController
The app loads without crashing, and UICollectionViewController.viewDidLoad() and .numberOfSections() execute correctly.
But anything that I put in
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)
does not seem to execute. Once the app loads, no cells load. And any print statement in the function doesn't execute either.
All elements have their corresponding class correctly assigned in the Storyboard Identity Inspector, and the cells have the correct reusable identifier.
How can I make it work correctly?
My Collection View Controller:
class ValidCardsCollectionViewController: UICollectionViewController {
let dataSource: [String] = ["hearts", "clubs", "diamonds", "spades"]
override func viewDidLoad() {
super.viewDidLoad()
print(dataSource)
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
print("Loading \(dataSource.count) cells")
return dataSource.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell = UICollectionViewCell()
if let cardCell = collectionView.dequeueReusableCell(withReuseIdentifier: "CardCell", for: indexPath) as? CardCollectionViewCell{
cardCell.configure(with: dataSource[indexPath.row])
cell = cardCell
}
print("loading cell")
return cell
}
My UICollectionViewCell:
class CardCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var lblStr: UILabel!
func configure(with str:String){
lblStr.text = str
}
}
Storyboard layout:
Simulator:
Topic:
UI Frameworks
SubTopic:
UIKit
We are currently combining AutoLayout and StackView to structure our cells, and we’re using UICollectionViewCompositionalLayout to set up sections. Additionally, we’re utilizing UICollectionViewDiffableDataSource to manage the data source. On the home screen, we display cells in a multi-section layout.
In the main screen, we support infinite scrolling and use a paging method that fetches 10 items at a time from the API. As we fetch and render more data, the number of displayed cells increases. However, we’ve noticed that as the number of displayed cells grows, the UI freezes during the process of fetching and rendering more data.
We suspect that the issue lies in the configuration of UICollectionViewCompositionalLayout. When data is fetched through paging, the data is applied to the CollectionViewDiffableDataSource, and during the process of displaying it on the screen, the method that configures the UICollectionViewCompositionalLayout layout is called. The problem here is that when 10 cells are displayed on the screen and we fetch more data through paging and add 10 more cells, the layout calculation is redone for all 20 cells. In other words, the UICollectionViewCompositionalLayout layout configuration occurs a total of 20 times.
Because of this, it seems that the UI freezing issue occurs as the number of cells increases.
What steps can we take to resolve this problem? We have attached the relevant code for your reference.
private lazy var collectionView = UICollectionView(
frame: .zero,
collectionViewLayout: self.createCollectionViewLayout()
)
private func createCollectionViewLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { [weak self] sectionIndex, _ in
guard let self, self.dataSource.snapshot().sectionIdentifiers.isEmpty == false
else { return LayoutProvider.emptySection() }
private func applyRefreshSnapshot(with sections: [PlateViewSection]) {
var snapshot = self.dataSource.snapshot()
snapshot.deleteAllItems()
snapshot.appendSections(sections)
sections.forEach { section in
snapshot.appendItems(section.items, toSection: section)
}
self.dataSource.apply(snapshot, animatingDifferences: false)
}
let sectionIdentifier = self.dataSource.snapshot().sectionIdentifiers[safe: sectionIndex]
let analyticsScreen = self.payload.analyticsScreen
switch sectionIdentifier?.module {
case let .tabOutlined(_, reactor):
if self.tabOutlinedView == nil {
let tabOutlinedView = self.dependency.tabOutlinedViewFactory.create(
payload: .init(
reactor: reactor,
collectionView: self.collectionView,
analyticsScreen: analyticsScreen,
currentDisplayDepthObserver: .init { event in
guard let depth = event.element else { return }
self.currentLayoutHeaderTabDepth = depth
},
selectedTabItemObserver: .init { [weak self] event in
guard let (tab, isPrimaryTabClick) = event.element else { return }
var queryParams: [String: String]?
if isPrimaryTabClick == false {
guard let currentState = self?.reactor?.currentState else { return }
let currentSelectedQueryParams = self?.dependency.userDefaults
.dictionary(forKey: Keys.PlateParamsKeys.brandQueryParams) as? [String: String]
queryParams = currentSelectedQueryParams ?? currentState.defaultQueryParams
}
self?.scrollCollectionViewToTop()
self?.collectionView.viewWithTag(
QueryToggleModuleCell.Metric.optionsMenuViewTag
)?.removeFromSuperview()
self?.reactor?.action.onNext(.refreshWithParams(
tabParams: tab?.params,
queryParams: queryParams
))
}
)
)
self.view.addSubview(tabOutlinedView)
tabOutlinedView.snp.makeConstraints { make in
make.top.leading.trailing.equalToSuperview()
}
self.view.layoutIfNeeded()
self.tabOutlinedView = tabOutlinedView
self.tabOutlinedView?.emitInitializeAction()
}
return LayoutProvider.emptySection()
case let .carouselOneRowBrand(module, _):
let section = self.dependency.layoutProvider.createLayoutSection(module: module)
section.visibleItemsInvalidationHandler = { [weak self] _, _, _ in
guard let self else { return }
self.emitFetchLikedAction(module: module, sectionIndex: sectionIndex)
}
return section
case let .queryToggle(module):
return self.dependency.layoutProvider.createLayoutSection(module: module)
case .loadingIndicator:
return LayoutProvider.loadingIndicatorSection()
case let .space(module):
return self.dependency.layoutProvider.createLayoutSection(module: module)
case let .noResult(module):
return self.dependency.layoutProvider.createLayoutSection(module: module)
case let .buttonViewAll(module):
return self.dependency.layoutProvider.createLayoutSection(module: module)
case .footer:
return LayoutProvider.footerSection()
default:
return LayoutProvider.emptySection()
}
}
return layout
}
private func applyAppendSnapshot(with sections: [PlateViewSection]) {
var snapshot = self.dataSource.snapshot()
// loadingIndicator section delete
let sectionsToDelete = snapshot.sectionIdentifiers.filter { section in
section.module == .loadingIndicator
}
snapshot.deleteSections(sectionsToDelete)
snapshot.appendSections(sections)
sections.forEach { section in
snapshot.appendItems(section.items, toSection: section)
}
self.dataSource.apply(snapshot, animatingDifferences: false)
}
Topic:
UI Frameworks
SubTopic:
UIKit