可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am creating a private library that includes resources that are referenced by components in the library. The library is shared with apps using CocoaPods. In the .podspec for the library, I've included a line like this:
s.resource_bundles = {'IXMapKitResources' => ['IXMapKit/Resources/*']}
One of the resources in the bundle is an asset catalog with multiple image sets, one of which is called 'IXMKAnnotationIcons-Normal-Accident'. The following code returns a nil:
UIImage * image = [UIImage imageNamed: @"IXMKAnnotationIcons-Normal-Accident"];
I found an article on mokacoding.com describing how to load fonts from a pod, but this didn't work for me:
- (UIImage *) ixmk_imageNamed: (NSString *) name
{
NSString * IXMKResourceBundleName = @"IXMapKitResources.bundle";
NSString * resourceName = [NSString stringWithFormat: @"%@/%@", IXMKResourceBundleName, name];
NSString * imageTypeString = [self ixmk_stringForImageType: imageType];
NSURL * url = [[NSBundle mainBundle] URLForResource: resourceName withExtension: imageTypeString];
NSData * imageData = [NSData dataWithContentsOfURL: url];
if (imageData != nil)
{
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef) imageData);
CGImageRef imageRef = [self ixmk_imageFromDataProvider: provider imageType: imageType];
UIImage * image = [UIImage imageWithCGImage: imageRef];
CFRelease(imageRef);
CFRelease(provider);
return image;
}
else
{
return nil;
}
}
The CocoaPods webpage describing the resources keyword has the following warning:
We strongly recommend library developers to adopt resource bundles as
there can be name collisions using the resources attribute. Moreover
resources specified with this attribute are copied directly to the
client target and therefore they are not optimized by Xcode.
I'm at a loss of what to do here.
回答1:
This turns out to be a problem with asset catalogs, not CocoaPods or bundles. Moving the images out of the asset catalog solved the problem. It looks like Apple doesn't support asset catalogs in secondary resource bundles. Pity.
回答2:
For example Paramount
podspec
s.resource_bundle = {
'Paramount' => ['Sources/Paramount.bundle/*.png']
}
swift
public extension UIImage {
static func make(name: String) -> UIImage? {
let bundle = NSBundle(forClass: Paramount.Toolbar.self)
return UIImage(named: "Paramount.bundle/\(name)", inBundle: bundle, compatibleWithTraitCollection: nil)
}
}
Here Paramount.Toolbar.self
can be any class in that framework
回答3:
The obvious solution that wasn’t listed anywhere is using the Cocoapods generated bundle (which the folder actually doesn’t exist) as a NSBundle:
have a try:
http://blog.flaviocaetano.com/post/cocoapods-and-resource_bundles/
it worked for me!!
回答4:
As for me, I had to add the "s.resources" into the .podspec. Before this was missing.
Only the s.resource_bundles were set this way: 'BPPicker/Assets/.', changed it to 'BPPicker/Assets/*' as well.
#
# Be sure to run `pod lib lint BPPicker.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'BPPicker'
s.version = '0.1.11'
s.summary = 'This is the imito Body Part Picker.'
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = <<-DESC
TODO: Add long description of the pod here.
DESC
s.homepage = 'https://bitbucket.org/imito/bppicker'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Ievgen Naloiko' => 'naloiko@gmail.com' }
s.source = { :git => 'https://ievgen_naloiko@bitbucket.org/imito/bppicker.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.ios.deployment_target = '9.0'
s.source_files = 'BPPicker/Classes/**/*'
s.resource_bundles = {
'BPPicker' => ['BPPicker/Assets/*']
}
s.resources = "BPPicker/**/*.{png,json}"
s.frameworks = 'UIKit'
s.dependency 'ObjectMapper'
end
回答5:
I made a pod that can locate the resource bundles in pods.
I hope it will end the "CocoaPods resource bundle" problem once and for all.
https://github.com/haifengkao/PodAsset
回答6:
This answer works with Swift3 and Swift4.
Create a function under the pod directory into the file.
func loadImageBundle(named imageName:String) -> UIImage? {
let podBundle = Bundle(for: self.classForCoder)
if let bundleURL = podBundle.url(forResource: "Update with directory name", withExtension: "bundle")
{
let imageBundel = Bundle(url:bundleURL )
let image = UIImage(named: imageName, in: imageBundel, compatibleWith: nil)
return image
}
return nil
}
Usage
imageView.image = loadImageBundle(named: "imagefile")
回答7:
In your pod file: images are in .xcassets so it can be easily organized with 1x, 2x, 3x
s.resources = 'PodName/Assets/**'
Usage: Swift
let bundle = Bundle(for: ClassThatWillUseTheImage.self)
let image = UIImage(named: "close", in: bundle, with: .none)
Usage: Objective-C
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
UIImage *image = [UIImage imageNamed:@"close" inBundle:bundle withConfiguration:nil];
Tested in Version 11.4 (11E146) iOS 13.0+
Using #imageLiteral(resourceName: "close")
does not work however, it shows the image being read but will throw and error.