Posts

Post not yet marked as solved
2 Replies
To quote the documentation If you don’t explicitly provide a deep link into your app with widgetURL(_:) or Link, the system launches your app and passes a NSUserActivity object to the scene(_:willContinueUserActivityWithType:) and scene(_:continue:) callbacks. Implement both callbacks and check whether the NSUserActivity object’s activityType is NSUserActivityTypeLiveActivity, and add code to open a screen in your app that fits the context of the active Live Activity. So if you omit widgetURL and Links you should be able to check for the incoming activity type to be NSUserActivityTypeLiveActivity. Maybe this type will also be set when using widgetURL and Links but I haven't tried that yet.
Post not yet marked as solved
1 Replies
This is for backwards capability. If you have an Apple watch paired with your iPhone and the content update arrives while your phone is locked the notification (with title, body and sound) will be proxied to your Apple Watch. At least this is what I observed during testing the feature
Post not yet marked as solved
4 Replies
Thanks to @sowenjub I got it working. He wrote a really nice blog post that sums up everything (https://sowenjub.me/writes/localizing-app-shortcuts-with-app-intents/) The gist is that you need 2 localization files: an AppShortcuts.strings for the phrases and Localizable.strings for the rest (it is possible to have something other than that specific name but you have to provide the table name in every place you reference the Strings which is quite annoying) Then everything in code like the phrase "Key: Add a meal (.$content) to (.applicationName)" (implicitly looked up in AppShortcuts.strings) gets referenced via the following in your AppShortcuts.strings (i.e. english): "Key: Add a meal {content} to {applicationName}" = "Add a meal {content} to {applicationName}"; And stuff like app entitiy typeDisplayNames: static var typeDisplayName: LocalizedStringResource = "some.entitiy.type.name" (implicitly looked up in Localizable.strings; if you have an Alternative.strings file use something like .init("some.entitiy.type.name", table: "Alternative", locale: .autoupdatingCurrent, bundle: .main, comment: nil)) gets referenced via the following in your Localizable.strings (i.e. english): "some.entitiy.type.name" = "Some";
Post marked as solved
7 Replies
I also have not figured out a way to migrate all the corner complications (basically 95% look like this) and filed feedback (FB11192958). Another issue is that the gauge inside the widgetLabel ignores the gradient so it's impossible to get even close to the design shown by all the weather widgets.
Post not yet marked as solved
5 Replies
What do you mean by separate target? Your app intents have to be compiled from within the app target to work
Post not yet marked as solved
4 Replies
I couldn't get localization to work at all in the new AppIntents framework (I filed several radars). Almost nothing with parameters works and even some unparameterized phrases just show the localization key. I thought we could still use %@ like in normal localizations and it does work for the dialog in the perform function. i.e. return .result(dialog: "play.news.intent.success \(station.name)") gives me the correct result for the "play.news.intent.success %@" localization key
Post marked as solved
3 Replies
We have actually contacted Developer Technical Support for this and while the response wasn't exactly what we needed it pointed us in the right direction to come up with something that works for us. Note that there are still scaling issues when ALL items within a section have no detail text (but that's another issue). Here is what we use: extension CPListItem { convenience init(text: String?, detailText: String?, remoteImageUrl: URL?, placeholder: UIImage?, accessoryImage: UIImage? = nil, accessoryType: CPListItemAccessoryType = .none, imageOperation: RemoteImageOperation? = nil) { self.init(text: text, detailText: detailText, image: placeholder, accessoryImage: accessoryImage, accessoryType: accessoryType) setImageUrl(remoteImageUrl) } func setImageUrl(_ url: URL?) { guard let imageUrl = url else { return } Current.downloadImage(imageUrl) { image in guard let cropped = image?.cpCropSquareImage, let resized = cropped.resized(to: CPListItem.maximumImageSize), let carPlayImage = resized.carPlayImage else { return } DispatchQueue.main.async { [weak self] in self?.setImage(carPlayImage) } } } } extension UIImage { var carPlayImage: UIImage? { guard let traits = Current.interfaceController?.carTraitCollection else { return nil } let imageAsset = UIImageAsset() imageAsset.register(self, with: traits) return imageAsset.image(with: traits) } var cpCropSquareImage: UIImage { /* basic image cropping ... */ } func resized(to newSize: CGSize) -> UIImage? { /* basic image resizing ... */ } } The basic idea is to put the image in a UIImageAsset and take it out again which magically makes things work. Other than that we also crop it to a square and resize it to the maximum allowed image size. Our Current is like a dependency container where download is just a function to access our image cache/downloader and the interfaceController is the one we get when connecting the CarPlay scene (this is important for the native scale of the CarPlay display instead of the connected iOS device's display scale).
Post not yet marked as solved
1 Replies
You can already access the development guidelines here: https://developer.apple.com/carplay/documentation/CarPlay-App-Programming-Guide.pdf After you have been accepted you get an email with that link and tell you to watch the WWDC20 video “Accelerate Your App with CarPlay”. They don't provide any sample code. This was for a CarPlay Audio entitlement so it may be possible that you get sample code if you're building an Automaker App.
Post not yet marked as solved
5 Replies
I have taken a look at CarPlaySupport.framework with Hopper to check when this exception is thrown (calls to clientPushedIllegalTemplateOfClass). It is called from _templateIsValidForCurrentEntitlement which check whether the template is valid at all for the current entitlement (it is) and then there is this aforementioned check if the top view controller is a CPSNowPlayingViewController the template to be pushed has to be a CPListTemplate. Can you check again, that there are no calls to pushTemplate containing anything but list templates?
Post not yet marked as solved
5 Replies
Hm, the crash mentions the grid template being pushed but maybe it is because you try to set the template as the root template (instead of embedding it in a tab template)? Tab and list templates might be the only allowed root templates. Another problem might be that you exceed the number of allowed templates in the navigation stack (afaik 5 for audio apps), so it just happens to be a grid template that's pushed on a "full" stack.
Post not yet marked as solved
12 Replies
Using custom entitlements works by specifying separate entitlements files for the CODESIGNENTITLEMENTS key. I use xcconfig files for this: CODE_SIGN_ENTITLEMENTS = $(SRCROOT)/Config/MyApp.entitlements CODE_SIGN_ENTITLEMENTS = $(SRCROOT)/Config/MyApp_Mac.entitlements Of course, you can also do this in the build settings directly by specifying a platform conditional (Any macOS SDK)