How are we supposed to keep our widgets also compatible with iOS 14-16 with this new containerBackground requirement? How can we conditionally apply a modifier based on iOS version?
Post
Replies
Boosts
Views
Activity
This other post: https://developer.apple.com/forums/thread/696280 mentions that if the Watch app is a standalone app and the companion iPhone app is removed then the Watch notifications are delivered on time. I can confirm this is true!
I still get three calls to the willPresentNotification delegate method for a single notification when the app is running in the foreground, but they all occur within 0.3 seconds of each other and at the correct time. When the app is running in the background, the notification appears at the correct time.
I changed my Watch app to NOT be independent (the iPhone app must be installed) and got delayed notifications again.
So, notifications scheduled on the Watch app will be delayed about 14 seconds if the companion iPhone app is installed.
This is still happening on watchOS 9.1. There's an old stackoverflow post which reported the issue in watchOS 6.0.1 in October 2019. It has a reply in November 2019 claiming it was fixed in watchOS 6.1: https://stackoverflow.com/questions/58283416/why-are-apple-watchs-local-notifications-delayed
I've been seeing this issue for years and it's incredibly frustrating. What use is a timer app with notifications if the notifications don't appear at the correct time! Notifications created on the phone but delivered to the Watch (because the phone's display is off) appear exactly when they should. But notifications scheduled on the Watch are consistently delivered about 14 seconds too late.
I am implementing userNotificationCenter:willPresentNotification: to cause the notification to be delivered even when my app is in the foreground and I see that method being called at exactly the right time, but no notification appears. It is then called 14 seconds later with a different UNNotification object, which has different UNNotificationRequest and UNNotificationContent objects, but with the same underlying notification identifier. It is then called immediately a third time. I'm unsure whether it is the second or third call which actually shows the notification.
If my Watch app is not running in the foreground then the willPresentNotification delegate method is not called (which is correct - this is only called when in the foreground). The notification is still not shown until 14 seconds later than it was scheduled.
EDIT: I think maybe I wasn't seeing files get rebuilt properly because I managed to get it working!
The 'U' references are not necessarily going to cause link issues. Using "nm -m" I can see that the single remaining 'U' when I do include Joe's workaround is for a "weak external" symbol which, presumably, will not cause a link failure:
(undefined) weak external _$s9WidgetKit22IntentTimelineProviderP15recommendationsSayAA0C14RecommendationVy0C0QzGGyFTq (from WidgetKit)
When I don't include the workaround the other 'U' reference is not weak:
(undefined) external _$s9WidgetKit22IntentTimelineProviderPAAE15recommendationsSayAA0C14RecommendationVy0C0QzGGyF (from WidgetKit)
ORIGINAL COMMENT BELOW:
Joe's solution isn't working for me. I did some investigation to try and work out where the undefined symbol is coming from. If I don't use his workaround, when I use the 'nm' command to look for symbols containing the word "recommendations" in the built widget .appex file I see this:
Villanelle:AdaptivityWidget14Extension.appex geoff$ nm AdaptivityWidget14Extension | grep recommendations
000000010003ff94 t _$s27AdaptivityWidget14Extension22LayoutTimelineProviderV9WidgetKit06IntenteF0AadEP15recommendationsSayAD0I14RecommendationVy0I0QzGGyFTW
00000001000173f4 t _$s27AdaptivityWidget14Extension27DynamicTypeTimelineProviderV9WidgetKit06IntentfG0AadEP15recommendationsSayAD0J14RecommendationVy0J0QzGGyFTW
00000001000292fc t _$s27AdaptivityWidget14Extension27SystemImageTimelineProviderV9WidgetKit06IntentfG0AadEP15recommendationsSayAD0J14RecommendationVy0J0QzGGyFTW
0000000100033b68 t _$s27AdaptivityWidget14Extension28SystemImagesTimelineProviderV9WidgetKit06IntentfG0AadEP15recommendationsSayAD0J14RecommendationVy0J0QzGGyFTW
000000010002c498 t _$s27AdaptivityWidget14Extension32LockScreenLayoutTimelineProviderV9WidgetKit06IntentgH0AadEP15recommendationsSayAD0K14RecommendationVy0K0QzGGyFTW
0000000100077674 t _$s27AdaptivityWidget14Extension37LockScreenSystemImageTimelineProviderV9WidgetKit06IntenthI0AadEP15recommendationsSayAD0L14RecommendationVy0L0QzGGyFTW
U _$s9WidgetKit22IntentTimelineProviderP15recommendationsSayAA0C14RecommendationVy0C0QzGGyFTq
U _$s9WidgetKit22IntentTimelineProviderPAAE15recommendationsSayAA0C14RecommendationVy0C0QzGGyF
I have six different widgets, each of which is responsible for one of the 't' entries. This indicates those symbols are defined in my .appex. The problem is coming from the 'U' undefined symbols. These need to be resolved at dynamic link time.
According to www . swiftdemangler . com, these two undefined symbols demangle to these names:
_$s9WidgetKit22IntentTimelineProviderP15recommendationsSayAA0C14RecommendationVy0C0QzGGyFTq
method descriptor for WidgetKit.IntentTimelineProvider.recommendations() -> Swift.Array>
_$s9WidgetKit22IntentTimelineProviderPAAE15recommendationsSayAA0C14RecommendationVy0C0QzGGyF
(extension in WidgetKit):WidgetKit.IntentTimelineProvider.recommendations() -> Swift.Array>
The lowercase 't' for my own symbols means they are (according to the man page for nm) "text section symbols" that are "local (non-external)" (that's what lowercase means).
_$s27AdaptivityWidget14Extension22LayoutTimelineProviderV9WidgetKit06IntenteF0AadEP15recommendationsSayAD0I14RecommendationVy0I0QzGGyFTW
protocol witness for WidgetKit.IntentTimelineProvider.recommendations() -> Swift.Array> in conformance AdaptivityWidget14Extension.LayoutTimelineProvider : WidgetKit.IntentTimelineProvider in AdaptivityWidget14Extensio
When I do define the recommendations method in each of my intent timeline providers I get an extra 'T' entry for each of my widgets and one of the undefined symbols disappears:
/Users/geoff/Library/Developer/Xcode/DerivedData/Adaptivity-cckxaccqtttwkcadthuihwqqbxkv/Build/Products/Debug-iphoneos/AdaptivityWidget14Extension.appex
Villanelle:AdaptivityWidget14Extension.appex geoff$ nm AdaptivityWidget14Extension | grep recommendations
000000010003fed8 T _$s27AdaptivityWidget14Extension22LayoutTimelineProviderV15recommendationsSay9WidgetKit20IntentRecommendationVyAA022ADTLayoutConfigurationJ0CGGyF
000000010003ff18 t _$s27AdaptivityWidget14Extension22LayoutTimelineProviderV9WidgetKit06IntenteF0AadEP15recommendationsSayAD0I14RecommendationVy0I0QzGGyFTW
0000000100017298 T _$s27AdaptivityWidget14Extension27DynamicTypeTimelineProviderV15recommendationsSay9WidgetKit20IntentRecommendationVyAA010ADTDynamice13ConfigurationK0CGGyF
00000001000172d8 t _$s27AdaptivityWidget14Extension27DynamicTypeTimelineProviderV9WidgetKit06IntentfG0AadEP15recommendationsSayAD0J14RecommendationVy0J0QzGGyFTW
00000001000291c8 T _$s27AdaptivityWidget14Extension27SystemImageTimelineProviderV15recommendationsSay9WidgetKit20IntentRecommendationVyAA09ADTSysteme13ConfigurationK0CGGyF
0000000100029208 t _$s27AdaptivityWidget14Extension27SystemImageTimelineProviderV9WidgetKit06IntentfG0AadEP15recommendationsSayAD0J14RecommendationVy0J0QzGGyFTW
0000000100033a98 T _$s27AdaptivityWidget14Extension28SystemImagesTimelineProviderV15recommendationsSay9WidgetKit20IntentRecommendationVyAA09ADTSysteme13ConfigurationK0CGGyF
0000000100033ac4 t _$s27AdaptivityWidget14Extension28SystemImagesTimelineProviderV9WidgetKit06IntentfG0AadEP15recommendationsSayAD0J14RecommendationVy0J0QzGGyFTW
000000010002c38c T _$s27AdaptivityWidget14Extension32LockScreenLayoutTimelineProviderV15recommendationsSay9WidgetKit20IntentRecommendationVyAA07ADTLockef13ConfigurationL0CGGyF
000000010002c3cc t _$s27AdaptivityWidget14Extension32LockScreenLayoutTimelineProviderV9WidgetKit06IntentgH0AadEP15recommendationsSayAD0K14RecommendationVy0K0QzGGyFTW
00000001000775e0 T _$s27AdaptivityWidget14Extension37LockScreenSystemImageTimelineProviderV15recommendationsSay9WidgetKit20IntentRecommendationVyAA07ADTLockefg13ConfigurationM0CGGyF
0000000100077620 t _$s27AdaptivityWidget14Extension37LockScreenSystemImageTimelineProviderV9WidgetKit06IntenthI0AadEP15recommendationsSayAD0L14RecommendationVy0L0QzGGyFTW
U _$s9WidgetKit22IntentTimelineProviderP15recommendationsSayAA0C14RecommendationVy0C0QzGGyFTq
I don't know enough about linking to know why I still get this outstanding undefined symbol when Joe, presumably, does not.
In my own testing (hoping this Twitter link will work: https://twitter.com/geoffhackworth/status/1537786888626524162 ), I've found that the width only works for the default design. Attempting to vary the width of rounded has no effect, and attempting to vary the width of serif and monospace causes some font weights to actually return what looks like regular weight with the default design.
I've been able to experiment with this a bit. You have to set a 'width' attribute trait on the font descriptor. Apologies for the Objective-C, but hopefully this will give you enough to figure it out!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ADTSystemFontTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[ADTSystemFontTableViewCell reuseIdentifier] forIndexPath:indexPath];
UIFontDescriptor *fontDescriptor = [self fontDescriptorAtIndexPath:indexPath];
NSDictionary *widthSetting = @{UIFontWidthTrait : @(-1.0)};
fontDescriptor = [fontDescriptor fontDescriptorByAddingAttributes:@{UIFontDescriptorTraitsAttribute: widthSetting}];
cell.fontDescriptor = fontDescriptor;
cell.title = [self titleForRowAtIndexPath:indexPath];
cell.showFontName = [ADTAppSettingsManager sharedInstance].showSystemFontsInfo.value;
return cell;
}
However, in my testing it seems that only the regular SF font design, and not rounded, serif and monospaced, work. I'm not entirely sure whether the width is just another way to vary the base default SF design, or whether it is intended to be a separate dimension like point size and weight that should work across all designs.
Xcode 14 update to this issue. It seems that Xcode 14 no longer adds the com.apple.developer.user-fonts entitlement when building for Mac Catalyst. That meant my earlier workaround stopped working because I was asking plutil to remove an entry that wasn't there. This caused plutil to (correctly) return a non-zero exit code. Which breaks my build.
The fix is simple: check that the entitlement is there before trying to remove it:
if [ "${IS_MACCATALYST}" = "YES" ]; then
ENTITLEMENTS_FILE="${TARGET_TEMP_DIR}/${FULL_PRODUCT_NAME}.xcent"
# Xcode 14 doesn't seem to add this entitlement for Catalyst builds and plutil returns a non-zero exit code if I try to remove it
if grep -q "com\.apple\.developer\.user-fonts" "${ENTITLEMENTS_FILE}"; then
echo "Removing com.apple.developer.user-fonts entitlement on Mac Catalyst from ${ENTITLEMENTS_FILE}"
plutil -remove "com\.apple\.developer\.user-fonts" "${ENTITLEMENTS_FILE}"
else
echo "No need to remove com.apple.developer.user-fonts entitlement on Mac Catalyst from ${ENTITLEMENTS_FILE}"
fi
fi
I also see this issue with both collection views and table views. I'm using Objective-C on Xcode 13.2 release candidate with iOS 15.2 (19C51).
In order to get a leak I have to:
return a non-empty array from the table/collection view delegate that asks for itemsForBeginningDragSession:
return a UIContextMenuConfiguration from the table/collection view delegate that asks for the contextMenuConfigurationForRow/ItemAtIndexPath
long press on the cell and NOT drag
dismiss my view controller that has the table/collection view
I then see that the collection/table view is leaked (and, in turn, its cached table view cells and the diffable data source object)
I have found that I do NOT get a leak if I do any one of these things:
return an empty array from the table/collection view delegate that asks for itemsForBeginningDragSession:
return nil from the table/collection view delegate that asks for the contextMenuConfigurationForRow/ItemAtIndexPath
after the long press, begin dragging
It does not matter whether the drag is dropped or cancelled, just starting to drag will prevent the leak.
Returning a non-nil UIContextMenuConfiguration which has blocks for its previewProvider and actionProvider that return nil (which is visually the same as returning a nil configuration - no context menu is shown on a long press) will still leak.
Same issue for me. What’s really frustrating is “Apps with compatibility references to a pre-GM version of an Apple operating system SDK” suggests that it is totally acceptable to refer to a GM version. iOS 15 is in GM (or RC as they’ve called it for a long time).
This still seems to be broken in iOS 14.2.1. It might be an issue extensions in general as a request to reload the timeline from a Notification Content Extension doesn't seem to work either.
Oh my. This seems to have been fixed in watchOS 7!
If you implement the getLocalizableSampleTemplate(for:withHandler:) method in your CLKComplicationDataSourceimplementation, these sample templates will sync from the watch to the paired phone automatically and be the same across both devices. This is preferred to generating complication bundles to include in your project. Are you saying we should no longer be including a complication gallery in our Xcode project? It would be nice if the documentation didn't still tell us to do it the old way: https://developer.apple.com/documentation/clockkit/creating_complications_for_your_watchos_app/adding_placeholders_for_your_complication
It seems that Xcode 12 GM completely breaks builds of Mac Catalyst apps which have iOS 14 features. Code that would build fine in Xcode 12 beta 6 no longer builds. It's as if the GM thinks Mac Catalyst is only capable of iOS 13 features.
You can prevent the widget from being included in the Catalyst build (which probably isn't what you want): https://stackoverflow.com/questions/59795971/extension-is-not-available-when-building-for-mac-catalyst
That will get you past that particular error. But you will probably then find code that won't compile for Catalyst. Xcode complains that iOS 14 symbols just don't exist: https://developer.apple.com/forums/thread/660274?page=1#632760022
It seems that Xcode 12 GM can't build Mac Catalyst apps which use classes/properties etc. that were added in iOS 14. I get a similar error in one of my apps when I try and build the Catalyst version:
unknown type name 'UISplitViewControllerSplitBehavior' Xcode 12 beta 6 will build fine but, of course, can't be used to submit for review.
I can build a different app for Catalyst on Xcode 12 GM, presumably because that code doesn't use iOS 14 features.