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

UIKit Documentation

Posts under UIKit tag

1,022 Posts
Sort by:
Post marked as solved
8 Replies
143 Views
In my app, users can select from a range of UI color-palettes to customize the look of the app to suite their preference. The app's root viewcontroller is a UINavigationController (this app is not using SwiftUI, nor has it adopted UIScene yet). However, I noticed only the first time (to be specific: this is in the appDelegate's application(:didFinishLaunchingWithOptions:), so before anything is actually rendered to the screen) the appearance settings are applied, but subsequent changes do not take effect. However, the following code seems to 'fix' the issue: self.window?.rootViewController = nil self.updateAppearance() self.window?.rootViewController = navigationController This to me seems hacky/kludgy and unlikely to be a sustainable 'fix', and I think it indicates that the appearance information is only taken into account when a view(controller) gets inserted into the view(controller) hierarchy, in other words: when it gets drawn. So then the question would be: how to tell a UINavigationController / Bar to redraw using the updated appearance settings? I'm sure I'm overlooking something relatively simple (as I imagine this kind of thing is something many apps do to support darkmode), but alas, I can't seem to find it. I setup a small test-project to isolate this issue. It has only one custom viewcontroller (ContentViewController) which only sets the backgroundColor in viewDidLoad(), and an AppDelegate (code below). No storyboards, no UIScene related things. So, here is the minimal code that reproduces my issue: AppDelegate.swift: import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var rootNavigationController: UINavigationController? let contentViewController = ViewController() let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.main) func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { window = UIWindow() let navigationController = UINavigationController(rootViewController: contentViewController) rootNavigationController = navigationController window?.rootViewController = navigationController window?.makeKeyAndVisible() // initial setup of appearance, this first call will take effect as expected updateAppearance() // setup a timer to repeatedly change the appearance of the navigationbar timer.setEventHandler { /// ! uncommenting this line and the one after `self.updateAppearance()` /// will cause `self.updateAppearance()` to take effect as expected // self.window?.rootViewController = nil self.updateAppearance() //self.window?.rootViewController = navigationController } timer.schedule(deadline: .now(), repeating: .seconds(2), leeway: .milliseconds(50)) timer.resume() return true } // some vars to automatically toggle between colors / textstyles var colorIndex = 0 let colors = [ UIColor.blue, UIColor.yellow] let textStyles: [UIFont.TextStyle] = [.title3, .body] func updateAppearance() { let color = colors[colorIndex] let textStyle = textStyles[colorIndex] contentViewController.title = "bgColor: \(colorIndex) \(textStyle.rawValue)" colorIndex = (colorIndex == 0) ? 1 : 0 let textColor = colors[colorIndex] self.rootNavigationController?.navigationBar.isTranslucent = false let navigationBarAppearance = UINavigationBarAppearance() navigationBarAppearance.configureWithOpaqueBackground() navigationBarAppearance.backgroundColor = color         let textAttributes: [NSAttributedString.Key : Any] =         [.font: UIFont.preferredFont(forTextStyle: textStyle),          .foregroundColor: textColor ] navigationBarAppearance.titleTextAttributes = textAttributes UINavigationBar.appearance().standardAppearance = navigationBarAppearance UINavigationBar.appearance().compactAppearance = navigationBarAppearance UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance } } ViewController: import UIKit class ViewController: UIViewController {     override func viewDidLoad()     {         super.viewDidLoad()         view.backgroundColor = UIColor.lightGray     } }
Posted
by Joride.
Last updated
.
Post not yet marked as solved
0 Replies
91 Views
Im observing a bigger down size of my text when using .adjustsFontSizeToFitWidth on iOS15 vz iOS14 Xcode 13 but i haven't find any release notes explaining why. My observations are this: Same frame for the label result on a different text size in a proportion of heiht: 1, width:4 even more stranger if I increase the height of the frame the behavior returns to be like the old one and this don't affect behavior on iOS14 // First label is render smaller on iOS 15 vz 14 UILabel *yourLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, 160, 40)]; [yourLabel1 setTextColor:[UIColor brownColor]]; [yourLabel1 setBackgroundColor:[UIColor systemRedColor]]; [yourLabel1 setFont:[UIFont boldSystemFontOfSize:52]]; [yourLabel1 setText:@"HELLO"]; yourLabel1.minimumScaleFactor = 0.2; yourLabel1.adjustsFontSizeToFitWidth = YES; [self.view addSubview:yourLabel1]; // Second label is render equal on iOS 15 and 14 only difference is a change on the height UILabel *yourLabel2 = [[UILabel alloc] initWithFrame:CGRectMake(0, 300, 160, 60)]; [yourLabel2 setTextColor:[UIColor brownColor]]; [yourLabel2 setBackgroundColor:[UIColor systemRedColor]]; [yourLabel2 setFont:[UIFont boldSystemFontOfSize:52]]; [yourLabel2 setText:@"HELLO"]; yourLabel2.minimumScaleFactor = 0.2; yourLabel2.adjustsFontSizeToFitWidth = YES; [self.view addSubview:yourLabel2];
Posted
by misaely.
Last updated
.
Post not yet marked as solved
0 Replies
74 Views
It looks like a custom keyboard created through an UIInputViewController doesn't have access to all events. How can one know inside a messaging App that the Send button was tapped? And how does one know what text was sent and text was not sent when the keyboard is closed? Is this a privacy policy or is there an API I am missing?
Posted Last updated
.
Post not yet marked as solved
0 Replies
61 Views
Hi, is it possible to customize the colors of the icons and placeholders in the SearchField created with the .searchable modifier in SwiftUI? I am currently using a dark navigation bar in the .light color scheme (and the other way around). This makes the SearchField unreadable since the contrast is very low.
Posted
by moogle19.
Last updated
.
Post marked as solved
2 Replies
540 Views
Hi, I am faced with a strange problem with a Catalyst app that uses MapKit. If the map is visible and I resize the window (causing the map the resize), sometime the app crashes with some Metal related error. Is this a know issue between MapKit and Catalyst? There is something I can do in order to prevent this crash? Below you can find the error message and a screenshot of the thread that caused the crash. Thank you -[MTLDebugDevice notifyExternalReferencesNonZeroOnDealloc:]:2951: failed assertion `The following Metal object is being destroyed while still required to be alive by the command buffer 0x7f96de27f600 (label: <no label set>): <MTLToolsObject: 0x7f96dde552e0> -> <BronzeMtlTexture: 0x7f96dc04c230> label = <none> textureType = MTLTextureType2D pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB width = 2372 height = 1668 depth = 1 arrayLength = 1 mipmapLevelCount = 1 sampleCount = 1 cpuCacheMode = MTLCPUCacheModeDefaultCache storageMode = MTLStorageModeManaged hazardTrackingMode = MTLHazardTrackingModeTracked resourceOptions = MTLResourceCPUCacheModeDefaultCache MTLResourceStorageModeManaged MTLResourceHazardTrackingModeTracked usage = MTLTextureUsageShaderRead MTLTextureUsageRenderTarget shareable = 0 framebufferOnly = 0 purgeableState = MTLPurgeableStateNonVolatile swizzle = [MTLTextureSwizzleRed, MTLTextureSwizzleGreen, MTLTextureSwizzleBlue, MTLTextureSwizzleAlpha] isCompressed = 0 parentTexture = <null> parentRelativeLevel = 0 parentRelativeSlice = 0 buffer = <null> bufferOffset = 0 bufferBytesPerRow = 0 iosurface = 0x0 iosurfacePlane = 0 allowGPUOptimizedContents = YES'
Posted
by DaleOne.
Last updated
.
Post not yet marked as solved
0 Replies
98 Views
I have made an UICollectionView in which you can double tap a cell to resize it. I'm using a CompositionalLayout, a DiffableDataSource and the new UIHostingConfiguration hosting a SwiftUI View which depends on an ObservableObject. The resizing is triggered by updating the height property of the ObservableObject. That causes the SwiftUI View to change its frame which leads to the collectionView automatically resizing the cell. The caveat is that it does so immediately without animation only jumping between the old and the new frame of the view. The ideal end-goal would be to be able to add a .animation() modifier to the SwiftUI View that then determines animation for both view and cell. Doing so now without additional setup makes the SwiftUI View animate but not the cell. Is there a way to make the cell (orange) follow the size of the view (green) dynamically? The proper way to manipulate the cell animation (as far as I known) is to override initialLayoutAttributesForAppearingItem() and finalLayoutAttributesForDisappearingItem() but since the cell just changes and doesn't appear/disappear they don't have an effect. One could also think of Auto Layout constraints to archive this but I don’t think they are usable with UIHostingConfiguration? I've also tried: subclassing UICollectionViewCell and overriding apply(_ layoutAttributes: UICollectionViewLayoutAttributes) but it only effects the orange cell-background on initial appearance. to put layout.invalidateLayout() or collectionView.layoutIfNeeded() inside UIView.animate() but it does not seem to have an effect on the size change. Any thoughts, hints, ideas are greatly appreciated ✌️ Cheers! Here is the code I used for the first gif: struct CellContentModel { var height: CGFloat? = 100 } class CellContentController: ObservableObject, Identifiable { let id = UUID() @Published var cellContentModel: CellContentModel init(cellContentModel: CellContentModel) { self.cellContentModel = cellContentModel } } class DataStore { var data: [CellContentController] var dataById: [CellContentController.ID: CellContentController] init(data: [CellContentController]) { self.data = data self.dataById = Dictionary(uniqueKeysWithValues: data.map { ($0.id, $0) } ) } static let testData = [ CellContentController(cellContentModel: CellContentModel()), CellContentController(cellContentModel: CellContentModel(height: 80)), CellContentController(cellContentModel: CellContentModel()) ] } class CollectionViewController: UIViewController { enum Section { case first } var dataStore = DataStore(data: DataStore.testData) private var layout: UICollectionViewCompositionalLayout! private var collectionView: UICollectionView! private var dataSource: UICollectionViewDiffableDataSource<Section, CellContentController.ID>! override func loadView() { createLayout() createCollectionView() createDataSource() view = collectionView } } // - MARK: Layout extension CollectionViewController { func createLayout() { let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50)) let Item = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.8), heightDimension: .estimated(300)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [Item]) let section = NSCollectionLayoutSection(group: group) layout = .init(section: section) } } // - MARK: CollectionView extension CollectionViewController { func createCollectionView() { collectionView = .init(frame: .zero, collectionViewLayout: layout) let doubleTapGestureRecognizer = DoubleTapGestureRecognizer() doubleTapGestureRecognizer.doubleTapAction = { [unowned self] touch, _ in let touchLocation = touch.location(in: collectionView) guard let touchedIndexPath = collectionView.indexPathForItem(at: touchLocation) else { return } let touchedItemIdentifier = dataSource.itemIdentifier(for: touchedIndexPath)! dataStore.dataById[touchedItemIdentifier]!.cellContentModel.height = dataStore.dataById[touchedItemIdentifier]!.cellContentModel.height == 100 ? nil : 100 } collectionView.addGestureRecognizer(doubleTapGestureRecognizer) } } // - MARK: DataSource extension CollectionViewController { func createDataSource() { let cellRegistration = UICollectionView.CellRegistration<UICollectionViewCell, CellContentController.ID>() { cell, indexPath, itemIdentifier in let cellContentController = self.dataStore.dataById[itemIdentifier]! cell.contentConfiguration = UIHostingConfiguration { TextView(cellContentController: cellContentController) } .background(.orange) } dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier) } var initialSnapshot = NSDiffableDataSourceSnapshot<Section, CellContentController.ID>() initialSnapshot.appendSections([Section.first]) initialSnapshot.appendItems(dataStore.data.map{ $0.id }, toSection: Section.first) dataSource.applySnapshotUsingReloadData(initialSnapshot) } } class DoubleTapGestureRecognizer: UITapGestureRecognizer { var doubleTapAction: ((UITouch, UIEvent) -> Void)? override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) { if touches.first!.tapCount == 2 { doubleTapAction?(touches.first!, event) } } } struct TextView: View { @StateObject var cellContentController: CellContentController var body: some View { Text(cellContentController.cellContentModel.height?.description ?? "nil") .frame(height: cellContentController.cellContentModel.height, alignment: .top) .background(.green) } }
Posted Last updated
.
Post not yet marked as solved
1 Replies
106 Views
In this documentation for completeRequest(returningItems:completionHandler:), there is a box shaded yellow that says: Important If the system calls your block with an expired value of true, you must immediately suspend your app extension. If you fail to do this, the system terminates your extension’s process. How does my app or my Share Extension know when the system calls the block spoken of?
Posted Last updated
.
Post not yet marked as solved
0 Replies
47 Views
I have this code to adjust UITextView when keyboard is about to be displayed. @objc func keyboardWillShow(notification: NSNotification) { if let rectValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue { let keyboardSize = rectValue.cgRectValue.size let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height - view.safeAreaInsets.bottom, right: 0) textView.contentInset = contentInsets textView.scrollIndicatorInsets = contentInsets } } I see setting contentInset automatically creates a scrolling animation (after the keyboard appears fully) that makes the text at the cursor visible. The animation happens automatically and there is no way to disable it. I want to scroll to a given location in the textView sometimes when the keyboard is presented (preferably, animating it along with keyboard appearance). The implicit contentInset animation makes it impossible however. First the keyboard animates, then contentInset animates, and now only can I animate to my chosen location in textView. This is awkward. I am wondering what is the right way to achieve it?
Posted Last updated
.
Post not yet marked as solved
0 Replies
144 Views
I made an UICollectionView that uses a CompositionalLayout, DiffableDataSource, the new UIHostingConfiguration and an ObservableObject. You can resize cells by double tapping them (see gif + example code). The resizing is triggered by updating the ObservableObject. Now I want to set an animation mainly to animate the shrinking as well as the size change of the last cell but I can't seem to find the right way to do so. By default there is no animation when shrinking and on the last cell: While there are many guides on how to create dynamically resizeable cells they all either use changes in Autolayout constraints (which can't be used with UIHostingConfiguration - correct me if I'm wrong) or they add an optional part to the view inside UIHostingConfiguration with "if some condition {MyAdditionalView(); .transition(someTransition)}" instead of changing its frame. I also tried these different ways to manipulate the animation but with no success: setting an animation modifier .animation(): this makes a fading animation appear and the view inside the hosting configuration starts to jump (It seems to be anchored in the centre of the cell). setting a transition modifier .transition(): this has no effect on the animation. subclassing UICompositionalLayout and overriding initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) as well as finalLayoutAttributesForDisappearingItem(at itemIndexPath: IndexPath): this has no effect on the animation. subclassing UICollectionViewCell and overriding apply(_ layoutAttributes: UICollectionViewLayoutAttributes): this only effects the orange cell-background on initial appearance. using snapshot.reloadItems([ItemIdentifier]) or snapshot.reconfigureItems([ItemIdentifier]): they have no effect on the animation and lead to inconsistent behaviour when combined with ObservableObject. setting collectionView.selfSizingInvalidation = .enabledIncludingConstraints: no effect. Setting it to .disabled stops the orange cells from resizing altogether. Is there a way to customize the size change animation of a cell using UIHostingConfiguration and ObservableObject? Code without animation: struct CellContentModel {     var height: CGFloat? = 100 } class CellContentController: ObservableObject, Identifiable {     let id = UUID()     @Published var cellContentModel: CellContentModel     init(cellContentModel: CellContentModel) {         self.cellContentModel = cellContentModel     } } class DataStore {     var data: [CellContentController]     var dataById: [CellContentController.ID: CellContentController]     init(data: [CellContentController]) {         self.data = data         self.dataById = Dictionary(uniqueKeysWithValues: data.map { ($0.id, $0) } )     }     static let testData = [         CellContentController(cellContentModel: CellContentModel()),         CellContentController(cellContentModel: CellContentModel(height: 80)),         CellContentController(cellContentModel: CellContentModel())     ] } class CollectionViewController: UIViewController {     enum Section {         case first     }     var dataStore = DataStore(data: DataStore.testData)     private var layout: UICollectionViewCompositionalLayout!     private var collectionView: UICollectionView!     private var dataSource: UICollectionViewDiffableDataSource<Section, CellContentController.ID>!     override func loadView() {         createLayout()         createCollectionView()         createDataSource()         view = collectionView     } } // - MARK: Layout extension CollectionViewController {     func createLayout() {         let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))         let Item = NSCollectionLayoutItem(layoutSize: itemSize)         let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.8), heightDimension: .estimated(300))         let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [Item])         let section = NSCollectionLayoutSection(group: group)         layout = .init(section: section)     } } // - MARK: CollectionView extension CollectionViewController {     func createCollectionView() {         collectionView = .init(frame: .zero, collectionViewLayout: layout)         let doubleTapGestureRecognizer = DoubleTapGestureRecognizer()         doubleTapGestureRecognizer.doubleTapAction = { [unowned self] touch, _ in             let touchLocation = touch.location(in: collectionView)             guard let touchedIndexPath = collectionView.indexPathForItem(at: touchLocation) else { return }             let touchedItemIdentifier = dataSource.itemIdentifier(for: touchedIndexPath)!             dataStore.dataById[touchedItemIdentifier]!.cellContentModel.height = dataStore.dataById[touchedItemIdentifier]!.cellContentModel.height == 100 ? nil : 100 // <- this triggers the resizing }         collectionView.addGestureRecognizer(doubleTapGestureRecognizer)     } } // - MARK: DataSource extension CollectionViewController {     func createDataSource() {         let cellRegistration = UICollectionView.CellRegistration<C, CellContentController.ID>() { cell, indexPath, itemIdentifier in             let cellContentController = self.dataStore.dataById[itemIdentifier]!             cell.contentConfiguration = UIHostingConfiguration {                 TextView(cellContentController: cellContentController)             }             .background(.orange)         }         dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in             return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)         }         var initialSnapshot = NSDiffableDataSourceSnapshot<Section, CellContentController.ID>()         initialSnapshot.appendSections([Section.first])         initialSnapshot.appendItems(dataStore.data.map{ $0.id }, toSection: Section.first)         dataSource.applySnapshotUsingReloadData(initialSnapshot)     } } class DoubleTapGestureRecognizer: UITapGestureRecognizer {     var doubleTapAction: ((UITouch, UIEvent) -> Void)?     override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {         if touches.first!.tapCount == 2 {             doubleTapAction?(touches.first!, event)         }     } } struct TextView: View {     @StateObject var cellContentController: CellContentController     var body: some View { Text(cellContentController.cellContentModel.height?.description ?? "nil")             .frame(height: cellContentController.cellContentModel.height)             .background(.green)     } }
Posted Last updated
.
Post not yet marked as solved
6 Replies
153 Views
Please help me understand what will be better for the complex app for the Apple platform I read a few articles about UIKit vs SwiftUI and quoted one of the articles <You can choose UIKit if you want maximum control over how your app looks. > this phrase is a little confused me. I know about widgets, rendering ideas, minimum iOS version, live preview, and speed of development, I am not worried about this stuff. This question is easy to get an answer to but with the complex app it's a big problem, I will try to focus on key points for a more accurate representation of the problem. My requirements for the app are: Future supporting, ideally one app for iOS and Mac OS platform( exclude audience that prefers Mac platform for work, UI should be different). Maximum UI control, I mean animation and interaction, the application will be huge. Classic UI like in Apple News, Podcasts, App Store. Complex architecture like VIP. I don’t have enough experience with SwiftUI, but can say that can do all that I want using UIKit, my one complex example with SwiftUI and UIKit was 3D Carousel, and I can say that this is easy using SwiftUI, but it was only one complex stuff which I tried and that’s it In short form, my question is: can I do any interaction and most of the animation using SwiftUI, because I hope in another interaction like DB, etc it will not be a problem.
Posted Last updated
.
Post not yet marked as solved
1 Replies
885 Views
Hello, I'm having a little issue with this code. struct nfcButton : UIViewRepresentable {     @Binding var data: String     @Binding var showData: Bool     func makeUIView(context: UIViewRepresentableContext<nfcButton>) -> UIButton {         let button = UIButton()         button.setImage(UIImage(named: "phoneFinal"), for: .normal)         button.addTarget(context.coordinator, action: #selector(context.coordinator.beginScan(_:)), for: .touchUpInside)         return button     } I just change my image with a better and bigger one. The thing is don't know how to resize it. I tried to add .frame to the structure call like so : nfcButton(data: $data, showData: $showNFCMobile) &#9;&#9;.frame(width: 150.0, height: 250.0) I also tried with resizableImage method but I don't really understand what is the capInsets button.setImage(UIImage(named: "phoneFinal")?.resizableImage(withCapInsets: <#T##UIEdgeInsets#>), for: .normal) I know in my regular view I just need to make like this and it works; Image("Image_name").resizable().frame(width: 150) Thank for your help !
Posted Last updated
.
Post not yet marked as solved
3 Replies
4.7k Views
The top of the keyboard needs to be about 2 inches from the bottom of the *device* as it is held.Prior to the iPhone X, this is easy because all devices used the exact same bezel insets, so it's 216 pts from the bottom of the screen.How do we calculate this height on an iPhone X? Safe area insets alone not sufficient for calculating 2 inches from the bottom of the device. Here's how I'm doing it now:@implementation UIScreen(MyExtensions) - (UIEdgeInsets)standardBezelInsets { CGSize iPhoneXSize = CGSizeMake(375, 812); if (CGSizeEqualToSize(self.bounds.size, iPhoneXSize)) { return (UIEdgeInsets) { .top = 43, .bottom = 74 }; // 290 - 216 } return UIEdgeInsetsZero; } @end @implementation MyKeyboardView - (CGFloat)preferredHeight { return [[UIScreen mainScreen] standardBezelInsets].bottom + 216; } ... @endThere are a few problems with that.Is there a better way?
Posted
by darren11.
Last updated
.
Post not yet marked as solved
0 Replies
67 Views
This issue is driving me crazy. I load an NSAttributedString in UITextView and within moments after loading the foregroundColor attribute of text is erased(i.e becomes white) without me doing anything. Here is the code and NSLog dump. How do I debug this I wonder? class ScriptEditingView: UITextView, UITextViewDelegate { var defaultFont = UIFont.preferredFont(forTextStyle: .body) var defaultTextColor = UIColor.white private func commonInit() { self.font = UIFont.preferredFont(forTextStyle: .body) self.allowsEditingTextAttributes = true self.textColor = defaultTextColor self.backgroundColor = UIColor.black self.isOpaque = true self.isEditable = true self.isSelectable = true self.dataDetectorTypes = [] self.showsHorizontalScrollIndicator = false } } And then in my ViewController that contains the UITextView, I have this code: textView = ScriptEditingView(frame: newTextViewRect, textContainer: nil) textView.delegate = self view.addSubview(textView) textView.allowsEditingTextAttributes = true let guide = view.safeAreaLayoutGuide // 5 textView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ textView.leadingAnchor.constraint(equalTo: guide.leadingAnchor), textView.trailingAnchor.constraint(equalTo: guide.trailingAnchor), textView.topAnchor.constraint(equalTo: view.topAnchor), textView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) textView.attributedText = attributedString NSLog("Attributed now") dumpAttributesOfText() DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { NSLog("Attributes after 1 sec") self.dumpAttributesOfText() } And here is code to dump attributes of text: private func dumpAttributesOfText() { textView.attributedText?.enumerateAttributes(in: NSRange(location: 0, length: textView.attributedText!.length), options: .longestEffectiveRangeNotRequired, using: { dictionary, range, stop in NSLog(" range \(range)") if let font = dictionary[.font] as? UIFont { NSLog("Font at range \(range) - \(font.fontName), \(font.pointSize)") } if let foregroundColor = dictionary[.foregroundColor] as? UIColor { NSLog("Foregroundcolor \(foregroundColor) at range \(range)") } if let underline = dictionary[.underlineStyle] as? Int { NSLog("Underline \(underline) at range \(range)") } }) } The logs show this: 2022-07-02 13:16:02.841199+0400 MyApp[12054:922491] Attributed now 2022-07-02 13:16:02.841370+0400 MyApp[12054:922491] range {0, 14} 2022-07-02 13:16:02.841486+0400 MyApp[12054:922491] Font at range {0, 14} - HelveticaNeue, 30.0 2022-07-02 13:16:02.841586+0400 MyApp[12054:922491] Foregroundcolor UIExtendedGrayColorSpace 1 1 at range {0, 14} 2022-07-02 13:16:02.841681+0400 MyApp[12054:922491] range {14, 6} 2022-07-02 13:16:02.841770+0400 MyApp[12054:922491] Font at range {14, 6} - HelveticaNeue, 30.0 2022-07-02 13:16:02.841855+0400 MyApp[12054:922491] Foregroundcolor kCGColorSpaceModelRGB 0.96863 0.80784 0.27451 1 at range {14, 6} 2022-07-02 13:16:03.934816+0400 MyApp[12054:922491] Attributes after 1 sec 2022-07-02 13:16:03.935087+0400 MyApp[12054:922491] range {0, 20} 2022-07-02 13:16:03.935183+0400 MyApp[12054:922491] Font at range {0, 20} - HelveticaNeue, 30.0 2022-07-02 13:16:03.935255+0400 MyApp[12054:922491] Foregroundcolor UIExtendedGrayColorSpace 1 1 at range {0, 20}
Posted Last updated
.
Post not yet marked as solved
0 Replies
97 Views
Does anyone experience this before? I am using an AVPlayer to present a video. The app has only one .mp4 but for a different use case, the same video needs to get flipped. Both videos (the normal and the flipped one) work fine on iOS 15.5 but the flipped video does not show the play and the 15 seconds forward/backward buttons in iOS 16 (see image attached). The buttons are there and completely functional, you can press the play and the 15 seconds forward/backward buttons but they don't appear in the screen (4th video in the attached image) The code the app is using to flip the video is as follows: (The code that flips the video is in the if block). presenter.present(avPlayerController, animated: true, completion: { let url = URL(fileURLWithPath: path) let avPlayer = self.dependency.avPlayerFactory(url) if doFlip() { let flippedLayer = AVPlayerLayer(player: avPlayer as? AVPlayer) let transform = CGAffineTransform(scaleX: -1.0, y: 1.0) flippedLayer.frame = (avPlayerController as UIViewController).view.frame flippedLayer.setAffineTransform(transform) (avPlayerController as UIViewController).view.layer.addSublayer(flippedLayer) } avPlayerController.player = avPlayer as? AVPlayer avPlayer.play() })
Posted Last updated
.
Post not yet marked as solved
1 Replies
124 Views
I have a problem with grayscale PNG Images which are loaded as completey black Images only on iPad 4 with iOS 10. On newer iPads this problem doesn't appear.The Images are loaded normally from the Filesystem. I also created a Bug Report but i dont get any answer. This Bug doesn' appear when i create a new Image from this grayscale Image with RGBA ColorSpace.
Posted Last updated
.
Post not yet marked as solved
0 Replies
102 Views
XCODE 14 / iOS 16 beta 2 on both simulator and iPad 6, the below warning is issued for all views in my app with a Navigation bar with buttons. Navigation bar colours are customised and buttons added programatically. Is anyone else seeing this? 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.  (     "<NSLayoutConstraint:0x13bb1e2b0 UIImageView:0x135dfcae0.width <= _UIModernBarButton:0x13be321e0.width   (active)>",     "<NSLayoutConstraint:0x13bbf14b0 '_UITemporaryLayoutWidth' _UIButtonBarButton:0x13be31d10.width == 0   (active)>",     "<NSLayoutConstraint:0x13bb844a0 'IB_Leading_Leading' H:|-(>=11)-[_UIModernBarButton:0x13be321e0]   (active, names: '|':_UIButtonBarButton:0x13be31d10 )>",     "<NSLayoutConstraint:0x13bbad9a0 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x13be321e0]-(>=11)-|   (active, names: '|':_UIButtonBarButton:0x13be31d10 )>" ) Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x13bb1e2b0 UIImageView:0x135dfcae0.width <= _UIModernBarButton:0x13be321e0.width   (active)>
Posted
by ptclarke.
Last updated
.
Post not yet marked as solved
1 Replies
75 Views
My viewWillAppear (below) worked before iOS 15.5. Now, as part of super.viewWillAppear the OS calls titleForHeaderInSection, which crashes. It crashes because it calls getHeaderText, which depends on my variable monitor being bound. monitor doesn't get bound until my function setupUserGuideMonitor() is called. class myClass: UITableViewController { var monitor: UserGuideMonitor! override func viewWillAppear(_ animated: Bool) {         super.viewWillAppear(animated)         self.setupUserGuideMonitor()         self.listenForNotifications()     } } There are various ways to fix this, including calling setupUserGuidMonitor before super.viewWillAppear, but my understanding of best practices is that only minimum setup should occur before super gets called. I have a very large code base with lots of other complex viewWillAppear calls and I am worried about other fallout from this change and other similar changes that may have occurred. I found nothing about this in the release notes for 15.5. In general I'd like to know what protocol methods are going to be invoked during a viewWillAppear. It's not like I can look at the source code for UITableViewController.
Posted
by Papley.
Last updated
.