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

UIKit Documentation

Posts under UIKit tag

723 Posts
Sort by:
Post not yet marked as solved
0 Replies
150 Views
First of all, I decided to make my project with only UIKit. So I deleted 'Main' storyboard, Info.plist->Storyboard name, and Main storyboard file base name->Main. And I edited SceneDelegate. So now I can display the single viewControllers, but when I try to set 'UITabBarController' to rootViewController, It cause this error(title). I tried to make UITabBarController in ViewController, UITabBarController in SceneDelegate and some more. // BackgroundViewController for the rootViewController import UIKit class BackgroundViewController: UIViewController { let backgroundTabBarController = UITabBarController() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white createTabBar() } } extension BackgroundViewController { private func createTabBar() { view.backgroundColor = .white view.addSubview(backgroundTabBarController.view) let firstViewController = BookSearchViewController() let secondViewController = MainViewController() let thirdViewController = UserStatusViewController() let lastViewController = OrderViewController() firstViewController.tabBarItem = UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass.circle.fill"), selectedImage: UIImage(systemName: "magnifyingglass.circle")) secondViewController.tabBarItem = UITabBarItem(title: "Main", image: UIImage(systemName: "house.fill"), selectedImage: UIImage(systemName: "house")) thirdViewController.tabBarItem = UITabBarItem(title: "My", image: UIImage(systemName: "person.fill"), selectedImage: UIImage(systemName: "person")) lastViewController.tabBarItem = UITabBarItem(title: "Order", image: UIImage(systemName: "menucard.fill"), selectedImage: UIImage(systemName: "menucard")) backgroundTabBarController.viewControllers = [firstViewController, secondViewController, thirdViewController, lastViewController] backgroundTabBarController.selectedViewController = secondViewController } } // SceneDelegate import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: windowScene) window?.rootViewController = BackgroundViewController() window?.makeKeyAndVisible() } } // Error code Thread 1: "Could not find a storyboard named 'Main' in bundle NSBundle </Users/[MyDesktopName]/Library/Developer/CoreSimulator/Devices/[ApplicationName]/data/Containers/Bundle/Application/[ApplicationName]/BTY.app> (loaded)" But anyone of this solve the problem. How can I make UITabBarController to rootViewController? Make UITabBarController in SceneDelegate Make new UIViewController that have UITabBarController and set to rootViewController Set ViewControllers with 'UINavigationController(rootViewController:)' Present UITabBarController from other viewController
Posted
by J_ROLF.
Last updated
.
Post not yet marked as solved
0 Replies
156 Views
First of all, I decided to make my project with only UIKit. So I deleted 'Main' storyboard, Info.plist->Storyboard name, and Main storyboard file base name->Main. And I edited SceneDelegate. So now I can display the single viewControllers, but when I try to set 'UITabBarController' to rootViewController, It cause this error(title). I tried to make UITabBarController in ViewController, UITabBarController in SceneDelegate and some more. How can I fix this? We can't use code-based UITabBarController in new version of Xcode now?
Posted
by J_ROLF.
Last updated
.
Post not yet marked as solved
0 Replies
118 Views
I'm using something similar to this example. import SwiftUI struct ContentView: View { @State private var toggle = false var body: some View { CustomParentView { Button { toggle.toggle() } label: { Text(toggle.description) } } } } struct CustomParentView<Content: View>: UIViewRepresentable { let content: Content @inlinable init(@ViewBuilder content: () -> Content) { self.content = content() } func makeUIView(context: Context) -> UIView { let view = UIView() let hostingController = context.coordinator.hostingController hostingController.view.frame = view.bounds hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(hostingController.view) return view } func updateUIView(_ uiView: UIView, context: Context) { context.coordinator.hostingController.rootView = self.content } class Coordinator: NSObject { var hostingController: UIHostingController<Content> init(hostingController: UIHostingController<Content>) { self.hostingController = hostingController } } func makeCoordinator() -> Coordinator { return Coordinator(hostingController: UIHostingController(rootView: content)) } } The only different thing is I'm using UIScrollView. When I have a @State width and call .frame(width) on the content, the content would stay with initial width even when width is changed. I tried: hostingController.sizingOptions = .intrinsicContentSize This time the size would change to correct size if I pinch zoom the content, but the initial size that trigger updateUIView would be .zero. This prevents me to center the content. Is there a way to dynamically set size and get correct rendering just like any child view of a normal SwiftUI view?
Posted Last updated
.
Post not yet marked as solved
2 Replies
728 Views
The standard Command-A keyboard shortcut in a UITextView is broken in Mac Catalyst 16/ Ventura with either TextKit 2 or TextKit 1 for long texts. In iOS 16 the selection is instant but on MacOS with Catalyst a beachball is displayed for more than 50 seconds and the app consumes gigabytes of memory. Earlier versions of Mac Catalyst work fine. To duplicate this just create a small storyBoard app with an editable UITextView and paste a long document around 1Mb then use the standard Select All Command either from the keyboard or the app menu. l I use Tale of Two Cities which is about 800k to test in my app. Is there any workaround for this?
Posted Last updated
.
Post not yet marked as solved
0 Replies
144 Views
It's been a really long time since I've tried this, so I'm not sure if something has changed or if I've stumbled onto a bug... I'm trying to implement a custom Transition Animation for a UINavigationController. While documentation around this is pretty sparse this days, I was able to take the old sample from the View Controller Programming Guide:, rewriting it in Swift: func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let containerView = transitionContext.containerView guard let fromVC = transitionContext.viewController(forKey: .from), let toVC = transitionContext.viewController(forKey: .to), let toView = transitionContext.view(forKey: .to), let fromView = transitionContext.view(forKey: .from) else { transitionContext.completeTransition(false) return } let containerFrame = containerView.frame var toViewStartFrame = transitionContext.initialFrame(for: toVC) let toViewFinalFrame = transitionContext.finalFrame(for: toVC) var fromViewFinalFrame = transitionContext.finalFrame(for: fromVC) let fromViewStartFrame = transitionContext.initialFrame(for: fromVC) if operation.isPresenting { toViewStartFrame.origin.x = containerFrame.size.width toViewStartFrame.origin.y = containerFrame.size.height } else { fromViewFinalFrame = CGRect(x: containerFrame.size.width, y: containerFrame.size.height, width: toView.frame.size.width, height: toView.frame.size.height) // missing from Apple's sample code toViewStartFrame = toViewFinalFrame } containerView.addSubview(toView) toView.frame = toViewStartFrame // Add the from view to the container view on dismissal, this is missing from Apple's sample code if !operation.isPresenting { containerView.addSubview(fromView) fromView.frame = fromViewStartFrame } UIView.animate(withDuration: transitionDuration(using: transitionContext)) { if self.operation.isPresenting { toView.frame = toViewFinalFrame } else { fromView.frame = fromViewFinalFrame } } completion: { completed in let success = !transitionContext.transitionWasCancelled if (self.operation.isPresenting && !success) || (!self.operation.isPresenting && success) { toView.removeFromSuperview() } // missing from Apple's sample code if !self.operation.isPresenting { fromView.removeFromSuperview() } transitionContext.completeTransition(success) } } I added a couple of things to support dismissals and pops. In order to use it with in my app, I set the navigation controller's delegate and returned the type conforming to UIViewControllerAnimatedTransitioning, containing the above code, from navigationController(_ :, animationControllerFor operation:, from fromVC:, to toVC). I've confirmed that that all behaves as you expect. If I use this animation controller for a modal presentation or dismissal, it works fine. For a Navigation push, again, behaves as expected. But when I use it for a navigation pop I run into a problem. The animation is performed, but once it completes, the Navigation Controller's view appears to be completely empty. In a sample app, the screen goes black. In the View Debugger, I see that the UIViewControllerWrapperView has no subviews. Another curious thing I found is that my View Controller never gets a viewWillDisappear message sent. Is there an additional setup step that I missed in order to get this working properly?
Posted Last updated
.
Post not yet marked as solved
0 Replies
149 Views
0 I want to get notification like UIApplication.didBecomeActiveNotification and UIApplication.willResignActiveNotification when app switches in iPad Stage Controller Mode, but UIApplication.didBecomeActiveNotification, UIApplication.willResignActiveNotification just dont work, is there any method to get this notification
Posted
by Monzy.
Last updated
.
Post not yet marked as solved
0 Replies
133 Views
I am trying to sync up the selected tab bar item once a user presses back and navigates back in the web wrapper iOS app. Here is how the app works: When a user logs in, they are presented with the Home Screen. To navigate, the select a tab item on the tab bar. This tells webkit to redirect to that URL and then that webpage is shown in the app (wrapped). A back button also appears. When a user presses the back button, the webView.goBack() method sends the user back on in the webView.backForwardList. What happens then is that the user is now on the previous page, however the tab bar has not updated. In other words, the user is back on the first tab but the second tab is highlighted. I tried fixing this by telling the tab bar controller what item to select, however this creates a state malfunction because it also tells the webView to navigate to that url again, so in fact this means that the user isn't going back through web history, but actually is going forward while simulating going back. I need to be able to highlight the tab bar items that sync up with the page that we have gone back to without selecting it. Does anyone have an idea for how to manually highlight or select a tab bar item without actually navigating to that tab bar item? Thank you!
Posted Last updated
.
Post not yet marked as solved
0 Replies
123 Views
I'm working with PDFKit and trying to rotate PDFAnnotation from a PDFView: Here is my code for a normal case(no rotated): class ImageAnnotation: PDFAnnotation { var image: UIImage? init(image: UIImage?, bounds: CGRect) { self.image = image super.init(bounds: bounds, forType: .stamp, withProperties: nil) } override func draw(with box: PDFDisplayBox, in context: CGContext) { guard let cgImage = self.image?.cgImage else { return } context.draw(cgImage, in: bound) } } And here is the way I used to rotate PDFAnnotation: init(image: UIImage?, bounds: CGRect) { self.image = image super.init(bounds: bounds.applying(CGAffineTransform(rotationAngle: -CGFloat.pi/12)), forType: .stamp, withProperties: nil) } override func draw(with box: PDFDisplayBox, in context: CGContext) { guard let cgImage = self.image?.cgImage else { return } context.rotate(by: CGFloat.pi/12) context.draw(cgImage, in: bounds) } But it doesn't work as expected. Can you help me? Thank you.
Posted
by dhuy.
Last updated
.
Post not yet marked as solved
1 Replies
183 Views
Hi all, Here I want to encode OrderedDictionary to JSON file, I use the JSONEncoder below: let encoder = JSONEncoder() encoder.outputFormatting = [.prettyPrinted, .withoutEscapingSlashes] and I declare variables qwe, asd and zxc: var qwe = OrderedDictionary<String, Int>() qwe["bbb"] = 12 qwe["ccc"] = 13 qwe["ddd"] = 14 qwe["bbc"] = 15 var asd = Dictionary<String, Int>() asd["bbb"] = 1 asd["ccc"] = 3 asd["ddd"] = 4 asd["bbc"] = 5 var zxc: KeyValuePairs<String, String> { return [ "zz": "zz", "aa": "aa", "bb": "bb", "cc": "cc", "bc": "bc", ] } After I do try encoder.encode(qwe).write(to: path ,options: .atomic) encoder.encode(asd).write(to: path ,options: .atomic) encoder.encode(zxc).write(to: path ,options: .atomic) the output JSON file format of OrderedDictionary isn't what I expected. The output JSON of OrderDictionary is like this: [ "bbb", 12, "ccc", 13, "ddd", 14, "bbc", 15 ] On the other hand, the output JSON of Dictionary and KeyValuePairs are normal, just with different order: Dictonary: { "ccc" : 3, "bbb" : 1, "bbc" : 5, "ddd" : 4 } KeyValuePairs: { "cc" : "cc", "aa" : "aa", "zz" : "zz", "bb" : "bb", "bc" : "bc" } I also Log these objects after I declare them, the Log show their structure are similar: qwe -> ["bbb": 12, "ccc": 13, "ddd": 14, "bbc": 15] asd -> ["ccc": 3, "bbb": 1, "bbc": 5, "ddd": 4] zxc -> ["zz": "zz", "aa": A"aa", "bb": "bb", "cc": "cc", "bc": "bc"] I thought the OrderedDictionary is similar to Dictionary, but does anyone know why the output of OrderedDictionary is not like this: {"bbb": 12, "ccc": 13, "ddd": 14, "bbc": 15} Or is there any other way I can customize the order of keys in my encoded JSON file? Thank you so much!
Posted Last updated
.
Post not yet marked as solved
1 Replies
184 Views
I have encountered inconsistent paste behaviors in UITextView depending on whether the text is in English or Korean. When pasting at the beginning of a text with an English sentence in UITextView, a space is added after the pasted text. In the middle, spaces are added before and after the pasted text. However, when pasting at the end, only a space is added before the pasted text. On the other hand, when there is a Korean sentence in UITextView, pasting at the beginning results in the inclusion of "\n" at the beginning of the pasted text, while in other cases, no additional text is added upon pasting. I'm curious to know if this behavior is intentional. I would appreciate understanding the rationale behind appending "\n" in Korean text and the absence of additional text in other cases.
Posted
by pane4846.
Last updated
.
Post not yet marked as solved
13 Replies
566 Views
On app minor update, after moving to xcode 15.2 Any thoughts on what could be causing it? Thank you in advance.
Posted
by JBarrac.
Last updated
.
Post not yet marked as solved
7 Replies
1k Views
I'm trying to create a dynamic menu on Mac Catalyst. Using a UIBarButtonitem like so to make a "pull down" button: UIDeferredMenuElement *deferredmenuElement; deferredmenuElement = [UIDeferredMenuElement elementWithUncachedProvider:^(void (^ _Nonnull completion)(NSArray<UIMenuElement *> * _Nonnull)) { UIAction *actionOne = [UIAction actionWithTitle:@"Action One" image:nil identifier:nil handler:^(__kindof UIAction * _Nonnull action) { NSLog(@"action one fired."); }]; UIAction *actionTwo = [UIAction actionWithTitle:@"Action Two" image:nil identifier:nil handler:^(__kindof UIAction * _Nonnull action) { NSLog(@"action two fired."); }]; UIAction *actionThree = [UIAction actionWithTitle:@"Action Three" image:nil identifier:nil handler:^(__kindof UIAction * _Nonnull action) { NSLog(@"action three fired."); }]; completion(@[actionOne,actionTwo,actionThree]); }]; UIMenu *wrappedMenu = [UIMenu menuWithChildren:@[deferredmenuElement]]; UIBarButtonItem *uiBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:nil menu:wrappedMenu]; uiBarButtonItem.image = [UIImage systemImageNamed:@"rectangle.and.pencil.and.ellipsis"]; self.navigationItem.rightBarButtonItems = @[uiBarButtonItem]; The button appears in the toolbar but when I click it to expose the menu I get a menu with on element in it that says "Loading...". The the uncached provider block is never called. Running Ventura 13.2.1 and Xcode 14.2.
Posted Last updated
.
Post not yet marked as solved
2 Replies
437 Views
Activity image for custom activity is blank ever since iOS 17 release ,compiled in Xcode 15. The image being sent is 180x180 px. Works fine in iOS 16 running earlier Xcodes. Attached a image of the issue showing blank icons (mail and messages are the custom activities) Anyone facing the issue?
Posted
by Azzo03.
Last updated
.
Post not yet marked as solved
0 Replies
175 Views
I am currently working on an iOS application where I want to implement the safari tabs and when I have to minimize that one to check how many numbers of tabs are opened. How can I do this?
Posted
by ckdash.
Last updated
.
Post not yet marked as solved
1 Replies
195 Views
I have created a custom input field by conforming to UITextInput. It is setup to use UITextInteraction. Everything works very well. If the user taps on the custom field, the cursor (provided by UITextInteraction) appears. The user can type, select, move the cursor, etc. But I'm stumped trying to get the cursor to appear automatically. With a normal UITextField or UITextView you simply call becomeFirstResponder(). But doing that with my custom UITextInput does not result in the cursor appearing. It only appears if the user taps on the custom field. I don't know what I'm missing. I don't see any API in UITextInteraction that can be called to say "activate the cursor layer". Does anyone know what steps are required with a custom UITextInput using UITextInteraction to activate the cursor programmatically without the user needing to tap on the custom field?
Posted
by RickMaddy.
Last updated
.
Post marked as solved
2 Replies
193 Views
This is a simple collection view with compositional layout and diffable data source. It displays one cell, of type UICollectionViewListCell, whose contentView has a text view as a subview. import UIKit class ViewController: UIViewController { var collectionView: UICollectionView! let textView = UITextView() var dataSource: UICollectionViewDiffableDataSource<Section, Int>! enum Section: CaseIterable { case first } override func viewDidLoad() { super.viewDidLoad() configureHierarchy() configureDataSource() } private func configureHierarchy() { collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout()) view.addSubview(collectionView) collectionView.autoresizingMask = [.flexibleHeight, .flexibleWidth] textView.delegate = self } func configureDataSource() { let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { [weak self] cell, indexPath, itemIdentifier in guard let self else { return } cell.contentView.addSubview(textView) textView.pinToSuperviewMargins() } dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier) } var snapshot = NSDiffableDataSourceSnapshot<Section, Int>() snapshot.appendSections(Section.allCases) snapshot.appendItems([1], toSection: .first) dataSource.apply(snapshot) } func createLayout() -> UICollectionViewLayout { UICollectionViewCompositionalLayout { section, layoutEnvironment in var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped) return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment) } } } extension ViewController: UITextViewDelegate { func textViewDidChange(_ textView: UITextView) { // Do something here? } } The pinToSuperviewMargins method sets the top, bottom, leading and trailing constraints of the view on which it's called to its superview's and its translatesAutoResizingMaskIntoConstraints property to false: extension UIView { func pinToSuperviewMargins( top: CGFloat = 0, bottom: CGFloat = 0, leading: CGFloat = 0, trailing: CGFloat = 0, file: StaticString = #file, line: UInt = #line ) { guard let superview = self.superview else { let localFilePath = URL(fileURLWithPath: "\(file)").lastPathComponent print(">> \(#function) failed in file: \(localFilePath), at line: \(line): could not find \(Self.self).superView.") return } self.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ self.topAnchor.constraint(equalTo: superview.topAnchor, constant: top), self.bottomAnchor.constraint(equalTo: superview.bottomAnchor, constant: bottom), self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: leading), self.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: trailing), ]) } func pinToSuperviewMargins(constant c: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { self.pinToSuperviewMargins(top: c, bottom: c, leading: c, trailing: c, file: file, line: line) } } I tried calling collectionView.setNeedsLayout() in textViewDidChange(_:) but it doesn't work. I used to accomplish cell resizing with tableView.beginUpdates(); tableView.endUpdates() when dealing with table views.
Posted
by Filippo02.
Last updated
.
Post not yet marked as solved
0 Replies
168 Views
I am subclassing a UICollectionViewCompositionalLayout, for the purpose of adding custom margins to a decoration view. On vertical layouts it works as expected, however when a section with orthogonal scrolling is introduced, UICollectionViewLayoutAttributes that do not pass through layoutAttributesForElements get applied to the DecorationView and thus breaking the layout during scroll. I suspect the OrthogonalScrollViews apply their own attributes incorrectly thus breaking this code. FeedbackID: FB13705625 final class CompositionalViewLayout: UICollectionViewCompositionalLayout { private var decorationViewAttributes: [IndexPath: BackgroundDecoratorLayoutAttributes] = [:] override func prepare() { super.prepare() guard let collectionView = collectionView else { return } decorationViewAttributes.removeAll() for sectionIndex in 0..<collectionView.numberOfSections { let numberOfItems = collectionView.numberOfItems(inSection: sectionIndex) guard numberOfItems > 0, let firstItem = layoutAttributesForItem(at: IndexPath(item: 0, section: sectionIndex)), let lastItem = layoutAttributesForItem( at: IndexPath(item: numberOfItems - 1, section: sectionIndex) ) else { continue } let indexPath = IndexPath(item: 0, section: sectionIndex) // Create section frame var sectionFrame = firstItem.frame.union(lastItem.frame) sectionFrame.size.width = collectionView.frame.width sectionFrame.origin.x = 12 sectionFrame.size.width -= 24 createSectionDecorationView( sectionFrame: sectionFrame, indexPath: indexPath ) } } override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let attributes: [UICollectionViewLayoutAttributes] = super.layoutAttributesForElements(in: rect) ?? [] print("Dinesh :: super Attributes \(attributes)") var modifiedAttributes = [UICollectionViewLayoutAttributes]() var addedAttributes = Set<UICollectionViewLayoutAttributes>() for attribute in attributes { if let customAttr = decorationViewAttributes[attribute.indexPath], attribute.representedElementKind == customAttr.representedElementKind { modifiedAttributes.append(customAttr) addedAttributes.insert(customAttr) } else { modifiedAttributes.append(attribute) } } modifiedAttributes.append(contentsOf: decorationViewAttributes.values.filter { return (!addedAttributes.contains($0) && rect.intersects($0.frame)) }) return modifiedAttributes } override func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { guard elementKind == ViewController.sectionBackgroundDecorationElementKind, let decorationAttribute = decorationViewAttributes[indexPath] else { return super.layoutAttributesForDecorationView(ofKind: elementKind, at: indexPath) } return decorationAttribute } private func createSectionDecorationView(sectionFrame: CGRect, indexPath: IndexPath) { let attr = BackgroundDecoratorLayoutAttributes( forDecorationViewOfKind: ViewController.sectionBackgroundDecorationElementKind, with: indexPath ) attr.frame = sectionFrame attr.zIndex = -1 attr.cornerRadius = 12 switch indexPath.section { case 0: attr.backgroundColor = .systemRed case 1: attr.backgroundColor = .systemYellow case 2: attr.backgroundColor = .systemBlue case 3: attr.backgroundColor = .systemGreen case 4: attr.backgroundColor = .systemPink default: attr.backgroundColor = .systemGray } // Cache attribute decorationViewAttributes[indexPath] = attr } } class SectionBackgroundDecorationView: UICollectionReusableView { override init(frame: CGRect) { super.init(frame: frame) configure() } required init?(coder: NSCoder) { fatalError("not implemented") } override func layoutSubviews() { super.layoutSubviews() } override func prepareForReuse() { super.prepareForReuse() } override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) { super.apply(layoutAttributes) guard let attr = layoutAttributes as? BackgroundDecoratorLayoutAttributes else { return } backgroundColor = attr.backgroundColor layer.cornerRadius = attr.cornerRadius } }
Posted Last updated
.
Post not yet marked as solved
0 Replies
211 Views
Hi! I've got a custom UICollectionViewLayout which has its cells and two supplementary kind of views scattered all over randomly within its bounds. It should be a calendar month view with day of week labels on top, week numbers on the left (supplementary views) and day cells in the middle (items). So far I tracked down that the layoutAttributesForItem(at indexPath:) and layoutAttributesForSupplementaryView(ofKind elementKind:, at indexPath:) are not getting called. Which gives them a reason not to be placed where they should be. layoutAttributesForElements(in rect: ) gets called indeed and the returned value is also OK: override func layoutAttributesForElements(in rect: CGRect) -&gt; [UICollectionViewLayoutAttributes]? { super.layoutAttributesForElements(in: rect) var arr = [UICollectionViewLayoutAttributes]() arr.append(contentsOf: AllAttributes.filter({ (Item:UICollectionViewLayoutAttributes) -&gt; Bool in (collectionView!.numberOfSections) &gt; Item.indexPath.section &amp;&amp; rect.intersects(Item.frame) })) return arr //47 long array of UICollectionViewLayoutAttributes } In IB the Collection View is specified to be Custom Layout and the respective subclass is specified there. I inspected the official example code here: https://developer.apple.com/documentation/uikit/views_and_controls/collection_views/layouts/customizing_collection_view_layouts The only diffrerence I see is that the example uses UICollectionViewController, which is specified to be Flow Layout in IB, and then the UICollectionView is re-instantiated in code as custom during viewDidLoad. Could that really make a difference? This solution would not be too convenient for me, as I have also other controls on my Controller View. Any help would be appreciated.
Posted Last updated
.
Post marked as solved
1 Replies
206 Views
I thought I could easily display a toolbar in UIKit, but I was wrong, or at least I can't do so without getting "Unable to simultaneously satisfy constraints." console messages. Here is my code: import UIKit class ViewController: UIViewController { let toolbar = UIToolbar() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground toolbar.items = [ UIBarButtonItem(title: "Title", style: .plain, target: nil, action: nil), UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) ] view.addSubview(toolbar) toolbar.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ toolbar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), toolbar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), toolbar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), toolbar.heightAnchor.constraint(equalToConstant: 44) ]) } } And here is the console log: Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) ( "<NSAutoresizingMaskLayoutConstraint:0x600002107b10 h=--& v=--& _UIToolbarContentView:0x104008e40.height == 0 (active)>", "<NSLayoutConstraint:0x600002122e90 V:|-(0)-[_UIButtonBarStackView:0x10250d8b0] (active, names: '|':_UIToolbarContentView:0x104008e40 )>", "<NSLayoutConstraint:0x600002121ef0 _UIButtonBarStackView:0x10250d8b0.bottom == _UIToolbarContentView:0x104008e40.bottom (active)>", "<NSLayoutConstraint:0x600002107a70 UIButtonLabel:0x10250f280.centerY == _UIModernBarButton:0x1027059c0'Title'.centerY + 1.5 (active)>", "<NSLayoutConstraint:0x60000210ea30 'TB_Baseline_Baseline' _UIModernBarButton:0x1027059c0'Title'.lastBaseline == UILayoutGuide:0x600003b0ca80'UIViewLayoutMarginsGuide'.bottom (active)>", "<NSLayoutConstraint:0x60000210ea80 'TB_Top_Top' V:|-(>=0)-[_UIModernBarButton:0x1027059c0'Title'] (active, names: '|':_UIButtonBarButton:0x102607120 )>", "<NSLayoutConstraint:0x60000210e8f0 'UIButtonBar.maximumAlignmentSize' _UIButtonBarButton:0x102607120.height == UILayoutGuide:0x600003b00380'UIViewLayoutMarginsGuide'.height (active)>", "<NSLayoutConstraint:0x60000212c960 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600003b00380'UIViewLayoutMarginsGuide']-(0)-| (active, names: '|':_UIButtonBarStackView:0x10250d8b0 )>", "<NSLayoutConstraint:0x60000210ec60 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600003b0ca80'UIViewLayoutMarginsGuide']-(11)-| (active, names: '|':_UIButtonBarButton:0x102607120 )>", "<NSLayoutConstraint:0x60000212d6d0 'UIView-topMargin-guide-constraint' V:|-(0)-[UILayoutGuide:0x600003b00380'UIViewLayoutMarginsGuide'] (active, names: '|':_UIButtonBarStackView:0x10250d8b0 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x600002107a70 UIButtonLabel:0x10250f280.centerY == _UIModernBarButton:0x1027059c0'Title'.centerY + 1.5 (active)> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful. Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) ( "<NSAutoresizingMaskLayoutConstraint:0x600002106710 h=--& v=--& _UIToolbarContentView:0x104008e40.width == 0 (active)>", "<NSLayoutConstraint:0x600002120b40 H:|-(0)-[_UIButtonBarStackView:0x10250d8b0] (active, names: '|':_UIToolbarContentView:0x104008e40 )>", "<NSLayoutConstraint:0x600002122e40 H:[_UIButtonBarStackView:0x10250d8b0]-(0)-| (active, names: '|':_UIToolbarContentView:0x104008e40 )>", "<NSLayoutConstraint:0x60000210eda0 'TB_Leading_Leading' H:|-(16)-[_UIModernBarButton:0x1027059c0'Title'] (active, names: '|':_UIButtonBarButton:0x102607120 )>", "<NSLayoutConstraint:0x60000210eb70 'TB_Trailing_Trailing' H:[_UIModernBarButton:0x1027059c0'Title']-(16)-| (active, names: '|':_UIButtonBarButton:0x102607120 )>", "<NSLayoutConstraint:0x60000210e580 'UISV-canvas-connection' UILayoutGuide:0x600003b00380'UIViewLayoutMarginsGuide'.leading == _UIButtonBarButton:0x102607120.leading (active)>", "<NSLayoutConstraint:0x60000210e5d0 'UISV-canvas-connection' UILayoutGuide:0x600003b00380'UIViewLayoutMarginsGuide'.trailing == UIView:0x10400e480.trailing (active)>", "<NSLayoutConstraint:0x60000210e9e0 'UISV-spacing' H:[_UIButtonBarButton:0x102607120]-(0)-[UIView:0x10400e480] (active)>", "<NSLayoutConstraint:0x60000212c820 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x600003b00380'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':_UIButtonBarStackView:0x10250d8b0 )>", "<NSLayoutConstraint:0x60000212ca00 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x600003b00380'UIViewLayoutMarginsGuide']-(0)-|(LTR) (active, names: '|':_UIButtonBarStackView:0x10250d8b0 )>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x60000210eb70 'TB_Trailing_Trailing' H:[_UIModernBarButton:0x1027059c0'Title']-(16)-| (active, names: '|':_UIButtonBarButton:0x102607120 )> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful. I tried giving the toolbar a frame rather than constraints, and also to not give it an explicit height. The only thing that works is to comment out UIBarButtonItem(title: "Title", style: .plain, target: nil, action: nil), which isn't really a solution. What am I doing wrong?
Posted
by Filippo02.
Last updated
.