While I have a different setup the general problem remains them same. I use SwiftGen to generate symbols for my colors (and images, and Strings) and I get a crash when trying to access the color in a test (because it cannot be found in the bundle. Did you solve this issue somehow?
Post
Replies
Boosts
Views
Activity
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.
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
Hi Bastian. I'm sorry but that is special treatment for Apple's Live Activities. You can't have any interaction with the live activity that won't route you to your application. It's also currently not possible to show a marquee label if text is too long for your activity.
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";
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.
What do you mean by separate target? Your app intents have to be compiled from within the app target to work
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
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).
I just checked with my CarPlay Audio apps and the entitlements show up in the downloaded Distribution Profile.
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?
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.
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.
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)