Swift/Objective-C-使用Cocoapods創(chuàng)建/管理私有庫(高級用法)

接著上篇文章"Swift/Objective-C-使用Cocoapods創(chuàng)建/管理私有庫(初中級用法)"的探索之路。

另外兩篇文章:
Swift/Objective-C-使用Cocoapods創(chuàng)建/管理公共庫
Swift/Objective-C-使用Cocoapods創(chuàng)建/管理私有庫(初中級用法)

  • 高級
  • 通過subspec創(chuàng)建子模塊(pod時可根據(jù)需要引入私有庫的某個或者某幾個模塊到項目中拳氢,用不到的模塊不引入);
  • 私有庫中ARC和MRC文件的配置哼拔;
  • 依賴自己其他的私有庫到當(dāng)前創(chuàng)建的私有庫中概行;
  • 添加第三方公共庫到私有庫中(兩種情況:含/不含動態(tài)(.framework)、靜態(tài)(.a)文件)儒鹿;
  • 私有庫中Swift和Objective-C混編化撕;


一、通過subspec創(chuàng)建子模塊约炎,及子模塊之間的引用

Subspecs是一種分解Podspec功能的方法植阴,它允許人們安裝庫的一個子集。也就是說圾浅,一個私有庫中掠手,包含很多模塊,有時我們只需要pod這個私有庫中的某個或者某些模塊狸捕,選擇性的使用喷鸽,并不是pod全部,這時我們就需要在私有庫中添加subspec灸拍,將各個模塊開放分解出來做祝,成為一個單獨的子模塊,以實現(xiàn)這樣的需求鸡岗』旎保或者私有庫中的某個模塊和某個模塊之間有引用關(guān)聯(lián),為了不影響其他模塊的使用和冗余轩性,也需要將這部分和其他模塊區(qū)分開声登,也需要添加subspec。
在添加subspec時需要我們在編碼的過程中盡量減少模塊之間的依賴揣苏,使各個模塊兒可以獨立運行悯嗓。

  • .podspec文件中添加子模塊(subspec),并設(shè)置子模塊鍵舒岸,配置如下:
Pod::Spec.new do |s|
  s.name             = 'JYPrivateLibTest0'
  s.version          = '1.0.1'
  s.summary          = '這是一個私有測試庫绅作!'

  s.homepage         = 'https://git.asd.net/pod/JYPrivateLibTest0'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'JYanshao' => '654565181@qq.com' }
  s.source           = { :git => 'https://git.asd.net/pod/JYPrivateLibTest0.git', :tag => s.version.to_s }

  s.ios.deployment_target = '8.0'
  s.requires_arc = true
  s.swift_version = '4.0'
  # s.source_files = 'JYPrivateLibTest0/Classes/**/*'

  # ------ 創(chuàng)建子模塊 ------
  s.subspec 'TextField' do |tf|  # tf為子模塊鍵
      tf.source_files = 'JYPrivateLibTest0/Classes/TextField/*'
      tf.dependency 'JYPrivateLibTest0/Constant'  # TextField模塊中文件使用了Constant模塊的東西,所以需要引入依賴蛾派。如果不寫依賴俄认,當(dāng)你只引入TextField模塊的時候,就會報錯洪乍,由于找不到Constant模塊中你使用的東西眯杏。這里不可以直接引入主spec,即tf.dependency 'JYPrivateLibTest0'壳澳,因為cocospods不允許(podspec文件:[!子規(guī)范不能要求它的父規(guī)范岂贩。),且在實際項目中引入時引入不成功巷波,錯誤移步下邊萎津。
  end
  
  s.subspec 'Constant' do |c|  # c為子模塊鍵
      c.source_files = 'JYPrivateLibTest0/Classes/Constant/*'
  end
   
end

在上面的例子中卸伞,一個工程中,有多個模塊锉屈,并把各模塊分解為子模塊荤傲,使用 pod 'JYPrivateLibTest0' 的Podfile會包含整個庫,而 pod 'JYPrivateLibTest0/Constant' 會只包含Constant模塊颈渊。只引入你的項目中需要的模塊遂黍,其他不需要的可以不引入。

  • 問題:tf.dependency 'JYPrivateLibTest0/Constant' TextField模塊中文件使用了Contants模塊的東西俊嗽,子模塊的依賴不能直接依賴父spec雾家,如tf.dependency 'JYPrivateLibTest0', 這樣cocospods是不允許,你pod的時候也不會pod成功绍豁,錯誤如下:
Analyzing dependencies
Fetching podspec for `JYPrivateLibTest0 ` from `../`
[!] Failed to load 'JYPrivateLibTest0' podspec: 
[!] Invalid `JYPrivateLibTest0.podspec` file: [!] A subspec can't require one of its parents specifications.

 #  from /Users/123456/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0.podspec:49
 #  -------------------------------------------
 #      tf.source_files = 'JYPrivateLibTest0/Classes/TextField/*'
 >      tf.dependency 'JYPrivateLibTest0'
 #    end
 #  -------------------------------------------

解釋:[!]加載“ JYPrivateLibTest0”podspec失敗:
[! JYPrivateLibTest0]無效”芯咧。podspec文件:[!子規(guī)范不能要求它的父規(guī)范。
也就是說:同一工程中一子模塊使用了另一子模塊的東西妹田,需要引入對另一子模塊的依賴唬党,且另一子模塊也必須為subspec,不能直接依賴父spec鬼佣。

二驶拱、私有庫中ARC(自動內(nèi)存管理)和MRC(手動內(nèi)存管理)文件的配置

我這里找到一個使用Objective-C寫的Base64加密的封裝(Base64.h/Base64.m),且為MRC(手動內(nèi)存管理)晶衷。下面讓我們看一下如何來區(qū)別對待MRC和ARC文件吧蓝纲,即如何讓Cocoapods自動給MRC的文件添加-fno-objc-arc標(biāo)識,使MRC和ARC共存晌纫。

  • 方法一:在.podspec文件中税迷,先將整個子模塊設(shè)置為MRC,即ocb.requires_arc = false锹漱,再通過requires_arc設(shè)置ARC文件箭养,具體如下:(官方推薦
Pod::Spec.new do |s|
    ...
    // 此處省略一些不便的配置
    ...

    s.subspec 'OCBase64' do |ocb|
        ocb.requires_arc = false
        ocb.requires_arc = ['JYPrivateLibTest0/Classes/OCBase64/*.{h,m}']
    end
end
  • 方法二:在.podspec文件中,先將子整個模塊設(shè)置為ARC哥牍,即ocb.requires_arc = true毕泌,然后再通過exclude_filessubspec設(shè)置MRC文件嗅辣,具體如下:
Pod::Spec.new do |s|
    ...
    // 此處省略一些不便的配置
    ...

    s.subspec 'OCBase64' do |ocb|
        ocb.requires_arc = true # 如果其他地方已經(jīng)寫了這句撼泛,可省略;或者直接省略也可
        ocb.source_files = 'JYPrivateLibTest0/Classes/OCBase64/*'
      
        non_arc_files = 'JYPrivateLibTest0/Classes/OCBase64/Base64/*.{h,m}'
        ocb.exclude_files = non_arc_files # 排除MRC文件
        ocb.subspec 'no-arc' do |dd|
            dd.source_files = non_arc_files
            dd.requires_arc = false
        end
    end
end

這兩種配置方法的區(qū)別就是:
方法一澡谭,在項目中拉取私有庫的時候愿题,不會自動創(chuàng)建一個包含MRC文件的文件夾,看起來代碼比較整齊。
方法二潘酗,在項目中拉取私有庫的時候杆兵,會自動創(chuàng)建一個包含MRC文件的文件夾。

三仔夺、私有庫中依賴其他私有庫
  • 私有庫中依賴其他的私有庫
    這里以TESTRely私有庫為例拧咳,該私有庫中除了自己的封裝還依賴了公共庫AFNetworking。
  1. 將自己使用了TESTRely私有庫的源代碼封裝文件囚灼,添加到Classes文件夾目錄下,步驟參考上邊的步驟祭衩;

  2. 配置.podspec文件灶体,參數(shù)如下:(這里都是以子模塊的形式添加的)

Pod::Spec.new do |s|
  ...
  // 這里省略沒改變的配置
  ...

  s.subspec 'TestController' do |tc|
        tc.source_files = 'JYPrivateLibTest0/Classes/TestController/*'
        tc.dependency 'TESTRely', '~>0.0.6'  # 依賴TESTRely私有庫
  end

end
  1. 配置demo工程的Podfile文件,通過source添加TESTRely私有庫對應(yīng)的索引庫地址和TESTRely依賴的公共庫AFNetworking對應(yīng)的索引庫地址掐暮,如下:
source 'https://git.asd.net/pod/JYPrivateRepoTest0.git'  # JYPrivateRepoTest0對應(yīng)的私有索引庫地址
source 'https://git.asd.net/CocoaPods/TESTRelyLibrary.git'  # TESTRely對應(yīng)的私有索引庫地址
source 'https://github.com/CocoaPods/Specs.git'  # 官方公共庫對應(yīng)的公共索引庫地址

注意:在項目中使用私有庫蝎抽,這個私有庫又中的封裝又依賴其他私有庫或公共庫,則項目的Podfile文件中路克,需要將該私有庫樟结,以及其依賴的其他私有庫或公共庫的索引庫地址都添加到Podfile文件中,否則會報錯精算,找不到依賴的其他私有庫或公共庫瓢宦。
pod install時錯誤如下:

Analyzing dependencies
[!] Unable to find a specification for `TESTRely (~> 0.0.6)` depended upon by `JYPrivateLibTest0/TestController`

You have either:
 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
 * mistyped the name or version.
 * not added the source repo that hosts the Podspec to your Podfile.

Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.
  1. 驗證本地的.podspec文件,命令如下:
$ pod lib lint --sources=https://git.asd.net/pod/TESTRelyLibrary.git,https://github.com/CocoaPods/Specs.git --allow-warnings

Cloning spec repo `asd-pod-testrelylibrary` from `https://git.asd.net/pod/TESTRelyLibrary.git`
 -> JYPrivateLibTest0 (1.0.2)
    - NOTE  | [JYPrivateLibTest0/TextField, JYPrivateLibTest0/Constant, JYPrivateLibTest0/NetworkService, and more...] xcodebuild:  note: Using new build system
    - NOTE  | [JYPrivateLibTest0/TextField, JYPrivateLibTest0/Constant, JYPrivateLibTest0/NetworkService, and more...] xcodebuild:  note: Planning build
    - NOTE  | [JYPrivateLibTest0/TextField, JYPrivateLibTest0/Constant, JYPrivateLibTest0/NetworkService, and more...] xcodebuild:  note: Constructing build description
    - NOTE  | [JYPrivateLibTest0/TextField, JYPrivateLibTest0/Constant, JYPrivateLibTest0/NetworkService, and more...] xcodebuild:  warning: Skipping code signing because the target does not have an Info.plist file. (in target 'App')

JYPrivateLibTest0 passed validation.

注意:這里驗證命令不能直接使用$ pod lib lint灰羽,這樣會報找不到該私有庫中依賴的其他私有庫驮履,導(dǎo)致驗證通不過,后邊必須通過--sources命令添加其他私有庫和公共庫的索引庫地址廉嚼,且用“,”隔開玫镐,如:$ pod lib lint --sources=https://git.asd.net/pod/TESTRelyLibrary.git,https://github.com/CocoaPods/Specs.git。運行pod sepc lint怠噪、pod repo push [REPO] [NAME.podspec]命令時恐似,也需要通過--sources命令添加其他私有庫和公共庫的索引庫地址,否則也會驗證通不過傍念。

驗證不通過矫夷,錯誤信息如下:

$ pod lib lint

 -> JYPrivateLibTest0 (1.0.2)
    - ERROR | [iOS] unknown: Encountered an unknown error (Unable to find a specification for `TESTRely (~> 0.0.6)` depended upon by `JYPrivateLibTest0/TestController`

You have either:
 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
 * mistyped the name or version.
 * not added the source repo that hosts the Podspec to your Podfile.

Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.
) during validation.

[!] JYPrivateLibTest0 did not pass validation, due to 1 error.
You can use the `--no-clean` option to inspect any issue.
  1. 運行g(shù)it命令,提交修改到遠(yuǎn)程端私有代碼庫捂寿;

  2. 驗證遠(yuǎn)程端.podspec文件口四,命令:

$ pod spec lint --sources=https://git.asd.net/pod/TESTRelyLibrary.git,https://github.com/CocoaPods/Specs.git --allow-warnings
  1. 將.podspec文件提交到遠(yuǎn)程端私有索引庫,命令:
$ pod repo push JYPrivateRepoTest0 JYPrivateLibTest0.podspec --sources=https://git.asd.net/pod/TESTRelyLibrary.git,https://github.com/CocoaPods/Specs.git --allow-warnings
  1. 項目中驗證秦陋,注意別忘了通過source引入私有庫對應(yīng)的私有索引庫地址蔓彩。
四、私有庫中依賴第三方公共庫

私有庫中引入Cocoapods中的公共庫,包含兩種情況赤嚼。
1. 引入的公共庫中不包含動態(tài)文件(.framework)旷赖、靜態(tài)文件(.a)
在制作我自己私有Pod時,我們往往需要用到第三方提供的工具包更卒,比如說網(wǎng)絡(luò)請求Alamofire等孵、圖片加載SDWebImage等,對于這些只有源代碼文件的框架的使用是很簡單的蹂空,我們在制作Pod的時候俯萌,只需要在.podspec文件中直接通過s.dependency引入即可,如:s.dependency 'Alamofire', '~> 4.8.1'上枕。添加咐熙、驗證、上傳步驟請參考上邊辨萍。

具體配置信息如下:

Pod::Spec.new do |s|
   ...
   // 這里省略沒改變的配置
   ...

   s.subspec 'NetworkService' do |ns|
      ns.source_files = 'JYPrivateLibTest0/Classes/NetworkService/*'
      ns.dependency 'Alamofire', '~> 4.8.1'
   end
end

當(dāng)執(zhí)行pod install命令時棋恼,Pod會自己檢測并且install我所引用到的第三方倉庫。

2. 引入的公共庫中包含動態(tài)文件(.framework)锈玉、靜態(tài)文件(.a)
有時呢爪飘,我們也會用到諸如ShareSDK分享、高德地圖等制作成動態(tài)庫(framework)拉背、靜態(tài)庫(library/.a)方式的第三方庫师崎,其中有些庫是給你提供了Pod方式導(dǎo)入的,有些沒有提供去团。下面讓我們都試試吧抡诞。
這里以ShareSDK為例。
1). 提供了Pod方式導(dǎo)入的土陪,可能你會想到直接通過dependency依賴昼汗,如下:

Pod::Spec.new do |s|
  ...
  // 這里省略沒改變的配置
  ...

  s.static_framework = true # 是否包含靜態(tài)庫框架(注意:不能寫在subspec子模塊中)
  
  s.subspec 'ShareService' do |ss|
        ss.dependency 'mob_sharesdk', '~>4.2.3'
        ss.dependency 'mob_sharesdk/ShareSDKPlatforms/QQ', '~>4.2.3'
        ss.dependency 'mob_sharesdk/ShareSDKPlatforms/SinaWeibo', '~>4.2.3'
        ss.dependency 'mob_sharesdk/ShareSDKPlatforms/WeChat', '~>4.2.3'
        ss.dependency 'mob_sharesdk/ShareSDKUI', '~>4.2.3'
        ss.dependency 'mob_sharesdk/ShareSDKExtension', '~>4.2.3'
  end
end

這樣引入是沒問題的,可以通過pod lib lint鬼雀、pod sepc lint命令的驗證顷窒,提交到遠(yuǎn)程端的私有代碼庫。在項目中測試源哩,是沒有問題的鞋吉,可以引入和使用,如下圖:

第三方庫頭文件引入.png

遇到的錯誤:
如果你在pod lib lint驗證時励烦,遇到如下錯誤谓着,導(dǎo)致驗證不通過,說明你沒有配置s.static_framework = true坛掠,因為你使用了動態(tài)庫(.framework)赊锚、靜態(tài)庫(.a)治筒,如果use_frameworks!指定時,pod應(yīng)包含靜態(tài)庫框架舷蒲,所以需要允許靜態(tài)庫的使用耸袜。錯誤信息如下:

$ pod lib lint JYPrivateLibTest0.podspec

 -> JYPrivateLibTest0 (1.0.4)
    - ERROR | [iOS] unknown: Encountered an unknown error (The 'Pods-App' target has transitive dependencies that include static binaries: (/private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/ShareSDK.framework, /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/Required/ShareSDKConnector.framework, /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/Optional/ShareSDKExtension.framework, /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/PlatformSDK/QQSDK/TencentOpenAPI.framework, /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/PlatformConnector/QQConnector.framework, /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/PlatformSDK/SinaWeiboSDK/libWeiboSDK.a, /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/PlatformConnector/SinaWeiboConnector.framework, /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/PlatformSDK/WeChatSDK/libWeChatSDK.a, /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/PlatformConnector/WechatConnector.framework, and /private/var/folders/qt/d9rd9h7n2m3cb9014qph7xkm0000gn/T/CocoaPods-Lint-20190320-5532-92gozf-JYPrivateLibTest0/Pods/mob_sharesdk/ShareSDK/Support/Optional/ShareSDKUI.framework)) during validation.

[!] JYPrivateLibTest0 did not pass validation, due to 1 error.
You can use the `--no-clean` option to inspect any issue.

以上錯誤信息解讀:在驗證過程中,遇到一個未知的錯誤(' podcast - app '目標(biāo)有傳遞依賴關(guān)系牲平,包括動靜態(tài)二進(jìn)制文件堤框。

2). 這種不管能不能pod導(dǎo)入,都要下載你需要的SDK包纵柿,手動導(dǎo)入蜈抓。以ShareSDK為例,首先在ShareSDK官網(wǎng)下載你所需要的ShareSDK包昂儒,然后將下載的ShareSDK包资昧,導(dǎo)入到你的私有庫的Classes文件夾下,再然后配置你的.podspec文件荆忍。(這里僅僅是導(dǎo)入第三方庫,不包含其他文件)
.podspec文件配置如下:

Pod::Spec.new do |s|
  ...
  // 這里省略沒改變的配置
  ...

  # 是否包含靜態(tài)庫框架(注意:不能寫在subspec子模塊中)
  s.static_framework = true  
  
  s.subspec 'ShareService' do |ss|
          # 文件的路徑和公開頭文件路徑
          #ss.source_files = 'JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/**/*.framework/Headers/*.h'
          #ss.public_header_files = 'JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/**/*.framework/Headers/*.h'

          # ShareSDK的所有動態(tài)庫路徑(也可以寫具體的路徑撤缴,ShareSDK的framework太多了刹枉,偷懶一下)
          ss.vendored_frameworks = 'JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/**/*.framework'
          # 第三方的靜態(tài)文件路徑
          ss.vendored_libraries = 'JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/Support/PlatformSDK/**/*.a'
          # 第三方的資源文件
          ss.resources = 'JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/Support/**/*.bundle'
         
          # 第三方用到的系統(tǒng)動態(tài)庫
          ss.frameworks = 'UIKit', 'JavaScriptCore', 'ImageIO'
          # 第三方用到的系統(tǒng)靜態(tài)文件(前面的lib要去掉,否則會報錯)
          ss.libraries = 'icucore', 'z', 'c++', 'sqlite3'
        
          # Build Settings里邊的設(shè)置
          ss.pod_target_xcconfig = {
              #'FRAMEWORK_SEARCH_PATHS' => '${PODS_ROOT}/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK',
              'HEADER_SEARCH_PATHS' => '$(PODS_ROOT)/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/**/*.framework/Headers',
              'LD_RUNPATH_SEARCH_PATHS' => '$(PODS_ROOT)/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/',
              'OTHER_LDFLAGS' => ['-ObjC']
          }
  end
end

將修改提交到遠(yuǎn)程端私有代碼庫屈呕,通過pod lib lint微宝、pod sepc lint命令驗證,并提交到遠(yuǎn)程端的私有代碼庫虎眨。
注意:s.static_framework = true 必須和s.name同級蟋软,不能寫在s.subspec子模塊中,否則回報錯誤嗽桩。

遇到的問題:
demo工程pod install后岳守,編譯運行,以及pod lib lint驗證時都會報以下錯誤碌冶,錯誤信息如下:

編譯運行demo報錯.png

$ pod lib lint --sources=https://git.asd.net/pod/TESTRelyLibrary.git,https://github.com/CocoaPods/Specs.git --allow-warnings

 -> JYPrivateLibTest0 (1.0.5)
    - ERROR | [iOS] xcodebuild: Returned an unsuccessful exit code. You can use `--verbose` for more information.
    - NOTE  | [JYPrivateLibTest0/Constant, JYPrivateLibTest0/TextField, JYPrivateLibTest0/NetworkService, and more...] xcodebuild:  note: Using new build system
    - NOTE  | [JYPrivateLibTest0/Constant, JYPrivateLibTest0/TextField, JYPrivateLibTest0/NetworkService, and more...] xcodebuild:  note: Planning build
    - NOTE  | [JYPrivateLibTest0/Constant, JYPrivateLibTest0/TextField, JYPrivateLibTest0/NetworkService, and more...] xcodebuild:  note: Constructing build description
    - NOTE  | [JYPrivateLibTest0/Constant, JYPrivateLibTest0/TextField, JYPrivateLibTest0/NetworkService, and more...] xcodebuild:  warning: Skipping code signing because the target does not have an Info.plist file. (in target 'App')
    - NOTE  | xcodebuild:  <module-includes>:1:9: note: in file included from <module-includes>:1:
    - NOTE  | [iOS] xcodebuild:  //privateTarget Support Files/JYPrivateLibTest0/JYPrivateLibTest0-umbrella.h:45:9: note: in file included from //privateTarget Support Files/JYPrivateLibTest0/JYPrivateLibTest0-umbrella.h:45:
    - ERROR | [iOS] xcodebuild:  /Users/123/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/Required/MOBFoundation.framework/Headers/MOBFOAuthService.h:9:9: error: include of non-modular header inside framework module 'JYPrivateLibTest0.MOBFOAuthService': '/Users/123/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/Required/MOBFoundation.framework/Headers/MOBFoundation.h'
    - NOTE  | [iOS] xcodebuild:  //privateTarget Support Files/JYPrivateLibTest0/JYPrivateLibTest0-umbrella.h:64:9: note: in file included from //privateTarget Support Files/JYPrivateLibTest0/JYPrivateLibTest0-umbrella.h:64:
    - ERROR | [iOS] xcodebuild:  /Users/123/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/ShareSDK.framework/Headers/ShareSDK+Base.h:9:9: error: include of non-modular header inside framework module 'JYPrivateLibTest0.ShareSDK_Base': '/Users/123/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/ShareSDK.framework/Headers/ShareSDK.h'
    - NOTE  | xcodebuild:  //privateTarget Support Files/JYPrivateLibTest0/JYPrivateLibTest0-umbrella.h:84:9: note: in file included from //privateTarget Support Files/JYPrivateLibTest0/JYPrivateLibTest0-umbrella.h:84:
    - ERROR | [iOS] xcodebuild:  /Users/123/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/Support/Optional/ShareSDKUI.framework/Headers/ShareSDKUI.h:13:9: error: include of non-modular header inside framework module 'JYPrivateLibTest0.ShareSDKUI': '/Users/123/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/Support/Optional/ShareSDKUI.framework/Headers/SSUIEditorConfiguration.h'
    - ERROR | [iOS] xcodebuild:  /Users/123/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/Support/Optional/ShareSDKUI.framework/Headers/ShareSDKUI.h:14:9: error: include of non-modular header inside framework module 'JYPrivateLibTest0.ShareSDKUI': '/Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/Support/Optional/ShareSDKUI.framework/Headers/SSUIShareSheetConfiguration.h'
    - ERROR | [iOS] xcodebuild:  /Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/Support/Optional/ShareSDKUI.framework/Headers/ShareSDKUI.h:15:9: error: include of non-modular header inside framework module 'JYPrivateLibTest0.ShareSDKUI': '/Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/Support/Optional/ShareSDKUI.framework/Headers/SSUIPlatformItem.h'
    - NOTE  | [iOS] xcodebuild:  <unknown>:0: error: could not build Objective-C module 'JYPrivateLibTest0'
    - WARN  | [JYPrivateLibTest0/TestController] xcodebuild:  /Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/TestController/JYFather.swift:9:8: warning: file 'JYFather.swift' is part of module 'JYPrivateLibTest0'; ignoring import
    - WARN  | [JYPrivateLibTest0/TestController, JYPrivateLibTest0/OCBase64, JYPrivateLibTest0/OCBase64/Base64, and more...] xcodebuild:  /Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/OCBase64/Base64/Base64.m:63:63: warning: implicit conversion loses integer precision: 'long long' to 'NSUInteger' (aka 'unsigned int') [-Wshorten-64-to-32]
    - WARN  | [JYPrivateLibTest0/TestController, JYPrivateLibTest0/OCBase64, JYPrivateLibTest0/OCBase64/Base64, and more...] xcodebuild:  /Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/OCBase64/Base64/Base64.m:91:25: warning: implicit conversion loses integer precision: 'long long' to 'NSUInteger' (aka 'unsigned int') [-Wshorten-64-to-32]
    - WARN  | [JYPrivateLibTest0/TestController, JYPrivateLibTest0/OCBase64, JYPrivateLibTest0/OCBase64/Base64, and more...] xcodebuild:  /Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/OCBase64/Base64/Base64.m:107:58: warning: implicit conversion loses integer precision: 'long long' to 'unsigned long' [-Wshorten-64-to-32]
    - WARN  | [JYPrivateLibTest0/TestController, JYPrivateLibTest0/OCBase64, JYPrivateLibTest0/OCBase64/Base64, and more...] xcodebuild:  /Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/OCBase64/Base64/Base64.m:147:44: warning: implicit conversion loses integer precision: 'long long' to 'unsigned long' [-Wshorten-64-to-32]
    - WARN  | [JYPrivateLibTest0/TestController, JYPrivateLibTest0/OCBase64, JYPrivateLibTest0/OCBase64/Base64, and more...] xcodebuild:  /Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/OCBase64/Base64/Base64.m:149:54: warning: implicit conversion loses integer precision: 'long long' to 'NSUInteger' (aka 'unsigned int') [-Wshorten-64-to-32]

[!] JYPrivateLibTest0 did not pass validation, due to 6 errors.
You can use the `--no-clean` option to inspect any issue.

上面信息的摘仁 :

 error: include of non-modular header inside framework module 'JYPrivateLibTest0.ShareSDK_Base': '/Users/asd/Desktop/PrivateRepository/JYPrivateLibTest0/JYPrivateLibTest0/Classes/ShareService/JYMobShareSDK/ShareSDK/ShareSDK.framework/Headers/ShareSDK.h'

要解決這個錯誤其實很簡單,只需要注釋掉或刪除掉ShareService子模塊中的ss.source_files和ss.public_header_files這兩個參數(shù)及配置即可扑庞。

那報這個錯誤是什么原因造成的呢譬重?
在創(chuàng)建Pod,且引入Objective-C語言開發(fā)的第三方公共庫供Swift使用時罐氨,我們并不需要創(chuàng)建xxx-Bridge-Header.h橋文件去引入Objective-C的頭文件臀规, 這個工作是交由xxx-umbrella.h文件完成,這個文件的其中一個作用:其實和xxx-Bridge-Header.h橋文件的作用基本相同栅隐,向外界暴露Objective-C的頭文件供Swift使用塔嬉,實現(xiàn)Swift和Objective-C的混編玩徊。當(dāng)你再次通過ss.source_files和ss.public_header_files暴露第三方公共的頭文件時會重復(fù)定義,所以需要注釋掉或刪除掉ss.source_files和ss.public_header_files這兩個參數(shù)及配置邑遏。讓我們試試能否成功吧佣赖,結(jié)果是肯定的。

  • 優(yōu)化(僅限手動導(dǎo)入的第三方)
    通過以上的第三方公庫的導(dǎo)入已經(jīng)是可以使用了记盒。但是呢憎蛤,你可能會想到如果你的項目主要是采用Swift語言來寫的,那么你就必須要創(chuàng)建xxx-Bridge-Heder.h橋文件來引入Objective-C的頭文件纪吮,那有沒有一種方式是可以不需要創(chuàng)建xxx-Bridge-Header.h橋文件的呢俩檬?

為了使你更好的了解,在這里我新創(chuàng)建了一個私有代碼庫JYPLibTest1碾盟,且使用百度地圖Lib來演示棚辽,然后通過subspec在.podsepc中創(chuàng)建百度地圖的子模塊JYBaiDuMapKit(子模塊文件夾名字,可隨意缺取)屈藐。目錄如下:

百度地圖Lib目錄結(jié)構(gòu).png

解決方案:讓我們來優(yōu)化一下吧,這里我將創(chuàng)建一個.modulemap文件來解決這個問題熙尉,讓我們修改.podspec联逻,為所引用到的framework創(chuàng)建Module

注意:如果我們手動創(chuàng)建一個. modulemap文件检痰,然后直接將該文件拖到相應(yīng)的目錄下包归,這樣在 pod install 時可能會導(dǎo)致丟失該文件,那么我們應(yīng)該怎么辦呢铅歼?解決辦法是公壤,我們需要使用prepare_command屬性,來幫助我們自動創(chuàng)建.modulemap文件椎椰。

prepare_command屬性的解釋厦幅、使用場景及禁用條件:
prepare_command屬性是下載Pod后將執(zhí)行的bash腳本。此命令可用于創(chuàng)建慨飘、刪除和修改下載的任何文件慨削,并將在收集規(guī)范的其他文件屬性的任何路徑之前運行。
此命令在清理Pod和創(chuàng)建Pods項目之前執(zhí)行套媚。工作目錄是Pod的根目錄缚态。
prepare_command屬性必須在主模塊中使用。
如果pod安裝了:path選項堤瘤,則不會執(zhí)行此命令玫芦。

具體配置如下:

Pod::Spec.new do |s|
  s.name             = 'JYPLibTest1'
  s.version          = '1.0.0'
  s.summary          = '另一個測試私有庫'
  s.homepage         = 'https://git.artron.net/CocoaPods/JYPLibTest1'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'JYanshao' => '654565181@qq.com' }
  s.source           = { :git => 'https://git.123.net/CocoaPods/JYPLibTest1.git', :tag => s.version.to_s }
  s.ios.deployment_target = '8.0'
  s.source_files = 'JYPLibTest1/Classes/**/*.swift'
  s.swift_version = '4.2'
  
  s.subspec 'JYBaiDuMapKit' do |mk|
      
      mk.vendored_frameworks =  'JYPLibTest1/Classes/JYBaiDuMapKit/*.framework'
      mk.vendored_libraries = 'JYPLibTest1/Classes/JYBaiDuMapKit/thirdlibs/*.a'

      mk.resources = 'JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Map.framework/mapapi.bundle'
      
      mk.frameworks   =  'CoreLocation', 'QuartzCore', 'OpenGLES', 'SystemConfiguration', 'CoreGraphics', 'Security', 'CoreTelephony'
      mk.libraries    = 'sqlite3', 'c++'
      
      mk.preserve_paths = 'JYPLibTest1/Classes/JYBaiDuMapKit/*.framework', 'JYPLibTest1/Classes/JYBaiDuMapKit/thirdlibs/*.a'

      mk.pod_target_xcconfig = {
          'HEADER_SEARCH_PATHS' => '$(PODS_ROOT)/JYPLibTest1/Classes/JYBaiDuMapKit/*.framework/Headers',
          'LD_RUNPATH_SEARCH_PATHS' => '$(PODS_ROOT)/JYPLibTest1/Classes/JYBaiDuMapKit/',
          'OTHER_LDFLAGS' => '-ObjC'
      }
  end
  
  # prepare_command屬性必須在主模塊中使用
  s.prepare_command = <<-EOF
      
      # 創(chuàng)建BaiduMapAPI_Base Module
      rm -rf JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Base.framework/Modules
      mkdir JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Base.framework/Modules
      touch JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Base.framework/Modules/module.modulemap
      cat <<-EOF > JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Base.framework/Modules/module.modulemap
      framework module BaiduMapAPI_Base {
          umbrella header "BMKBaseComponent.h"
          export *
          link "sqlite3"
          link "c++"
      }
      \EOF
      
      # 創(chuàng)建BaiduMapAPI_Map Module
      rm -rf JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Map.framework/Modules
      mkdir JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Map.framework/Modules
      touch JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Map.framework/Modules/module.modulemap
      cat <<-EOF > JYPLibTest1/Classes/JYBaiDuMapKit/BaiduMapAPI_Map.framework/Modules/module.modulemap
      framework module BaiduMapAPI_Map {
          umbrella header "BMKMapComponent.h"
          export *
          link "sqlite3"
          link "c++"
      }
      \EOF
      
  EOF
  
end

配置完成,讓我們更新一下demo工程本辐,測試一下是否可以使用桥帆。在測試項目中的使用和在自己私有庫中的使用医增,結(jié)果如下圖:
測試項目中的使用.png
私有庫中的使用.png
百度地圖運行結(jié)果.png

相同的方法在ShareSDK相應(yīng)的framework目錄下創(chuàng)建Module卻出現(xiàn)了錯誤,暫時未解決老虫,有興趣的朋友可以試試叶骨,分享一下。

五祈匙、私有庫中Swift和Objective-C混編(兩種情況)

這里我門先看一下忽刽,混編的兩種情況的文件目錄結(jié)構(gòu),然后再一步一步的往下走夺欲,目錄結(jié)構(gòu)如下:

├── JYPLibTest1
│   ├── Assets
│   ├── Classes
│   │   ├── OCClass                      # Objective-C類的文件夾(OCClass子模塊)
│   │   │   ├── JYFamily.h                    # 家庭類(NSObject)
│   │   │   ├── JYFamily.m
│   │   │   ├── JYFather.swift             # 父親類(NSObject)
│   │   │   ├── JYKid.h                           # 孩子類(NSObject)
│   │   │   ├── JYKid.m
│   │   │   ├── JYMother.swift                # 母親類(NSObject)
│   │   │   ├── JYPLibTest1.h                  # 頭文件(項目要求要有的)
│   │   │   └── JYPersonProtocol.h       # 協(xié)議類
│   │   ├── SwiftClass                      # Swift類的文件夾(SwiftClass子模塊)
│   │   │   ├── JYFather2.swift               # 父親類2(NSObject)
│   │   │   └── JYMother2.swift             # 母親類2(NSObject)

1. 同一個模塊(OCClass)內(nèi)的Swift和Objective-C混編
一個層面問題的解決跪帝,又伴隨著另一層面的思考,那就是如何在私有庫中實現(xiàn)Swfit和Objective-C的混編及混合打包(我們這一步只驗證Swift與Objective-C混合打包)些阅。

同一個模塊(OCClass)內(nèi)的Swift和Objective-C混編伞剑,可以是單向調(diào)用,即Swift調(diào)用Objective-C市埋,或者Objective-C調(diào)用Swift黎泣,也可以是雙向調(diào)用,即Swift調(diào)用Objective-C缤谎,Objective-C又調(diào)用Swift聘裁。

在這里我們繼續(xù)使用JYPLibTest1私有庫,且以雙向調(diào)用為例弓千。這個問題讓我們通過一個案例來看,能更好的理解献起。
案例:一個周末的早上洋访,家中的父母做好早餐,叫孩子起床谴餐,喂他/她吃飯姻政。(一個家庭中,包括父母和孩子岂嗓,父母中又包括孩子汁展,父母、孩子都有吃的動作厌殉,孩子吃飯是由父母喂的)食绿。

  • 首先讓我們創(chuàng)建一個JYKid(孩子)類和一個JYPersonProtocol協(xié)議類,這兩個類都是Objective-C類公罕。接下來實現(xiàn)這兩個類器紧,代碼如下:
/// JYKid.h
#import <Foundation/Foundation.h>
#import "JYPersonProtocol.h"

@interface JYKid : NSObject <JYPersonProtocol> // 遵循協(xié)議

@property (nonatomic, strong) NSString *name;

@end


/// JYKid.m
#import "JYKid.h"

@implementation JYKid

/// 實現(xiàn)JYPersonProtocol協(xié)議方法
- (void)eat {
    NSLog(@"%@ is eating", self.name != nil ? self.name : @"Kid");
}

@end
/// JYPersonProtocol.h
#import <Foundation/Foundation.h>

@protocol JYPersonProtocol <NSObject>

@optional
- (void)eat;

@end

完成后,我們的這兩個類肯定是需要給外部文件(Objective-C/Swift)使用的楼眷,那么該如何處理呢铲汪?其實解決辦法很簡單熊尉,只需將Objective-C類的.h文件設(shè)置為public即可。以JYKid.h為例掌腰,具體設(shè)置如下圖:
將OC的.h文件設(shè)置為public.png

相同的方法狰住,將JYPersonProtocol.h也設(shè)置為public。有的文件創(chuàng)建完默認(rèn)就是public齿梁,那就可以略過此步了催植。

設(shè)置完成,修改.podspec文件士飒,內(nèi)容如下:

Pod::Spec.new do |s|
  s.name             = 'JYPLibTest1'
  s.version          = '1.0.1'
  s.summary          = '另一個測試私有庫'
  s.homepage         = 'https://git.artron.net/CocoaPods/JYPLibTest1'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'JYanshao' => '654565181@qq.com' }
  s.source           = { :git => 'https://git.artron.net/CocoaPods/JYPLibTest1.git', :tag => s.version.to_s }
  s.ios.deployment_target = '8.0'
  s.source_files = 'JYPLibTest1/Classes/**/*.swift'
  
  s.subspec 'OCClass' do |cc|
      cc.source_files = 'JYPLibTest1/Classes/OCClass/*.{h,m}'
  end  
end

在終端執(zhí)行下pod install命令查邢,更新下demo工程,編譯運行沒有錯誤酵幕。然后打開demo中的xxx-umbrella.h文件扰藕,你會發(fā)現(xiàn)JYKid和JYPersonProtocol兩個文件的頭文件已經(jīng)被自動引入進(jìn)來了。如下圖:

xxx-umbrella.h文件可以被看成是你項目中橋接文件xxx-Bridge-Header.h芳撒,也可以看成是一個Objective-C的頭文件邓深。

查看JYPLibTest1-umbrella.h文件.png

讓我們繼續(xù),創(chuàng)建兩個Swift類JYFather和JYMother笔刹,然后實現(xiàn)Swift對Objective-C類的引用芥备,使其有一個小孩JYKid并且實現(xiàn)JYPersonProtocol協(xié)議,然后喂這個小孩吃飯舌菜。
注意:Swift類與Objective-C類有些區(qū)別萌壳,Swift類不需要像Objective-C類一樣設(shè)置他們的頭文件為public,Swift類只需要定義其文件的訪問權(quán)限即可日月。
JYFather和JYMother文件中的代碼一樣袱瓮,以JYFather為例,代碼如下:

/// JYFather.swift / JYMother.swift 這兩個文件中的代碼一樣爱咬,copy一下
/// 父母這兩個文件都繼承JYPersonProtocol協(xié)議尺借,并實現(xiàn)其方法
import UIKit

open class JYFather: NSObject, JYPersonProtocol {
    var name: String = ""
    var kid: JYKid?
    
    public init(name: String, kid: JYKid) {
        super.init()
        self.name = name
        self.kid = kid
    }
    
    @objc public func feed(_ food: String) {
        print("\(name) is feeding \(kid?.name ?? "kid") eat \(food)")
    }
    
    /// 實現(xiàn)協(xié)議方法
    public func eat() {
        print("\(name) is eating")
    }
}

修改.podspec文件,配置如下:

Pod::Spec.new do |s|
    ...
    # 沒有變化的部分省略了
    ...

    s.subspec 'OCClass' do |cc|
          cc.source_files = 'JYPLibTest1/Classes/OCClass/*.{h,m,swift}'
    end
end

執(zhí)行pod install精拟,更新demo燎斩,編譯運行,結(jié)果報錯了蜂绎,錯誤如下:

錯誤1.png

錯誤11.png

提示我們沒有找到JYPLibTest1.h文件栅表,因為項目中根本就沒有這個文件,所以才找不到师枣,既然它需要這么一個文件谨读,那就按它的意思創(chuàng)建一個JYPLibTest1.h頭文件,并 #import 引入已經(jīng)創(chuàng)建的Objective-C類頭文件坛吁。
注意:JYPLibTest1頭文件劳殖,是一個Objective-C類的頭文件铐尚。用來導(dǎo)入Objective-C類的頭文件用的,相當(dāng)于xxx-Bridging-Header.h文件哆姻。

JYPLibTest1.h頭文件.png

更新demo宣增,并編譯運行發(fā)現(xiàn)沒有問題了。

到這里矛缨,我們創(chuàng)建了父母爹脾、孩子、以及吃的協(xié)議類箕昭,接下來讓我們創(chuàng)建一個Objective-C的家庭類JYFamily灵妨,把他們組合成一個家庭吧,這樣才圓滿落竹,并實現(xiàn)Objective-C類調(diào)用Swift類泌霍。
JYFamily類的代碼如下:

/// JYFamily.h
#import <Foundation/Foundation.h>
#import "JYKid.h"
@class JYFather, JYMother;   // 這里有個問題需注意,后面會講到

@interface JYFamily : NSObject

@property (nonatomic, strong) JYKid *kid;
@property (nonatomic, strong) JYFather *father;
@property (nonatomic, strong) JYMother *mother;

// 打印父母各自的喂食
- (void)feed:(NSString *)fFood mFood:(NSString *)mFood;

@end


/// JYFamily.m
#import "JYFamily.h"
#import <JYPLibTest1/JYPLibTest1-Swift.h>

@implementation JYFamily

- (void)feed:(NSString *)fFood mFood:(NSString *)mFood {
    [self.father feed:fFood]; // 父親喂孩子吃食物
    [self.mother feed:mFood]; // 母親喂孩子吃食物
}

@end

更新demo述召,并編譯運行朱转,發(fā)現(xiàn)沒有錯誤。然后在測試項目中引入积暖,并測試是否可用藤为。我的測試結(jié)果如下:


Swift和OC混合開發(fā)運行結(jié)果.png

本地和遠(yuǎn)程驗證也是可以通過的,上傳也是成功的夺刑。

這里有個問題需要注意一下
如果你在JYFamily.h文件中直接引入#import "JYPLibTest1-Swift.h"頭文件的話缅疟,編譯運行demo可能會報如下錯誤。

導(dǎo)入JYPLibTest1-Swift.h錯誤.png

原因有兩點:1). 在你的ProjectName-Swift.h中是引用了JYFamily.h的遍愿,如果你這時候在定義JYFamily.h中又引用ProjectName-Swift.h造成了有點像循環(huán)引用的概念存淫,所以在JYFamily.h中只需要用@Class聲明一下用到的文件即可,在JYFamily.m中在真正引用需要用到的文件错览;
(下面這張圖片是借用的凌彬,原文章在下邊的參考文章部分有鏈接)

image

2). Swift只支持動態(tài)庫弯淘,但并非完全意義的動態(tài)庫,而我們的代碼在Pod之后實際上是一個動態(tài)的Framework寇荧,Swift是有命名空間的一個概念刽脖,這時候你需要做的是在引用時需要寫明命名空間羞海。

基于上述兩點原因,我們只能在Objective-C類的JYFamily.m文件中引用(#import)并且加上命名空間曲管,而JYFamily.h文件中則用 @Class 聲明一下引用的類却邓。最終結(jié)果如下圖:


循環(huán)關(guān)聯(lián)和命名空間2解決方案.png
循環(huán)關(guān)聯(lián)和命名空間1解決方案.png

解決完這個問題,記得更新demo院水,編譯運行腊徙。

2.不同模塊內(nèi)的Swift和Objective-C的混編

不同模塊內(nèi)的Swift和Objective-C混編简十,可以是單向調(diào)用,即Swift調(diào)用Objective-C撬腾,或者Objective-C調(diào)用Swift螟蝙,也可以是雙向調(diào)用,但有些限制民傻,不是很靈活胰默。

緊接著第一種情況,我們來探索一下第二種情況(還是以雙向引用為例)漓踢。
我們還使用上面OCClass子模塊中的Objective-C類牵署,然后在SwiftClass文件夾下創(chuàng)建Swift類JYFather2和JYMother2兩個文件,這兩個文件中的代碼是copy的JYFather和JYMother兩個文件中的代碼喧半。

創(chuàng)建并編輯完成后奴迅,將JYFamily文件中的JYFather和JYMother替換為JYFather2和JYMother2。如下圖所示:
修改后的JYFamily.h文件.png

完成以上步驟薯酝,修改.podspec文件的配置半沽,因為是兩個不同的子模塊之間的混編,所以需要通過dependency來引入另一個模塊供本模塊使用吴菠,具體配置如下:

Pod::Spec.new do |s|
  ...
  # 不變的配置省略
  ...
  
  s.subspec 'OCClass' do |cc|
      cc.source_files = 'JYPLibTest1/Classes/OCClass/*.{h,m,swift}'
      #cc.dependency 'JYPLibTest1/SwiftClass' # 這里不能再依賴SwiftClass子模塊了者填,否則會造成循環(huán)依賴的問題
  end
  
  s.subspec 'SwiftClass' do |sc|
      sc.source_files = 'JYPLibTest1/Classes/SwiftClass/*.swift'
      sc.dependency 'JYPLibTest1/OCClass'
  end
end 

終端下更新demo工程,編譯運行做葵,沒有問題占哟。
但是在執(zhí)行pod lib lint驗證時卻出現(xiàn)了錯誤,具體錯誤如下:

- ERROR | [JYPLibTest1/OCClass,JYPLibTest1/SwiftClass] xcodebuild:  /Users/artron/Desktop/PrivateRepository/JYPLibTest1/JYPLibTest1/Classes/OCClass/JYFamily.m:15:6: error: receiver type 'JYFather2' for instance message is a forward declaration
- ERROR | [JYPLibTest1/OCClass,JYPLibTest1/SwiftClass] xcodebuild:  /Users/artron/Desktop/PrivateRepository/JYPLibTest1/JYPLibTest1/Classes/OCClass/JYFamily.m:16:6: error: receiver type 'JYMother2' for instance message is a forward declaration

這個問題造成的原因是你的JYFamily.h文件中用了@Class聲明了你的JYFather2和JYMother2酿矢,但是在JYFamily.m中使用的時候沒有檢測到你用#import引入這兩個文件榨乎,所以驗證失敗。所以子模塊之間的混編會有些局限瘫筐。

子模塊之間還要注意循環(huán)依賴的問題
如上.podspec中蜜暑,cc.dependency 'JYPLibTest1/SwiftClass'sc.dependency 'JYPLibTest1/OCClass'兩個子模塊都互相依賴了對方策肝,這時執(zhí)行pod install肛捍,會報JYPLibTest1/SwiftClassJYPLibTest1/OCClass之間存在循環(huán)依賴關(guān)系的問題,解決方法就是斷開一方的依賴即可之众。
具體錯誤如下:

兩者之間循環(huán)依賴問題.png

以上若有不妥請指正拙毫。



參考文章:
Build with CocoaPods
使用私有Cocoapods倉庫 中高級用法
pod庫包含MRC的文件
組件化開發(fā)之-如何解決Swift/OC-Framenwork/Library混合創(chuàng)建pod問題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市棺禾,隨后出現(xiàn)的幾起案子缀蹄,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缺前,死亡現(xiàn)場離奇詭異蛀醉,居然都是意外死亡,警方通過查閱死者的電腦和手機诡延,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門滞欠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肆良,你說我怎么就攤上這事筛璧。” “怎么了惹恃?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵夭谤,是天一觀的道長。 經(jīng)常有香客問我巫糙,道長朗儒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任参淹,我火速辦了婚禮醉锄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浙值。我一直安慰自己恳不,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布开呐。 她就那樣靜靜地躺著烟勋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪筐付。 梳的紋絲不亂的頭發(fā)上卵惦,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音瓦戚,去河邊找鬼沮尿。 笑死,一個胖子當(dāng)著我的面吹牛较解,可吹牛的內(nèi)容都是我干的畜疾。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼哨坪,長吁一口氣:“原來是場噩夢啊……” “哼庸疾!你這毒婦竟也來了乍楚?” 一聲冷哼從身側(cè)響起当编,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徒溪,沒想到半個月后忿偷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體金顿,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年鲤桥,在試婚紗的時候發(fā)現(xiàn)自己被綠了揍拆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡茶凳,死狀恐怖嫂拴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情贮喧,我是刑警寧澤筒狠,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站箱沦,受9級特大地震影響辩恼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谓形,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一灶伊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寒跳,春花似錦聘萨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至康愤,卻和暖如春儡循,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背征冷。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工择膝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人检激。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓肴捉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親叔收。 傳聞我的和親對象是個殘疾皇子齿穗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345