美文网首页iOS成长之路
Cocoapods组件私有库创建Framework

Cocoapods组件私有库创建Framework

作者: AdamShi | 来源:发表于2022-08-10 10:20 被阅读0次

    公司有个新的项目A,项目A的需求是: 把已有的项目B中的某些页面及功能封装成SDK,涉及到的场景和技术点是:
    1.依赖了cocoapods三方库,比如AFNetworking, SDWebImage等,所以要解决三方库依赖
    2.项目主要是OC,但是也有一些Swift类做的混编,所以Framework里面要考虑混编的问题
    3.项目有多语言国际化,需要考虑bundle切换
    4.测试工程要能源码断点调试,最好也能jenkins自动打包
    5.能脚本自动化出包
    6.后期做组件化,技术方案最好能低成本切换到组件化


    先做技术调研评估和选型,封装Framework有如下方式:

    1.Framework的project工程

    目前网上大部分文章都是这个方案,我做了下总结:
    网址: iOS SDK Framework封装
    优点:文档比较全,工程独立,代码逻辑清晰
    缺点:代码同步问题,如果项目B中的代码或资源有改动,需要手动将改动复制到SDK中

    2.已有项目直接添加target

    已有项目要打包成Framework,可以试试在已有项目中添加target,target的类型是Framework
    优点:直接复用项目B中代码,不需要同步代码,复制改动
    缺点:项目B中需要添加SDK逻辑,后面逻辑会越来越混乱,难以维护
    具体参考: iOS封装framework

    3.cocoapods组件私有库创建Framework

    创建cocoapods私有库,方便调试,可以用cocoapods的package工具打包
    优点:工程独立,代码逻辑清晰; 跟方案1比较的话,cocoapods三方库依赖管理更简单.附带demo.有专门的打包工具package
    缺点:代码同步问题,如果项目B中的代码或资源有改动,需要手动将改动复制到SDK中

    最终觉得方案3比较合适,做过组件化的都很熟悉


    关于动态库和静态库

    关于动态库和静态库网上讲的很多了.网上大部分还是说用static打包成静态库. 但是自从iOS8开始,已经允许动态库上架了, 而且动态库获取资源bundle和资源文件更为简单,所以推荐打成动态库
    【iOS】使用workspace搭建SDK开发框架
    iOS 最全动态库/静态库制作 Framework/.a
    iOS之深入解析静态库和动态库

    一.创建私有库组件

    二.导入类

    最耗时间的工作,抽丝剥茧,把页面依赖的类都抽出来
    导入头文件,可以用@class?

    三.导入资源文件

    最好全局搜索bundle,image,nib,xib,html,js或其他资源关键字,修改所有涉及到的资源等等

    获取资源文件方式, 基本都是先拿到bundle包路径,然后再通过bundle加载资源

    框架和业务分离
    iOS:NSBundle的一些理解
    iOS SDK(二):Bundle 创建 & 使用
    NSBundle使用
    注意: 动态库和静态库获取资源的方式是不一样的
    【iOS】使用workspace搭建SDK开发框架

    1.image

    2.xib

    3.多语言

    4.字体

    一般加载字体都是静态加载,需要在info.plist提前声明用了什么字体; 私有库中一般不会要求集成方做这个设置,所以一般用动态加载字体方式:
    如何向 Cocoapod 添加自定义字体?
    iOS动态字体加载及坑
    iOS 动态加载字体
    iOS 组件化实战篇(私有库)
    cocoapods 管理图片资源和字体库
    iOS中使用自定义字体, 动态下载字体

    5.bundle的管理

    a.如果封装的是动态库,那么不需要对bundle做特殊处理,cocoapods会自动链接并把bundle打包到framework里面
    b.如果封装的是静态库framework,那么bundle的管理会很麻烦.组件打包时,需要在pod-sdk'starget-Build Phases-Copy Bundle Resources中,手动链接bundle文件,而且SDK使用方需要添加个脚本,把静态bundle拷贝到APP中,才能寻找到bundle文件

    四.修改podspec文件

    官网: cocoapods官网podspec文档
    CocoPods之.podspec语法参考
    s.source源应该改为本地路径?

    ///保持路径?
    spec.header_mappings_dir = 'XXXSDK/Classes/**'
    

    五.OC和Swift混编

    私有库中混编:

    1.OC调用Swift:

    swift添加public关键字,如果不行,就添加open关键字; 查文档说最好用open,public的话,有可能出现找不到类或者方法等等问题
    如果这个swift类还调用了其他的swift三方库,会崩溃,查了很久发现需要在podspec添加配置s.swift_version = '5.0'指定swift版本就行了

    引用swift头文件方式
    #import <XXXSDK/XXXSDK-Swift.h>
    
    2.Swift调用OC

    系统自动生成XXX-umbrella.h

    参考:
    CocoaPods 制作私有库 Swift/OC 过程、注意点和错误总结
    进阶-Swift和OC混编生成 swift pod私有库
    OC和Swift混编, 在Cocoapods私有库中的用法
    Swift/Objective-C-使用Cocoapods创建/管理私有库(高级用法)
    OC和Swift混合开发(Pod私有库的相互引用)
    组件化开发之-如何解决Swift/OC-Framenwork/Library混合创建pod问题
    制作Swift和Objective-C Mixed的Pod
    如何在模块化/组件化项目中实现 ObjC-Swift 混编?
    CocoaPods组件化之OC与Swift混编问题
    iOS组件化 pod命令创建私有库详解【引用其他私有库、oc、Swift混编】
    Swift和OC在同一个库中如何实现混编?
    iOS Swift 创建的私有库与oc混编报错"#import <xxx/xxx.h> file not found"
    iOS使用Cocoapods对Swift和OC进行混编
    Swift和Objective-C混编在有赞移动的实践

    六.出包

    两种方式,推荐第二种方式

    1.安装cocoapods package插件,专用于打包.

    这种方式不太推荐,因为这个插件已经很久不更新了,直接用的话还有问题, 而且好像不支持最新的xcframework格式的包
    【cocoapods】-cocoapods-packager打包静态库
    iOS开发之CocoaPods:插件篇一 CocoaPods Packager
    IOS pod package 报错:Pods/build/package.a and Pods/build-sim/package.a have the same architectures
    使用cocoapods package打包

    package打包命令,好像都可以:
    1.
    //打包静态framework 用这个
    pod package xxx.podspec --force --no-mangle --embedded
    //打包静态.a 用这个
    pod package xxx.podspec --library --force
    
    2.
    pod package xxx.podspec --force --no-mangle --exclude-deps
    
    2.xcodebuild命令

    推荐用这种方式生成XCFramework
    使用 Xcode 制作 Framework 与 XCFramework
    iOS开发进阶六:lipo指令和XCFramework

    #脚本需要放到工程目录里
    scheme_name="XXX"
    workspace_file_path="Example/YYY.xcworkspace"
    configuration_type="Release"
    result_folder_path="../SDKArchive/${scheme_name}"
    archive_folder_path="${result_folder_path}/Archives"
    xcframework_file_path="${result_folder_path}/${scheme_name}.xcframework"
     
    rm -rf ${archive_folder_path}
    rm -rf ${xcframework_file_path}
    
    # clean
    xcodebuild clean -workspace ${workspace_file_path} \
                     -scheme ${scheme_name} \
                     -configuration ${configuration_type}
    
    # iOS devices
    xcodebuild archive -workspace ${workspace_file_path}\
                       -scheme ${scheme_name} \
                       -configuration ${configuration_type} \
                       -archivePath "${archive_folder_path}/${scheme_name}-iOS.xcarchive" \
                       -destination "generic/platform=iOS" \
                       -sdk iphoneos \
                       SKIP_INSTALL=NO \
                       BUILD_LIBRARY_FOR_DISTRIBUTION=YES
    
    # iOS simulators
    xcodebuild archive -workspace ${workspace_file_path}\
                       -scheme ${scheme_name} \
                       -configuration ${configuration_type} \
                       -archivePath "${archive_folder_path}/${scheme_name}-iOS-simulator.xcarchive" \
                       -destination "generic/platform=iOS Simulator" \
                       -sdk iphonesimulator \
                       SKIP_INSTALL=NO \
                       BUILD_LIBRARY_FOR_DISTRIBUTION=YES
    
    xcodebuild -create-xcframework \
               -framework "${archive_folder_path}/${scheme_name}-iOS.xcarchive/Products/Library/Frameworks/${scheme_name}.framework" \
               -framework "${archive_folder_path}/${scheme_name}-iOS-simulator.xcarchive/Products/Library/Frameworks/${scheme_name}.framework" \
               -output ${xcframework_file_path}
        
    
    open ${result_folder_path}
    
    

    七.集成SDK

    1.手动集成

    如果framework里有category,集成方需要在other linker flag-添加-ObjC(如果是动态库,好像不加也没事...)

    如果手动集成动态库,需要设置: Target-General-Frameworks, Libraries, and Embedded Content,把动态库设置为Embed & Sign

    iOS framework之Embed、Signing
    Framework 嵌套与依赖

    2.发布公有库

    这里有个坑,如果是发布的动态库,那么一切好说; 如果发布的是静态库,而且有OC和Swift混编,可能验证一直无法通过,因为必须要所有pod target的BUILD_LIBRARY_FOR_DISTRIBUTION都设置为yes才行,所以只能验证命令添加--skip-import-validation, 跳过验证才能发布成功

    //podspec文件添加
      s.vendored_frameworks = 'Frameworks/xxx.xcframework' 
    
    //两个常用验证命令
    //如果验证不通过,可以试试pod lib lint --verbose --allow-warnings --skip-import-validation, pod trunk push时,也要添加--skip-import-validation
    //cd到podspec目录下
    //公有库验证:
    pod spec lint --verbose --allow-warnings
    pod trunk push XXXSDK.podspec --verbose --allow-warnings
    
    //私有库验证:
    pod lib lint  --verbose --allow-warnings --sources="https://github.com/CocoaPods/Specs.git,https://xxx.git"
    pod repo push 仓库Name SpecName.podspec --verbose --allow-warnings --sources="https://github.com/CocoaPods/Specs.git,https://xxx.git"
    
    //其他参数
    --use-libraries
    --use-static-frameworks 
    --skip-import-validation
    --skip-tests
    
    

    XCFramework从0到发布到Cocoapod
    CocoaPods私有库可能遇到的坑

    Xcode12 执行 pod lib lint 报错:building for iOS Simulator, not found for architecture arm64
    解决pod lib lint/repo push不支持i386编译&只能真机运行的库
    ios Framework静态库以及上传私有库
    iOS 私有库中依赖私有库 且有第三方framework的处理
    2018-06-24 私有库坑 :Include of non-modular header inside framework module
    2019-07-31 记录私有库坑 :Include of non-modular header inside framework module
    使用cocoapods打包静态库(依赖私有库,开源库,私有库又包含静态库)
    [Cocoapods]使用Cocoapods + Github托管代码
    Pod spec私有库集成遇到的错误(一)
    Pod spec私有库集成遇到的错误(二)
    Pod本地私有库使用图片和XIB资源文件

    不管是静态库还是动态库,不管是手动集成还是cocoapods集成,只要有OC和Swift混编,打包出来的XCFramework,集成方都有可能报错,找不到类或者方法,这个问题找了很久,终于在github上看到解决方案:解决办法
    //集成方需要在podfile最下面添加设置
    post_install do |installer|
      installer.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
          config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
        end
      end
    end
    
    

    八.问题以及坑

    1.pod install时报很长的警告,解决方式:

    install!'cocoapods',:deterministic_uuids=>false
    参考: [Xcodeproj] Generated duplicate UUIDs

    2.pod spec lint时

    --use--modular-headers 干啥的?

    3.其他:

    Cocoapods打包framework/静态库的注意点
    [Cocoapods]项目添加Cocoapods支持遇到的坑
    cocoaPods 进行SDK二次包装(cocoapods-packager完成 framework静态库打包,避免第三方库冲突)
    关于使用CocoaPods的package打包Framework以及使用注意


    参考文章
    封装framework 并支持pod 管理 (1)
    封装framework 并支持pod 管理 (2)-cocoapods-packager
    使用Cocoapods创建SDK,并生成Framework
    使用cocoapods创建framework组件
    Cocoapods私有库组件创建Framework
    坑: iOS打包framework通过pod方式给别人用
    iOS Xcode Framework 私有pod
    iOS开发之CocoaPods:进阶篇 搭建私有库

    相关文章

      网友评论

        本文标题:Cocoapods组件私有库创建Framework

        本文链接:https://www.haomeiwen.com/subject/jjeowrtx.html