This is a tricky one. I have a shipping product which, when compiled under Xcode 14.3.1 works as expected on Sonoma.
If the same project is recompiled with Xcode 15, the subclass of NSTextView will not display correctly (text is same color as background).
I am also using a custom NSLayoutManager (to draw invisibles).
Unfortunately, there is an intermittent aspect to this. I use this subclass in several places and it works on my setup on the main editor, but not with some customers.
Then I found a different use of the same subclass that does not work for me.
When it does not work, it is consistent for that user.
I have manually marked the textViews as using TextKit 1, with no change.
I also tried the Clips Bounds to yes, again no change.
If I change the class to NSTextView, the text displays properly, but I lose existing functionality.
There appears to be some undocumented behavior change in Xcode 15 (or when linking against Sonoma SDK) that for subclasses of NSTextView (stored in XIB files). I know that there is a push to move toward TextKit 2, but it seems TextKit 1 support was possibly changed as well.
The text is there and I can edit it, double click, copy and paste it, it is just invisible, when compiled with Xcode 15 (also 15.1).
It has to be something very subtle that the subclassed TextView from one XIB will work, but from another XIB will not.
Does anyone have any insight into the potential change with TextKit 1 implementation?
Thanks.
General
RSS for tagDelve into the world of built-in app and system services available to developers. Discuss leveraging these services to enhance your app's functionality and user experience.
Post
Replies
Boosts
Views
Activity
Ok, weird one here. I have a widgetkit watch extension that I'm transitioning to. All code compiles clean, but when I go to install I get an error that it can't be installed on the watch because the extension does not define either a NSExtensionMainStoryboard or an NSExtensionPrincipalClass key. I don't have a storyboard for the extension as it's for the complications, so I added a principal class key.
Now it won't install with the error that it defines a principal class which is not allowed for the extension point com.apple.widgetkit-extension.
Huh. Well, ok, um... I guess I'll rip it out and stay with the deprecated clock kit complications, since they at least install. But this is very frustrating, and makes me think Apple wants us to go insane!
According to upcoming privacy manifest document, NSUserDefaults is only allowed for a use for the app itself.
It is serious for developers who makes App Extensions.
https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api
CA92.1
Declare this reason to access user defaults to read and write information that is only accessible to the app itself.
This reason does not permit reading information that was written by other apps or the system, or writing information that can be accessed by other apps.
Developers, please submit a request to add the permission of App Group.
https://developer.apple.com/contact/request/privacy-manifest-reason/
let formatter = DateIntervalFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .none
formatter.dateTemplate = "EEEjm"
Produces, in my locale and on my device with 24 hour time on:
"Tue, 6:39 – 7:10 pm"
I was expecting:
"Tue, 18:39 – 19:10"
Other date formatters are showing 24 hour time using the j symbol. For example:
let formatter = DateFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .none
formatter.setLocalizedDateFormatFromTemplate("EEEjm")
Produces, for the start and end dates:
Tue 18:39
Tue 19:10
Further, NSDateIntervalFormatter.h suggests I should be able to use symbols like j.
So why can't I create strings in 24 hour time with DateIntervalFormatter?
Thanks for your time.
iOS 16.7.1 / Xcode 15
Hi,
I was using NFCNDEFReaderSessionDelegate at first to read and write the cards, but didDetect tags method did not detect any tag because my nfc tag is not pre-formatted, it was calling other delegate methods so I have my NFCNDEFReaderSessionDelegate setup correctly. Hence, I used NFCTagReaderSessionDelegate, didDetect tags method of NFCTagReaderSessionDelegate detected tag and the tag was not pre-formatted. The issue I have been facing is I am not able to write for the first time and getting an error
Error Domain=NFCError Code=102 "Tag Not NDEF formatted" UserInfo={NSLocalizedDescription=Tag Not NDEF formatted}.
When I used another app from apple store to write data on the same tag which is not pre-formatted. Using that app, I am able to write the data on that tag. That app was using CoreNFC framework I believe, as it has NFC session alert which seems it was from apple library CoreNFC, so I assume that there must be a way to write the data on unformatted nfc tags. Do I have to use any low level of commands? I am not sure how can I fix this issue. Please provide some sample code, suggestions, right path to make the tag ready to have NDEF format and able to write the data on it.
Here is my NFC tag details:
I am trying to transfer data from one device to another using NFC. I'm trying to figure out if this is possible, I downloaded apple's sample project about CoreNFC, I was able to read NFC Tags (it wasn't a real NFC Tag, rather it was an NFC Tag emulated with an android device). Can I use my iPhone to emulate an NFC Tag to transfer data to another iPhone or Android device?
My app sends screen time awareness notifications based on DeviceActivityMonitor thresholds.
Often, users receive two notifications in a row for the same screen time threshold. This means that the app extension is triggering the same eventDidReachThreshold callback function twice for the same threshold. I've made sure that there is only one activity schedule being monitored. This happens often, but not every time (over 50% of the time).
Anybody else experience this issue, and any way to mitigate it?
I'd like to implement a fully immersive space that's experienced by multiple Vision Pro users simultaneously via SharePlay. To do this, the multiple Vision Pro users will join a SharePlay-enabled visionOS window that has a button to enter a fully immersive space, which is also SharePlay-enabled. I tried following the WWDC sessions and docs, but they don't provide enough detail about integrating SharePlay into an existing window and immersive space. How can I adjust my SharePlay code so it makes my visionOS window + fully immersive space SharePlay-able? Please see existing code below for a SharePlay visionOS widow, thank you.
P.S. WWDC ref. https://developer.apple.com/videos/play/wwdc2023/10087
import SwiftUI
import RealityKit
import RealityKitContent
import GroupActivities
import LinkPresentation
struct SharePlayWorld: View, GroupActivity {
@Environment(ViewModel.self) private var model
@Environment(\.openWindow) private var openWindow
@Environment(\.dismissWindow) private var dismissWindow
@Environment(\.openImmersiveSpace) private var openImmersiveSpace
@Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace
var body: some View {
@Bindable var model = model
Toggle(
model.isShowingPracticeSpace ? "Leave Space" : "Enter Space",
isOn: $model.isShowingPracticeSpace
)
.onChange(of: model.isShowingPracticeSpace) { _, isShowing in
Task {
if isShowing
{
await openImmersiveSpace(id: "SharePlayWorld")
}
else
{
await dismissImmersiveSpace()
}
}
}
.toggleStyle(.button)
}
// SHAREPLAY CODE
private func startSharePlaySession() async {
for await session in SharePlayWorld.sessions() {
guard let systemCoordinator = await session.systemCoordinator else { continue }
let isLocalParticipantSpatial = systemCoordinator.localParticipantState.isSpatial
Task.detached {
for await localParticipantState in systemCoordinator.localParticipantStates {
if localParticipantState.isSpatial {
// Start syncing scroll position
} else {
// Stop syncing scroll position
}
}
}
var configuration = SystemCoordinator.Configuration()
configuration.spatialTemplatePreference = .sideBySide
systemCoordinator.configuration = configuration
session.join()
}
// Create the activity
let activity = SharePlayWorld()
// Register the activity on the item provider
let itemProvider = NSItemProvider()
itemProvider.registerGroupActivity(activity)
// Create the activity items configuration
let configuration = await UIActivityItemsConfiguration(itemProviders: [itemProvider])
// Provide the metadata for the group activity
configuration.metadataProvider = { key in
guard key == .linkPresentationMetadata else { return nil }
let metadata = LPLinkMetadata()
metadata.title = "Explore Together"
metadata.imageProvider = NSItemProvider(object: UIImage(named: "explore-activity")!)
return metadata
}
self.activityItemsConfiguration = configuration
}
}
#Preview {
SharePlayWorld()
.environment(ViewModel())
}
I have a Home Screen widget that contains a timer counting down to a specific date. In this image you can see the date calculations:
eventDate: 25th Dec 2023 at 09:00:00
entryDate(Date.now): This is just showing you the date in the first SimpleEntry for the widget.
getTimeRemaining(entryDate): This shows the number of seconds from the entryDate to the eventDate, figures out how many days there are ("43 days"), and how many hours:mins:secs to the event time, so "10:48:52".
Then there's a second entry, entryDate2, that's one hour later, and the values are appropriately calculated.
When I create the timeline entries, I add them for:
Now (1 entry)
Now plus one hour to a week away (one entry per hour = 167 entries)
Event date (1 entry)
Event date plus one hour to a week later (one entry per hour = 167 entries)
Each SimpleEntry entry contains a dictionary with the relevant timer details, and that's what the widget uses to determine what to display in the timer.
SwiftUI lacks any useful formatting for a timer. Even the developer docs state: "Example output: 36:59:01". Who wants to see a timer with 36 hours on it? I want it to say "1 day 12:59:01", so I munge the numbers about and grab the separate parts, converting 36:59:01 into "1 day" and "12:59:01". You can see that in the image above.
When the entry date of the timeline is reached and the widget is redrawn, it uses the entry containing the dictionary saying it should display "43 days" and the countdown timer should be 10:48:52, then an hour later the dictionary says it's 43 days 9:48:52, etc.
The issue is that the widgets, even though they're supposed to have entries at each hour, will always end up displaying something like "29:17:09". The timeline has an entry at every hour, so it should be using the right values. I've checked, and the right values are in the dictionary, so why does the timer keep getting out of sync?
I could cut out a massive amount of my widget code if only Text.init(date, style: .timer) would allow some proper formatting.
I have edited the default widget with Intent, but am being hit with the following errors… it runs perfectly fine if I don’t use an Intent in a static widget
Could not find an intent with identifier ConfigurationAppIntent, mangledTypeName: Optional("27trainWidgetsConfigExtension22ConfigurationAppIntentV")
associateAppIntent(forUserActivity:) Error converting INIntent to App Intent: AppIntents.PerformIntentError.intentNotFound
I think it may be something to do with Info.plist?
Hello. I'm experiencing some issues with my iOS application. We distribute our app through an enterprise plan, and our app is almost 8 years old. We've noticed that on iOS 17 devices, our UserDefaults files are not being saved in the Preferences folder. I've conducted research on this issue, and everywhere I looked, it indicated that the system should handle this saving process. Does anyone know what changes have been made in iOS 17 that prevent us from saving data in UserDefaults? I've tested it with a new app, and it worked perfectly fine.
Below are screenshots of the 'Preferences' folder on iOS 17 and 16.
Hello
After updating my/our devices to iOS 17 (or XCode 15, not entirely sure), the custom fonts in our application have started randomly not working. Usually it will happen after the app has been in the background for a while.
What happens is that:
The fonts either don't load at all. For icon fonts, this means a lot of question marks.
The fonts get swapped around, meaning regular text (Roboto, custom font) starts rendering using the icon font (Font Awesome). I can tell because I recognize the font from development.
I have no idea how to reproduce it. I tried simulating the memory warning on the simulator, but that doesn't trigger it. It did not happen when building for iOS 16 and I did not change any font logic since then. It still does not happen on devices running iOS 17 but on versions of the app built with XCode 14.
Some debug info:
XCode: 15.0.1 (15A507)
iOS: 17.1.1 (real device, I have not observed it on Simulator)
We load the custom fonts from a proprietary SPM package:
fileprivate static func registerFont(fontName: String, ext: String = "otf") {
guard let fontURL = Bundle.module.url(forResource: fontName, withExtension: ext),
let fontDataProvider = CGDataProvider(url: fontURL as CFURL),
let font = CGFont(fontDataProvider) else {
fatalError("Couldn't create font from filename: \(fontName).\(ext)")
}
var error: Unmanaged<CFError>?
CTFontManagerRegisterGraphicsFont(font, &error)
}
public static func registerFonts() {
registerFont(fontName: "Font Awesome 6 Brands-Regular-400")
registerFont(fontName: "Font Awesome 6 Duotone-Solid-900")
registerFont(fontName: "Font Awesome 6 Pro-Light-300")
registerFont(fontName: "Font Awesome 6 Pro-Regular-400")
registerFont(fontName: "Font Awesome 6 Pro-Solid-900")
registerFont(fontName: "Font Awesome 6 Pro-Thin-100")
registerFont(fontName: "Font Awesome 6 Sharp-Light-300")
registerFont(fontName: "Font Awesome 6 Sharp-Regular-400")
registerFont(fontName: "Font Awesome 6 Sharp-Solid-900")
registerFont(fontName: "Roboto-Medium", ext: "ttf")
registerFont(fontName: "Roboto-Regular", ext: "ttf")
registerFont(fontName: "RobotoMono-Regular", ext: "ttf")
}
// Similar methods for all font types and icons:
@objc public static func getDefaultFont(size: CGFloat) -> UIFont {
return UIFont.init(name: "Roboto-Regular", size: size) ?? UIFont.systemFont(ofSize: size);
}
This code is the called in didFinishLaunching, and it would crash the app if it failed:
FontHandler.registerFonts()
To reiterate, all the fonts work when launching the app. Restarting the app always fixes it, which, combined with the fact that they get swapped around, leads me to believe that it's some kind of font caching issue.
We use the fonts in code-only (no storyboards or xibs ever). A font would be loaded like this:
let label = UILabel()
label.font = FontHandler.getDefaultFont(size: 15)
The font files ship with the SPM package itself, which contains the FontHandler class used above.
import PackageDescription
let package = Package(
name: "MyPackageName",
defaultLocalization: "en",
platforms: [
.iOS(.v11)
],
products: [
.library(
name: "MyPackageName",
targets: ["MyPackageName"]),
],
targets: [
.target(
name: "MyPackageName",
resources: [
.process("Fonts")
]),
.testTarget(
name: "MyPackageNameTests",
dependencies: ["MyPackageName"]),
]
)
I have a function that computes MD5 hash of a file:
func ComputeMD5(ofFile path: String) -> [UInt8]? {
if let data = try? Data(contentsOf: URL(fileURLWithPath: path)) {
var digest = [UInt8](repeating: 0, count: 16)
data.withUnsafeBytes {
_ = CC_MD5($0.baseAddress, UInt32(data.count), &digest)
}
return digest
}
return nil
}
Now I wonder/worry what happens if the file is very huge. Does the runtime perform disk memory paging?
Hello,
I'm currently experiencing an issue with the DeviceActivityMonitor extension in my code, specifically with the eventDidReachThreshold callback. I'm hoping to get some insights into why this problem occurs and how to resolve it.
Problem:
Issue 1: The eventDidReachThreshold callback is not triggering as expected. It appears that the callback is not being invoked when the threshold is reached.
Issue 2: After a few seconds, the eventDidReachThreshold callback starts to trigger multiple times. This unexpected behavior is causing problems in my code, as it results in incorrect actions being taken.
Issue 3: There are instances where the eventDidReachThreshold callback provides an incorrect event name.
iOS version: iOS16.7.2 and iOS17.1.1
Here is my code to start the monitoring:
func startMonitoring() {
var startTime : DateComponents = DateComponents(hour: 0, minute: 0)
let endTime : DateComponents = DateComponents(hour: 23, minute: 59)
/// Creates the schedule for the activity, specifying the start and end times, and setting it to repeat.
let schedule = DeviceActivitySchedule(intervalStart: startTime, intervalEnd: endTime, repeats: true, warningTime: nil)
/// Defines the event that should trigger the encouragement.
let event = DeviceActivityEvent(applications: socialActivitySelection.applicationTokens, categories: socialActivitySelection.categoryTokens, webDomains: socialActivitySelection.webDomainTokens, threshold: DateComponents(minute: 2))
let events: [DeviceActivityEvent.Name: DeviceActivityEvent] = [.socialScreenTimeEvent : event]
do {
activityCenter.stopMonitoring([.socialScreenTime])
/// Tries to start monitoring the activity using the specified schedule and events.
try activityCenter.startMonitoring(.socialScreenTime, during: schedule, events: events)
} catch {
/// Prints an error message if the activity could not be started.
print("Could not start monitoring: \(error)")
}
}
In addition, I should mention that, with each iteration through the eventDidReachThreshold callback, I increment the threshold by 2 minutes and restart the monitoring.
If there are any known workarounds or potential solutions, please share them.
Thank you.
Hello all,
My team makes a third-party SDK in the form of an xcframework, and we're working on creating our privacy manifest. However, I've noticed that the privacy manifest we include in the xcframework does not seem to get aggregated in with the base app's manifest when generating the privacy report.
Is that even the expected behavior? That when generating a privacy report, it will aggregate the manifests from the app and all frameworks? We've always recommended to our clients to select "Do not embed" when adding our SDK, as embedding it seems to introduce problems when submitting to the app store. Are the problems in the aggregation due to the fact that it's not embedded?
If it turns out that our manifest won't get aggregated with the client's app's manifest, what should we do? Should we recommend that they manually include any items from our manifest into theirs?
I'd appreciate any information, I haven't been able to find any solid details on any of this.
Hello.
I'd like to report something different behavior with before.
In previous versions of iOS (16.1~), after completing Apple Home app → SmartThings iOS app Multi Fabric onboarding, there was only one iOS system fabric in the device's fabric list as shown below.
Apple Home app
Apple Keychain (iOS system fabric commissioned by the Apple Home app or SmartThings iOS app)
SmartThings
In iOS 16.6.1, after completing Apple Home app → ST iOS app Multi Fabric onboarding, the device's fabric list has been changed to include two iOS system fabrics as shown below.
Apple Home app
Apple Keychain (iOS system fabric commissioned by the Apple Home app)
Apple Keychain (iOS system fabric commissioned by the SmartThings iOS app)
SmartThings
At this time, if the user removes the device from the SmartThings iOS app, only SmartThings fabric (4) will be deleted and Apple Keychain (3) will remain.
Apple Home app
Apple Keychain (iOS system fabric commissioned by the Apple Home app)
Apple Keychain (iOS system fabric commissioned by the SmartThings iOS app)
I'm afraid that it will fail if I try to add my device to Google Home or Alexa. Because max fabric count is 5 and it counts Apple keychain also.
Is this behavior expected?
Thanks.
Hello.
I'd like to ask below issue.
I have two SmartThings hub and one Matter device.
After I add it to the first hub, and then share this to the second hub with QR code, it always fails with below log. (SmartThings app shows both MPC and QR code when sharing a device)
with MPC code, it works fine
with QR code, it always fails in HomeUIService
default 23:15:16.895670+0900 homed >>> [E:42896i S:51446 M:229068112 (Ack:46785785)] (S) Msg RX from 0:FFFFFFFB00000000 [0000] --- Type 0001:09 (IM:InvokeCommandResponse)
default 23:15:16.897723+0900 homed Received Command Response Data, Endpoint=0 Cluster=0x0000_0030 Command=0x0000_0001
default 23:15:16.897753+0900 homed Failsafe disarmed
default 23:15:16.897789+0900 homed Successfully finished commissioning step 'Cleanup'
default 23:15:16.897823+0900 homed DeviceControllerDelegate Commissioning complete. NodeId 965088193 Status ../../../../../../../../Sources/CHIPFramework/connectedhomeip/src/controller/CHIPDeviceController.cpp:1405: CHIP Error 0x0000007E: Trying to add a NOC for a fabric that already exists
default 23:15:16.897892+0900 proximitycontrold < 91167F44>: Needs to restart ranging session as guest
default 23:15:16.897933+0900 homed SecureSession[0xda63c2b50]: Moving from state 'kActive' --> 'kPendingEviction'
error 23:15:16.898150+0900 homed Creating NSError from ../../../../../../../../Sources/CHIPFramework/connectedhomeip/src/controller/CHIPDeviceController.cpp:1405: CHIP Error 0x0000007E: Trying to add a NOC for a fabric that already exists
error 23:15:16.899257+0900 homed [965088193/1870446891] CHIP Accessory pairing failed: Error Domain=MTRErrorDomain Code=11 "The device is already a member of this fabric." UserInfo={NSLocalizedDescription=The device is already a member of this fabric.}
error 23:15:16.901186+0900 homed [188914BD-5163-425C-9E59-CAE9BFA1A288] Failed to stage CHIP accessory pairing for request UUID <private>: Error Domain=HMErrorDomain Code=13 "Accessory is already paired" UserInfo={NSLocalizedDescription=Accessory is already paired, NSUnderlyingError=0xda63f4600 {Error Domain=HAPErrorDomain Code=18}}
error 23:15:16.901587+0900 HomeUIService [34760036-B05B-475C-9C00-592445A9A053] Failed to stage CHIP accessory pairing in steps: Error Domain=HMErrorDomain Code=13 UserInfo={NSLocalizedDescription=<private>, NSUnderlyingError=0x2824bac70 {Error Domain=HAPErrorDomain Code=18}}
default 23:15:16.901762+0900 homed Answering incoming message HMASC.m.confirmDeviceCredential (795677CF-21ED-4E60-A5D5-3A7BF67BACCB) from client 'HomeUIService' that does expect a response with error Error Domain=HMErrorDomain Code=13 "Accessory is already paired" UserInfo={NSLocalizedDescription=Accessory is already paired, NSUnderlyingError=0xda63f4600 {Error Domain=HAPErrorDomain Code=18 "(null)"}}
default 23:15:16.902126+0900 HomeUIService -[HSSetupStateMachineCHIPPartnerConfiguration stageCHIPAccessory]_block_invoke Staged CHIP accessory without stagedCHIPAccessoryPairingIdentifier as it is already paired.
error 23:15:16.902254+0900 homed [188914BD-5163-425C-9E59-CAE9BFA1A288] tag="stagedPairingFailure" desc="Failed to stage CHIP accessory for request UUID" errorDomain="HMErrorDomain" errorCode="13" underlyingErrorDomain="HAPErrorDomain" underlyingErrorCode="18"
error 23:15:16.975718+0900 homed Creating NSError from /Library/Caches/com.apple.xbs/Sources/CHIPFramework/connectedhomeip/src/darwin/Framework/CHIP/MTRDeviceController.mm:701: CHIP Error 0x00000003: Incorrect state
error 23:15:16.975922+0900 homed [965088193/1870446891] Error: Error Domain=MTRErrorDomain Code=6 "Invalid object state." UserInfo={NSLocalizedDescription=Invalid object state.}. Failed to establish a connection to the device for unpairing. The device will not be notified of removal
error 23:15:16.979939+0900 homed Failed to remove keychain entry for accessory <HMDUnpairedHAPAccessory> - error Error Domain=HMErrorDomain Code=13 "Accessory is already paired" UserInfo={NSLocalizedDescription=Accessory is already paired, NSUnderlyingError=0xda63f4600 {Error Domain=HAPErrorDomain Code=18}}
I am setting up universal links for my app. And running into some issues when setting it up for production.
The following technical advisory recommends to use app search API validation tool.
Technical Advisory: https://developer.apple.com/library/archive/qa/qa1916/_index.html#//apple_ref/doc/uid/DTS40017117
Tool Path: https://search.developer.apple.com/appsearch-validation-tool
However clicking on the app search API validation tool leads to the generic search.developer.apple.com page. So where is the tool?
AASA File was applied to apply UniversalLink to the App. I deleted AASA to remove UniversalLink while using it normally. However, even though I deleted the file, I'm still opening the app. I've tried reinstalling the app several times, and I've also disabled the server cache, but it's no use. What should I do? Anyone knows?
We are developing a mobile app that allows users to purchase gift cards from popular retailers, and this app requires valid email address during login/register which is needed for mapping all user’s wallet and gift card details.
This app also supports social login like Apple, Facebook and Google and we are also providing a web platform where users can check their gift cards and wallet informations.
We are currently facing an issue with Apple SignIn when using “Hide by Email” flow. We observed that in this flow, the app generates a tokenised email address for user to login, and the same tokenised email address will be mapped to the user's gift card and wallet information.
Assume that an user register with mobile app using tokenised email address and the same user login into the web platform with a valid email address. In this flow, the user will not be able to see the wallet and purchased gift card information which could result in data issues and discrepancies between web and mobile apps.
We would like to know for any option to disable or remove “Hide by Email” from Apple’s SignIn popup. If not, could you suggest us a way to fix this issue.
Appreciate your quick response. Thank you!