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.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Activity

Glitchy page transitions with TabView on watchOS
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
0
1
343
Sep ’24
Scale contextMenu preview size to containing content
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]) } ) } }
0
0
633
Sep ’24
NSRuleEditor only allow criterion row to be added once
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!
0
0
342
Sep ’24
SwiftUI Form (Grouped) with Table
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!
3
1
754
Sep ’24
ControlWidget Can't use onOpenURL
`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
2
0
548
Sep ’24
.redacted(reason:) modifier ignores .minimumScaleFactor?
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)
0
0
383
Sep ’24
Drag&Drop broken in iOS18.0?
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
1
0
351
Sep ’24
Setting value of NSSlider resets mouse cursor
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
0
0
329
Sep ’24
iOS App is crashing
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
1
0
306
Sep ’24
UIPrintInteractionController.shared on Mac OS Sonoma running iPad App
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.
10
0
3.0k
Sep ’24
Core Data : about newBackgroundContext()
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! 😊
0
0
274
Sep ’24
Core Data: Behavior of newBackgroundContext() and Parent-Child Relationships
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! 😊
0
0
535
Sep ’24
[UITextView becomeFirstResponder] crash with [__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]
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!
0
0
375
Sep ’24
UIDeferredMenuElement on MacCatalyst: closure called only once on first menu display
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?
1
0
462
Sep ’24
#Preview a Widget placeholder?
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?
1
0
572
Sep ’24
iOS 18 Control Widget Button won't open app
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!
1
0
1.1k
Sep ’24
UICardViewController does not load cells
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
3
0
279
Sep ’24
I have a question regarding UI hang issues when using CompositionalLayout. As the number of cells displayed on the screen increases, the UI becomes less responsive. Could you provide advice or solutions for optimizing performance in such cases?
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
3
0
306
Sep ’24