Hey everyone,
From WWDC23 lab conversations, in order to run a fitness app, health tracking apps, etc. on iPadOS 17 that 'requires' health, you actually have to remove the UI Required Device Capabilities for Health. The UIRDC will still prohibit the app from running on iPad this fall even though from a developer lens it is satisfied.
I understand this is to allow iPhone apps a chance to upgrade and get ready for iPadOS 17, but there isn't a path forward if an app truly requires HealthKit. Namely for fitness apps that ONLY read and or write data to Health. Sure I could move my target SDK to 17, but that doesn't help my existing users who can't upgrade on iOS < 17.
What is the path forward for Apps that want to target something like the following?
iOS 14+
watchOS 7+
iPadOS 17+
Socializing the idea of having an App Store Connect feature or checkbox to allow / opt into being available on iPadOS 17+. The same applies for App Clips that also require HealthKit.
FB12327957 - Health / App Store Connect: Ability to make HealthKit required on iPadOS and iOS together
Post
Replies
Boosts
Views
Activity
I've been getting duplicate visits sent to my CLLocationManagerDelegate. This is new since iOS 16, I did not see this behavior in iOS 15--the observed effect is a quite severe regression in the behavior of CoreLocation.
Here is what I'm seeing:
The visits have already been delivered
When they're sent 'again', they're sent in dozens of callbacks
When they're sent 'again', they're sent in batches irrespective of app state
I have had a debug app on my phone running since November to capture sysdiagnose for FB12107066. My app simply records data from CoreLocation into a mini Core Data table.
Since November 11th, I have had 3808 visits, but when I do some distinct queries on arrival and departure I get a fraction of that.
Select distinct arrivalDate: 929
Select distinct departureDate: 799
Select distinct arrivalDate + departureDate: 1172
I wrote some logic to attempt to deduplicate and filter out garbage visits that have already been delivered to me, but my filtering isn't bullet proof. This issue has been happening for me on multiple devices since Nov (iOS 16.2 days?).
This happens on an iPhone 13 Pro and an iPad Pro 11-inch (4th gen).
This is a real nasty bug as it also keeps waking my app up in the background when I don't expect it to since the OS is delivering me old / replay visits. :/
Has anyone else seen issue with the Core Location Visit API in iOS 16?
What deduplication and filtering logic did you come up with?
While the issue is affecting me via CoreLocation, I would suspect the same might also occur for anyone using the visits API in SensorKit too.
I have a simulator named "iPhone 14 Pro" created and booted. The override --time command doesn't appear to take anymore. This worked months ago, but broke somewhere along the road of Xcode 14.x. It is a drag setting the system time to 9:41 for App Store Connect screenshots which is why I used the command in the first place.
I cannot seem to successfully set the status bar time of the simulator via the following command anymore: xcrun simctl status_bar "iPhone 14 Pro" override --time "9:41"
Is this working for anyone else lately?
Feedbacks; Created these Dec 7, 2022
FB11859751 - Simulator: iOS simulator not responding to simctl set time
FB11859744 - Simulator: watchOS simulator not responding to simctl set time
Note: My app is in pre-order status for a version approved against Xcode 13.4.1, the below is for submitting an update with iOS/iPadOS 16 support using Xcode 14 RC released today.
Is this happening for anyone else?
I just downloaded Xcode 14 RC and archived/uploaded a build. When I select the build in App Store Connect to submit to review, it isn't showing my App Clip domains.
When I select a build that was created yesterday with Xcode 14 Beta 6 from Xcode Cloud, the domains show, but for obvious reasons (Xcode beta tools) I cannot submit that build.
I'm waiting for Xcode Cloud to add RC to their list and try again, but I'm stuck. I think it is just an App Store Connect issue, because my code is literally unchanged between these two builds less the build version. Furthermore, I inspected the archive locally from Xcode 14 RC and in the validation step, confirmed the entitlement lists my two appclips associated domains in both the app target and app clip target.
I created a feedback for this here: FB11471066, FB11335182
Has anyone else had this issue? I know that App Clips was having some issues a few weeks ago but this seems like something entirely different: https://developer.apple.com/forums/thread/712372
Finally, to the last of my ability to troubleshoot, running the Diagnostics under App Clips Testing in the Settings app, I get all green checkmarks for both of my domains--so I really just believe this to be a portal issue and that everything actually checks out.
I would like to socialize the idea of starting a Live Activity while the app is in the background. According to the ActivityKit, documentation, Live Activities can only be started while your app is foreground. I wrote up a really lengthy feedback about this enhanced ActivityKit permission concept but will summarize to share with others here. FB11308611
The idea is this, like CoreLocation, the ActivityKit framework could have the permission model of 'when in use' and 'always'. Apps that the user has granted the 'always' permission for would then be allowed to start an activity from some sort of background execution. I'm looking at the Background Modes defined in Xcode namely: Location Updates, Bluetooth, Remote Notifications, Nearby Interactions, etc.
My specific use case is to combine my usage of Core Location Region Monitoring and Visit Monitoring into triggering a Live Activity to the users Lock Screen when they are at a place contextually relevant to my app(s). I can imagine this applies to many other applications too. While the current experience I have will present the user with a local notification gets the job done, the user experience could be so much more engaging. When I saw the Live Activities feature get announced during WWDC22, this was the first thing that came to mind. FB11308699
Some very high level concepts:
Live Activity when entering a sport stadium
Live Activity when entering a concert venue
Live Activity when entering a gym
Live Activity when entering a restaurant
Live Activity when entering a store
Got another use case? Share it! Like a use case in this thread? Comment on it!
I just released my app for pre-order and the message link preview in the Messages app for the listing is somehow using an older screenshot that was provided to App Store Connect weeks ago.
I deleted and uploaded new screenshots just this weekend before sending in for review and everything looks correct in App Store Connect. I just confirmed what is showing in link previews does NOT match what was approved in App Store Connect. Has anyone else encountered similar issues when listing their apps for pre-order or just in general?
What is really strange is that the image being shown in link previews was approved once, but I developer rejected it. Maybe some caching issue with Apple preemptively propagating the images when it was approved the first time before I chose to release it? Just speculating.
FB11257903
I'm getting a 404 page when I attempt to interact with the advanced App Clip editor page within App Store Connect. Can anyone else edit their app clip experiences right now, or do you also get a 404?
Steps for both released and unreleased apps:
Navigate to an app in App Store Connect
Scroll to App Clip section
Click "Edit Advanced Experiences" button
Receive a 404 page
Last tested Sunday Aug 14, 2022, @ 9:52 AM CDT.
I filed this feedback for this issue: FB11252461
Separately, has anyone integrated with the App Store Connect API for App Clips? Not sure if just the portal is affected or if the API for App Clips is down too.
I have an existing WidgetBundle containing a single widget today that works with iOS 14/15. When I add the ActivityKit widget (aka Live Activities), Xcode naturally complains that this is available iOS 16 only.
Adding an #if available(iOS 16.0, *) check inside the WidgetBundle results in an error:
"Closure containing control flow statement cannot be used with result builder 'WidgetBundleBuilder'"
Would the proper mechanism here be to create a second widget extension that ONLY includes the widget for the Live Activity and then use the available modifier on the entire widget bundle to only include it in iOS 16+?
This thinking is based off the following here
Typically, you include all your widgets in a single widget extension, although your app can contain multiple extensions. For example, if some of your widgets use location information and others don’t, keep the widgets that use location information in a separate extension. This allows the system to prompt the user for authorization to use location information only for the widgets from the extension that uses location information.
Hey everyone, I've been experimenting around with the new searchable update to add scope to SwiftUI search bars. I requested this last fall and now I'm looking into it as available with Xcode 14 / iOS 16 (FB9674003).
I found two bugs in case others run into them.
The search bar's segmented 'scopes' only show if the search binding is a non-empty string. (FB10558607)
The selected scope binding is not honored when updated outside of the searchable search bar itself. (FB10558881)
It is my assumption that these are both defects. Attached is a sample view that illustrates the two bugs.
Additionally, writing this up, I felt it was important to also provide developers the ability to specify the visibility of the segmented scopes within the search bar which is possible in UIKit (FB10558936). Something like .searchableScopeVisibility(.always).
import SwiftUI
struct ContentView: View {
enum FoodScope: CaseIterable {
case fruit
case veggies
func scopeText() -> String {
switch self {
case .fruit:
return "Fruit"
case .veggies:
return "Veggies"
}
}
}
private let fruits: [String] = ["Apple", "Apricot", "Banana", "Cantaloupe"]
private let veggies: [String] = ["Asparagus", "Beets", "Broccoli", "Cabbage"]
@State private var searchText: String = ""
@State private var scope: FoodScope = .fruit
private var filteredFood: [String] {
switch scope {
case .fruit:
guard searchText != "" else { return fruits }
return fruits.filter { $0.contains(searchText) }
case .veggies:
guard searchText != "" else { return veggies }
return veggies.filter { $0.contains(searchText) }
}
}
var body: some View {
NavigationStack {
List {
Section {
ForEach(filteredFood, id: \.self) { food in
NavigationLink(food, value: food)
}
} header: {
Text("Food")
.textCase(.none)
}
// FB10558607 - SwiftUI: Searchable "scope" non functional in Xcode 14 beta 2 (scope items not visible when searching)
Section {
} footer: {
Text("The 'scopes' provided within the new searchable modifier will only be shown when the searchable text binding is a non-empty string. Try for your self by tapping inside the search. You \"should\" see the scope segments appear right away but they don't. Then type any character and they'll show on screen. FB10558607")
}
// FB10558881 - SwiftUI: Searchable 'scope' binding is not honored when updated by another mechamsim outside of the searchable scope picker
// Create another binding to the selected scope and change it. The picker in the search bar does NOT reflect the state of SwiftUI's @State scope property.
Section {
Picker("Scope", selection: $scope) {
ForEach(FoodScope.allCases, id: \.self) { scope in
Text(scope.scopeText())
.tag(scope)
}
}
.pickerStyle(.segmented)
.buttonStyle(.plain)
.listRowBackground(Color.clear)
} header: {
Text("Searchable Scope Binding Selector")
.textCase(.none)
} footer: {
Text("Additionally, the scope binding will not update when modified via another mechanism (like another segmented picker). When the segments are visible with the search, change the scope and you'll see the binding to the picker change. But, if you change the scope of the picker below, the scope in the search bar will not react as expected. ")
}
}
.listStyle(.insetGrouped)
.searchable(text: $searchText, scope: $scope) {
ForEach(FoodScope.allCases, id: \.self) { scope in
Text(scope.scopeText())
.tag(scope)
}
}
.navigationTitle("FB9674003")
.onChange(of: scope) { newValue in
print("New scope \(newValue.scopeText())")
}
.navigationDestination(for: String.self) { value in
Text("You selected \(value)")
.navigationTitle("Yummy food")
}
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
Xcode 14 beta 1 is yelling at me that CKNotification initializer should return a non-optional value. This happens only AFTER letting Xcode upgrade my project settings.
The change that the upgrade project settings made was it merged my WatchKit and WatchKit extension targets into a single watch app target.
After doing so, this code will not compile which I know to be good.
// This line fails to compile with '
if let notification = CKNotification(fromRemoteNotificationDictionary: userInfo) {
// Do something
}
Compile error: "Initializer for conditional binding must have Optional type, not 'CKNotification'"
Feedback w/ sysdiagnose:
FB10282805 - watchOS / CloudKit: CKNotification doesn't return optional, xcode build failing after updating project settings for Xcode 14
I could not reproduce this in a sample application. I tried making a standalone watch app with Xcode 13, upgrading the project file with Xcode 14 beta, and then creating a CKNotification object--but that worked fine. :/
Has anyone been successful creating a widget configuration that uses any of the "Measurement" type parameters? I'm running into crashes in the Widget/Home Screen when I try to do so.
I am building a widget that provides functionality to 'nearby' points of interest. I just discovered that SiriIntents support specifying a Measurement type now --> Distance.
When I have my configuration "nearbyDistance" parameter type set to the measurement type of Distance, adding the widget from the widget gallery crashes it after I hit the add button and it doesn't get added.
This works:
This crashes the Widget Preview and doesn't add the widget to the Home Screen:
Right before I add my widget, things seem to be good:
As soon as I tap Add Widget, this happens:
I have created a feedback for this and attached some recordings and a sysdiagnose: FB10002319
I've noticed a bug in my app recently, it appears that in watchOS 8.5 (or earlier) that page layout is no longer initializing or awakingWithContext the pages beyond the first index.
According to the documentation:
In a page-based interface, all interface controllers are initialized up front but only the first one is displayed initially.
https://developer.apple.com/documentation/watchkit/wkinterfacecontroller/1619521-init
I am simply not seeing this happen anymore. I have logging in all of the lifecycle method of all three of my pages and the second and third controllers don't fire anything (including init) until I swipe to the right. This is when I would expect the willActivate and didActivate methods to be invoked. Instead I get init, awake, willActivate, and then didActivate. :/
This is unfortunate and a bug to the user because the second controller asks to becomeCurrent under some certain conditions that the first detects and fires via NotificationCenter. The automatic programatic switching between pages is totally broken.
FB9972047
Hey developer community / CloudKit fans,
I'm making an application that utilizes CloudKit's identity system to provide my users a 'social' aspect of the app as well as their own identity. When filling out my App Privacy label, I'm torn if I should disclose Contact usage or not.
https://developer.apple.com/documentation/cloudkit/ckcontainer/1640421-discoverallidentities
Right now, I'm leaning to not specifying Contacts collection. Here are my thoughts:
Data Collection defined by Apple, paraphrased, is transmitting data off device for longer than needed for the request.
How Apple implements the function of the CloudKit identity lookup is outside of our control as developers, however, it is reasonable to expect that Apple would not save your contact address book in CloudKit and the data does not live in CloudKit longer than it needs to.
I don't access the Contacts app or API in the implementation.
Apple in fact use your contacts under the hood to service this request according to the documentation, however to the user, there is no contacts permission / access prompt for the application itself. The app doesn't get access to the full contacts db.
When you receive a CKUserIdentity, the contacts identifier is just that, a lookup identifier string.
I'm not going further than just displaying the information on the user identity. I could back link the identifier to a contacts record, but I don't need to. If I did that, even then I would say no, because the operation all happens locally on device.
Does your app use CKUserIdentities? How did you answer the App Privacy question for Contacts?
If you have strong feelings one way or another, I'd love to hear your perspective.
In my application initializer, I set a property on ApplicationDelegate. It is a reference to my data controller that manages access to many things (core data model). It gets passed in there to handle launch keys and pushes, and is relied upon as a required dependency to many services--namely push, navigation actions (quick look, Siri intents, etc.).
In summary, I want to clean up and move some initialization code from my application initializer (tons of compiler directives for multi targets, watch, app, etc.) to the respective application delegates. BUT this requires an assumption that didFinishLaunching will be called after a property is injected into app delegate. Is this a safe assumption to make?
I have observed the didFinishLaunching getting invoked only AFTER the initializer of Application completes. Can this be relied upon in terms of dependency injection?
Can this order be assumed?
Application init
Property assignment on app delegate within app init
App delegate init
Property is set (didSet fires)
App initialization complete, return
Delegate fires willFinishLaunching
Delegate fires didFinishLaunching
Other delegate methods fire accordingly
I assume that the implementation of UIApplicationDelegateAdaptor under the hood is similar to the Coordinators in UIViewRepresentable where as soon as you try to access / assign something on it, then it constructs the object and assigns an instance to the property wrapper.
Additionally, if it hadn't already been initialized, because it DOES need to call delegate callbacks, the system will invoke it had you not already assigned a property to initialize it.
I have a record type called ContactInformation that has phone and email as fields. This record type also has two references that point to different types. Namely type1 and type2 for illustration (one is a person reference, another is a place reference).
When I seed my application I do a blind query operation to get all records. I don't think there is a way to perform a query using a predicate where the field isn't nil but thought I'd pose the question to the forums.
The idea would be query where type1 != nil and then a second one where type2 != nil. Using CloudKit Console doesn't receive any results when running the following queries so I don't think this is supported as of today.
CloudKit Console provides the following error when a reference filter by is applied with empty value: invalid id string: empty
As a work around, I could create a 'dummy/default' reference id then the != "dummy identifier" would in theory work but it feels very hacky.
Has anyone found a more elegant solution than to use a dummy reference ID?
I filed this feedback requesting the ability to create a predicate that supports nil values: FB9833175