UITextView erroneously overrides string attributes when applying spellchecker annotation attributes.
It doesn't need any particular setting. Default UITextView instance with attributed text
let textView = UITextView(usingTextLayoutManager: true)
textView.spellCheckingType = .yes
Once spellcheck attributes get applied, other attributes like foreground color get applied to the misspelled words. This behavior happens only on Mac Catalyst, and started to appear on macOS 14 or newer.
Please check the Xcode project that demonstrates the issue https://github.com/user-attachments/files/16689336/TextEditor-FB14165227.zip
Open TextEditor project
Select "My Mac (Mac Catalyst)" build destination
Run the project. A window with a text area should appear
Select the whole text (either using mouse or keyboard command+a)
Observe how foregroundColor changes to text (this is the issue)
That eventually led to crash 💥
This bug is reported to Apple FB14165227
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Post
Replies
Boosts
Views
Activity
We use the triple column layout and when running our app under Sequoia Beta, the Secondary view controller's navigation bar is not shown initially. If a view is pushed inside the secondary (which contains a UINavigationController), and then popped again, the navigation bar is shown.
When reordering items within a table view, I can use tableView:targetIndexPathForMoveFromRowAtIndexPath: to adjust the destination index path.
Is there a way to adjust the destination index path when dropping onto a table view if the drag was initiated in a different view?
For example, if I'm dropping an object into a table view where the rows are sorted alphabetically, I want the gap to appear in the location where the item is going to end up, regardless of which row the dragged item is being dragged / dropped at.
I create a UIKit PullDown menu (in a positionMenu button), with the following code:
func setupPullDownMenu() {
let menu1 = UIAction(title: "Menu1") { [self] _ in
// some code
}
let menu2 = UIAction(title: "Menu2") { [self] _ in
// some code
}
let menu3 = UIAction(title: "Menu3") { [self] _ in
// some code
}
let menu = UIMenu(title: "Positions", children: [menu1, menu2, menu3])
positionMenu.menu = menu
positionMenu.showsMenuAsPrimaryAction = true
}
In Portrait, options are listed as Menu1, Menu2, Menu3
But in Landscape it is the reverse: Menu3, Menu2, Menu1
I use Xcode 16.1ß and iOS 17.0 simulator
Is it the expected behaviour ?
Hi folks, I'm struggling with an issue on MacCatalyst. I'm using a dynamic menu that is supposed to show the current state of a setting (state = .on / .off). The UIDeferredMenuElement works great on iOS, the closure is called on each display of the (context) menu.
On MacCatalyst however - where I use the menu as a submenu in the main menu - the closure is called only once on first menu display. The system seems to show a cached menu item even though I'm using UIDeferredMenuElement.uncached.
Here's the relevant code:
func getMenuElement() {
let element = UIDeferredMenuElement.uncached { completion in
let modeString = mode.myLocalizedDescription
let trackingMode = <current setting>
let mode = <menu item setting option>
let state = trackingMode == mode ? .on : .off
let action = UIAction(title: modeString,
image: <image>,
state: state) { _ in
viewController.setUserTrackingMode(mode)
}
completion([action])
}
return element
}
Any ideas how to trick the system into generating the dynamic menu item on each menu display?
Have the requirements to support swipe to dismiss from a quick-look view controller changed in iOS18? I am noticing that my app no longer supports gestural dismissal in an iOS18 build.
Not this is a QLPreviewController presented from a UIViewController presented in a SwiftUI view hierarchy as part of a ViewControllerRepresentable.
I am writing to report an issue I encountered with iOS 18 beta that affects my application, which has been available on the App Store for over two years and currently has over 60,000 active users.
My application utilizes a UITabBarController to manage multiple tabs, where each tab hosts a UIViewController embedded within a UINavigationController. The application operates in two different states, where users may have either 5, 4, or 3 tabBarItems depending on their configuration.
The issue arises when fewer than 5 tabs are present. In these cases, I add child view controllers to the UITabBarController to ensure they are displayed above the tab bar, rather than below it. The relevant code snippet is as follows:
tabBarController.addChild(childController)
tabBarController.view.addSubview(childController.view)
Prior to iOS 18, this implementation functioned as expected. However, with the release of iOS 18, adding a child view controller to the UITabBarController results in the child being incorrectly added as a UITabBarItem. This misbehavior leads to an application crash when the unintended tab is selected.
The crash trace is as follows:
"Inconsistency in UITabBar items and view controllers detected. No view controller matches the UITabBarItem '<UITabBarItem: 0x142d9c480> selected'."
I have attached screenshots from iOS 18 and previous versions to illustrate the issue, which compares the expected behavior in earlier iOS versions with the problematic behavior in iOS 18.
I appreciate your attention to this matter and look forward to any guidance or resolution you can provide.
I'd like to receive files in my app, but only certain UIScenes can receive a file. How do I tell the system which of the UIScenes in my app can receive that file? How does the system pick a scene?
I've tried using UISceneActivationConditions(). Here is what I put in the scenes that can receive files:
var preferredActivatePredicates = [NSPredicate]()
var canActivatePredicates = [NSPredicate]()
// Any scene *can* be activated at any time
canActivatePredicates.append(NSPredicate(value: true))
if hasWriteAccess {
// We are also the preferrred scene for receiving files
for fileExtension in ["png", "jpeg", "jpg", "pdf"] {
preferredActivatePredicates.append(NSPredicate(format: "SELF ENDSWITH[c] '.%@'", fileExtension))
}
}
let conditions = UISceneActivationConditions()
conditions.canActivateForTargetContentIdentifierPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: canActivatePredicates)
conditions.prefersToActivateForTargetContentIdentifierPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: preferredActivatePredicates)
scene.activationConditions = conditions
Unfortunately, this does not seem to have an effect. It does not activate the hasWriteAccess scenes for func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
Is there any way to tell what content identifier the system is using when a file share activates an app?
Thank you for your help!
The question is:
We did not add "GameController framework", but we do not know why the "GameController framework" is loaded at startup.
I am checking the launch time of our app, using Instruments->App launch
I was confused to find the GameConroller framework loaded
I check the project, in the plist file, no configuration GCSupportedGameControllers, GCSupportsControllerUserInteraction related key.
What else causes the GameController framework to load?
Instead of implementing a textview from scratch (UITextInput it a lot of work/boilerplate)
It makes sense for me to subclass UITextView.
However, when subclassing it seems this is limited to TextKit 1 only, I get an assertion failure:
*** Assertion failure in -[_UITextKit1LayoutController initWithTextView:textContainer:], _UITextKit1LayoutController.m:72
I thought I would just need to call the super init:
super.init(usingTextLayoutManager: true)
But this isn't a designated initialiser:
Must call a designated initializer of the superclass 'UITextView'
Is there a way to do this and override the layout manager so that it uses TextKit 2 in the subclass?
(My aim is to then draw the fragments manually using TextKit2 to get a custom layout while ultimately using all of the UITextView implementation as 99% of it is what I want - other than custom drawing of text fragments).
My code is below:
class DocumentTextView: UITextView {
private let _textLayoutManager = NSTextLayoutManager()
private var textContentStorage: NSTextContentStorage {
textLayoutManager!.textContentManager as! NSTextContentStorage
}
override var textLayoutManager: NSTextLayoutManager? {
_textLayoutManager
}
init() {
let textContainer = NSTextContainer(size: .zero)
super.init(frame: .zero, textContainer: textContainer)
_textLayoutManager.textContainer = textContainer
textContentStorage.attributedString = NSAttributedString(string: text, attributes: [
.foregroundColor: UIColor.label,
])
textContentStorage.addTextLayoutManager(_textLayoutManager)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Platform and Version
iOS
Development environment: Xcode 16.0 beta 5 (16A5221g), macOS 14.6.1 (23G93)
Run-time configuration: iOS 18.0 beta 5 (22A5326g)
Description of Problem
Starting with iOS 18 SDK, test bundles containing a +load method that accesses UIScreen.mainScreen result in deadlock during test bundle injection.
Also filed as FB14703057
I'm looking for clarity on whether this behavior is considered a bug in iOS or whether we will need to change the implementation of our app.
Steps to Reproduce
Create a new iOS app project using Objective-C and including unit tests
Add the following code snippet to any .m file in the test target:
@interface Foo: NSObject
@end
@implementation Foo
+ (void)load {
UIScreen * const mainScreen = UIScreen.mainScreen;
NSLog(@"%@", mainScreen);
}
@end
Run the tests
Expected Behavior
As with iOS 17 & Xcode 15, the tests run to completion.
Actual Behavior
With iOS 18 & Xcode 16, deadlock during test bundle injection.
stack_trace.txt
I made a custom slider by subclassing UISlider, and I'm trying to add scrubbing functionality to it, but for some reason the scrubbing is barely even noticeable at 0.1? In my code, I tried multiplying change in x distance by the scrubbing value, but it doesn't seem to work. Also, when I manually set the scrubbing speed to a lower value such as 0.01, it does go slower but it looks really laggy and weird?? What am I doing wrong?
Any help or advice would be greatly appreciated!
Subclass of UISlider:
class SizeSliderView: UISlider {
private var previousLocation: CGPoint?
private var currentLocation: CGPoint?
private var translation: CGFloat = 0
private var scrubbingSpeed: CGFloat = 1
private var defaultDiameter: Float
init(startValue: Float = 0, defaultDiameter: Float = 500) {
self.defaultDiameter = defaultDiameter
super.init(frame: .zero)
value = clamp(value: startValue, min: minimumValue, max: maximumValue)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
clear()
createThumbImageView()
addTarget(self, action: #selector(valueChanged(_:)), for: .valueChanged)
}
// Clear elements
private func clear() {
tintColor = .clear
maximumTrackTintColor = .clear
backgroundColor = .clear
thumbTintColor = .clear
}
// Call when value is changed
@objc private func valueChanged(_ sender: SizeSliderView) {
CATransaction.begin()
CATransaction.setDisableActions(true)
CATransaction.commit()
createThumbImageView()
}
// Create thumb image with thumb diameter dependent on thumb value
private func createThumbImageView() {
let thumbDiameter = CGFloat(defaultDiameter * value)
let thumbImage = UIColor.red.circle(CGSize(width: thumbDiameter, height: thumbDiameter))
setThumbImage(thumbImage, for: .normal)
setThumbImage(thumbImage, for: .highlighted)
setThumbImage(thumbImage, for: .application)
setThumbImage(thumbImage, for: .disabled)
setThumbImage(thumbImage, for: .focused)
setThumbImage(thumbImage, for: .reserved)
setThumbImage(thumbImage, for: .selected)
}
// Return true so touches are tracked
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let location = touch.location(in: self)
// Ensure that start location is on thumb
let thumbDiameter = CGFloat(defaultDiameter * value)
if location.x < bounds.width / 2 - thumbDiameter / 2 || location.x > bounds.width / 2 + thumbDiameter / 2 || location.y < 0 || location.y > thumbDiameter {
return false
}
previousLocation = location
super.beginTracking(touch, with: event)
return true
}
// Track based on moving slider
override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
guard isTracking else { return false }
guard let previousLocation = previousLocation else { return false }
// Reference
// location: location of touch relative to device
// delta location: change in touch location WITH scrubbing
// adjusted location: location of touch to slider bounds (WITH scrubbing)
// translation: location of slider relative to device
let location = touch.location(in: self)
currentLocation = location
scrubbingSpeed = getScrubbingSpeed(for: location.y - 50)
let deltaLocation = (location.x - previousLocation.x) * scrubbingSpeed
var adjustedLocation = deltaLocation + previousLocation.x - translation
if adjustedLocation < 0 {
translation += adjustedLocation
adjustedLocation = deltaLocation + previousLocation.x - translation
} else if adjustedLocation > bounds.width {
translation += adjustedLocation - bounds.width
adjustedLocation = deltaLocation + previousLocation.x - translation
}
self.previousLocation = CGPoint(x: deltaLocation + previousLocation.x, y: location.y)
let newValue = Float(adjustedLocation / bounds.width) * (maximumValue - minimumValue) + minimumValue
setValue(newValue, animated: false)
sendActions(for: .valueChanged)
return true
}
// Reset start and current location
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.currentLocation = nil
self.translation = 0
super.touchesEnded(touches, with: event)
}
// Thumb location follows current location and resets in middle
override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
let thumbDiameter = CGFloat(defaultDiameter * value)
let origin = CGPoint(x: (currentLocation?.x ?? bounds.width / 2) - thumbDiameter / 2, y: (currentLocation?.y ?? thumbDiameter / 2) - thumbDiameter / 2)
return CGRect(origin: origin, size: CGSize(width: thumbDiameter, height: thumbDiameter))
}
private func getScrubbingSpeed(for value: CGFloat) -> CGFloat {
switch value {
case 0:
return 1
case 0...50:
return 0.5
case 50...100:
return 0.25
case 100...:
return 0.1
default:
return 1
}
}
private func clamp(value: Float, min: Float, max: Float) -> Float {
if value < min {
return min
} else if value > max {
return max
} else {
return value
}
}
}
UIView representative:
struct SizeSlider: UIViewRepresentable {
private var startValue: Float
private var defaultDiameter: Float
init(startValue: Float, defaultDiameter: Float) {
self.startValue = startValue
self.defaultDiameter = defaultDiameter
}
func makeUIView(context: Context) -> SizeSliderView {
let view = SizeSliderView(startValue: startValue, defaultDiameter: defaultDiameter)
view.minimumValue = 0.1
view.maximumValue = 1
return view
}
func updateUIView(_ uiView: SizeSliderView, context: Context) {}
}
Content view:
struct ContentView: View {
var body: some View {
SizeSlider(startValue: 0.20, defaultDiameter: 100)
.frame(width: 400)
}
}
Can I ask why Apple added a new type UITextContentType - birthdate, but when you set it for a text field, and then become in that text field, the system doesn't offer your date of birth ?
I have already checked everything, the date of birth is set everywhere, I have created a new test application, only with one text field, I set it type “birthdate” and nothing offers, with all other types of fields and their setting, everything works fine. And there is no information about it anywhere on the internet.
And also, if you go to sites through safari, and becomes in the field to enter the date of birth, the system offers autofill, but in the application does not.
Tab bars on iPadOS 18 have moved to the top of the screen. They now share space with navigation bars.
We have added calls to setTabBarHidden(_:animated:) alongside existing calls to setNavigationBarHidden(_:animated:) in pushed view controller's viewWillAppear(_:) methods to manage the appearance of the tab bar and navigation bar within navigation controllers.
This results in layout issues with the safe area and navigation bar. I've attached screenshots from an example app demonstrating the issue. How can we manage the appearance of both the navigation bar and tab bar so that they share the same space when visible, but are properly hidden and excluded from the safe area when not?
/// The root view controller shows both the navigation bar and tab bar
class ViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
tabBarController?.setTabBarHidden(false, animated: animated)
}
}
/// The second view controller hides both the navigation bar and tab bar
class ViewController2: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: animated)
tabBarController?.setTabBarHidden(true, animated: animated)
}
@IBAction func customBackButtonTapped(_ sender: Any) {
navigationController?.popViewController(animated: true)
}
}
/// The third view controller shows the navigation bar but hides the tab bar
class ViewController3: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: animated)
tabBarController?.setTabBarHidden(true, animated: animated)
}
}
I'm trying to unpack this sentence
Note that after adding a second text container to the layout manager, the text views become uneditable and unselectable.
Found on this example code:
https://developer.apple.com/documentation/uikit/textkit/display_text_with_a_custom_layout
I'm implementing my own UITextInput which makes use of the example code setup to replicate a multi-page text editor (kind of like a basic version of Pages/Word)
Each page has its own NSTextContainer which gets added to one NSLayoutManager.
The code works and my views are rendering text across each page, however, only the first text view is editable.
It appears this is "by design" (?)
How do we get around this? Is there another level we have to drop down to enable multiple editing containers?
The sample code is wayback in iOS 13, so it would seem very odd if the capability of multiple editable text fields/containers was impossible to achieve.
Sample app
The following is a UIKit app that displays a collection view with list layout and diffable data source (one section, one row).
class ViewController: UIViewController {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<String, String>!
override func viewDidLoad() {
super.viewDidLoad()
configureHierarchy()
configureDataSource()
}
func configureHierarchy() {
collectionView = .init(frame: .zero, collectionViewLayout: createLayout())
view.addSubview(collectionView)
collectionView.frame = view.bounds
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
func createLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { section, layoutEnvironment in
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
}
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, itemIdentifier in
var backgroundConfiguration = UIBackgroundConfiguration.listGroupedCell()
backgroundConfiguration.backgroundColor = .systemBlue
cell.backgroundConfiguration = backgroundConfiguration
}
dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
}
var snapshot = NSDiffableDataSourceSnapshot<String, String>()
snapshot.appendSections(["main"])
snapshot.appendItems(["demo"])
dataSource.apply(snapshot, animatingDifferences: false)
}
}
Problem
If you tap on the row, it doesn't look like it gets selected: the line backgroundConfiguration.backgroundColor = .systemBlue breaks the cell's default background color transformer.
Question
Given that my goal is to have my cell manifest its selection exactly like usual (meaning exactly as it would without the line backgroundConfiguration.backgroundColor = .systemBlue), that the details of how a cell usually does so are likely not public, that I would like to set a custom background color for my cell and that I would want to configure its appearance using configurations, since I seem to understand that that is the way to go from iOS 14 onwards, does anybody know how to achieve my goal by resetting something to whatever it was before I said backgroundConfiguration.backgroundColor = .systemBlue?
What I've tried and didn't work:
Setting the collection view's delegate and specifying that you can select any row
Setting the color transformer to .grayscale
Setting the cell's backgroundConfiguration to UIBackgroundConfiguration.listGroupedCell().updated(for: cell.configurationState)
Setting the color transformer to cell.defaultBackgroundConfiguration().backgroundColorTransformer
Using collection view controllers (and setting collectionView.clearsSelectionOnViewWillAppear to false)
Setting the cell's automaticallyUpdatesBackgroundConfiguration to false and then back to true
Putting the cell's configuration code inside a configurationUpdateHandler
Combinations of the approaches above
Setting the color transformer to UIBackgroundConfiguration.listGroupedCell().backgroundColorTransformer and cell.backgroundConfiguration?.backgroundColorTransformer (they're both nil)
Workaround 1: use a custom color transformer
var backgroundConfiguration = UIBackgroundConfiguration.listGroupedCell()
backgroundConfiguration.backgroundColorTransformer = .init { _ in
if cell.configurationState.isSelected || cell.configurationState.isHighlighted || cell.configurationState.isFocused {
.systemRed
} else {
.systemBlue
}
}
cell.backgroundConfiguration = backgroundConfiguration
Workaround 2: don't use a background configuration
You can set the cell's selectedBackgroundView, like so:
let v = UIView()
v.backgroundColor = .systemBlue
cell.selectedBackgroundView = v
You won't be able to use custom background content configurations though and might want to use background views instead:
var contentConfiguration = UIListContentConfiguration.cell()
contentConfiguration.text = "Hello"
cell.contentConfiguration = contentConfiguration
let v = UIView()
v.backgroundColor = .systemBlue
cell.backgroundView = v
let bv = UIView()
bv.backgroundColor = .systemRed
cell.selectedBackgroundView = bv
Consideration on the workarounds
Both workarounds seem to also not break this code, which deselects cells on viewWillAppear(_:) and was taken and slightly adapted from Apple's Modern Collection Views project (e.g. EmojiExplorerViewController.swift):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
deselectSelectedItems(animated: animated)
}
func deselectSelectedItems(animated: Bool) {
if let indexPath = collectionView.indexPathsForSelectedItems?.first {
if let coordinator = transitionCoordinator {
coordinator.animate(alongsideTransition: { [weak self] context in
self?.collectionView.deselectItem(at: indexPath, animated: true)
}) { [weak self] (context) in
if context.isCancelled {
self?.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: [])
}
}
} else {
collectionView.deselectItem(at: indexPath, animated: animated)
}
}
}
(Collection view controllers don't sport all of that logic out of the box, even though their clearsSelectionOnViewWillAppear property is true by default.)
I am trying to build an application that interacts with iphone screen to perform operations like touch/tap/swipe (Not inside an app but whole screen). The closest tool to do it is FB IDB (Ios Development Bridge). But IDB doesn't support UI interactions with physical device, quoting that apple doesn't allow it. Is it possible to do it? If not, is there any official document that quotes apple doesn't allow UI interactions on physical devices, programmatically ?
I am trying to keep the tableVies scroll position when I come back into my screen. I am getting this error:
Terminating app due to uncaught exception 'NSRangeException', reason: 'Attempted to scroll the table view to an out-of-bounds row (7) when there are only 4 rows in section 0.
There should be 10 rows in section 0. I think that the tableView is not fully loaded and that's why the error says there is only 1 row in section 0 because this crash doesn't occur most of the time. Usually it works fine. Variable savedRowMainFave is saved in viewWillDisappear
I put some print statements to show values:
Leaving indexPath = [0, 7]. (this is in the viewWillDisappear(). Prints savedRowMainFave = (dealsTable.indexPathsForVisibleRows?.last) ?? savedRowMainFave)
filteredDeals.count = 10 (also in the viewWillAppear() this is the number of items in the array that populates the tableView called dealsTable)
this is the calculated rows = 10 (also in the viewWillAppear() this prints self.dealsTable.numberOfRows(inSection: savedRowMainFave.section))
This code scrolls to the saved position. The if statement is supposed to protect from crashing but is obviously self.dealsTable.numberOfRows(inSection: savedRowMainFave.section) is not working
if (self.dealsTable.numberOfRows(inSection: savedRowMainFave.section) > savedRowMainFave.row){
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {self.dealsTable.scrollToRow(at: savedRowMainFave, at: .bottom, animated: false)
}
Any suggestions for ways of verifying a valid savedRowMainIndex ( an indexPath) would be greatly appreciated. Thanks
Starting from August 6, some iOS18 users will experience crashes during the App startup phase. From the stack of the crash log, it can be seen that the system's Network library crashed. Below is the specific crash information, please check it out. This problem has never occurred before. Is this a bug in the iOS18 system?
I have an iOS app I've added Catalyst support to. It is a UIDocument based app using a UIDocumentBrowserController subclass.
When the app launches a file browser SHOULD appear in front of the app window. And if I have launched the app for the first time or it was force quit the last time it was used this works as intended.
However if I open a document and then quit the app either by closing the app window or choosing AppMenu -> Quit then launch the app again I get an error dialog that only Says "No document could be created" with an okay button. When you click okay the app window comes to the front covering the document browser creating an app killing problem that is confusing for users. Yes they can go to file -> New or File -> Open Document but the situation is very confusing.
I have tried returning false for these functions in my AppDelegate:
func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
return false
}
func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
return false
}
func application(_ application: UIApplication, shouldSaveSecureApplicationState coder: NSCoder) -> Bool{
return false
}
And I've added NSQuitAlwaysKeepsWindows = No in my info.plist and the problem persists.
I have set a break point in my document's init(fileURL:) function but it is not called so I have no idea what document is attempting to be created or how to stop it.