iOS组件化(四) - iOS组件中图片文件资源的使用

2,824 阅读3分钟


参考文章:iOS组件化(三)----- 加载图片等资源文件

以上文章详细介绍了各个情况的资源文件


本文仅限于使用模块的项目PodFile中使用use_frameworks!的情况


一、组件中代码和资源的位置

1. 项目中代码放在组件目录下的Classes

image.png

2. 项目中图片等资源放在组件目录下的Assets

image.png

3. .podspec中的图片资源配置

其中InformationModuleImageBundle为图片资源的bundle名,后面为资源路径

  # 设置图片资源
  s.resource_bundles = {
      'InformationModuleImageBundle' => ['InformationModule/Assets/*']
  }

image.png

二、使用模块的项目PodFile中使用use_frameworks!的情况

image.png

使用组件的项目的PodFile使用use_frameworks!,则资源在APP中所在路径为: /Build/Products/Debug-iphonesimulator/InformationModule_Example.app/Frameworks/InformationModule.framework/InformationModuleImageBundle.bundle

具体查看资源方法:

1. 右键.app文件,show in finder

image.png

2. 显示包内容

image.png

3. Feameworks - .framework - .bundle

image.png

4. 图片

image.png

5. 图片在Pods中的位置

image.png

三、定义获取组件中图片和文件资源的Util

image.png

//
//  InformationModuleUtil.swift
//  TestDemo
//
//  Created by yuanzhiying on 2021/7/30.
//

import UIKit

open class InformationModuleUtil {
    // 通用 - 获取InformationModule.framework的Bundle
    static func getInformationModuleFrameworkBundle(_ moduleName: String = "InformationModule") -> Bundle? {
        // 先进入MainBundle下的Frameworks文件夹下
        if var bundleURL = Bundle.main.url(forResource: "Frameworks", withExtension: nil) {
            // 再进入InformationModule.framework包下
            bundleURL = bundleURL.appendingPathComponent(moduleName)
            bundleURL = bundleURL.appendingPathExtension("framework")
            // 拿到InformationModule.framework的Bundle
            return Bundle(url: bundleURL)
        }
        return nil
    }

    // 获取组件中的图片
    // 组件中的图片在InformationModule.framework下的InformationModuleImageBundle.bundle下
    // 组件中图片在组件项目中的路径是在assets文件夹下
    // 2. 图片没有放在imageset里,imageName直接使用imageName.png
    // 3. 如果放在dou.imageset/里,则imageName传"dou.imageset/dou.png"
    public static func getImformationModuleImage(imageName: String, _ resourceBundle: String = "InformationModuleImageBundle") -> UIImage? {
        if let informationModuleFrameworkBundle = getInformationModuleFrameworkBundle() {
            // 获取InformationModuleImageBundle.bundle路径
            if let tempBundleURL = informationModuleFrameworkBundle.url(forResource: resourceBundle, withExtension: "bundle") {
                // 获取InformationModuleImageBundle.bundle的Bundle
                let tempBundle = Bundle(url: tempBundleURL)
                // 拿InformationModuleImageBundle.bundle下的头文件
                if let file = tempBundle?.path(forResource: imageName, ofType: nil) {
                    return UIImage(contentsOfFile: file)
                }
            }
        }
        return nil
    }

    // 获取组件中的storyboard
    // 组件中的storyboard在InformationModule.framework下
    public static func getInformationModuleStoryboard(storyboardName: String, _ moduleName: String = "InformationModule") -> UIStoryboard? {
        if let informationModuleFrameworkBundle = getInformationModuleFrameworkBundle() {
            return UIStoryboard(name: storyboardName, bundle: informationModuleFrameworkBundle)
        }
        return nil
    }
}

四、在项目中使用组件的资源、类、文件

image.png

//
//  ViewController.swift
//  InformationModule
//
//  Created by 873965092@qq.com on 07/28/2021.
//  Copyright (c) 2021 873965092@qq.com. All rights reserved.
//

import InformationModule
import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        /// 引用组件中的UIView
        let testView = TestView(frame: CGRect(x: 50, y: 50, width: 120, height: 120))
        testView.backgroundColor = UIColor.red
        view.addSubview(testView)

        // 引用组件中的类和方法
        let model = InformationModel()
        model.helloWorld()

        // 获取并展示组件中的图片资源
        let imageView = UIImageView(frame: CGRect(x: 200, y: 300, width: 20, height: 25))
        imageView.image = InformationModuleUtil.getImformationModuleImage(imageName: "phone.png")
        view.addSubview(imageView)

        // 获取并展示组件中的图片资源
        let imageView2 = UIImageView(frame: CGRect(x: 150, y: 350, width: 72, height: 29))
        imageView2.image = InformationModuleUtil.getImformationModuleImage(imageName: "dou.imageset/dou.png")
        view.addSubview(imageView2)
    }

    @IBAction func pushStoryboard(_ sender: Any) {
        let storyboard = InformationModuleUtil.getInformationModuleStoryboard(storyboardName: "InformationPage")
        if let vc = storyboard?.instantiateViewController(withIdentifier: "InformationPage") {
            present(vc, animated: true, completion: nil)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

五、在组件中使用组件中的资源、图片、文件、类等

  • InformationPage

image.png

//
//  InformationPage.swift
//  InformationModule
//
//  Created by yuanzhiying on 2021/7/30.
//

import UIKit

class InformationPage: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        
        self.view.backgroundColor = UIColor.white

        let pushStoryboardButton = UIButton(type: .custom)
        pushStoryboardButton.frame = CGRect(x: 50, y: 250, width: 250, height: 250)
        pushStoryboardButton.backgroundColor = UIColor.blue
        pushStoryboardButton.setTitle("pushSecondStoryboard", for: .normal)
        pushStoryboardButton.setTitleColor(UIColor.white, for: .normal)
        pushStoryboardButton.addTarget(self, action: #selector(pushStoryboardPage), for: .touchUpInside)
        
        self.view.addSubview(pushStoryboardButton)
    }
    
    @objc func pushStoryboardPage() {
        let storyboard = InformationModuleUtil.getInformationModuleStoryboard(storyboardName: "SecondViewController")
        if let vc = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") {
            self.present(vc, animated: true, completion: nil)
        }
    }
    

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

  • TestView

image.png

//
//  TestView.swift
//  InformationModule
//
//  Created by yuanzhiying on 2021/7/30.
//

import UIKit

open class TestView: UIView {
    override public init(frame: CGRect) {
        super.init(frame: frame)
        
        // 组件中展示组件中的图片资源
        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 25))
        imageView.image = InformationModuleUtil.getImformationModuleImage(imageName: "phone.png")
        addSubview(imageView)
    }
    
    public required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

  • InformationPage.storyboard

使用InformationModuleImageBundle.bundle/dou.imageset/dou.png

image.png

使用InformationModuleImageBundle.bundle/phone.png

image.png