SwiftTweaks icon indicating copy to clipboard operation
SwiftTweaks copied to clipboard

[CRASH] SwiftTweaks crashes when integrated via Cocoapods with the new Resource bundles change

Open JoeSzymanski opened this issue 3 years ago • 2 comments

  • [x] I have read through CONTRIBUTING.md

Describe the bug When integrating via Cocoapods (using the new resource bundles), SwiftTweaks crashes when navigating to a sub-menu.

To Reproduce Steps to reproduce the behavior:

  1. Integrate SwiftTweaks through Cocoapods
  2. Run the app and open the SwiftTweaks menu
  3. Navigate to a submenu
  4. Notice the crash

Expected behavior The submenu is displayed.

Additional context The code that's causing the issue in question is the following:

	// NOTE (bryan): if we just used UIImage(named:_), we get crashes when running in other apps!
	// (Why? Because by default, iOS searches in your app's bundle, but we need to redirect that to the bundle associated with SwiftTweaks
	private convenience init?(inThisBundleNamed imageName: String) {
		#if SWIFT_PACKAGE
		self.init(named: imageName, in: Bundle.module, compatibleWith: nil)
		#else
		self.init(named: imageName, in: Bundle(for: TweakTableCell.self), compatibleWith: nil) // NOTE (bryan): Could've used any class in SwiftTweaks here.
		#endif
	}

Note that because the resource bundle now is a named bundle and not directly part of the SwiftTweaks framework itself, Bundle(for: TweakTableCell.self) will no longer work. This should be updated to reference the new resource bundle directly, though this might also impact other integrations.

JoeSzymanski avatar Oct 28 '22 17:10 JoeSzymanski

Nice catch, thanks!

bryanjclark avatar Oct 28 '22 21:10 bryanjclark

For reference, we use a solution like the code below to handle this case in a way that supports both static and dynamic integration through Cocoapods:

        let bundleName = "SwiftTweaks"
        if let bundleURL = Bundle(for: TweakTableCell.self).url(forResource: bundleName, withExtension: "bundle"), let bundle = Bundle(url: bundleURL) {
            return bundle
        } else if let bundleURL = Bundle.main.url(forResource: bundleName, withExtension: "bundle"), let bundle = Bundle(url: bundleURL) {
            return bundle
        } else {
            return nil
        }

I'm not sure how this would interact with other forms of integration such as SPM or Carthage, though.

JoeSzymanski avatar Nov 09 '22 17:11 JoeSzymanski