During WWDC Q&As I asked how I could add an inspector to my UIKit app that’s using UISplitViewController with a double column style featuring a sidebar and detail view controller. I initially tried a full-height inspector (by putting my split view controller into a SwiftUI view and applying the inspector on that, embedding that into a UIHostingController to be the rootViewController) but this caused a bunch of UI bugs (seemingly related to optimizations made for a size class that doesn’t match the actual appearance) and it doesn’t extend into the NSToolbar on Mac Catalyst anyways. I now want to try implementing the under-the-toolbar solution. An engineer said:
For an under toolbar appearance, you should be able to use .inspector on the detail view controller (after wrapping it in a SwiftUI view), but you may have to do manual toolbar management here (hiding and showing) to make sure you don't end up with stacked toolbars/UINavigationBars
I have indeed run into the problem with two navigation bars in my inspector. I want to keep the navigation bar visible in the detail screen, but I do not want any navigation bars visible in my inspector since I’m going to provide my own button to toggle the inspector (via a button in the detail on iOS and an NSToolbarItem on macOS). Is this layout possible? I tried applying .toolbar(.hidden) on the inspector’s view but this doesn’t do anything, there’s still two stacked navigation bars (tested on iPadOS 17 beta 2). I think even if that worked it would only hide the inner navigation bar, I’d still have an undesirable navigation bar. :/ Wishing there were a UIKit API I could avoid the interop complexity ha
In the sample project attached to FB12447791, the root view controller is a UISplitViewController. The primary view controller is a UINavigationController containing a sidebar. The secondary view controller is a UINavigationController containing a UIHostingController whose root view is a SecondaryColumnView. SecondaryColumnView is a Form that has a button to Toggle Inspector, a navigation title, and an inspector. The inspector is a Form that has .toolbar(.hidden).
I've provided several screen recordings in the feedback report as well. Thanks for your help and insight!
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
The updated Photos access dialog in iOS 17 states:
Photos may contain metadata, such as location, depth information, or captions.
How do I access the caption a user added to a photo in my app? This wasn’t possible in iOS 16, is there new API in 17? I previously requested this ability via metadata in FB10205012 and via PHAsset in FB8244665. If it remains inaccessible I’ve submitted FB12437093 to request captions be removed from this wording.
I have an accessoryCircular Lock Screen widget built for iOS 16:
ZStack {
AccessoryWidgetBackground()
VStack {
Text("MON")
.font(.caption)
Text("6")
.font(.title)
}
}
When run on iOS 17 it renders an error “Please adopt containerBackground API”. So I changed it to:
VStack {
Text("MON")
.font(.caption)
Text("6")
.font(.title)
}
.containerBackground(for: .widget) {
AccessoryWidgetBackground()
}
This causes the error to go away but the circular background is no longer visible (tested with iPadOS 17b2). What’s the right way to implement this?
I have an app that uses NSPersistentCloudKitContainer and a widget that displays a record. I want to add a button with interactive widgets in iOS 17 to modify the visible record via an AppIntent. When I do this the app logs:
CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate managedObjectContextSaved:](2945): <NSCloudKitMirroringDelegate: 0x2818002a0>: Observed context save: <NSPersistentStoreCoordinator: 0x280a05180> - <NSManagedObjectContext: 0x281a00410>
It does not automatically sync this change to iCloud, not until I manually return the app to the foreground, even if I delay returning from the perform() function. Is there a way to sync NSPersistentCloudKitContainer while the app is in the background as a result of this change triggered in the widget? Thanks!
In my app I get a UIImage for a PHAsset via PHImageManager.requestImage(for:targetSize:contentMode:options:resultHandler:). I directly display that image in a UIImageView that has preferredImageDynamicRange set to .high. The problem is I do not see the high dynamic range.
I see the HDRDemo23 sample code uses PhotosPicker to get a UIImage from Data through UIImageReader whose config enables prefersHighDynamicRange.
Is there a way to support HDR when using the Photos APIs to request display images?
And is there support for PHLivePhoto displayed in PHLivePhotoView retrieved via PHImageManager.requestLivePhoto?
I’m implementing App Shortcuts in my iOS app to allow you to add and find plants. In attempt to get a “Find Plants” shortcut, I created a query that conforms to EnumerableEntityQuery and set that as the defaultQuery in my PlantAppEntity. I have the typeDisplayRepresentation set to TypeDisplayRepresentation(name: "Plant", numericFormat: "\(placeholder: .int) plants"). I added a Localizable.stringsdict to the app target, added Plant and %lld plants as the header comments shows, then clicked Localize so now English is selected in the Localization section. But when I run the app then open Shortcuts and tap my app, there’s a Find Plant shortcut, but I expected it to be titled Find Plants. When I tap the info button it shows “plant” instead of “plants” in every parameter description. When you add that action to a shortcut the placeholder is All Plant, unlike similar shortcuts from Reminders and Contacts that say “All Reminders” and “All Contacts”. The action is working properly as it returns an array of plants, the only issue is it’s using the singular form of plant in places it should be plural. Have I done something wrong, am I missing anything, or is this a bug? (FB12908309)
In iOS 17 when you search Spotlight for Notes you can see it has an App Shortcut titled New Note that simply opens the Notes app and starts composing a new note. When you open the Shortcuts app, create a new shortcut, search for and tap Notes, notice the New Note action is ONLY included at the top - it's not in the list of actions underneath. There is another intent in the list titled Create Note which will create a new note using the content you specify without opening the Notes app.
I want to achieve this same thing in my app - an App Shortcut to open the app and start creating a new item, and a shortcut action to create a new item without opening the app. How can this be done?
So far I have created two AppIntents, NewItem and CreateItem. My AppShortcutsProvider only includes NewItem. This works great when searching for my app in Spotlight. But when I open Shortcuts and go to add an action from my app to a shortcut, it includes Add Item at the top as an App Shortcut but also in the actions list underneath. Create Item is included in the list as well which is confusing. I don't want Add Item to be an available action because it's fairly useless to open the app and start creating an item, instead they should use Create Item to create an item in the background.
Do I need to instead create a single shortcut that behaves differently in Spotlight vs Shortcuts, is that possible?
I have an iOS app and I added Vision Pro as a supported destination. I'm ready to add an app icon. When I select my existing AppIcon there's no option to add visionOS assets to it. I went ahead and created a new visionOS App Icon titled VisionAppIcon. Now how do I configure the project to use VisionAppIcon for visionOS while continuing to use AppIcon for iOS?
When I select the target and go to Build Settings there's Primary App Icon Set Name currently set to AppIcon. When I run the visionOS app, no app icon appears. If I change that to VisionAppIcon then it appears of course. But I don't see a way to add variants for it other than Debug and Release.
With UIKit you can open a window via drag and drop by creating a UIDragItem with an NSItemProvider and NSUserActivity object in a collection view.
Is there a similar SwiftUI API to open a window by dragging out a view from a grid? Or can we only manually invoke openWindow from a button?
Is it possible to get the original date created for an IntentFile? The following code always gets the date for right now, surely because it's copied into a temporary directory so that's when it was created at that location.
if let fileURL = file.fileURL, fileURL.startAccessingSecurityScopedResource() {
if let attributes = try? FileManager.default.attributesOfItem(atPath: fileURL.path), let date = attributes[.creationDate] as? Date {
print(date)
}
fileURL.stopAccessingSecurityScopedResource()
}
Is it possible to sort the user library assets by date captured? The Photos app in iOS 18 lets you choose between Date Captured and Recently Added and I want to offer that same choice in my app. This seems to always sort them by creation date (which I believe is the same as recently added):
let assetCollection = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil).firstObject!
let fetchResult = PHAsset.fetchAssets(in: assetCollection, options: PHFetchOptions.imageMediaType())
I've had an app that edits photos in your library since the PhotoKit API was released in iOS 8. I know it was required if you preserve photo metadata you had to change the value of Orientation to 1 (up), otherwise PhotoKit would fail to perform the asset change request. When I remove this code, I'm seeing Orientation is getting changed to 1 automatically both at root and in the TIFF dictionary (tested with iOS 18). I wanted to confirm this is expected behavior, the system does this for us now? If so, can I remove this code for iOS 15+, or was it a recent iOS version this started happening? Thanks!
I’m looking into building a closed source XCFramework from a local Swift package that has dependencies on other packages, which can later be distributed via Swift Package Manager. In initial discussions, we thought xcodebuild does not support linking the dependencies externally, it always includes them statically in the built framework. It's my understanding this is because we're asking xcodebuild to build a framework from a local Swift Package. Is there another way this can be achieved?
To explain in more detail:
I have built a closed source SDK for other developers to integrate in their apps, currently distributed as an XCFramework. The interesting thing about the SDK is it has dependencies on other libraries, which need to be resolved when adding this SDK as a dependency to an app. The SDK’s dependencies should not be baked into our XCFramework. CocoaPods has worked well for that but we want to instead use SPM.
The current project setup is an iOS framework Xcode project and an app Xcode workspace. The framework project is included in the app workspace and is in the same repo as the app, which allows me to modify the framework source code then run the app to test it. The framework project can also be opened independently and built to verify it doesn’t have any errors, but to verify it’s working I run it with the app. To distribute a new release I use xcodebuild to create an XCFramework and then deploy that. For this to work with CocoaPods I had to add a Podfile to the app directly as well as the framework directory so both have the dependencies available. This means I have an xcworkspace for the framework and not just a xcodeproj. I specify the framework workspace file in the xcodebuild command.
To switch to a setup that utilizes Swift Package Manager, I created a Package.swift in the iOS framework project’s directory that specifies its dependencies, removed CocoaPods integration including deleting the workspace file, removed the framework project from the app’s workspace, added the Package as a local package to the app project, and added the framework directory via + > Add Files to “App” which adds the package to the top of the sidebar, making its source code available to edit within the app workspace. Everything is working when I run the app. Xcode properly resolves the dependencies for the local package and I can run the app to develop it.
Now to create an XCFramework I run the following command in the framework directory (which contains the Package.swift):
xcodebuild archive -workspace . -scheme FrameworkName -configuration Release -destination 'generic/platform=iOS' -archivePath './build/FrameworkName.framework-iphoneos.xcarchive' SKIP_INSTALL=NO BUILD_LIBRARIES_FOR_DISTRIBUTION=YES ENABLE_USER_SCRIPT_SANDBOXING=NO
This succeeds however the dependencies have been linked statically thus included in our SDK. We need to only include the code from our framework and link to external dependencies, like it does with our current CocoaPods setup.
I'm wondering what options there are to achieve this. Even if I need to change the project setup locally, for example to continue using a framework project/workspace instead of a local Swift package. It seems I just need xcodebuild to be able to create an XCFramework which can then be distributed with its own Package.swift file that specifies its dependencies.
If it's not possible to link the dependencies externally, could you help me to understand the implications of including them statically? I don't know what problems could arise as a result of that or other concerns this would bring. Thanks!
I've created a closed source iOS SDK from a local Swift package, which has dependencies on other Swift packages, and successfully created a binary XCFramework following the solution from my previous post.
Now I'm proceeding with the process to distribute this SDK. I believe I want to upload the XCFramework to a public repo alongside a Package.swift file and an Example app project that uses the XCFramework. So each time I go to create a new release I’ll create a new XCFramework replacing the current one, verify it's working properly in the example app, then commit, tag, and push to the repo.
My question is how do I set this up as a Swift package that includes an example app that uses the local XCFramework (not a remote url to a zip of the framework) and properly resolves dependencies?
So far I created a directory containing MyFramework.xcframework and Package.swift containing:
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyFramework",
platforms: [
.iOS(.v14)
],
products: [
.library(
name: "MyFramework",
targets: ["MyFramework"]
)
],
dependencies: [
.package(url: "https://github.com/example/example.git", from: "1.0.0")
],
targets: [
.binaryTarget(
name: "MyFramework",
path: "MyFramework.xcframework"
)
]
)
I then created an Example iOS app project in that directory and now need to integrate the local XCFramework. I wondered if I could do that via File > Add Package Dependencies > Add Local, but when I navigate to that Package.swift and click Add Package it says
The selected package cannot be a direct ancestor of the project.
Do I need a different Package.swift for the Example app, and if so, how do I get that set up? I created a separate Package.swift (contents below) alongside the xcodeproj but when I try to add that in Xcode I get the same error, despite the fact this package is a sibling of the project not an ancestor.
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyFramework-Example",
platforms: [
.iOS(.v14)
],
dependencies: [
.package(name: "MyFramework", path: "../")
],
targets: [
.target(
name: "MyFramework-Example",
dependencies: ["MyFramework"]
)
]
)
I've created a closed source iOS SDK from a local Swift package, which has dependencies on other Swift packages, and successfully created a binary XCFramework following the solution from my previous post. I would now like to create a Package.swift to vend this XCFramework and test it in an example app to verify it works as expected before I upload it to a public repo for distribution.
I understand that binaryTarget does not support dependencies so we need to use a wrapper. I created a directory containing the following:
Package.swift
MyFramework.xcframework/
MyFrameworkWrapper/
├─ dummy.swift
Package.swift contains:
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyFramework",
platforms: [
.iOS(.v14)
],
products: [
.library(
name: "MyFramework",
targets: ["MyFramework", "MyFrameworkWrapper"]
)
],
dependencies: [
.package(url: "https://github.com/gordontucker/FittedSheets.git", from: "2.6.1")
],
targets: [
.target(
name: "MyFrameworkWrapper",
dependencies: [
"FittedSheets"
],
path: "MyFrameworkWrapper"
),
.binaryTarget(
name: "MyFramework",
path: "MyFramework.xcframework"
)
]
)
I created a new iOS app, selected the project, Package Dependencies > + > Add Local, and added the directory containing this Package.swift. Xcode resolves the dependencies and lists them in the sidebar. I added code to import and use the framework. It builds successfully but the app crashes when run:
dyld[63959]: Library not loaded: @rpath/FittedSheets.framework/FittedSheets
Referenced from: <7DE247FC-DAFF-3946-AD21-E80F5AF841C9> /Users/Jordan/Library/Developer/Xcode/DerivedData/MyFramework-Example-gaeeymnqzenzrbbmhuebpodqctsz/Build/Products/Debug-iphonesimulator/MyFramework.framework/MyFramework
How do I get this working? I'm wondering is my package set up properly to vend the framework specifying its dependencies, and is my XCFramework created correctly?
The Package.swift for the framework's source code contains:
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyFramework",
platforms: [
.iOS(.v14)
],
products: [
.library(
name: "MyFramework",
type: .dynamic,
targets: ["MyFramework"]
)
],
dependencies: [
.package(url: "https://github.com/gordontucker/FittedSheets.git", from: "2.6.1")
],
targets: [
.target(
name: "MyFramework",
dependencies: [
"FittedSheets"
],
path: "Sources"
)
]
)
And I created the XCFramework following the steps in that previous thread:
Create archive from package via xcodebuild archive -workspace "$PACKAGE_PATH" -scheme "$FRAMEWORK_NAME" -destination 'generic/platform=iOS' -archivePath "$ARCHIVE_PATH/iOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_USER_SCRIPT_SANDBOXING=NO ENABLE_MODULE_VERIFIER=NO OTHER_SWIFT_FLAGS=-no-verify-emitted-module-interface
Create the Modules directory in the framework via mkdir -p "$ARCHIVE_PATH/iOS.xcarchive/Products/usr/local/lib/$FRAMEWORK_NAME.framework/Modules"
Copy the Swift interface files into the framework from the build in DerivedData via cp -a "$BUILD_PRODUCTS_PATH/Build/Intermediates.noindex/ArchiveIntermediates/$FRAMEWORK_NAME/BuildProductsPath/Release-iphoneos/$FRAMEWORK_NAME.swiftmodule" "$ARCHIVE_PATH/iOS.xcarchive/Products/usr/local/lib/$FRAMEWORK_NAME.framework/Modules"
Repeat 1-3 for iOS Simulator
Create an XCFramework via xcodebuild -create-xcframework -framework "$ARCHIVE_PATH/iOS.xcarchive/Products/usr/local/lib/$FRAMEWORK_NAME.framework" -framework "$ARCHIVE_PATH/iOS_Simulator.xcarchive/Products/usr/local/lib/$FRAMEWORK_NAME.framework" -output "$ARCHIVE_PATH/$FRAMEWORK_NAME.xcframework"