When I create a modal segue to a navigation controller in a storyboard, the navigation bar buttons appear correctly. But when trying to recreate this programmatically, no buttons appear:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .infoLight, primaryAction: UIAction(handler: { _ in
self.present(UINavigationController(rootViewController: ModalViewController()), animated: true)
}))
button.frame.origin = CGPoint(x: 100, y: 100)
view.addSubview(button)
}
}
class ModalViewController: UIViewController {
override func loadView() {
let button = UIBarButtonItem(title: "button")
button.primaryAction = UIAction(handler: { action in
})
button.style = .done
navigationItem.title = "title"
navigationItem.rightBarButtonItem = button
view = UITableView()
}
}
What am I doing wrong?
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Post
Replies
Boosts
Views
Activity
Hello everyone !
We've observed with our team that the default value of the modalPresentationStyle for an UIViewController has changed on iOS 18/XCode 16.
We've made a small playground to test it
import UIKit
var navigationController = UINavigationController()
navigationController.modalPresentationStyle = .automatic
navigationController.modalPresentationStyle.rawValue
The rawValue of the modalPresentationStyle on XCode 15 was 1, so the value of .pageSheet, which is okay since it is the default value specified in the documentation.
Since Xcode 16 this value has changed to 2 which is the value of .formSheet.
Did this change in particular has been specified anywhere by Apple ? The closest thing I've been able to find is the new .presentationSizingfor sheets in SwiftUI but I have not found anything for UIKit.
Thank you very much for your time !
Below iOS, 18.0 its working properly but in iOS 18.0 facing issue
I can download pdf , I can see downloaded pdf in app sandbox container but unable to preview with app
I was trying to show my nextKeyboardButton based on the value of needsInputModeSwitchKey when the viewDidLoad or viewWillAppear.
nextKeyboardButton.isHidden = !self.needsInputModeSwitchKey
However, my Xcode console always showed this error when I call the key at viewDidLoad, viewWillAppear, viewWillLayoutSubviews and viewDidLayoutSubviews.
2024-10-15 11:50:34.306515+0800 MyKeyboard[6040:25025964] [External] -[UIInputViewController needsInputModeSwitchKey] was called before a connection was established to the host application. This will produce an inaccurate result. Please make sure to call this after your primary view controller has been initialized.
The timing of connection was established to the host application. probably not related to the life cycle of extension? What's the right way use this key without warning?
In iOS, when using a UICollectionView with horizontal scrolling and only one row of cells: if all the cells have the same width, the spacing between cells is determined by minimumLineSpacing. If the cell widths are different, the spacing between cells is controlled by minimumInteritemSpacing. However, when the cell widths are different and the collectionView's height is smaller than the height of the cells, the minimumInteritemSpacing is applied to the left side of the first cell, causing the left margin of the first cell to become wider. Why does this happen?
I'm embedding PHPickerViewController in my application with a little bit of other chrome around it to provider context about how to upload.
But the fact that the controller has a translucent background to the videos when scrolling, and the rest of my UI doesn't, looks bad. Is there a way to customize the controller to either:
have the translucent background extend further than the extents of it, or
remove the translucent background entirely?
There's been an article where it says Apple/iOS apps can use the FONT_FAMILY='System' which is defaulted to use San Francisco (SF font). Is this valid Fontfamily to use? If yes, is it open source to use?
Hello everyone,
I'm working on an iOS application using Objective-C and UITabBarController. My app has more than 5 tabs, so the additional tabs are placed under the "More" tab. However, I've encountered an issue specific to iOS 18 where the first item in the "More" tab does not show up properly. This issue does not occur in iOS 17 or earlier versions.
Here's my setup method:
(void)mainTabbarSetUp {
NSMutableArray *tabItemArray = [NSMutableArray array];
UIViewController *viewController1, *viewController2, *viewController3, *viewController4, *viewController5, *viewController6, *viewController7;
UINavigationController *navviewController1, *navviewController2, *navviewController3, *navviewController4, *navviewController5, *navviewController6, *navviewController7;
viewController1 = [[UIViewController alloc] init];
navviewController1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
navviewController1.tabBarItem.title = @"Watch List";
navviewController1.tabBarItem.image = [UIImage imageNamed:@"tab_icn_watchlist"];
[tabItemArray addObject:navviewController1];
// Similarly adding other view controllers...
viewController6 = [[UIViewController alloc] init];
navviewController6 = [[UINavigationController alloc] initWithRootViewController:viewController6];
navviewController6.tabBarItem.title = @"Cancelled";
navviewController6.tabBarItem.image = [UIImage imageNamed:@"tab_icn_cancelled"];
[tabItemArray addObject:navviewController6];
self.mainTabBarController.viewControllers = tabItemArray;
}
What I've Tried:
Verified that each view controller is correctly initialized and assigned to a UINavigationController before being added to the tab array.
Logged the contents of the moreNavigationController to confirm that it contains the correct view controllers.
Tested by reducing the number of view controllers to less than 5, and the issue does not occur.
Ensured that all UINavigationControllers are configured consistently (e.g., translucency, bar style, etc.).
I have an iOS app that relies on dynamic text size such that all fonts in the app respect the user's setting of Text Size in the iOS Settings app.
This app also runs on macOS via Mac Catalyst. But until macOS 14 Sonoma, there was no Text Size setting in the macOS Settings app. But even as of Sonoma, the Text Size setting isn't usable by 3rd party apps. And Sequoia doesn't seem to change that.
As a work around, my Mac Catalyst app provides its own Text Size setting. I was able to make it work by providing my own UIApplication subclass and overriding preferredContentSizeCategory. Under macOS 12 to macOS 14, this workaround works just fine and all fonts in the app created with code such as UIFont.preferredFont(forTextStyle:) gives appropriately sized fonts based on the overridden content size category.
However, this workaround stopped working with macOS 15 Sequoia. I've also tried code such as:
self.window.traitOverrides.preferredContentSizeCategory = myCustomSizeCategoryValue
and
self.window.maximumContentSizeCategory = myCustomSizeCategoryValue
self.window.minimumContentSizeCategory = myCustomSizeCategoryValue
in the scene delegate but that made no difference.
Is there any way to get code such as UIFont.preferredFont(forTextStyle:) to return an appropriately sized font based on some app provided content size category in a Mac Catalyst app running under macOS 15?
It sure would be nice if Mac Catalyst apps automatically responded to the macOS Text Size setting under Settings -> Accessibility -> Display -> Text Size just like a native iOS app.
Hello
I'm working on implementing some changes to my app's tab bar, particularly to support some features in the new iPad floating tab bar, which has required me to adopt some of the new tab APIs from iOS 18.
The issue I've encountered is that I would like the tabs visible in regular (floating tab bar) and compact (bottom tab bar) to be slightly different. The compact variant should show a subset of the tabs visible on iPad. For example:
Floating tab bar: Use tabs A, B, C
Bottom tab bar: Use tabs A, B
I'm finding this quite difficult, especially in the scenario of split view on iPad, where the size class and tab bar location can change as the user interacts with the app.
I went down the route of changing my tab bar controller's tabs property when the trait collection changed
tabBarController.tabs = eligibleTabs
where eligibleTabs for compact passes tabs AB, and when in regular - ABC. This throws an exception
UIViewController cannot be shared between multiple UITab
*** Assertion failure in -[UITab viewController], UITab.m:173
I'm not sharing view controllers between tabs. I can only assume that the system doesn't like me passing the same values (always at least tabs A & B) multiple times to the tabs property.
I then later noticed a new iOS 18 property on UITabBarController - compactTabIdentifiers. This seemed like exactly what I was looking for: An optional filter to display only select root-level tabs when in a compact appearance. Default is nil, which would make all tabs available.
So I changed my implementation:
tabBarController.tabs = [tabA, tabB, tabC] tabBarController.compactTabIdentifiers = [tabAIdentifier, tabBIdentifier]
and don't make any explicit updates when split view is enabled.
Unfortunately this doesn't seem to work, at least not how I would expect it to. When enabling split view on iPad, the bottom tab bar appears, but it doesn't respect the tab identifiers I passed in tabBarController.compactTabIdentifiers.
I'm not sure if this a bug or that I'm not really understanding how to use tabBarController.compactTabIdentifiers.
Does anyone have any insight on this?
I encountered a crash when calling the tabBarView:didSelectIndex: method, and it only happens on iOS 18.
Here is crash report:
`OS Version: iPhone OS 18.0.1 (22A3370)
Report Version: 105
SDK Version: 0.0.4
Exception Type: SIGABRT
Exception Codes: #0 at 0x1f0acb274
Crashed Thread: 0
Application Specific Information:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Layout requested for visible navigation bar, <UINavigationBar: 0x11266ef80; frame = (0 -91; 428 44); autoresize = W; tintColor = UIExtendedSRGBColorSpace 1 1 1 0.8; layer = <CALayer: 0x301e14800>> delegate=0x112670600 standardAppearance=0x3035b3720 scrollEdgeAppearance=0x3035b3b10, when the top item belongs to a different navigation bar. topItem = <UINavigationItem: 0x14309cf00> title='' titleView=0x15b1af700 style=navigator leftBarButtonItems=0x301c08940 rightBarButtonItems=0x301caa180, navigation bar = <UINavigationBar: 0x11266e080; frame = (0 -91; 428 44); autoresize = W; tintColor = UIExtendedSRGBColorSpace 1 1 1 0.8; layer = <CALayer: 0x301e1d0a0>> delegate=0x112670000 standardAppearance=0x30355ae60 scrollEdgeAppearance=0x30355aed0, possibly from a client attempt to nest wrapped navigation controllers.'
Last Exception Backtrace:
0 CoreFoundation 0x00000001a0cad08c 0x1a0c29000 + 540812
1 libobjc.A.dylib 0x000000019dfaf2e4 0x19df98000 + 94948
2 Foundation 0x00000001a007e15c 0x19f85c000 + 8528220
3 UIKitCore 0x00000001a36b6028 0x1a33f4000 + 2891816
4 UIKitCore 0x00000001a3404248 0x1a33f4000 + 66120
5 UIKitCore 0x00000001a354d878 0x1a33f4000 + 1415288
6 QuartzCore 0x00000001a2749630 0x1a26d1000 + 493104
7 UIKitCore 0x00000001a3447cd0 0x1a33f4000 + 343248
8 UIKitCore 0x00000001a34e9a60 0x1a33f4000 + 1006176
9 UIKitCore 0x00000001a354aa48 0x1a33f4000 + 1403464
10 UIKitCore 0x00000001a34f1c64 0x1a33f4000 + 1039460
11 UIKitCore 0x00000001a368e2c8 0x1a33f4000 + 2728648
12 UIKitCore 0x00000001a368c504 0x1a33f4000 + 2721028
13 UIKitCore 0x00000001a34193c8 0x1a33f4000 + 152520
14 UIKitCore 0x00000001a34191f4 0x1a33f4000 + 152052
15 UIKitCore 0x00000001a340ae84 0x1a33f4000 + 93828
16 CoreAutoLayout 0x00000001c3ad7030 0x1c3ac5000 + 73776
17 UIKitCore 0x00000001a340ddc8 0x1a33f4000 + 105928
18 UIKitCore 0x00000001a340c7f0 0x1a33f4000 + 100336
19 UIKitCore 0x00000001a378087c 0x1a33f4000 + 3721340
20 UIKitCore 0x00000001a37804f0 0x1a33f4000 + 3720432
21 UIKitCore 0x00000001a377e814 0x1a33f4000 + 3713044
22 UIKitCore 0x00000001a37ee8a4 0x1a33f4000 + 4171940
23 UIKitCore 0x00000001a37edf14 0x1a33f4000 + 4169492`
I'm trying to create a brush by drawing in CGContext using a UIImage for a brush. However, I when I try drawing, the stroke is antialiased when I don't want it to be. I tried
context.interpolationQuality = .none
context.setShouldAntialias(false)
but it doesn't seem to work. Is it a problem with my brush or resizing the brush maybe?? (Also this problem doesn't occur when I draw a regular stroke without the brush.)
Any help or advice would be greatly appreciated!
Here is my draw function
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
context.interpolationQuality = .none
context.setShouldAntialias(false)
for stroke in strokes {
let brush = UIColor.blue.circle(size: CGSize(width: CGFloat(stroke.width * 10), height: CGFloat(stroke.width * 10))).mask(color: UIColor(cgColor: stroke.color))
var first = true
for point in stroke.points {
if first {
first = false
context.move(to: point)
continue
}
context.addLine(to: point, using: brush)
}
}
}
Circle brush
extension UIColor {
func circle(size: CGSize = CGSize(width: 1, height: 1)) -> UIImage {
return UIGraphicsImageRenderer(size: size).image { rendererContext in
self.setFill()
UIBezierPath(ovalIn: CGRect(origin: .zero, size: size)).fill()
}
}
}
CGConext extension where I overloaded addLine
extension CGContext {
func addLine(to point: CGPoint, using brush: UIImage, density: CGFloat = 1.0) {
var frame: CGRect = .zero
frame.size = brush.size
let lastPoint = self.currentPointOfPath
let distanceX = point.x - lastPoint.x
let distanceY = point.y - lastPoint.y
let distanceR = sqrt(pow(distanceX, 2) + pow(distanceY, 2))
let deltaR = (1.0 / density)
let numOfSteps = ceil(distanceR / deltaR)
var renders : CGFloat = 0.0
let deltaX = distanceX / numOfSteps
let deltaY = distanceY / numOfSteps
var currentCenter = lastPoint
repeat {
frame.origin.x = currentCenter.x - frame.width / 2.0
frame.origin.y = currentCenter.y - frame.height / 2.0
brush.draw(in: frame)
currentCenter.x += deltaX
currentCenter.y += deltaY
renders += 1.0
} while (renders <= numOfSteps)
self.move(to: point)
}
}
Hi everyone,
If you're encountering the following error in Xcode while executing a simple webbrowser.open() command in your Python file, you're in the right place:
"BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(:) needs to migrate to the non-deprecated UIApplication.open(:options:completionHandler:). Force returning false (NO)."
This issue arises because, starting from iOS 18, the UIApplication.openURL(:) method has been deprecated. If you created your project, dependencies, and the kivy-ios folder before iOS 18, every time you try to open a URL, the deprecated method will be called.
To resolve this issue without rebuilding the entire project and waiting for the kivy-ios toolchain to be updated, simply follow these steps:
At the very top of your main.py file remplace import webbrowser by :
from pyobjus import autoclass
from pyobjus.dylib_manager import load_framework
load_framework('/System/Library/Frameworks/UIKit.framework')
NSURL = autoclass('NSURL')
UIApplication = autoclass('UIApplication')
def open_url(url):
nsurl = NSURL.URLWithString_(url)
app = UIApplication.sharedApplication()
options = {}
app.openURL_options_completionHandler_(nsurl, options, None)
Then replace all your webbrowser.open(url) commands by open_url(url)
You no longer need webbrowser.
Hope it helped.
Summary
In iOS 18, the UICollectionViewDelegate method
collectionView(_:targetIndexPathForMoveOfItemFromOriginalIndexPath:atCurrentIndexPath:toProposedIndexPath:)
is not being called when moving items in a UICollectionView. This method works as expected in iOS 17.5 and earlier versions.
Steps to Reproduce
Create a UICollectionView with drag and drop enabled.
Implement the UICollectionViewDelegate method:
func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveOfItemFromOriginalIndexPath originalIndexPath: IndexPath, atCurrentIndexPath currentIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
print("🐸 Move")
return proposedIndexPath
}
Run the app on iOS 18.
Attempt to drag and drop items within the collection view.
Expected Behavior
The method should be called during the drag and drop operation, and "🐸 Move" should be printed to the console.
Actual Behavior
The method is not called, and nothing is printed to the console. The drag and drop operation still occurs, but without invoking this delegate method.
Configuration
iOS Version: 18
Xcode Version: Xcode 16.0.0
The UITextView.allowedWritingToolsResultOptions has no effect to how "Writing Tools" feature works. When it is set to empty, it still offer all options in the Writing Tools popup dialog. The result is that it is not possible to limit output results to eg. only plain text, or disable tables in output.
let textView = UITextView()
textView.isEditable = true
textView.writingToolsBehavior = .complete
textView.allowedWritingToolsResultOptions = []
resulting Writing Tools has all options available. I Tested with TextKit1 and TextKit 2 setup.
tested on iPadOS 18.1 beta (22B5069a)
Report: FB15429824
Use a UITabBarController to load two ViewControllers, A and B, both wrapped in UINavigationController.
In A’s viewDidLoad method, push to C, with C’s hidesBottomBarWhenPushed set to true. When popping back to A, the tab bar flickers and then disappears.
In versions lower than iOS 18, after popping back, the tabBar does not flicker and disappear.
A ViewController
override func viewDidLoad() {
super.viewDidLoad()
let vc = CViewController()
vc.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(vc, animated: true)
// Do any additional setup after loading the view.
}
MACCATALYST
I am able to hide title bar title using below line.
windowScene.titlebar?.titleVisibility = .hidden
but,
windowScene.titlebar?.toolbarStyle = .unifiedCompact
windowScene.titlebar?.toolbar = nil
with above 2 lines, my title bar is still visible with system defined some background color.
I want to make it transparent(clear background color)
Below style case was crash after 17.6.1
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
let titleText = UITextView(frame: CGRect(origin: .zero, size: CGSize(width: 82, height: 100)))
titleText.textContainer.maximumNumberOfLines = 2
titleText.textContainer.lineFragmentPadding = 0
titleText.textContainer.lineBreakMode = .byTruncatingTail
titleText.textContainerInset = UIEdgeInsets.zero
let attributedText = NSMutableAttributedString(string: text, attributes: [.font: UIFont.systemFont(ofSize: 14), .foregroundColor: UIColor.red])
titleText.attributedText = attributedText
view.addSubview(titleText)
self.view = view
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
Hi.
Since Xcode 16 and/or iOS 18.0 (I upgraded at the same time), I have an strange effect in the lower (let's say) 20% section of the Navigation Bar when changing to another tab, and this independently if large titles are used or not. Mentioned section is brighter or darker than the rest of the Navigation Bar background, depending on which background tint is used. This effect lasts about 0.3 seconds, but is clearly visible, quite disturbing and new as of Xcode 16 and/or iOS 18.0.
I use the code below in AppDelegate to get a gradient coloured Navigation Bar background.
let appearance = UINavigationBarAppearance()
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
UINavigationBar.appearance().compactScrollEdgeAppearance = appearance
If I don't use above code., the background color is filled and without gradient. Subject effect doesn't show in this case.
The effect basically looks like when changing tab, the new Navigation Bar background doesn't clear right away, and keeps the background from the previous Navigation Bar for 0.3 seconds before new one Navigation Bar background is rendered.
I spent quite some time on changing every possible setting, in code as well as storyboard ... no success so far.
Any ideas how to disable this undesired animation?
If I put the phone flat on a table, the left and right swipe gestures is not working but up and down gestures works.
Only when I put the iPhone to some vertical degree, the left and right swipe works.
Tested on 2 iPhone 7 Plus and 2 iPhone 13.
Anyone has similar experience? If yes, why?