I have a SwiftUI View I've introduced to a UIKit app, using UIHostingController. The UIView instance that contains the SwiftUI view is animated using auto layout constraints. In this code block, when a view controller's viewDidAppear method I'm creating the hosting controller and adding its view as a subview of this view controller's view, in addition to doing the Container View Controller dance.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let hostingViewController = UIHostingController(rootView: TestView())
hostingViewController.view.translatesAutoresizingMaskIntoConstraints = false
addChild(hostingViewController)
view.addSubview(hostingViewController.view)
let centerXConstraint = hostingViewController.view.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let topConstraint = hostingViewController.view.topAnchor.constraint(equalTo: view.topAnchor)
widthConstraint = hostingViewController.view.widthAnchor.constraint(equalToConstant: 361)
heightConstraint = hostingViewController.view.heightAnchor.constraint(equalToConstant: 342)
NSLayoutConstraint.activate([centerXConstraint, topConstraint, widthConstraint, heightConstraint])
hostingViewController.didMove(toParent: self)
self.hostingViewController = hostingViewController
}
I add a button to the UI which will scale the UIHostingViewController by adjusting its height and width constraints. When it's tapped, this action method runs.
@IBAction func animate(_ sender: Any) {
widthConstraint.constant = 120.3
heightConstraint.constant = 114.0
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}
The problem is, the SwiftUI view's contents "jump" at the start of the animation to the final height, then animate into place. I see this both using UIView.animate the UIKit way, or creating a SwiftUI animation and calling `UIView.
What else do I need to add to make this animate smoothly?
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Post
Replies
Boosts
Views
Activity
In the header for UIViewController, the method dismissViewControllerAnimated is declared like this:
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion NS_SWIFT_DISABLE_ASYNC API_AVAILABLE(ios(5.0));
NS_SWIFT_DISABLE_ASYNC means that there's no async version exposed like there would normally be of a method that exposes a completion handler. Why is this? And is it unwise / unsafe for me to make my own async version of it using a continuation?
My use case is that I want a method that will sequentially dismiss all view controllers presented by a root view controller. So I could have this extension on UIViewController:
extension UIViewController {
func dismissAsync(animated: Bool) async {
await withCheckedContinuation { continuation in
self.dismiss(animated: animated) {
continuation.resume()
}
}
}
func dismissPresentedViewControllers() async {
while self.topPresentedViewController != self {
await self.topPresentedViewController.dismissAsync(animated: true)
}
}
var topPresentedViewController: UIViewController {
var result = self
while result.presentedViewController != nil {
result = result.presentedViewController!
}
return result
}
in iOS, user can set focus on UItextField and tapping a key in the virtual keyboard updates the text in the textfield. This user action causes the relevant delegates of UITextFieldDelegate to get invoked, i.e the handlers associated with action of user entering some text in the textfield.
I m trying to simulate this user action where I am trying to do this programatically. I want to simulate it in a way such that all the handlers/listeners which otherwise would have been invoked as a result of user typing in the textfield should also get invoked now when i am trying to do it programatically. I have a specific usecase of this in my application.
Below is how I m performing this simulation.
I m manually updating the text field associated(UITextField.text) and updating its value.
And then I m invoking the delegate manually as textField.delegate?.textField?(textField, shouldChangeCharactersIn: nsRange, replacementString: replacementString)
I wanted to know If this is the right way to do this. Is there something better available that can be used, such that simulation has the same affect as the user performing the update?
I want SensorKit data for research purposes in my current application. I have applied for and received permission from Apple to access SensorKit data.
During implementation, I encountered an issue in which no data was being retrieved despite granting all the necessary permissions.
I am using did CompleteFetch & didFetchResult delegate methods for retrieving data from Sensorkit. CompleteFetch method calls but where I can find different event data like Device usage, Ambient Light, etc? & didFetchResult method does not call.
Methods I am using:
1. func sensorReader(_ reader: SRSensorReader, didCompleteFetch fetchRequest: SRFetchRequest)
2. func sensorReader(_ reader: SRSensorReader, fetching fetchRequest: SRFetchRequest, didFetchResult result: SRFetchResult<AnyObject>) -> Bool
Could anyone please assist me in resolving this issue? Any guidance or troubleshooting steps would be greatly appreciated.
I wanted to perform simulation in my application as a self tour guide for my user. For this I want to programatically simulate various user interaction events like button click, keypress event in the UITextField or moving the cursor around in the textField. These are only few examples to state, it can be any user interaction event or other events.
I wanted to know what is the apple recommendation on how should these simulations be performed? Is there something that apple offers like creating an event which can be directly executed for simulations. Is there some library available for this purpose?
I writing swift code to change the app icon using setAlternateIconName and flutter MethodChannel to invoke swift.
UIApplication.shared.setAlternateIconName(iconName) { error in
if let error = error {
print("Error setting alternate icon: \(error.localizedDescription)")
result(FlutterError(code: "ICON_CHANGE_ERROR", message: error.localizedDescription, details: nil)) // Send error back to Flutter
} else {
print("App icon changed successfully!")
result(nil) // Success!
}
}
But I got an error message the requested operation couldn't be completed because the feature is not supported when using it on iOS 17+.
So, Is setAlternateIconName still available?
PS. In XCode, the code hinting shows that setAlternateIconName is still not deprecated.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
do {
let shapeLayer = CAShapeLayer()
shapeLayer.frame = CGRect(x: 50, y: 100, width: 200, height: 108)
let path = UIBezierPath(roundedRect: shapeLayer.bounds, cornerRadius: 36)
shapeLayer.path = path.cgPath
shapeLayer.fillColor = UIColor.orange.cgColor
view.layer.addSublayer(shapeLayer)
}
do {
let layer = CALayer()
layer.backgroundColor = UIColor.blue.cgColor
layer.cornerRadius = 36
layer.frame = CGRect(x: 50, y: 300, width: 200, height: 108)
view.layer.addSublayer(layer)
}
}
}
The corner radius is set to 36 through CAShapeLayer, but the actual effect is larger than 36, close to half of the height.
Setting it through CALayer is fine
Can anyone explain it to me? Thank you
I'm having this problem, with this code:
let docPicker = UIDocumentPickerViewController(forOpeningContentTypes: [
.pdf
])
docPicker.delegate = self
docPicker.modalPresentationStyle = .currentContext
view.window?.rootViewController?.present(docPicker, animated: true, completion: nil)
but then when I open the simulator and click the button that calls to the method that has this code...
Cannot pick the pdf document.
Testing in browserstack with real devices is working, but it's a very slow process, why I cannot use simulators to make work this?
I found a memory leak in tvOS 17.4, but it's not happening in tvOS 18.0
here is the code flow
1.I have controller inside which I have tableView which in turn contains a collectionview
here I have passed self to tableViewcell as delegate and then from tableview cell I have passed self again as delegate to collectionViewcell, but memory is not released, because self is retained
"I have passed self as weak every where still memory leak is happening only in tvOS 17.4 and below versions. but in 18.0 and above versions it's fine"
IOS 12 - 18.1.1 - objective C, Xcode 16.0
App runs on both iPhone and iPad, this issue only occurs happens on iPads. For the iPhones I am able to get a decent numeric only keyboard to display.
I pulled down NumericKeypad from GitHub and used that a model on how to implement a custom keypad.
In the inputView of the delegate, a new custom text field is create and then assigned a delegate and other properties then it returns the view to the main ViewController. When the ViewControllers and the correct text field is entered my custom keyboard display and the buttons respond but nothing is displayed in the text field. This has worked for years and all of the sudden it stopped.
The original project for the example 10 key custom keyboard builds and when loaded that works on the iPad. If I comment out condition to only execute if running on an iPad and test with an iPhone the keyboards works.
It is only on a iPad that this happens.
This is the cod that creates creates the keyboard from a .xib file. I am using a storyboard for the main app.
#import "Numeric10KeyTextField.h"
#import "Numeric10KeyViewController.h"
@implementation Numeric10KeyTextField
(UIView *)inputView {
UIView *view = nil;
Numeric10KeyViewController *numVC;
// Add hook here for iPhone or other devices if needed but now return nil if iPhone so it uses the default
// if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
numVC = [[Numeric10KeyViewController alloc] initWithNibName:@"Numeric10Key" bundle:nil];
[numVC setActionSubviews:numVC.view];
numVC.delegate = self.numeric10KeyDelegate;
numVC.numpadTextField = self;
view = numVC.view;
// }
return view;
}
@end
I create a notification with an image attachment:
let center = UNUserNotificationCenter.current()
center.delegate = self
let content = UNMutableNotificationContent()
// some more stuff…
let paths = NSSearchPathForDirectoriesInDomains(
FileManager.SearchPathDirectory.documentDirectory,
FileManager.SearchPathDomainMask.userDomainMask, true)
let documentsDirectory = paths[0] as NSString
let fileExtPNG = "#" + "\(imageName)" + " photo.png"
let fileNamePNG = documentsDirectory.appendingPathComponent(fileExtPNG) as String
url = URL(fileURLWithPath: fileNamePNG)
let attachment = try UNNotificationAttachment(identifier: "Image", url: url, options: nil)
content.attachments = [attachment]
I then add the request:
let request = UNNotificationRequest(identifier:requestIdentifier, content: content, trigger: nil)
center.removePendingNotificationRequests(withIdentifiers: [requestIdentifier])
center.add(request) {(error) in }
Problem: when I later test (once notification has been registered), the file do not exist anymore at the url.
I've commented out the add request to confirm.
I have a work around, by creating a temporary copy of the file at the URL and pass it in the attachment.
Then, everything works fine and the copy is deleted.
But that's a bit bizarre. What am I missing here ?
Hello!
I’m experiencing a crash in my iOS/iPadOS app related to a CALayer rendering process. The crash occurs when attempting to render a UIImage on a background thread. The crashes are occurring in our production app, and while we can monitor them through Crashlytics, we are unable to reproduce the issue in our development environment.
Relevant Code
I have a custom view controller that handles rendering CALayers onto images. This method creates a CALayer on the main thread and then starts a detached task to render this CALayer into a UIImage. The whole idea is learnt from this StackOverflow post: https://stackoverflow.com/a/77834613/9202699
Here are key parts of my implementation:
class MyViewController: UIViewController {
@MainActor
func renderToUIImage(size: CGSize, itemsToDraw: [MyDrawingItem], transform: CGAffineTransform) async -> UIImage? {
// Create CALayer and add it to the view.
CATransaction.begin()
let customLayer = MyDrawingLayer()
customLayer.setupContent(itemsToDraw: itemsToDraw)
// Position the frame off-screen to it hidden.
customLayer.frame = CGRect(
origin: CGPoint(x: -100 - size.width, y: -100 - size.height),
size: size)
customLayer.masksToBounds = true
customLayer.drawsAsynchronously = true
view.layer.addSublayer(customLayer)
CATransaction.commit()
// Render CALayer to UIImage in background thread.
let image = await Task.detached {
customLayer.setNeedsDisplay()
let renderer = UIGraphicsImageRenderer(size: size)
let image = renderer.image { // CRASH happens on this line
let cgContext = $0.cgContext
cgContext.saveGState()
cgContext.concatenate(transform)
customLayer.render(in: cgContext)
cgContext.restoreGState()
}
return image
}.value
// Remove the CALayer from the view.
CATransaction.begin()
customLayer.removeFromSuperlayer()
CATransaction.commit()
return image
}
}
class MyDrawingLayer: CALayer {
var itemsToDraw: [MyDrawingItem] = []
func setupContent(itemsToDraw: [MyDrawingItem]) {
self.itemsToDraw = itemsToDraw
}
override func draw(in ctx: CGContext) {
for item in itemsToDraw {
// Render the item to the context (example pseudo-code).
// All items are thread-safe to use.
// Things to draw may include CGPath, CGImages, UIImages, NSAttributedString, etc.
item.draw(in: ctx)
}
}
}
Crash Log
The crash occurs at the following location:
Crashed: com.apple.root.default-qos.cooperative
0 MyApp 0x5cb300 closure #1 in closure #1 in MyViewController.renderToUIImage(size: CGSize, itemsToDraw: [MyDrawingItem], transform: CGAffineTransform) + 4313002752 (<compiler-generated>:4313002752)
1 MyApp 0x5cb300 closure #1 in closure #1 in MyViewController.renderToUIImage(size: CGSize, itemsToDraw: [MyDrawingItem], transform: CGAffineTransform) + 4313002752 (<compiler-generated>:4313002752)
2 MyApp 0x1a4578 AnyModifier.modified(for:) + 4308649336 (<compiler-generated>:4308649336)
3 MyApp 0x7b4e64 thunk for @escaping @callee_guaranteed (@guaranteed UIGraphicsPDFRendererContext) -> () + 4315008612 (<compiler-generated>:4315008612)
4 UIKitCore 0x1489c0 -[UIGraphicsRenderer runDrawingActions:completionActions:format:error:] + 324
5 UIKitCore 0x14884c -[UIGraphicsRenderer runDrawingActions:completionActions:error:] + 92
6 UIKitCore 0x148778 -[UIGraphicsImageRenderer imageWithActions:] + 184
7 MyApp 0x5cb1c0 closure #1 in MyViewController.renderToUIImage(size: CGSize, itemsToDraw: [MyDrawingItem], transform: CGAffineTransform) + 100 (FileName.swift:100)
8 libswift_Concurrency.dylib 0x60f5c swift::runJobInEstablishedExecutorContext(swift::Job*) + 252
9 libswift_Concurrency.dylib 0x62514 swift_job_runImpl(swift::Job*, swift::SerialExecutorRef) + 144
10 libdispatch.dylib 0x15ec0 _dispatch_root_queue_drain + 392
11 libdispatch.dylib 0x166c4 _dispatch_worker_thread2 + 156
12 libsystem_pthread.dylib 0x3644 _pthread_wqthread + 228
13 libsystem_pthread.dylib 0x1474 start_wqthread + 8
Questions
Is it safe to run UIGraphicsImageRenderer.image on the background thread?
Given that I want to leverage GPU rendering, what are some best practices for rendering images off the main thread while ensuring stability?
Are there alternatives to using UIGraphicsImageRenderer for background rendering that can still take advantage of GPU rendering?
It is particularly interesting that the crash logs indicate the error may be related to UIGraphicsPDFRendererContext (crash log line number 3). It would be very helpful if someone could explain the connection between starting and drawing on a UIGraphicsImageRenderer and UIGraphicsPDFRendererContext.
Any insights or guidance on this issue would be greatly appreciated. Thanks!!!
When picking a photo in the gallery, whatever the orientation of the original image, size is always as landscape
if let image = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.editedImage)] as? UIImage {
print("picked original", image.size)
For a portrait photo:
picked original (1122.0, 932.0)
For a landscape:
picked original (1124.0, 844.0)
What am I missing ?
I have a setup:
Collection view with compositional layout
a self sizing cell inside
a subview inside the cell
and unrelated view outside the collection view
I would like to:
modify the layout (constraints) of the cell inside the collection view with UIView.animate
trigger an animated layout update of collection view
synchronize the position of an unrelated view to the position of one of the subviews of a collection view cell
What I tried:
UIView.animate(withDuration: 0.25) {
cellViewReference.updateState(state: state, animated: false)
collectionView.collectionViewLayout.invalidateLayout()
collectionView.layoutIfNeeded()
someOtherViewOutsideCollectionView.center = cellViewReference.getPositionOfThatOneViewInWindowCoordinateSystem()
}
What I'm expecting:
after invalidateLayout, the layout update of the collection view is merely scheduled, but not yet performed
layoutIfNeeded forces an update on the collectionViewLayout + update on the frames of the views inside the UICollectionViewCells
all the frames become correct to what they will look like after the animation is performed
I call getPositionOfThatOneViewInWindowCoordinateSystem and it gives me the position of the view after the uicollectionview AND the cell's layout has updated
What happens instead:
getPositionOfThatOneViewInWindowCoordinateSystem returns me an old value
I am observing that the bounds of the cell didn't actually change during layoutIfNeeded
And moreover, the bounds change without animation, instantly
Question:
how to animate self sizing cell size change due relayout
how to synchronize outside views with collection views
When pushing a page in the navigation, changing the state of interactivePopGestureRecognizer causes the page to freeze.
Just like this:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
CGFloat red = (arc4random_uniform(256) / 255.0);
CGFloat green = (arc4random_uniform(256) / 255.0);
CGFloat blue = (arc4random_uniform(256) / 255.0);
CGFloat alpha = 1.0; //
self.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0, 0, 100, 44);
btn.backgroundColor = [UIColor redColor];
btn.center = self.view.center;
[btn setTitle:@"push click" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)click:(id)sender {
[self.navigationController pushViewController:[ViewController new] animated:YES];
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
@end
Modern collection views use UICollectionViewDiffableDataSource with UICollectionView.CellRegistration and UICollectionView.dequeueConfiguredReusableCell(registration:indexPath:item).
There are runtime crashes when passing nil as argument for the item parameter. There's no clear documentation on whether optional items are allowed or not.
The function signature in Swift is:
@MainActor @preconcurrency func dequeueConfiguredReusableCell<Cell, Item>(using registration: UICollectionView.CellRegistration<Cell, Item>, for indexPath: IndexPath, item: Item?) -> Cell where Cell : UICollectionViewCell
Given the Item? type one would assume Optionals are allowed.
In Objective-C the signature is:
- (__kindof UICollectionViewCell *)dequeueConfiguredReusableCellWithRegistration:(UICollectionViewCellRegistration *)registration forIndexPath:(NSIndexPath *)indexPath item:(id)item;
I'm not sure, if there's implicit nullability bridging to the Swift API or if the Objective-C files has some explicit nullability annotation.
The crash is due to a swift_dynamicCast failing with:
Could not cast value of type '__SwiftNull' (0x10b1c4dd0) to 'Item' (0x10d6086e0).
It's possible to workaround this by making a custom Optional type like
enum MyOptional<T> {
case nothing
case something(T)
}
and then wrapping and unwrapping Item? to MyOptional<Item>. But this feels like unnecessary boilerplate.
With the current situation it's easy to ship an app where everything seems to work, but in production only certain edge cases cause nil values being used and then crashing the app.
Please clarify the allowed arguments / types for the dequeueConfiguredReusableCell function.
Either Optionals should be supported and not crash at runtime or the signatures should be changed so there's a compile time error, when trying to use an Item?.
Feedback: FB16494078
My app is experiencing a recurring crash in the PRD environment, but it cannot be reproduced locally or in QA testing.
Below is the crash log—I’d appreciate any help or insights on how to diagnose and resolve this issue. Thank you!
0 libobjc.A.dylib 0x2354 objc_release_x0 + 16
1 libobjc.A.dylib 0x2354 objc_release + 16
2 libobjc.A.dylib 0x4e38 AutoreleasePoolPage::releaseUntil(objc_object**) + 204
3 libobjc.A.dylib 0x4b8c objc_autoreleasePoolPop + 260
4 FrontBoardServices 0x1f4d0 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 176
5 FrontBoardServices 0x2eb90 -[FBSWorkspaceScenesClient _callOutQueue_sendDidCreateForScene:transitionContext:completion:] + 468
6 libdispatch.dylib 0x3fa8 _dispatch_client_callout + 20
7 libdispatch.dylib 0x79f0 _dispatch_block_invoke_direct + 284
8 FrontBoardServices 0x18378 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 52
9 FrontBoardServices 0x182f8 -[FBSMainRunLoopSerialQueue _targetQueue_performNextIfPossible] + 240
10 FrontBoardServices 0x181d0 -[FBSMainRunLoopSerialQueue _performNextFromRunLoopSource] + 28
11 CoreFoundation 0x73f3c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
12 CoreFoundation 0x73ed0 __CFRunLoopDoSource0 + 176
13 CoreFoundation 0x76b94 __CFRunLoopDoSources0 + 344
14 CoreFoundation 0x75d2c __CFRunLoopRun + 840
15 CoreFoundation 0xc8274 CFRunLoopRunSpecific + 588
16 GraphicsServices 0x14c0 GSEventRunModal + 164
17 UIKitCore 0x3ee77c -[UIApplication _run] + 816
18 UIKitCore 0x14e64 UIApplicationMain + 340
Currently I came across an issue in mac catalyst project. All the buttons in my project are not visible, they are in their actual positions and also clickable and performing their tasks as assigned but they are not visible.
When Iam doing:
crossButton.setImage(UIImage(named: "CrossComMac"), for: .normal)
Button does not contain image
While in the below code, image is visible but Iam not able to resize it.
crossButton.imageView?.image = UIImage(named: "CrossComMac")
Also title of the button is not visible too.
Anything related to button in my mac catalyst project is not visible.
Main issue:
Button's image is visible in Xcode running project
Button's image is not visible in build project...(funny thing right)
There are two issues about SFSafariViewController.
After rotate from landscape to portrait,
The topAnchor is destroyed.
The specified bar tint color and control tint color are invalidated.(Returns to system color)
Regarding the second issue, I’ve found a temporary workaround.
Override the viewWillTransition(to:with:) and keep it empty. Don't call super.viewWillTransition(to:with:).
Since UIKit is not open source, I don’t know the exact cause, but I found something that could be the key to the issue. So, I reported it to Apple Feedback Assistant. You can check the details and the sample project in the GitHub repository below.
https://github.com/ueunli/SafariViewer
I have a UITextView being added at runtime to a UIImageView as the result of doing text recognition. It's set to be editable = NO and selectable = YES. When I set the text and select it, it asks the delegate for the menu to display via:
textView:editMenuForTextInRange:suggestedActions:
The suggested items contains many UIAction and UICommand objects that have private methods or do not have the destructive attribute set, yet they are destructive. Some of these are:
promptForReplace:
transliterateChinese:
_insertDrawing:
_showTextFormattingOptions:
I need to return a menu that has only non-destructive commands in it.
First, why isn't UITextView sending only non-destructive suggested commands when its editable is NO?
Second, how can I filter the array of suggested commands when it's impossible to know if they're destructive (as some are missing that attribute)?
In addition to that, even non-destructive commands are causing an unrecognized selector exception, such as the Speak command, which it is sending to my view controller instead of to the UITextView, which is the only thing that knows what the text is that it should speak.