I'm developing an iOS 14 Catalyst app and I'm trying to setup the window toolbar.
I created a NSToolbar and assigned to the scene window titlebar property.
var toolbarDelegate = ToolbarDelegate()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
#if targetEnvironment(macCatalyst)
guard let windowScene = scene as? UIWindowScene else { return }
let toolbar = NSToolbar(identifier: "main")
toolbar.delegate = toolbarDelegate
toolbar.displayMode = .iconOnly
if let titlebar = windowScene.titlebar {
titlebar.toolbar = toolbar
titlebar.toolbarStyle = .unified
titlebar.titleVisibility = .hidden
}
#endif
}
I then assigned some items to the toolbar via the toolbarDefaultItemIdentifiers delegate method.
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
let identifiers: [NSToolbarItem.Identifier] = [
.toggleSidebar,
.print,
.flexibleSpace,
.print
]
return identifiers
}
This work as expected.
Now, let's say that I want to align some items with the edges of the supplementary column.
I found that there is an NSToolbarItem named supplementarySidebarTrackingSeparatorItemIdentifier.
This item appears to allow us to align items with the supplementary column. If I do this:
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
let identifiers: [NSToolbarItem.Identifier] = [
.toggleSidebar,
.flexibleSpace,
.print,
.supplementarySidebarTrackingSeparatorItemIdentifier,
.print,
.flexibleSpace,
.print
]
return identifiers
}
I got the following result which is exactly what I want to achieve (the items are aligned with the supplementary column):
But there are some issues.
As you can see from the above image for some reason the background color of the toolbar on top of the supplementary column become white. But it's worse. If I resize the window the background instantly become gray:
If I then scroll the content of the supplementary column the toolbar become white again.
Another issue is that If I collapse the primary column the toolbar on top of the supplementary column loose the right separator line. Why?
I tried to search some info online but if I try to search for supplementarySidebarTrackingSeparatorItemIdentifier I got only 5 results! One of these is Apple's official documentation page, which does not contain any info about the behaviour of this item:
Apple documentation about supplementarySidebarTrackingSeparatorItemIdentifier
At this point I wonder if this item is ready to be used in real apps.
Someone has experience using the supplementarySidebarTrackingSeparatorItemIdentifier item?
There is a way to align toolbar items with the supplementary column without having the above described issues? (different toolbar background color, missing toolbar separator line)
Thank you
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Post
Replies
Boosts
Views
Activity
First off, i believe i do know what the option 'Preserve Vector Data' does. But just in case, let me recap: When using PDFs or SVGs in my Asset Catalog, Xcode by default creates assets at fixed sizes from these files at buildtime. When i tick the 'Preserve Vector Data' box, the asset is scaled at runtime using the vector data, allowing for smooth scaling and crisp images at any scale.
But the question i'm asking myself now is what exactly is the drawback - most likely performance-wise - to simply activating this option for each an every SVG or PDF Asset i use in my project?
I would be very happy if someone could elaborate on this or direct me to some more in-depth documentation on Vector Assets :)
I'm using UIDocumentPickerViewController to import document to my app from OneDrive and I want to show the OneDrive folder every time I use UIDocumentPickerViewController instead of the last folder I opened. Is it possible? Can I use pickerController.directoryURL ? And how to get folder URL of OneDrive?
class ViewController: UIViewController, DocumentDelegate {
var picker: DocumentPicker?
override func viewDidLoad() {
super.viewDidLoad()
picker = DocumentPicker(presentationController: self, delegate: self)
}
@IBAction func create_picker(_ sender: Any) {
picker?.presentDocumentPicker()
}
func didPickImage(image: UIImage?) {}
}
protocol DocumentDelegate: AnyObject {
func didPickImage(image: UIImage?)
}
class DocumentPicker: NSObject {
private var pickerController: UIDocumentPickerViewController?
private weak var presentationController: UIViewController?
private weak var delegate: DocumentDelegate?
init(presentationController: UIViewController,
delegate: DocumentDelegate) {
super.init()
self.presentationController = presentationController
self.delegate = delegate
}
func presentDocumentPicker() {
pickerController = UIDocumentPickerViewController(forOpeningContentTypes: [.image])
if let pickerController = pickerController {
pickerController.delegate = self
pickerController.allowsMultipleSelection = false
presentationController?.present(pickerController, animated: true)
}
}
}
extension DocumentPicker: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first else { return }
print(url)
}
}
I'm reworking my app and update code and design. Because my app is one both iPhone and iPad, i'm using Splitview to handle the configurations. But my app has 4 section that I manage using a Tab bar and each tab has a SplitView.
As you can see in images, the problem is that if I attach directly the UISplitViewController to UITabBarController you don't see two columns but only one (the primary or secondary view) both iPhone landscape orientation and iPad.
A solution that I found is to attach the splitviewcontroller to a view that contains a ContainerViewController e connect the split view to this container. If you do this, you see the split view work correctly ma the problem is the customization of appearance (look at image 3)
So may questions are:
why I have to embed a split view in a container view controller and i can't connect it directly to tabbar as we done until now?
Is there an other better solution then put a split view in a containerView?
Thank you
)
My application is currently crashing in production in iPhone devices running iOS 15.x. The app will work as normal while running developer mode, enterprise builds and Test Flight builds. Unfortunately, I am unable to reproduce this issue even app is downloaded from the app store.
I observed crash is happening at main.m.
Can someone help me to reproduce this issue?
How to read this crash log file?
Please find the crash log details attached.
2022-03-04_14-15-23.6227_+0900-a1899fd803a4ed683466702be71b9d224b4cd5bc.crash
Hi dear , I am a beginner developer
I have an application idea , and I think its great idea 😎
I think the application needs to use Device activity frame work , and UIScreen class , even if the app is in background or terminated , the problem is I don't know how to use these classes and frameworks 🤷🏻♂️
the questions are :
can I detect UITouch event on UIScreen object even if the app is in background or terminated
How to get the current activity name of the device
We are currently trying to adopt the newly introduced find bar in our app.
The app:
The app is a text editor with a main text view. However it includes nested views (for text like footnotes) that are presented as modal sheets. So you tap on the footnote within the main text, a form sheet is presented with the contents of the footnote ready to be edited. We have an existing search implementation, but are eager to move to the system-provided UI. Connecting the find bar through a custom UIFindSession with our existing implementation is working without any issues.
The Problem:
Searching for text does not only work in the main text view, but also nested text (like footnotes). Let's say I have a text containing the word "iPhone" both in the main text and the footnote. In our existing implementation, stepping from the search match to the next one would open the modal and highlight the match in the nested text. The keyboard would stay open.
With the new UIFindInteraction this is not working however. As soon as a modal form sheet is presented, the find interaction closes. By looking at the stack trace I can see a private class called UIInputWindowController that cleans up input accessory views after the modal gets presented. I believe it is causing the find panel to give up its first responder state. I noticed that opening popovers appears to be working fine.
Is there a way to alter the presentation of the nested text so that the view is either not modal or able to preserve the current find session? Or is this unsupported behavior and we should try and look for a different way?
The thing that really confuses me is that this appears to work without issue in Notes.app. There the find bar is implemented as well. There are multiple views that can be presented while the find bar is open. Move Note is one of them. The view appears as a modal sheet. It keeps the find bar open and active, though its tint color matches the deactivated one of the main Notes view. The find bar is still functional with the text field being active and the overlay updating in the background. This behavior appears to be a bug in the Notes app, but is exactly what we want for our use case.
I attached some images: Two are from the Notes app, two from a test project demonstrating the problem. Opening a modal view closes the find bar there.
Hey, I'm not sure I'm even in the correct ballpark - trying to allow my app to download largish videos from user's OneDrive and G-Drive to app
Is it correct to use NSFileCoordinator in this way?
How do I report progress as it downloads the video (is it possible?)
Is it correct to dismiss the picker like this?
anything else wrong (or, like is....any of it correct? :)
it's sort of working with my contrived examples (I created new personal G-drive / Onedrive accounts, and copied vids up there), but...when I use a file from our corporate OneDrive, from shared folder, I get:
"NSCocoaErrorDomain Code=3328 "The requested operation couldn’t be completed because the feature is not supported."
Is this the NSFileProvider extension (Microsoft's) complaining?
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first else {
return
}
let isSecurityScoped = url.startAccessingSecurityScopedResource()
print("(#function) - iSecurityScoped = (isSecurityScoped)")
print("(#function) - document at (url)")
let filename = String(UUID().uuidString.suffix(6)) + "_" + url.lastPathComponent
let newURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(filename)
let readingIntent = NSFileAccessIntent.readingIntent(with: url, options: .withoutChanges)
fileCoordinator.coordinate(with: [readingIntent], queue: queue) { error in
defer {
if isSecurityScoped {
url.stopAccessingSecurityScopedResource()
}
}
if let error = error {
print("(#function) - (error)")
return
}
let safeURL = readingIntent.url
do {
let fileData = try Data(contentsOf: safeURL)
try fileData.write(to: newURL, options: .atomic)
print("(#function) - SUCCESS - newURL = (newURL)")
} catch {
print("(#function) - NOOOOO - (error)")
}
}
controller.dismiss(animated: true)
}
Starting iOS 16 seeing some crashes related to pdf printing in the crash reporter. It looks like the issue is not so frequent. Also, I'm unable to reproduce the crash. Looks like the app crashes when the print preview dialog is opening. According to crash reports, there are some crashes on different iOS 16 versions: 16.0.0, 16.0.2, and 16.0.3.
Printing code:
let printInfo = UIPrintInfo.printInfo()
printInfo.jobName = "Printing Job Name"
self.printViewController = UIPrintInteractionController.shared
self.printViewController?.printInfo = printInfo
self.printViewController?.printingItem = pdfURL
self.printViewController?.present(from: barButtonItem, animated: true) { (controller, completed, error) in
self.printViewController = nil
}
Stack trace:
compare_key + 4 (CGPDFObject.c:134)
bsearch + 68 (bsearch.c:70)
CGPDFDictionaryGetUnresolvedObject + 68 (CGPDFDictionary.c:153)
CGPDFDictionaryGetObject + 44 (CGPDFDictionary.c:172)
CGPDFDictionaryGetDictionary + 44 (CGPDFDictionary.c:284)
get_pages_dictionary + 68 (pdf-reader.c:410)
pdf_reader_get_number_of_pages + 76 (pdf-reader.c:557)
-[UIPrintPreviewPageFetcher fetchNumberOfItems] + 76 (UIPrintPreviewPageFetcher.m:115)
-[UIPrintPreviewViewController collectionView:numberOfItemsInSection:] + 32 (UIPrintPreviewViewController.m:482)
-[UICollectionViewData _updateItemCounts] + 220 (UICollectionViewData.mm:335)
-[UICollectionViewData isIndexPathValid:validateItemCounts:] + 52 (UICollectionViewData.mm:348)
-[UICollectionViewData validatedGlobalIndexForItemAtIndexPath:] + 36 (UICollectionViewData.mm:778)
-[UICollectionView _cellForItemAtIndexPath:] + 108 (UICollectionView.m:7112)
-[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:collectionViewAnimator:] + 1384 (UICollectionView.m:9357)
-[UICollectionView _updateRowsAtIndexPaths:updateAction:updates:] + 396 (UICollectionView.m:9104)
-[UICollectionView reloadItemsAtIndexPaths:] + 52 (UICollectionView.m:9124)
-[UIPrintPreviewViewController reloadVisibleItems:] + 256 (UIPrintPreviewViewController.m:568)
__63-[UIPrintPreviewViewController updatePdfURL:options:completed:]_block_invoke_2 + 44 (UIPrintPreviewViewController.m:305)
__NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 24 (NSOperation.m:1545)
-[NSBlockOperation main] + 104 (NSOperation.m:1564)
__NSOPERATION_IS_INVOKING_MAIN__ + 16 (NSOperation.m:2189)
-[NSOperation start] + 708 (NSOperation.m:2206)
There is full stack trace I got from the Organizer
Thanks!
Paging Steve Breen! 😄
I've seen this question asked a zillion times but I've never seen an answer.
Is it possible to configure compositional layout to give you a grid of N columns (say 2 or 3) where each item in each row/group self-size their height, but the heights of those items are then set to be the height of the tallest item in their row.
This is easy to do if you ignore the self-sizing requirement (just use a fixed or absolute item height), but on the surface this doesn't even appear to be possible if you require self-sizing.
What I've Tried
Configuring a layout where the items are set to a fractional height of 1.0 and their group is set to an estimated height (ex: 100). I was hoping compositional layout would interpret this as, "Please self-size the height of the group and make each item 100% of that height." Unfortunately, compositional layout just uses the estimate you provide for the height as the actual height and no self-sizing occurs at all. Sad panda. 🐼
Use visibleItemsInvalidationHandler to attempt to identify which items share a row and reset their heights to be the height of the tallest item in that row. Sadly, the handler doesn't really have access to the data it needs to do this, nor is it allowed to change frames, nor is it called on the first layout pass, nor does it appear to be supported at all for layouts containing estimated items. In fact, if you try to use it with layouts that support self-sizing, you'll get this error message:
[UICompositionalLayout] note: the section invalidation handler cannot currently mutate visible items for layouts containing estimated items. Please file an enhancement request on UICollectionView.
Wishing upon a star. Oh, and I also filed a radar asking: FB11776888
Here's a visual aid:
I have a little test program as well, but unfortunately I can't upload it here. Happy to share if it would be helpful. Here are a couple snippets:
#1
// This doesn't work
private func makeLayout1() -> UICollectionViewCompositionalLayout {
// Item
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
// Group
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(100))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, repeatingSubitem: item, count: 2)
group.interItemSpacing = .fixed(10)
// Section
let section = NSCollectionLayoutSection(group: group)
return UICollectionViewCompositionalLayout(section: section)
}
#2
// This self-sizes the heights of the items, but allows the items in each row to be different heights rather than providing any way to constrain them to the height of the tallest self-sized item in each row
private func makeLayout2() -> UICollectionViewCompositionalLayout {
// Item
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .estimated(100))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
// Group
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(100))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, repeatingSubitem: item, count: 2)
group.interItemSpacing = .fixed(10)
// Section
let section = NSCollectionLayoutSection(group: group)
return UICollectionViewCompositionalLayout(section: section)
}
Options?
My guess is that compositional layout simply doesn't support layouts that require a "partial second pass" per group, where the frames of the items can be updated based on information collected during self-sizing the other items in the group (to, for example, force them all to a common height, or align them top/bottom/centered within their group).
If that's the case (not supported), I would love a suggestion for where I might override the layout to provide this capability.
Thank you! ❤️
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?
UILargeContentViewerInteraction, added in iOS 13, works out of the box on the tab bar in a UITabBarController, and it's easy to set up on a custom view using the UILargeContentViewerItem properties on UIView. But how do I set it up on a UITabBar that's not connected to a UITabBarController? There don't appear to be any relevant properties on UITabBarItem.
To try this, I made a sample app, added a tab bar, set up some items, set their largeContentSizeImage properties for good measure, ran the app, set text size to a large accessibility value, and long-pressed on the items, and I get no large content viewer.
I also tried adding a UILargeContentViewerInteraction to the tab bar, and implemented the viewControllerForInteraction method in the delegate.
Is there a way to observe the currentEDRHeadroom property of UIScreen for changes? KVO is not working for this property...
I understand that I can query the current headroom in the draw(...) method to adapt the rendering. However, our apps only render on-demand when the user changes parameters. But we would also like to re-render when the current EDR headroom changes to adapt the tone mapping to the new environment.
The only solution we've found so far is to continuously query the screen for changes, which doesn't seem ideal. It would be better if the property would be observable via KVO or if there would be a system notification to listen for.
Thanks!
Our app has a Crash, here is the Crash report. How should I investigate this error?
Fatal Exception: NSInvalidArgumentException
0 CoreFoundation 0x9e48 __exceptionPreprocess
1 libobjc.A.dylib 0x178d8 objc_exception_throw
2 UIKitCore 0x326cbc -[UIViewController _presentViewController:withAnimationController:completion:]
3 UIKitCore 0x325c10 __63-[UIViewController _presentViewController:animated:completion:]_block_invoke
4 UIKitCore 0x349598 -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:]
5 UIKitCore 0x2b7a48 -[_UIViewControllerTransitionContext _runAlongsideCompletions]
6 UIKitCore 0x2b6ad8 -[_UIViewControllerTransitionContext completeTransition:]
7 UIKitCore 0x2b7c38 -[UITransitionView notifyDidCompleteTransition:]
8 UIKitCore 0x2b7838 -[UITransitionView _didCompleteTransition:]
9 UIKit 0xa7e58 -[UITransitionViewAccessibility _didCompleteTransition:]
10 UIKitCore 0x103d464 __UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__
11 UIKitCore 0xd14ac -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:]
12 UIKitCore 0xd0408 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]
13 UIKitCore 0xcfb28 -[UIViewAnimationState animationDidStop:finished:]
14 UIKit 0xb0f50 -[UIViewAnimationStateAccessibility animationDidStop:finished:]
15 UIKitCore 0xcfc3c -[UIViewAnimationState animationDidStop:finished:]
16 UIKit 0xb0f50 -[UIViewAnimationStateAccessibility animationDidStop:finished:]
17 QuartzCore 0x1310c CA::Layer::run_animation_callbacks(void*)
18 libdispatch.dylib 0x3fdc _dispatch_client_callout
19 libdispatch.dylib 0x127f4 _dispatch_main_queue_drain
20 libdispatch.dylib 0x12444 _dispatch_main_queue_callback_4CF
21 CoreFoundation 0x9a6d8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
22 CoreFoundation 0x7c03c __CFRunLoopRun
23 CoreFoundation 0x80ec0 CFRunLoopRunSpecific
24 GraphicsServices 0x1368 GSEventRunModal
25 UIKitCore 0x3a186c -[UIApplication _run]
26 UIKitCore 0x3a14d0 UIApplicationMain
27 Authenticator 0x9334 main + 26 (AppDelegate.swift:26)
28 ??? 0x1b65de960 (シンボルが不足しています)
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.
I have an app that uses UITextView for some text editing. I have some custom operations I can do on the text that I want to be able to undo, and I'm representing those operations in a way that plugs into NSUndoManager nicely. For example, if I have a button that appends an emoji to the text, it looks something like this:
func addEmoji() {
let inserting = NSAttributedString(string: "😀")
self.textStorage.append(inserting)
let len = inserting.length
let range = NSRange(location: self.textStorage.length - len, length: len)
self.undoManager?.registerUndo(withTarget: self, handler: { view in
view.textStorage.deleteCharacters(in: range)
}
}
My goal is something like this:
Type some text
Press the emoji button to add the emoji
Trigger undo (via gesture or keyboard shortcut) and the emoji is removed
Trigger undo again and the typing from step 1 is reversed
If I just type and then trigger undo, the typing is reversed as you'd expect. And if I just add the emoji and trigger undo, the emoji is removed. But if I do the sequence above, step 3 works but step 4 doesn't. The emoji is removed but the typing isn't reversed.
Notably, if step 3 only changes attributes of the text, like applying a strikethrough to a selection, then the full undo chain works. I can type, apply strikethrough, undo strikethrough, and undo typing.
It's almost as if changing the text invalidates the undo manager's previous operations?
How do I insert my own changes into UITextView's NSUndoManager without invalidating its chain of other operations?
Our app crashes intermittently when calling performSegue(withIdentifier:,sender:). The segue does exist, as most of the time it works fine. The destination view controller only has its view as a connection. Crash report excerpt below. Uploading the crash report isn't working for some reason, so I'll try to do so as a reply.
The stack trace shows searchForClientURL... as the last part of our code that gets executed.
I'm curious if I should look at things in our code that happen while the segue is being performed such as prepare(for:, sender:), the init of the destination controller, etc. or not because they're not showing up in the stack trace.
Thanks for any help!
0 CoreFoundation 0x19e310e38 __exceptionPreprocess + 164 (NSException.m:202)
1 libobjc.A.dylib 0x19749f8d8 objc_exception_throw + 60 (objc-exception.mm:356)
2 UIKitCore 0x1a1306630 __66-[UIStoryboardPushSegueTemplate newDefaultPerformHandlerForSegue:]_block_invoke + 880 (UIStoryboardPushSegueTemplate.m:58)
3 UIKitCore 0x1a08f3c84 -[UIStoryboardSegueTemplate _performWithDestinationViewController:sender:] + 172 (UIStoryboardSegueTemplate.m:134)
4 UIKitCore 0x1a08f3ba4 -[UIStoryboardSegueTemplate _perform:] + 68 (UIStoryboardSegueTemplate.m:121)
5 UIKitCore 0x1a0cc74c0 -[UIViewController performSegueWithIdentifier:sender:] + 300 (UIViewController.m:5017)
6 AWApp 0x10061ce38 closure #1 in ClientSelectorViewController.searchForClientURL(nameOrGUID:shouldTestSession:) + 3616 (ClientSelectorViewController.swift:231)
For those with existing projects that rely on a SceneDelegate and are primarily UIKit-based, I am curious how one might launch a window with a style of volumetric or an ImmersiveSpace. Is this possible without having a SwiftUI-based @Main entry point?
On iOS17, UIDevice.current.batteryLevel is returning values rounded to 0.05, such as 1, 0.95, 0.9. Which used to be a 1% granularity in iOS16. Is this a bug or a new feature?
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()
}
}