I have an App that builds for iOS, iPadOS, macOS and Apple TV, which was last released to all the App Stores in April. Preferences/settings are handled by the App itself except for the Apple TV variant, where I use a Settings bundle. This worked fine until tvOS 15.0, where it appears that tvOS is not updating the value of the App’s settings from NSUserDefaults when the Settings App opens. I have been working on this problem off and on for the last week and am at wits end.
I’ve searched WWDC videos looking for a clue, there must be some simple change I cannot see. I’ve made clean projects for iOS and tvOS, and using the identical OBJ-C code and Settings plist entries, the iOS version works perfectly, the tvOS version fails in the simulator and on the device. I am not trying to synchronize Settings across devices, just persist across restarts on a single device.
My code stores data correctly in NSUserDefaults, it simply seems that tvOS Settings App is not reading values from there for display, nor writing changes that the user makes from Settings back to user defaults. None of the types in the test projects work: TexField, Switch, Title.
The test code is so simple I hesitate to include it, but the code and the NSUserDefaults key identifiers do match. This code will preset my App’s version number for Settings to display in iOS 15 but not tvOS 15. It used to work in tvOS 14:
<key>DefaultValue</key>
<string>DefaultVersionValue</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
<key>Title</key>
<string>Version</string>
<key>Key</key>
<string>VersionKey</string>
</dict>
``` NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud registerDefaults:@{
@"TextFieldKey" : @"TextFieldValue",
@"VersionKey" : @"VersionValue"
}];
[ud setObject:@"3.14" forKey:@"VersionKey"];
Any idea? Many thanks.
General
RSS for tagExplore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
In TextKit 1, I can override drawBackground(forGlyphRange:at:) in NSLayoutManager to do custom background drawing. However, I'm not too sure what the designated way of doing background drawing is in TextKit 2.
One thing I've tried is to do custom drawing in my own CALayer that's used in the configureRenderingSurface delegate callback, but I'm unsure if we are suppose to use this API and steal the textViewportLayoutController.delegate away from _UITextLayoutcanvasView?
We have been having problems with our app clip not working when sharing through iMessage. The app and app clip are published and work correctly when scanning a QR code that points to the URL: https://www.coderus.com/locations?loc=1 however if this same URL is shared through the iMessage app, a link to the website displays and not the app clip card.
We have confirmed that:
AASA file is available and has the type application/json
Both devices are above iOS 14
Both devices are in each other's contacts
The website has the meta tag for the smart app clip banner
The website has a meta tag for the og:image
Launch experiences have been configured on AppStoreConnect - as said before, the QR codes work correctly
The link leads to a 404 page, I wasn't sure if there needs to be an actual page that the link points to as app clips seem to work fine without when scanning the QR code through the camera app.
Hello Team,
We have Advanced App Clip Experiences live but we have add App Clip experience URL since long ago but status remains as Received and never changed to Published, can you please help us to fix this issue.
Please see attached.
Thanks
Simplely, when we set UITextView.inputView and then call becomeFirstResponder, but the custom inputView could not show expectedly just like before. We test this code in iOS17 and below, while only iOS17 does not work.
And xcode console print these logs:
Failed to retrieve snapshot.
-[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] perform input operation requires a valid sessionID
-[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] perform input operation requires a valid sessionID
-[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] perform input operation requires a valid sessionID
-[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] perform input operation requires a valid sessionID
Unsupported action selector setShiftStatesNeededInDestination:autoShifted:shiftLocked:
Unsupported action selector setShiftStatesNeededInDestination:autoShifted:shiftLocked:
Unsupported action selector setShiftStatesNeededInDestination:autoShifted:shiftLocked:
Unsupported action selector setShiftStatesNeededInDestination:autoShifted:shiftLocked:
Hello everyone,
I am currently working on a project that requires me to programmatically manage keyboard layouts on both iOS and macOS devices. I'm looking for a comprehensive list of KeyboardLayout ID values for all the native keyboard layouts available in both iOS and macOS. While I can extract some of this information from the /System/Library/Keyboard Layouts/ directory on macOS, I cannot extract all without adding every keyboard layout active, having a complete and pre-compiled list would be immensely helpful.
Does anyone here have such a list or know where I might find one? Any guidance on this matter would be greatly appreciated.
Thank you in advance for your assistance!
JJ
Hi - I use TipKit in my App and AppClip. TipKit is configured with the app group's datastore. The tips show in the App, but on the AppClip, with the same rules/state, the tips do not display. Is this expected? TipKit is not listed as one of the frameworks unavailable to AppClips.
try? Tips.configure([
Tips.ConfigurationOption.displayFrequency(.hourly),
Tips.ConfigurationOption.datastoreLocation(.groupContainer(identifier: BuildConfiguration.shared.userDefaultsSuite))
])
Hi,
I have few questions regarding the widgets.
I would like to know whether widget and app extensions are same ? This link(https://developer.apple.com/app-extensions/) says widget is type of app extension but I am not quite sure as few link in web says they are different. so need to confirm here :)
Can a widget share same bundle id as the main app ? so basically can we use the same provisioning profile as the main app?
If we use the same bundle id and provisioning profile, will there be any issue during the app store submission process.?
Hi,
I am trying out the new UITabBar stuff in iOS18, and I don't think it'll be a good fit for my app. Is there a way to revert to the old iPad UITabBar look and placement that we've been using before? I don't want to make such a big change like this just yet, but I would need to make other changes to the app as well and I don't want to use the new UITabBar just yet. Is there a way to achieve this?
Is there currently an option to make generated asset symbols public?
If not, would it be possible to set the generated asset symbol so they are public. It's quite common to have an apps design system implemented in a separate framework. Currently the generate assets symbols is useless for this as they can't be access in the framework consumer.
It would be great to add it to this new dropdown in Xcode 16 or along side it. (113704993 in the release notes) So the options would be Internal, Public and Off. This should affect the symbols, the extensions and the framework support.
(There's a post on the swift forums about this as well here: https://forums.swift.org/t/generate-images-and-colors-inside-a-swift-package/65674)
Unable to record and play the new contacts permission system dialog.
App: https://developer.apple.com/documentation/contacts/accessing-a-person-s-contact-data-using-contacts-and-contactsui
func handleContactsAccessAlert() {
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowButton = springboard.buttons["Allow Full Access"]
allowButton.tap()
let access6ContactsButton = springboard.alerts["Allow full access to 6 contacts?"].scrollViews.otherElements.buttons["Allow"]
access6ContactsButton.tap()
}
func handleContactsPermissionAlert() {
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowButton = springboard.buttons["Continue"]
if allowButton.exists {
allowButton.tap()
sleep(5)
handleContactsAccessAlert()
}
}
func testContactPermissions() {
let app = XCUIApplication()
app.launch()
app.buttons["Request Access"].tap()
sleep(5)
handleContactsPermissionAlert()
sleep(5)
app.collectionViews/*@START_MENU_TOKEN@*/.staticTexts["Kate Bell"]/*[[".cells.staticTexts[\"Kate Bell\"]",".staticTexts[\"Kate Bell\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap()
}
Is there a trick to getting the new Live Activities on Apple Watch working via the simulator? I have an iPhone paired to a watch simulator, but live activities created on the phone aren't appearing on the watch Smart Stack.
It looks like maybe the Smart Stack isn't functional on the watch simulator, as there are a bunch of blank tiles where the Smart Stack should be.
demo code :
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// Flip the coordinate system
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
NSDictionary *attrs = @{NSFontAttributeName: [UIFont systemFontOfSize:20],
NSForegroundColorAttributeName: [UIColor blueColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleThick),
};
// Make an attributed string
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:@"Hello CoreText!" attributes:attrs];
CFAttributedStringRef attributedStringRef = (__bridge CFAttributedStringRef)attributedString;
// Simple CoreText with CTFrameDraw
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attributedStringRef);
CGPathRef path = CGPathCreateWithRect(self.bounds,NULL);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0, 0),path,NULL);
//CTFrameDraw(frame, context);
// You can comment the line 'CTFrameDraw' and use the following lines
// draw with CTLineDraw
CFArrayRef lines = CTFrameGetLines(frame);
CGPoint lineOrigins[CFArrayGetCount(lines)];
CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins);
for (int i = 0; i < CFArrayGetCount(lines); i++) {
CTLineRef line = CFArrayGetValueAtIndex(lines, i);
CGContextSetTextPosition(context, lineOrigins[i].x, lineOrigins[i].y);
// CTLineDraw(line, context);
// You can comment the line 'CTLineDraw' and use the following lines
// draw with CTRunDraw
// use CTRunDraw will lost some attributes like NSUnderlineStyleAttributeName,
// so you need draw it by yourself
CFArrayRef runs = CTLineGetGlyphRuns(line);
for (int j = 0; j < CFArrayGetCount(runs); j++) {
CTRunRef run = CFArrayGetValueAtIndex(runs, j);
CTRunDraw(run, context, CFRangeMake(0, 0));
}
}
}
this code will use CTRunDraw to draw the content , and the underline will draw and show normally in iOS17 & Xcode 15 , But when you build it with XCode16 & iOS18 beta . the underline will be missing .
The SF Symbols app 6.0 (99) does not export the ‘Can Rotate’ property of layers when exporting a symbol via File > Export Symbol.
Without this, all the new fantastic edit functions in the app related to rotating in SF Symbols is completely useless.
This issue with the SF Symbols 6 app can be reproduced by exporting a rotatable symbol like fan.desk, and then by importing the result as custom symbol. When inspecting ‘Group 1’ of the imported symbol, it is no longer marked as rotatable.
SF Symbols app 6.0 is still in beta, but hasn't been updated since 10 June. Hopefully this bug will be solved in the release version, or earlier.
Does anyone know how to manually add the missing rotation info to the exported SVG file?
In case an Apple engineer reads this: FB13916635
How can we performantly scroll to a target location using TextKit 2?
Hi everyone,
I'm building a custom text editor using TextKit 2 and would like to scroll to a target location efficiently. For instance, I would like to move to the end of a document seamlessly, similar to how users can do in standard text editors by using CMD + Down.
Background:
NSTextView and TextEdit on macOS can navigate to the end of large documents in milliseconds. However, after reading the documentation and experimenting with various ideas using TextKit 2's APIs, it's not clear how third-party developers are supposed to achieve this.
My Code:
Here's the code I use to move the selection to the end of the document and scroll the viewport to reveal the selection.
override func moveToEndOfDocument(_ sender: Any?) {
textLayoutManager.ensureLayout(for: textLayoutManager.documentRange)
let targetLocation = textLayoutManager.documentRange.endLocation
let beforeTargetLocation = textLayoutManager.location(targetLocation, offsetBy: -1)!
textLayoutManager.textViewportLayoutController.layoutViewport()
guard let textLayoutFragment = textLayoutManager.textLayoutFragment(for: beforeTargetLocation) else {
return
}
guard let textLineFragment = textLayoutFragment.textLineFragment(for: targetLocation, isUpstreamAffinity: true) else {
return
}
let lineFrame = textLayoutFragment.layoutFragmentFrame
let lineFragmentFrame = textLineFragment.typographicBounds.offsetBy(dx: 0, dy: lineFrame.minY)
scrollToVisible(lineFragmentFrame)
}
While this code works as intended, it is very inefficient because ensureLayout(_:) is incredibly expensive and can take seconds for large documents.
Issues Encountered:
In my attempts, I have come across the following two issues.
Estimated Frames: The frames of NSTextLayoutFragment and NSTextLineFragment are approximate and not precise enough for scrolling unless the text layout fragment has been fully laid out.
Laying out all text is expensive: The frames become accurate once NSTextLayoutManager's ensureLayout(for:) method has been called with a range covering the entire document. However, ensureLayout(for:) is resource-intensive and can take seconds for large documents. NSTextView, on the other hand, accomplishes the same scrolling to the end of a document in milliseconds.
I've tried using NSTextViewportLayoutController's relocateViewport(to:) without success. It's unclear to me whether this function is intended for a use case like mine. If it is, I would appreciate some guidance on its proper usage.
Configuration:
I'm testing on macOS Sonoma 14.5 (23F79), Swift (AppKit), Xcode 15.4 (15F31d).
I'm working on a multi-platform project written in AppKit and UIKit, so I'm looking for either a single solution that works in both AppKit and UIKit or two solutions, one for each UI framework.
Question:
How can third-party developers scroll to a target location, specifically the end of a document, performantly using TextKit 2?
Steps to Reproduce:
The issue can be reproduced using the example project (download from link below) by following these steps:
Open the example project.
Run the example app on a Mac. The example app shows an uneditable text view in a scroll view. The text view displays a long text.
Press the "Move to End of Document" toolbar item.
Notice that the text view has scrolled to the bottom, but this took several seconds (~3 seconds on my MacBook Pro 16-inch, 2021). The duration will be shown in Xcode's log.
You can open the ExampleTextView.swift file and find the implementation of moveToEndOfDocument(_:). Comment out line 84 where the ensureLayout(_:) is called, rerun the app, and then select "Move to End of Document" again. This time, you will notice that the text view moves fast but does not end up at the bottom of the document.
You may also open the large-file.json in the project, the same file that the example app displays, in TextEdit, and press CMD+Down to move to the end of the document. Notice that TextEdit does this in mere milliseconds.
Example Project:
The example project is located on GitHub:
https://github.com/simonbs/apple-developer-forums/tree/main/how-can-we-performantly-scroll-to-a-target-location-using-textkit-2
Any advice or guidance on how to achieve this with TextKit 2 would be greatly appreciated.
Thanks in advance!
Best regards,
Simon
On testing my app with tvOS 18, I have noticed the Siri Remote back button no longer provides system-provided behavior when interacting with tab bar controller pages. Instead of moving focus back to the tab bar when pressed, the back button will close the app, as if the Home button was pressed. This occurs both on device and in the Simulator.
Create tvOS project with a tab bar controller.
Create pages/tabs which contain focusable items (ie. buttons)
Scroll down to any focusable item (ie. a button or UICollectionView cell)
Hit the Siri Remote back button. See expect behavior below:
Expected behavior: System-provided behavior should move focus back to the tab bar at the top of the screen.
Actual results: App is closed and user is taken back to the Home Screen.
Has anyone else noticed this behavior?
I created a Radar for this FB14766095, but thought I would add it here for extra visibility, or if anyone else had any thoughts on the issue.
Basic Information
Please provide a descriptive title for your feedback:
iOS 18 hit testing functionality differs from iOS 17
What type of feedback are you reporting?
Incorrect/Unexpected Behavior
Description:
Please describe the issue and what steps we can take to reproduce it:
We have an issue in iOS 18 Beta 6 where hit testing functionality differs from the expected functionality in iOS 17.5.1 and previous versions of iOS.
iOS 17: When a sheet is presented, the hit-testing logic considers subviews of the root view, meaning the rootView itself is rarely the hit view.
iOS 18: When a sheet is presented, the hit-testing logic changes, sometimes considering the rootView itself as the hit view.
Code:
import SwiftUI
struct ContentView: View {
@State var isPresentingView: Bool = false
var body: some View {
VStack {
Text("View One")
Button {
isPresentingView.toggle()
} label: {
Text("Present View Two")
}
}
.padding()
.sheet(isPresented: $isPresentingView) {
ContentViewTwo()
}
}
}
#Preview {
ContentView()
}
struct ContentViewTwo: View {
@State var isPresentingView: Bool = false
var body: some View {
VStack {
Text("View Two")
}
.padding()
}
}
extension UIWindow {
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
/// Get view from superclass.
guard let hitView = super.hitTest(point, with: event) else { return nil }
print("RPTEST rootViewController = ", rootViewController.hashValue)
print("RPTEST rootViewController?.view = ", rootViewController?.view.hashValue)
print("RPTEST hitView = ", hitView.hashValue)
if let rootView = rootViewController?.view {
print("RPTEST rootViewController's view memory address: \(Unmanaged.passUnretained(rootView).toOpaque())")
print("RPTEST hitView memory address: \(Unmanaged.passUnretained(hitView).toOpaque())")
print("RPTEST Are they equal? \(rootView == hitView)")
}
/// If the returned view is the `UIHostingController`'s view, ignore.
print("MTEST: hitTest rootViewController?.view == hitView", rootViewController?.view == hitView)
print("MTEST: -")
return hitView
}
}
Looking at the print statements from the provided sample project:
iOS 17 presenting a sheet from a button tap on the ContentView():
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fd25000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fd25000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
iOS 17 dismiss from presented view:
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fe04080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x0000000120009200
RPTEST hitView memory address: 0x000000011fe04080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
iOS 18 presenting a sheet from a button tap on the ContentView():
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103342080
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x000000010333e3c0
RPTEST Are they equal? true
MTEST: hitTest rootViewController?.view == hitView true
You can see here ☝️ that in iOS 18 the views have the same memory address on the second call and are evaluated to be the same. This differs from iOS 17.
iOS 18 dismiss
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103e80000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
RPTEST rootViewController's view memory address: 0x000000010333e3c0
RPTEST hitView memory address: 0x0000000103e80000
RPTEST Are they equal? false
MTEST: hitTest rootViewController?.view == hitView false
The question I want to ask:
Is this an intended change, meaning the current functionality in iOS 18 is expected?
Or is this a bug and it's something that needs to be fixed?
As a user, I would expect that the hit testing functionality would remain the same from iOS 17 to iOS 18.
Thank you for your time.
`struct OpenMainAppIntent: AppIntent {
static let title: LocalizedStringResource = "OpenMainAppIntent"
static var openAppWhenRun: Bool = true
init() {}
@MainActor
func perform() async throws -> some IntentResult & OpensIntent {
guard let url = URL(string: "myapp://open") else {
throw OpenURLError.invalidURL
}
return .result(opensIntent: OpenURLIntent(url))
}
}
`
This is an action in my custom control widget, and i want to use this deeplink open my application and get the link's info, but it won't perform onOpenURL
`@main
struct TestControlWidgetApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
print("url: \(url)")
}
}
}
}`
Topic:
UI Frameworks
SubTopic:
General
Hi,
is there any description/documentation about what can not be used as SwiftData attributes?
I do not mean things which cause issues at compile time, like having a type which is not Codeable. But rather I am looking for info which things to avoid, if you do not want to run into application crashes in modelContext.save(). Like for example having an enum which as an optional associated value as an attribute type (crashes on save is the associated value is nil).
Anybody seen any documentation about that? Or tech notes?
Thanks in advance for any hints :-).
Cheers, Michael
Hello!
I'm getting crash reports in PHPickerViewController for iOS 17 users only. Can someone point me into the right direction what could be the root cause in my case since it's related to PHPickerViewController?
Thread 0 name:
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001e7e9342c __pthread_kill + 8 (:-1)
1 libsystem_pthread.dylib 0x00000001fbc32c0c pthread_kill + 268 (pthread.c:1721)
2 libsystem_c.dylib 0x00000001a6d36ba0 abort + 180 (abort.c:118)
3 PhotoFoundation 0x00000001d2420280 -[PFAssertionPolicyAbort notifyAssertion:] + 68 (PFAssert.m:432)
4 PhotoFoundation 0x00000001d2420068 -[PFAssertionPolicyComposite notifyAssertion:] + 160 (PFAssert.m:259)
5 PhotoFoundation 0x00000001d242061c -[PFAssertionPolicyUnique notifyAssertion:] + 176 (PFAssert.m:292)
6 PhotoFoundation 0x00000001d241f7f4 -[PFAssertionHandler handleFailureInFunction:file:lineNumber:description:arguments:] + 140 (PFAssert.m:169)
7 PhotoFoundation 0x00000001d2420c74 _PFAssertFailHandler + 148 (PFAssert.m:127)
8 PhotosUI 0x0000000216b59e30 -[PHPickerViewController _handleRemoteViewControllerConnection:extension:extensionRequestIdentifier:error:completionHandler:] + 1356 (PHPicker.m:1502)
9 PhotosUI 0x0000000216b5a954 __66-[PHPickerViewController _setupExtension:error:completionHandler:]_block_invoke_3 + 52 (PHPicker.m:1454)
Crash report: 2024-09-05_18-27-56.7526_+0500-a953eaee085338a690ac1604a78de86e3e49d182.crash