wake-up-neo.com

So verwenden Sie den Bilderbestandskatalog in der Cocoapod-Bibliothek für iOS

Ich habe eine Cocoapod-Bibliothek, die Assets in 2 Formaten enthält:

  • ein .storyboard 
  • XCode-Bestandskatalog .xcassets (mit Bildern)

meine podspec-Datei enthält die Definition für das Ressourcenpaket:

s.resource_bundle = {'SparkSetup' => ['Resources/**/*.{xcassets,storyboard}']}

und ich habe ein separates Ziel im Pod-Projekt, um ein Ressourcenpaket zu erstellen, indem diese Dateien verwendet werden + eine Plist-Datei für dieses Paket.

wenn ich den Pod in einem App-Projekt verwende, kann ich sehen, dass die Storyboard-/Xcassets-Dateien im Pod-Ziel sind und ich das Storyboard problemlos aufrufen und ausführen kann, aber die im Storyboard referenzierten Bilder (auf die .xcassets-Datei) sind nicht zur Laufzeit gefunden (aber korrekt in IB angezeigt).

Fehler, den ich bekomme ist:

Could not load the "spinner" image referenced from a nib in the bundle with identifier "(null)"

Ich sehe eine Bundle-Datei im Produktverzeichnis . Um VCs im Storyboard zu instanziieren, verwende ich:

+(NSBundle *)getResourcesBundle
{
    NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"SparkSetup" withExtension:@"bundle"]];
    return bundle;
}


+(UIStoryboard *)getSetupStoryboard
{
    UIStoryboard *setupStoryboard = [UIStoryboard storyboardWithName:@"setup" bundle:[SparkSetupMainController getResourcesBundle]];
    return setupStoryboard;
}

das scheint gut zu funktionieren, um das Storyboard zu finden, aber nicht, um Bilder in den .xcassets im selben Bundle zu finden.

Was mache ich falsch? Wie kann ich Bilder aus diesem Storyboard/aus Code referenzieren und diesen UI-Pod in jede App integrieren?

Vielen Dank!

22
mindbomb

Ab Version 1.0.1 von Cocoapods werden Image-Asset-Kataloge unterstützt.

In meinem Swift-Code habe ich verwendet:

public static var GoogleIcon:UIImage {
    let bundle = NSBundle(forClass: self)
    Log.msg("bundle: \(bundle)")
    return UIImage(named: "GoogleIcon", inBundle: bundle,compatibleWithTraitCollection: nil)!
}

In meiner Pod-Spezifikation habe ich verwendet:

s.resources = "SMCoreLib/Assets/*.xcassets"

Wenn ich mit dem Simulator baue, erscheint die .car-Datei do im Framework:

cd /Users/<snip>/SMCoreLib.framework 
ls
Assets.car  Info.plist  SMCoreLib
27
Chris Prince

Nun, Image-Asset-Kataloge werden nicht über Pods unterstützt. Fügen Sie einfach ein Ressourcenpaket hinzu, das Ihre Image-Dateien in Ihrer Podspec enthält.

s.subspec 'Resources' do |resources|
    resources.resource_bundle = {'MyBundle' => ['Resources/**/*.{png}']}

end

und greifen Sie auf die Bilder so sicher von der Pod zu:

+(NSBundle *)getResourcesBundle
{
    NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle bundleForClass:[self class]] URLForResource:@"MyBundle" withExtension:@"bundle"]];
    return bundle;
}


+(UIImage *)loadImageFromResourceBundle:(NSString *)imageName
{
    NSBundle *bundle = [MyClass getResourcesBundle];
    NSString *imageFileName = [NSString stringWithFormat:@"%@.png",imageName];
    UIImage *image = [UIImage imageNamed:imageFileName inBundle:bundle compatibleWithTraitCollection:nil];
    return image;
}

Das löst alle Probleme beim Umgang mit Bildern/Ressourcen innerhalb eines Kokosapods.

10
mindbomb

Swift 3 Version

private func getImageFromBundle(name: String) -> UIImage {
   let podBundle = Bundle(for: YourClass.self)
   if let url = podBundle.url(forResource: "YourClass", withExtension: "bundle") {
      let bundle = Bundle(url: url)
      return UIImage(named: name, in: bundle, compatibleWith: nil)!
   }
   return UIImage()
}
4
Phil

wenn Sie Swift verwenden.

class func loadImage(name: String) -> UIImage? {
    let podBundle = NSBundle(forClass: MyClass.self)
    if let url = podBundle.URLForResource("MyBundleName", withExtension: "bundle") {
        let bundle = NSBundle(URL: url)
        return UIImage(named: name, inBundle: bundle, compatibleWithTraitCollection: nil)
    }
    return nil
}
3
Daishi Nakajima

Nur das funktioniert für mich (Swift 3 & Swift 4)

public struct ImagesHelper {
  private static var podsBundle: Bundle {
    let bundle = Bundle(for: YourClass.self)
    return Bundle(url: bundle.url(forResource: "YourClass",
                                  withExtension: "bundle")!)!
  }

  private static func imageFor(name imageName: String) -> UIImage {
    return UIImage.init(named: imageName, in: podsBundle, compatibleWith: nil)!
  }

  public static var myImage: UIImage {
    return imageFor(name: "imageName")
  }
}

Dann benutze es wie folgt:

ImagesHelper.myImage

Vergessen Sie nicht, Ihre Podspec-Datei wie in der Antwort in @Chris Prince zu aktualisieren:

s.resource_bundles = {
  'YourClass' => ['YourPodName/*/Assets.xcassets']
}
2

In dir podspec so machen

s.resources = 'RootFolder/**/*.{lproj,storyboard,xcdatamodeld,xib,xcassets,json}'
2

Ich kann es immer noch nicht zum Laufen bringen, mit keiner der oben genannten Lösungen.

Und in meinen Pod-Klassen möchte ich auf Bilder aus den Assets zugreifen

So spezifiziert:

s.resource_bundles = {
     'SWDownloadPlayButton' => ['SWDownloadPlayButton/Assets/Assets.xcassets']
}

Mit diesem Helfer:

public struct ImagesHelper {
    private static var podsBundle: Bundle {
        let bundle = Bundle(for: SWDownloadPlayButton.self)
        return Bundle(url: bundle.url(forResource: "SWDownloadPlayButton",
                                      withExtension: "bundle")!)!
    }

    private static func imageFor(name imageName: String) -> UIImage {
        return UIImage.init(named: imageName, in: podsBundle, compatibleWith: nil)!
    }

    public static var download_icon: UIImage {
        return imageFor(name: "download_icon")
    }
}

Was auch immer ich in meinen Pod-Klassen mache (nicht im Beispielprojekt) ... so

 var centerImage: UIImage = ImagesHelper.download_icon.withRenderingMode(.alwaysTemplate) {
        didSet {
            updateImage()
        }
    }

Ich bekomme immer noch ein Null auf das centerImage

1
jr00n

Fügen Sie Ihre .xcassets-Datei innerhalb der Ressourcen in Ihrer Pod-Spezifikation hinzu und verwenden Sie die folgende UIImage-Init: 

extension UIImage {
    convenience init?(podAssetName: String) {
        let podBundle = Bundle(for: ConfettiView.self)

    /// A given class within your Pod framework
    guard let url = podBundle.url(forResource: "CryptoContribute",
                                  withExtension: "bundle") else {
        return nil

    }

    self.init(named: podAssetName,
              in: Bundle(url: url),
              compatibleWith: nil)
    }
 }
0
thexande

Meine eigene Lösung für das Problem mit CocoaPods. Anstatt mit UIImage zu arbeiten, habe ich stattdessen eine Methode zu Bundle hinzugefügt. Die Methode versucht, ein inneres Bündel eines bestimmten Namens zu finden, greift jedoch auf das ursprüngliche Bündel zurück. Dadurch kann der Code sowohl im Anwendungscode unter Verwendung von Pods als auch im Pod-Code selbst ausgeführt werden.

extension Bundle {

    /**
     Locate an inner Bundle generated from CocoaPod packaging.

     - parameter name: the name of the inner resource bundle. This should match the "s.resource_bundle" key or
       one of the "s.resoruce_bundles" keys from the podspec file that defines the CocoPod.
     - returns: the resource Bundle or `self` if resource bundle was not found
    */
    func podResource(name: String) -> Bundle {
        guard let bundleUrl = self.url(forResource: name, withExtension: "bundle") else { return self }
        return Bundle(url: bundleUrl) ?? self
    }
}

Geben Sie dann in der viewDidLoad-Methode oder wo immer Sie Ihren Image-Einstellungscode haben, etwas wie folgt ein, wobei "ClassFromPod" auf eine Swift-Klasse von einem CocoaPod verweist und "ResourceName" der Name des inneren Pakets innerhalb des Pods ist Sie können die Bundles mit dem Xcode-Projektnavigator unter "Pods/Projects" sehen. Eingebettete Bundles haben ein LEGO-Symbol und ein Suffix "Bundle".)

super.viewDidLoad()
let bundle = Bundle(for: ClassFromPod.self).podResource(name: "ResourceName")
img1 = UIImage(named: "FancyBase", in: bundle, compatibleWith: nil)
img2 = UIImage(named: "FancyHandle", in: bundle, compatibleWith: nil)

Wie Sie sehen, bleibt die UIImage-API gleich, nur das verwendete Bundle unterscheidet sich je nachdem, was zur Laufzeit gefunden wird.

0
Brad Howes

Sie können über die Bundle-ID auf Bilder von Pods zugreifen

 enter image description here

 NSBundle * bundle = [NSBundle bundleWithIdentifier:@"bundle id of your pod"];
UIImage * image = [UIImage imageNamed:@"imageName" inBundle:bundle compatibleWithTraitCollection:nil];
0
levin varghese