Construct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.

UIKit Documentation

Post

Replies

Boosts

Views

Activity

Crash in iOS18
I have a UITableView which contains a UICollectionView in the first row. It used to work fine in iOS17, but now I get a crash when running with Xcode 16 / iOS18 beta: Expected dequeued view to be returned to the collection view in preparation for display. When the collection view's data source is asked to provide a view for a given index path, ensure that a single view is dequeued and returned to the collection view. Avoid dequeuing views without a request from the collection view. For retrieving an existing view in the collection view, use -[UICollectionView cellForItemAtIndexPath:] or -[UICollectionView supplementaryViewForElementKind:atIndexPath:] This is my UITableView delegate call: AddEditDataCell *cell = nil; if (indexPath.section == 0) { if (indexPath.row == 0) { AddEditDataContactsCell *contactNameCell = (AddEditDataContactsCell *)[self cellForContactNamesCollectionAtIndexPath:indexPath tableView:tableView]; return contactNameCell; - (AddEditDataContactsCell *)cellForContactNamesCollectionAtIndexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView { AddEditDataContactsCell *contactsCell = (AddEditDataContactsCell *)[self.tableView dequeueReusableCellWithIdentifier:@"ContactsCell" forIndexPath:indexPath]; if (self.collectionNameCell == nil) { self.collectionNameCell = [contactsCell.collectionView dequeueReusableCellWithReuseIdentifier:@"LogContactNameCollectionCellIdentifier" forIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; contactsCell.nameCellDelegate = self; } contactsCell.frame = CGRectZero; [contactsCell setNeedsLayout]; [contactsCell.collectionView reloadData]; contactsCell.collectionViewHeightConstraint.constant = contactsCell.collectionView.collectionViewLayout.collectionViewContentSize.height; [contactsCell.collectionView.collectionViewLayout invalidateLayout]; return contactsCell; }
21
18
12k
Jun ’24
ios 18 Crash
My project use manual reference counting and crash with UIAlertController when touch to Action Button: UIAlertController alert = [[UIAlertController alertControllerWithTitle:@"fsđs" message:@"fsđs" preferredStyle:UIAlertControllerStyleAlert ]autorelease]; UIAlertAction actionOk = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil]; [alert addAction:actionOk]; [self.window.rootViewController presentViewController:alert animated:YES completion:^{ }];
2
1
470
Sep ’24
How to remove antialiasing in CGContext?
I'm trying to create a brush by drawing in CGContext using a UIImage for a brush. However, I when I try drawing, the stroke is antialiased when I don't want it to be. I tried context.interpolationQuality = .none context.setShouldAntialias(false) but it doesn't seem to work. Is it a problem with my brush or resizing the brush maybe?? (Also this problem doesn't occur when I draw a regular stroke without the brush.) Any help or advice would be greatly appreciated! Here is my draw function override func draw(_ rect: CGRect) { super.draw(rect) guard let context = UIGraphicsGetCurrentContext() else { return } context.interpolationQuality = .none context.setShouldAntialias(false) for stroke in strokes { let brush = UIColor.blue.circle(size: CGSize(width: CGFloat(stroke.width * 10), height: CGFloat(stroke.width * 10))).mask(color: UIColor(cgColor: stroke.color)) var first = true for point in stroke.points { if first { first = false context.move(to: point) continue } context.addLine(to: point, using: brush) } } } Circle brush extension UIColor { func circle(size: CGSize = CGSize(width: 1, height: 1)) -> UIImage { return UIGraphicsImageRenderer(size: size).image { rendererContext in self.setFill() UIBezierPath(ovalIn: CGRect(origin: .zero, size: size)).fill() } } } CGConext extension where I overloaded addLine extension CGContext { func addLine(to point: CGPoint, using brush: UIImage, density: CGFloat = 1.0) { var frame: CGRect = .zero frame.size = brush.size let lastPoint = self.currentPointOfPath let distanceX = point.x - lastPoint.x let distanceY = point.y - lastPoint.y let distanceR = sqrt(pow(distanceX, 2) + pow(distanceY, 2)) let deltaR = (1.0 / density) let numOfSteps = ceil(distanceR / deltaR) var renders : CGFloat = 0.0 let deltaX = distanceX / numOfSteps let deltaY = distanceY / numOfSteps var currentCenter = lastPoint repeat { frame.origin.x = currentCenter.x - frame.width / 2.0 frame.origin.y = currentCenter.y - frame.height / 2.0 brush.draw(in: frame) currentCenter.x += deltaX currentCenter.y += deltaY renders += 1.0 } while (renders <= numOfSteps) self.move(to: point) } }
4
0
250
Oct ’24
How to get UIFont to respect preferredContentSizeCategory in a Mac Catalyst app?
I have an iOS app that relies on dynamic text size such that all fonts in the app respect the user's setting of Text Size in the iOS Settings app. This app also runs on macOS via Mac Catalyst. But until macOS 14 Sonoma, there was no Text Size setting in the macOS Settings app. But even as of Sonoma, the Text Size setting isn't usable by 3rd party apps. And Sequoia doesn't seem to change that. As a work around, my Mac Catalyst app provides its own Text Size setting. I was able to make it work by providing my own UIApplication subclass and overriding preferredContentSizeCategory. Under macOS 12 to macOS 14, this workaround works just fine and all fonts in the app created with code such as UIFont.preferredFont(forTextStyle:) gives appropriately sized fonts based on the overridden content size category. However, this workaround stopped working with macOS 15 Sequoia. I've also tried code such as: self.window.traitOverrides.preferredContentSizeCategory = myCustomSizeCategoryValue and self.window.maximumContentSizeCategory = myCustomSizeCategoryValue self.window.minimumContentSizeCategory = myCustomSizeCategoryValue in the scene delegate but that made no difference. Is there any way to get code such as UIFont.preferredFont(forTextStyle:) to return an appropriately sized font based on some app provided content size category in a Mac Catalyst app running under macOS 15? It sure would be nice if Mac Catalyst apps automatically responded to the macOS Text Size setting under Settings -> Accessibility -> Display -> Text Size just like a native iOS app.
2
0
295
Oct ’24
UIViewRepresentable animations
I've tried to animate custom UIViewRepresentable with SwitfUI animations, but it doesn't work. It just sets value without interpolation. What should i do to use interpolation values in UIKit views? My example shows two "progress bars" red one is UIKit view, blue one is SwiftUI version. Sliders controls value directly, randomize button changes value to random with 5s animation. When I press button SwiftUI progress bar animates exactly as it should, but UIKit's one just jumps to final position. Set block of animatableData inside Animatable extension not called. How can I use SwiftUI animation value interpolations for UIKit? import SwiftUI import UIKit class UIAnimationView: UIView { var progress: CGFloat = 0.5 { didSet { if self.progressConstraint != nil, self.innerView != nil { self.removeConstraint(self.progressConstraint!) } let progressConstraint = NSLayoutConstraint( item: innerView!, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: min(1.0, max(0.0001, progress)), constant: 0 ) self.addConstraint(progressConstraint) self.progressConstraint = progressConstraint self.layoutIfNeeded() } } var innerView: UIView? private var progressConstraint: NSLayoutConstraint? public override init(frame: CGRect) { super.init(frame: frame) self.performInit() } public required init?(coder: NSCoder) { super.init(coder: coder) self.performInit() } private func performInit() { let innerView = UIView() innerView.translatesAutoresizingMaskIntoConstraints = false self.addSubview(innerView) self.leadingAnchor.constraint(equalTo: innerView.leadingAnchor).isActive = true self.topAnchor.constraint(equalTo: innerView.topAnchor).isActive = true self.bottomAnchor.constraint(equalTo: innerView.bottomAnchor).isActive = true let progressConstraint = NSLayoutConstraint( item: innerView, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: progress, constant: 0 ) self.progressConstraint = progressConstraint self.addConstraint(progressConstraint) self.innerView = innerView self.innerView!.backgroundColor = UIColor.red self.backgroundColor = UIColor.black } } struct AnimationTest: UIViewRepresentable { var progress: CGFloat typealias UIViewType = UIAnimationView func updateUIView(_ uiView: UIAnimationView, context: Context) { print("progress: \(progress) \(context.transaction.isContinuous)") uiView.progress = progress } func makeUIView(context: Context) -> UIAnimationView { let view = UIAnimationView() view.progress = progress return view } } extension AnimationTest: Animatable { var animatableData: CGFloat { get { return progress } set { print("Animation \(newValue)") progress = newValue } } } struct AnimationDebug: View { @State var progress: CGFloat = 0.75 var body: some View { VStack { AnimationTest(progress: progress) Spacer() VStack { Slider(value: $progress, in: 0...1) { Text("Progress") } } GeometryReader { gr in Color.blue .frame( width: gr.size.width * progress, height: 48) } .frame(height: 48) Button("Randomize") { withAnimation(Animation.easeInOut(duration: 5)) { progress = CGFloat.random(in: 0...1) } } } } } struct AnimationTest_Previews: PreviewProvider { static var previews: some View { AnimationDebug() } }
2
0
1.2k
Jun ’23
SF font licensing in iOS
There's been an article where it says Apple/iOS apps can use the FONT_FAMILY='System' which is defaulted to use San Francisco (SF font). Is this valid Fontfamily to use? If yes, is it open source to use?
0
0
217
Oct ’24
ios 18.0 bug UITabBarController "More" Tab First Item Not Displaying Properly on iOS 18
Hello everyone, I'm working on an iOS application using Objective-C and UITabBarController. My app has more than 5 tabs, so the additional tabs are placed under the "More" tab. However, I've encountered an issue specific to iOS 18 where the first item in the "More" tab does not show up properly. This issue does not occur in iOS 17 or earlier versions. Here's my setup method: (void)mainTabbarSetUp { NSMutableArray *tabItemArray = [NSMutableArray array]; UIViewController *viewController1, *viewController2, *viewController3, *viewController4, *viewController5, *viewController6, *viewController7; UINavigationController *navviewController1, *navviewController2, *navviewController3, *navviewController4, *navviewController5, *navviewController6, *navviewController7; viewController1 = [[UIViewController alloc] init]; navviewController1 = [[UINavigationController alloc] initWithRootViewController:viewController1]; navviewController1.tabBarItem.title = @"Watch List"; navviewController1.tabBarItem.image = [UIImage imageNamed:@"tab_icn_watchlist"]; [tabItemArray addObject:navviewController1]; // Similarly adding other view controllers... viewController6 = [[UIViewController alloc] init]; navviewController6 = [[UINavigationController alloc] initWithRootViewController:viewController6]; navviewController6.tabBarItem.title = @"Cancelled"; navviewController6.tabBarItem.image = [UIImage imageNamed:@"tab_icn_cancelled"]; [tabItemArray addObject:navviewController6]; self.mainTabBarController.viewControllers = tabItemArray; } What I've Tried: Verified that each view controller is correctly initialized and assigned to a UINavigationController before being added to the tab array. Logged the contents of the moreNavigationController to confirm that it contains the correct view controllers. Tested by reducing the number of view controllers to less than 5, and the issue does not occur. Ensured that all UINavigationControllers are configured consistently (e.g., translucency, bar style, etc.).
1
0
538
Oct ’24
UICollectionView Move Item Method Not Called in iOS 18
Summary In iOS 18, the UICollectionViewDelegate method collectionView(_:targetIndexPathForMoveOfItemFromOriginalIndexPath:atCurrentIndexPath:toProposedIndexPath:) is not being called when moving items in a UICollectionView. This method works as expected in iOS 17.5 and earlier versions. Steps to Reproduce Create a UICollectionView with drag and drop enabled. Implement the UICollectionViewDelegate method: func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveOfItemFromOriginalIndexPath originalIndexPath: IndexPath, atCurrentIndexPath currentIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath { print("🐸 Move") return proposedIndexPath } Run the app on iOS 18. Attempt to drag and drop items within the collection view. Expected Behavior The method should be called during the drag and drop operation, and "🐸 Move" should be printed to the console. Actual Behavior The method is not called, and nothing is printed to the console. The drag and drop operation still occurs, but without invoking this delegate method. Configuration iOS Version: 18 Xcode Version: Xcode 16.0.0
1
1
202
Oct ’24
iOS 18 crash on UITextView
Below style case was crash after 17.6.1 import UIKit import PlaygroundSupport class MyViewController : UIViewController { override func loadView() { let view = UIView() view.backgroundColor = .white let titleText = UITextView(frame: CGRect(origin: .zero, size: CGSize(width: 82, height: 100))) titleText.textContainer.maximumNumberOfLines = 2 titleText.textContainer.lineFragmentPadding = 0 titleText.textContainer.lineBreakMode = .byTruncatingTail titleText.textContainerInset = UIEdgeInsets.zero let attributedText = NSMutableAttributedString(string: text, attributes: [.font: UIFont.systemFont(ofSize: 14), .foregroundColor: UIColor.red]) titleText.attributedText = attributedText view.addSubview(titleText) self.view = view } } // Present the view controller in the Live View window PlaygroundPage.current.liveView = MyViewController()
4
0
163
Oct ’24
iOS18 UINavigationBar Crash
I encountered a crash when calling the tabBarView:didSelectIndex: method, and it only happens on iOS 18. Here is crash report: `OS Version: iPhone OS 18.0.1 (22A3370) Report Version: 105 SDK Version: 0.0.4 Exception Type: SIGABRT Exception Codes: #0 at 0x1f0acb274 Crashed Thread: 0 Application Specific Information: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Layout requested for visible navigation bar, <UINavigationBar: 0x11266ef80; frame = (0 -91; 428 44); autoresize = W; tintColor = UIExtendedSRGBColorSpace 1 1 1 0.8; layer = <CALayer: 0x301e14800>> delegate=0x112670600 standardAppearance=0x3035b3720 scrollEdgeAppearance=0x3035b3b10, when the top item belongs to a different navigation bar. topItem = <UINavigationItem: 0x14309cf00> title='' titleView=0x15b1af700 style=navigator leftBarButtonItems=0x301c08940 rightBarButtonItems=0x301caa180, navigation bar = <UINavigationBar: 0x11266e080; frame = (0 -91; 428 44); autoresize = W; tintColor = UIExtendedSRGBColorSpace 1 1 1 0.8; layer = <CALayer: 0x301e1d0a0>> delegate=0x112670000 standardAppearance=0x30355ae60 scrollEdgeAppearance=0x30355aed0, possibly from a client attempt to nest wrapped navigation controllers.' Last Exception Backtrace: 0 CoreFoundation 0x00000001a0cad08c 0x1a0c29000 + 540812 1 libobjc.A.dylib 0x000000019dfaf2e4 0x19df98000 + 94948 2 Foundation 0x00000001a007e15c 0x19f85c000 + 8528220 3 UIKitCore 0x00000001a36b6028 0x1a33f4000 + 2891816 4 UIKitCore 0x00000001a3404248 0x1a33f4000 + 66120 5 UIKitCore 0x00000001a354d878 0x1a33f4000 + 1415288 6 QuartzCore 0x00000001a2749630 0x1a26d1000 + 493104 7 UIKitCore 0x00000001a3447cd0 0x1a33f4000 + 343248 8 UIKitCore 0x00000001a34e9a60 0x1a33f4000 + 1006176 9 UIKitCore 0x00000001a354aa48 0x1a33f4000 + 1403464 10 UIKitCore 0x00000001a34f1c64 0x1a33f4000 + 1039460 11 UIKitCore 0x00000001a368e2c8 0x1a33f4000 + 2728648 12 UIKitCore 0x00000001a368c504 0x1a33f4000 + 2721028 13 UIKitCore 0x00000001a34193c8 0x1a33f4000 + 152520 14 UIKitCore 0x00000001a34191f4 0x1a33f4000 + 152052 15 UIKitCore 0x00000001a340ae84 0x1a33f4000 + 93828 16 CoreAutoLayout 0x00000001c3ad7030 0x1c3ac5000 + 73776 17 UIKitCore 0x00000001a340ddc8 0x1a33f4000 + 105928 18 UIKitCore 0x00000001a340c7f0 0x1a33f4000 + 100336 19 UIKitCore 0x00000001a378087c 0x1a33f4000 + 3721340 20 UIKitCore 0x00000001a37804f0 0x1a33f4000 + 3720432 21 UIKitCore 0x00000001a377e814 0x1a33f4000 + 3713044 22 UIKitCore 0x00000001a37ee8a4 0x1a33f4000 + 4171940 23 UIKitCore 0x00000001a37edf14 0x1a33f4000 + 4169492`
0
0
129
Oct ’24
Anyone getting BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(:) needs to migrate... with Python webbrowser in a IOS Kivy app ?
Hi everyone, If you're encountering the following error in Xcode while executing a simple webbrowser.open() command in your Python file, you're in the right place: "BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(:) needs to migrate to the non-deprecated UIApplication.open(:options:completionHandler:). Force returning false (NO)." This issue arises because, starting from iOS 18, the UIApplication.openURL(:) method has been deprecated. If you created your project, dependencies, and the kivy-ios folder before iOS 18, every time you try to open a URL, the deprecated method will be called. To resolve this issue without rebuilding the entire project and waiting for the kivy-ios toolchain to be updated, simply follow these steps: At the very top of your main.py file remplace import webbrowser by : from pyobjus import autoclass from pyobjus.dylib_manager import load_framework load_framework('/System/Library/Frameworks/UIKit.framework') NSURL = autoclass('NSURL') UIApplication = autoclass('UIApplication') def open_url(url): nsurl = NSURL.URLWithString_(url) app = UIApplication.sharedApplication() options = {} app.openURL_options_completionHandler_(nsurl, options, None) Then replace all your webbrowser.open(url) commands by open_url(url) You no longer need webbrowser. Hope it helped.
0
0
414
Oct ’24
iOS 18 tabbar flickers and then disappears
Use a UITabBarController to load two ViewControllers, A and B, both wrapped in UINavigationController. In A’s viewDidLoad method, push to C, with C’s hidesBottomBarWhenPushed set to true. When popping back to A, the tab bar flickers and then disappears. In versions lower than iOS 18, after popping back, the tabBar does not flicker and disappear. A ViewController override func viewDidLoad() { super.viewDidLoad() let vc = CViewController() vc.hidesBottomBarWhenPushed = true navigationController?.pushViewController(vc, animated: true) // Do any additional setup after loading the view. }
2
0
344
Oct ’24
Navigation Bar animation upon Tab change
Hi. Since Xcode 16 and/or iOS 18.0 (I upgraded at the same time), I have an strange effect in the lower (let's say) 20% section of the Navigation Bar when changing to another tab, and this independently if large titles are used or not. Mentioned section is brighter or darker than the rest of the Navigation Bar background, depending on which background tint is used. This effect lasts about 0.3 seconds, but is clearly visible, quite disturbing and new as of Xcode 16 and/or iOS 18.0. I use the code below in AppDelegate to get a gradient coloured Navigation Bar background. let appearance = UINavigationBarAppearance() UINavigationBar.appearance().standardAppearance = appearance UINavigationBar.appearance().compactAppearance = appearance UINavigationBar.appearance().scrollEdgeAppearance = appearance UINavigationBar.appearance().compactScrollEdgeAppearance = appearance If I don't use above code., the background color is filled and without gradient. Subject effect doesn't show in this case. The effect basically looks like when changing tab, the new Navigation Bar background doesn't clear right away, and keeps the background from the previous Navigation Bar for 0.3 seconds before new one Navigation Bar background is rendered. I spent quite some time on changing every possible setting, in code as well as storyboard ... no success so far. Any ideas how to disable this undesired animation?
0
0
219
Oct ’24
Clarification on New Transition Behavior of UIDocumentInteractionController in iOS 18: Feature or Bug?
Starting with iOS 18, there is a change in how the transition from an underlying view to a UIDocumentInteractionController’s preview view is animated. The transition now scales down the size of the content within the controller’s view, using the center point of the root view as the base of the transformation. This results in a smaller, compressed view centered within the root view, revealing the root view’s background, which is typically white. Even if this background color is adjusted to match elements like the navigation bar, the transformed view has non-rounded corners. I have not tested this behavior when presenting a UIDocumentInteractionController from a SwiftUI view. My question to the UIKit framework developers: Is this new behavior of UIDocumentInteractionController an intentional feature, a feature with bugs, or just a bug?
0
0
208
Oct ’24
MFMessageComposeViewController attachments button disabled
Hello everyone! I was implementing a MFMessageComposeViewController to send messages. Currently I'm observing behaviour that attachments button is always disabled. But thing is that I'm showing MFMessageComposeViewController only when canSendText() && canSendAttachments() are true. if MFMessageComposeViewController.canSendText() && MFMessageComposeViewController.canSendAttachments() { let composeVC = MFMessageComposeViewController() composeVC.messageComposeDelegate = self composeVC.body = "Test message" self.present(composeVC, animated: true, completion: nil) } I've checked that mms are enabled.
2
0
185
Oct ’24
How to connect SwiftUI state with UITable?
I use @Binding to sync data between SwiftUI component state and UITable state. my observations: while reordering @State variable of the TestView is updating, it can be checked by taping the button inside the table the data is not updating. 'log2' is always the same on reorder and which is more important the app crashes when I try to remove item. What to I missing? import SwiftUI import UIKit struct TestView: View { @State var items = ["item 1", "item 2", "item 3", "item 4", "item 5"] var body: some View { VStack { Button("Print Items") { print("log1", items) } ReorderableListView( items: $items ) { item in Text(item) } } } } private struct ReorderableListView<Content: View>: UIViewControllerRepresentable { @Binding var items: [String] let content: (String) -> Content class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate { var parent: ReorderableListView init(parent: ReorderableListView) { self.parent = parent } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { print("log2", parent.items) return parent.items.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) let hostingController = UIHostingController(rootView: parent.content(parent.items[indexPath.row])) hostingController.view.backgroundColor = .clear cell.contentView.subviews.forEach { $0.removeFromSuperview() } cell.contentView.addSubview(hostingController.view) cell.separatorInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15) if indexPath.row == self.parent.items.count - 1 { cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: .greatestFiniteMagnitude) } hostingController.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ hostingController.view.topAnchor.constraint(equalTo: cell.contentView.topAnchor), hostingController.view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor), hostingController.view.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor), hostingController.view.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor) ]) return cell } func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { let movedObject = parent.items.remove(at: sourceIndexPath.row) parent.items.insert(movedObject, at: destinationIndexPath.row) } func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { return true } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { parent.items.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .automatic) } } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIViewController(context: Context) -> UITableViewController { let tableViewController = UITableViewController() tableViewController.tableView.dataSource = context.coordinator tableViewController.tableView.delegate = context.coordinator tableViewController.tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "Cell") tableViewController.tableView.isEditing = true return tableViewController } func updateUIViewController(_ uiViewController: UITableViewController, context: Context) { uiViewController.tableView.reloadData() } } private class CustomTableViewCell: UITableViewCell { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) } override func layoutSubviews() { super.layoutSubviews() superview?.subviews.filter({ "\(type(of: $0))" == "UIShadowView" }).forEach { (sv: UIView) in sv.removeFromSuperview() } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } #Preview { TestView() }
1
0
199
Oct ’24
trailingSwipeActionsConfigurationProvider causes shadow effect on UICollectionViewListCell gone
Currently, I have achieve shadow and corner effect for UICollectionViewListCell, using the following code. UICollectionViewListCell class NoteCell: UICollectionViewListCell { override func awakeFromNib() { super.awakeFromNib() initShadow() initCorner() } private func updateShadowColor() { // Determine the shadow color based on the current interface style let shadowUIColor = UIColor.label self.layer.shadowColor = shadowUIColor.cgColor } private func initShadow() { // https://www.hackingwithswift.com/example-code/uikit/how-to-add-a-shadow-to-a-uiview self.layer.shadowOpacity = 0.3 self.layer.shadowOffset = CGSize(width: 0.5, height: 0.5) self.layer.shadowRadius = 2 self.layer.masksToBounds = false self.updateShadowColor() // Remove the following two lines if you experience any issues with shadow rendering: self.layer.shouldRasterize = true self.layer.rasterizationScale = UIScreen.main.scale } private func initCorner() { var backgroundConfig = UIBackgroundConfiguration.listPlainCell() backgroundConfig.backgroundColor = .systemBackground backgroundConfig.cornerRadius = 16 self.backgroundConfiguration = backgroundConfig } layout private func layoutConfig() -> UICollectionViewCompositionalLayout { let layout = UICollectionViewCompositionalLayout { section, layoutEnvironment in var config = UICollectionLayoutListConfiguration(appearance: .plain) config.headerMode = .none config.footerMode = .none config.showsSeparators = false config.headerTopPadding = 0 config.backgroundColor = nil config.trailingSwipeActionsConfigurationProvider = { [weak self] indexPath in guard let self = self else { return nil } // Knowing what we are tapping at. var snapshot = dataSource.snapshot() let sectionIdentifier = snapshot.sectionIdentifiers[indexPath.section] let itemIdentifiers = snapshot.itemIdentifiers(inSection: sectionIdentifier) let itemIdentifier: NoteWrapper = itemIdentifiers[indexPath.item] let deleteHandler: UIContextualAction.Handler = { action, view, completion in completion(true) // TODO: //snapshot.reloadItems([itemIdentifier]) } let deleteAction = UIContextualAction(style: .normal, title: "Trash", handler: deleteHandler) var swipeActionsConfiguration = UISwipeActionsConfiguration(actions: [ deleteAction, ]) deleteAction.image = UIImage(systemName: "trash") deleteAction.backgroundColor = UIColor.systemRed swipeActionsConfiguration.performsFirstActionWithFullSwipe = false return swipeActionsConfiguration } // https://developer.apple.com/forums/thread/759987 let layoutSection = NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment) layoutSection.interGroupSpacing = 16 // Distance between item. layoutSection.contentInsets = NSDirectionalEdgeInsets( top: 16, // Distance between 1st item and its own header. leading: 16, bottom: 16, // Distance of last item and other header/ bottom edge. trailing: 16 ) return layoutSection } return layout } This is the outcome. However, when I perform swipe action, the shadow effect is gone. Do you have any idea how I can resolve such? Thanks.
0
0
183
Oct ’24