Delve 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

Device Activity Label constantly logging 3x error
Every time I present an application title using SwiftUI view using Label(some_token) I get 3x of these logs, which sometimes incurs a noticeable lag in displaying my containing view. Otherwise the icon + title display correctly. I have tried making the most simple SwiftUI View just containing Label(some_token) without any other code, no state, no navigation, no transitions, no other views, just that and I still get this - usually in triplicate: [activityItem] Label is already or no longer part of the view hierarchy [activityItem] Label is already or no longer part of the view hierarchy [activityItem] Label is already or no longer part of the view hierarchy If I use .labelStyle(.titleOnly) I only see it twice. Here's the code I used var body: some View { VStack { // uses a static token provided just for testing. // same behavior regardless of how the token is passed in. Label(some_static_token) .labelStyle(.titleOnly) } } Is this log something to be expected?
9
1
2.1k
Mar ’23
iOS shortcut hangs with record audio if called by Siri in 16.4
Since the iOS 16.4 update on my iPhone 12 Pro I’ve been unable to run shortcuts using the record audio command, if the shortcut was called by Siri. It seems that Siri might be running it twice, as when I set the command to ask for input for its parameters I get the menu twice. When I run it from Siri, the record screen freezes and the seconds don’t count down, but when I run it from Shortcuts it works fine. Has anyone else experienced this, or have any suggestions? Thanks!
9
2
1.1k
Mar ’23
Incorrect Metadata.appintents with Xcode 14.3?
Recently (I think when updated to Xcode 14.3) my macOS Shortcut actions (implemented via AppIntent) started having a problem: When I click an action's AppEntity parameter I see the following error instead of seeing a list of entries to select from. The action “Demo Action” could not run because an internal error occurred. One difference that I notice between my builds that didn't exhibit this error and my builds that do exhibit the error: Working builds include objects.appintentsmanifest in the metadata folder Builds that break with the above behavior do not include that file Did something change in recent Xcode? What do I need to do so that Shortcuts app will run my queries again and provide popups so that I can select queried AppEnties? To recreate the problem I created a new Document Based App in Xcode 14.3 and included the following code. I then dragged "Demo Action" into a new Shortcut and clicked "Show More" and then clicked "Books: Choose". import AppIntents struct BookEntity: Identifiable, AppEntity { var id: UUID @Property(title: "Title") var title: String var displayRepresentation: DisplayRepresentation { DisplayRepresentation(title: LocalizedStringResource(stringLiteral: title)) } init(id: UUID, title: String?) { self.id = id self.title = title ?? "Unknown Title" } static var typeDisplayRepresentation: TypeDisplayRepresentation = "Book" static var defaultQuery = BookQuery() } struct BookQuery: EntityStringQuery { func entities(for identifiers: [UUID]) async throws -> [BookEntity] { library.filter { identifiers.contains($0.id) } } func entities(matching query: String) async throws -> [BookEntity] { library.filter { $0.title.localizedCaseInsensitiveContains(query) } } func suggestedEntities() async throws -> [BookEntity] { library } } struct DemoAction: AppIntent { static var title: LocalizedStringResource = "Demo Action" @Parameter(title: "Books") var books: [BookEntity] func perform() async throws -> some IntentResult { .result() } } let library: [BookEntity] = [ BookEntity(id: UUID(), title: "The Hobbit"), BookEntity(id: UUID(), title: "The Lord of the Rings"), ]
3
0
1k
Apr ’23
App Intents with OpensIntent does not work correctly
We are developing an app for iOS 16 using App Intents and Siri. We have been testing the behavior of opening another App Intent by passing the opensIntent argument to the result function in the App Intent with iOS 16.4 devices. As a result, we found that the dialog text specified in the result argument of the Intent to which it transitions is not displayed and therefore does not work. And also found that when invoked from Siri, the Intent passed to the opensIntent argument is invoked "twice". Are these behaviors bugs? Any ideas? The following is a sample code and logs. import AppIntents struct PrimaryIntent: AppIntent { static var title: LocalizedStringResource = "Primary" func perform() async throws -> some OpensIntent { print("\(String(describing: Self.self)).\(#function): invoked") return .result(opensIntent: SecondaryIntent()) } } struct SecondaryIntent: AppIntent { static var title: LocalizedStringResource = "Secondary" func perform() async throws -> some ProvidesDialog { print("\(String(describing: Self.self)).\(#function): invoked") return .result(dialog: .init(stringLiteral: "test")) } } struct ShortcutsProvider: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut(intent: PrimaryIntent(), phrases: ["\(.applicationName)"]) } } logs from Shortcut App PrimaryIntent.perform(): invoked SecondaryIntent.perform(): invoked # is not displayed dialog... logs from Siri PrimaryIntent.perform(): invoked SecondaryIntent.perform(): invoked SecondaryIntent.perform(): invoked # is not displayed dialog... # SecondaryIntent invoked twice...
1
1
1.5k
Apr ’23
CarPlay Simulator not receiving microphone input (Siri)
CarPlay Simulator not receiving microphone input (Siri) Running carplay simulator Version 1.1 (480.26) Running on: M1 Macbook Pro running macOS Ventura 13.3.1 Connected to: iPhone 13 pro max running iOS 16.4 (20E246) When launching Siri by "Hey Siri", the, the siri indicator apppears and I am able to communicate and send a command, such as "send a text". Then, the Siri will say "who do you want to message", but it is no longer able to hear my voice as input.
1
0
708
Apr ’23
DeviceActivityMonitor eventDidReachThreshold triggering every time in same second as intervalDidStart gets called
Hello, I am trying to make use of Screentime API in my app, I have issue with the DeviceActivityMonitor extension. I have schedule DeviceActivitySchedule which I set like this: let schedule = DeviceActivitySchedule( intervalStart: DateComponents(hour: 00, minute: 00), intervalEnd: DateComponents(hour: 23, minute: 59), repeats: false ) and DeviceActivityEvent which I set like this: let dateComponent = DateComponents(minute: 1) var events: [DeviceActivityEvent.Name: DeviceActivityEvent] = [ .encouraged: DeviceActivityEvent(threshold: dateComponent) ] The issue is that every time I start monitoring, by calling this piece of code from the app: do { print("Try start monitoring...") try center.startMonitoring(.daily, during: schedule, events: events) } catch { print("Error: ", error) } I catch in the extension that the event intervalDidStart is called, but in the same second I get called eventDidReachThreshold. What could be done wrong? Is event set properly? I was trying to set event with different Datecomponents (minute, hour, second), by setting different amount of time, like: let dateComponent = DateComponents(minute: 3) let dateComponent = DateComponents(second: 120) but nothing worked differently, every time, it was triggering eventDidReachThreshold right after the interval starts. If I put something unnormally high, like: let dateComponent = DateComponents(second: 120) The event eventDidReachThreshold is not triggered same time as the intervalStarts, but it is not counting time properly. Please if someone could help me, I want to be able to use events properly, with the amount of time which I set. Any help would be appreciated. Thanks in advance
3
1
1.2k
Apr ’23
DeviceActivityReport Lag
There have been several posts (i.e. here, here) about the lagginess of the DeviceActivityReport extension. Often it takes a few seconds for the view to load, or sometimes doesn't show up at all. I've confirmed this is not a case of excessive memory usage in the extension (exceeding 100MB), because I've profiled the extension and it consistently maxes out at 10MB. I've placed a loading screen behind the DeviceActivityReport inside a ZStack in the host app in order to see if the lag is because it takes some time for the extension to spin up - but the loading screen does not appear, indicating that the extension is running right away, but receiving the view from the extension in the host app is where the lag happens. It's been extremely difficult to debug because the lag only occurs a fraction of the time, and DeviceActivityReport is pretty much a black box. There's no documentation about how the host app and extension actually communicate. I've also combed through the logs using the Console app on Mac with no indication of any issues, (but I do see the message "Connection to view service was invalidated" coming from the extension even when there is no lag). I'm pretty convinced that the problem lies in the host app, because when I strip everything away from the host app, DeviceActivityReport never lags. I suspect that there are processes running (network requests, async tasks, or state updates) that block the report view from being received in the host app. Could you please help me understand why this could be happening, with as many details as you could provide? Any details on how the host and extension communicate, what processes could block the view from appearing, or anything else. Seems like this is a common issue but plenty of apps also don't experience it. Any guidance you can provide would be extremely helpful, as I've been trying to fix this bug every since I've been working with this API with no luck. Thanks in advance!
3
4
1.1k
Apr ’23
Resuming a file download in the background on iOS sometimes corrupts the file
To download files, we have two NSURLSession objects. One configured for foreground downloads and one for background downloads. Initially, we download user-requested files in the foreground using downloadTaskWithRequest, because foreground downloads are faster than background downloads. We then also start a background task for each download using beginBackgroundTaskWithName:expirationHandler:. This background task's expiration handler starts a background download if the download didn't complete in the foreground. It cancels the foreground download with resume data using cancelByProducingResumeData. A background download task is then started using downloadTaskWithResumeData. Now, testing has shown that background download tasks resume correctly (the urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:) callback is called by iOS) if the background task is started immediately. However, iOS can decide to start these background download tasks later. As a sidenote, the isDiscretionary property of our background download session is set to the default, which should be false. The issue we have is that background downloads that are resumed several minutes (6,5 minutes in the session I'm currently looking at) after their original foreground download was cancelled, are not resumed properly. They download the remaining part of the file, but the first part that was downloaded in the foreground is lost. What could have happened? Perhaps the temporary file has been deleted in the meantime? Is there some way to maintain this file or detect this case?
6
1
1.1k
Apr ’23
Time zone for PHAsset creationDate
Dear Experts, PHAsset.creationDate is an NSDate, which does not have a timezone associated with it, right? Consider a photo viewer app. If I take a photo of the sunrise at 0600 local time while I am away, when I get home and view the photo in the app, I believe I want the timestamp shown with the photo to be 0600. Do you agree? But NSDate is just a time-point, and I don't think Foundation (or anything else in iOS) has a type that combines a time-point with a time zone. Nor does PHAsset have any other useful attributes - unless I were to determine the time zone from the location! Am I missing anything?
3
1
1.1k
Apr ’23
Update Watch Complication with CloudKit
I have an iPhone app the uses CloudKit for Core Data syncing. I also have a companion Apple Watch app that syncs to the same CloudKit records. The watch can be used without the iPhone app as well but they both independently sync to the same CloudKit database. This works reasonably well. As soon as either app is opened, the CloudKit will pull down the latest records. I'd like to add a watch complication that shows the state of the CloudKit records. I supported this by adding a Widget extension, embedded in my watch app. The Core Data database in the watch app is part of an app group, so the complication is able to query the same database. So far so good. I'm running into problems with the complication updating after remote records are changed from the iPhone. Here is what is happening: When records are changed on the iPhone, the data syncs to CloudKit but the watch app is not updated when in the background. This is noticed when you open the app and it takes a second for the view to show the new records. Since Core Data database on the watch is not being updated while in the background, the complication is not being updated at all. Part of my confusion is I assumed CloudKit was meant to make this more seamless with silent push notifications? I have the "Remote Notifications" capability enabled on my WatchApp. It seems that only works while the app is in the foreground though. This seems very limiting when you have a complication that depends on the Watch app's Core Data state. I have a few things to work around this with mixed success: "Wake" the watch app explicitly when records are changed on the iPhone app using WatchConnectivityManager. The hope is that by waking the watch app, it will sync with iCloud. This either isn't working or intermittenly works. It is also not clear to me that by activating the watch app, that it will trigger records to sync. I wish there were a way to ask Core Data to sync explicitly. Whenever the Apple watch app wakes in the last step, ask it to WidgetCenter to reload the widget. This process feels convoluted and seems to negate some of the the benefits of CloudKit to synchronize data which I thought would be baked into this process. Any thoughts on a better approach to all this?
3
1
1.2k
May ’23
Performance Issues with UITextView and TextKit 2
I've been working with UITextView and TextKit 2, which became the default text engine since iOS 16, and I've encountered performance issues when handling very large text documents. Even on iPhone 14 Pro, I've noticed stuttering and frame drops when scrolling through the text view containing a large amount of text. To reproduce the issue, you can use the following code: // In iOS 16 let textView = UITextView() textView.text = "some really large string (say 1 million characters)" The scrolling performance in this scenario is not smooth. However, if you switch to TextKit 1 by accessing the layoutManager property, the performance significantly improves: // In iOS 16 let textView = UITextView() let _ = textView.layoutManager // this enables the compatibility mode textView.text = "some really large string (say 1 million characters)" With this code, scrolling remains smooth even with large text documents. It's very disappointing to see TextKit 2 performing worse than TextKit 1, even though Apple claims TextKit 2 has significantly improved performance with noncontiguous layout. Furthermore, the sample code for TextKit 2, available here, crashes when handling very large text due to excessive memory usage. Has anyone else experienced similar performance issues with TextKit 2, and are there any potential solutions or workarounds to improve the performance?
2
0
1.2k
May ’23
App Site Association (AASA) not recognised for App Clip
I am trying to configure App Clip Experience URL in App Store Connect and it gives me this error message and does not allow to proceed: This URL is not contained in your app’s associated domains. Update associated domains or use a different URL. I have already investigated different options why it can fail and also validated the file over third-party validators. So this is already checked: AASA file available on my domain Content for app clips and app links is specified (see below) Team ID is correct JSON is properly formatted Content Type JSON is specified AASA file visible over Apple CDN https://app-site-association.cdn-apple.com/a/v1/ I waited enough hours after last change Target domain entered into Associations List in Xcode in both main app and App Clip target App bundle with updated Associations is uploaded to App Store Connect I have created Apple TSI yet got no answer for a week already. Any other ideas what I can check? AASA file content: "applinks":{ "apps":[ ], "details":[ { "appID":"8KDIE88JJ.com.baraboo.app", "paths":[ "NOT /_/*", "/*" ] } ] }, "appclips":{ "apps":[ "8KDIE88JJ.com.baraboo.app.Clip" ] } }
3
0
962
May ’23
Device Activity - DeviceActivitySchedule DateComponents intervals
Hi, I'm having trouble understanding what is the correct DateComponents format for the DeviceActivityCenter.startMonitoring to work as expected. Here's how it behaves with my setup: The schedule interval is set for 15 minutes (the minimum). On intervalDidStart I set the shields shield.applicationCategories = .all(except: exclCat) shield.webDomainCategories = .all(except: exclWeb) On intervalDidEnd I clear the settings shield.applicationCategories = nil shield.webDomainCategories = nil Different behavior with different DeviceActivitySchedule intervals. In the below examples I'll refer to hour, minute and second components as time components, and the calendar, timeZone, year, month, day, hour, minute and second components as date and time components. Also, with all combinations below no errors are thrown when calling the startMonitoring method. A. ❌ The start interval has time components, while the end interval has date and time components: The intervalDidStart is not triggered. DeviceActivitySchedule(schedule: <USDeviceActivitySchedule: 0x28354a5e0> IntervalStart: <NSDateComponents: 0x2839c7f40> { Hour: 9 Minute: 24 Second: 55 IntervalEnd: <NSDateComponents: 0x2839c7f70> { Calendar: <CFCalendar 0x2818f9090 [0x1e4fb1d10]>{identifier = 'gregorian'} TimeZone: Asia/Manila (GMT+8) offset 28800 Calendar Year: 2023 Month: 5 Leap Month: 0 Day: 15 Hour: 9 Minute: 39 Second: 55 Repeats: 0 WarningTime: (null)) B. ❌ The start interval has date and time components, while the end interval has time components: Here, the opposite of the above example happens — the intervalDidStart is triggered, but the intervalDidEnd is not. C. ❌ Both intervals have time components: The intervalDidStart is not triggered. D. ✅ Only hour, minute, and second components for both start and end intervals: Callbacks are called as expected. DeviceActivitySchedule(schedule: <USDeviceActivitySchedule: 0x282e80450> IntervalStart: <NSDateComponents: 0x2822f39f0> { Hour: 9 Minute: 12 Second: 15 IntervalEnd: <NSDateComponents: 0x2822f3a00> { Hour: 9 Minute: 27 Second: 15 Repeats: 0 WarningTime: (null)) So it seems that the correct and working version is with the time components only. However, from the documentation, the maximum schedule interval is a week. So if I need to set the schedule starting from a certain time of day A and ending in a certain time of day B, what should the DateComponents look like? Thanks for you help!
5
2
1.5k
May ’23
ShieldConfigurationExtension not working
I created a ShieldConfigurationExtension in Xcode 14.3 with File > New > Target > ShieldConfigurationExtension. This created the extension with all the necessary Info.plist values (correct NSExtensionPrincipalClass, etc.), with the extension included in embedded content in the host app target. No matter what I try, the extension is not getting invoked when I shield applications from my host app. The custom UI does not show as the shield, and looking at the debugger, an extension process is never invoked. I am shielding categories like this: let managedSettings = ManagedSettingsStore() ... managedSettings.shield.applicationCategories = .all() And my extension code overrides all the ShieldConfigurationDataSource functions. class ShieldConfigurationExtension: ShieldConfigurationDataSource { override func configuration(shielding application: Application) -> ShieldConfiguration { return ShieldConfiguration( backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial, backgroundColor: UIColor.white, icon: UIImage(systemName: "stopwatch"), title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow) ) } override func configuration(shielding application: Application, in category: ActivityCategory) -> ShieldConfiguration { return ShieldConfiguration( backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial, backgroundColor: UIColor.white, icon: UIImage(systemName: "stopwatch"), title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow) ) } override func configuration(shielding webDomain: WebDomain) -> ShieldConfiguration { return ShieldConfiguration( backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial, backgroundColor: UIColor.white, icon: UIImage(systemName: "stopwatch"), title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow) ) } override func configuration(shielding webDomain: WebDomain, in category: ActivityCategory) -> ShieldConfiguration { return ShieldConfiguration( backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial, backgroundColor: UIColor.white, icon: UIImage(systemName: "stopwatch"), title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow) ) } } What am I missing?
4
2
1.7k
May ’23