Hi, I'm working with UIDocument to store a PDF file. This is code I use for saving a file.
document.close(completionHandler: { (success) in
if success {
document.save(to: url,
for: .forOverwriting,
completionHandler: { (success) in
if success {
print("Saved file successfully")
}
})
}
})
This code works well with a small file size. But if it's a large file like 100MB, it takes around 2-5 minutes to save the file. Is there a way to save file with the changes only? Or create an auto save function triggered whenever the user edit the file?
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Posts under UIKit tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hello,
I have a macOS Catalyst app that I now began updating and building against the iOS 18/macOS Sequoia SDKs. Most things appear to be working just fine as before, apart from my NSToolbar.
At the root of my app I am presenting a UISplitViewController which gets a custom SidebarViewController and a UITabBarController as its viewControllers.
Then at same point in the apps lifecycle the UITabBarController presents another ViewController modally. I then associate the controllers window with a custom NSToolbar like this:
let toolbar = NSToolbar(identifier: "mainToolbar")
toolbar.displayMode = .iconAndLabel
toolbar.delegate = self
toolbar.allowsUserCustomization = false
titleBar.toolbarStyle = .automatic
titleBar.titleVisibility = .hidden
titleBar.toolbar = toolbar
I also disable automatic NSToolbar hosting via: https://developer.apple.com/documentation/uikit/uinavigationbardelegate/3987959-navigationbarnstoolbarsection (returning .none).
Now all of this worked fine on macOS Sonoma and previous versions but on Sequoia my custom toolbar refuses to show up.
My suspicion is that is has something to do with the new tab and sidebar behaviour introduced with the new SDKs (https://developer.apple.com/documentation/uikit/uinavigationbardelegate/3987959-navigationbarnstoolbarsection).
For now within my UITabBarController I was able to revert to the old look using:
if #available(iOS 18.0, *) {
mode = .tabSidebar
sidebar.isHidden = true
isTabBarHidden = true
}
This result in a look similar to the previous macOS version but my NSToolbar unfortunately remains hidden.
Is there an easy fix for this? Since I am a solo developer I would prefer to spend my available resources currently on other features and adopt the new tab/sidebars a couple months down the line.
Appreciate any help and hints, thanks!
There used to be a toolbar here on the right side. ↑
I'm an experienced iOS developer but new to tvOS, and I'm finding the focus engine to be somewhat confounding.
My app launches with a UINavigationController, whose root view is a UITableViewController. When I select a row, a UIViewController is pushed.
That view controller contains a bunch of nested UICollectionViews. One of the collection view cells contains 3 UIButtons. When the view first appears, the first of those (Button1) has focus.
I can move focus from Button1 to Button2, and from Button2 to Button3. I can also go back from Button3 to Button2. But I cannot navigate back to Button1, and I'm trying to figure out why.
I have focus logging turned on. It's very verbose, but here are the parts that seem useful to me:
When the view controller displays initially, I see
Updating focus from <UITableViewCell: 0x104841a00> to <DXETV.CustomButton: 0x104232610> in focus system <UIFocusSystem: 0x60000370c900>.
The result of the focus update was determined from the following preferred focus search:
|
| Starting preferred focus search.
| <UINavigationController: 0x10600f000>
| └ <DXETV.RenderExampleViewController: 0x10484ae00>
| └ <DXETV.RenderExampleView: 0x10421ab70>
| └ <DXETV.LayoutElementView: 0x107021000>
| └ <DXETV.LayoutCollectionView: 0x10707d200>
| └ <DXETV.LayoutViewCell: 0x10681ee00>
| └ <DXETV.LayoutElementView: 0x106862000>
| └ <DXETV.LayoutCollectionView: 0x106865a00>
| └ <DXETV.LayoutViewCell: 0x106851000>
| └ <DXETV.LayoutElementView: 0x104891800>
| └ <DXETV.LayoutCollectionView: 0x10488da00>
| └ <DXETV.LayoutViewCell: 0x1048de600>
| └ <DXETV.CustomButton: 0x104232610>
| (info) It's focusable!
|
This seems right... focus moves from the table view cell to Button1, and this is he view hierarchy I expect.
Then we see
Creating focus scroll animator entry for environment <DXETV.LayoutCollectionView: 0x10707d200>
This is the topmost collection view. This is followed by many lines about locking and unlocking this collection view, followed by
Removing focus scroll animator entry for environment <DXETV.LayoutCollectionView: 0x10707d200>
I don't know if this is normal or not.
After I move focus from Button1 to Button2, I see
Updating focus with context <UIFocusUpdateContext: 0x6000033200a0: previouslyFocusedItem=<DXETV.CustomButton 0x104232610>, nextFocusedItem=<DXETV.CustomButton 0x104312900>, focusHeading=Down>:
Moving focus from <DXETV.CustomButton: 0x104232610> to <DXETV.CustomButton: 0x104312900> in focus system <UIFocusSystem: 0x60000370c900>.
Which seems correct.
When I move focus from Button2 to Button3, I get this, which is now expected:
Updating focus with context <UIFocusUpdateContext: 0x60000330c5a0: previouslyFocusedItem=<DXETV.CustomButton 0x104312900>, nextFocusedItem=<DXETV.CustomButton 0x1043134d0>, focusHeading=Down>:
Moving focus from <DXETV.CustomButton: 0x104312900> to <DXETV.CustomButton: 0x1043134d0> in focus system <UIFocusSystem: 0x60000370c900>.
Followed by another round of creating and removing a focus scroll animator entry, this time for the middle collection view.
Moving from Button3 back to Button2 also looks as expected:
Updating focus with context <UIFocusUpdateContext: 0x600003318f00: previouslyFocusedItem=<DXETV.CustomButton 0x1043134d0>, nextFocusedItem=<DXETV.CustomButton 0x104312900>, focusHeading=Up>:
Moving focus from <DXETV.CustomButton: 0x1043134d0> to <DXETV.CustomButton: 0x104312900> in focus system <UIFocusSystem: 0x60000370c900>.
But here, everything stops. When I press the up arrow again to go back to Button1, nothing happens. Nothing is printed to the console, and the focused button does not change.
Any hints as to what may be wrong or how to debug this further would be most appreciated!!!
Hello,
I have collection view with context menu using contextMenuConfigurationForItemAt and I wanted to customize the preview, when user long presses and context menu is shown. Something maybe like in the Music app when you long press on an album it shows the album in bigger size...
I found some snippets online for highlightPreviewForItemAt and dismissalPreviewForItemAt but it just doesn't work. As soon as a implemented these delegate methods, nothing happens when I long press, not even the standard preview with context menu.
These two methods aren't being called at all. Do I need to do something else? Do I need the previewProvider when creating the context menu? It is my understanding that that is needed only when the item should also open further detail on tap - which is something I don't need and want.
Below is my relevant implementation:
private func shareMenuConfiguration(for itemAt: URL, indexPath: IndexPath) -> UIContextMenuConfiguration {
let share = UIAction(title: "Share".localized(), image: UIImage(systemName: "square.and.arrow.up")) { [unowned self] _ in
let shareVC = UIActivityViewController(activityItems: [itemAt], applicationActivities: nil)
if let cell = collectionView.cellForItem(at: indexPath) {
shareVC.popoverPresentationController?.sourceView = cell.contentView
shareVC.popoverPresentationController?.sourceRect = cell.contentView.bounds
}
self.present(shareVC, animated: true)
}
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
UIMenu(title: "", children: [share])
}
}
func collectionView(_ collectionView: UICollectionView, contextMenuConfiguration configuration: UIContextMenuConfiguration, highlightPreviewForItemAt indexPath: IndexPath) -> UITargetedPreview? {
guard let item = datasource.itemIdentifier(for: indexPath), let cell = collectionView.cellForItem(at: indexPath) as? GalleryImageCell else {
return nil
}
let parameters = UIPreviewParameters()
let visibleRect = cell.contentView.bounds.insetBy(dx: 1/3, dy: 1/3)
let visiblePath = UIBezierPath(roundedRect: visibleRect, cornerRadius: 4)
parameters.visiblePath = visiblePath
return UITargetedPreview(
view: cell.contentView,
parameters: parameters,
target: .init(container: collectionView, center: collectionView.convert(cell.contentView.center, from: cell.contentView))
)
}
func collectionView(_ collectionView: UICollectionView, contextMenuConfiguration configuration: UIContextMenuConfiguration, dismissalPreviewForItemAt indexPath: IndexPath) -> UITargetedPreview? {
guard let item = datasource.itemIdentifier(for: indexPath), let cell = collectionView.cellForItem(at: indexPath) as? GalleryImageCell else {
return nil
}
let parameters = UIPreviewParameters()
let visibleRect = cell.contentView.bounds.insetBy(dx: 1/3, dy: 1/3)
let visiblePath = UIBezierPath(roundedRect: visibleRect, cornerRadius: 4)
parameters.visiblePath = visiblePath
return UITargetedPreview(
view: cell.contentView,
parameters: parameters,
target: .init(container: collectionView, center: collectionView.convert(cell.contentView.center, from: cell.contentView))
)
}
Thanks!
Hello !
Since iOS/iPadOS 18 there is a new switch transition between tabs in UITabBarController where is a little zoom of the selected UIViewController.
At first, I thought that was a bug but I found the same animation on the Apple's apps (like music, shortcuts...)
On my app, this animation produce a little flash/blink white before zooming, it's not smooth like on Apple's apps.
I searched on documentation but I didn't found any topics about how to disable it or handled it better.
Is this possible to disabled it ?
Hi, everyone
I have an app already in production that uses SwiftUI's lifecycle (paired with an AppDelegate). Due to some specific behaviour of the app, we decided to migrate the app to use UIKit's lifecycle, adding the corresponding SceneDelegate to the app, as well as modifying the Info.plist file accordingly to accommodate to these new changes.
Although everything seems to work when installing the app from zero, when installing it on top of another version, the screen goes black and the user cannot interact with the app at all unless they reinstall it completely. As I've read online, iOS is reusing the window configuration from the previous execution of the app. I know this because the AppDelegate's application(application:connectingSceneSession:options) is not being called when coming from a previous version of the app.
I would love to know what can I do to make this work because, as you may understand, we cannot ask our user base to reinstall the application.
Thank you very much.
I have an iPad app using the new UITabBarController on iPadOS18, which is suffering from a new issue from the new layout. Within my tabs, I have a UISplitViewController, with a 2 column layout. If I load the app, it works ok, but if I put the app in the background, and then bring it to foreground, the navigation bar buttons and title just disappear from the splitView controller’s primary view controller.
Before going to background:
After coming back from background:
I also get the following layout issues posted in the debugger consoler:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x600002106ee0 UILayoutGuide:0x600003b088c0'TitleView(layout=0x103d18d40)'.trailing <= UILayoutGuide:0x600003b08c40'UIViewLayoutMarginsGuide'.trailing (active)>",
"<NSLayoutConstraint:0x600002137520 H:|-(590)-[UILayoutGuide:0x600003b00a80'TabBarGuide(0x103d18810)'](LTR) (active, names: '|':_UINavigationBarContentView:0x103d18810 )>",
"<NSLayoutConstraint:0x600002137610 UILayoutGuide:0x600003b00a80'TabBarGuide(0x103d18810)'.width == 0 (active)>",
"<NSLayoutConstraint:0x6000021414a0 UILayoutGuide:0x600003b088c0'TitleView(layout=0x103d18d40)'.trailing >= UILayoutGuide:0x600003b00a80'TabBarGuide(0x103d18810)'.trailing (active)>",
"<NSLayoutConstraint:0x600002148e10 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x103d18810.width == 585 (active)>",
"<NSLayoutConstraint:0x600002107570 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x600003b08c40'UIViewLayoutMarginsGuide']-(20)-|(LTR) (active, names: '|':_UINavigationBarContentView:0x103d18810 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600002106ee0 UILayoutGuide:0x600003b088c0'TitleView(layout=0x103d18d40)'.trailing <= UILayoutGuide:0x600003b08c40'UIViewLayoutMarginsGuide'.trailing (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
I filed a bug report: FB14971801
Is there something I can do avoid this? It'll make my app pretty unusable if the bar button items just disappear every time the user puts the app in the background and then foregrounds the app.
Sample app
A collection view controller with list layout, 1 section and 1 row.
The cell's content view contains a text view.
class ViewController: UICollectionViewController {
var snapshot: NSDiffableDataSourceSnapshot<Section, String> {
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
snapshot.appendSections([.main])
snapshot.appendItems(["one", "two"], toSection: .main)
return snapshot
}
var dataSource: UICollectionViewDiffableDataSource<Section, String>?
enum Section {
case main
}
init() {
super.init(collectionViewLayout: .init())
collectionView.collectionViewLayout = createLayout()
configureDataSource() // more likely and automatically avoid unpleasant animations on iOS 15 by configuring the data source in the init rather than in view did load
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, itemIdentifier in
let textView = UITextView()
textView.font = .systemFont(ofSize: UIFont.labelFontSize)
cell.contentView.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: cell.contentView.topAnchor, constant: 8),
textView.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor, constant: -8),
textView.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: cell.directionalLayoutMargins.leading),
textView.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: -cell.directionalLayoutMargins.trailing)
])
}
dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
}
dataSource?.apply(self.snapshot, animatingDifferences: false)
}
func createLayout() -> UICollectionViewLayout {
return UICollectionViewCompositionalLayout { section, layoutEnvironment in
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
}
}
}
Question 1
Can anybody edit the provided sample code so that the text view's vertical indicator inset is not cut off at the top?
Question 2
It seems to me that Apple has successfully implemented text views inside table view cells: can anybody provide Apple documentation as per how to do so?
What I've tried and didn't work
textView.verticalScrollIndicatorInsets.top = 30 // does nothing
Adding the text view to a custom view and the view to the cell's content view
textView.contentInset = .zero
textView.scrollIndicatorInsets = .zero
textView.textContainerInset = .zero
textView.textContainer.lineFragmentPadding = 0
Centering the text view vertically and constraining its height to that of the content view with an 8 points constant to leave some padding
Constraining the top and bottom anchors of the text view to the cell's layout margins guide's top and bottom anchors
Constraint
I need the text view to have some padding from the top and bottom of the cell for aesthetic reasons.
In our app, we noticed that edit menus (i.e. when long pressing in a text field) have weird spacing inside each element. Which, as a result, causes the entire menu content to be truncated.
To be honest, I have no idea how this is being customized (to my understanding it shouldn't be?), but this is a relatively old and large app so something weird could possibly do it. I basically came here for guidance to see if anyone has thoughts on WHAT could possibly cause this customization / padding / resizing of each item, so I can fix it back to the system behavior.
Our app:
System:
Thanks for your help :)
Shai
Having below issues with Navigation bar in UISplitViewController Primary View Controller,
Navigation title is not showing with new Elevated Tab bar.
Navigation right bar button is not showing.
Navigation bar height issue with Primary and Secondary View
Working fine in iPad OS 17.
SplitViewController preferred display mode is
preferredDisplayMode = UISplitViewController.DisplayMode.oneBesideSecondary
Tested with Xcode 16.1 Beta and Xcode 16.0 Beta 6
iPad OS 18.1
iPadOS 17.5
I found two tab bar issues:
How do you programmatically hide/show the tab bar for iPadOS and Catalyst apps under macOS Sequoia? Also, is there a way to prevent the user from doing this via the menu?
Programmatically changing the current tab view correctly changes the tab view but not the tab item highlighted in the tab bar in:
Mac Catalyst apps under Sequoia
iPad apps under Sequoia
tvOS 18 apps
Is there a workaround I can use until this bug is fixed?
In iOS 18, the tab bar has been moved to the top on iPad. How can I hide this tab bar? Using TabBarController.tabBar.isHidden = true isn't working.
My app creates dynamic copies of UI controls that are based on a custom UIButton subclass using this legacy approach:
let archivedButton = try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
guard let buttonDuplicate = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archivedButton) as? UIWagerButton else {return nil }
I am currently trying to work passed the deprecation of
NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data: Data)
Per the guidance, I should be replacing that line with the following and ensuring that the custom class implements NSSecureCoding
guard let buttonDuplicate = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIWagerButton.self, from: archivedButton) else {return nil}
However, while the code does compile and run, decoding the data reference throws the following error:
value for key 'UIButtonStatefulContent' was of unexpected class 'NSMutableDictionary'
I can only assume that if I get passed this specific property, there will be other properties that are also problematic.
Question: Is this a bug? Or, am I now responsible for navigating the underlying property matrix of this UIControl to specifically, manually, handle the encoding and decoding of each of it's properties?
I am developing an iPhone app related to finance and currently I am using isCaptured value to prevent screen recording by checking the isCaptured value and if it is true then I blur the video recording.
It was working fine while using UIScreen.main.isCaptured till iOS 17 . But for iOS 18 it became deprecated and it is not working any more. Below is the obj-c code block.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
if (@available(iOS 11.0, *)) {
BOOL isCaptured = [[UIScreen mainScreen] isCaptured];
if(isCaptured){
// Do the action for hiding the screen recording
}
} else{
// Fallback on earlier versions
}
return YES;
}
The replacement sceneCaptureState is working only for a scene-based app which uses UISceneDelegate lifecycle but it's not working for the old structure so now i have that problem, my iPhone app is very big and does not support scenes at all since we are following UIAppDelegate life cycle for years, what shall I do to prevent screen recording from iOS 18 onwards ?
Note: My iPhone app does not support any scene configuration
Please help me in this.
Regards,
Carol
I have a UIViewController that presents a UIPrintInteractionController when a user selects the print button on the UI. The problem is starting in iOS 18 (currently using beta 7) when the print controller is presented the UIViewController's viewWillAppear() is being called. This did not happen in earlier iOS releases and is causing unwanted behavior in the app. Is this a bug or will this be the behavior going forward?
As the title says, when a ScrollView is near a UIViewControllerRepresentable, then the ScrollView's content no longer accurately recognizes taps. In particular, taps along the leading edge (10 points-ish) are ignored.
Here's a working example:
struct ContentView: View {
var body: some View {
HStack(spacing: 0) {
MyRepresentable()
// .allowsHitTesting(false)
ScrollView {
LazyVStack {
ForEach(0..<10, id: \.self) { index in
HStack(spacing: 0) {
Button {
print("tapped \(index)")
} label: {
Color.red
}
.frame(width: 50)
Color.blue
}
.frame(height: 50)
}
}
}
}
}
}
Here's the representable and a placeholder controller:
struct MyRepresentable: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> MyViewController {
MyViewController()
}
func updateUIViewController(_ uiViewController: MyViewController, context: Context) {}
}
final class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .gray
}
}
When you tap along the leading edge of the red buttons, the taps are ignored for about the first 10 points. But if you prevent hit testing on the representable (by un-commenting the .allowsHitTesting modifier), then the red buttons behave as expected. Also if you just remove the representable entirely, then all the buttons behave as expected.
It's as if the hit targets of the buttons are getting "pushed" over by the representable. Or is the representable simply intercepting these touches?
I've confirmed this incorrect behavior on iPad via touch and mouse. However, Apple Pencil (1st gen) and Apple Pencil Pro behave correctly - even in the presence of that UIViewControllerRepresentable. Perhaps the Pencil follows a different hit-test codepath?
Is this expected behavior? If so, then how do I use UIViewControllerRepresentable and ScrollView side-by-side?
UITraitCollection.sceneCaptureState does not work when using iPhone mirroring on iOS 18 beta and MacOS sequoia beta.
The path to reproducing this bug is as follows:
Set the default language of macOS to Korean
Change the default language setting in macOS to English
Use the iPhone Mirroring app
In situations like this, sceneCaptureState of UITraitCollection.current appears as inactive.
This can lead to serious bugs and abuse in many applications listed on the App Store.
UITraitCollection.current.sceneCaptureState
when I push a UIViewController, the bottom view controller was pushed out of navigationController.
I'm using UIKit picker in SwiftUI. To minimize the memory concerns with my picker's large number of values in my project, I decided to move UIKit picker in SwiftUI. When I quickly scroll the picker from top to bottom and vice versa, my picker occasionally leaps to the next value from the top or from bottom to the next/previous value.
Steps to reproduce:
Create a UIKit picker in SwiftUI
Scroll the picker quickly from top to bottom and vice versa
Intermittently, the selected value moves to the next value in the picker
Code:
Below attached sample code for reference
@State private var isPresented = false
@State private var selection: [Int] = [5]
@State var visiblePicker: Bool = false
private let data: [[String]] = [
Array(0...10).map { "\($0)" }
]
var body: some View {
VStack(spacing: 5) {
Button("Picker") {
self.isPresented = true
}
Text("\(self.data[0][self.selection[0]])")
.onTapGesture {
self.visiblePicker.toggle()
}
}
PickerView(data: self.data, selections: self.$selection)
}
}
struct PickerView: UIViewRepresentable {
var data: [[String]]
@Binding var selections: [Int]
func makeCoordinator() -> PickerView.Coordinator {
Coordinator(self)
}
func makeUIView(context: UIViewRepresentableContext<PickerView>) -> UIPickerView {
let picker = UIPickerView(frame: .zero)
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
return picker
}
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<PickerView>) {
for i in 0...(self.selections.count - 1) {
print("UpdateUIView: \(self.selections[i])")
view.selectRow(self.selections[i], inComponent: i, animated: false)
}
}
class Coordinator: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var parent: PickerView
init(_ pickerView: PickerView) {
self.parent = pickerView
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return self.parent.data.count
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.parent.data[component].count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return self.parent.data[component][row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print("selected row = \(row)")
self.parent.selections[component] = row
}
}
}
I am able to send invitation from my device to friend's device. When friend clicks on invitation that was shared through text messages it says:
Open "Resources"?
User X wants to collaborate.
You'll join as User Y
(user Y @iCloud.com).
|Not Now| |Open|
If friend clicks on |Open| then nothing happens. Share remains in "invited" state and the callbacks which I expected to be called are not.
The official Apple CloudKit Sharing App - https://github.com/apple/sample-cloudkit-sharing/blob/main/Sharing/App/AppDelegate.swift - is confusing me because it does not have following code like typical SwiftUI app:
@main
struct MainApp: App {
Instead it uses @main for AppDelegate.
Here is my code with prints that encode what is going on:
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("I see this getting called on App startup")
return true
}
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
print("I also see this getting called on App startup")
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
print("I don't see this getting called")
}
func application(userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) -> Bool {
print("However, I expected this to be called when friend opened his CloudKit share invitation")
return false
}
}
@main
struct MainApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
static let sharedModelActor: ModelActorDatabase = {
let schema = Schema([
Resource.self,
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false, cloudKitDatabase: .none)
do {
let modelContainer = try ModelContainer(for: schema, configurations: [modelConfiguration])
return ModelActorDatabase(modelContainer: modelContainer)
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
@StateObject var syncedDatabase: SyncedDatabase = SyncedDatabase(modelContainer: Self.sharedModelActor.modelContainer)
var body: some Scene {
WindowGroup {
ResourceView()
.environmentObject(syncedDatabase)
}
.modelContainer( Self.sharedModelActor.modelContainer )
.database(SharedDatabase.shared.database)
}
}
I was expecting that this would call userDidAcceptCloudKitShareWith, but it is not. Why?