Posts

Post marked as solved
1 Replies
From the error message, it looks like a value of nil is not acceptable. Try adding a UTF8 string value and see if it works then.
Post not yet marked as solved
1 Replies
Users on iOS 15 will still be able to download your 'final iOS 15' app version if you let them via last compatible version. You can look at this page and see a screenshot of it in App Store Connect. https://developer.apple.com/help/app-store-connect/manage-your-apps-availability/make-a-version-unavailable-for-download Keep in mind any services or APIs that you integrate with are still subject to availability per those providers.
Post not yet marked as solved
3 Replies
@andreikrn @atul3189 @dkvijay The conversation I had with a MetricKit engineer during WWDC20 or WWDC21 labs was that the user setting to "Share with App Developers" is not used in MetricKit when deciding to generate a metric or diagnostic payload. If you read the footer carefully, "Share with App Developers" is an Apple thing, Apple is sharing it with developers. MetricKit allows YOU, the developer, directly receive the data and then handle it responsibly. I have been operating under this assumption for years. I just wrote up a feedback requesting a docs update for this. Fingers crossed. FB13618353 - MetricKit / Developer Documentation: Add description to the behavior of MetricKit with respect to "Share with App Developers" setting Before operating under this assumption, please consider giving your users the option to control data collection. #privacy-by-design So now that you've thought about letting users choose to participate in this data collection within a feature or setting in your app, it is easy to validate the assumption that MetricKit is not tied to "Share with app developers". Turn off the "Share with App Developers" setting Create a button that crashes your app. Generate logs or save the payload in your subscriber didReceive callback Install this app on a device via Xcode or TestFlight Ensure you are NOT debugging, as the crash will be caught by Xcode Tap the crash button Relaunch the app, your app SHOULD get a callback Verify that your log is printed or the payload is persisted via your process An alternate path if you don't log or save the MXDiagnosticPayload would be: Set a breakpoint on your didReceive diagnostics method Attach the debugger (run app) on your device with Xcode after the app is crashed Verify during app launch that you didReceive diagnostic callback is invoked. I just verified this with iOS 17.3.x in one of my apps using the alternate path and Xcode 15.2. NOTE: For all of this to work, you should be setting the .addSubscriber method somewhere during app startup--my favorite spot is didFinishLaunching. Even for a SwiftUI application, I still have a UIApplicationDelegateAdaptor and in that implementation I put it in didFinishLaunching. Now a note on privacy and MetricKit data collection. Because the user can't control my app's MetricKit payload collection via the global setting "Share with app developers", I have explicitly put reference to MetricKit metrics and diagnostics in my privacy statement. Furthermore I have given users the option to enable/disable directly within my app. With that having been said, I do make a decision that, if you use a TestFlight build of my app for beta testing, both diagnostics and metrics will be recorded by default to help improve my app--that is after all the whole purpose of TestFlight right? P.S. Don't forget to update your App Privacy Label with respect to this data collection too! I conditionally detect installed from TestFlight and add a disclaimer to the very top of my Privacy Policy. If the user did in fact install a TestFlight build, they will see this in the settings to enable/disable collection. Again, note the disclaimer. My apps don't always crash, but when they do MetricKit is there for me to records it. As an added perk, MetricKit can capture events that other off-the-shelf crash reporters just can't do, so I use MetricKit exclusively to build the most privacy preserving crash reporting solution I can.
Post not yet marked as solved
1 Replies
You should unit test your logic, not your CBCentralManager itself. Unit testing Core Bluetooth isn't going to yield the results you expect. It is just as you described, unit testing isn't running in an app per-say. Simple fact, you can't initialize many of the Core Bluetooth types, namely CBPeripheral. I'd check out the following video and refactor your code accordingly for testing. https://developer.apple.com/videos/play/wwdc2018/417/
Post marked as solved
3 Replies
What are you trying to enable the user to do? Most things are not possible to navigate directly into the Settings app. Secret apple sauce. If Bluetooth is off and you want to turn it on AND you're using CoreBluetooth, initialize your manager with the power key. This will trigger a prompt to the user to either enable Bluetooth, or start new connections if that was turned off for the day. self.centralManager = CBCentralManager(delegate: nil, queue: .main, options: [CBCentralManagerOptionShowPowerAlertKey: true])
Post not yet marked as solved
2 Replies
According to the documentation of the characteristic write options, the write with response SHOULD chop up the message and perform a long write. Core spec 4.0 Part G 4.9.4. https://developer.apple.com/documentation/corebluetooth/cbcharacteristicwritetype I created a feedback for this as I am also encountering the prepareQueueFull unexpectedly. FB13596337 Here are some console logs: Central (iPadOS 17.2) (client) error bluetoothd 21:53:42.361949-0600 com.apple.bluetooth Stack.GATT Received error response 9 for write long value - canceling execution (status=65535) error bluetoothd 21:53:42.421534-0600 com.apple.bluetooth Server.GATT Failed to write long characteristic value at handle 0x001b on device "58B87653-65EE-23CB-2E99-0D70A24D0CE2" - result was 9 error bluetoothd 21:53:42.421727-0600 com.apple.bluetooth Server.GATT Command failed to execute with status 9 error bluetoothd 21:53:42.422360-0600 com.apple.bluetooth Server.GATT Command failed to execute with status 9 Peripheral (macOS 14.2) (server) error bluetoothd 21:54:52.323246-0600 com.apple.bluetooth Server.GATT Refusing Prepare Write Request as it would exceed the maximum amount of data queued (512) for this connection by 135 byte(s) error bluetoothd 21:54:52.323518-0600 com.apple.bluetooth Stack.ATT Failed to write value to attribute handle 0x001B with result 9 (status=65535)
Post not yet marked as solved
1 Replies
Have you considered passing in your preference value directly as an initializer parameter to your UIViewRepresentable type? If it needs to change, you can pass a binding. What was the motivation for using a preference value?
Post not yet marked as solved
1 Replies
Have you confirmed via another mechanism that your app is indeed crashing? Off the shelf crash solution, device crash file, test flight crashes, etc. I assume that you are calling your start() method. To check this out: Run your app with Xcode with debugger attached Xcode > Debug > Simulate Metric Payloads Observe your code being invoked (or not). I have noticed that in flavors of Xcode 14, this doesn't work to reliably give diagnostic payloads but seems to have been fixed for my setup in Xcode 15. Once you've verified your code is wired up properly via the Xcode feature, then check your understanding/expectation about WHEN the diagnostics will be delivered to your callback below. If you're expecting the app to crash in the background here is a tip: The MetricKit diagnostic payload callback, according to the MetricKit team via a WWDC session a few years ago, is non-launching. Do you have other features in your app that would normally launch the app in the background? If so, you should expect diagnostics periodically. If not, then you'd get them when your app was launched by the user. If you're expecting the app to crash in the foreground, then for sure, the next time you launch it I would expect to receive the payload.
Post not yet marked as solved
3 Replies
@joshmooredd TLDR: Start using MXCrashDiagnostics contained within the MXDiagnosticPayload. This has timestamps of crashes. If you're looking for exact timestamps, you might be able to discern some of them by looking at the MXDiagnosticPayload and the resulting MXCrashDiagnostics within. If however, you are just looking for ORDER and relative time, then you can build this out yourself with a few different techniques. Meaning if you just care about timeline and sequence of your events intermixed with exits--check out the following recommendations. Use official Apple API to detect TERMINATIONS (by the user). See: UIApplicationDelegate - applicationWillTerminate You're not guaranteed to get this callback, but when you do, expect it to show up in exit data later on in the metric payload Use a signal handler to inspect uncaught exceptions. Not for the faint of heart. If you're only looking to make breadcrumbs and NOT capture things like call stacks at the time of an uncaught exception, this might be an okay thing to do. Look at ANY of the shelf open source crash reporting solution for examples. BUT, also heed the words of @eskimo here: Implementing your own crash report If you're just worried about order, start looking at the crashes found in the MXDiagnosticPayload. They will contain a timestamp of when the crash occurred and then you can build your timeline. Some of the MXCrashDiagnostic might have easy to map exceptionType, exceptionCode, and bsd signals that you can map to the exit data counts. If you're targeting iOS 17, PID to the rescue. I asked in feedback to add some identifiers to be added to the payloads, and as a response I got PID in the metadata (big thanks MetricKit team!!! FB9616844). IF your events were capturing PID, hint look at ProcessInfo, you could know for certain which crashes were in which run of the app with respect to your events. Then use this info and combine it with suggestion 3. Hope this helps you on your journey to making better apps!
Post not yet marked as solved
1 Replies
@BringSupersonicsBack What are the other fields of the crash? Have you converted the exception code, type, and signal to the mach exception codes and BSD signals? That might give us some hints--though I expect all types to generate a stack frame. Also, have you noticed any consistency when this happens in terms of either device type or os version? Look at the metadata. This would be helpful to identify if it smells like a bug introduced in X OS version on Y device models. Smells like a bug to me. I'd suggest making a defect with the MetricKit team via Feedback Assistant. I'm building a MetricKit analysis app for iPad and Mac and I'm curious about your findings too as it is a data scenario I haven't considered. The strange thing that I have found in the past is call stack frames, but none of them marked as attributed. - FB12739927
Post not yet marked as solved
1 Replies
Make sure that you first create an index for the timestamp. Add the queryable index if you plan to use it in your predicate, such as 'created|modified after Tuesday'. Add the sortable index if you plan to use the property as a sort descriptor. Finally, if you're testing in production, make sure that your indices were pushed to production! This is never a fun thing to debug. Been there done that. I'm doing a manual synchronization where I 'fetch modified since last cursor'. Regarding the name of the properties, if you're fetching all properties, you can use the debugger to inspect the system field names.
Post not yet marked as solved
1 Replies
When you run your CloudKit app via Xcode, on simulator or device, the container being used is 'development'. When ever I detect a change of deployment type (i.e. #if DEBUG), I **** my local core data database and let it rebuild from CloudKit. While you can replicate the data in both development and production containers, it probably won't be 'auto-magic' like you're hoping. When you install the app via TestFlight, can you first delete your local app? I would assume this would get you past the synchronization error you've shared above. Another thing to check is to make sure your schema is deployed. NOTE: Schema can only add fields, so once you deploy to production, you're stuck with them.
Post not yet marked as solved
1 Replies
@brandonK212, The ActivityViewContext is the context object passed inside the ActivityConfiguration for building your view bodies. The preview for a live activity is very different from previewing a widget. You have to create your attributes set and then request a preview on that instead. Here is a minimally required code snip to get you started. Create custom Attributes Create a widget that uses an ActivityConfiguration of your custom attributes In your preview, instantiate an instance of your attributes and call .preview on it As a note, you need your widget defined as main, or use a widget bundle. I originally missed this and nothing happened. Presumably, under the hood it will lookup which ActivityConfiguration to invoke, and thus which 'View' to finally instantiate for the preview. https://developer.apple.com/documentation/widgetkit/activitypreviewviewkind https://developer.apple.com/documentation/activitykit/activityattributes/previewcontext(_:isstale:viewkind:) P.S. This is brand new with Xcode 14.2 and requires iOS 16.2 :) @available(iOSApplicationExtension 16.1, *) @main struct LocationWidget: Widget {     var body: some WidgetConfiguration {         ActivityConfiguration(for: LocationAttributes.self) { context in             Text("You're at \(context.attributes.name)")         } dynamicIsland: { context in             DynamicIsland {                 DynamicIslandExpandedRegion(.leading) {                     Image(systemName: "mappin.circle")                         .resizable()                         .scaledToFit()                         .frame(width: 32, height: 32)                 }                                  DynamicIslandExpandedRegion(.center) {                     VStack(alignment: .center) {                         Text("You're visiting \(context.attributes.name)")                         HStack {                             Text("\(context.state.location.latitude), \(context.state.location.longitude)")                         }                     }                 }                                  DynamicIslandExpandedRegion(.trailing) {                     HStack {                         Image(systemName: "hand.thumbsup.fill")                             .resizable()                             .scaledToFit()                             .frame(width: 32, height: 32)                                                  Image(systemName: "hand.thumbsdown")                             .resizable()                             .scaledToFit()                             .frame(width: 32, height: 32)                     }                 }                                  DynamicIslandExpandedRegion(.bottom) {                     Text("Enjoy your visit!")                 }             } compactLeading: {                 Text("Compact Leading")             } compactTrailing: {                 Text("Compact Trailing")             } minimal: {                 Text("Minimal")             }         }     } } struct LocationActivityView: View {     var body: some View {         Text("Hello Location")     } } struct LocationAttributes: ActivityAttributes {     struct ContentState: Codable, Hashable {         var location: Location     }          let name: String } struct Location: Codable, Hashable {     let latitude: Double     let longitude: Double } #if DEBUG @available(iOSApplicationExtension 16.2, *) struct LocationActivityView_Previews: PreviewProvider {          static var previews: some View {         Group {             LocationAttributes(name: "London Eye")                 .previewContext(                     LocationAttributes.ContentState(location: Location(latitude: 51.503351, longitude: -0.119623)),                     viewKind: .content                 )                          LocationAttributes(name: "London Eye")                 .previewContext(                     LocationAttributes.ContentState(location: Location(latitude: 51.503351, longitude: -0.119623)),                     viewKind: .dynamicIsland(.expanded)                 )         }     } } #endif I'm getting an error trying to attach the resulting preview screenshot but give it a run and check it out for yourself!
Post not yet marked as solved
1 Replies
@ricardo.sms, Likely what you're running into is the length of your domain. I have two domains that are identical except one prefixes with "the", "thecxxxxxxxxxxxxe.app" and "cxxxxxxxxxxxxe.app". The visual App Clip Code can only encode so much. I brought this up during WWDC 2021 lab with App Clip team; they know we want more space. What to do for now? #filefeedback for future OS releases and App Clip Code embedded data size. Okay fine, hope for more in the future, but what to do about iOS 14-16? Here is my implementation: Through experimentation, I found that I only have 6 characters to work with when I use my shorter domain (cxxxxxxxxxxxxe.app). The "the" in my domain really restricts me and I wish I could have a fancy short/OG top level domain, but domain squatters make them so expensive... So I'm stuck with cxxxxxxxxxxxxe.app/id/123456 for my clip urls.
Post not yet marked as solved
10 Replies
@Claude31, I'm also curious what you've encountered. I have yet to convert my watch apps over to SwiftUI but plan on doing so due to some WatchKit defects that surfaced the last two years that are quite annoying--though I just checked watchOS 9 beta 2 and they appear to be fixed. In any case, if you post your feedbacks here with a quick description and they apply to my apps too, I'd be happy to write matching ones up on my side and reference yours as duplicate to help upvote what you found. For other devs finding their way to this post, here are some defects that I've filed against watchOS 7 / 8: FB9972047 - WatchKit: awakeWithContext not invoked on page 2 and 3 in multipage layout until after swiping [watchOS 8] In short, three "page" layout in WatchKit, the second and third pages don't receive an init until the user swipes. Previously, in the init of the second interface controller, I was having it become the active page upon initialization. I can't do this anymore so programatic navigation is totally busted. FB8965949 - WKInterfacePicker text baseline clips with y and g [watchOS 7.2/8] In short, I added a picker that has "kayaking" and "canoeing" in my watch app. The letters are being clipped when using the WKInterfacePicker control, but when I rewrote in SwiftUI this was not the case.