Post

Replies

Boosts

Views

Activity

Reply to How do I enable UILargeContentViewerInteraction on UITabBar outside of UITabBarController?
For what it's worth, here's my implementation to add a UILargeContentViewerInteraction to a UITabBar without using UITabBarController but inside a custom UIViewController. Interaction First, add the interaction to the view of the view controller with the view controller as the interaction delegate. view.showsLargeContentViewer = true view.scalesLargeContentImage = true view.addInteraction(UILargeContentViewerInteraction(delegate: self)) Delegate It's needed to implement tow function of the UILargeContentViewerInteractionDelegate protocol: largeContentViewerInteraction(_:itemAt:) largeContentViewerInteraction(_:didEndOn:at:) Retrieve Item Both functions have to get the index of the tab bar item for the point parameter so here's a function to do that: private func tabItemIndex(for point: CGPoint) -> Int? { let convertedPoint = view.convert(point, to: tabBar) guard tabBar.point(inside: convertedPoint, with: nil), let numberOfItems = tabBar.items?.count, numberOfItems > 0 else { return nil } let itemWidth = tabBar.bounds.width / CGFloat(numberOfItems) return Int(convertedPoint.x / itemWidth) } The function converts the point from the view to the tabBar and ensures the point is inside the tabBar. Then the point x member is divided by the width of an item so that every point targets an item. Large Content Item For the large content item, the view itself is used. It is configured using the retrieved UITabBarItem: func largeContentViewerInteraction( _: UILargeContentViewerInteraction, itemAt point: CGPoint ) -> (any UILargeContentViewerItem)? { guard let tabItemIndex = tabItemIndex(for: point), let item = tabBar.items?[tabItemIndex] else { return nil } view.largeContentTitle = item.title view.largeContentImage = item.image return view } Selecting Item The item is then selected when the interaction ends. func largeContentViewerInteraction( _: UILargeContentViewerInteraction, didEndOn _: (any UILargeContentViewerItem)?, at point: CGPoint ) { guard let tabItemIndex = tabItemIndex(for: point), let item = tabBar.items?[tabItemIndex] else { return } tabBar.selectedItem = item tabBar(tabBar, didSelect: item) // call of UITabBarDelegate }
Sep ’24
Reply to iOS 17 - New status bar default style doesn't work if the status bar was previously hidden
I am facing the same issue with iOS 17.5.1 although I have found a workaround. I noticed that the status bar reset to the desired default behavior when toggling the OS preferred color scheme (light/dark mode). I tried to reproduced such a thing in code and was able to achieve similar results by returning either lightContent or darkContent for preferredStatusBarStyle when updating the status bar appearance after changing its visibility value. Then requesting again an update with the default value for preferredStatusBarStyle. It looks something like this. // returned by `prefersStatusBarHidden` isStatusBarHidden = false // returned by `preferredStatusBarStyle` preferredStyle = .darkContent setNeedsStatusBarAppearanceUpdate() // here we reset to default preferredStyle = .default setNeedsStatusBarAppearanceUpdate() // status bar style should be back to desired default behavior Hoping iOS 18 will fix this issue 🤞
Jun ’24
Reply to Multi Channel Audio With AVAudioEngine, Flipping Audio Channels
Hey ! I stumbled across your post while searching myself, since I found a solution, let me post it here. Goal To recap, I am trying to read several audio files and output them in different channels. In my setup, I have 2 devices that both have two channels so I have 4 channels in the end. I use an aggregate device and run the iOS app with Catalyst (I couldn't make aggregate device work with AVAudioEngine on macOS 🤷‍♂️). I use AVAudioSourceNode as input but it should also work with AVAudioPlayerNode since both have an auAudioUnit property. Setup formats When the engine is being setup, I make sure that the channels count of the output node is 4: let outputFormat = audioEngine.outputNode.outputFormat(forBus: 0) print("Channels count:", outputFormat.channelCount) // 4 If not, this might be because the AVAudioSession is not configured with the multiRoute category. Mixer -> Output Then, I had to connect the engine main mixer node to the output node using the output node format. audioEngine.connect(audioEngine.mainMixerNode, to: audioEngine.outputNode, format: format) I don't know why it's necessary. When I read the doc, it seems that it's already done by default. If the client never sets the connection format between the mainMixerNode and the outputNode, the engine always updates the format to track the format of the outputNode on startup or restart, even after an AVAudioEngineConfigurationChange. Source -> Mixer I also had to connect each source node to the main mixer node using the output format. Otherwise the channel mapping will not be effective. engine.connect(sourceNode, to: engine.mainMixerNode, format: outputFormat) Source channels mapping In the end, I could set the auAudioUnit.channelMap of each source node to output to the desired channels. For instance sourceNode.auAudioUnit.channelMap = [0, 1, -1, -1] to output in the first pair of speakers (default) and sourceNode.auAudioUnit.channelMap = [-1, -1, 0, 1] to output to the second pair of speakers.
Jun ’23
Reply to tvOS search: grid keyboard will not slide when search results are focused
Thanks for taking the time to answer. I still have interrogations if I may: it is said in the video that the keyboard will slide. Is it only for 3rd party apps? the line keyboard does hide for 3rd party apps. Is it different from the grid keyboard? with the grid keyboard it’s not possible to align the leading elements of a collection view with the leading edge of the search container. Not without clipping the elements when focused. Could you tell me if there is a proper solution for that ?
Dec ’22
Reply to tvOS search: grid keyboard will not slide when search results are focused
YouTube is hiding the keyboard too. I wonder if Spotify and YouTube use UIKit or TVMLKit for their search tab. When inspecting the search controller, it embeds the search results controller view inside another view and doesn't set any constraint on it. I guess they only set the frame of the containing view (the X origin is ~500 points). When the keyboard looses the focus, the containing view should have its origin updated to snap to the safe area leading edge, and the keyboard trailing edge should be set to the window leading edge. Maybe they forgot to implement this behavior. Note: I filed a bug through Feedback Assistant two months ago but did not get any answer so far. Still open.
Nov ’22
Reply to Xcode 13.1: What happened to shortcuts on international keyboards?
The shortcuts in Xcode 13.1 were localized: they were the same key combinations for every keyboard and language, or what made the most sense. After a few days using them, I got accustomed and really enjoyed the small boost of productivity they gave me. This was hard at first but the reward was worth it. Now with Xcode 13.2 they took this feature back and I have to mentally remap the shortcuts to the previous one (argh). That's too bad. They may have had to revert the modification because too much people were complaining (may they be right or wrong). Now I am stuck with the previous shortcuts although I have tasted the new ones and preferred them. Maybe the best option would be to let people choose what shortcuts they prefer? Or when to take the step to learn the new shortcuts and get a productivity gain?
Jan ’22
Reply to import PDFKit in MacOS
If anyone ends up on this thread because they can't import PDFKit in a macOS app, especially because of "Undefined symbols", that's because the right way to do it is import Quartz.PDFKit I don't know why it's not mentioned in the documentation page - https://developer.apple.com/documentation/pdfkit/pdfview since the one - https://developer.apple.com/documentation/quartz/pdfkit talking about it seems to be a mirror. Anyway, you can checkout the WWDC17 video - https://developer.apple.com/videos/play/wwdc2017/241/ about that (first example given is with a Cocoa app).
Oct ’20