This is a follow up to this post about building a Control Center widget to open the app directly to a particular feature. I have it working in a sample app, but when I do the same thing in my full app I get this error:
[[com.olivetree.BR-Free::com.olivetree.BR-Free.VerseWidget:com.olivetree.BR-Free.ContinueReadingPlanControl:-]] Control action: failed with error: Error Domain=ChronoKit.InteractiveWidgetActionRunner.Errors Code=1 "(null)"
Google has nothing for any of that. Can anyone shed light on what it means?
This is my control and its action:
@available(iOS 18.0, *)
struct ContinueReadingPlanControl : ControlWidget {
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(kind: "com.olivetree.BR-Free.ContinueReadingPlanControl") {
ControlWidgetButton(action: ContinueReadingPlanIntent()) {
Image(systemName: "book")
}
}
.displayName("Continue Reading Plan")
}
}
@available(iOS 18.0, *)
struct ContinueReadingPlanIntent : ControlConfigurationIntent {
static let title: LocalizedStringResource = "Continue Reading Plan"
static let description = IntentDescription(stringLiteral: "Continue the last-used reading plan")
static let isDiscoverable = false
static let opensAppWhenRun: Bool = true
@MainActor
func perform() async throws -> some IntentResult & OpensIntent {
let strUrl = "olivetree://startplanday"
UserDefaults.standard.setValue(strUrl, forKey: "StartupUrl")
return .result(opensIntent: OpenURLIntent(URL(string: strUrl)!))
}
}
Note also that I'm pulling this from Console.app, streaming the logs from my device. I don't know of a way to debug a Control Center widget in Xcode, though this thread implies that it's possible.
UIKit
RSS for tagConstruct and manage graphical, event-driven user interfaces for iOS or tvOS apps using UIKit.
Post
Replies
Boosts
Views
Activity
I want to add a Control Center widget for my app that will open the app to a particular feature. I'm looking at the "Open your app with a control" example here, which seems like exactly what I want:
Set your control’s action to an app intent that conforms to OpenIntent to open your app when someone uses a control. Using OpenIntent allows you to take someone to a specific area of your app when a control performs its action.
The example doesn't show exactly how to hook up the LaunchAppIntent to a control widget, but I'm guessing it's something like this:
@available(iOS 18.0, *)
struct OpenFeatureControl : ControlWidget {
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(kind: "com.example.OpenFeature") {
ControlWidgetButton(action: LaunchAppIntent()) {
Image(systemName: "book")
}
}
.displayName("Launch Feature")
}
}
But there's one critical piece missing here: how is the target feature actually opened? My initial assumption would have been that once the app launches or resumes, there's a call to some method like continueUserActivity that has a user-info dict with some key whose value is the LaunchAppEnum. But I've put breakpoints on all those methods in my app and none of them get called (I'm using UIKit scene lifecycle).
I also tried a regular AppIntent with a perform method that talks to my app directly:
@available(iOS 18.0, *)
struct OpenFeatureIntent : AppIntent {
static let title: LocalizedStringResource = "Open My Feature"
static let opensAppWhenRun: Bool = true
init() {}
func perform() async throws -> some IntentResult {
//MAIN_APP is defined in Active Compilation Conditions in build settings
#if MAIN_APP
let url = URL(string: "myapp://openfeature")!
UrlHandler.instance().handle(url)
#endif
return .result()
}
}
But when run, this simply does nothing.
Launching an app directly to a particular view or feature seems like a common use-case for control widgets, and there are apps doing it, but I can't find an example of how it's supposed to work. And the docs are really not helpful. Can anyone provide the missing piece here? What's the expected plumbing in an OpenIntent that actually launches particular UI in the app?
I've got an existing app using storyboards and would like to incorporate the new iOS 18 ContactAccessButton() and contactAccessPicker() into the GUI.
However, how can that be done? If I try to do something like add a UIView to a view controller in the storyboard, then ContactAccessButton can't be assigned to it (even though ContactAccessButton inherits from UIView).
Nor can a ContactAccessButton be used as a type within the Storyboard/the View Controller.
How do I go about integrating this new iOS feature into an existing app using Storyboards and view controllers?
A lot of us developers use localizeKey for localization from GUI. But in XCode16 Beta, Its not present in Storyboard or XIB. Please provide a solution in the next release.
We are in the process of migrating our application to SceneDelegate. We currently check in a variety of places if the app is running in the background for analytics reasons. The app may be running in the background due to location updates, notifications being received, or background refresh. With scene delegate, the app starts in the background state and only becomes active once a scene has connected. We have been unable to find a way if an app is truly running in the background or if a scene delegate is about to be launched.
Based on this TextKit 2 demo project I thought that I could implement syntax highlighting by parsing syntax block tokens (e.g. comments like <!-- --> or /* */) in processEditing and storing their locations, and then actually applying the rendering with NSTextContentStorageDelegate in textContentStorage(_:textParagraphWith:) by checking the location of each paragraph against the store of syntax tokens.
This sort of works except that the rendering is only updated for paragraphs which are changed.
Is there a way to trigger NSTextContentStorage to re-fetch paragraphs in a given range? Or is this a totally misguided approach to the problem?
So we are testing our app code base with Xcode16 and fix any compile errors. After it builds and run, we found our tar bar controller's tar bar is behind the selected VC's view.
We thought it is our bug, but we have tested below combo:
Xcode15 + iOS18 - Fine
we are invited to your office to test the new iPhone 16 series, they are iOS18, and our app on the app store is totally fine (built with Xcode 15)
Xcode15 + iOS < 18 - Fine
Apparentely ok, it's shipped.
Xcode16 RC + iOS 17 device - Fine
it's also fine
Xcode16 RC + iOS18 RC: tar bar is behind selected VC
because we are not able to add iPhone 16 model to our account, we flushed our in-house device to iOS18 RC to test Xcode16 built app,
The tar bar is behind the selected VC.
We want to ask for help ASAP because we are totally out of mind what's going on.
I have filed FB 15120641 but want to raise it here to gain more support and insights.
I wrote an app that can show live streaming. When using iPad, I can connect an external display and move app to display, that I can do what I want on my iPad and watch live streaming on external display using cable.
But app moving to display is not always full screen, and on some displays it shows larger than the external display range that I should go to Settings -> Display & Brightness -> External Display -> Switching "Allow Display Mode Changes" to fix this issue.
Are there APIs to make the App "move to display" programmatically, keep app full-screen, matching the external display's resolution on the External display?
I am using Xcode 16 RC + iPhone 15 Pro (iOS 18) and a UIDocumentPickerViewController pops up and the interface displays abnormally. Is this a bug in the simulator?
I am using Xcode 16 RC to debug an iPhone 16 app. The status bar height returned by iPhone 16 and iPhone 16 Pro is 54, while the height of the status bar returned by iPhone 16 ProMax is 44. Why is this? Here is the code I use:
[UIApplication sharedApplication].windows.firstObject.windowScene.statusBarManager.statusBarFrame.size.height
Making the call as:
UIApplication.shared.open(websiteURL)
doesn't open the browser and gives the following in the console:
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).
However, making the call as:
UIApplication.shared.open(websiteURL) { _ in }
opens the browser and there is nothing in the cosole.
Does someone understand why is this or if it's Apple's iOS 18 bug? In the iOS & iPadOS 18 RC Release Notes | Apple Developer Documentation there is a section around resolving this or something similar, unsure.
navigationItem.title does not display on the first view controller in the new UITabBarController on iPad. Also, if I set navigationItem.titleMenuProvider an empty space is displayed. Everything displays as expected if it isn’t the first view controller.
let tabBarController = UITabBarController(tabs: [
UITab(title: "Tab 1", image: nil, identifier: "tab1", viewControllerProvider: { _ in
return UINavigationController(rootViewController: ViewController())
})
])
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "First"
navigationItem.titleMenuProvider = { suggestions in
return UIMenu(children: [
UIAction(title: "Option 1", handler: { _ in
self.navigationController?.pushViewController(SecondViewController(), animated: true)
}),
UIAction(title: "Option 2", handler: { _ in })
])
}
}
}
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Second"
navigationItem.titleMenuProvider = { suggestions in
return UIMenu(children: [
UIAction(title: "Option 1", handler: { _ in }),
UIAction(title: "Option 2", handler: { _ in })
])
}
}
}
As iPadOS 18 shows Tab Bar on top (tvOS'esq), can someone please tell me what changes do I need to make to get tab bar shown as a regular one (Pre iPadOS 18 style)?
Tab bar being at the bottom is easily accessible. And, it being on top needs too much of hands movement.
That being on top is is occupying, in a way, more screen real estate.
Any ideas appreciated. Thank you.
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?
-Environment
iPad:10th、iOS:17.6.1、Printer:EPSON PX-S730
-Question
Is this phenomenon due to iOS specifications?
Restarting the iPad solves the problem, but I don't think it's best practice to restart it every time you reproduce it.
Please let me know if you have a good solution.
-Problem
I am developing a print preview screen using AirPrint's print method.
If you submit a print job using AirPrint on an iPad while the printer is turned off and then cancel it, the print center remains on the app switcher.
After that, when I turned on the printer, I was no longer able to print using AirPrint on my iPad.
When using AirPrint's API "print" and when printing by launching AirPrint from Safari, we have confirmed the same behavior in both cases.
-How to reproduce
Turn off the printer
Print from iPad to printer using AirPrint
Launch the print center from the app switcher, cancel the print job, and set the number of print jobs to 0.
When you start the app switcher, the Print Center app remains.
In step 4, turn on the printer and print from the iPad to the printer using AirPrint.
When you start Print Center from the app switcher, the print job status becomes "Waiting" and the print job is not executed.
-Expected result
When there are no print jobs on the print center, the print center is closed on the app switcher.
You can print from your iPad to the printer using AirPrint, and then print from the printer.
-Actual results
When there are no print jobs on the print center, the print center remains on the app switcher without being closed.
In the above situation, when printing from the iPad to the printer using AirPrint, the printer does not print.
When I start the print center, the print job status is "Waiting" and is queued.
-Code
printInfo.jobName = "Print Job"
printController.printInfo = printInfo
let pdfURL = Bundle.main.url(forResource: "sample", withExtension: "pdf")!
printController.printingItem = pdfURL
let printer = UIPrinter(url: printerUrl)
printController.print(to: printer, completionHandler: { [self] printController, completed, error in
if(error != nil){
print("error").
}else if completed{
print("completed") //this scenario handles completion response
}else{
print("cancel")
}
})
-Link of API used
Apple Developer-AirPrint-print
-Similar inquiries
Apple Developer Forum - Print Center on my iPhone shows a pending document to print and I can't get rid of it
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!!!
When I want to update my iOS, get this message:
does temporary removing this apps, changes their identifierForVendor?
Because as documentation states, identifier changes when all apps from the same vendor are being reinstalled. If it does, does also UserDefaults gets cleared?
in iOS18 Xcode16.
when i select a tabBarItem, the selected viewController has an animation.
how should i disable this animation?
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!