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

Assertion failure in iOS 15 #89

Closed
jminutaglio opened this issue Sep 15, 2021 · 14 comments
Closed

Assertion failure in iOS 15 #89

jminutaglio opened this issue Sep 15, 2021 · 14 comments
Labels

Comments

@jminutaglio
Copy link

jminutaglio commented Sep 15, 2021

Using:

let viewController = AcknowListViewController()
navigationController?.pushViewController(viewController, animated: true)

On Xcode 13 RC (Version 13.0 (13A233)) ->

On Simulator iOS 14.5 -> expected behavior (AcknowList viewController shows)

On Simulator iOS 15.0:

2021-09-15 00:12:36.534344-0400 <project>16143:173446] *** Assertion failure in UITraitCollection *UIViewControllerMissingInitialTraitCollection(UIViewController *__strong)(), UIViewController.m:2434
2021-09-15 00:12:36.559665-0400 <project>[16143:173446] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UIViewController is missing its initial trait collection populated during initialization. This is a serious bug, likely caused by accessing properties or methods on the view controller before calling a UIViewController initializer. View controller: <UITableViewController: 0x7fe893379490>'
*** First throw call stack:
(
	0   CoreFoundation                      0x000000011fbdebb4 __exceptionPreprocess + 242
	1   libobjc.A.dylib                     0x0000000119b76be7 objc_exception_throw + 48
	2   Foundation                          0x0000000114a59da9 -[NSMutableDictionary(NSMutableDictionary) classForCoder] + 0
	3   UIKitCore                           0x00000001347fb6c6 UIViewControllerMissingInitialTraitCollection + 188
	4   UIKitCore                           0x00000001347ffbef -[UIViewController traitCollection] + 155
	5   UIKitCore                           0x00000001347ee93a -[UITableViewController dealloc] + 196
	6   AcknowList                          0x000000010f532a7e $s10AcknowList0aB14ViewControllerC9plistPath5styleACSS_So07UITableC5StyleVtcfc + 206
	7   AcknowList                          0x000000010f532b0b $s10AcknowList0aB14ViewControllerC9plistPath5styleACSS_So07UITableC5StyleVtcfcTo + 59
	8   AcknowList                          0x000000010f532615 $s10AcknowList0aB14ViewControllerCACycfc + 325
	9   AcknowList                          0x000000010f5326bf $s10AcknowList0aB14ViewControllerCACycfcTo + 15
	10  AcknowList                          0x000000010f5324cb $s10AcknowList0aB14ViewControllerCACycfC + 27
	11  <project>                          0x000000010911ad79 $s9<project>19ViewControllerLegalC13ackListActionyyypF + 153
	12  <project>                           0x000000010911ceb1 $s9<project>19ViewControllerLegalC13ackListActionyyypFTo + 65
	13  UIKitCore                           0x0000000134fc2189 -[UIApplication sendAction:to:from:forEvent:] + 83
	14  UIKitCore                           0x000000013485b573 -[UIControl sendAction:to:forEvent:] + 110
	15  UIKitCore                           0x000000013485b955 -[UIControl _sendActionsForEvents:withEvent:] + 332
	16  UIKitCore                           0x0000000134857e8c -[UIButton _sendActionsForEvents:withEvent:] + 148
	17  UIKitCore                           0x000000013485a206 -[UIControl touchesEnded:withEvent:] + 488
	18  UIKitCore                           0x000000013500295d -[UIWindow _sendTouchesForEvent:] + 1287
	19  UIKitCore                           0x00000001350049df -[UIWindow sendEvent:] + 5295
	20  UIKitCore                           0x0000000134fdb4e8 -[UIApplication sendEvent:] + 825
	21  UIKitCore                           0x000000013507128a __dispatchPreprocessedEventFromEventQueue + 8695
	22  UIKitCore                           0x0000000135073a10 __processEventQueue + 8579
	23  UIKitCore                           0x000000013506a1b6 __eventFetcherSourceCallback + 240
	24  CoreFoundation                      0x000000011fb4ce25 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
	25  CoreFoundation                      0x000000011fb4cd1d __CFRunLoopDoSource0 + 180
	26  CoreFoundation                      0x000000011fb4c1f2 __CFRunLoopDoSources0 + 242
	27  CoreFoundation                      0x000000011fb46951 __CFRunLoopRun + 875
	28  CoreFoundation                      0x000000011fb46103 CFRunLoopRunSpecific + 567
	29  GraphicsServices                    0x000000012131fcd3 GSEventRunModal + 139
	30  UIKitCore                           0x0000000134fbbe63 -[UIApplication _run] + 928
	31  UIKitCore                           0x0000000134fc0a53 UIApplicationMain + 101
	32  <project>                           0x000000010908a14f main + 63
	33  dyld                                0x000000010ea60e1e start_sim + 10
	34  ???                                 0x0000000000000001 0x0 + 1
	35  ???                                 0x0000000000000002 0x0 + 2

Same codeline, just an error on iOS 15...

Any ideas? ty in advance. AcknowList is awesome btw!

@psalzAppDev
Copy link

It is probably a bug that will be fixed in later Xcode versions - some problems with the initializers not visible to objc. However, for now, I got it resolved using this: https://stackoverflow.com/questions/69092599/xcode-13-beta-5-error-uiviewcontroller-is-missing-its-initial-trait-collection

I will try to put this into a PR

@psalzAppDev
Copy link

psalzAppDev commented Sep 15, 2021

Ok, so I tried my solution, but it turned out that your last convenience initializer that finally calls super.init(style:) uses an array of Acknow, which is a struct. Therefore, this initializer cannot be exposed to @objc.

The solution would be to expose all convenience initializers to @objc and then overriding init(style:), like this:

/**
Bugfix for [Issue #89](https://github.com/vtourraine/AcknowList/issues/89).
     
On iOS 15 using Xcode 13 RC, the initializer will crash unless this one is overridden.
     
Solution taken from [StackOverflow](https://stackoverflow.com/questions/69092599/xcode-13-beta-5-error-uiviewcontroller-is-missing-its-initial-trait-collection)
*/
public override init(style: UITableView.Style) {
        
   self.acknowledgements = []
        
   super.init(style: style)
}

And then calling self.init(style: style) in the convenience initializer instead of super.init(style: style):

@objc public convenience init(acknowledgements: [Acknow], style: UITableView.Style = .grouped) {
        
   self.init(style: style)

   self.acknowledgements = acknowledgements

   self.title = AcknowLocalization.localizedTitle()
}

It seems to be your only solution for now is to remove the above convenience initializer, which means acknowledgements have to be set after initialization. Or hope that Apple fixes this annoying bug anytime soon.

Something really hacky might work too:
Duplicate Acknow as a class inheriting from NSObject, thus exposing it to @objc. Then replace the struct Acknow array in the initializer with the class Acknow array and create a struct Acknow array by copying the values.

Something like this:

@objc public class AcknowC: NSObject {
   // Duplicate everything as in struct Acknow
}

...

@objc public convenience init(acknowledgements: [AcknowC], style: UITableView.Style = .grouped) {
        
   self.init(style: style)

   self.acknowledgements = acknowledgements.map {
      Acknow(title: $0.title, string: $0.string, license: $0.license)
   }

   self.title = AcknowLocalization.localizedTitle()
}

psalzAppDev added a commit to psalzAppDev/AcknowList that referenced this issue Sep 15, 2021
On iOS 15 using Xcode 13 RC, the initializer will crash unless the init(style:) initializer is overridden.

Solution taken from https://stackoverflow.com/questions/69092599/xcode-13-beta-5-error-uiviewcontroller-is-missing-its-initial-trait-collection
psalzAppDev added a commit to psalzAppDev/AcknowList that referenced this issue Sep 15, 2021
On iOS 15 using Xcode 13 RC, the initializer will crash unless the init(style:) initializer is overridden.

Solution taken from https://stackoverflow.com/questions/69092599/xcode-13-beta-5-error-uiviewcontroller-is-missing-its-initial-trait-collection

As I describe in the issue, the struct Acknow cannot be exposed to @objc. Therefore, a class AcknowClass was specified that is used in the initializer and then transformed into the Acknow struct. This is really hacky and breaks all projects using the init(acknowledgements:style:) initializer directly, but it solves the crash in iOS 15 when using Xcode 13 RC.
@psalzAppDev
Copy link

So this actually works. I'll create a PR for you to test and then you can decide whether you want this hacky and breaking change or wait until Apple fixes this bug (hopefully...)

@jminutaglio
Copy link
Author

@psalzAppDev - used your code/fork and confirmed it works here also. TY so much! iOS 15 is coming bugs or not! :)

@vtourraine
Copy link
Owner

Thank you so much for reporting this issue, and for preparing the pull request!

I’m not sure we should merge it as-is, though. Is it really just a bug, or just how the latest Swift compiler works? I would love to better understand the issue before touching the initializers interface. Any indication about what is going on exactly?

But in the meantime, I’m glad we have your workaround for folks who would need it.

@vtourraine vtourraine added the bug label Sep 16, 2021
@psalzAppDev
Copy link

Thank you so much for reporting this issue, and for preparing the pull request!

I’m not sure we should merge it as-is, though. Is it really just a bug, or just how the latest Swift compiler works? I would love to better understand the issue before touching the initializers interface. Any indication about what is going on exactly?

But in the meantime, I’m glad we have your workaround for folks who would need it.

I agree, this is a messy fix and I hope that this is an internal bug that will soon be fixed. There is not much information around about it though. I can't believe that this behavior is intended.

On the downside, anyone who uses your framework will notice that the app crashes on iOS 15. So hopefully they find their way to this thread and can decide whether to use my PR for now to keep their app working. That's what I did when I noticed that my app crashed on my iOS15 test device.

When new Xcode versions arrive, I will test for this bug and report back to you.

@jminutaglio
Copy link
Author

I’m not sure we should merge it as-is, though. Is it really just a bug, or just how the latest Swift compiler works? I would love to better understand the issue before touching the initializers interface. Any indication about what is going on exactly?

My $0.02 - this will be the shipping iOS 15 and the impact is that AcknowList will fail on open every time - so the impact to AcknowList is as major as it gets, starting next week when iOS 15 drops. I'd implement the workaround unless & until Apple's build allows the current initializer code to function without failure. Considering the length of the iOS 15 beta I'd suggest it won't be anytime soon... :/

@vtourraine
Copy link
Owner

@jminutaglio Agreed, we should address that as soon as possible.

I have found a different solution, though. The problem somehow comes from the interoperability between Swift and Objective-C code. If we remove the @objc annotations from the initializers, there’s no more crash. I would also mean that the library would no longer be usable from Objective-C code. That’s bad, but I think I would rather do that, instead of adding all the extra code to dance around the issue.

What do you think?

@jminutaglio
Copy link
Author

@vtourraine - makes sense to me. I'd guess most projects have moved from Obj-C to Swift at this point, so the impact to folks using AcknowList may be minor/none...

@jminutaglio
Copy link
Author

@vtourraine - AcknowList 2.0.2 is still throwing the assertion failure on iOS 15 - FYI.

:(

@vtourraine
Copy link
Owner

Hum, it gets weirder indeed. The crash is fixed for the “AcknowExampleManual” project, but not for the “AcknowExampleCocoaPods”. 😞 Looking into it...

@vtourraine
Copy link
Owner

Alright, I reimplemented the AcknowListViewController default initializer, and it seems to really fix this issue. I’ve released it as version 2.0.3. Please check it out, and let me know if that works for you.

@jminutaglio
Copy link
Author

@vtourraine - looks good here. Confirmed fixed!

TY!

@vtourraine
Copy link
Owner

@jminutaglio Glad to hear it, thanks for the feedback 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants