Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISO8601DateFormatter.withMilliseconds: fixed iOS 11 crash #2037

Merged
merged 2 commits into from
Nov 8, 2022

Conversation

NachoSoto
Copy link
Contributor

@NachoSoto NachoSoto commented Nov 8, 2022

Fixes TRIAGE-172

See stacktrace:

Fatal Exception: NSInternalInconsistencyException
Invalid parameter not satisfying: formatOptions == 0 || !(formatOptions & ~(NSISO8601DateFormatWithYear | NSISO8601DateFormatWithMonth | NSISO8601DateFormatWithWeekOfYear | NSISO8601DateFormatWithDay | NSISO8601DateFormatWithTime | NSISO8601DateFormatWithTimeZone | NSISO8601DateFormatWithSpaceBetweenDateAndTime | NSISO8601DateFormatWithDashSeparatorInDate | NSISO8601DateFormatWithColonSeparatorInTime | NSISO8601DateFormatWithColonSeparatorInTimeZone | NSISO8601DateFormatWithFullDate | NSISO8601DateFormatWithFullTime | NSISO8601DateFormatWithInternetDateTime))
Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x141d04 __exceptionPreprocess
1 libobjc.A.dylib 0x8528 objc_exception_throw
2 CoreFoundation 0x141bd8 +[NSException raise:format:]
3 Foundation 0xacc24 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]
4 Foundation 0xe4794 -[NSISO8601DateFormatter setFormatOptions:]
5 RevenueCat 0x4795c one-time initialization function for withMilliseconds
6 libdispatch.dylib 0x1048 _dispatch_client_callout
7 libdispatch.dylib 0x4710 dispatch_once_f$VARIANT$mp
8 RevenueCat 0x47b0c date(from:) in Formatter #1 in closure #1 in variable initialization expression of static NSISO8601DateFormatter.default + 60 (DateFormatter+Extensions.swift:60)
9 RevenueCat 0x47b68 protocol witness for DateFormatterType.date(from:) in conformance Formatter #1 in closure #1 in variable initialization expression of static NSISO8601DateFormatter.default (<compiler-generated>)
10 RevenueCat 0xe6b8 AppleReceiptBuilder.build(fromContainer:) (AppleReceiptBuilder.swift)

This is the key part:
formatOptions == 0 || !(formatOptions & ~(NSISO8601DateFormatWithYear | NSISO8601DateFormatWithMonth | NSISO8601DateFormatWithWeekOfYear | NSISO8601DateFormatWithDay | NSISO8601DateFormatWithTime | NSISO8601DateFormatWithTimeZone | NSISO8601DateFormatWithSpaceBetweenDateAndTime | NSISO8601DateFormatWithDashSeparatorInDate | NSISO8601DateFormatWithColonSeparatorInTime | NSISO8601DateFormatWithColonSeparatorInTimeZone | NSISO8601DateFormatWithFullDate | NSISO8601DateFormatWithFullTime | NSISO8601DateFormatWithInternetDateTime))

This is coming from the following code:

static let withMilliseconds: DateFormatterType = {
    let formatter = ISO8601DateFormatter()
    formatter.formatOptions = [
        .withInternetDateTime,
        .withFractionalSeconds
    ]

    return formatter
}()

Even though .withFractionalSeconds is available in iOS 11, that assertion seems wrong, as it's treating that option as invalid. This was a regression in #998, almost a year ago, but since we have very little coverage on iOS 11 we never noticed until now.

Unfortunately it seems like we won't be able to run iOS 11 tests in CI (#2036), but this change is fairly safe, it just reverts to using the old DateFormatter for older versions.

@NachoSoto NachoSoto added the pr:fix A bug fix label Nov 8, 2022
@NachoSoto NachoSoto requested a review from a team November 8, 2022 00:07
@NachoSoto NachoSoto merged commit f54a30a into main Nov 8, 2022
@NachoSoto NachoSoto deleted the date-formatter-ios-11 branch November 8, 2022 17:27
NachoSoto pushed a commit that referenced this pull request Nov 9, 2022
**This is an automatic release.**

### Bugfixes
* `ISO8601DateFormatter.withMilliseconds`: fixed iOS 11 crash (#2037)
via NachoSoto (@NachoSoto)
* Changed `StoreKit2Setting.default` back to
`.enabledOnlyForOptimizations` (#2022) via NachoSoto (@NachoSoto)
### Other Changes
* `Integration Tests`: changed weekly to monthly subscriptions to work
around 0-second subscriptions (#2042) via NachoSoto (@NachoSoto)
* `Integration Tests`: fixed `testPurchaseWithAskToBuyPostsReceipt`
(#2040) via NachoSoto (@NachoSoto)
* `ReceiptRefreshPolicy.retryUntilProductIsFound`: default to returning
"invalid" receipt (#2024) via NachoSoto (@NachoSoto)
* `CachingProductsManager`: use partial cached products (#2014) via
NachoSoto (@NachoSoto)
* Added `BackendErrorCode.purchasedProductMissingInAppleReceipt` (#2033)
via NachoSoto (@NachoSoto)
* `PurchaseTesterSwiftUI`: replaced `Purchases` dependency with `SPM`
(#2027) via NachoSoto (@NachoSoto)
* `Integration Tests`: changed log output to `raw` (#2031) via NachoSoto
(@NachoSoto)
* `Integration Tests`: run on iOS 16 (#2035) via NachoSoto (@NachoSoto)
* CI: fixed `iOS 14` tests Xcode version (#2030) via NachoSoto
(@NachoSoto)
* `Async.call`: added non-throwing overload (#2006) via NachoSoto
(@NachoSoto)
* Documentation: Fixed references in `V4_API_Migration_guide.md` (#2018)
via NachoSoto (@NachoSoto)
* `eligiblePromotionalOffers`: don't log error if response is ineligible
(#2019) via NachoSoto (@NachoSoto)
* Runs push-pods after make-release (#2025) via Cesar de la Vega
(@vegaro)
* Some updates on notify-on-non-patch-release-branches: (#2026) via
Cesar de la Vega (@vegaro)
* Deploy `PurchaseTesterSwiftUI` to TestFlight (#2003) via NachoSoto
(@NachoSoto)
* `PurchaseTesterSwiftUI`: added "logs" screen (#2012) via NachoSoto
(@NachoSoto)
* `PurchaseTesterSwiftUI`: allow configuring API key at runtime (#1999)
via NachoSoto (@NachoSoto)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr:fix A bug fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants