大刘的 iOS 自学笔记

NSBundle

2022-06-11  本文已影响0人  大刘

Created by 大刘 liuxing8807@126.com

Apple: Accessing a Bundle's Contents
Apple: NSBundle class reference

A representation of the code and resources stored in a bundle directory on disk.

注:并不是所有的资源都一定要通过Bundle来获取:

Some types of frequently used resources can be located and opened without a bundle. For example, when loading images, you store images in asset catalogs and load them using the imageNamed: methods of UIImage or NSImage. Similarly, for string resources, you use NSLocalizedString to load individual strings instead of loading the entire .strings file yourself.
放在Assets中的图片文件和国际化文本并不是通过Bundle来获取的

main bundle

**The main bundle is the bundle that contains the code and resources for the running application. **

在定位一个资源之前,首先要做的就是指定这个资源所属的bundle, NSBundle有很多构造方法,最常用的就是mainBundle, Bundle.main返回的是包含当前可执行代码的bundle: Returns the bundle object that contains the current executable., 对于app来说,就是主工程。使用mainBundle获取资源通常使用两个方法:

在Swift中:

open class Bundle : NSObject {
    /* Methods for creating or retrieving bundle instances. */
    open class var main: Bundle { get }    
    public init?(path: String) // 对应OC [NSBundle bundleWithPath]

    @available(iOS 4.0, *)
    public convenience init?(url: URL)
    public /*not inherited*/ init(for aClass: AnyClass) // 对应OC [NSBundle bundleForClass]
    public /*not inherited*/ init?(identifier: String)

在子framework中是无法获取主bundle的资源的,因此使用main bundle必须是在App中,而不是在其他App所包含的framework中。对于一个动态库来说,它本身就是一个单独的bundle,App可以调用这个framework, 但framework无法使用工程App的功能。

获取Bundle中资源是有讲究的,下面直接通过一个代码示例演示在main bundle和在动态库中获取资源的不同方式, 完整代码可参见 HERE

在主工程中:

class MainBundleViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.title = "main bundle"
    }

    // 普通图片
    @IBAction func getImage(_ sender: Any) {
        // OK -- Bundle.main
        // self.imageView.image = UIImage(named: "1.png", in: Bundle.main, compatibleWith: nil)
        
        // OK -- Bundle(for: AnyClass)
        // self.imageView.image = UIImage(named: "1.png", in: Bundle(for: MainBundleViewController.self), compatibleWith: nil)
        
        // OK -- Bundle.main.path
        if let path = Bundle.main.path(forResource: "1", ofType: "png") {
            self.imageView.image = UIImage(contentsOfFile: path)
        }
    }
    
    // 在文件夹images中图片
    @IBAction func getImageInDir(_ sender: Any) {
        // OK -- Bundle.main
        // self.imageView.image = UIImage(named: "2.png", in: Bundle.main, compatibleWith: nil) // 不可写为images/2.png
        
        // OK -- Bundle.main.path
        // self.imageView.image = UIImage(named: "2.png", in: Bundle(for: MainBundleViewController.self), compatibleWith: nil) // 不可写为images/2.png
        
        // OK
        if let path = Bundle.main.path(forResource: "2", ofType: "png") { // 不可写为images/2
            self.imageView.image = UIImage(contentsOfFile: path)
        }
    }
    
    // 在bundle中的图片
    @IBAction func getImageInBundle(_ sender: Any) {
        // 新建文件夹,改后缀名,托入XCode
        // https://stackoverflow.com/questions/4888208/how-to-make-an-ios-asset-bundle
        /**OK
        let imagePath: String = Bundle.main.path(forResource: "MyBundle.bundle/1", ofType: "png")!
        self.imageView.image = UIImage(contentsOfFile: imagePath)
        */
        
        let bundlePath: String = Bundle.main.path(forResource: "MyBundle", ofType: "bundle")!
        if let bundle = Bundle(path: bundlePath) {
            // OK
            // self.imageView.image = UIImage(named: "1.png", in: bundle, compatibleWith: nil)
            
            let imagePath: String = bundle.path(forResource: "1", ofType: "png")!
            self.imageView.image = UIImage(contentsOfFile: imagePath)
        }
    }
}

在动态库Framework中:

public class LoginViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!
    
    convenience init() {
        self.init(nibName: "LoginViewController", bundle: Bundle(for: LoginViewController.self))
    }
    
    override public func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white
    }
    
    // 普通图片
    @IBAction func getImage(_ sender: Any) {
        // OK
        // self.imageView.image = UIImage(named: "1.jpeg", in: self.currentBundle(), compatibleWith: nil)
        
        // OK
        let path: String = self.currentBundle().path(forResource: "1", ofType: "jpeg")!
        self.imageView.image = UIImage(contentsOfFile: path)
    }
    
    // 在文件夹images中图片
    @IBAction func getImageInDir(_ sender: Any) {
        // OK
        // self.imageView.image = UIImage(named: "2.png", in: self.currentBundle(), compatibleWith: nil) // 不可写为images/2.png
        
        // OK
        if let path = self.currentBundle().path(forResource: "2", ofType: "png") { // 不可写为images/2
            self.imageView.image = UIImage(contentsOfFile: path)
        }
    }
    
    // 在bundle中的图片
    @IBAction func getImageInBundle(_ sender: Any) {
        /** // OK
        let imagePath:String! = self.currentBundle()?.path(forResource: "AccountBundle.bundle/1", ofType: "png")!
        self.imageView.image = UIImage(contentsOfFile: imagePath)
         */
        
        let bundlePath: String = self.currentBundle().path(forResource: "AccountBundle", ofType: "bundle")!
        if let bundle = Bundle(path: bundlePath) {
            // OK
            // self.imageView.image = UIImage(named: "1.png", in: bundle, compatibleWith: nil)
            
            // OK
            let imagePath: String = bundle.path(forResource: "1", ofType: "png")!
            self.imageView.image = UIImage(contentsOfFile: imagePath)
        }
    }
    
    // 在Account.xcassets中
    @IBAction func getImageInXcassets(_ sender: Any) {
        self.imageView.image = UIImage(named: "1.png", in: self.currentBundle(), compatibleWith: nil)
    }
    
    func currentBundle() -> Bundle! {
        return Bundle(for: LoginViewController.self)
    }
}
上一篇下一篇

猜你喜欢

热点阅读