Cocoapods: resource_bundles not working with assets catalog (cocoapods 1.0.1)

Created on 8 Jun 2016  路  19Comments  路  Source: CocoaPods/CocoaPods

After upgrade to 1.0.x the UIImage(named:inBundle:compatibleWithTraitCollection) no longer worked with images in assets catalog.

What did you do?

  • upgrade to cocoapod 1.0.1
  • run test project
  • failed to load the image file from assets catalog that used to work

Note, we have no problem loading a plain image file (outside of the .xcassets) from the bundle, just not able to access the same file when it's in .xcassets. And I do see the Assets.car file in the bundle directory, along with the plaint image file.

What did you expected to happen?

the image should be able to load from assets catalog.

What happened instead?

UIImage(named:inBundle:compatibleWithTraitCollection) returns nil. The code should be correct as it can load plain image file from the same bundle.

CocoaPods Environment

Stack

   CocoaPods : 1.0.1
        Ruby : ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]
    RubyGems : 2.2.2
        Host : Mac OS X 10.11.5 (15F34)
       Xcode : 7.3.1 (7D1014)
         Git : git version 2.1.1
Ruby lib dir : /usr/local/Cellar/ruby/2.1.5/lib
Repositories : master - https://github.com/CocoaPods/Specs.git @ 4de31805e74f3ed92f1777b261fa474f1b18806b

Installation Source

Executable Path: /usr/local/bin/pod

Plugins

cocoapods-deintegrate : 1.0.0
cocoapods-playgrounds : 1.2.0
cocoapods-plugins     : 1.0.0
cocoapods-search      : 1.0.0
cocoapods-stats       : 1.0.0
cocoapods-trunk       : 1.0.0
cocoapods-try         : 1.0.0

Podfile

use_frameworks!

target 'ResourceTest_Example' do
  pod 'ResourceTest', :path => '../'

  target 'ResourceTest_Tests' do
    inherit! :search_paths

    pod 'Quick', '~> 0.8'
  pod 'Nimble', '~> 3.0'
  pod 'FBSnapshotTestCase'
  pod 'Nimble-Snapshots'
  end
end

Project that demonstrates the issue

ResourceTest:
the code that loads the image is in AFunc.swift

awaiting input

Most helpful comment

This still seems to be an issue - I have a framework with a resource_bundles entry that includes an xcassets file. I can confirm that the assets are compiled into an Assets.car that is included in the named bundle, but [UIImage imageNamed:inBundle:compatibleWithTraitCollection:] cannot load the image.

The issue seemed to be that the resources weren't included in the right target by default. Manually assigning targets worked for my sample project, but that's not really a good story to tell our customers.

Replacing resource_bundles with resources in our podspec fixed our issue.

All 19 comments

Reading through lots of resource_bundles/assets-catalog related issues on the net, it wasn't very clearly to us what the official stand of assets catalog support in Cocoapod. Judging that it was working prior to 1.0, we assumed it should continue to work in 1.0.x. If this is not the right assumption, please advice...

@efirestone any interest in looking at this?

Would be happy to help, but I'm out on vacation without a laptop until June 17th. In the meantime, without being able to investigate:

  • asset catalogs should be supported, in fact they should be better supported as of 1.0
  • try using something like resources/*_/_ for your resource_bundles value, rather than something like resources/_/_.png

The biggest change with 1.0 is they CocoaPods should properly understand asset catalogs now, so you want to include the catalog, the JSON files, and everything else, rather than just be image files themselves.

The other issue is that I seem to remember imageNamed:inBundle:compatibleWithTraitCollections: being particular about looking up asset catalog images. You might try creating a catalog by hand and comparing the two (assuming that one works).

If it's still an issue when I get back, happy to help out.

@efirestone,

thanks for the suggestion, the resource_bundles is defined as:
s.resource_bundles = { 'ResourceTest' => ['ResourceTest/Assets/**/*'] }
as I mentioned earlier, the Assets.car file is indeed in the bundle's directory, as far as we can tell.

... I seem to remember imageNamed:inBundle:compatibleWithTraitCollections: being particular about looking up asset catalog images.

Can you elaborate on this point... We didn't change the catalog between Cocoapods releases, so not sure by manually recreating the catalog would make any difference...

I don't remember the particulars unfortunately, and could be thinking of something else entirely. Your resource bundle definition looks right, so not sure what's up. You're definitely passing the correct bundle to imageNamed:?

I tried use of 'bundle_resources'.
However, the resource bundle was not copied to [APPNAME].app/Frameworks/[FRAMEWORK_NAME].frameworks.

If resources is only image, I can evade it by using xcassets.
However, xib, storyboard gif animations and other are not suitable for xcassets.

ex)

https://github.com/ANNotunzdY/SVProgressHUD/blob/pod101/SVProgressHUD.podspec

 s.resource_bundles    = {
    'SVProgressHUD' => ['SVProgressHUD/SVProgressHUD.bundle/*']
  }

screen shot 2016-06-09 at 16 48 57

@ANNotunzdY your issue is likely different. You're specifying both a resources and resource_bundles attribute. You should only be specifying one (resource_bundles). Your file system layout is a bit odd too. It should work, but you don't need to call the folder SVProgressHUD.bundle, CocoaPods will do that for you. Usually you would name it something like SVProgressHUD/Resources, then use something like

 s.resource_bundles    = {
    'SVProgressHUD' => ['SVProgressHUD/Resources/**/*']
  }

@efirestone, I think the bundle should be right, since I can use the same bundle to retrieve the image file from bundle as long as it is not in assets catalog:

let bundle = NSBundle(URL: NSBundle(forClass: Dummy.self).URLForResource("ResourceTest", withExtension: "bundle")!)!

this failed: image.png is in assets catalog:
let image1 = UIImage(named:"image", inBundle: bundle, compatibleWithTraitCollection: nil)

this succeeded: image2.png is outside of assets catalog (but still in the resource_bundles of course):
let image2 = UIImage(named:"image2", inBundle: bundle, compatibleWithTraitCollection: nil)

I have posted the sample project, you can download and test with it: https://github.com/connectdotz/ResourceTest

Aha! Looks like this is a UIKit/asset catalog limitation. There does seem to be a way to make it work though: use -[NSBundle imageForResource:]. See this post for more.

If this works for you then we can close this issue as it's not a CocoaPods limitation.

@efirestone, imageForResource: is not available on iOS, only on mac. I believe the UIImage(named:inBundle:compatibleWithTraitCollection:) is the iOS equivalent.

This API used to work with cocoapods 0.39.x, there must be something introduced in 1.0.x that somehow broke it... did 0.39 actually copy the resources from assets catalog instead of deploying the compiled version?

I ran in the same issue and I found that the product bundle identifier for the resource bundle target is not set if the spec (or subspec) that defines the resource_bundle doesn't have source files. As a result of this the final binary Info.plist for the bundle doesn't have the CFBundleIdentifier key. This seems to affect UIImage(named:inBundle:compatibleWithTraitCollection:) but not UIViewController(nibName:bundle:).

This quick fix worked for me

post_install do |installer|
  installer.pods_project.targets.select { |target| target.name == 'MyResourceOnlyPod-BundleName' }.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.BundleName'
    end
  end
end

I can confirm that this is indeed an issue. Yesterday I moved from 0.39 to 1.0.1 and immediately my app was crashing due to failing to load images from a dependent pod. I restored to CocoaPods 0.39, regenerated everything (clean pod install) rebuilt and everything was again working as expected.

My pod contains code, so @vavvolo's solution didn't seem to help. I looked at the generated plist in the install and it had the bundle identifier as expected without adding the code he suggested.

So back to 0.39 for me, I guess.

Early this week we ran into this issue as well, so I can confirm it still happens with the latest version of CocoaPods. The funny thing is that a plugin we created for a completely different purpose "works-around" this issue as well, so you could try it out https://github.com/Ruenzuo/cocoapods-amimono if you're okay with what the plugin is doing.

Any developments on this?

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.

This still seems to be an issue - I have a framework with a resource_bundles entry that includes an xcassets file. I can confirm that the assets are compiled into an Assets.car that is included in the named bundle, but [UIImage imageNamed:inBundle:compatibleWithTraitCollection:] cannot load the image.

The issue seemed to be that the resources weren't included in the right target by default. Manually assigning targets worked for my sample project, but that's not really a good story to tell our customers.

Replacing resource_bundles with resources in our podspec fixed our issue.

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.

This issue will be auto-closed because there hasn't been any activity for a few months. Feel free to open a new one if you still experience this problem :+1:

Has there been any updates on this, because i still face the same issue? 馃馃槈

Was this page helpful?
0 / 5 - 0 ratings