• cocoapods应用第一部分-xcode创建.framework相关


    问题的提出:
    随着项目的越来越大,可能会出现好几个团队共同维护一个项目的情况,比如:项目组A负责当中的A块,项目组B负责当中的B块.....这几块彼此之间既独立,也相互联系.对于这样的情况,能够採用约定的方式,比方,你仅仅改动你那块,不要改动公共的.假设要改动公共的,那么必需要通知一下其他组,大家共同决定怎么改动,这样的方式有一个非常大的问题,非常有可能不经意间就改了别的团队的代码.还有维护的越来越复杂等.
    诸如此类的问题,非常自然的我们会考虑每一个团队建立一个静态库
     IOS的静态库有两种,.a和.framework,  动态库.framework居多.   静态库建议也生成.framework模式的,优点是.framework包括了相关的.h文件等..a文件还要自己加入相关的.h文件
       静态库:链接时,静态库会被完整地拷贝到可运行文件里。被多次使用就有多份冗余拷贝.比如我们在我们的程序中使用了百度地图的.a文件,另外一个应用也使用了百度地图.a.这样整个系统中,会出现两个 百度地图.a文件
       动态库:链接时不复制,程序执行时由系统动态载入到内存,供程序调用,系统仅仅载入一次,多个程序共用。节省内存.系统提供的库基本上都属于此类,比如UIKit等,A应用和B应用中都用到了UIKit,系统仅仅载入了一份在内存中.IOS中对于第三方的动态库,非常遗憾,眼下还不支持的.
    一:framework的制作
       从xcode6開始,已经提供了制作.framework的选项了
    以下我们用系统自带的来新建.framework.然后再加入一个依赖库 AFNetworking
    1) xcode的菜单条  File -> New Project  建立一个名为  YohunlUtilsLib 的Cocoa Touch Framework的project. 将Target 改为 7.0(因为如今大多数应用都还要支持7.0sdk,故此处我们改动为支持7.0)

    这时候,编译一下,你可能会遇到警告  

              (null): Embedded dylibs/frameworks only run on iOS 8 or later

    别着急,这个是因为 从IOS8開始,建立的framework可以是动态的(并非全然意义上的动态,这里的动态,事实上还是要嵌入到我们的应用中,而不可以从网上下载,然后用dlopen动态载入的).

    我们要改动 Mach-O Type.从默认的Dynamic Library 改为 Static Library,再编译,警告消失


    那么选择 Dynamic Library 还是   Static Library 有什么影响呢? 我已经实际的检验过了.(我採用了一个包括了 第三方库 AFnetworking的測试project)

      Static Library 支持IOS8.0 sdk下面的,从眼下来看,大多数project都还要支持7.0 sdk,所以我们最经常使用的就是Static Library  
    当我们使用   Static Library时候,生成的framework直接如同加入普通文件的形式加入进来就能够了.它会自己主动在




    只是当我们执行的时候,会提示:
    当生成后,加入到演示样例project中,



    好吧,这样的模式的加入,看来有些问题呀,还要自己加入依赖库,这些依赖库都是系统的,依据提示自己加入就能够了
    再执行,OK



    当我们使用 Dynamic Library模式(仅仅有IOS8.0及以上才支持)的时候.如同普通文件一样加入到演示样例project中去的话,执行,会出现提示:
    dyld: Library not loaded: @rpath/NetTestLib.framework/NetTestLib
      Referenced from: /Users/yohunl/Library/Developer/CoreSimulator/Devices/B1DBCA26-C113-4C74-BB81-297D4AF1E0C8/data/Containers/Bundle/Application/C1B4F6D5-96FD-4245-8E6D-4F1C569EEF6F/TestFramework.app/TestFramework
      Reason: image not found



    解决的方式 
    在project的配置  Embedded Binaries以下加入.而不是在 Linked Frameworks and Libraries下加入.这样的方式,不须要加入 AFNetworking所须要的系统库,这一点不知道是什么原因!!!假设有知道原因的,请也告知我一下啊


    再执行,OK


    2)  命令行,进入文件夹下  pod init 建立一个podfile文件,由于我们制作的.framework须要用到AFNetworking网络库 PS:你也能够用随意的方式建立这个podfile文件
        打开它,由于我採用 pod init命令建立的,打开后你会发现它已经有内容了

    改动其内容为
                       platform :ios, '7.0'
                       inhibit_all_warnings!

                      target 'YohunlUtilsLib' do
                            pod 'AFNetworking'
                      end

                      target 'YohunlUtilsLibTests' do
                      end

    再运行 pod install 建立依赖
    打开project,加入一个文件  YONetwork.h,在当中加入方法
    @interfaceYONetwork :NSObject
    /**
     * 
    获取github上用户的repo
     *
     * 
    @paramuser   username
     * 
    @paramsuccess成功的回调
     * 
    @paramfailure失败的回调
     */

    - (
    void)getGithubReposForUser:(NSString*)user withSuccess:(void(^)(idresponseObject))success failure:(void(^)(NSError*error))failure;


    /**
     * 
    測试 getGithubReposForUser:withSuccess:failure
     */

    - (
    void)test;
    @end
    #import"YONetwork.h"
    #import
    "AFNetworking.h"
    @implementationYONetwork
    - (
    void)getGithubReposForUser:(NSString*)user withSuccess:(void(^)(idresponseObject))success failure:(void(^)(NSError*error))failure
    {
       
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManagermanager];
        [manager
    GET:[NSStringstringWithFormat:@"https://api.github.com/users/%@/repos", user] parameters:nilsuccess:^(AFHTTPRequestOperation*operation,id responseObject) {
            success(responseObject);
        }
    failure:^(AFHTTPRequestOperation*operation,NSError*error) {
            failure(error);
        }];
    }


    - (
    void) test {
        [
    selfgetGithubReposForUser:@"yohunl"withSuccess:^(idresponseObject) {
           
    NSLog(@"getGithubReposForUser response = %@",responseObject);
        }
    failure:^(NSError*error) {
           
    NSLog(@"getGithubReposForUser error = %@",error);
        }];
    }
    @end


    编译执行 (command + B),生成对应的.framework文件 
    菜单 -  organizer 

    能够看到文件夹结构例如以下:

    当中的 YohunlUtilsLib.framework 就是我们要的  : 注意,YohunlUtilsLib.framework中并没有包括AFNetworking库的内容,这一点我们能够用例如以下的命令来验证.
    命令进入 Debug-iphoneos
    $ lipo -info YohunlUtilsLib.framework/YohunlUtilsLib
    输出
    Architectures in the fat file: YohunlUtilsLib.framework/YohunlUtilsLib are: armv7 arm64
    说明我们生成的真机framework:YohunlUtilsLib.framework 包括了两种架构 armv7 arm64
    分离出每一种架构
    $ mkdir armV7  当前文件夹建立文件夹,用于存放分离后的架构,和分离出的.o文件
    $ lipo YohunlUtilsLib.framework/YohunlUtilsLib -thin armv7 -output ./armv7/YohunlUtilsLib_armv7  分离出armv7架构到目录armV7下
    $ cd armV7 进入目录
    $ ar -x YohunlUtilsLib_armv7  分离出armv7架构的全部的.o文件
    分离后,如图:

    能够看到,最后的.framework中,并没有包括我们pod加入的 AFNetworking.所以 当我们把我们生成的YohunlUtilsLib.framework给别人使用过的时候,别人自己要在项目中加入 AFNetworking,否则会提示找不到的错误. 
     验证的方式能够參见 http://jiapumin.iteye.com/blog/2119102  主要是利用命令   

    3) 我们使用命令来合并我们生成的真机和模拟器的framework
    建立一个新的target


    target建立后

    加入例如以下的合并模拟器和真机的脚本

    # Constants
    SF_TARGET_NAME=${PROJECT_NAME}
    #自己定义的用来存放最后合并的framework
    UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal



    #IPHONE_DEVICE_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos

    WORKSPACE_NAME=${PROJECT_NAME}.xcworkspace
    YO_SCHEME=${PROJECT_NAME}

    #clean build是先清除原来的build
    xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${YO_SCHEME} -sdk iphonesimulator -configuration
    "${CONFIGURATION}"clean build
    xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${YO_SCHEME} -sdk iphoneos -configuration
    "${CONFIGURATION}"clean build

    # build project
    #xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/arm64" SYMROOT="${SYMROOT}" ARCHS='arm64' VALID_ARCHS='arm64' $ACTION

    #xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"  CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/armv7" SYMROOT="${SYMROOT}" ARCHS='armv7 armv7s' VALID_ARCHS='armv7 armv7s' $ACTION

    # Copy the framework structure to the universal folder (clean it first)
    #由于framework的合并,lipo仅仅是合并了最后的二进制可运行文件,所以其他的须要我们自己复制过来
    #先移除原来的
    rm -rf
    "${UNIVERSAL_OUTPUTFOLDER}"
    mkdir -p
    "${UNIVERSAL_OUTPUTFOLDER}"
    cp -R
    "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"

    #合并模拟器和真机的架构
    lipo -create 
    "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}""${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"-output"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"

    open
    "${UNIVERSAL_OUTPUTFOLDER}"







    对于以上的脚本,当中用到了非常多的 xcode提前定义的变量,这些变量怎么来的呢?你能够在命令行下, 输入
    xcodebuild -workspace YohunlUtilsLib.xcworkspace -scheme YohunlUtilsLib -sdk iphonesimulator -configuration Debug -showBuildSettings > xcodebuild_showBuildSettings.txt
    来将全部的xcode提前定义变量都导入到文本xcodebuild_showBuildSettings.txt 中,然后你就能够选用你须要的啦

    当然了,我们一般都应该合并release模式的,而不是debug模式的framework,这个能够在



    ccmmand+B 编译
    假设不出错的话,应该会弹出


    到此处,我们的framework建立好了,以下能够建立一个測试project来測试一下,能否够了

    4)建立一个single View Application的測试上述framework的project TestFrameworkDemo
    将上一步生成的 Release-universal/YohunlUtilsLib.framework 增加到project TestFrameworkDemo
    再写一个測试用例:


    执行,这时候,你会收到错误提示

    还记得前面说过吧,我们打包的framework并不包括
    此时,我们有两种方式解决问题:
     1. 将我们生成 YohunlUtilsLib.framework 过程中生成的libAFNetworking.a 拷贝过来,加入到project中(当然了,你要自己合并 libAFNetworking的真机和模拟器的.a文件) [这样的方式的优点是能够保证我们的YohunlUtilsLib.framework使用到的libAFNetworking和我们一样的版本号,保证了兼容性,,但同一时候也添加了集成的复杂性,我们要申明我们的framework用到了哪些第三方和第三方的版本号信息]
    2.在TestFrameworkDemo project中,添加 podFile文件,在当中添加 依赖  pod 'AFNetworking'
      又一次pod install一下 [推荐这样的方式,由于,我们用到的第三方都能够使用pod管理,方便],以下就以这样的方法来说明


    执行,OK!!!

    二:使用 pod 的命令  pod lib create 来创建 使用pod的framework
    採用cocoapods自带的命令,比較方便的http://guides.cocoapods.org/making/using-pod-lib-create   比如  pod lib create BZLib.能够自带demo的
    命令例如以下   pod lib create YohunlUtilsPod
    注意:各个版本号的cocoapods生成的演示样例project结构什么的,会有点不一样,比方最新的带有demo的生成的libproject就本身就是target的名字,可是之前版本号target的名字是 名字_example

    pod lib create project名  使会让你确认4个问题,由此来建立project,4个问题都是非常easy的,你能够自行选择

      



    注意到了没?这里我们的 YohunlUtilsPod 文件夹下,并没有podfile文件,那么我们建立的库要怎么依赖第三方的啊.这里就是 YohunlUtilsPod.podspec 文件出场了,在这个文件里,能够制定我们生成的framework依赖于什么.有关于spec文件,是重要文件,原则上,仅仅要我们把这个文件交给别人,别人就能够加入我们的lib到project里了


    编辑YohunlUtilsPod.podspec 文件(此文件实际上是 ruby格式的,假设你用ruby相关的编辑器打开,就能高亮显示了),改动内容为
    Pod::Spec.new do |s|
      s.name             = "YohunlUtilsPod"
      s.version          = "1.0.0"
      s.summary          = "
    測试pod生成frameworkYohunlUtilsPod."

      s.description      = "
    測试用的,我们用来測试使用pod lib create 生成的frameworkproject"

      s.homepage         = "https://github.com/yohunl/YohunlUtilsPod"
      # s.screenshots     = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
      s.license          = 'MIT'
      s.author           = { "yohunl" => "yohunl@163.com" }
      s.source           = { :git => "https://github.com/yohunl/YohunlUtilsPod.git", :tag => s.version.to_s }

      # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

      s.platform     = :ios, '7.0'
      s.requires_arc = true

      s.source_files = 'Pod/Classes/**/*'
      s.resource_bundles = {
        'YohunlUtilsPod' => ['Pod/Assets/*.png']
      }

      # s.public_header_files = 'Pod/Classes/**/*.h'
      # s.frameworks = 'UIKit', 'MapKit'
       s.dependency 'AFNetworking'
    end 
    验证podspec文件是否正确是使用命令  在podspec所在文件夹下运行  pod lib lint

    假设提示错误的话,它会给出具体的提示,你照着改动就好了,备注:我已经将源代码上传到了github上(你也能够上传你的私有gitserver,一般公司都应该有自己的gitserver)

    更改完后,在project中再增加  YONetwork.h和.YONetwork.m 

    再执行 pod install  
    假设提示 
    SZ-lingdaiping:Example yohunl$ pod install
    Updating local specs repositories
    Analyzing dependencies
    Fetching podspec for `YohunlUtilsPod` from `../`
    [!] Unable to satisfy the following requirements:

    - `YohunlUtilsPod (from `../`)` required by `Podfile`
    - `YohunlUtilsPod (from `../`)` required by `Podfile`
    - `YohunlUtilsPod (= 0.1.0)` required by `Podfile.lock`

    那么删掉  Podfile.lock文件,由于我们更改了podspec文件中的库的版本了

    看到没,是在 Development Pods目录下,由于并没有上传到官方去,所以,在此处是 私有的,所以在Development Pods目录下  .

    接下来,如同第一个一样,加入一个新的target,加入 run script脚本 ,执行它,得到  

    建立一个測试project

    注意上面图里面的文字,此处由于我们的frameworkproject採用dynamic 模式的(上文有论述!!!)  所以须要在Embedded Binaries下加入对应的库.至于为什么还要加入 AFNetworking.framework,上面也有论述,是由于我们打包的.framework并没有包括AFNetworking.framework,假设不加上,执行起来,还是要报错的哦

    好了,第一部分讲完了
    那么我们怎么使用 像我们使用其他开源库那样的,仅仅要在demoproject里加入一句
    pod ‘YohunlUtilsPod' 然后pod install一下就能够加入呢?(当然了,这样的方式,我们通常是直接源代码模式的framework加入demoproject)

    这就是第二部分要讲的.



    參考文档:







  • 相关阅读:
    laravel 控制器方法里存get值 和 blade 模板获得闪存值的方法
    获取对象中的值的方法
    python3 语法小结
    集合一些方法陷阱
    文件的读写操作
    字符编码
    数字,字符串,列表,元祖,字典,集合类型内置方法
    if判断,while循环,for循环
    交互,格式化输出,运算符,解压缩!
    python基础知识
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7199784.html
Copyright © 2020-2023  润新知